# TrafficMonitor Administrator & Developer Guide

This guide is the exhaustive technical reference for **TrafficMonitor** — a native Windows desktop network/hardware monitor written in C++ with the **MFC** framework. It is intended for power users, IT administrators who deploy it across machines, skin and plugin developers, and anyone who needs to understand, build, configure, or extend the application from source.

Where the User Guide explains *how to use* TrafficMonitor, this guide explains *how it is built, where it stores state, every setting it persists, how to compile it, and how to extend it*.

---

## 1. Executive Summary

| Attribute | Value |
| --- | --- |
| Project | TrafficMonitor |
| Type | Native Windows desktop GUI application |
| Language | C++ (C++17), MFC (Microsoft Foundation Classes) |
| UI framework | MFC dialog‑based application (`CWinApp` + `CDialog`) |
| Build system | Visual Studio (MSBuild) — `.sln` + `.vcxproj` |
| Editions | Standard (with temperature monitoring, requires admin) and Lite (no temperature, no admin) |
| Configuration | INI files (`config.ini`, `global_cfg.ini`) |
| Persistence | Flat files (`config.ini`, `history_traffic.dat`); **no database** |
| Network data source | Windows IP Helper API (`iphlpapi`, `MIB_IFTABLE`) |
| Hardware data sources | Performance Counters (PDH) + LibreHardwareMonitor (.NET, temperatures) |
| Extensibility | Native C++ plugin DLLs (`ITMPlugin` interface, API v7) |
| Theming | File‑based skins (`skin.ini` / `skin.xml` + background images) |
| Localization | External `.ini` language files (15 languages) |
| Source commit | `7901ce0` (2026‑04‑06) |
| License | Anti‑996 License (see `LICENSE` / `LICENSE_CN`) |

**Design in one sentence:** a single‑instance MFC dialog application that samples network and hardware counters on a timer, renders the results into a floating window and/or a window embedded in the Windows taskbar, and persists all user choices to INI files located either beside the executable (portable mode) or in `%AppData%`.

> [!NOTE]
> TrafficMonitor has **no command‑line interface, no network server, no API, and no telemetry**. Its only outbound network activity is an optional update check against GitHub or Gitee. All "configuration" is performed through the GUI and serialized to INI files documented in [Section 5](#5-configuration-reference).

---

## 2. Architecture

### 2.1 High‑level structure

```text
                     +--------------------------------------------------+
                     |              CTrafficMonitorApp (CWinApp)         |
                     |  - InitInstance(): single-instance mutex,         |
                     |    path resolution, plugin load, config load      |
                     |  - LoadConfig()/SaveConfig(): INI <-> structs      |
                     |  - Update check thread, hardware-init thread       |
                     +-------------------------+------------------------+
                                               |
                          +--------------------+--------------------+
                          |                                         |
              +-----------v-----------+               +-------------v------------+
              | CTrafficMonitorDlg     |               |  Worker threads          |
              | (main floating window) |               |  - MonitorThreadCallback |
              |  - OnTimer sampling    |               |  - CheckUpdateThreadFunc |
              |  - right-click menu     |               |  - InitOpenHardwareLib   |
              |  - notify (tray) icon  |               +-------------+------------+
              |  - hosts CTaskBarDlg   |                             |
              +-----------+-----------+               +-------------v------------+
                          |                            |  Data acquisition layer  |
          +---------------+--------------+             |  - iphlpapi (net speed)  |
          |               |              |             |  - PdhHardwareQuery      |
   +------v-----+  +------v------+ +-----v------+      |    (CPU/GPU/disk/freq)   |
   | CTaskBarDlg|  | CSkinFile   | | PluginMgr  |      |  - OpenHardwareMonitorApi|
   | (taskbar   |  | CSkinManager| | (ITMPlugin)|      |    (temperatures, .NET)  |
   |  window)   |  +-------------+ +------------+      +--------------------------+
   +-----+------+
         |
   +-----v-----------------------------+
   | Rendering backends (factory)      |
   |  - GDI / GDI+ (DrawCommon)         |
   |  - Direct2D / DComposition (D2D1)  |
   +-----------------------------------+
```

### 2.2 Component inventory

The codebase is organized into one main application project plus several helper projects. Key modules:

| Module / file | Responsibility |
| --- | --- |
| `TrafficMonitor.cpp/.h` | `CTrafficMonitorApp` (the `CWinApp`): startup, config load/save, update check, autostart, global state |
| `TrafficMonitorDlg.cpp/.h` | `CTrafficMonitorDlg`: the floating main window, timer sampling, right‑click menu, tray icon, owns the taskbar window |
| `TaskBarDlg.cpp/.h` | `CTaskBarDlg`: the window embedded into the Windows taskbar |
| `TaskBarDlgDrawCommon.*` | Direct2D/DComposition drawing for the taskbar window |
| `CommonData.h` | All global structs and enums (settings data, display items, fonts) |
| `Common.cpp/.h` | `CCommon`: utility helpers (string conversion, color, paths, theme detection) |
| `IniHelper.*`, `SettingsHelper.*` | INI read/write abstraction over the config files |
| `SkinFile.*`, `SkinManager.*` | Skin parsing (`skin.ini`/`skin.xml`) and skin discovery |
| `PluginManager.*` | Discovers, loads, and dispatches to plugin DLLs |
| `PluginInterface.h` (in `include/`) | Public C++ ABI for plugins (`ITMPlugin`, `IPluginItem`, `ITrafficMonitor`) |
| `PdhHardwareQuery/` | `CCPUUsage`, `CPdhCpuFreq`, `CPdhGPUUsage`, `CPdhDiskUsage` — Performance‑Counter wrappers |
| `OpenHardwareMonitorApi/` | C++/CLI bridge to LibreHardwareMonitor for temperature/sensor data |
| `HistoryTrafficFile.*` | Binary persistence of daily traffic to `history_traffic.dat` |
| `AdapterCommon.*` | Network adapter enumeration via IP Helper API |
| `auto_start_helper.*` | Autostart via Task Scheduler |
| `crashtool.*` | Crash reporting / minidump and call‑stack capture |
| `DrawCommon*`, `D2D1Support`, `WIC`, `Image2DEffect` | Rendering primitives (GDI+, Direct2D, WIC image loading) |
| `StrTable.*`, `language.h`, `language/*.ini` | Localization string tables |
| `tinyxml2/` | Vendored XML parser used for `skin.xml` and update feeds |

### 2.3 Threading model

TrafficMonitor is predominantly single‑threaded (MFC message pump) with a few dedicated worker threads to keep the UI responsive:

| Thread | Function | Purpose |
| --- | --- | --- |
| Main/UI | MFC pump, `OnTimer` | Sampling tick, drawing, menu handling |
| Monitor thread | `MonitorThreadCallback` | Offloads monitor data acquisition (`DoMonitorAcquisition`) so sampling doesn't block the UI |
| Update thread | `CheckUpdateThreadFunc` | Checks GitHub/Gitee for new versions and plugin updates without freezing startup |
| Hardware‑init thread | `InitOpenHardwareMonitorLibThreadFunc` | Initializes LibreHardwareMonitor (slow) in the background; guarded by a critical section |

> [!NOTE]
> The monitor thread communicates results back to the UI via a posted message (`OnMonitorInfoUpdated`) and the `m_monitor_data_required` flag, with a `CEvent` (`m_threadExitEvent`) used to coordinate clean shutdown.

### 2.4 Rendering backends

Drawing is abstracted behind a factory (`DrawCommonFactory` / `IDrawCommon`) so the taskbar window can render with either GDI/GDI+ or **Direct2D** (with DirectComposition for layered transparency). Direct2D was added in v1.85 to fix jagged font edges and HDR/transparency issues; it can be toggled with the `disable_d2d` setting.

---

## 3. System Requirements

| Requirement | Standard | Lite |
| --- | --- | --- |
| OS | Windows 7 / 8 / 8.1 / 10 / 11 | Same |
| Architecture | x86, x64, ARM64EC | Same |
| Visual C++ Redistributable | Required (latest MSVC runtime) | Required |
| .NET Framework 4.5+ | Required (for temperature via LibreHardwareMonitor) | Not required |
| Administrator privileges | **Required** (hardware/temperature access) | Not required |
| Disk | A few MB; plus space for `history_traffic.dat` growth | Same |

> [!IMPORTANT]
> The Standard version checks for .NET Framework 4.5 at startup (`IsDotNetFramework4Point5Installed`) and warns if it is missing. The Lite version (built with `WITHOUT_TEMPERATURE`) skips this check entirely.

---

## 4. Installation & Deployment

### 4.1 Standard deployment

TrafficMonitor is portable. To deploy:

1. Extract the release ZIP to a target folder.
2. Decide the data location strategy (see [4.2](#42-portable-mode-vs-appdata)).
3. Launch `TrafficMonitor.exe`.

### 4.2 Portable mode vs AppData

At startup, `LoadGlobalConfig()` decides where settings are stored:

```text
global_cfg.ini exists?
  ├─ yes → read [config] portable_mode
  └─ no  → portable_mode defaults to:
             (config.ini already in %AppData%? → false : true)

Then InitInstance():
  if portable_mode → config_dir = <program folder>
  else             → config_dir = %AppData%\Roaming\TrafficMonitor\

Hard override: if the program folder is NOT writable, OR the program is
running from a Temp directory → portable_mode forced to false (use AppData).
```

`global_cfg.ini` (in the program folder) controls the switch:

```ini
[config]
portable_mode = false
```

| `portable_mode` | Data location |
| --- | --- |
| `true` | Settings/history kept beside `TrafficMonitor.exe` (portable, USB‑friendly) |
| `false` | Settings/history kept in `%AppData%\Roaming\TrafficMonitor\` |

> [!TIP]
> For multi‑user machines or installs under `C:\Program Files\`, set `portable_mode = false` so each user gets their own settings under their profile and write‑permission errors are avoided.

### 4.3 Files written at runtime

| File | Location (per mode) | Format | Purpose |
| --- | --- | --- | --- |
| `config.ini` | `config_dir` | INI (UTF‑16) | All user settings |
| `history_traffic.dat` | `config_dir` | Binary | Daily traffic history |
| `history_traffic.dat.bak` | `config_dir` | Binary | Backup of history file |
| `error.log` | `config_dir` | Text | Error/debug log (when enabled) |
| `global_cfg.ini` | Program folder | INI | `portable_mode` switch |

### 4.4 Mass deployment notes

- To pre‑seed settings across machines, distribute a prepared `config.ini` alongside the executable and set `portable_mode = true`, **or** drop the `config.ini` into each user's `%AppData%\Roaming\TrafficMonitor\`.
- Autostart is **per‑user** (HKCU registry or a per‑user scheduled task), so it must be configured in each user's session, not machine‑wide.

---

## 5. Configuration Reference

All settings live in `config.ini` and are loaded/saved by `CTrafficMonitorApp::LoadConfig()` / `SaveConfig()`. The file is organized into the sections below. **These keys, types, and defaults are taken directly from the source** and represent the authoritative configuration reference.

> [!CAUTION]
> Editing `config.ini` by hand is supported but unusual — the GUI is the intended interface. If you do edit it, close TrafficMonitor first, because `SaveConfig()` rewrites the whole file on exit and will overwrite your changes.

### 5.1 `[general]` — General settings

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `check_update_when_start` | bool | `true` | Check for updates at startup |
| `language` | string | (system) | UI language (BCP‑47 based config string) |
| `update_source` | int | `1` if Simplified Chinese else `0` | `0`=GitHub, `1`=Gitee |
| `show_all_interface` | bool | `false` | Show all interfaces |
| `monitor_time_span` | int (ms) | `1000` | Sampling interval; clamped to 200–30000 |
| `hard_disk_name` | string | `""` | Disk to monitor (temperature) |
| `cpu_core_name` | string | `"Core Average"` | CPU core to monitor (temperature) |
| `hardware_monitor_item` | int (bitmask) | `0` | Enabled hardware: CPU=1, GPU=2, HDD=4, MBD=8 |
| `connections_hide` | string list | `[]` | Adapters hidden from the "Select connection" menu |

### 5.2 `[config]` — Main window & general toggles

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `transparency` | int | `80` | Main window opacity (0–100) |
| `always_on_top` | bool | `true` | Keep floating window topmost |
| `lock_window_pos` | bool | `false` | Lock window position |
| `show_notify_icon` | bool | `true` | Show notification‑area (tray) icon |
| `show_cpu_memory` | bool | `false` | Show CPU/memory on the floating window ("Show More Info") |
| `mouse_penetrate` | bool | `false` | Click‑through floating window |
| `show_task_bar_wnd` | bool | `false` | Show the taskbar‑embedded window |
| `position_x` / `position_y` | int | `-1` | Saved window position |
| `hide_main_window` | bool | `false` | Hide the floating window |
| `skin_selected` | string | `""` | Selected skin name |
| `notify_icon_selected` | int | `2` on Win7/8, else default | Which tray icon image to use |
| `notify_icon_auto_adapt` | bool | `true` | Auto pick tray icon for Win10 light/dark |
| `swap_up_down` | bool | `false` | Swap upload/download positions |
| `hide_main_wnd_when_fullscreen` | bool | `true` | Hide floating window when a fullscreen app runs |
| `speed_short_mode` | bool | `false` | Compact speed display |
| `separate_value_unit_with_space` | bool | `true` | Space between value and unit |
| `show_tool_tip` | bool | `true` | Show mouse tooltips |
| `memory_display` | enum int | `0` | 0=percentage, 1=used, 2=available |
| `unit_byte` | bool | `true` | Use bytes (B) vs bits (b) |
| `speed_unit` | enum int | `0` | 0=auto, 1=KB/s, 2=MB/s |
| `hide_unit` | bool | `false` | Hide the speed unit |
| `hide_percent` | bool | `false` | Hide the `%` sign |
| `double_click_action` | enum int | `0` | Action on double‑click (see `DoubleClickAction`) |
| `double_click_exe` | string | `…\Taskmgr.exe` | Program to launch for the "specific app" action |
| `alow_out_of_border` | bool | `false` | Allow floating window off‑screen |
| `plugin_disabled` | string set | `""` | IDs of disabled plugins |

### 5.3 `[connection]` — Network adapter selection

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `auto_select` | bool | `true` | Auto‑select the active adapter |
| `select_all` | bool | `false` | Sum traffic across all adapters |
| `connection_name` | string | `""` | Name of the manually selected adapter |

### 5.4 `[skins]` — Skin auto‑adaptation

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `skin_auto_adapt` | bool | `false` | Switch skin with Windows light/dark mode |
| `skin_name_dark_mode` | string | `""` | Skin used in dark mode |
| `skin_name_light_mode` | string | `""` | Skin used in light mode |

### 5.5 `[task_bar]` — Taskbar window settings

The taskbar window has its own complete set of appearance and behavior settings.

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `task_bar_back_color` | color int | `dft_back_color` | Background color |
| `transparent_color` | color int | `dft_transparent_color` | Transparent color key |
| `status_bar_color` | color int | `0x5A5A5A` | CPU/memory status‑bar color |
| `task_bar_text_color` | colors | white | Per‑item text colors |
| `specify_each_item_color` | bool | `false` | Use per‑item colors |
| `tbar_display_item` | int (bitmask) | `{UP,DOWN}` | Which items to display |
| `show_taskbar_wnd_in_secondary_display` | bool | `false` | Show on a secondary monitor |
| `secondary_display_index` | int | `0` | Which secondary monitor |
| `task_bar_wnd_on_left` | bool | `false` | Place window left of taskbar |
| `task_bar_wnd_snap` | bool | `false` | Snap to center taskbar (Win11) |
| `task_bar_speed_short_mode` | bool | `false` | Compact speed mode |
| `unit_byte` | bool | `true` | Bytes vs bits |
| `task_bar_speed_unit` | enum int | `0` | Speed unit |
| `task_bar_hide_unit` | bool | `false` | Hide unit |
| `task_bar_hide_percent` | bool | `false` | Hide `%` |
| `value_right_align` | bool | `true` | Right‑align values |
| `horizontal_arrange` | bool | `false` | Arrange items horizontally |
| `show_status_bar` | bool | `false` | Show CPU/memory status bars |
| `separate_value_unit_with_space` | bool | `true` | Space between value/unit |
| `show_tool_tip` | bool | `true` | Tooltips |
| `digits_number` | int | `4` | Reserved digits for speed width |
| `memory_display` | enum int | `0` | Memory display mode |
| `double_click_action` | enum int | `0` | Double‑click action |
| `double_click_exe` | string | `…\Taskmgr.exe` | Program for double‑click |
| `cm_graph_type` | bool | `true` | Usage‑graph style |
| `show_graph_dashed_box` | bool | `false` | Dashed box around graph |
| `item_space` | int | `8` | Spacing between items |
| `vertical_margin` | int | `0` | Vertical item margin |
| `window_offset_top` | int | `0` | Window top offset |
| `window_offset_left` | int | `0` | Window left offset |
| `avoid_overlap_with_widgets` | bool | `false` | Avoid Win11 Widgets overlap |
| `taskbar_left_space_win11` | int | `160` | Win11 left widget width |
| `taskbar_right_space_win11` | int | `280` | Win11 right space |
| `auto_adapt_light_theme` | bool | `false` (Win10+ only) | Auto switch colors with theme |
| `dark_default_style` | int | `0` | Preset for dark mode |
| `light_default_style` | int | preset index | Preset for light mode |
| `auto_set_background_color` | bool | `false` (Win8+) | Follow taskbar color |
| `item_order` | string | `""` | Custom item ordering |
| `plugin_display_item` | string | `""` | Which plugin items to show |
| `auto_save_taskbar_color_settings_to_preset` | bool | `true` | Auto‑save colors to preset |
| `show_netspeed_figure` | bool | `false` | Show net‑speed graph |
| `netspeed_figure_max_value` | int | `512` | Graph max value |
| `netspeed_figure_max_value_unit` | int | `0` | 0=KB, 1=MB |
| `graph_color_following_system` | bool | `false` | Graph color follows system |
| `disable_d2d` | bool | `true` (or per support) | Disable Direct2D rendering |
| `enable_colorful_emoji` | bool | `true` | Colorful emoji (D2D only) |

### 5.6 `[notify_tip]` — Notification thresholds

Each threshold has an `_enable` bool and a `_value` int.

| Keys | Default | Meaning |
| --- | --- | --- |
| `traffic_tip_enable` / `traffic_tip_value` / `traffic_tip_unit` | `false` / `200` / `0` (MB) | Notify when traffic exceeds value |
| `memory_usage_tip_enable` / `memory_tip_value` | `false` / `80` | Notify on high memory % |
| `cpu_temperature_tip_enable` / `cpu_temperature_tip_value` | `false` / `80` | Notify on high CPU temp |
| `gpu_temperature_tip_enable` / `gpu_temperature_tip_value` | `false` / `80` | Notify on high GPU temp |
| `hdd_temperature_tip_enable` / `hdd_temperature_tip_value` | `false` / `80` | Notify on high disk temp |
| `mainboard_temperature_tip_enable` / `mainboard_temperature_tip_value` | `false` / `80` | Notify on high board temp |

### 5.7 `[histroy_traffic]` — History view *(note: key is spelled "histroy" in code)*

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `use_log_scale` | bool | `true` | Logarithmic scale in history chart |
| `sunday_first` | bool | `true` | Week starts on Sunday |
| `view_type` | enum int | `0` (day) | Day/Week/Month/Quarter/Year |

### 5.8 `[other]` — Advanced/internal

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `notify_interval` | int (s) | `60` | Minimum interval between notifications |
| `no_multistart_warning` | bool | `false` | Suppress "already running" dialog |
| `exit_when_start_by_restart_manager` | bool | `true` | Exit if launched by Restart Manager |
| `debug_log` | bool | `false` | Write debug log |
| `taksbar_transparent_color_enable` | bool | `true` (false on Win7) | Allow taskbar transparent color |
| `last_light_mode` | bool | (system) | Last detected light/dark mode |
| `show_mouse_panetrate_tip` | bool | `true` | Show mouse‑penetrate hint |
| `show_dot_net_notinstalled_tip` | bool | `true` | Show .NET‑missing warning |

### 5.9 `[app]` — Bookkeeping

| Key | Type | Meaning |
| --- | --- | --- |
| `version` | string | The program version that last wrote the file |

> [!NOTE]
> Several keys are deliberately **not** in `config.ini`: the main window's text colors, fonts, and display text are saved **per‑skin** (in each skin's settings) rather than globally — see the comments in `LoadConfig()`.

---

## 6. Operations

### 6.1 Autostart management

TrafficMonitor supports two autostart mechanisms (`SetAutoRun(auto_run, task_scheduler)`):

| Mechanism | When used | Where it lives |
| --- | --- | --- |
| Registry | Lite / pre‑1.80 | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` → value `TrafficMonitor` |
| Task Scheduler | Standard (temperature) version | Per‑user scheduled task |

```text
GetAutoRun() compares the stored path to the current m_module_path_reg:
  - registry value present AND equals current exe path → autostart active
  - otherwise → inactive (stale path = broken autostart)
```

> [!IMPORTANT]
> Moving the program folder invalidates autostart because the stored path no longer matches. The Task Scheduler approach exists specifically because the registry method fails when the app needs to run elevated. Switching between Standard and Lite migrates the autostart entry from one mechanism to the other automatically.

> [!WARNING]
> Registry‑based autostart does **not** work when "Run as administrator" is set on the executable, because the Run key launches non‑elevated. Use the Task Scheduler method (Standard version) for elevated autostart.

### 6.2 Single‑instance enforcement

`InitInstance()` creates a named mutex (`TrafficMonitor-1419J3XLKL1w8OZc` in release builds). If it already exists, the new process finds the existing window via `FindWindow(APP_CLASS_NAME)`, shows the "already running" dialog, and exits. Suppress the dialog with `[other] no_multistart_warning = true`.

### 6.3 Update checking

At startup (and on demand), `CheckUpdate()` queries the configured update source:

- `update_source = 0` → GitHub
- `update_source = 1` → Gitee (default for Simplified Chinese, since GitHub is often blocked in mainland China)

It selects a per‑architecture download link (`GetLink64` / `GetLinkArm64ec` / `GetLink`) and compares the remote version string to the compiled `VERSION`. Plugin updates are checked in the same background thread via `m_plugin_update.CheckForUpdate()`.

### 6.4 Logs & crash reports

- `crashtool` installs a crash handler (`CRASHREPORT::StartCrashReport()`) that, since v1.86, displays the call stack and writes crash information to a log file.
- Enable verbose logging with `[other] debug_log = true`; output goes to `error.log` in `config_dir`.

### 6.5 Backup & restore

- **Settings:** copy `config.ini` from `config_dir`.
- **History:** copy `history_traffic.dat` (and `.bak`). The app keeps a `.bak` backup and can restore from it (`BackupHistoryTrafficFile` / restore logic in `HistoryTrafficFile`).
- To migrate a user to a new machine, copy both files into the same `config_dir` (portable folder or `%AppData%\Roaming\TrafficMonitor\`).

---

## 7. Security Analysis

> [!NOTE]
> This section is an objective security review of an open‑source desktop utility, intended to help administrators make deployment decisions. TrafficMonitor is a legitimate monitoring tool with no malicious behavior identified in source.

### 7.1 Privilege model

- The **Lite** version runs with standard user rights.
- The **Standard** version requires **administrator** privileges to read hardware sensors via LibreHardwareMonitor, which loads a kernel driver (`LibreHardwareMonitorLib.sys`) for low‑level hardware access.

> [!CAUTION]
> The bundled `LibreHardwareMonitorLib.dll` and its kernel driver are a third‑party component with deep hardware access. Some endpoint‑security products (e.g. Huorong, per issue reports) flag or block the driver. This is the highest‑privilege surface in the application. If you do not need temperatures, deploy the Lite version to avoid loading the driver entirely.

### 7.2 Attack surface

| Surface | Assessment |
| --- | --- |
| Network listening | **None** — the app opens no listening sockets and exposes no API. |
| Outbound network | Only update checks to GitHub/Gitee (HTTPS) and plugin update feeds. |
| Untrusted input | Skin files (`skin.ini`/`skin.xml`) and plugin DLLs are the only externally supplied content. |
| **Plugins** | Native DLLs loaded from `plugins\` run **in‑process with the host's privileges**. A malicious plugin has full access to the user session (and admin rights in the Standard version). |
| Config files | INI files are user‑writable; no privilege escalation path through them. |

> [!WARNING]
> The plugin system is the primary trust boundary. Because plugins are unsigned native DLLs loaded by file presence in `plugins\`, only deploy plugins from trusted sources. In managed environments, consider locking down write access to the `plugins\` directory.

### 7.3 Data privacy

- All monitoring data and history stay **local** in flat files. No data is transmitted.
- The "Contact Author" feature opens the user's mail client; it does not auto‑send anything.

### 7.4 Hardening recommendations

- [ ] Deploy the **Lite** version unless temperatures are required (removes the kernel driver).
- [ ] Run as a standard user (avoid elevation) where possible.
- [ ] Restrict write permissions on the `plugins\` and `skins\` folders in shared environments.
- [ ] Set `portable_mode = false` so per‑user data lives under each profile.
- [ ] Keep the program updated (it self‑checks; or push updates centrally).

---

## 8. Building From Source

### 8.1 Toolchain

| Requirement | Detail |
| --- | --- |
| IDE | Visual Studio (with C++ Desktop workload and **MFC** component) |
| Language standard | C++17 |
| Frameworks | MFC, ATL, GDI+, Direct2D/DirectComposition, WIC |
| .NET (temperature only) | C++/CLI bridge to LibreHardwareMonitor; needs .NET targeting |
| Architectures | x86, x64, ARM64EC |

### 8.2 Solution files

| File | Builds |
| --- | --- |
| `TrafficMonitor.sln` | Full solution: `TrafficMonitor`, `OpenHardwareMonitorApi`, `PluginDemo` |
| `TrafficMonitor_Lite.sln` | Lite build (defines `WITHOUT_TEMPERATURE`, excludes the OpenHardwareMonitor bridge) |

### 8.3 Build steps

```text
1. Open TrafficMonitor.sln (or TrafficMonitor_Lite.sln) in Visual Studio.
2. Select configuration (Debug/Release) and platform (x64 / Win32 / ARM64EC).
3. Build Solution.
4. Output: TrafficMonitor.exe in the configuration's output folder,
   with skins\ and language\ copied alongside.
```

### 8.4 Important compile‑time defines

| Macro | Effect |
| --- | --- |
| `WITHOUT_TEMPERATURE` | Builds the **Lite** edition: removes temperature display items (`TDI_*_TEMP`), skips the .NET/OpenHardwareMonitor init and the .NET‑installed check. |
| `DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR` | Disables the WinRT‑based Win11 Widgets detector. |
| `_DEBUG` | Uses a debug mutex name and the local `.\` config dir; skips startup update check. |

### 8.5 Project layout

```text
TrafficMonitor/            Main application (179 source files)
  PdhHardwareQuery/        Performance-counter wrappers (CPU/GPU/disk/freq)
  language/                15 localization .ini files
  skins/                   Bundled skins (skin.ini/skin.xml + backgrounds)
  res/                     Icons and bitmaps
  tinyxml2/                Vendored XML parser
OpenHardwareMonitorApi/    C++/CLI bridge to LibreHardwareMonitor (temperature)
  LibreHardwareMonitorLib.dll   Bundled .NET hardware library
include/
  PluginInterface.h        Public plugin ABI
  OpenHardwareMonitor/     OpenHardwareMonitor API headers
PluginDemo/                Example plugin project
```

---

## 9. Plugin Development Reference

Plugins are native C++ DLLs placed in `plugins\` next to the executable. They are discovered and loaded at startup by `CPluginManager`. A plugin DLL must export a single C function:

```cpp
// Returns a pointer to a single, long-lived ITMPlugin object
// (usually a global/static). It must not be freed before program exit.
ITMPlugin* TMPluginGetInstance();
```

### 9.1 Interfaces

The plugin ABI is declared in `include/PluginInterface.h`. Current **API version: 7**.

| Interface | Role |
| --- | --- |
| `ITMPlugin` | The plugin itself: provides items, receives data ticks, options dialog, info, commands |
| `IPluginItem` | A single display item the plugin contributes (label/value text or custom drawing) |
| `ITrafficMonitor` | Host interface passed to the plugin so it can query the main program |

### 9.2 `ITMPlugin` (implement this)

| Method | Purpose |
| --- | --- |
| `int GetAPIVersion()` | Returns `7`. **Do not override** — used for ABI compatibility. |
| `IPluginItem* GetItem(int index)` | Return each display item (0..N‑1), `nullptr` past the end. |
| `void DataRequired()` | Called every tick — fetch and cache your monitored data here. |
| `OptionReturn ShowOptionsDialog(void* hParent)` | Show a settings dialog (optional). |
| `const wchar_t* GetInfo(PluginInfoIndex)` | Name, description, author, copyright, version, URL. |
| `void OnMonitorInfo(const MonitorInfo&)` | Receive the host's monitored values (being deprecated in favor of `ITrafficMonitor::GetMonitorValue`). |
| `const wchar_t* GetTooltipInfo()` | Text for the mouse tooltip. |
| `void OnExtenedInfo(ExtendedInfoIndex, const wchar_t*)` | Receive host display options (unit, color, config dir, etc.). |
| `void* GetPluginIcon()` | `HICON` for the plugin. |
| `int GetCommandCount()` / `GetCommandName` / `GetCommandIcon` / `OnPluginCommand` / `IsCommandChecked` | Context‑menu commands contributed by the plugin. |
| `void OnInitialize(ITrafficMonitor* pApp)` | Receive and store the host interface pointer (API v7). |

### 9.3 `IPluginItem` (one per display item)

| Method | Purpose |
| --- | --- |
| `GetItemName` / `GetItemId` | Display name and **unique ID** (used as the INI key). |
| `GetItemLableText` / `GetItemValueText` / `GetItemValueSampleText` | Label, current value, and a sample value (sample width sizes the field). |
| `bool IsCustomDraw()` | If `true`, the plugin draws the item itself via `DrawItem`. |
| `int GetItemWidth()` / `GetItemWidthEx(hDC)` | Width for custom drawing (DPI‑scaled vs actual). |
| `void DrawItem(hDC, x, y, w, h, dark_mode)` | Custom rendering. |
| `int OnMouseEvent(...)` / `int OnKeboardEvent(...)` | Handle input; return non‑zero to suppress default handling (e.g. the context menu). |
| `int IsDrawResourceUsageGraph()` / `float GetResourceUsageGraphValue()` | Contribute a 0.0–1.0 usage graph (taskbar). |

### 9.4 `ITrafficMonitor` (host interface, provided to you)

| Method | Purpose |
| --- | --- |
| `GetAPIVersion()` / `GetVersion()` | Host ABI version and product version. |
| `double GetMonitorValue(MonitorItem)` | Read a host metric (up/down speed, CPU, memory, GPU, temps, freq, today's traffic). |
| `const wchar_t* GetMonitorValueString(MonitorItem, is_main_window)` | Formatted metric string. |
| `void ShowNotifyMessage(const wchar_t*)` | Pop a notification. |
| `unsigned short GetLanguageId()` | Current UI language. |
| `const wchar_t* GetPluginConfigDir()` | Directory where the plugin may store its config. |
| `int GetDPI(DPIType)` | DPI for the main or taskbar window. |
| `unsigned int GetThemeColor()` | Current system theme color (COLORREF). |
| `const wchar_t* GetStringRes(key, section)` | Look up a localized string. |

> [!TIP]
> Cache data in `DataRequired()` and simply return cached values from `GetItemValueText()` — that getter is called frequently for layout and must be cheap. This guidance is stated directly in the interface header.

### 9.5 API version history (ABI evolution)

| API ver | Added |
| --- | --- |
| 1 | Initial version |
| 2 | `ITMPlugin::GetTooltipInfo` |
| 3 | `IPluginItem::GetItemWidthEx`, `OnMouseEvent` |
| 4 | `IPluginItem::OnKeboardEvent`, `OnItemInfo` |
| 5 | `ITMPlugin::GetCommandName`, `GetCommandIcon`, `OnPluginCommand` |
| 6 | `IPluginItem::GetResourceUsageGraphType`, `GetResourceUsageGraphValue` |
| 7 | `ITMPlugin::OnInitialize` |

A reference implementation is provided in the `PluginDemo` project (items for system date/time plus a custom‑drawn item).

---

## 10. Skin Format Reference

Skins live in `skins\<SkinName>\` and theme the **floating window** only. A skin folder contains:

| File | Required | Purpose |
| --- | --- | --- |
| `background.bmp` / `.png` | Yes | Horizontal‑layout background (PNG supports transparency, v1.85+) |
| `background_l.bmp` / `.png` | Yes | Vertical/left‑layout background |
| `skin.ini` | One of ini/xml | Legacy config: colors, fonts, author, per‑item positions/sizes |
| `skin.xml` | Recommended | Modern config (v1.80+); **required** to display temperature and GPU items |

> [!IMPORTANT]
> A skin that ships only `skin.ini` cannot render temperature/GPU items. Skin authors should provide `skin.xml`. Parsing is handled by `CSkinFile` using the vendored `tinyxml2` for XML and `IniHelper` for INI.

See the project's skin‑making tutorial (`皮肤制作教程.md` / Wiki) for the full field reference.

---

## 11. Localization

The UI is fully externalized into `.ini` language files under `TrafficMonitor/language/`. Supported languages:

```text
English, Simplified Chinese, Traditional Chinese, German, French, Italian,
Russian, Polish, Korean, Spanish, Brazilian Portuguese, Turkish, Hebrew,
Hungarian, Vietnamese
```

Strings are loaded by `CStrTable` (`StrTable.*`), keyed by the IDs in `language.h`. Each `LanguageInfo` carries a display name, BCP‑47 code, default font, and translator credit. Adding a language means dropping a new translated `.ini` into the `language\` folder.

> [!NOTE]
> Multilingual strings moved to external INI files in v1.86, which is why translators can add languages without recompiling.

---

## 12. Troubleshooting (Operational)

### Issue: `LibreHardwareMonitorLib.dll` function acquisition failed, error code 127

**Cause:** The .NET bridge could not load the hardware library (missing/blocked DLL or missing .NET runtime). Error 127 = a required export/dependency was not found. *(Reported in issue #2221.)*

**Resolution:**
1. Confirm .NET Framework 4.5+ is installed.
2. Ensure `LibreHardwareMonitorLib.dll` is present next to the executable and not quarantined by antivirus.
3. If a newer LibreHardwareMonitor works standalone, replace the bundled `LibreHardwareMonitorLib.dll` with the newer one.
4. If unresolved, deploy the Lite version (no hardware library) or use the Hardware Monitor plugin.

### Issue: Driver blocked by security software

Some security suites block `LibreHardwareMonitorLib.sys`. Whitelist it, or deploy the Lite version which never loads the driver.

### Issue: High CPU/RAM or crashes after enabling hardware monitoring

Disable all items under **General Settings → Hardware Monitoring**, restart, and confirm stability. The hardware library is the most common crash source; the author cannot fix faults inside it.

### Issue: GPU usage incorrect / shows integrated GPU

GPU monitoring depends on counter availability per driver. Intel GPU support was added in v1.85; behavior still varies by vendor/driver. *(Related: issues #1627, #891.)*

### Issue: Net speed cannot be read after sleep/resume

Fixed in v1.86 (connections are re‑initialized after resume). If on an older build, switch the monitored adapter or restart.

### Issue: "Unable to Save Settings"

The program folder is not writable. Either move it to a writable location, enable **Save to AppData**, or set `portable_mode = false` in `global_cfg.ini`. See User Guide for the full procedure.

---

## 13. Known Limitations & Improvement Areas

These are observations from the source and issue tracker, useful for maintainers and for setting deployment expectations.

- **Windows 11 full‑taskbar overlap** — when the taskbar is full, the embedded window can overlap icons; documented as currently unfixable. Mitigation is configuration‑only.
- **Hardware/temperature stability** — the LibreHardwareMonitor dependency is the dominant crash and resource‑usage source; the maintainer has effectively deprecated built‑in temperature in favor of the plugin. *(Issues #2290, #2345, #2335, #2258.)*
- **CPU‑priority interaction** — a community report (#2345) notes Explorer instability under high load related to CPU priority; a community workaround exists.
- **`config.ini` whole‑file rewrite** — `SaveConfig()` serializes the entire settings struct on exit, so concurrent/manual edits are overwritten. There is no partial/atomic write.
- **Section‑name typo** — the history section is persisted as `[histroy_traffic]` (misspelled in source). It must remain as‑is for backward compatibility; flagged here so administrators editing INI files use the exact key.
- **Per‑user autostart only** — no machine‑wide autostart; deployment scripts must configure each user.
- **No app network control** — repeated requests for per‑app network throttling/blocking (#2324) are out of scope; TrafficMonitor only *observes* traffic.
- **Remote/web view** — requested (#2133) but not implemented; the app is local‑only by design.

### Suggested enhancements

- [ ] Atomic/partial `config.ini` writes to tolerate external edits and reduce data‑loss risk on crash during save.
- [ ] Optional plugin signature/allowlist to harden the plugin trust boundary in managed deployments.
- [ ] Make the optional netspeed decimals configurable (#1817).

---

## 14. Quick Reference

### File & registry map

| Item | Path |
| --- | --- |
| Settings | `config.ini` in `config_dir` |
| History | `history_traffic.dat` (+ `.bak`) in `config_dir` |
| Portable switch | `global_cfg.ini` → `[config] portable_mode` |
| AppData dir | `%AppData%\Roaming\TrafficMonitor\` |
| Registry autostart | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run\TrafficMonitor` |
| Task autostart | Per‑user Task Scheduler task |
| Skins | `skins\<name>\` |
| Plugins | `plugins\*.dll` |
| Languages | `language\*.ini` |

### Hardware bitmask (`[general] hardware_monitor_item`)

| Bit | Value | Hardware |
| --- | --- | --- |
| 0 | 1 | CPU |
| 1 | 2 | GPU |
| 2 | 4 | HDD |
| 3 | 8 | Motherboard |

### Build matrix

| Edition | Solution | Define | Admin | Temperature |
| --- | --- | --- | --- | --- |
| Standard | `TrafficMonitor.sln` | — | Yes | Yes |
| Lite | `TrafficMonitor_Lite.sln` | `WITHOUT_TEMPERATURE` | No | No (use plugin) |

### Key source entry points

| Symbol | File | Role |
| --- | --- | --- |
| `CTrafficMonitorApp::InitInstance` | `TrafficMonitor.cpp` | App startup |
| `CTrafficMonitorApp::LoadConfig` / `SaveConfig` | `TrafficMonitor.cpp` | Config (de)serialization |
| `CTrafficMonitorDlg::OnTimer` | `TrafficMonitorDlg.cpp` | Sampling tick |
| `CPluginManager::LoadPlugins` | `PluginManager.cpp` | Plugin discovery |
| `TMPluginGetInstance` | (plugin DLL) | Plugin entry export |

---

_Generated June 2026 from zhongyang219/TrafficMonitor at 7901ce0. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
