go my file uploader

This commit is contained in:
AirDog46
2025-05-13 19:45:22 +03:00
commit c5fab8aa94
708 changed files with 343216 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
1.4
* Fixed incorrect drive letters
* Fixed drive letter and panel clipping issue
1.3
* Fixed Vista support
* Adapter information is now updated regardless of whether System Information is open
* Added disk statistics support
1.2
* Added network adapter details window
1.1
* Added native network driver statistics support
1.0
* Initial release

View File

@@ -0,0 +1,402 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,0,0
PRODUCTVERSION 1,4,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "Hardware Devices plugin for Process Hacker"
VALUE "FileVersion", "1.4"
VALUE "InternalName", "HardwareDevices"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "HardwareDevices.dll"
VALUE "ProductName", "Hardware Devices plugin for Process Hacker"
VALUE "ProductVersion", "1.4"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_NETADAPTER_OPTIONS DIALOGEX 0, 0, 265, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Network Adapters"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_NETADAPTERS_LISTVIEW,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,7,251,146
CONTROL "Show hidden adapters",IDC_SHOW_HIDDEN_ADAPTERS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,159,87,10
END
IDD_NETADAPTER_DIALOG DIALOGEX 0, 0, 269, 130
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "",IDC_GRAPH_LAYOUT,0,21,269,53,NOT WS_VISIBLE | WS_BORDER
LTEXT "Static",IDC_ADAPTERNAME,0,0,269,21
LTEXT "Panel layout",IDC_LAYOUT,0,91,268,36,NOT WS_VISIBLE
END
IDD_NETADAPTER_PANEL DIALOGEX 0, 0, 254, 50
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Link speed",IDC_STATIC,7,11,35,8
RTEXT "Static",IDC_LINK_SPEED,50,11,54,8,SS_ENDELLIPSIS
GROUPBOX "Adapter",IDC_STATIC,0,0,111,34
LTEXT "Link state",IDC_STATIC,7,23,32,8
RTEXT "Static",IDC_LINK_STATE,50,23,54,8,SS_ENDELLIPSIS
GROUPBOX "Statistics",IDC_STATIC,116,0,136,45
LTEXT "Bytes sent",IDC_STATIC,125,11,36,8
LTEXT "Bytes received",IDC_STATIC,125,22,50,8
RTEXT "Static",IDC_STAT_BSENT,182,11,62,8,SS_ENDELLIPSIS
RTEXT "Static",IDC_STAT_BRECEIVED,182,22,62,8,SS_ENDELLIPSIS
LTEXT "Bytes total",IDC_STATIC,125,33,37,8
RTEXT "Static",IDC_STAT_BTOTAL,182,33,62,8,SS_ENDELLIPSIS
PUSHBUTTON "Details",IDC_DETAILS,0,35,50,14
END
IDD_NETADAPTER_DETAILS DIALOGEX 0, 0, 309, 265
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Adapter Details"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Close",IDOK,253,244,50,14
CONTROL "",IDC_DETAILS_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,295,235
END
IDD_DISKDRIVE_OPTIONS DIALOGEX 0, 0, 265, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Disk Drives"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_DISKDRIVE_LISTVIEW,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,7,251,163
END
IDD_DISKDRIVE_DIALOG DIALOGEX 0, 0, 315, 135
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "",IDC_GRAPH_LAYOUT,0,21,314,60,NOT WS_VISIBLE | WS_BORDER
LTEXT "Disk",IDC_DISKMOUNTPATH,0,0,105,21
LTEXT "Panel layout",IDC_LAYOUT,0,98,314,36,NOT WS_VISIBLE
RTEXT "Disk name",IDC_DISKNAME,107,4,207,16,SS_WORDELLIPSIS
END
IDD_DISKDRIVE_PANEL DIALOGEX 0, 0, 330, 50
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Statistics",IDC_STATIC,139,0,136,44
LTEXT "Bytes read",IDC_STATIC,148,11,38,8
LTEXT "Bytes written",IDC_STATIC,148,22,45,8
RTEXT "Static",IDC_STAT_BREAD,205,11,62,8,SS_ENDELLIPSIS
RTEXT "Static",IDC_STAT_BWRITE,205,22,62,8,SS_ENDELLIPSIS
LTEXT "Bytes total",IDC_STATIC,148,33,37,8
RTEXT "Static",IDC_STAT_BTOTAL,205,33,62,8,SS_ENDELLIPSIS
LTEXT "Active time",IDC_STATIC,8,11,53,8,SS_ENDELLIPSIS
LTEXT "Response time",IDC_STATIC,8,22,64,8,SS_ENDELLIPSIS
LTEXT "Queue length",IDC_STATIC,8,33,57,8,SS_ENDELLIPSIS
GROUPBOX "Disk",IDC_STATIC,0,0,135,44
PUSHBUTTON "Details",IDC_DETAILS,278,30,50,14,NOT WS_VISIBLE
RTEXT "Static",IDC_STAT_ACTIVE,65,11,62,8,SS_ENDELLIPSIS
RTEXT "Static",IDC_STAT_RESPONSETIME,65,22,62,8,SS_ENDELLIPSIS
RTEXT "Static",IDC_STAT_QUEUELENGTH,65,33,62,8,SS_ENDELLIPSIS
END
IDD_DISKDRIVE_DETAILS_SMART DIALOGEX 0, 0, 309, 265
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "SMART"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_DETAILS_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,295,182
EDITTEXT IDC_EDIT1,7,200,295,58,ES_MULTILINE | ES_READONLY | WS_VSCROLL
LTEXT "Description:",IDC_DESCRIPTION,7,190,39,8
END
IDD_DISKDRIVE_DETAILS_FILESYSTEM DIALOGEX 0, 0, 309, 265
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Volume(s)"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_DETAILS_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,295,182
EDITTEXT IDC_EDIT1,7,200,295,58,ES_MULTILINE | ES_READONLY | WS_VSCROLL
LTEXT "Description:",IDC_DESCRIPTION,7,190,39,8
END
IDD_DISKDRIVE_DETAILS_GENERAL DIALOGEX 0, 0, 275, 262
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
IDD_GPU_DIALOG DIALOGEX 0, 0, 315, 191
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "GPU",IDC_TITLE,0,0,72,21
RTEXT "GPU Name",IDC_GPUNAME,83,4,232,16,SS_WORDELLIPSIS
LTEXT "Panel layout",IDC_LAYOUT,0,145,315,46,NOT WS_VISIBLE
LTEXT "Graph layout",IDC_GRAPH_LAYOUT,0,22,315,120,NOT WS_VISIBLE
LTEXT "GPU:",IDC_GPU_L,73,0,17,8
LTEXT "Memory:",IDC_MEMORY_L,73,5,29,8
LTEXT "Memory Controller:",IDC_SHARED_L,74,11,62,8
LTEXT "Bus Interface:",IDC_BUS_L,74,18,47,8
END
IDD_GPU_PANEL DIALOGEX 0, 0, 372, 47
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Clocks",IDC_STATIC,0,0,118,43
LTEXT "Core",IDC_STATIC,8,10,16,8
LTEXT "Memory",IDC_STATIC,8,21,26,8
RTEXT "Static",IDC_CLOCK_CORE,55,10,54,8,SS_ENDELLIPSIS
RTEXT "Static",IDC_CLOCK_MEMORY,55,21,54,8,SS_ENDELLIPSIS
GROUPBOX "Fan",IDC_STATIC,122,0,124,22
LTEXT "Speed",IDC_STATIC,130,10,21,8
RTEXT "Static",IDC_FAN_PERCENT,158,10,78,8,SS_ENDELLIPSIS
LTEXT "Shader",IDC_STATIC,8,32,24,8
RTEXT "Static",IDC_CLOCK_SHADER,55,32,54,8,SS_ENDELLIPSIS
GROUPBOX "Temperature",IDC_STATIC,122,22,124,21
LTEXT "Core",IDC_STATIC,130,32,16,8
RTEXT "Static",IDC_TEMP_VALUE,158,32,78,8,SS_ENDELLIPSIS
GROUPBOX "Voltage",IDC_STATIC,248,0,124,22
LTEXT "Core",IDC_STATIC,256,10,16,8
RTEXT "Static",IDC_VOLTAGE,284,10,78,8,SS_ENDELLIPSIS
PUSHBUTTON "Details",IDC_DETAILS,249,27,50,14,NOT WS_VISIBLE
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_NETADAPTER_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 258
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
IDD_NETADAPTER_DIALOG, DIALOG
BEGIN
END
IDD_NETADAPTER_PANEL, DIALOG
BEGIN
RIGHTMARGIN, 253
TOPMARGIN, 1
END
IDD_NETADAPTER_DETAILS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 258
END
IDD_DISKDRIVE_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 258
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
IDD_DISKDRIVE_DIALOG, DIALOG
BEGIN
RIGHTMARGIN, 314
BOTTOMMARGIN, 134
END
IDD_DISKDRIVE_PANEL, DIALOG
BEGIN
RIGHTMARGIN, 329
BOTTOMMARGIN, 49
END
IDD_DISKDRIVE_DETAILS_SMART, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 258
END
IDD_DISKDRIVE_DETAILS_FILESYSTEM, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 258
END
IDD_DISKDRIVE_DETAILS_GENERAL, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 268
TOPMARGIN, 7
BOTTOMMARGIN, 255
END
IDD_GPU_DIALOG, DIALOG
BEGIN
END
IDD_GPU_PANEL, DIALOG
BEGIN
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_NETADAPTER_PANEL AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_NETADAPTER_DETAILS AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_NETADAPTER_OPTIONS AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_NETADAPTER_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_OPTIONS AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_PANEL AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_DETAILS_SMART AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_DETAILS_FILESYSTEM AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISKDRIVE_DETAILS_GENERAL AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_GPU_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_GPU_PANEL AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5F0D72C4-8319-4B61-9E13-6084B680EB90}</ProjectGuid>
<RootNamespace>HardwareDevices</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>HardwareDevices</ProjectName>
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Plugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug64</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>iphlpapi.lib;setupapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;setupapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>iphlpapi.lib;setupapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;setupapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<AdditionalDependencies>iphlpapi.lib;setupapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;setupapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<AdditionalDependencies>iphlpapi.lib;setupapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;setupapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="adapter.c" />
<ClCompile Include="diskdetails.c" />
<ClCompile Include="disknotify.c" />
<ClCompile Include="gpugraph.c" />
<ClCompile Include="netdetails.c" />
<ClCompile Include="diskgraph.c" />
<ClCompile Include="diskoptions.c" />
<ClCompile Include="disk.c" />
<ClCompile Include="netgraph.c" />
<ClCompile Include="main.c" />
<ClCompile Include="ndis.c" />
<ClCompile Include="netoptions.c" />
<ClCompile Include="nvidia.c" />
<ClCompile Include="storage.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="devices.h" />
<ClInclude Include="nvapi\nvapi.h" />
<ClInclude Include="nvapi\nvapi_lite_common.h" />
<ClInclude Include="nvidia.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="HardwareDevices.rc" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{47359E56-A930-4DDC-A651-E2E99D48E957}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4965CB7A-371A-4B22-AC3F-E70DC77C5D24}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{00475F04-2369-42D8-9A52-9DB77E37AE62}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Disk">
<UniqueIdentifier>{1ccecf79-cd82-4ae5-b891-64a0a2d18e8e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Network">
<UniqueIdentifier>{c7c48d78-64cd-4559-87c1-74e2141dcd2e}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Graphics">
<UniqueIdentifier>{17660e06-b187-4eca-81d7-f6d3548f3c2f}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Graphics">
<UniqueIdentifier>{987f6036-c8df-4352-abc3-060d5a1bc7e4}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="devices.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nvapi\nvapi.h">
<Filter>Header Files\Graphics</Filter>
</ClInclude>
<ClInclude Include="nvapi\nvapi_lite_common.h">
<Filter>Header Files\Graphics</Filter>
</ClInclude>
<ClInclude Include="nvidia.h">
<Filter>Header Files\Graphics</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="diskoptions.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="ndis.c">
<Filter>Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="storage.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="adapter.c">
<Filter>Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="netgraph.c">
<Filter>Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="netoptions.c">
<Filter>Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="netdetails.c">
<Filter>Source Files\Network</Filter>
</ClCompile>
<ClCompile Include="disk.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="diskgraph.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="diskdetails.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="disknotify.c">
<Filter>Source Files\Disk</Filter>
</ClCompile>
<ClCompile Include="gpugraph.c">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
<ClCompile Include="nvidia.c">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="HardwareDevices.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,292 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
VOID AdapterEntryDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
)
{
PDV_NETADAPTER_ENTRY entry = Object;
PhAcquireQueuedLockExclusive(&NetworkAdaptersListLock);
PhRemoveItemList(NetworkAdaptersList, PhFindItemList(NetworkAdaptersList, entry));
PhReleaseQueuedLockExclusive(&NetworkAdaptersListLock);
DeleteNetAdapterId(&entry->Id);
PhClearReference(&entry->AdapterName);
PhDeleteCircularBuffer_ULONG64(&entry->InboundBuffer);
PhDeleteCircularBuffer_ULONG64(&entry->OutboundBuffer);
}
VOID NetAdaptersInitialize(
VOID
)
{
NetworkAdaptersList = PhCreateList(1);
NetAdapterEntryType = PhCreateObjectType(L"NetAdapterEntry", 0, AdapterEntryDeleteProcedure);
}
VOID NetAdaptersUpdate(
VOID
)
{
static ULONG runCount = 0; // MUST keep in sync with runCount in process provider
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
HANDLE deviceHandle = NULL;
PDV_NETADAPTER_ENTRY entry;
ULONG64 networkInOctets = 0;
ULONG64 networkOutOctets = 0;
ULONG64 networkRcvSpeed = 0;
ULONG64 networkXmitSpeed = 0;
NDIS_MEDIA_CONNECT_STATE mediaState = MediaConnectStateUnknown;
entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!entry)
continue;
if (PhGetIntegerSetting(SETTING_NAME_ENABLE_NDIS))
{
if (NT_SUCCESS(NetworkAdapterCreateHandle(&deviceHandle, entry->Id.InterfaceGuid)))
{
if (!entry->CheckedDeviceSupport)
{
// Check the network adapter supports the OIDs we're going to be using.
if (NetworkAdapterQuerySupported(deviceHandle))
{
entry->DeviceSupported = TRUE;
}
entry->CheckedDeviceSupport = TRUE;
}
if (!entry->DeviceSupported)
{
// Device is faulty. Close the handle so we can fallback to GetIfEntry.
NtClose(deviceHandle);
deviceHandle = NULL;
}
}
}
if (deviceHandle)
{
NDIS_STATISTICS_INFO interfaceStats;
NDIS_LINK_STATE interfaceState;
memset(&interfaceStats, 0, sizeof(NDIS_STATISTICS_INFO));
NetworkAdapterQueryStatistics(deviceHandle, &interfaceStats);
if (NT_SUCCESS(NetworkAdapterQueryLinkState(deviceHandle, &interfaceState)))
{
mediaState = interfaceState.MediaConnectState;
}
if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV))
networkInOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_RCV);
else
networkInOctets = interfaceStats.ifHCInOctets;
if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT))
networkOutOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_XMIT);
else
networkOutOctets = interfaceStats.ifHCOutOctets;
networkRcvSpeed = networkInOctets - entry->LastInboundValue;
networkXmitSpeed = networkOutOctets - entry->LastOutboundValue;
// HACK: Pull the Adapter name from the current query.
if (!entry->AdapterName)
{
entry->AdapterName = NetworkAdapterQueryName(deviceHandle, entry->Id.InterfaceGuid);
}
entry->DevicePresent = TRUE;
NtClose(deviceHandle);
}
else if (WindowsVersion >= WINDOWS_VISTA && GetIfEntry2)
{
MIB_IF_ROW2 interfaceRow;
if (QueryInterfaceRowVista(&entry->Id, &interfaceRow))
{
networkInOctets = interfaceRow.InOctets;
networkOutOctets = interfaceRow.OutOctets;
mediaState = interfaceRow.MediaConnectState;
networkRcvSpeed = networkInOctets - entry->LastInboundValue;
networkXmitSpeed = networkOutOctets - entry->LastOutboundValue;
// HACK: Pull the Adapter name from the current query.
if (!entry->AdapterName && PhCountStringZ(interfaceRow.Description) > 0)
{
entry->AdapterName = PhCreateString(interfaceRow.Description);
}
entry->DevicePresent = TRUE;
}
else
{
entry->DevicePresent = FALSE;
}
}
else
{
MIB_IFROW interfaceRow;
if (QueryInterfaceRowXP(&entry->Id, &interfaceRow))
{
networkInOctets = interfaceRow.dwInOctets;
networkOutOctets = interfaceRow.dwOutOctets;
mediaState = interfaceRow.dwOperStatus == IF_OPER_STATUS_OPERATIONAL ? MediaConnectStateConnected : MediaConnectStateDisconnected;
networkRcvSpeed = networkInOctets - entry->LastInboundValue;
networkXmitSpeed = networkOutOctets - entry->LastOutboundValue;
// HACK: Pull the Adapter name from the current query.
if (!entry->AdapterName && strlen(interfaceRow.bDescr) > 0)
{
entry->AdapterName = PhConvertMultiByteToUtf16(interfaceRow.bDescr);
}
entry->DevicePresent = TRUE;
}
else
{
entry->DevicePresent = FALSE;
}
}
if (mediaState == MediaConnectStateUnknown)
{
// We don't want incorrect data when the adapter is disabled.
networkRcvSpeed = 0;
networkXmitSpeed = 0;
}
if (!entry->HaveFirstSample)
{
// The first sample must be zero.
networkRcvSpeed = 0;
networkXmitSpeed = 0;
entry->HaveFirstSample = TRUE;
}
if (runCount != 0)
{
PhAddItemCircularBuffer_ULONG64(&entry->InboundBuffer, networkRcvSpeed);
PhAddItemCircularBuffer_ULONG64(&entry->OutboundBuffer, networkXmitSpeed);
}
//context->LinkSpeed = networkLinkSpeed;
entry->InboundValue = networkRcvSpeed;
entry->OutboundValue = networkXmitSpeed;
entry->LastInboundValue = networkInOctets;
entry->LastOutboundValue = networkOutOctets;
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
runCount++;
}
VOID InitializeNetAdapterId(
_Out_ PDV_NETADAPTER_ID Id,
_In_ NET_IFINDEX InterfaceIndex,
_In_ IF_LUID InterfaceLuid,
_In_ PPH_STRING InterfaceGuid
)
{
Id->InterfaceIndex = InterfaceIndex;
Id->InterfaceLuid = InterfaceLuid;
PhSetReference(&Id->InterfaceGuid, InterfaceGuid);
}
VOID CopyNetAdapterId(
_Out_ PDV_NETADAPTER_ID Destination,
_In_ PDV_NETADAPTER_ID Source
)
{
InitializeNetAdapterId(
Destination,
Source->InterfaceIndex,
Source->InterfaceLuid,
Source->InterfaceGuid
);
}
VOID DeleteNetAdapterId(
_Inout_ PDV_NETADAPTER_ID Id
)
{
PhClearReference(&Id->InterfaceGuid);
}
BOOLEAN EquivalentNetAdapterId(
_In_ PDV_NETADAPTER_ID Id1,
_In_ PDV_NETADAPTER_ID Id2
)
{
if (WindowsVersion >= WINDOWS_VISTA)
{
if (Id1->InterfaceLuid.Value == Id2->InterfaceLuid.Value)
return TRUE;
}
else
{
if (Id1->InterfaceIndex == Id2->InterfaceIndex)
return TRUE;
}
return FALSE;
}
PDV_NETADAPTER_ENTRY CreateNetAdapterEntry(
_In_ PDV_NETADAPTER_ID Id
)
{
PDV_NETADAPTER_ENTRY entry;
entry = PhCreateObject(sizeof(DV_NETADAPTER_ENTRY), NetAdapterEntryType);
memset(entry, 0, sizeof(DV_NETADAPTER_ENTRY));
CopyNetAdapterId(&entry->Id, Id);
PhInitializeCircularBuffer_ULONG64(&entry->InboundBuffer, PhGetIntegerSetting(L"SampleCount"));
PhInitializeCircularBuffer_ULONG64(&entry->OutboundBuffer, PhGetIntegerSetting(L"SampleCount"));
PhAcquireQueuedLockExclusive(&NetworkAdaptersListLock);
PhAddItemList(NetworkAdaptersList, entry);
PhReleaseQueuedLockExclusive(&NetworkAdaptersListLock);
return entry;
}

View File

@@ -0,0 +1,773 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DEVICES_H_
#define _DEVICES_H_
#define PLUGIN_NAME L"ProcessHacker.HardwareDevices"
#define SETTING_NAME_ENABLE_NDIS (PLUGIN_NAME L".EnableNDIS")
#define SETTING_NAME_INTERFACE_LIST (PLUGIN_NAME L".NetworkList")
#define SETTING_NAME_DISK_LIST (PLUGIN_NAME L".DiskList")
#ifdef _NV_GPU_BUILD
#define SETTING_NAME_ENABLE_GPU (PLUGIN_NAME L".EnableGpu")
#define SETTING_NAME_ENABLE_FAHRENHEIT (PLUGIN_NAME L".ShowFahrenheit")
#endif
#define CINTERFACE
#define COBJMACROS
#include <phdk.h>
#include <phappresource.h>
#include <windowsx.h>
#include <uxtheme.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <nldef.h>
#include <netioapi.h>
//#include <WinSock2.h>
#include "resource.h"
#define WM_SHOWDIALOG (WM_APP + 1)
#define UPDATE_MSG (WM_APP + 2)
extern PPH_PLUGIN PluginInstance;
extern PPH_OBJECT_TYPE NetAdapterEntryType;
extern PPH_LIST NetworkAdaptersList;
extern PH_QUEUED_LOCK NetworkAdaptersListLock;
extern PPH_OBJECT_TYPE DiskDriveEntryType;
extern PPH_LIST DiskDrivesList;
extern PH_QUEUED_LOCK DiskDrivesListLock;
// main.c
PPH_STRING TrimString(
_In_ PPH_STRING String
);
INT AddListViewGroup(
_In_ HWND ListViewHandle,
_In_ INT Index,
_In_ PWSTR Text
);
INT AddListViewItemGroupId(
_In_ HWND ListViewHandle,
_In_ INT GroupId,
_In_ INT Index,
_In_ PWSTR Text,
_In_opt_ PVOID Param
);
ULONG64 RegQueryUlong64(
_In_ HANDLE KeyHandle,
_In_ PWSTR ValueName
);
VOID ShowDeviceMenu(
_In_ HWND ParentWindow,
_In_ PPH_STRING DeviceInstance
);
// adapter.c
typedef struct _DV_NETADAPTER_ID
{
NET_IFINDEX InterfaceIndex;
IF_LUID InterfaceLuid;
PPH_STRING InterfaceGuid;
} DV_NETADAPTER_ID, *PDV_NETADAPTER_ID;
typedef struct _DV_NETADAPTER_ENTRY
{
DV_NETADAPTER_ID Id;
PPH_STRING AdapterName;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN UserReference : 1;
BOOLEAN HaveFirstSample : 1;
BOOLEAN CheckedDeviceSupport : 1;
BOOLEAN DeviceSupported : 1;
BOOLEAN DevicePresent : 1;
BOOLEAN Spare : 3;
};
};
//ULONG64 LinkSpeed;
ULONG64 InboundValue;
ULONG64 OutboundValue;
ULONG64 LastInboundValue;
ULONG64 LastOutboundValue;
PH_CIRCULAR_BUFFER_ULONG64 InboundBuffer;
PH_CIRCULAR_BUFFER_ULONG64 OutboundBuffer;
} DV_NETADAPTER_ENTRY, *PDV_NETADAPTER_ENTRY;
typedef struct _DV_NETADAPTER_SYSINFO_CONTEXT
{
PDV_NETADAPTER_ENTRY AdapterEntry;
PPH_STRING SectionName;
HWND WindowHandle;
HWND PanelWindowHandle;
HWND GraphHandle;
PPH_SYSINFO_SECTION SysinfoSection;
PH_GRAPH_STATE GraphState;
PH_LAYOUT_MANAGER LayoutManager;
} DV_NETADAPTER_SYSINFO_CONTEXT, *PDV_NETADAPTER_SYSINFO_CONTEXT;
typedef struct _DV_NETADAPTER_DETAILS_CONTEXT
{
PPH_STRING AdapterName;
DV_NETADAPTER_ID AdapterId;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN HaveFirstSample : 1;
BOOLEAN CheckedDeviceSupport : 1;
BOOLEAN DeviceSupported : 1;
BOOLEAN Spare : 5;
};
};
HWND WindowHandle;
HWND ParentHandle;
HWND ListViewHandle;
HANDLE NotifyHandle;
PH_LAYOUT_MANAGER LayoutManager;
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
ULONG64 LastDetailsInboundValue;
ULONG64 LastDetailsIOutboundValue;
} DV_NETADAPTER_DETAILS_CONTEXT, *PDV_NETADAPTER_DETAILS_CONTEXT;
typedef struct _DV_NETADAPTER_CONTEXT
{
HWND ListViewHandle;
//HIMAGELIST ImageList;
BOOLEAN OptionsChanged;
BOOLEAN EnumeratingAdapters;
BOOLEAN UseAlternateMethod;
} DV_NETADAPTER_CONTEXT, *PDV_NETADAPTER_CONTEXT;
VOID NetAdaptersLoadList(
VOID
);
VOID ShowOptionsDialog(
_In_ HWND ParentHandle
);
// adapter.c
VOID NetAdaptersInitialize(
VOID
);
VOID NetAdaptersUpdate(
VOID
);
VOID InitializeNetAdapterId(
_Out_ PDV_NETADAPTER_ID Id,
_In_ NET_IFINDEX InterfaceIndex,
_In_ IF_LUID InterfaceLuid,
_In_ PPH_STRING InterfaceGuid
);
VOID CopyNetAdapterId(
_Out_ PDV_NETADAPTER_ID Destination,
_In_ PDV_NETADAPTER_ID Source
);
VOID DeleteNetAdapterId(
_Inout_ PDV_NETADAPTER_ID Id
);
BOOLEAN EquivalentNetAdapterId(
_In_ PDV_NETADAPTER_ID Id1,
_In_ PDV_NETADAPTER_ID Id2
);
PDV_NETADAPTER_ENTRY CreateNetAdapterEntry(
_In_ PDV_NETADAPTER_ID Id
);
// dialog.c
typedef enum _NETADAPTER_DETAILS_CATEGORY
{
NETADAPTER_DETAILS_CATEGORY_ADAPTER,
NETADAPTER_DETAILS_CATEGORY_UNICAST,
NETADAPTER_DETAILS_CATEGORY_BROADCAST,
NETADAPTER_DETAILS_CATEGORY_MULTICAST,
NETADAPTER_DETAILS_CATEGORY_ERRORS
} NETADAPTER_DETAILS_CATEGORY;
typedef enum _NETADAPTER_DETAILS_INDEX
{
NETADAPTER_DETAILS_INDEX_STATE,
//NETADAPTER_DETAILS_INDEX_CONNECTIVITY,
NETADAPTER_DETAILS_INDEX_IPADDRESS,
NETADAPTER_DETAILS_INDEX_SUBNET,
NETADAPTER_DETAILS_INDEX_GATEWAY,
NETADAPTER_DETAILS_INDEX_DNS,
NETADAPTER_DETAILS_INDEX_DOMAIN,
NETADAPTER_DETAILS_INDEX_LINKSPEED,
NETADAPTER_DETAILS_INDEX_SENT,
NETADAPTER_DETAILS_INDEX_RECEIVED,
NETADAPTER_DETAILS_INDEX_TOTAL,
NETADAPTER_DETAILS_INDEX_SENDING,
NETADAPTER_DETAILS_INDEX_RECEIVING,
NETADAPTER_DETAILS_INDEX_UTILIZATION,
NETADAPTER_DETAILS_INDEX_UNICAST_SENTPKTS,
NETADAPTER_DETAILS_INDEX_UNICAST_RECVPKTS,
NETADAPTER_DETAILS_INDEX_UNICAST_TOTALPKTS,
NETADAPTER_DETAILS_INDEX_UNICAST_SENT,
NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVED,
NETADAPTER_DETAILS_INDEX_UNICAST_TOTAL,
//NETADAPTER_DETAILS_INDEX_UNICAST_SENDING,
//NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVING,
//NETADAPTER_DETAILS_INDEX_UNICAST_UTILIZATION,
NETADAPTER_DETAILS_INDEX_BROADCAST_SENTPKTS,
NETADAPTER_DETAILS_INDEX_BROADCAST_RECVPKTS,
NETADAPTER_DETAILS_INDEX_BROADCAST_TOTALPKTS,
NETADAPTER_DETAILS_INDEX_BROADCAST_SENT,
NETADAPTER_DETAILS_INDEX_BROADCAST_RECEIVED,
NETADAPTER_DETAILS_INDEX_BROADCAST_TOTAL,
NETADAPTER_DETAILS_INDEX_MULTICAST_SENTPKTS,
NETADAPTER_DETAILS_INDEX_MULTICAST_RECVPKTS,
NETADAPTER_DETAILS_INDEX_MULTICAST_TOTALPKTS,
NETADAPTER_DETAILS_INDEX_MULTICAST_SENT,
NETADAPTER_DETAILS_INDEX_MULTICAST_RECEIVED,
NETADAPTER_DETAILS_INDEX_MULTICAST_TOTAL,
NETADAPTER_DETAILS_INDEX_ERRORS_SENTPKTS,
NETADAPTER_DETAILS_INDEX_ERRORS_RECVPKTS,
NETADAPTER_DETAILS_INDEX_ERRORS_TOTALPKTS,
NETADAPTER_DETAILS_INDEX_ERRORS_SENT,
NETADAPTER_DETAILS_INDEX_ERRORS_RECEIVED,
NETADAPTER_DETAILS_INDEX_ERRORS_TOTAL
} NETADAPTER_DETAILS_INDEX;
VOID ShowNetAdapterDetailsDialog(
_In_ PDV_NETADAPTER_SYSINFO_CONTEXT Context
);
// ndis.c
#define BITS_IN_ONE_BYTE 8
#define NDIS_UNIT_OF_MEASUREMENT 100
// dmex: rev
typedef ULONG (WINAPI* _GetInterfaceDescriptionFromGuid)(
_Inout_ PGUID InterfaceGuid,
_Out_opt_ PWSTR InterfaceDescription,
_Inout_ PSIZE_T LengthAddress,
PVOID Unknown1,
PVOID Unknown2
);
NTSTATUS NetworkAdapterCreateHandle(
_Out_ PHANDLE DeviceHandle,
_In_ PPH_STRING InterfaceGuid
);
BOOLEAN NetworkAdapterQuerySupported(
_In_ HANDLE DeviceHandle
);
BOOLEAN NetworkAdapterQueryNdisVersion(
_In_ HANDLE DeviceHandle,
_Out_opt_ PUINT MajorVersion,
_Out_opt_ PUINT MinorVersion
);
PPH_STRING NetworkAdapterQueryName(
_In_ HANDLE DeviceHandle,
_In_ PPH_STRING InterfaceGuid
);
NTSTATUS NetworkAdapterQueryStatistics(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_STATISTICS_INFO Info
);
NTSTATUS NetworkAdapterQueryLinkState(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_LINK_STATE State
);
BOOLEAN NetworkAdapterQueryMediaType(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_PHYSICAL_MEDIUM Medium
);
NTSTATUS NetworkAdapterQueryLinkSpeed(
_In_ HANDLE DeviceHandle,
_Out_ PULONG64 LinkSpeed
);
ULONG64 NetworkAdapterQueryValue(
_In_ HANDLE DeviceHandle,
_In_ NDIS_OID OpCode
);
BOOLEAN QueryInterfaceRowVista(
_In_ PDV_NETADAPTER_ID Id,
_Out_ PMIB_IF_ROW2 InterfaceRow
);
BOOLEAN QueryInterfaceRowXP(
_In_ PDV_NETADAPTER_ID Id,
_Out_ PMIB_IFROW InterfaceRow
);
// netoptions.c
INT_PTR CALLBACK NetworkAdapterOptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// diskoptions.c
INT_PTR CALLBACK DiskDriveOptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// disk.c
typedef struct _DV_DISK_ID
{
PPH_STRING DevicePath;
} DV_DISK_ID, *PDV_DISK_ID;
typedef struct _DV_DISK_ENTRY
{
DV_DISK_ID Id;
PPH_STRING DiskName;
PPH_STRING DiskIndexName;
ULONG DiskIndex;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN UserReference : 1;
BOOLEAN HaveFirstSample : 1;
BOOLEAN DevicePresent : 1;
BOOLEAN Spare : 5;
};
};
PH_CIRCULAR_BUFFER_ULONG64 ReadBuffer;
PH_CIRCULAR_BUFFER_ULONG64 WriteBuffer;
PH_UINT64_DELTA BytesReadDelta;
PH_UINT64_DELTA BytesWrittenDelta;
PH_UINT64_DELTA ReadTimeDelta;
PH_UINT64_DELTA WriteTimeDelta;
PH_UINT64_DELTA IdleTimeDelta;
PH_UINT32_DELTA ReadCountDelta;
PH_UINT32_DELTA WriteCountDelta;
PH_UINT64_DELTA QueryTimeDelta;
FLOAT ResponseTime;
FLOAT ActiveTime;
ULONG QueueDepth;
ULONG SplitCount;
} DV_DISK_ENTRY, *PDV_DISK_ENTRY;
typedef struct _DV_DISK_SYSINFO_CONTEXT
{
PDV_DISK_ENTRY DiskEntry;
PPH_STRING SectionName;
HWND WindowHandle;
HWND PanelWindowHandle;
HWND GraphHandle;
PPH_SYSINFO_SECTION SysinfoSection;
PH_GRAPH_STATE GraphState;
PH_LAYOUT_MANAGER LayoutManager;
} DV_DISK_SYSINFO_CONTEXT, *PDV_DISK_SYSINFO_CONTEXT;
typedef struct _DV_DISK_OPTIONS_CONTEXT
{
HWND ListViewHandle;
//HIMAGELIST ImageList;
BOOLEAN OptionsChanged;
BOOLEAN EnumeratingDisks;
} DV_DISK_OPTIONS_CONTEXT, *PDV_DISK_OPTIONS_CONTEXT;
VOID DiskDrivesInitialize(VOID);
VOID DiskDrivesLoadList(VOID);
VOID DiskDrivesUpdate(VOID);
VOID DiskDriveUpdateDeviceInfo(
_In_opt_ HANDLE DeviceHandle,
_In_ PDV_DISK_ENTRY DiskEntry
);
VOID InitializeDiskId(
_Out_ PDV_DISK_ID Id,
_In_ PPH_STRING DevicePath
);
VOID CopyDiskId(
_Out_ PDV_DISK_ID Destination,
_In_ PDV_DISK_ID Source
);
VOID DeleteDiskId(
_Inout_ PDV_DISK_ID Id
);
BOOLEAN EquivalentDiskId(
_In_ PDV_DISK_ID Id1,
_In_ PDV_DISK_ID Id2
);
PDV_DISK_ENTRY CreateDiskEntry(
_In_ PDV_DISK_ID Id
);
// diskdetails.c
VOID ShowDiskDriveDetailsDialog(
_In_ PDV_DISK_SYSINFO_CONTEXT Context
);
// disknotify.c
VOID AddRemoveDeviceChangeCallback(
VOID
);
// storage.c
NTSTATUS DiskDriveCreateHandle(
_Out_ PHANDLE DeviceHandle,
_In_ PPH_STRING DevicePath
);
PPH_STRING DiskDriveQueryDosMountPoints(
_In_ ULONG DeviceNumber
);
BOOLEAN DiskDriveQueryDeviceInformation(
_In_ HANDLE DeviceHandle,
_Out_opt_ PPH_STRING* DiskVendor,
_Out_opt_ PPH_STRING* DiskModel,
_Out_opt_ PPH_STRING* DiskRevision,
_Out_opt_ PPH_STRING* DiskSerial
);
NTSTATUS DiskDriveQueryDeviceTypeAndNumber(
_In_ HANDLE DeviceHandle,
_Out_opt_ PULONG DeviceNumber,
_Out_opt_ DEVICE_TYPE* DeviceType
);
NTSTATUS DiskDriveQueryStatistics(
_In_ HANDLE DeviceHandle,
_Out_ PDISK_PERFORMANCE Info
);
PPH_STRING DiskDriveQueryGeometry(
_In_ HANDLE DeviceHandle
);
BOOLEAN DiskDriveQueryImminentFailure(
_In_ HANDLE DeviceHandle,
_Out_ PPH_LIST* DiskSmartAttributes
);
typedef struct _DISK_HANDLE_ENTRY
{
WCHAR DeviceLetter;
HANDLE DeviceHandle;
} DISK_HANDLE_ENTRY, *PDISK_HANDLE_ENTRY;
PPH_LIST DiskDriveQueryMountPointHandles(
_In_ ULONG DeviceNumber
);
typedef struct _NTFS_FILESYSTEM_STATISTICS
{
FILESYSTEM_STATISTICS FileSystemStatistics;
NTFS_STATISTICS NtfsStatistics;
} NTFS_FILESYSTEM_STATISTICS, *PNTFS_FILESYSTEM_STATISTICS;
typedef struct _FAT_FILESYSTEM_STATISTICS
{
FILESYSTEM_STATISTICS FileSystemStatistics;
NTFS_STATISTICS FatStatistics;
} FAT_FILESYSTEM_STATISTICS, *PFAT_FILESYSTEM_STATISTICS;
typedef struct _EXFAT_FILESYSTEM_STATISTICS
{
FILESYSTEM_STATISTICS FileSystemStatistics;
EXFAT_STATISTICS ExFatStatistics;
} EXFAT_FILESYSTEM_STATISTICS, *PEXFAT_FILESYSTEM_STATISTICS;
BOOLEAN DiskDriveQueryFileSystemInfo(
_In_ HANDLE DeviceHandle,
_Out_ USHORT* FileSystemType,
_Out_ PVOID* FileSystemStatistics
);
typedef struct _NTFS_VOLUME_INFO
{
NTFS_VOLUME_DATA_BUFFER VolumeData;
NTFS_EXTENDED_VOLUME_DATA ExtendedVolumeData;
} NTFS_VOLUME_INFO, *PNTFS_VOLUME_INFO;
BOOLEAN DiskDriveQueryNtfsVolumeInfo(
_In_ HANDLE DosDeviceHandle,
_Out_ PNTFS_VOLUME_INFO VolumeInfo
);
BOOLEAN DiskDriveQueryRefsVolumeInfo(
_In_ HANDLE DosDeviceHandle,
_Out_ PREFS_VOLUME_DATA_BUFFER VolumeInfo
);
NTSTATUS DiskDriveQueryVolumeInformation(
_In_ HANDLE DosDeviceHandle,
_Out_ PFILE_FS_VOLUME_INFORMATION* VolumeInfo
);
NTSTATUS DiskDriveQueryVolumeAttributes(
_In_ HANDLE DosDeviceHandle,
_Out_ PFILE_FS_ATTRIBUTE_INFORMATION* AttributeInfo
);
typedef enum _SMART_ATTRIBUTE_ID
{
SMART_ATTRIBUTE_ID_READ_ERROR_RATE = 0x01,
SMART_ATTRIBUTE_ID_THROUGHPUT_PERFORMANCE = 0x02,
SMART_ATTRIBUTE_ID_SPIN_UP_TIME = 0x03,
SMART_ATTRIBUTE_ID_START_STOP_COUNT = 0x04,
SMART_ATTRIBUTE_ID_REALLOCATED_SECTORS_COUNT = 0x05,
SMART_ATTRIBUTE_ID_READ_CHANNEL_MARGIN = 0x06,
SMART_ATTRIBUTE_ID_SEEK_ERROR_RATE = 0x07,
SMART_ATTRIBUTE_ID_SEEK_TIME_PERFORMANCE = 0x08,
SMART_ATTRIBUTE_ID_POWER_ON_HOURS = 0x09,
SMART_ATTRIBUTE_ID_SPIN_RETRY_COUNT = 0x0A,
SMART_ATTRIBUTE_ID_CALIBRATION_RETRY_COUNT = 0x0B,
SMART_ATTRIBUTE_ID_POWER_CYCLE_COUNT = 0x0C,
SMART_ATTRIBUTE_ID_SOFT_READ_ERROR_RATE = 0x0D,
// Unknown values 14-182
SMART_ATTRIBUTE_ID_SATA_DOWNSHIFT_ERROR_COUNT = 0xB7,
SMART_ATTRIBUTE_ID_END_TO_END_ERROR = 0xB8,
SMART_ATTRIBUTE_ID_HEAD_STABILITY = 0xB9,
SMART_ATTRIBUTE_ID_INDUCED_OP_VIBRATION_DETECTION = 0xBA,
SMART_ATTRIBUTE_ID_REPORTED_UNCORRECTABLE_ERRORS = 0xBB,
SMART_ATTRIBUTE_ID_COMMAND_TIMEOUT = 0xBC,
SMART_ATTRIBUTE_ID_HIGH_FLY_WRITES = 0xBD,
SMART_ATTRIBUTE_ID_TEMPERATURE_DIFFERENCE_FROM_100 = 0xBE, // AirflowTemperature
SMART_ATTRIBUTE_ID_GSENSE_ERROR_RATE = 0xBF,
SMART_ATTRIBUTE_ID_POWER_OFF_RETRACT_COUNT = 0xC0,
SMART_ATTRIBUTE_ID_LOAD_CYCLE_COUNT = 0xC1,
SMART_ATTRIBUTE_ID_TEMPERATURE = 0xC2,
SMART_ATTRIBUTE_ID_HARDWARE_ECC_RECOVERED = 0xC3,
SMART_ATTRIBUTE_ID_REALLOCATION_EVENT_COUNT = 0xC4,
SMART_ATTRIBUTE_ID_CURRENT_PENDING_SECTOR_COUNT = 0xC5,
SMART_ATTRIBUTE_ID_UNCORRECTABLE_SECTOR_COUNT = 0xC6,
SMART_ATTRIBUTE_ID_ULTRADMA_CRC_ERROR_COUNT = 0xC7,
SMART_ATTRIBUTE_ID_MULTI_ZONE_ERROR_RATE = 0xC8,
SMART_ATTRIBUTE_ID_OFFTRACK_SOFT_READ_ERROR_RATE = 0xC9,
SMART_ATTRIBUTE_ID_DATA_ADDRESS_MARK_ERRORS = 0xCA,
SMART_ATTRIBUTE_ID_RUN_OUT_CANCEL = 0xCB,
SMART_ATTRIBUTE_ID_SOFT_ECC_CORRECTION = 0xCC,
SMART_ATTRIBUTE_ID_THERMAL_ASPERITY_RATE_TAR = 0xCD,
SMART_ATTRIBUTE_ID_FLYING_HEIGHT = 0xCE,
SMART_ATTRIBUTE_ID_SPIN_HIGH_CURRENT = 0xCF,
SMART_ATTRIBUTE_ID_SPIN_BUZZ = 0xD0,
SMART_ATTRIBUTE_ID_OFFLINE_SEEK_PERFORMANCE = 0xD1,
SMART_ATTRIBUTE_ID_VIBRATION_DURING_WRITE = 0xD3,
SMART_ATTRIBUTE_ID_SHOCK_DURING_WRITE = 0xD4,
SMART_ATTRIBUTE_ID_DISK_SHIFT = 0xDC,
SMART_ATTRIBUTE_ID_GSENSE_ERROR_RATE_ALT = 0xDD,
SMART_ATTRIBUTE_ID_LOADED_HOURS = 0xDE,
SMART_ATTRIBUTE_ID_LOAD_UNLOAD_RETRY_COUNT = 0xDF,
SMART_ATTRIBUTE_ID_LOAD_FRICTION = 0xE0,
SMART_ATTRIBUTE_ID_LOAD_UNLOAD_CYCLE_COUNT = 0xE1,
SMART_ATTRIBUTE_ID_LOAD_IN_TIME = 0xE2,
SMART_ATTRIBUTE_ID_TORQUE_AMPLIFICATION_COUNT = 0xE3,
SMART_ATTRIBUTE_ID_POWER_OFF_RETTRACT_CYCLE = 0xE4,
// Unknown values 229
SMART_ATTRIBUTE_ID_GMR_HEAD_AMPLITUDE = 0xE6,
SMART_ATTRIBUTE_ID_DRIVE_TEMPERATURE = 0xE7,
// Unknown values 232-239
SMART_ATTRIBUTE_ID_HEAD_FLYING_HOURS = 0xF0,
SMART_ATTRIBUTE_ID_TOTAL_LBA_WRITTEN = 0xF1,
SMART_ATTRIBUTE_ID_TOTAL_LBA_READ = 0xF2,
// Unknown values 243-249
SMART_ATTRIBUTE_ID_READ_ERROR_RETY_RATE = 0xFA,
// Unknown values 251-253
SMART_ATTRIBUTE_ID_FREE_FALL_PROTECTION = 0xFE,
} SMART_ATTRIBUTE_ID;
#define SMART_HEADER_SIZE 2
#include <pshpack1.h>
typedef struct _SMART_ATTRIBUTE
{
BYTE Id;
USHORT Flags;
BYTE CurrentValue;
BYTE WorstValue;
BYTE RawValue[6];
BYTE Reserved;
} SMART_ATTRIBUTE, *PSMART_ATTRIBUTE;
#include <poppack.h>
typedef struct _SMART_ATTRIBUTES
{
SMART_ATTRIBUTE_ID AttributeId;
UINT CurrentValue;
UINT WorstValue;
UINT RawValue;
// Pre-fail/Advisory bit
// This bit is applicable only when the value of this attribute is less than or equal to its threshhold.
// 0 : Advisory: The device has exceeded its intended design life period.
// 1 : Pre-failure notification : Failure is predicted within 24 hours.
BOOLEAN Advisory;
BOOLEAN FailureImminent;
// Online data collection bit
// 0 : This value of this attribute is only updated during offline activities.
// 1 : The value of this attribute is updated during both normal operation and offline activities.
BOOLEAN OnlineDataCollection;
// TRUE: This attribute characterizes a performance aspect of the drive,
// degradation of which may indicate imminent drive failure, such as data throughput, seektimes, spin up time, etc.
BOOLEAN Performance;
// TRUE: This attribute is based on the expected, non-fatal errors that are inherent in disk drives,
// increases in which may indicate imminent drive failure, such as ECC errors, seek errors, etc.
BOOLEAN ErrorRate;
// TRUE: This attribute counts events, of which an excessive number of which may
// indicate imminent drive failure, such as number of re-allocated sectors, etc.
BOOLEAN EventCount;
// TRUE: This type is used to specify an attribute that is collected and saved by the drive automatically.
BOOLEAN SelfPreserving;
} SMART_ATTRIBUTES, *PSMART_ATTRIBUTES;
PWSTR SmartAttributeGetText(
_In_ SMART_ATTRIBUTE_ID AttributeId
);
PWSTR SmartAttributeGetDescription(
_In_ SMART_ATTRIBUTE_ID AttributeId
);
// diskgraph.c
VOID DiskDriveSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers,
_In_ _Assume_refs_(1) PDV_DISK_ENTRY DiskEntry
);
// netgraph.c
VOID NetAdapterSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers,
_In_ _Assume_refs_(1) PDV_NETADAPTER_ENTRY AdapterEntry
);
#ifdef _NV_GPU_BUILD
// Graphics
extern BOOLEAN NvApiInitialized;
extern ULONG GpuMemoryLimit;
extern FLOAT GpuCurrentGpuUsage;
extern FLOAT GpuCurrentCoreUsage;
extern FLOAT GpuCurrentBusUsage;
extern ULONG GpuCurrentMemUsage;
extern ULONG GpuCurrentMemSharedUsage;
extern ULONG GpuCurrentCoreTemp;
extern ULONG GpuCurrentBoardTemp;
extern ULONG GpuCurrentCoreClock;
extern ULONG GpuCurrentMemoryClock;
extern ULONG GpuCurrentShaderClock;
extern ULONG GpuCurrentVoltage;
extern PH_CIRCULAR_BUFFER_FLOAT GpuUtilizationHistory;
extern PH_CIRCULAR_BUFFER_ULONG GpuMemoryHistory;
extern PH_CIRCULAR_BUFFER_FLOAT GpuBoardHistory;
extern PH_CIRCULAR_BUFFER_FLOAT GpuBusHistory;
VOID NvGpuSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers
);
VOID NvApiInitialize(VOID);
BOOLEAN DestroyNvApi(VOID);
PPH_STRING NvGpuQueryDriverVersion(VOID);
PPH_STRING NvGpuQueryVbiosVersionString(VOID);
PPH_STRING NvGpuQueryName(VOID);
PPH_STRING NvGpuQueryShortName(VOID);
PPH_STRING NvGpuQueryRevision(VOID);
PPH_STRING NvGpuQueryRamType(VOID);
PPH_STRING NvGpuQueryFoundry(VOID);
PPH_STRING NvGpuQueryDeviceId(VOID);
PPH_STRING NvGpuQueryRopsCount(VOID);
PPH_STRING NvGpuQueryShaderCount(VOID);
PPH_STRING NvGpuQueryPciInfo(VOID);
PPH_STRING NvGpuQueryBusWidth(VOID);
PPH_STRING NvGpuQueryPcbValue(VOID);
PPH_STRING NvGpuQueryDriverSettings(VOID);
PPH_STRING NvGpuQueryFanSpeed(VOID);
BOOLEAN NvGpuDriverIsWHQL(VOID);
VOID NvGpuUpdate(VOID);
#endif
#endif _DEVICES_H_

View File

@@ -0,0 +1,303 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
VOID DiskEntryDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
)
{
PDV_DISK_ENTRY entry = Object;
PhAcquireQueuedLockExclusive(&DiskDrivesListLock);
PhRemoveItemList(DiskDrivesList, PhFindItemList(DiskDrivesList, entry));
PhReleaseQueuedLockExclusive(&DiskDrivesListLock);
DeleteDiskId(&entry->Id);
PhClearReference(&entry->DiskName);
PhDeleteCircularBuffer_ULONG64(&entry->ReadBuffer);
PhDeleteCircularBuffer_ULONG64(&entry->WriteBuffer);
AddRemoveDeviceChangeCallback();
}
VOID DiskDrivesInitialize(
VOID
)
{
DiskDrivesList = PhCreateList(1);
DiskDriveEntryType = PhCreateObjectType(L"DiskDriveEntry", 0, DiskEntryDeleteProcedure);
}
VOID DiskDrivesUpdate(
VOID
)
{
static ULONG runCount = 0; // MUST keep in sync with runCount in process provider
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
HANDLE deviceHandle;
PDV_DISK_ENTRY entry;
entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
if (NT_SUCCESS(DiskDriveCreateHandle(&deviceHandle, entry->Id.DevicePath)))
{
DISK_PERFORMANCE diskPerformance;
if (NT_SUCCESS(DiskDriveQueryStatistics(deviceHandle, &diskPerformance)))
{
ULONG64 readTime;
ULONG64 writeTime;
ULONG64 idleTime;
ULONG readCount;
ULONG writeCount;
ULONG64 queryTime;
PhUpdateDelta(&entry->BytesReadDelta, diskPerformance.BytesRead.QuadPart);
PhUpdateDelta(&entry->BytesWrittenDelta, diskPerformance.BytesWritten.QuadPart);
PhUpdateDelta(&entry->ReadTimeDelta, diskPerformance.ReadTime.QuadPart);
PhUpdateDelta(&entry->WriteTimeDelta, diskPerformance.WriteTime.QuadPart);
PhUpdateDelta(&entry->IdleTimeDelta, diskPerformance.IdleTime.QuadPart);
PhUpdateDelta(&entry->ReadCountDelta, diskPerformance.ReadCount);
PhUpdateDelta(&entry->WriteCountDelta, diskPerformance.WriteCount);
PhUpdateDelta(&entry->QueryTimeDelta, diskPerformance.QueryTime.QuadPart);
readTime = entry->ReadTimeDelta.Delta;
writeTime = entry->WriteTimeDelta.Delta;
idleTime = entry->IdleTimeDelta.Delta;
readCount = entry->ReadCountDelta.Delta;
writeCount = entry->WriteCountDelta.Delta;
queryTime = entry->QueryTimeDelta.Delta;
if (readCount + writeCount != 0)
entry->ResponseTime = ((FLOAT)readTime + (FLOAT)writeTime) / (readCount + writeCount);
else
entry->ResponseTime = 0;
if (queryTime != 0)
entry->ActiveTime = (FLOAT)(queryTime - idleTime) / queryTime * 100;
else
entry->ActiveTime = 0.0f;
if (entry->ActiveTime > 100.f)
entry->ActiveTime = 0.f;
if (entry->ActiveTime < 0.f)
entry->ActiveTime = 0.f;
entry->QueueDepth = diskPerformance.QueueDepth;
entry->SplitCount = diskPerformance.SplitCount;
entry->DiskIndex = diskPerformance.StorageDeviceNumber;
entry->DevicePresent = TRUE;
}
else
{
// Disk has been disconnected or dismounted.
PhInitializeDelta(&entry->BytesReadDelta);
PhInitializeDelta(&entry->BytesWrittenDelta);
PhInitializeDelta(&entry->ReadTimeDelta);
PhInitializeDelta(&entry->WriteTimeDelta);
PhInitializeDelta(&entry->IdleTimeDelta);
PhInitializeDelta(&entry->ReadCountDelta);
PhInitializeDelta(&entry->WriteCountDelta);
PhInitializeDelta(&entry->QueryTimeDelta);
entry->ResponseTime = 0;
entry->ActiveTime = 0.0f;
entry->QueueDepth = 0;
entry->SplitCount = 0;
entry->DiskIndex = ULONG_MAX;
entry->DevicePresent = FALSE;
PhClearReference(&entry->DiskIndexName);
}
if (runCount > 1)
{
// Delay the first query for the disk name, index and type.
// 1) This information is not needed until the user opens the sysinfo window.
// 2) Try not to query this information while opening the sysinfo window (e.g. delay).
// 3) Try not to query this information during startup (e.g. delay).
//
// Note: If the user opens the Sysinfo window before we query the disk info,
// we have a second check in diskgraph.c that queries the information on demand.
DiskDriveUpdateDeviceInfo(deviceHandle, entry);
}
NtClose(deviceHandle);
}
else
{
// Disk has been disconnected or dismounted.
PhInitializeDelta(&entry->BytesReadDelta);
PhInitializeDelta(&entry->BytesWrittenDelta);
PhInitializeDelta(&entry->ReadTimeDelta);
PhInitializeDelta(&entry->WriteTimeDelta);
PhInitializeDelta(&entry->IdleTimeDelta);
PhInitializeDelta(&entry->ReadCountDelta);
PhInitializeDelta(&entry->WriteCountDelta);
PhInitializeDelta(&entry->QueryTimeDelta);
entry->ResponseTime = 0;
entry->ActiveTime = 0.0f;
entry->QueueDepth = 0;
entry->SplitCount = 0;
entry->DiskIndex = ULONG_MAX;
entry->DevicePresent = FALSE;
PhClearReference(&entry->DiskIndexName);
}
if (!entry->HaveFirstSample)
{
// The first sample must be zero.
entry->BytesReadDelta.Delta = 0;
entry->BytesWrittenDelta.Delta = 0;
entry->HaveFirstSample = TRUE;
}
if (runCount != 0)
{
PhAddItemCircularBuffer_ULONG64(&entry->ReadBuffer, entry->BytesReadDelta.Delta);
PhAddItemCircularBuffer_ULONG64(&entry->WriteBuffer, entry->BytesWrittenDelta.Delta);
}
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
runCount++;
}
VOID DiskDriveUpdateDeviceInfo(
_In_opt_ HANDLE DeviceHandle,
_In_ PDV_DISK_ENTRY DiskEntry
)
{
if (!DiskEntry->DiskName || DiskEntry->DiskIndex == ULONG_MAX)
{
HANDLE deviceHandle = NULL;
if (!DeviceHandle)
{
DiskDriveCreateHandle(&deviceHandle, DiskEntry->Id.DevicePath);
}
else
{
deviceHandle = DeviceHandle;
}
if (deviceHandle)
{
if (!DiskEntry->DiskName)
{
PPH_STRING diskName = NULL;
if (NT_SUCCESS(DiskDriveQueryDeviceInformation(deviceHandle, NULL, &diskName, NULL, NULL)))
{
DiskEntry->DiskName = diskName;
}
}
if (DiskEntry->DiskIndex == ULONG_MAX)
{
ULONG diskIndex = ULONG_MAX; // Note: Do not initialize to zero.
if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber(deviceHandle, &diskIndex, NULL)))
{
DiskEntry->DiskIndex = diskIndex;
}
}
if (!DeviceHandle)
{
NtClose(deviceHandle);
}
}
}
}
VOID InitializeDiskId(
_Out_ PDV_DISK_ID Id,
_In_ PPH_STRING DevicePath
)
{
PhSetReference(&Id->DevicePath, DevicePath);
}
VOID CopyDiskId(
_Out_ PDV_DISK_ID Destination,
_In_ PDV_DISK_ID Source
)
{
InitializeDiskId(
Destination,
Source->DevicePath
);
}
VOID DeleteDiskId(
_Inout_ PDV_DISK_ID Id
)
{
PhClearReference(&Id->DevicePath);
}
BOOLEAN EquivalentDiskId(
_In_ PDV_DISK_ID Id1,
_In_ PDV_DISK_ID Id2
)
{
return PhEqualString(Id1->DevicePath, Id2->DevicePath, TRUE);
}
PDV_DISK_ENTRY CreateDiskEntry(
_In_ PDV_DISK_ID Id
)
{
PDV_DISK_ENTRY entry;
entry = PhCreateObject(sizeof(DV_DISK_ENTRY), DiskDriveEntryType);
memset(entry, 0, sizeof(DV_DISK_ENTRY));
entry->DiskIndex = ULONG_MAX;
CopyDiskId(&entry->Id, Id);
PhInitializeCircularBuffer_ULONG64(&entry->ReadBuffer, PhGetIntegerSetting(L"SampleCount"));
PhInitializeCircularBuffer_ULONG64(&entry->WriteBuffer, PhGetIntegerSetting(L"SampleCount"));
PhAcquireQueuedLockExclusive(&DiskDrivesListLock);
PhAddItemList(DiskDrivesList, entry);
PhReleaseQueuedLockExclusive(&DiskDrivesListLock);
AddRemoveDeviceChangeCallback();
return entry;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,504 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
VOID DiskDriveUpdateGraphs(
_Inout_ PDV_DISK_SYSINFO_CONTEXT Context
)
{
Context->GraphState.Valid = FALSE;
Context->GraphState.TooltipIndex = -1;
Graph_MoveGrid(Context->GraphHandle, 1);
Graph_Draw(Context->GraphHandle);
Graph_UpdateTooltip(Context->GraphHandle);
InvalidateRect(Context->GraphHandle, NULL, FALSE);
}
VOID DiskDriveUpdatePanel(
_Inout_ PDV_DISK_SYSINFO_CONTEXT Context
)
{
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BREAD, PhaFormatSize(Context->DiskEntry->BytesReadDelta.Value, -1)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BWRITE, PhaFormatSize(Context->DiskEntry->BytesWrittenDelta.Value, -1)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BTOTAL, PhaFormatSize(Context->DiskEntry->BytesReadDelta.Value + Context->DiskEntry->BytesWrittenDelta.Value, -1)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_ACTIVE,
PhaFormatString(L"%.0f%%", Context->DiskEntry->ActiveTime)->Buffer
);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_RESPONSETIME,
PhaFormatString(L"%.1f ms", Context->DiskEntry->ResponseTime / PH_TICKS_PER_MS)->Buffer
);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_QUEUELENGTH,
PhaFormatString(L"%lu", Context->DiskEntry->QueueDepth)->Buffer
);
}
VOID UpdateDiskDriveDialog(
_Inout_ PDV_DISK_SYSINFO_CONTEXT Context
)
{
if (Context->DiskEntry->DiskName)
SetDlgItemText(Context->WindowHandle, IDC_DISKNAME, Context->DiskEntry->DiskName->Buffer);
else
SetDlgItemText(Context->WindowHandle, IDC_DISKNAME, L"Unknown disk");
if (Context->DiskEntry->DiskIndexName)
SetDlgItemText(Context->WindowHandle, IDC_DISKMOUNTPATH, Context->DiskEntry->DiskIndexName->Buffer);
else
SetDlgItemText(Context->WindowHandle, IDC_DISKMOUNTPATH, L"Unknown disk");
DiskDriveUpdateGraphs(Context);
DiskDriveUpdatePanel(Context);
}
VOID UpdateDiskIndexText(
_Inout_ PDV_DISK_SYSINFO_CONTEXT Context
)
{
// If our delayed lookup of the disk name, index and type hasn't fired then query the information now.
DiskDriveUpdateDeviceInfo(NULL, Context->DiskEntry);
// TODO: Move into DiskDriveUpdateDeviceInfo.
if (Context->DiskEntry->DiskIndex != ULONG_MAX && !Context->DiskEntry->DiskIndexName)
{
// Query the disk DosDevices mount points.
PPH_STRING diskMountPoints = PH_AUTO_T(PH_STRING, DiskDriveQueryDosMountPoints(Context->DiskEntry->DiskIndex));
if (!PhIsNullOrEmptyString(diskMountPoints))
{
PhMoveReference(&Context->DiskEntry->DiskIndexName, PhFormatString(
L"Disk %lu (%s)",
Context->DiskEntry->DiskIndex,
diskMountPoints->Buffer
));
}
else
{
PhMoveReference(&Context->DiskEntry->DiskIndexName, PhFormatString(
L"Disk %lu",
Context->DiskEntry->DiskIndex
));
}
}
}
INT_PTR CALLBACK DiskDrivePanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_DISK_SYSINFO_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_DISK_SYSINFO_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_DISK_SYSINFO_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_NCDESTROY)
{
RemoveProp(hwndDlg, L"Context");
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_DETAILS:
ShowDiskDriveDetailsDialog(context);
break;
}
}
break;
}
return FALSE;
}
INT_PTR CALLBACK DiskDriveDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_DISK_SYSINFO_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_DISK_SYSINFO_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_DISK_SYSINFO_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
PhDeleteLayoutManager(&context->LayoutManager);
PhDeleteGraphState(&context->GraphState);
if (context->GraphHandle)
DestroyWindow(context->GraphHandle);
if (context->PanelWindowHandle)
DestroyWindow(context->PanelWindowHandle);
RemoveProp(hwndDlg, L"Context");
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PPH_LAYOUT_ITEM graphItem;
PPH_LAYOUT_ITEM panelItem;
context->WindowHandle = hwndDlg;
PhInitializeGraphState(&context->GraphState);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_DISKMOUNTPATH), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_DISKNAME), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_TOP | PH_LAYOUT_FORCE_INVALIDATE);
graphItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
panelItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
SendMessage(GetDlgItem(hwndDlg, IDC_DISKMOUNTPATH), WM_SETFONT, (WPARAM)context->SysinfoSection->Parameters->LargeFont, FALSE);
SendMessage(GetDlgItem(hwndDlg, IDC_DISKNAME), WM_SETFONT, (WPARAM)context->SysinfoSection->Parameters->MediumFont, FALSE);
if (context->DiskEntry->DiskIndexName)
SetDlgItemText(hwndDlg, IDC_DISKMOUNTPATH, context->DiskEntry->DiskIndexName->Buffer);
else
SetDlgItemText(hwndDlg, IDC_DISKMOUNTPATH, L"Unknown disk");
if (context->DiskEntry->DiskName)
SetDlgItemText(hwndDlg, IDC_DISKNAME, context->DiskEntry->DiskName->Buffer);
else
SetDlgItemText(hwndDlg, IDC_DISKNAME, L"Unknown disk");
context->PanelWindowHandle = CreateDialogParam(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_DISKDRIVE_PANEL), hwndDlg, DiskDrivePanelDialogProc, (LPARAM)context);
ShowWindow(context->PanelWindowHandle, SW_SHOW);
PhAddLayoutItemEx(&context->LayoutManager, context->PanelWindowHandle, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
// Create the graph control.
context->GraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
hwndDlg,
NULL,
NULL,
NULL
);
Graph_SetTooltip(context->GraphHandle, TRUE);
PhAddLayoutItemEx(&context->LayoutManager, context->GraphHandle, NULL, PH_ANCHOR_ALL, graphItem->Margin);
UpdateDiskDriveDialog(context);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_NOTIFY:
{
NMHDR* header = (NMHDR*)lParam;
if (header->hwndFrom == context->GraphHandle)
{
switch (header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2;
context->SysinfoSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
PhGraphStateGetDrawInfo(
&context->GraphState,
getDrawInfo,
context->DiskEntry->ReadBuffer.Count
);
if (!context->GraphState.Valid)
{
FLOAT max = 1024 * 1024; // minimum scaling of 1 MB.
for (ULONG i = 0; i < drawInfo->LineDataCount; i++)
{
FLOAT data1;
FLOAT data2;
context->GraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskEntry->ReadBuffer, i);
context->GraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskEntry->WriteBuffer, i);
if (max < data1 + data2)
max = data1 + data2;
}
if (max != 0)
{
// Scale the data.
PhDivideSinglesBySingle(
context->GraphState.Data1,
max,
drawInfo->LineDataCount
);
// Scale the data.
PhDivideSinglesBySingle(
context->GraphState.Data2,
max,
drawInfo->LineDataCount
);
}
drawInfo->LabelYFunction = PhSiSizeLabelYFunction;
drawInfo->LabelYFunctionParameter = max;
context->GraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (context->GraphState.TooltipIndex != getTooltipText->Index)
{
ULONG64 diskReadValue = PhGetItemCircularBuffer_ULONG64(
&context->DiskEntry->ReadBuffer,
getTooltipText->Index
);
ULONG64 diskWriteValue = PhGetItemCircularBuffer_ULONG64(
&context->DiskEntry->WriteBuffer,
getTooltipText->Index
);
PhMoveReference(&context->GraphState.TooltipText, PhFormatString(
L"R: %s\nW: %s\n%s",
PhaFormatSize(diskReadValue, -1)->Buffer,
PhaFormatSize(diskWriteValue, -1)->Buffer,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = context->GraphState.TooltipText->sr;
}
}
break;
}
}
}
break;
case UPDATE_MSG:
{
UpdateDiskDriveDialog(context);
}
break;
}
return FALSE;
}
BOOLEAN DiskDriveSectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
)
{
PDV_DISK_SYSINFO_CONTEXT context = (PDV_DISK_SYSINFO_CONTEXT)Section->Context;
switch (Message)
{
case SysInfoCreate:
{
UpdateDiskIndexText(context);
}
return TRUE;
case SysInfoDestroy:
{
PhDereferenceObject(context->DiskEntry);
PhDereferenceObject(context->SectionName);
PhFree(context);
}
return TRUE;
case SysInfoTick:
{
UpdateDiskIndexText(context);
if (context->WindowHandle)
PostMessage(context->WindowHandle, UPDATE_MSG, 0, 0);
}
return TRUE;
case SysInfoCreateDialog:
{
PPH_SYSINFO_CREATE_DIALOG createDialog = (PPH_SYSINFO_CREATE_DIALOG)Parameter1;
createDialog->Instance = PluginInstance->DllBase;
createDialog->Template = MAKEINTRESOURCE(IDD_DISKDRIVE_DIALOG);
createDialog->DialogProc = DiskDriveDialogProc;
createDialog->Parameter = context;
}
return TRUE;
case SysInfoGraphGetDrawInfo:
{
PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)Parameter1;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, context->DiskEntry->ReadBuffer.Count);
if (!Section->GraphState.Valid)
{
FLOAT max = 1024 * 1024; // minimum scaling of 1 MB.
for (ULONG i = 0; i < drawInfo->LineDataCount; i++)
{
FLOAT data1;
FLOAT data2;
Section->GraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskEntry->ReadBuffer, i);
Section->GraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskEntry->WriteBuffer, i);
if (max < data1 + data2)
max = data1 + data2;
}
if (max != 0)
{
// Scale the data.
PhDivideSinglesBySingle(
Section->GraphState.Data1,
max,
drawInfo->LineDataCount
);
// Scale the data.
PhDivideSinglesBySingle(
Section->GraphState.Data2,
max,
drawInfo->LineDataCount
);
}
drawInfo->LabelYFunction = PhSiSizeLabelYFunction;
drawInfo->LabelYFunctionParameter = max;
Section->GraphState.Valid = TRUE;
}
}
return TRUE;
case SysInfoGraphGetTooltipText:
{
PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = (PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT)Parameter1;
ULONG64 diskReadValue = PhGetItemCircularBuffer_ULONG64(
&context->DiskEntry->ReadBuffer,
getTooltipText->Index
);
ULONG64 diskWriteValue = PhGetItemCircularBuffer_ULONG64(
&context->DiskEntry->WriteBuffer,
getTooltipText->Index
);
PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
L"R: %s\nW: %s\n%s",
PhaFormatSize(diskReadValue, -1)->Buffer,
PhaFormatSize(diskWriteValue, -1)->Buffer,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
getTooltipText->Text = Section->GraphState.TooltipText->sr;
}
return TRUE;
case SysInfoGraphDrawPanel:
{
PPH_SYSINFO_DRAW_PANEL drawPanel = (PPH_SYSINFO_DRAW_PANEL)Parameter1;
PhSetReference(&drawPanel->Title, context->DiskEntry->DiskIndexName);
drawPanel->SubTitle = PhFormatString(
L"R: %s\nW: %s",
PhaFormatSize(context->DiskEntry->BytesReadDelta.Delta, -1)->Buffer,
PhaFormatSize(context->DiskEntry->BytesWrittenDelta.Delta, -1)->Buffer
);
if (!drawPanel->Title)
drawPanel->Title = PhCreateString(L"Unknown disk");
}
return TRUE;
}
return FALSE;
}
VOID DiskDriveSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers,
_In_ _Assume_refs_(1) PDV_DISK_ENTRY DiskEntry
)
{
PH_SYSINFO_SECTION section;
PDV_DISK_SYSINFO_CONTEXT context;
context = (PDV_DISK_SYSINFO_CONTEXT)PhAllocate(sizeof(DV_DISK_SYSINFO_CONTEXT));
memset(context, 0, sizeof(DV_DISK_SYSINFO_CONTEXT));
memset(&section, 0, sizeof(PH_SYSINFO_SECTION));
context->DiskEntry = DiskEntry;
context->SectionName = PhConcatStrings2(L"Disk ", DiskEntry->Id.DevicePath->Buffer);
section.Context = context;
section.Callback = DiskDriveSectionCallback;
section.Name = context->SectionName->sr;
context->SysinfoSection = Pointers->CreateSection(&section);
}

View File

@@ -0,0 +1,119 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
#include <Dbt.h>
static BOOLEAN SubclassActive = FALSE;
LRESULT CALLBACK MainWndDevicesSubclassProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ ULONG_PTR dwRefData
)
{
// Subclassing the main window just to process drive letter notifications
// is bad and I don't know of any other way to achieve this.
// The IOCTL_MOUNTMGR_CHANGE_NOTIFY callback would have been preferred but
// doesn't work from non-elevated processes.
switch (uMsg)
{
case WM_DEVICECHANGE:
{
switch (wParam)
{
case DBT_DEVICEARRIVAL: // Drive letter added
case DBT_DEVICEREMOVECOMPLETE: // Drive letter removed
{
DEV_BROADCAST_HDR* deviceBroadcast = (DEV_BROADCAST_HDR*)lParam;
if (deviceBroadcast->dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME deviceVolume = (PDEV_BROADCAST_VOLUME)deviceBroadcast;
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
PDV_DISK_ENTRY entry;
entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
// Reset the DiskIndex so we can re-query the index on the next interval update.
entry->DiskIndex = ULONG_MAX;
// Reset the DiskIndexName so we can re-query the name on the next interval update.
PhClearReference(&entry->DiskIndexName);
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
}
}
}
goto DefaultWndProc;
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
DefaultWndProc:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
VOID AddRemoveDeviceChangeCallback(
VOID
)
{
// We get called during the plugin LoadCallback, don't do anything.
if (!PhMainWndHandle)
return;
// Add the subclass only when disks are being monitored, remove when no longer needed.
if (DiskDrivesList->Count != 0)
{
if (!SubclassActive)
{
// We have a disk device, subclass the main window to detect drive letter changes.
SetWindowSubclass(PhMainWndHandle, MainWndDevicesSubclassProc, 0, 0);
SubclassActive = TRUE;
}
}
else
{
if (SubclassActive)
{
// The user has removed the last disk device, remove the subclass.
RemoveWindowSubclass(PhMainWndHandle, MainWndDevicesSubclassProc, 0);
SubclassActive = FALSE;
}
}
}

View File

@@ -0,0 +1,695 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
#include <Setupapi.h>
#define ITEM_CHECKED (INDEXTOSTATEIMAGEMASK(2))
#define ITEM_UNCHECKED (INDEXTOSTATEIMAGEMASK(1))
typedef struct _DISK_ENUM_ENTRY
{
ULONG DeviceIndex;
BOOLEAN DevicePresent;
PPH_STRING DevicePath;
PPH_STRING DeviceName;
PPH_STRING DeviceMountPoints;
} DISK_ENUM_ENTRY, *PDISK_ENUM_ENTRY;
static int __cdecl DiskEntryCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
)
{
PDISK_ENUM_ENTRY entry1 = *(PDISK_ENUM_ENTRY *)elem1;
PDISK_ENUM_ENTRY entry2 = *(PDISK_ENUM_ENTRY *)elem2;
return uint64cmp(entry1->DeviceIndex, entry2->DeviceIndex);
}
VOID DiskDrivesLoadList(
VOID
)
{
PPH_STRING settingsString;
PH_STRINGREF remaining;
settingsString = PhaGetStringSetting(SETTING_NAME_DISK_LIST);
remaining = settingsString->sr;
while (remaining.Length != 0)
{
PH_STRINGREF part;
DV_DISK_ID id;
PDV_DISK_ENTRY entry;
if (remaining.Length == 0)
break;
PhSplitStringRefAtChar(&remaining, ',', &part, &remaining);
InitializeDiskId(&id, PhCreateString2(&part));
entry = CreateDiskEntry(&id);
DeleteDiskId(&id);
entry->UserReference = TRUE;
}
}
VOID DiskDrivesSaveList(
VOID
)
{
PH_STRING_BUILDER stringBuilder;
PPH_STRING settingsString;
PhInitializeStringBuilder(&stringBuilder, 260);
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
PDV_DISK_ENTRY entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
if (entry->UserReference)
{
PhAppendFormatStringBuilder(
&stringBuilder,
L"%s,",
entry->Id.DevicePath->Buffer // This value is SAFE and does not change.
);
}
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
if (stringBuilder.String->Length != 0)
PhRemoveEndStringBuilder(&stringBuilder, 1);
settingsString = PH_AUTO(PhFinalStringBuilderString(&stringBuilder));
PhSetStringSetting2(SETTING_NAME_DISK_LIST, &settingsString->sr);
}
BOOLEAN FindDiskEntry(
_In_ PDV_DISK_ID Id,
_In_ BOOLEAN RemoveUserReference
)
{
BOOLEAN found = FALSE;
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
PDV_DISK_ENTRY currentEntry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!currentEntry)
continue;
found = EquivalentDiskId(&currentEntry->Id, Id);
if (found)
{
if (RemoveUserReference)
{
if (currentEntry->UserReference)
{
PhDereferenceObjectDeferDelete(currentEntry);
currentEntry->UserReference = FALSE;
}
}
PhDereferenceObjectDeferDelete(currentEntry);
break;
}
else
{
PhDereferenceObjectDeferDelete(currentEntry);
}
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
return found;
}
VOID AddDiskDriveToListView(
_In_ PDV_DISK_OPTIONS_CONTEXT Context,
_In_ BOOLEAN DiskPresent,
_In_ PPH_STRING DiskPath,
_In_ PPH_STRING DiskName
)
{
DV_DISK_ID adapterId;
INT lvItemIndex;
BOOLEAN found = FALSE;
PDV_DISK_ID newId = NULL;
InitializeDiskId(&adapterId, DiskPath);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
PDV_DISK_ENTRY entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
if (EquivalentDiskId(&entry->Id, &adapterId))
{
newId = PhAllocate(sizeof(DV_DISK_ID));
CopyDiskId(newId, &entry->Id);
if (entry->UserReference)
found = TRUE;
}
PhDereferenceObjectDeferDelete(entry);
if (newId)
break;
}
if (!newId)
{
newId = PhAllocate(sizeof(DV_DISK_ID));
CopyDiskId(newId, &adapterId);
PhMoveReference(&newId->DevicePath, DiskPath);
}
lvItemIndex = AddListViewItemGroupId(
Context->ListViewHandle,
DiskPresent ? 0 : 1,
MAXINT,
DiskName->Buffer,
newId
);
if (found)
ListView_SetItemState(Context->ListViewHandle, lvItemIndex, ITEM_CHECKED, LVIS_STATEIMAGEMASK);
DeleteDiskId(&adapterId);
}
VOID FreeListViewDiskDriveEntries(
_In_ PDV_DISK_OPTIONS_CONTEXT Context
)
{
ULONG index = -1;
while ((index = PhFindListViewItemByFlags(
Context->ListViewHandle,
index,
LVNI_ALL
)) != -1)
{
PDV_DISK_ID param;
if (PhGetListViewItemParam(Context->ListViewHandle, index, &param))
{
DeleteDiskId(param);
PhFree(param);
}
}
}
VOID FindDiskDrives(
_In_ PDV_DISK_OPTIONS_CONTEXT Context
)
{
PPH_LIST deviceList;
HDEVINFO deviceInfoHandle;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail;
ULONG deviceInfoLength = 0;
if ((deviceInfoHandle = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_DISK,
NULL,
NULL,
DIGCF_DEVICEINTERFACE
)) == INVALID_HANDLE_VALUE)
{
return;
}
deviceList = PH_AUTO(PhCreateList(1));
for (ULONG i = 0; SetupDiEnumDeviceInterfaces(deviceInfoHandle, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++)
{
if (SetupDiGetDeviceInterfaceDetail(
deviceInfoHandle,
&deviceInterfaceData,
0,
0,
&deviceInfoLength,
&deviceInfoData
) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
continue;
}
deviceInterfaceDetail = PhAllocate(deviceInfoLength);
deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(
deviceInfoHandle,
&deviceInterfaceData,
deviceInterfaceDetail,
deviceInfoLength,
&deviceInfoLength,
&deviceInfoData
))
{
HANDLE deviceHandle;
PDISK_ENUM_ENTRY diskEntry;
WCHAR diskFriendlyName[MAX_PATH] = L"";
// This crashes on XP with error 0xC06D007F
//SetupDiGetDeviceProperty(
// deviceInfoHandle,
// &deviceInfoData,
// &DEVPKEY_Device_FriendlyName,
// &devicePropertyType,
// (PBYTE)diskFriendlyName,
// ARRAYSIZE(diskFriendlyName),
// NULL,
// 0
// );
if (!SetupDiGetDeviceRegistryProperty(
deviceInfoHandle,
&deviceInfoData,
SPDRP_FRIENDLYNAME,
NULL,
(PBYTE)diskFriendlyName,
ARRAYSIZE(diskFriendlyName),
NULL
))
{
continue;
}
diskEntry = PhAllocate(sizeof(DISK_ENUM_ENTRY));
memset(diskEntry, 0, sizeof(DISK_ENUM_ENTRY));
diskEntry->DeviceIndex = ULONG_MAX; // Note: Do not initialize to zero.
diskEntry->DeviceName = PhCreateString(diskFriendlyName);
diskEntry->DevicePath = PhCreateString(deviceInterfaceDetail->DevicePath);
if (NT_SUCCESS(DiskDriveCreateHandle(
&deviceHandle,
diskEntry->DevicePath
)))
{
ULONG diskIndex = ULONG_MAX; // Note: Do not initialize to zero
if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber(
deviceHandle,
&diskIndex,
NULL
)))
{
PPH_STRING diskMountPoints = PH_AUTO_T(PH_STRING, DiskDriveQueryDosMountPoints(diskIndex));
diskEntry->DeviceIndex = diskIndex;
diskEntry->DevicePresent = TRUE;
if (!PhIsNullOrEmptyString(diskMountPoints))
{
diskEntry->DeviceMountPoints = PhFormatString(
L"Disk %lu (%s) [%s]",
diskIndex,
diskMountPoints->Buffer,
diskFriendlyName
);
}
else
{
diskEntry->DeviceMountPoints = PhFormatString(
L"Disk %lu [%s]",
diskIndex,
diskFriendlyName
);
}
}
NtClose(deviceHandle);
}
PhAddItemList(deviceList, diskEntry);
}
PhFree(deviceInterfaceDetail);
}
SetupDiDestroyDeviceInfoList(deviceInfoHandle);
// Sort the entries
qsort(deviceList->Items, deviceList->Count, sizeof(PVOID), DiskEntryCompareFunction);
Context->EnumeratingDisks = TRUE;
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < deviceList->Count; i++)
{
PDISK_ENUM_ENTRY entry = deviceList->Items[i];
AddDiskDriveToListView(
Context,
entry->DevicePresent,
entry->DevicePath,
entry->DeviceMountPoints ? entry->DeviceMountPoints : entry->DeviceName
);
if (entry->DeviceMountPoints)
PhDereferenceObject(entry->DeviceMountPoints);
if (entry->DeviceName)
PhDereferenceObject(entry->DeviceName);
// Note: DevicePath is disposed by WM_DESTROY.
PhFree(entry);
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
Context->EnumeratingDisks = FALSE;
// HACK: Show all unknown devices.
Context->EnumeratingDisks = TRUE;
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
ULONG index = -1;
BOOLEAN found = FALSE;
PDV_DISK_ENTRY entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
while ((index = PhFindListViewItemByFlags(
Context->ListViewHandle,
index,
LVNI_ALL
)) != -1)
{
PDV_DISK_ID param;
if (PhGetListViewItemParam(Context->ListViewHandle, index, &param))
{
if (EquivalentDiskId(param, &entry->Id))
{
found = TRUE;
}
}
}
if (!found)
{
PPH_STRING description;
if (description = PhCreateString(L"Unknown disk"))
{
AddDiskDriveToListView(
Context,
FALSE,
entry->Id.DevicePath,
description
);
PhDereferenceObject(description);
}
}
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
Context->EnumeratingDisks = FALSE;
}
PPH_STRING FindDiskDeviceInstance(
_In_ PPH_STRING DevicePath
)
{
PPH_STRING deviceIdString = NULL;
HDEVINFO deviceInfoHandle;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail;
ULONG deviceInfoLength = 0;
if ((deviceInfoHandle = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_DISK,
NULL,
NULL,
DIGCF_DEVICEINTERFACE
)) == INVALID_HANDLE_VALUE)
{
return NULL;
}
for (ULONG i = 0; SetupDiEnumDeviceInterfaces(deviceInfoHandle, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++)
{
if (SetupDiGetDeviceInterfaceDetail(
deviceInfoHandle,
&deviceInterfaceData,
0,
0,
&deviceInfoLength,
&deviceInfoData
) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
continue;
}
deviceInterfaceDetail = PhAllocate(deviceInfoLength);
deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(
deviceInfoHandle,
&deviceInterfaceData,
deviceInterfaceDetail,
deviceInfoLength,
&deviceInfoLength,
&deviceInfoData
))
{
if (PhEqualStringZ(deviceInterfaceDetail->DevicePath, DevicePath->Buffer, TRUE))
{
deviceIdString = PhCreateStringEx(NULL, 0x100);
SetupDiGetDeviceInstanceId(
deviceInfoHandle,
&deviceInfoData,
deviceIdString->Buffer,
(ULONG)deviceIdString->Length,
NULL
);
PhTrimToNullTerminatorString(deviceIdString);
}
}
PhFree(deviceInterfaceDetail);
}
SetupDiDestroyDeviceInfoList(deviceInfoHandle);
return deviceIdString;
}
//VOID LoadDiskDriveImages(
// _In_ PDV_DISK_OPTIONS_CONTEXT Context
// )
//{
// HICON smallIcon = NULL;
//
// Context->ImageList = ImageList_Create(
// GetSystemMetrics(SM_CXSMICON),
// GetSystemMetrics(SM_CYSMICON),
// ILC_COLOR32,
// 1,
// 1
// );
//
// // We could use SetupDiLoadClassIcon but this works.
// // Copied from HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318}\\IconPath
// // The index is only valid on Vista and above.
// ExtractIconEx(
// L"%SystemRoot%\\system32\\imageres.dll",
// -32,
// NULL,
// &smallIcon,
// 1
// );
//
// if (smallIcon)
// {
// ImageList_AddIcon(Context->ImageList, smallIcon);
// DestroyIcon(smallIcon);
//
// // Set the imagelist only if the image was loaded.
// ListView_SetImageList(
// Context->ListViewHandle,
// Context->ImageList,
// LVSIL_SMALL
// );
// }
//}
INT_PTR CALLBACK DiskDriveOptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_DISK_OPTIONS_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_DISK_OPTIONS_CONTEXT)PhAllocate(sizeof(DV_DISK_OPTIONS_CONTEXT));
memset(context, 0, sizeof(DV_DISK_OPTIONS_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_DISK_OPTIONS_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
if (context->OptionsChanged)
DiskDrivesSaveList();
FreeListViewDiskDriveEntries(context);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
// Center the property sheet.
PhCenterWindow(GetParent(hwndDlg), GetParent(GetParent(hwndDlg)));
// Hide the OK button.
ShowWindow(GetDlgItem(GetParent(hwndDlg), IDOK), SW_HIDE);
// Set the Cancel button text.
Button_SetText(GetDlgItem(GetParent(hwndDlg), IDCANCEL), L"Close");
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_DISKDRIVE_LISTVIEW);
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
ListView_SetExtendedListViewStyleEx(context->ListViewHandle, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
PhSetControlTheme(context->ListViewHandle, L"explorer");
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 350, L"Disk Drives");
PhSetExtendedListView(context->ListViewHandle);
if (WindowsVersion >= WINDOWS_VISTA)
{
ListView_EnableGroupView(context->ListViewHandle, TRUE);
AddListViewGroup(context->ListViewHandle, 0, L"Connected");
AddListViewGroup(context->ListViewHandle, 1, L"Disconnected");
}
FindDiskDrives(context);
context->OptionsChanged = FALSE;
EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
if (header->code == LVN_ITEMCHANGED)
{
LPNM_LISTVIEW listView = (LPNM_LISTVIEW)lParam;
if (context->EnumeratingDisks)
break;
if (listView->uChanged & LVIF_STATE)
{
switch (listView->uNewState & LVIS_STATEIMAGEMASK)
{
case 0x2000: // checked
{
PDV_DISK_ID param = (PDV_DISK_ID)listView->lParam;
if (!FindDiskEntry(param, FALSE))
{
PDV_DISK_ENTRY entry;
entry = CreateDiskEntry(param);
entry->UserReference = TRUE;
}
context->OptionsChanged = TRUE;
}
break;
case 0x1000: // unchecked
{
PDV_DISK_ID param = (PDV_DISK_ID)listView->lParam;
FindDiskEntry(param, TRUE);
context->OptionsChanged = TRUE;
}
break;
}
}
}
else if (header->code == NM_RCLICK)
{
PDV_DISK_ID param;
PPH_STRING deviceInstance;
if (param = PhGetSelectedListViewItemParam(context->ListViewHandle))
{
if (deviceInstance = FindDiskDeviceInstance(param->DevicePath))
{
ShowDeviceMenu(hwndDlg, deviceInstance);
PhDereferenceObject(deviceInstance);
}
}
}
}
break;
}
return FALSE;
}

View File

@@ -0,0 +1,793 @@
/*
* Process Hacker Extra Plugins -
* Nvidia GPU Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
#ifdef _NV_GPU_BUILD
#define ET_GPU_PADDING 3
static RECT NormalGraphTextMargin = { 5, 5, 5, 5 };
static RECT NormalGraphTextPadding = { 3, 3, 3, 3 };
static PPH_STRING GpuName;
static HWND WindowHandle;
static HWND DetailsHandle;
static PPH_SYSINFO_SECTION Section;
static PH_LAYOUT_MANAGER LayoutManager;
static RECT GpuGraphMargin;
static HWND GpuPanel;
static HWND GpuLabelHandle;
static HWND MemLabelHandle;
static HWND SharedLabelHandle;
static HWND BusLabelHandle;
static HWND GpuGraphHandle;
static HWND MemGraphHandle;
static HWND SharedGraphHandle;
static HWND BusGraphHandle;
static PH_GRAPH_STATE GpuGraphState;
static PH_GRAPH_STATE MemGraphState;
static PH_GRAPH_STATE SharedGraphState;
static PH_GRAPH_STATE BusGraphState;
PH_CIRCULAR_BUFFER_FLOAT GpuUtilizationHistory;
PH_CIRCULAR_BUFFER_ULONG GpuMemoryHistory;
PH_CIRCULAR_BUFFER_FLOAT GpuBoardHistory;
PH_CIRCULAR_BUFFER_FLOAT GpuBusHistory;
INT_PTR CALLBACK NvGpuPanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
return FALSE;
}
VOID NvGpuCreateGraphs(
VOID
)
{
GpuGraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
WindowHandle,
NULL,
NULL,
NULL
);
Graph_SetTooltip(GpuGraphHandle, TRUE);
MemGraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
WindowHandle,
NULL,
NULL,
NULL
);
Graph_SetTooltip(MemGraphHandle, TRUE);
SharedGraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
WindowHandle,
NULL,
NULL,
NULL
);
Graph_SetTooltip(SharedGraphHandle, TRUE);
BusGraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
WindowHandle,
NULL,
NULL,
NULL
);
Graph_SetTooltip(BusGraphHandle, TRUE);
}
VOID NvGpuLayoutGraphs(
VOID
)
{
RECT clientRect;
RECT labelRect;
ULONG graphWidth;
ULONG graphHeight;
HDWP deferHandle;
ULONG y;
PhLayoutManagerLayout(&LayoutManager);
GetClientRect(WindowHandle, &clientRect);
GetClientRect(GpuLabelHandle, &labelRect);
graphWidth = clientRect.right - GpuGraphMargin.left - GpuGraphMargin.right;
graphHeight = (clientRect.bottom - GpuGraphMargin.top - GpuGraphMargin.bottom - labelRect.bottom * 4 - ET_GPU_PADDING * 5) / 4;
deferHandle = BeginDeferWindowPos(8);
y = GpuGraphMargin.top;
deferHandle = DeferWindowPos(
deferHandle,
GpuLabelHandle,
NULL,
GpuGraphMargin.left,
y,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
);
y += labelRect.bottom + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
GpuGraphHandle,
NULL,
GpuGraphMargin.left,
y,
graphWidth,
graphHeight,
SWP_NOACTIVATE | SWP_NOZORDER
);
y += graphHeight + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
MemLabelHandle,
NULL,
GpuGraphMargin.left,
y,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
);
y += labelRect.bottom + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
MemGraphHandle,
NULL,
GpuGraphMargin.left,
y,
graphWidth,
graphHeight,
SWP_NOACTIVATE | SWP_NOZORDER
);
y += graphHeight + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
SharedLabelHandle,
NULL,
GpuGraphMargin.left,
y,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
);
y += labelRect.bottom + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
SharedGraphHandle,
NULL,
GpuGraphMargin.left,
y,
graphWidth,
graphHeight,
SWP_NOACTIVATE | SWP_NOZORDER
);
y += graphHeight + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
BusLabelHandle,
NULL,
GpuGraphMargin.left,
y,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER
);
y += labelRect.bottom + ET_GPU_PADDING;
deferHandle = DeferWindowPos(
deferHandle,
BusGraphHandle,
NULL,
GpuGraphMargin.left,
y,
graphWidth,
clientRect.bottom - GpuGraphMargin.bottom - y,
SWP_NOACTIVATE | SWP_NOZORDER
);
EndDeferWindowPos(deferHandle);
}
VOID NvGpuNotifyUsageGraph(
_In_ NMHDR *Header
)
{
switch (Header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
PhGraphStateGetDrawInfo(&GpuGraphState, getDrawInfo, GpuUtilizationHistory.Count);
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(GpuGraphHandle);
PhMoveReference(&GpuGraphState.Text,
PhFormatString(L"%.0f%%", GpuCurrentGpuUsage * 100)
);
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &GpuGraphState.Text->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
if (!GpuGraphState.Valid)
{
PhCopyCircularBuffer_FLOAT(&GpuUtilizationHistory, GpuGraphState.Data1, drawInfo->LineDataCount);
GpuGraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (GpuGraphState.TooltipIndex != getTooltipText->Index)
{
FLOAT gpuUsageValue;
gpuUsageValue = PhGetItemCircularBuffer_FLOAT(&GpuUtilizationHistory, getTooltipText->Index);
PhMoveReference(&GpuGraphState.TooltipText, PhFormatString(
L"%.0f%%\n%s",
gpuUsageValue * 100,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = GpuGraphState.TooltipText->sr;
}
}
break;
}
}
VOID NvGpuNotifyMemoryGraph(
_In_ NMHDR *Header
)
{
switch (Header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0);
PhGraphStateGetDrawInfo(&MemGraphState, getDrawInfo, GpuMemoryHistory.Count);
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(MemGraphHandle);
PhMoveReference(&MemGraphState.Text, PhFormatString(
L"%s / %s (%.2f%%)",
PhaFormatSize(UInt32x32To64(GpuCurrentMemUsage, 1024), -1)->Buffer,
PhaFormatSize(UInt32x32To64(GpuMemoryLimit, 1024), -1)->Buffer,
(FLOAT)GpuCurrentMemUsage / GpuMemoryLimit * 100
));
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &MemGraphState.Text->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
if (!MemGraphState.Valid)
{
for (ULONG i = 0; i < drawInfo->LineDataCount; i++)
{
MemGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&GpuMemoryHistory, i);
}
if (GpuMemoryLimit != 0)
{
// Scale the data.
PhDivideSinglesBySingle(
MemGraphState.Data1,
(FLOAT)GpuMemoryLimit,
drawInfo->LineDataCount
);
}
MemGraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (MemGraphState.TooltipIndex != getTooltipText->Index)
{
ULONG usedPages;
usedPages = PhGetItemCircularBuffer_ULONG(&GpuMemoryHistory, getTooltipText->Index);
PhMoveReference(&MemGraphState.TooltipText, PhFormatString(
L"%s / %s (%.2f%%)\n%s",
PhaFormatSize(UInt32x32To64(usedPages, 1024), -1)->Buffer,
PhaFormatSize(UInt32x32To64(GpuMemoryLimit, 1024), -1)->Buffer,
(FLOAT)usedPages / GpuMemoryLimit * 100,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = MemGraphState.TooltipText->sr;
}
}
break;
}
}
VOID NvGpuNotifySharedGraph(
_In_ NMHDR *Header
)
{
switch (Header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
PhGraphStateGetDrawInfo(&SharedGraphState, getDrawInfo, GpuBoardHistory.Count);
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(SharedGraphHandle);
PhMoveReference(&SharedGraphState.Text, PhFormatString(
L"%.0f%%",
(FLOAT)GpuCurrentCoreUsage * 100
));
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &SharedGraphState.Text->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
if (!SharedGraphState.Valid)
{
PhCopyCircularBuffer_FLOAT(&GpuBoardHistory, SharedGraphState.Data1, drawInfo->LineDataCount);
SharedGraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (SharedGraphState.TooltipIndex != getTooltipText->Index)
{
FLOAT usedPages;
usedPages = PhGetItemCircularBuffer_FLOAT(&GpuBoardHistory, getTooltipText->Index);
PhMoveReference(&SharedGraphState.TooltipText, PhFormatString(
L"%.0f%%\n%s",
usedPages * 100,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = SharedGraphState.TooltipText->sr;
}
}
break;
}
}
VOID NvGpuNotifyBusGraph(
_In_ NMHDR *Header
)
{
switch (Header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
PhGraphStateGetDrawInfo(&BusGraphState, getDrawInfo, GpuBusHistory.Count);
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(BusGraphHandle);
PhMoveReference(&BusGraphState.Text, PhFormatString(
L"%.0f%%",
(FLOAT)GpuCurrentBusUsage * 100
));
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &BusGraphState.Text->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
if (!BusGraphState.Valid)
{
PhCopyCircularBuffer_FLOAT(&GpuBusHistory, BusGraphState.Data1, drawInfo->LineDataCount);
BusGraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (BusGraphState.TooltipIndex != getTooltipText->Index)
{
FLOAT busUsage;
busUsage = PhGetItemCircularBuffer_FLOAT(&GpuBusHistory, getTooltipText->Index);
PhMoveReference(&BusGraphState.TooltipText, PhFormatString(
L"%.0f%%\n%s",
busUsage * 100,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = BusGraphState.TooltipText->sr;
}
}
break;
}
}
VOID NvGpuUpdateGraphs(
VOID
)
{
GpuGraphState.Valid = FALSE;
GpuGraphState.TooltipIndex = -1;
Graph_MoveGrid(GpuGraphHandle, 1);
Graph_Draw(GpuGraphHandle);
Graph_UpdateTooltip(GpuGraphHandle);
InvalidateRect(GpuGraphHandle, NULL, FALSE);
MemGraphState.Valid = FALSE;
MemGraphState.TooltipIndex = -1;
Graph_MoveGrid(MemGraphHandle, 1);
Graph_Draw(MemGraphHandle);
Graph_UpdateTooltip(MemGraphHandle);
InvalidateRect(MemGraphHandle, NULL, FALSE);
SharedGraphState.Valid = FALSE;
SharedGraphState.TooltipIndex = -1;
Graph_MoveGrid(SharedGraphHandle, 1);
Graph_Draw(SharedGraphHandle);
Graph_UpdateTooltip(SharedGraphHandle);
InvalidateRect(SharedGraphHandle, NULL, FALSE);
BusGraphState.Valid = FALSE;
BusGraphState.TooltipIndex = -1;
Graph_MoveGrid(BusGraphHandle, 1);
Graph_Draw(BusGraphHandle);
Graph_UpdateTooltip(BusGraphHandle);
InvalidateRect(BusGraphHandle, NULL, FALSE);
}
VOID NvGpuUpdatePanel(
VOID
)
{
SetDlgItemText(GpuPanel, IDC_CLOCK_CORE, PhaFormatString(L"%lu MHz", GpuCurrentCoreClock)->Buffer);
SetDlgItemText(GpuPanel, IDC_CLOCK_MEMORY, PhaFormatString(L"%lu MHz", GpuCurrentMemoryClock)->Buffer);
SetDlgItemText(GpuPanel, IDC_CLOCK_SHADER, PhaFormatString(L"%lu MHz", GpuCurrentShaderClock)->Buffer);
SetDlgItemText(GpuPanel, IDC_FAN_PERCENT, ((PPH_STRING)PhAutoDereferenceObject(NvGpuQueryFanSpeed()))->Buffer);
if (PhGetIntegerSetting(SETTING_NAME_ENABLE_FAHRENHEIT))
{
FLOAT fahrenheit = (FLOAT)(GpuCurrentCoreTemp * 1.8 + 32);
SetDlgItemText(GpuPanel, IDC_TEMP_VALUE, PhaFormatString(L"%.1f\u00b0F", fahrenheit)->Buffer);
}
else
{
SetDlgItemText(GpuPanel, IDC_TEMP_VALUE, PhaFormatString(L"%lu\u00b0C", GpuCurrentCoreTemp)->Buffer);
}
//SetDlgItemText(GpuPanel, IDC_TEMP_VALUE, PhaFormatString(L"%s\u00b0C", PhaFormatUInt64(GpuCurrentBoardTemp, TRUE)->Buffer)->Buffer);
SetDlgItemText(GpuPanel, IDC_VOLTAGE, PhaFormatString(L"%lu mV", GpuCurrentVoltage)->Buffer);
}
static INT_PTR CALLBACK NvGpuDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
//PhDeleteLayoutManager(&LayoutManager);
//PhDeleteGraphState(&GpuGraphState);
//PhDeleteGraphState(&MemGraphState);
//PhDeleteGraphState(&SharedGraphState);
//PhDeleteGraphState(&BusGraphState);
//if (GpuGraphHandle)
// DestroyWindow(GpuGraphHandle);
//if (MemGraphHandle)
// DestroyWindow(MemGraphHandle);
//if (SharedGraphHandle)
// DestroyWindow(SharedGraphHandle);
//if (BusGraphHandle)
// DestroyWindow(BusGraphHandle);
//if (GpuPanel)
// DestroyWindow(GpuPanel);
switch (uMsg)
{
case WM_INITDIALOG:
{
PPH_LAYOUT_ITEM graphItem;
PPH_LAYOUT_ITEM panelItem;
WindowHandle = hwndDlg;
GpuLabelHandle = GetDlgItem(hwndDlg, IDC_GPU_L);
MemLabelHandle = GetDlgItem(hwndDlg, IDC_MEMORY_L);
SharedLabelHandle = GetDlgItem(hwndDlg, IDC_SHARED_L);
BusLabelHandle = GetDlgItem(hwndDlg, IDC_BUS_L);
PhInitializeGraphState(&GpuGraphState);
PhInitializeGraphState(&MemGraphState);
PhInitializeGraphState(&SharedGraphState);
PhInitializeGraphState(&BusGraphState);
PhInitializeLayoutManager(&LayoutManager, hwndDlg);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_GPUNAME), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
graphItem = PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
GpuGraphMargin = graphItem->Margin;
panelItem = PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_SETFONT, (WPARAM)Section->Parameters->LargeFont, FALSE);
SendMessage(GetDlgItem(hwndDlg, IDC_GPUNAME), WM_SETFONT, (WPARAM)Section->Parameters->MediumFont, FALSE);
SetDlgItemText(hwndDlg, IDC_GPUNAME, GpuName->Buffer);
GpuPanel = CreateDialog(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_GPU_PANEL), hwndDlg, NvGpuPanelDialogProc);
ShowWindow(GpuPanel, SW_SHOW);
PhAddLayoutItemEx(&LayoutManager, GpuPanel, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
NvGpuCreateGraphs();
NvGpuUpdate();
NvGpuUpdateGraphs();
NvGpuUpdatePanel();
}
break;
case WM_SIZE:
NvGpuLayoutGraphs();
break;
case WM_NOTIFY:
{
NMHDR* header = (NMHDR*)lParam;
if (header->hwndFrom == GpuGraphHandle)
{
NvGpuNotifyUsageGraph(header);
}
else if (header->hwndFrom == MemGraphHandle)
{
NvGpuNotifyMemoryGraph(header);
}
else if (header->hwndFrom == SharedGraphHandle)
{
NvGpuNotifySharedGraph(header);
}
else if (header->hwndFrom == BusGraphHandle)
{
NvGpuNotifyBusGraph(header);
}
}
break;
case UPDATE_MSG:
{
NvGpuUpdateGraphs();
NvGpuUpdatePanel();
}
break;
}
return FALSE;
}
static BOOLEAN NvGpuSectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
)
{
switch (Message)
{
case SysInfoCreate:
return TRUE;
case SysInfoDestroy:
return TRUE;
case SysInfoTick:
{
if (WindowHandle)
PostMessage(WindowHandle, UPDATE_MSG, 0, 0);
if (DetailsHandle)
PostMessage(DetailsHandle, UPDATE_MSG, 0, 0);
}
return TRUE;
case SysInfoCreateDialog:
{
PPH_SYSINFO_CREATE_DIALOG createDialog = (PPH_SYSINFO_CREATE_DIALOG)Parameter1;
createDialog->Instance = PluginInstance->DllBase;
createDialog->Template = MAKEINTRESOURCE(IDD_GPU_DIALOG);
createDialog->DialogProc = NvGpuDialogProc;
//createDialog->Parameter = context;
}
return TRUE;
case SysInfoGraphGetDrawInfo:
{
PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)Parameter1;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, GpuUtilizationHistory.Count);
if (!Section->GraphState.Valid)
{
PhCopyCircularBuffer_FLOAT(&GpuUtilizationHistory, Section->GraphState.Data1, drawInfo->LineDataCount);
Section->GraphState.Valid = TRUE;
}
}
return TRUE;
case SysInfoGraphGetTooltipText:
{
FLOAT gpuUsageValue;
PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = (PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT)Parameter1;
gpuUsageValue = PhGetItemCircularBuffer_FLOAT(&GpuUtilizationHistory, getTooltipText->Index);
PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
L"%.0f%%\n%s",
gpuUsageValue * 100,
((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
getTooltipText->Text = Section->GraphState.TooltipText->sr;
}
return TRUE;
case SysInfoGraphDrawPanel:
{
PPH_SYSINFO_DRAW_PANEL drawPanel = (PPH_SYSINFO_DRAW_PANEL)Parameter1;
drawPanel->Title = PhCreateString(Section->Name.Buffer);
drawPanel->SubTitle = PhFormatString(
L"%.0f%%",
GpuCurrentGpuUsage * 100
);
}
return TRUE;
}
return FALSE;
}
VOID NvGpuSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers
)
{
PH_SYSINFO_SECTION section;
if (!PhGetIntegerSetting(SETTING_NAME_ENABLE_GPU))
return;
if (!NvApiInitialized)
return;
memset(&section, 0, sizeof(PH_SYSINFO_SECTION));
section.Callback = NvGpuSectionCallback;
GpuName = NvGpuQueryName();
PhInitializeStringRef(&section.Name, GpuName->Buffer);
Section = Pointers->CreateSection(&section);
}
#endif

View File

@@ -0,0 +1,407 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
PPH_PLUGIN PluginInstance = NULL;
PPH_OBJECT_TYPE NetAdapterEntryType = NULL;
PPH_LIST NetworkAdaptersList = NULL;
PH_QUEUED_LOCK NetworkAdaptersListLock = PH_QUEUED_LOCK_INIT;
PPH_OBJECT_TYPE DiskDriveEntryType = NULL;
PPH_LIST DiskDrivesList = NULL;
PH_QUEUED_LOCK DiskDrivesListLock = PH_QUEUED_LOCK_INIT;
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginUnloadCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
PH_CALLBACK_REGISTRATION MainWindowShowingCallbackRegistration;
PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration;
PH_CALLBACK_REGISTRATION SystemInformationInitializingCallbackRegistration;
VOID NTAPI LoadCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
DiskDrivesInitialize();
NetAdaptersInitialize();
DiskDrivesLoadList();
NetAdaptersLoadList();
#ifdef _NV_GPU_BUILD
NvApiInitialize();
#endif
}
VOID NTAPI UnloadCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
NOTHING;
}
VOID NTAPI ShowOptionsCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) };
PROPSHEETPAGE propSheetPage;
HPROPSHEETPAGE pages[2];
propSheetHeader.dwFlags =
PSH_NOAPPLYNOW |
PSH_NOCONTEXTHELP;
propSheetHeader.hwndParent = (HWND)Parameter;
propSheetHeader.pszCaption = L"Hardware Devices Plugin";
propSheetHeader.nPages = 0;
propSheetHeader.nStartPage = 0;
propSheetHeader.phpage = pages;
// Disk Drives
memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
propSheetPage.hInstance = PluginInstance->DllBase;
propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_DISKDRIVE_OPTIONS);
propSheetPage.pfnDlgProc = DiskDriveOptionsDlgProc;
pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
// Network Adapters
memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
propSheetPage.hInstance = PluginInstance->DllBase;
propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_NETADAPTER_OPTIONS);
propSheetPage.pfnDlgProc = NetworkAdapterOptionsDlgProc;
pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
PhModalPropertySheet(&propSheetHeader);
}
VOID NTAPI MainWindowShowingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
AddRemoveDeviceChangeCallback();
}
VOID NTAPI ProcessesUpdatedCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
DiskDrivesUpdate();
NetAdaptersUpdate();
#ifdef _NV_GPU_BUILD
NvGpuUpdate();
#endif
}
VOID NTAPI SystemInformationInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_SYSINFO_POINTERS pluginEntry = (PPH_PLUGIN_SYSINFO_POINTERS)Parameter;
// Disk Drives
PhAcquireQueuedLockShared(&DiskDrivesListLock);
for (ULONG i = 0; i < DiskDrivesList->Count; i++)
{
PDV_DISK_ENTRY entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]);
if (!entry)
continue;
if (entry->DevicePresent)
{
DiskDriveSysInfoInitializing(pluginEntry, entry);
}
}
PhReleaseQueuedLockShared(&DiskDrivesListLock);
// Network Adapters
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!entry)
continue;
if (entry->DevicePresent)
{
NetAdapterSysInfoInitializing(pluginEntry, entry);
}
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
// Graphics cards
#ifdef _NV_GPU_BUILD
NvGpuSysInfoInitializing(pluginEntry);
#endif
}
PPH_STRING TrimString(
_In_ PPH_STRING String
)
{
static PH_STRINGREF whitespace = PH_STRINGREF_INIT(L" \t\r\n");
PH_STRINGREF sr = String->sr;
PhTrimStringRef(&sr, &whitespace, 0);
return PhCreateString2(&sr);
}
INT AddListViewGroup(
_In_ HWND ListViewHandle,
_In_ INT GroupId,
_In_ PWSTR Text
)
{
LVGROUP group;
group.cbSize = LVGROUP_V5_SIZE;
group.mask = LVGF_HEADER;
group.pszHeader = Text;
if (WindowsVersion >= WINDOWS_VISTA)
{
group.cbSize = sizeof(LVGROUP);
group.mask |= LVGF_ALIGN | LVGF_STATE | LVGF_GROUPID;
group.uAlign = LVGA_HEADER_LEFT;
group.state = LVGS_COLLAPSIBLE;
group.iGroupId = GroupId;
}
return (INT)ListView_InsertGroup(ListViewHandle, MAXINT, &group);
}
INT AddListViewItemGroupId(
_In_ HWND ListViewHandle,
_In_ INT GroupId,
_In_ INT Index,
_In_ PWSTR Text,
_In_opt_ PVOID Param
)
{
LVITEM item;
item.mask = LVIF_TEXT;
item.iItem = Index;
item.iSubItem = 0;
item.pszText = Text;
if (WindowsVersion >= WINDOWS_VISTA)
{
item.mask |= LVIF_GROUPID;
item.iGroupId = GroupId;
}
if (Param)
{
item.mask |= LVIF_PARAM;
item.lParam = (LPARAM)Param;
}
return ListView_InsertItem(ListViewHandle, &item);
}
ULONG64 RegQueryUlong64(
_In_ HANDLE KeyHandle,
_In_ PWSTR ValueName
)
{
ULONG64 value = 0;
PH_STRINGREF valueName;
PKEY_VALUE_PARTIAL_INFORMATION buffer;
PhInitializeStringRef(&valueName, ValueName);
if (NT_SUCCESS(PhQueryValueKey(KeyHandle, &valueName, KeyValuePartialInformation, &buffer)))
{
if (buffer->Type == REG_DWORD || buffer->Type == REG_QWORD)
{
value = *(ULONG64*)buffer->Data;
}
PhFree(buffer);
}
return value;
}
VOID ShowDeviceMenu(
_In_ HWND ParentWindow,
_In_ PPH_STRING DeviceInstance
)
{
POINT cursorPos;
PPH_EMENU menu;
PPH_EMENU_ITEM selectedItem;
GetCursorPos(&cursorPos);
menu = PhCreateEMenu();
//PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 0, L"Enable", NULL, NULL), -1);
//PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"Disable", NULL, NULL), -1);
//PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"Properties", NULL, NULL), -1);
selectedItem = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
cursorPos.x,
cursorPos.y
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case 1:
{
HMODULE devMgrHandle;
// https://msdn.microsoft.com/en-us/library/ff548181.aspx
VOID (WINAPI *DeviceProperties_RunDLL_I)(
_In_ HWND hwndStub,
_In_ HINSTANCE hAppInstance,
_In_ PWSTR lpCmdLine,
_In_ INT nCmdShow
);
if (devMgrHandle = LoadLibrary(L"devmgr.dll"))
{
if (DeviceProperties_RunDLL_I = (PVOID)GetProcAddress(devMgrHandle, "DeviceProperties_RunDLLW"))
{
// This will sometimes re-throw an RPC error during debugging and can be safely ignored.
DeviceProperties_RunDLL_I(
GetParent(ParentWindow),
NULL,
PhaFormatString(L"/DeviceID %s", DeviceInstance->Buffer)->Buffer,
0
);
}
FreeLibrary(devMgrHandle);
}
}
break;
}
}
PhDestroyEMenu(menu);
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ IntegerSettingType, SETTING_NAME_ENABLE_NDIS, L"1" },
{ StringSettingType, SETTING_NAME_INTERFACE_LIST, L"" },
{ StringSettingType, SETTING_NAME_DISK_LIST, L"" },
#ifdef _NV_GPU_BUILD
{ IntegerSettingType, SETTING_NAME_ENABLE_GPU, L"1" },
{ IntegerSettingType, SETTING_NAME_ENABLE_FAHRENHEIT, L"0" }
#endif
};
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"Hardware Devices";
info->Author = L"dmex, wj32";
info->Description = L"Plugin for monitoring hardware devices like Disk drives and Network adapters via the System Information window.";
info->Url = L"https://wj32.org/processhacker/forums/viewtopic.php?t=1820";
info->HasOptions = TRUE;
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
LoadCallback,
NULL,
&PluginLoadCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackUnload),
UnloadCallback,
NULL,
&PluginUnloadCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions),
ShowOptionsCallback,
NULL,
&PluginShowOptionsCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackMainWindowShowing),
MainWindowShowingCallback,
NULL,
&MainWindowShowingCallbackRegistration
);
PhRegisterCallback(
&PhProcessesUpdatedEvent,
ProcessesUpdatedCallback,
NULL,
&ProcessesUpdatedCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackSystemInformationInitializing),
SystemInformationInitializingCallback,
NULL,
&SystemInformationInitializingCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@@ -0,0 +1,597 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
#include <objbase.h>
PVOID IphlpHandle = NULL;
_GetInterfaceDescriptionFromGuid GetInterfaceDescriptionFromGuid_I = NULL;
NTSTATUS NetworkAdapterCreateHandle(
_Out_ PHANDLE DeviceHandle,
_In_ PPH_STRING InterfaceGuid
)
{
// NOTE: Do not cache this handle. The user will be unable to enable, disable or change adapter configuration.
return PhCreateFileWin32(
DeviceHandle,
PhaConcatStrings(2, L"\\\\.\\", InterfaceGuid->Buffer)->Buffer,
FILE_GENERIC_READ,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
);
}
BOOLEAN NetworkAdapterQuerySupported(
_In_ HANDLE DeviceHandle
)
{
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
BOOLEAN ndisQuerySupported = FALSE;
BOOLEAN adapterNameSupported = FALSE;
BOOLEAN adapterStatsSupported = FALSE;
BOOLEAN adapterLinkStateSupported = FALSE;
BOOLEAN adapterLinkSpeedSupported = FALSE;
PNDIS_OID ndisObjectIdentifiers = NULL;
// https://msdn.microsoft.com/en-us/library/ff569642.aspx
opcode = OID_GEN_SUPPORTED_LIST;
// TODO: 4096 objects might be too small...
ndisObjectIdentifiers = PhAllocate(PAGE_SIZE * sizeof(NDIS_OID));
memset(ndisObjectIdentifiers, 0, PAGE_SIZE * sizeof(NDIS_OID));
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS, // https://msdn.microsoft.com/en-us/library/windows/hardware/ff548975.aspx
&opcode,
sizeof(NDIS_OID),
ndisObjectIdentifiers,
PAGE_SIZE * sizeof(NDIS_OID)
)))
{
ndisQuerySupported = TRUE;
for (ULONG i = 0; i < (ULONG)isb.Information / sizeof(NDIS_OID); i++)
{
NDIS_OID opcode = ndisObjectIdentifiers[i];
switch (opcode)
{
case OID_GEN_FRIENDLY_NAME:
adapterNameSupported = TRUE;
break;
case OID_GEN_STATISTICS:
adapterStatsSupported = TRUE;
break;
case OID_GEN_LINK_STATE:
adapterLinkStateSupported = TRUE;
break;
case OID_GEN_LINK_SPEED:
adapterLinkSpeedSupported = TRUE;
break;
}
}
}
PhFree(ndisObjectIdentifiers);
if (!adapterNameSupported)
ndisQuerySupported = FALSE;
if (!adapterStatsSupported)
ndisQuerySupported = FALSE;
if (!adapterLinkStateSupported)
ndisQuerySupported = FALSE;
if (!adapterLinkSpeedSupported)
ndisQuerySupported = FALSE;
return ndisQuerySupported;
}
BOOLEAN NetworkAdapterQueryNdisVersion(
_In_ HANDLE DeviceHandle,
_Out_opt_ PUINT MajorVersion,
_Out_opt_ PUINT MinorVersion
)
{
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
ULONG versionResult = 0;
// https://msdn.microsoft.com/en-us/library/ff569582.aspx
opcode = OID_GEN_DRIVER_VERSION; // OID_GEN_VENDOR_DRIVER_VERSION
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&versionResult,
sizeof(versionResult)
)))
{
if (MajorVersion)
{
*MajorVersion = HIBYTE(versionResult);
}
if (MinorVersion)
{
*MinorVersion = LOBYTE(versionResult);
}
return TRUE;
}
return FALSE;
}
PPH_STRING NetworkAdapterQueryName(
_In_ HANDLE DeviceHandle,
_In_ PPH_STRING InterfaceGuid
)
{
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
WCHAR adapterName[NDIS_IF_MAX_STRING_SIZE + 1] = L"";
// https://msdn.microsoft.com/en-us/library/ff569584.aspx
opcode = OID_GEN_FRIENDLY_NAME;
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
adapterName,
sizeof(adapterName)
)))
{
return PhCreateString(adapterName);
}
if (!GetInterfaceDescriptionFromGuid_I)
{
if (IphlpHandle = LoadLibrary(L"iphlpapi.dll"))
{
GetInterfaceDescriptionFromGuid_I = PhGetProcedureAddress(IphlpHandle, "NhGetInterfaceDescriptionFromGuid", 0);
}
}
// HACK: Query adapter description using undocumented function.
if (GetInterfaceDescriptionFromGuid_I)
{
GUID deviceGuid = GUID_NULL;
UNICODE_STRING guidStringUs;
PhStringRefToUnicodeString(&InterfaceGuid->sr, &guidStringUs);
if (NT_SUCCESS(RtlGUIDFromString(&guidStringUs, &deviceGuid)))
{
WCHAR adapterDescription[NDIS_IF_MAX_STRING_SIZE + 1] = L"";
SIZE_T adapterDescriptionLength = sizeof(adapterDescription);
if (SUCCEEDED(GetInterfaceDescriptionFromGuid_I(&deviceGuid, adapterDescription, &adapterDescriptionLength, NULL, NULL)))
{
return PhCreateString(adapterDescription);
}
}
}
return PhCreateString(L"Unknown Network Adapter");
}
NTSTATUS NetworkAdapterQueryStatistics(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_STATISTICS_INFO Info
)
{
NTSTATUS status;
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
NDIS_STATISTICS_INFO result;
// https://msdn.microsoft.com/en-us/library/ff569640.aspx
opcode = OID_GEN_STATISTICS;
memset(&result, 0, sizeof(NDIS_STATISTICS_INFO));
result.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
result.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
result.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
status = NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&result,
sizeof(result)
);
*Info = result;
return status;
}
NTSTATUS NetworkAdapterQueryLinkState(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_LINK_STATE State
)
{
NTSTATUS status;
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
NDIS_LINK_STATE result;
// https://msdn.microsoft.com/en-us/library/ff569595.aspx
opcode = OID_GEN_LINK_STATE; // OID_GEN_MEDIA_CONNECT_STATUS;
memset(&result, 0, sizeof(NDIS_LINK_STATE));
result.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
result.Header.Revision = NDIS_LINK_STATE_REVISION_1;
result.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
status = NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&result,
sizeof(result)
);
*State = result;
return status;
}
BOOLEAN NetworkAdapterQueryMediaType(
_In_ HANDLE DeviceHandle,
_Out_ PNDIS_PHYSICAL_MEDIUM Medium
)
{
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
NDIS_PHYSICAL_MEDIUM adapterMediaType = NdisPhysicalMediumUnspecified;
// https://msdn.microsoft.com/en-us/library/ff569622.aspx
opcode = OID_GEN_PHYSICAL_MEDIUM_EX;
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&adapterMediaType,
sizeof(adapterMediaType)
)))
{
*Medium = adapterMediaType;
}
if (adapterMediaType != NdisPhysicalMediumUnspecified)
return TRUE;
// https://msdn.microsoft.com/en-us/library/ff569621.aspx
opcode = OID_GEN_PHYSICAL_MEDIUM;
adapterMediaType = NdisPhysicalMediumUnspecified;
memset(&isb, 0, sizeof(IO_STATUS_BLOCK));
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&adapterMediaType,
sizeof(adapterMediaType)
)))
{
*Medium = adapterMediaType;
}
if (adapterMediaType != NdisPhysicalMediumUnspecified)
return TRUE;
//NDIS_MEDIUM adapterMediaType = NdisMediumMax;
//opcode = OID_GEN_MEDIA_IN_USE;
return FALSE;
}
NTSTATUS NetworkAdapterQueryLinkSpeed(
_In_ HANDLE DeviceHandle,
_Out_ PULONG64 LinkSpeed
)
{
NTSTATUS status;
NDIS_OID opcode;
IO_STATUS_BLOCK isb;
NDIS_LINK_SPEED result;
// https://msdn.microsoft.com/en-us/library/ff569593.aspx
opcode = OID_GEN_LINK_SPEED;
memset(&result, 0, sizeof(NDIS_LINK_SPEED));
status = NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&opcode,
sizeof(NDIS_OID),
&result,
sizeof(result)
);
*LinkSpeed = UInt32x32To64(result.XmitLinkSpeed, NDIS_UNIT_OF_MEASUREMENT);
return status;
}
ULONG64 NetworkAdapterQueryValue(
_In_ HANDLE DeviceHandle,
_In_ NDIS_OID OpCode
)
{
IO_STATUS_BLOCK isb;
ULONG64 result = 0;
if (NT_SUCCESS(NtDeviceIoControlFile(
DeviceHandle,
NULL,
NULL,
NULL,
&isb,
IOCTL_NDIS_QUERY_GLOBAL_STATS,
&OpCode,
sizeof(NDIS_OID),
&result,
sizeof(result)
)))
{
return result;
}
return 0;
}
BOOLEAN QueryInterfaceRowVista(
_In_ PDV_NETADAPTER_ID Id,
_Out_ PMIB_IF_ROW2 InterfaceRow
)
{
BOOLEAN result = FALSE;
MIB_IF_ROW2 interfaceRow;
memset(&interfaceRow, 0, sizeof(MIB_IF_ROW2));
interfaceRow.InterfaceLuid = Id->InterfaceLuid;
interfaceRow.InterfaceIndex = Id->InterfaceIndex;
if (GetIfEntry2)
{
if (GetIfEntry2(&interfaceRow) == NO_ERROR)
{
result = TRUE;
*InterfaceRow = interfaceRow;
}
}
//MIB_IPINTERFACE_ROW interfaceTable;
//memset(&interfaceTable, 0, sizeof(MIB_IPINTERFACE_ROW));
//interfaceTable.Family = AF_INET;
//interfaceTable.InterfaceLuid.Value = Context->AdapterEntry->InterfaceLuidValue;
//interfaceTable.InterfaceIndex = Context->AdapterEntry->InterfaceIndex;
//GetIpInterfaceEntry(&interfaceTable);
return result;
}
BOOLEAN QueryInterfaceRowXP(
_In_ PDV_NETADAPTER_ID Id,
_Out_ PMIB_IFROW InterfaceRow
)
{
BOOLEAN result = FALSE;
MIB_IFROW interfaceRow;
memset(&interfaceRow, 0, sizeof(MIB_IFROW));
interfaceRow.dwIndex = Id->InterfaceIndex;
if (GetIfEntry(&interfaceRow) == NO_ERROR)
{
result = TRUE;
*InterfaceRow = interfaceRow;
}
//MIB_IPINTERFACE_ROW interfaceTable;
//memset(&interfaceTable, 0, sizeof(MIB_IPINTERFACE_ROW));
//interfaceTable.Family = AF_INET;
//interfaceTable.InterfaceIndex = Context->AdapterEntry->InterfaceIndex;
//GetIpInterfaceEntry(&interfaceTable);
return result;
}
//BOOLEAN NetworkAdapterQueryInternet(
// _Inout_ PDV_NETADAPTER_SYSINFO_CONTEXT Context,
// _In_ PPH_STRING IpAddress
// )
//{
// // https://technet.microsoft.com/en-us/library/cc766017.aspx
// BOOLEAN socketResult = FALSE;
// WSADATA wsadata;
// DNS_STATUS dnsQueryStatus = DNS_ERROR_RCODE_NO_ERROR;
// PDNS_RECORD dnsQueryRecords = NULL;
//
// WSAStartup(WINSOCK_VERSION, &wsadata);
//
// __try
// {
// if ((dnsQueryStatus = DnsQuery(
// L"www.msftncsi.com",
// DNS_TYPE_A,
// DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_BYPASS_CACHE,
// NULL,
// &dnsQueryRecords,
// NULL
// )) != DNS_ERROR_RCODE_NO_ERROR)
// {
// __leave;
// }
//
// for (PDNS_RECORD i = dnsQueryRecords; i != NULL; i = i->pNext)
// {
// if (i->wType == DNS_TYPE_A)
// {
// SOCKET socketHandle = INVALID_SOCKET;
//
// if ((socketHandle = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET)
// continue;
//
// IN_ADDR sockAddr;
// InetPton(AF_INET, IpAddress->Buffer, &sockAddr);
//
// SOCKADDR_IN localaddr = { 0 };
// localaddr.sin_family = AF_INET;
// localaddr.sin_addr.s_addr = sockAddr.s_addr;
//
// if (bind(socketHandle, (PSOCKADDR)&localaddr, sizeof(localaddr)) == SOCKET_ERROR)
// {
// closesocket(socketHandle);
// continue;
// }
//
// SOCKADDR_IN remoteAddr;
// remoteAddr.sin_family = AF_INET;
// remoteAddr.sin_port = htons(80);
// remoteAddr.sin_addr.s_addr = i->Data.A.IpAddress;
//
// if (WSAConnect(socketHandle, (PSOCKADDR)&remoteAddr, sizeof(remoteAddr), NULL, NULL, NULL, NULL) != SOCKET_ERROR)
// {
// socketResult = TRUE;
// closesocket(socketHandle);
// break;
// }
//
// closesocket(socketHandle);
// }
// }
// }
// __finally
// {
// if (dnsQueryRecords)
// {
// DnsFree(dnsQueryRecords, DnsFreeRecordList);
// }
// }
//
// __try
// {
// if ((dnsQueryStatus = DnsQuery(
// L"ipv6.msftncsi.com",
// DNS_TYPE_AAAA,
// DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_BYPASS_CACHE, // | DNS_QUERY_DUAL_ADDR
// NULL,
// &dnsQueryRecords,
// NULL
// )) != DNS_ERROR_RCODE_NO_ERROR)
// {
// __leave;
// }
//
// for (PDNS_RECORD i = dnsQueryRecords; i != NULL; i = i->pNext)
// {
// if (i->wType == DNS_TYPE_AAAA)
// {
// SOCKET socketHandle = INVALID_SOCKET;
//
// if ((socketHandle = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == INVALID_SOCKET)
// continue;
//
// IN6_ADDR sockAddr;
// InetPton(AF_INET6, IpAddress->Buffer, &sockAddr);
//
// SOCKADDR_IN6 remoteAddr = { 0 };
// remoteAddr.sin6_family = AF_INET6;
// remoteAddr.sin6_port = htons(80);
// memcpy(&remoteAddr.sin6_addr.u.Byte, i->Data.AAAA.Ip6Address.IP6Byte, sizeof(i->Data.AAAA.Ip6Address.IP6Byte));
//
// if (WSAConnect(socketHandle, (PSOCKADDR)&remoteAddr, sizeof(SOCKADDR_IN6), NULL, NULL, NULL, NULL) != SOCKET_ERROR)
// {
// socketResult = TRUE;
// closesocket(socketHandle);
// break;
// }
//
// closesocket(socketHandle);
// }
// }
// }
// __finally
// {
// if (dnsQueryRecords)
// {
// DnsFree(dnsQueryRecords, DnsFreeRecordList);
// }
// }
//
// WSACleanup();
//
// return socketResult;
//}

View File

@@ -0,0 +1,787 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
VOID NTAPI NetAdapterProcessesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PDV_NETADAPTER_DETAILS_CONTEXT context = Context;
if (context->WindowHandle)
{
PostMessage(context->WindowHandle, UPDATE_MSG, 0, 0);
}
}
VOID NetAdapterAddListViewItemGroups(
_In_ HWND ListViewHandle
)
{
if (WindowsVersion >= WINDOWS_VISTA)
{
ListView_EnableGroupView(ListViewHandle, TRUE);
AddListViewGroup(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, L"Adapter");
AddListViewGroup(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, L"Unicast");
AddListViewGroup(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, L"Broadcast");
AddListViewGroup(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, L"Multicast");
AddListViewGroup(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, L"Errors");
}
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_STATE, L"State", NULL);
//AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_CONNECTIVITY, L"Connectivity");
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_IPADDRESS, L"IP address", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_SUBNET, L"Subnet mask", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_GATEWAY, L"Default gateway", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_DNS, L"DNS", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_DOMAIN, L"Domain", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_LINKSPEED, L"Link speed", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_SENT, L"Sent", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_RECEIVED, L"Received", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_TOTAL, L"Total", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_SENDING, L"Sending", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_RECEIVING, L"Receiving", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ADAPTER, NETADAPTER_DETAILS_INDEX_UTILIZATION, L"Utilization", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_SENTPKTS, L"Sent packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_RECVPKTS, L"Received packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_TOTALPKTS, L"Total packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_SENT, L"Sent", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVED, L"Received", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_TOTAL, L"Total", NULL);
//AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_SENDING, L"Sending");
//AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVING, L"Receiving");
//AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_UNICAST, NETADAPTER_DETAILS_INDEX_UNICAST_UTILIZATION, L"Utilization");
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_SENTPKTS, L"Sent packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_RECVPKTS, L"Received packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_TOTALPKTS, L"Total packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_SENT, L"Sent", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_RECEIVED, L"Received", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_BROADCAST, NETADAPTER_DETAILS_INDEX_BROADCAST_TOTAL, L"Total", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_SENTPKTS, L"Sent packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_RECVPKTS, L"Received packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_TOTALPKTS, L"Total packets", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_SENT, L"Sent", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_RECEIVED, L"Received", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_MULTICAST, NETADAPTER_DETAILS_INDEX_MULTICAST_TOTAL, L"Total", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_SENTPKTS, L"Send errors", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_RECVPKTS, L"Receive errors", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_TOTALPKTS, L"Total errors", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_SENT, L"Send discards", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_RECEIVED, L"Receive discards", NULL);
AddListViewItemGroupId(ListViewHandle, NETADAPTER_DETAILS_CATEGORY_ERRORS, NETADAPTER_DETAILS_INDEX_ERRORS_TOTAL, L"Total discards", NULL);
}
PVOID NetAdapterGetAddresses(
_In_ ULONG Family
)
{
ULONG flags;
ULONG bufferLength = 0;
PIP_ADAPTER_ADDRESSES buffer = NULL;
flags = GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_SKIP_FRIENDLY_NAME;
if (WindowsVersion >= WINDOWS_VISTA)
{
flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES;
}
if (GetAdaptersAddresses(Family, flags, NULL, NULL, &bufferLength) != ERROR_BUFFER_OVERFLOW)
{
return NULL;
}
buffer = PhAllocate(bufferLength);
memset(buffer, 0, bufferLength);
if (GetAdaptersAddresses(Family, flags, NULL, buffer, &bufferLength) != ERROR_SUCCESS)
{
PhFree(buffer);
return NULL;
}
return buffer;
}
VOID NetAdapterEnumerateAddresses(
_In_ PVOID AddressesBuffer,
_In_ ULONG64 InterfaceLuid,
_In_ PPH_STRING_BUILDER DomainBuffer,
_In_ PPH_STRING_BUILDER IpAddressBuffer,
_In_ PPH_STRING_BUILDER SubnetAddressBuffer,
_In_ PPH_STRING_BUILDER GatewayAddressBuffer,
_In_ PPH_STRING_BUILDER DnsAddressBuffer
)
{
PIP_ADAPTER_ADDRESSES addressesBuffer;
PIP_ADAPTER_UNICAST_ADDRESS unicastAddress;
PIP_ADAPTER_GATEWAY_ADDRESS gatewayAddress;
PIP_ADAPTER_DNS_SERVER_ADDRESS dnsAddress;
for (addressesBuffer = AddressesBuffer; addressesBuffer; addressesBuffer = addressesBuffer->Next)
{
if (addressesBuffer->Luid.Value != InterfaceLuid)
continue;
if (addressesBuffer->DnsSuffix && PhCountStringZ(addressesBuffer->DnsSuffix) > 0)
{
PhAppendFormatStringBuilder(DomainBuffer, L"%s, ", addressesBuffer->DnsSuffix);
}
for (unicastAddress = addressesBuffer->FirstUnicastAddress; unicastAddress; unicastAddress = unicastAddress->Next)
{
if (unicastAddress->Address.lpSockaddr->sa_family == AF_INET)
{
PSOCKADDR_IN sockAddrIn = { 0 };
IN_ADDR subnetMask = { 0 };
WCHAR ipv4AddressString[INET_ADDRSTRLEN] = L"";
WCHAR subnetAddressString[INET_ADDRSTRLEN] = L"";
sockAddrIn = (PSOCKADDR_IN)unicastAddress->Address.lpSockaddr;
if (WindowsVersion >= WINDOWS_VISTA && ConvertLengthToIpv4Mask)
{
ConvertLengthToIpv4Mask(unicastAddress->OnLinkPrefixLength, &subnetMask.s_addr);
}
if (RtlIpv4AddressToString(&sockAddrIn->sin_addr, ipv4AddressString))
{
PhAppendFormatStringBuilder(IpAddressBuffer, L"%s, ", ipv4AddressString);
}
if (RtlIpv4AddressToString(&subnetMask, subnetAddressString))
{
PhAppendFormatStringBuilder(SubnetAddressBuffer, L"%s, ", subnetAddressString);
}
}
if (unicastAddress->Address.lpSockaddr->sa_family == AF_INET6)
{
PSOCKADDR_IN6 sockAddrIn6 = { 0 };
WCHAR ipv6AddressString[INET6_ADDRSTRLEN] = L"";
sockAddrIn6 = (PSOCKADDR_IN6)unicastAddress->Address.lpSockaddr;
if (RtlIpv6AddressToString(&sockAddrIn6->sin6_addr, ipv6AddressString))
{
PhAppendFormatStringBuilder(IpAddressBuffer, L"%s, ", ipv6AddressString);
}
}
}
for (gatewayAddress = addressesBuffer->FirstGatewayAddress; gatewayAddress; gatewayAddress = gatewayAddress->Next)
{
if (gatewayAddress->Address.lpSockaddr->sa_family == AF_INET)
{
PSOCKADDR_IN sockAddrIn = { 0 };
WCHAR ipv4AddressString[INET_ADDRSTRLEN] = L"";
sockAddrIn = (PSOCKADDR_IN)gatewayAddress->Address.lpSockaddr;
if (RtlIpv4AddressToString(&sockAddrIn->sin_addr, ipv4AddressString))
{
PhAppendFormatStringBuilder(GatewayAddressBuffer, L"%s, ", ipv4AddressString);
}
}
if (gatewayAddress->Address.lpSockaddr->sa_family == AF_INET6)
{
PSOCKADDR_IN6 sockAddrIn6 = (PSOCKADDR_IN6)gatewayAddress->Address.lpSockaddr;
WCHAR ipv6AddressString[INET6_ADDRSTRLEN] = L"";
if (RtlIpv6AddressToString(&sockAddrIn6->sin6_addr, ipv6AddressString))
{
PhAppendFormatStringBuilder(GatewayAddressBuffer, L"%s, ", ipv6AddressString);
}
}
}
for (dnsAddress = addressesBuffer->FirstDnsServerAddress; dnsAddress; dnsAddress = dnsAddress->Next)
{
if (dnsAddress->Address.lpSockaddr->sa_family == AF_INET)
{
PSOCKADDR_IN sockAddrIn = (PSOCKADDR_IN)dnsAddress->Address.lpSockaddr;
WCHAR ipv4AddressString[INET_ADDRSTRLEN] = L"";
if (RtlIpv4AddressToString(&sockAddrIn->sin_addr, ipv4AddressString))
{
PhAppendFormatStringBuilder(DnsAddressBuffer, L"%s, ", ipv4AddressString);
}
}
else if (dnsAddress->Address.lpSockaddr->sa_family == AF_INET6)
{
PSOCKADDR_IN6 sockAddrIn6 = (PSOCKADDR_IN6)dnsAddress->Address.lpSockaddr;
WCHAR ipv6AddressString[INET6_ADDRSTRLEN] = L"";
if (RtlIpv6AddressToString(&sockAddrIn6->sin6_addr, ipv6AddressString))
{
PhAppendFormatStringBuilder(DnsAddressBuffer, L"%s, ", ipv6AddressString);
}
}
}
}
}
VOID NetAdapterLookupConfig(
_Inout_ PDV_NETADAPTER_DETAILS_CONTEXT Context
)
{
if (WindowsVersion >= WINDOWS_VISTA)
{
PVOID addressesBuffer = NULL;
PPH_STRING domainString = NULL;
PPH_STRING ipAddressString = NULL;
PPH_STRING subnetAddressString = NULL;
PPH_STRING gatewayAddressString = NULL;
PPH_STRING dnsAddressString = NULL;
PH_STRING_BUILDER domainBuffer;
PH_STRING_BUILDER ipAddressBuffer;
PH_STRING_BUILDER subnetAddressBuffer;
PH_STRING_BUILDER gatewayAddressBuffer;
PH_STRING_BUILDER dnsAddressBuffer;
PhInitializeStringBuilder(&domainBuffer, 64);
PhInitializeStringBuilder(&ipAddressBuffer, 64);
PhInitializeStringBuilder(&subnetAddressBuffer, 64);
PhInitializeStringBuilder(&gatewayAddressBuffer, 64);
PhInitializeStringBuilder(&dnsAddressBuffer, 64);
if (addressesBuffer = NetAdapterGetAddresses(AF_INET))
{
NetAdapterEnumerateAddresses(
addressesBuffer,
Context->AdapterId.InterfaceLuid.Value,
&domainBuffer,
&ipAddressBuffer,
&subnetAddressBuffer,
&gatewayAddressBuffer,
&dnsAddressBuffer
);
PhFree(addressesBuffer);
}
if (addressesBuffer = NetAdapterGetAddresses(AF_INET6))
{
NetAdapterEnumerateAddresses(
addressesBuffer,
Context->AdapterId.InterfaceLuid.Value,
&domainBuffer,
&ipAddressBuffer,
&subnetAddressBuffer,
&gatewayAddressBuffer,
&dnsAddressBuffer
);
PhFree(addressesBuffer);
}
if (domainBuffer.String->Length > 2)
PhRemoveEndStringBuilder(&domainBuffer, 2);
if (ipAddressBuffer.String->Length > 2)
PhRemoveEndStringBuilder(&ipAddressBuffer, 2);
if (subnetAddressBuffer.String->Length > 2)
PhRemoveEndStringBuilder(&subnetAddressBuffer, 2);
if (gatewayAddressBuffer.String->Length > 2)
PhRemoveEndStringBuilder(&gatewayAddressBuffer, 2);
if (dnsAddressBuffer.String->Length > 2)
PhRemoveEndStringBuilder(&dnsAddressBuffer, 2);
domainString = PhFinalStringBuilderString(&domainBuffer);
ipAddressString = PhFinalStringBuilderString(&ipAddressBuffer);
subnetAddressString = PhFinalStringBuilderString(&subnetAddressBuffer);
gatewayAddressString = PhFinalStringBuilderString(&gatewayAddressBuffer);
dnsAddressString = PhFinalStringBuilderString(&dnsAddressBuffer);
//PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_CONNECTIVITY, 1, internet ? L"Internet" : L"Local");
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_IPADDRESS, 1, ipAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_SUBNET, 1, subnetAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_GATEWAY, 1, gatewayAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_DNS, 1, dnsAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_DOMAIN, 1, domainString->Buffer);
PhDeleteStringBuilder(&domainBuffer);
PhDeleteStringBuilder(&ipAddressBuffer);
PhDeleteStringBuilder(&subnetAddressBuffer);
PhDeleteStringBuilder(&gatewayAddressBuffer);
PhDeleteStringBuilder(&dnsAddressBuffer);
}
else
{
static PH_STRINGREF tcpIpv4KeyName = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\");
HANDLE keyHandle;
PPH_STRING keyNameIpV4;
keyNameIpV4 = PhConcatStringRef2(&tcpIpv4KeyName, &Context->AdapterId.InterfaceGuid->sr);
if (NT_SUCCESS(PhOpenKey(
&keyHandle,
KEY_READ,
PH_KEY_LOCAL_MACHINE,
&keyNameIpV4->sr,
0
)))
{
PPH_STRING domainString = NULL;
PPH_STRING ipAddressString = NULL;
PPH_STRING subnetAddressString = NULL;
PPH_STRING gatewayAddressString = NULL;
domainString = PhQueryRegistryString(keyHandle, L"DhcpDomain");
ipAddressString = PhQueryRegistryString(keyHandle, L"DhcpIPAddress");
subnetAddressString = PhQueryRegistryString(keyHandle, L"DhcpSubnetMask");
gatewayAddressString = PhQueryRegistryString(keyHandle, L"DhcpDefaultGateway");
if (PhIsNullOrEmptyString(domainString))
PhMoveReference(&domainString, PhQueryRegistryString(keyHandle, L"Domain"));
if (PhIsNullOrEmptyString(ipAddressString))
PhMoveReference(&ipAddressString, PhQueryRegistryString(keyHandle, L"IPAddress"));
if (PhIsNullOrEmptyString(subnetAddressString))
PhMoveReference(&subnetAddressString, PhQueryRegistryString(keyHandle, L"SubnetMask"));
if (PhIsNullOrEmptyString(gatewayAddressString))
PhMoveReference(&gatewayAddressString, PhQueryRegistryString(keyHandle, L"DefaultGateway"));
//PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_CONNECTIVITY, 1, internet ? L"Internet" : L"Local");
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_IPADDRESS, 1, PhIsNullOrEmptyString(ipAddressString) ? L"" : ipAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_SUBNET, 1, PhIsNullOrEmptyString(subnetAddressString) ? L"" : subnetAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_GATEWAY, 1, PhIsNullOrEmptyString(gatewayAddressString) ? L"" : gatewayAddressString->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_DOMAIN, 1, PhIsNullOrEmptyString(domainString) ? L"" : domainString->Buffer);
PhClearReference(&domainString);
PhClearReference(&ipAddressString);
PhClearReference(&subnetAddressString);
PhClearReference(&gatewayAddressString);
NtClose(keyHandle);
}
PhDereferenceObject(keyNameIpV4);
}
}
VOID NETIOAPI_API_ NetAdapterChangeCallback(
_In_ PVOID CallerContext,
_In_opt_ PMIB_IPINTERFACE_ROW Row,
_In_ MIB_NOTIFICATION_TYPE NotificationType
)
{
PDV_NETADAPTER_DETAILS_CONTEXT context = CallerContext;
if (NotificationType == MibInitialNotification)
{
NetAdapterLookupConfig(context);
}
else if (NotificationType == MibParameterNotification)
{
if (Row->InterfaceLuid.Value = context->AdapterId.InterfaceLuid.Value)
{
NetAdapterLookupConfig(context);
}
}
}
VOID NetAdapterUpdateDetails(
_Inout_ PDV_NETADAPTER_DETAILS_CONTEXT Context
)
{
ULONG64 interfaceLinkSpeed = 0;
ULONG64 interfaceRcvSpeed = 0;
ULONG64 interfaceXmitSpeed = 0;
NDIS_STATISTICS_INFO interfaceStats = { 0 };
NDIS_MEDIA_CONNECT_STATE mediaState = MediaConnectStateUnknown;
HANDLE deviceHandle = NULL;
if (PhGetIntegerSetting(SETTING_NAME_ENABLE_NDIS))
{
// Create the handle to the network device
if (NT_SUCCESS(NetworkAdapterCreateHandle(&deviceHandle, Context->AdapterId.InterfaceGuid)))
{
if (!Context->CheckedDeviceSupport)
{
// Check the network adapter supports the OIDs we're going to be using.
if (NetworkAdapterQuerySupported(deviceHandle))
{
Context->DeviceSupported = TRUE;
}
Context->CheckedDeviceSupport = TRUE;
}
if (!Context->DeviceSupported)
{
// Device is faulty. Close the handle so we can fallback to GetIfEntry.
NtClose(deviceHandle);
deviceHandle = NULL;
}
}
}
if (deviceHandle)
{
NDIS_LINK_STATE interfaceState;
NetworkAdapterQueryStatistics(deviceHandle, &interfaceStats);
if (NT_SUCCESS(NetworkAdapterQueryLinkState(deviceHandle, &interfaceState)))
{
mediaState = interfaceState.MediaConnectState;
interfaceLinkSpeed = interfaceState.XmitLinkSpeed;
}
else
{
NetworkAdapterQueryLinkSpeed(deviceHandle, &interfaceLinkSpeed);
}
NtClose(deviceHandle);
}
else
{
if (WindowsVersion >= WINDOWS_VISTA && GetIfEntry2)
{
MIB_IF_ROW2 interfaceRow;
if (QueryInterfaceRowVista(&Context->AdapterId, &interfaceRow))
{
interfaceStats.ifInDiscards = interfaceRow.InDiscards;
interfaceStats.ifInErrors = interfaceRow.InErrors;
interfaceStats.ifHCInOctets = interfaceRow.InOctets;
interfaceStats.ifHCInUcastPkts = interfaceRow.InUcastPkts;
//interfaceStats.ifHCInMulticastPkts;
//interfaceStats.ifHCInBroadcastPkts;
interfaceStats.ifHCOutOctets = interfaceRow.OutOctets;
interfaceStats.ifHCOutUcastPkts = interfaceRow.OutUcastPkts;
//interfaceStats.ifHCOutMulticastPkts;
//interfaceStats.ifHCOutBroadcastPkts;
interfaceStats.ifOutErrors = interfaceRow.OutErrors;
interfaceStats.ifOutDiscards = interfaceRow.OutDiscards;
interfaceStats.ifHCInUcastOctets = interfaceRow.InUcastOctets;
interfaceStats.ifHCInMulticastOctets = interfaceRow.InMulticastOctets;
interfaceStats.ifHCInBroadcastOctets = interfaceRow.InBroadcastOctets;
interfaceStats.ifHCOutUcastOctets = interfaceRow.OutUcastOctets;
interfaceStats.ifHCOutMulticastOctets = interfaceRow.OutMulticastOctets;
interfaceStats.ifHCOutBroadcastOctets = interfaceRow.OutBroadcastOctets;
//interfaceRow.InNUcastPkts;
//interfaceRow.InUnknownProtos;
//interfaceRow.OutNUcastPkts;
//interfaceRow.OutQLen;
mediaState = interfaceRow.MediaConnectState;
interfaceLinkSpeed = interfaceRow.TransmitLinkSpeed;
}
}
else
{
MIB_IFROW interfaceRow;
if (QueryInterfaceRowXP(&Context->AdapterId, &interfaceRow))
{
interfaceStats.ifInDiscards = interfaceRow.dwInDiscards;
interfaceStats.ifInErrors = interfaceRow.dwInErrors;
interfaceStats.ifHCInOctets = interfaceRow.dwInOctets;
interfaceStats.ifHCInUcastPkts = interfaceRow.dwInUcastPkts;
//interfaceStats.ifHCInMulticastPkts;
//interfaceStats.ifHCInBroadcastPkts;
interfaceStats.ifHCOutOctets = interfaceRow.dwOutOctets;
interfaceStats.ifHCOutUcastPkts = interfaceRow.dwOutUcastPkts;
//interfaceStats.ifHCOutMulticastPkts;
//interfaceStats.ifHCOutBroadcastPkts;
interfaceStats.ifOutErrors = interfaceRow.dwOutErrors;
interfaceStats.ifOutDiscards = interfaceRow.dwOutDiscards;
//interfaceStats.ifHCInUcastOctets;
//interfaceStats.ifHCInMulticastOctets;
//interfaceStats.ifHCInBroadcastOctets;
//interfaceStats.ifHCOutUcastOctets;
//interfaceStats.ifHCOutMulticastOctets;
//interfaceStats.ifHCOutBroadcastOctets;
//interfaceRow.InNUcastPkts;
//interfaceRow.InUnknownProtos;
//interfaceRow.OutNUcastPkts;
//interfaceRow.OutQLen;
mediaState = interfaceRow.dwOperStatus == IF_OPER_STATUS_OPERATIONAL ? MediaConnectStateConnected : MediaConnectStateDisconnected;
interfaceLinkSpeed = interfaceRow.dwSpeed;
}
}
}
interfaceRcvSpeed = interfaceStats.ifHCInOctets - Context->LastDetailsInboundValue;
interfaceXmitSpeed = interfaceStats.ifHCOutOctets - Context->LastDetailsIOutboundValue;
//interfaceRcvUnicastSpeed = interfaceStats.ifHCInUcastOctets - Context->LastDetailsInboundUnicastValue;
//interfaceXmitUnicastSpeed = interfaceStats.ifHCOutUcastOctets - Context->LastDetailsIOutboundUnicastValue;
if (!Context->HaveFirstSample)
{
interfaceRcvSpeed = 0;
interfaceXmitSpeed = 0;
Context->HaveFirstSample = TRUE;
}
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_STATE, 1, mediaState == MediaConnectStateConnected ? L"Connected" : L"Disconnected");
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_LINKSPEED, 1, PhaFormatString(L"%s/s", PhaFormatSize(interfaceLinkSpeed / BITS_IN_ONE_BYTE, -1)->Buffer)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_SENT, 1, PhaFormatSize(interfaceStats.ifHCOutOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_RECEIVED, 1, PhaFormatSize(interfaceStats.ifHCInOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_TOTAL, 1, PhaFormatSize(interfaceStats.ifHCInOctets + interfaceStats.ifHCOutOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_SENDING, 1, interfaceXmitSpeed != 0 ? PhaFormatString(L"%s/s", PhaFormatSize(interfaceXmitSpeed, -1)->Buffer)->Buffer : L"");
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_RECEIVING, 1, interfaceRcvSpeed != 0 ? PhaFormatString(L"%s/s", PhaFormatSize(interfaceRcvSpeed, -1)->Buffer)->Buffer : L"");
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UTILIZATION, 1, PhaFormatString(L"%.2f%%", (FLOAT)(interfaceRcvSpeed + interfaceXmitSpeed) / (interfaceLinkSpeed / BITS_IN_ONE_BYTE) * 100)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_SENTPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCOutUcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_RECVPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInUcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_TOTALPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInUcastPkts + interfaceStats.ifHCOutUcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_SENT, 1, PhaFormatSize(interfaceStats.ifHCOutUcastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVED, 1, PhaFormatSize(interfaceStats.ifHCInUcastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_TOTAL, 1, PhaFormatSize(interfaceStats.ifHCInUcastOctets + interfaceStats.ifHCOutUcastOctets, -1)->Buffer);
//PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_SENDING, 1, interfaceXmitUnicastSpeed != 0 ? PhaFormatString(L"%s/s", PhaFormatSize(interfaceXmitUnicastSpeed, -1)->Buffer)->Buffer : L"");
//PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_RECEIVING, 1, interfaceRcvUnicastSpeed != 0 ? PhaFormatString(L"%s/s", PhaFormatSize(interfaceRcvUnicastSpeed, -1)->Buffer)->Buffer : L"");
//PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_UNICAST_UTILIZATION, 1, PhaFormatString(L"%.2f%%", utilization2)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_SENTPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCOutBroadcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_RECVPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInBroadcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_TOTALPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInBroadcastPkts + interfaceStats.ifHCOutBroadcastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_SENT, 1, PhaFormatSize(interfaceStats.ifHCOutBroadcastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_RECEIVED, 1, PhaFormatSize(interfaceStats.ifHCInBroadcastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_BROADCAST_TOTAL, 1, PhaFormatSize(interfaceStats.ifHCInBroadcastOctets + interfaceStats.ifHCOutBroadcastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_SENTPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCOutMulticastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_RECVPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInMulticastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_TOTALPKTS, 1, PhaFormatUInt64(interfaceStats.ifHCInMulticastPkts + interfaceStats.ifHCOutMulticastPkts, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_SENT, 1, PhaFormatSize(interfaceStats.ifHCOutMulticastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_RECEIVED, 1, PhaFormatSize(interfaceStats.ifHCInMulticastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_MULTICAST_TOTAL, 1, PhaFormatSize(interfaceStats.ifHCInMulticastOctets + interfaceStats.ifHCOutMulticastOctets, -1)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_SENTPKTS, 1, PhaFormatUInt64(interfaceStats.ifOutErrors, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_RECVPKTS, 1, PhaFormatUInt64(interfaceStats.ifInErrors, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_TOTALPKTS, 1, PhaFormatUInt64(interfaceStats.ifInErrors + interfaceStats.ifOutErrors, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_SENT, 1, PhaFormatUInt64(interfaceStats.ifOutDiscards, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_RECEIVED, 1, PhaFormatUInt64(interfaceStats.ifInDiscards, TRUE)->Buffer);
PhSetListViewSubItem(Context->ListViewHandle, NETADAPTER_DETAILS_INDEX_ERRORS_TOTAL, 1, PhaFormatUInt64(interfaceStats.ifInDiscards + interfaceStats.ifOutDiscards, TRUE)->Buffer);
Context->LastDetailsInboundValue = interfaceStats.ifHCInOctets;
Context->LastDetailsIOutboundValue = interfaceStats.ifHCOutOctets;
//Context->LastDetailsInboundUnicastValue = interfaceStats.ifHCInUcastOctets;
//Context->LastDetailsIOutboundUnicastValue = interfaceStats.ifHCOutUcastOctets;
}
INT_PTR CALLBACK NetAdapterDetailsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_NETADAPTER_DETAILS_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_NETADAPTER_DETAILS_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_NETADAPTER_DETAILS_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
RemoveProp(hwndDlg, L"Context");
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
context->WindowHandle = hwndDlg;
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_DETAILS_LIST);
if (context->AdapterName)
SetWindowText(hwndDlg, context->AdapterName->Buffer);
else
SetWindowText(hwndDlg, L"Unknown network adapter");
PhCenterWindow(hwndDlg, context->ParentHandle);
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
PhSetControlTheme(context->ListViewHandle, L"explorer");
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 315, L"Property");
PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Value");
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
NetAdapterAddListViewItemGroups(context->ListViewHandle);
PhRegisterCallback(
&PhProcessesUpdatedEvent,
NetAdapterProcessesUpdatedHandler,
context,
&context->ProcessesUpdatedRegistration
);
NetAdapterLookupConfig(context);
NetAdapterUpdateDetails(context);
if (WindowsVersion >= WINDOWS_VISTA && NotifyIpInterfaceChange)
{
NotifyIpInterfaceChange(
AF_UNSPEC,
NetAdapterChangeCallback,
context,
FALSE,
&context->NotifyHandle
);
}
}
break;
case WM_DESTROY:
{
PhUnregisterCallback(
&PhProcessesUpdatedEvent,
&context->ProcessesUpdatedRegistration
);
if (WindowsVersion >= WINDOWS_VISTA && CancelMibChangeNotify2 && context->NotifyHandle)
{
CancelMibChangeNotify2(context->NotifyHandle);
}
PhDeleteLayoutManager(&context->LayoutManager);
PostQuitMessage(0);
}
break;
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDCANCEL:
case IDOK:
DestroyWindow(hwndDlg);
break;
}
}
break;
case WM_SIZE:
{
PhLayoutManagerLayout(&context->LayoutManager);
}
break;
case WM_SHOWDIALOG:
{
if (IsMinimized(hwndDlg))
ShowWindow(hwndDlg, SW_RESTORE);
else
ShowWindow(hwndDlg, SW_SHOW);
SetForegroundWindow(hwndDlg);
}
break;
case UPDATE_MSG:
{
NetAdapterUpdateDetails(context);
}
break;
}
return FALSE;
}
VOID FreeNetAdapterDetailsContext(
_In_ PDV_NETADAPTER_DETAILS_CONTEXT Context
)
{
DeleteNetAdapterId(&Context->AdapterId);
PhClearReference(&Context->AdapterName);
PhFree(Context);
}
NTSTATUS ShowNetAdapterDetailsDialogThread(
_In_ PVOID Parameter
)
{
PDV_NETADAPTER_DETAILS_CONTEXT context = (PDV_NETADAPTER_DETAILS_CONTEXT)Parameter;
BOOL result;
MSG message;
HWND dialogHandle;
PH_AUTO_POOL autoPool;
PhInitializeAutoPool(&autoPool);
dialogHandle = CreateDialogParam(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_NETADAPTER_DETAILS),
NULL,
NetAdapterDetailsDlgProc,
(LPARAM)context
);
PostMessage(dialogHandle, WM_SHOWDIALOG, 0, 0);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(dialogHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
FreeNetAdapterDetailsContext(context);
return STATUS_SUCCESS;
}
VOID ShowNetAdapterDetailsDialog(
_In_ PDV_NETADAPTER_SYSINFO_CONTEXT Context
)
{
HANDLE dialogThread = NULL;
PDV_NETADAPTER_DETAILS_CONTEXT context;
context = PhAllocate(sizeof(DV_NETADAPTER_DETAILS_CONTEXT));
memset(context, 0, sizeof(DV_NETADAPTER_DETAILS_CONTEXT));
context->ParentHandle = Context->WindowHandle;
PhSetReference(&context->AdapterName, Context->AdapterEntry->AdapterName);
CopyNetAdapterId(&context->AdapterId, &Context->AdapterEntry->Id);
if (dialogThread = PhCreateThread(0, ShowNetAdapterDetailsDialogThread, context))
NtClose(dialogThread);
else
FreeNetAdapterDetailsContext(context);
}

View File

@@ -0,0 +1,549 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
VOID NetAdapterUpdateGraphs(
_Inout_ PDV_NETADAPTER_SYSINFO_CONTEXT Context
)
{
Context->GraphState.Valid = FALSE;
Context->GraphState.TooltipIndex = -1;
Graph_MoveGrid(Context->GraphHandle, 1);
Graph_Draw(Context->GraphHandle);
Graph_UpdateTooltip(Context->GraphHandle);
InvalidateRect(Context->GraphHandle, NULL, FALSE);
}
VOID NetAdapterUpdatePanel(
_Inout_ PDV_NETADAPTER_SYSINFO_CONTEXT Context
)
{
ULONG64 inOctets = 0;
ULONG64 outOctets = 0;
ULONG64 linkSpeed = 0;
NDIS_MEDIA_CONNECT_STATE mediaState = MediaConnectStateUnknown;
HANDLE deviceHandle = NULL;
if (PhGetIntegerSetting(SETTING_NAME_ENABLE_NDIS))
{
// Create the handle to the network device
if (NT_SUCCESS(NetworkAdapterCreateHandle(&deviceHandle, Context->AdapterEntry->Id.InterfaceGuid)))
{
if (!Context->AdapterEntry->CheckedDeviceSupport)
{
// Check the network adapter supports the OIDs we're going to be using.
if (NetworkAdapterQuerySupported(deviceHandle))
{
Context->AdapterEntry->DeviceSupported = TRUE;
}
Context->AdapterEntry->CheckedDeviceSupport = TRUE;
}
if (!Context->AdapterEntry->DeviceSupported)
{
// Device is faulty. Close the handle so we can fallback to GetIfEntry.
NtClose(deviceHandle);
deviceHandle = NULL;
}
}
}
if (deviceHandle)
{
NDIS_STATISTICS_INFO interfaceStats;
NDIS_LINK_STATE interfaceState;
if (NT_SUCCESS(NetworkAdapterQueryStatistics(deviceHandle, &interfaceStats)))
{
if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV))
inOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_RCV);
else
inOctets = interfaceStats.ifHCInOctets;
if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT))
outOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_XMIT);
else
outOctets = interfaceStats.ifHCOutOctets;
}
else
{
// Note: The above code fails for some drivers that don't implement statistics (even though statistics are mandatory).
// NDIS handles these two OIDs for all miniport drivers and we can use these for those special cases.
// https://msdn.microsoft.com/en-us/library/ff569443.aspx
inOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_RCV);
// https://msdn.microsoft.com/en-us/library/ff569445.aspx
outOctets = NetworkAdapterQueryValue(deviceHandle, OID_GEN_BYTES_XMIT);
}
if (NT_SUCCESS(NetworkAdapterQueryLinkState(deviceHandle, &interfaceState)))
{
mediaState = interfaceState.MediaConnectState;
linkSpeed = interfaceState.XmitLinkSpeed;
}
else
{
NetworkAdapterQueryLinkSpeed(deviceHandle, &linkSpeed);
}
NtClose(deviceHandle);
}
else if (WindowsVersion >= WINDOWS_VISTA && GetIfEntry2)
{
MIB_IF_ROW2 interfaceRow;
if (QueryInterfaceRowVista(&Context->AdapterEntry->Id, &interfaceRow))
{
inOctets = interfaceRow.InOctets;
outOctets = interfaceRow.OutOctets;
mediaState = interfaceRow.MediaConnectState;
linkSpeed = interfaceRow.TransmitLinkSpeed;
}
}
else
{
MIB_IFROW interfaceRow;
if (QueryInterfaceRowXP(&Context->AdapterEntry->Id, &interfaceRow))
{
inOctets = interfaceRow.dwInOctets;
outOctets = interfaceRow.dwOutOctets;
mediaState = interfaceRow.dwOperStatus == IF_OPER_STATUS_OPERATIONAL ? MediaConnectStateConnected : MediaConnectStateUnknown;
linkSpeed = interfaceRow.dwSpeed;
}
}
if (mediaState == MediaConnectStateConnected)
SetDlgItemText(Context->PanelWindowHandle, IDC_LINK_STATE, L"Connected");
else
SetDlgItemText(Context->PanelWindowHandle, IDC_LINK_STATE, L"Disconnected");
SetDlgItemText(Context->PanelWindowHandle, IDC_LINK_SPEED, PhaFormatString(L"%s/s", PhaFormatSize(linkSpeed / BITS_IN_ONE_BYTE, -1)->Buffer)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BSENT, PhaFormatSize(outOctets, -1)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BRECEIVED, PhaFormatSize(inOctets, -1)->Buffer);
SetDlgItemText(Context->PanelWindowHandle, IDC_STAT_BTOTAL, PhaFormatSize(inOctets + outOctets, -1)->Buffer);
}
VOID UpdateNetAdapterDialog(
_Inout_ PDV_NETADAPTER_SYSINFO_CONTEXT Context
)
{
if (Context->AdapterEntry->AdapterName)
SetDlgItemText(Context->WindowHandle, IDC_ADAPTERNAME, Context->AdapterEntry->AdapterName->Buffer);
else
SetDlgItemText(Context->WindowHandle, IDC_ADAPTERNAME, L"Unknown network adapter");
NetAdapterUpdateGraphs(Context);
NetAdapterUpdatePanel(Context);
}
INT_PTR CALLBACK NetAdapterPanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_NETADAPTER_SYSINFO_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_NETADAPTER_SYSINFO_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_NETADAPTER_SYSINFO_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_NCDESTROY)
{
RemoveProp(hwndDlg, L"Context");
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_DETAILS:
ShowNetAdapterDetailsDialog(context);
break;
}
}
break;
}
return FALSE;
}
INT_PTR CALLBACK NetAdapterDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_NETADAPTER_SYSINFO_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_NETADAPTER_SYSINFO_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_NETADAPTER_SYSINFO_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
PhDeleteLayoutManager(&context->LayoutManager);
PhDeleteGraphState(&context->GraphState);
if (context->GraphHandle)
DestroyWindow(context->GraphHandle);
if (context->PanelWindowHandle)
DestroyWindow(context->PanelWindowHandle);
RemoveProp(hwndDlg, L"Context");
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PPH_LAYOUT_ITEM graphItem;
PPH_LAYOUT_ITEM panelItem;
context->WindowHandle = hwndDlg;
PhInitializeGraphState(&context->GraphState);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ADAPTERNAME), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
graphItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
panelItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
SendMessage(GetDlgItem(hwndDlg, IDC_ADAPTERNAME), WM_SETFONT, (WPARAM)context->SysinfoSection->Parameters->LargeFont, FALSE);
if (context->AdapterEntry->AdapterName)
SetDlgItemText(hwndDlg, IDC_ADAPTERNAME, context->AdapterEntry->AdapterName->Buffer);
else
SetDlgItemText(hwndDlg, IDC_ADAPTERNAME, L"Unknown network adapter");
context->PanelWindowHandle = CreateDialogParam(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_NETADAPTER_PANEL), hwndDlg, NetAdapterPanelDialogProc, (LPARAM)context);
ShowWindow(context->PanelWindowHandle, SW_SHOW);
PhAddLayoutItemEx(&context->LayoutManager, context->PanelWindowHandle, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
// Create the graph control.
context->GraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
hwndDlg,
NULL,
NULL,
NULL
);
Graph_SetTooltip(context->GraphHandle, TRUE);
PhAddLayoutItemEx(&context->LayoutManager, context->GraphHandle, NULL, PH_ANCHOR_ALL, graphItem->Margin);
UpdateNetAdapterDialog(context);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_NOTIFY:
{
NMHDR* header = (NMHDR*)lParam;
if (header->hwndFrom == context->GraphHandle)
{
switch (header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2;
context->SysinfoSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
PhGraphStateGetDrawInfo(
&context->GraphState,
getDrawInfo,
context->AdapterEntry->InboundBuffer.Count
);
if (!context->GraphState.Valid)
{
ULONG i;
FLOAT max = 4 * 1024; // Minimum scaling 4KB
for (i = 0; i < drawInfo->LineDataCount; i++)
{
FLOAT data1;
FLOAT data2;
context->GraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->AdapterEntry->InboundBuffer, i);
context->GraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->AdapterEntry->OutboundBuffer, i);
if (max < data1 + data2)
max = data1 + data2;
}
if (max != 0)
{
// Scale the data.
PhDivideSinglesBySingle(
context->GraphState.Data1,
max,
drawInfo->LineDataCount
);
PhDivideSinglesBySingle(
context->GraphState.Data2,
max,
drawInfo->LineDataCount
);
}
drawInfo->LabelYFunction = PhSiSizeLabelYFunction;
drawInfo->LabelYFunctionParameter = max;
context->GraphState.Valid = TRUE;
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (context->GraphState.TooltipIndex != getTooltipText->Index)
{
ULONG64 adapterInboundValue = PhGetItemCircularBuffer_ULONG64(
&context->AdapterEntry->InboundBuffer,
getTooltipText->Index
);
ULONG64 adapterOutboundValue = PhGetItemCircularBuffer_ULONG64(
&context->AdapterEntry->OutboundBuffer,
getTooltipText->Index
);
PhMoveReference(&context->GraphState.TooltipText, PhFormatString(
L"R: %s\nS: %s\n%s",
PhaFormatSize(adapterInboundValue, -1)->Buffer,
PhaFormatSize(adapterOutboundValue, -1)->Buffer,
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
}
getTooltipText->Text = context->GraphState.TooltipText->sr;
}
}
break;
}
}
}
break;
case UPDATE_MSG:
{
UpdateNetAdapterDialog(context);
}
break;
}
return FALSE;
}
BOOLEAN NetAdapterSectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
)
{
PDV_NETADAPTER_SYSINFO_CONTEXT context = (PDV_NETADAPTER_SYSINFO_CONTEXT)Section->Context;
switch (Message)
{
case SysInfoCreate:
return TRUE;
case SysInfoDestroy:
{
PhDereferenceObject(context->AdapterEntry);
PhDereferenceObject(context->SectionName);
PhFree(context);
}
return TRUE;
case SysInfoTick:
{
if (context->WindowHandle)
PostMessage(context->WindowHandle, UPDATE_MSG, 0, 0);
}
return TRUE;
case SysInfoCreateDialog:
{
PPH_SYSINFO_CREATE_DIALOG createDialog = (PPH_SYSINFO_CREATE_DIALOG)Parameter1;
createDialog->Instance = PluginInstance->DllBase;
createDialog->Template = MAKEINTRESOURCE(IDD_NETADAPTER_DIALOG);
createDialog->DialogProc = NetAdapterDialogProc;
createDialog->Parameter = context;
}
return TRUE;
case SysInfoGraphGetDrawInfo:
{
PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)Parameter1;
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2;
Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, context->AdapterEntry->InboundBuffer.Count);
if (!Section->GraphState.Valid)
{
FLOAT max = 4 * 1024; // Minimum scaling 4KB
for (ULONG i = 0; i < drawInfo->LineDataCount; i++)
{
FLOAT data1;
FLOAT data2;
Section->GraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->AdapterEntry->InboundBuffer, i);
Section->GraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->AdapterEntry->OutboundBuffer, i);
if (max < data1 + data2)
max = data1 + data2;
}
if (max != 0)
{
// Scale the data.
PhDivideSinglesBySingle(
Section->GraphState.Data1,
max,
drawInfo->LineDataCount
);
PhDivideSinglesBySingle(
Section->GraphState.Data2,
max,
drawInfo->LineDataCount
);
}
drawInfo->LabelYFunction = PhSiSizeLabelYFunction;
drawInfo->LabelYFunctionParameter = max;
Section->GraphState.Valid = TRUE;
}
}
return TRUE;
case SysInfoGraphGetTooltipText:
{
PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = (PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT)Parameter1;
ULONG64 adapterInboundValue = PhGetItemCircularBuffer_ULONG64(
&context->AdapterEntry->InboundBuffer,
getTooltipText->Index
);
ULONG64 adapterOutboundValue = PhGetItemCircularBuffer_ULONG64(
&context->AdapterEntry->OutboundBuffer,
getTooltipText->Index
);
PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
L"R: %s\nS: %s\n%s",
PhaFormatSize(adapterInboundValue, -1)->Buffer,
PhaFormatSize(adapterOutboundValue, -1)->Buffer,
((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
getTooltipText->Text = Section->GraphState.TooltipText->sr;
}
return TRUE;
case SysInfoGraphDrawPanel:
{
PPH_SYSINFO_DRAW_PANEL drawPanel = (PPH_SYSINFO_DRAW_PANEL)Parameter1;
PhSetReference(&drawPanel->Title, context->AdapterEntry->AdapterName);
drawPanel->SubTitle = PhFormatString(
L"R: %s\nS: %s",
PhaFormatSize(context->AdapterEntry->InboundValue, -1)->Buffer,
PhaFormatSize(context->AdapterEntry->OutboundValue, -1)->Buffer
);
if (!drawPanel->Title)
drawPanel->Title = PhCreateString(L"Unknown network adapter");
}
return TRUE;
}
return FALSE;
}
VOID NetAdapterSysInfoInitializing(
_In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers,
_In_ _Assume_refs_(1) PDV_NETADAPTER_ENTRY AdapterEntry
)
{
PH_SYSINFO_SECTION section;
PDV_NETADAPTER_SYSINFO_CONTEXT context;
context = (PDV_NETADAPTER_SYSINFO_CONTEXT)PhAllocate(sizeof(DV_NETADAPTER_SYSINFO_CONTEXT));
memset(context, 0, sizeof(DV_NETADAPTER_SYSINFO_CONTEXT));
memset(&section, 0, sizeof(PH_SYSINFO_SECTION));
context->AdapterEntry = AdapterEntry;
context->SectionName = PhConcatStrings2(L"NetAdapter ", AdapterEntry->Id.InterfaceGuid->Buffer);
section.Context = context;
section.Callback = NetAdapterSectionCallback;
section.Name = context->SectionName->sr;
context->SysinfoSection = Pointers->CreateSection(&section);
}

View File

@@ -0,0 +1,736 @@
/*
* Process Hacker Plugins -
* Hardware Devices Plugin
*
* Copyright (C) 2015-2016 dmex
* Copyright (C) 2016 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define INITGUID
#include "devices.h"
#include <Setupapi.h>
#include <ndisguid.h>
#define ITEM_CHECKED (INDEXTOSTATEIMAGEMASK(2))
#define ITEM_UNCHECKED (INDEXTOSTATEIMAGEMASK(1))
typedef struct _NET_ENUM_ENTRY
{
BOOLEAN DevicePresent;
IF_LUID DeviceLuid;
PPH_STRING DeviceGuid;
PPH_STRING DeviceName;
} NET_ENUM_ENTRY, *PNET_ENUM_ENTRY;
static int __cdecl AdapterEntryCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
)
{
PNET_ENUM_ENTRY entry1 = *(PNET_ENUM_ENTRY *)elem1;
PNET_ENUM_ENTRY entry2 = *(PNET_ENUM_ENTRY *)elem2;
return uint64cmp(entry1->DeviceLuid.Value, entry2->DeviceLuid.Value);
}
VOID NetAdaptersLoadList(
VOID
)
{
PPH_STRING settingsString;
PH_STRINGREF remaining;
settingsString = PhaGetStringSetting(SETTING_NAME_INTERFACE_LIST);
remaining = settingsString->sr;
while (remaining.Length != 0)
{
ULONG64 ifindex;
ULONG64 luid64;
PH_STRINGREF part1;
PH_STRINGREF part2;
PH_STRINGREF part3;
IF_LUID ifLuid;
DV_NETADAPTER_ID id;
PDV_NETADAPTER_ENTRY entry;
if (remaining.Length == 0)
break;
PhSplitStringRefAtChar(&remaining, ',', &part1, &remaining);
PhSplitStringRefAtChar(&remaining, ',', &part2, &remaining);
PhSplitStringRefAtChar(&remaining, ',', &part3, &remaining);
PhStringToInteger64(&part1, 10, &ifindex);
PhStringToInteger64(&part2, 10, &luid64);
ifLuid.Value = luid64;
InitializeNetAdapterId(&id, (IF_INDEX)ifindex, ifLuid, PhCreateString2(&part3));
entry = CreateNetAdapterEntry(&id);
DeleteNetAdapterId(&id);
entry->UserReference = TRUE;
}
}
VOID NetAdaptersSaveList(
VOID
)
{
PH_STRING_BUILDER stringBuilder;
PPH_STRING settingsString;
PhInitializeStringBuilder(&stringBuilder, 260);
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!entry)
continue;
if (entry->UserReference)
{
PhAppendFormatStringBuilder(
&stringBuilder,
L"%lu,%I64u,%s,",
entry->Id.InterfaceIndex, // This value is UNSAFE and may change after reboot.
entry->Id.InterfaceLuid.Value, // This value is SAFE and does not change (Vista+).
entry->Id.InterfaceGuid->Buffer
);
}
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
if (stringBuilder.String->Length != 0)
PhRemoveEndStringBuilder(&stringBuilder, 1);
settingsString = PH_AUTO(PhFinalStringBuilderString(&stringBuilder));
PhSetStringSetting2(SETTING_NAME_INTERFACE_LIST, &settingsString->sr);
}
BOOLEAN FindAdapterEntry(
_In_ PDV_NETADAPTER_ID Id,
_In_ BOOLEAN RemoveUserReference
)
{
BOOLEAN found = FALSE;
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
PDV_NETADAPTER_ENTRY currentEntry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!currentEntry)
continue;
found = EquivalentNetAdapterId(&currentEntry->Id, Id);
if (found)
{
if (RemoveUserReference)
{
if (currentEntry->UserReference)
{
PhDereferenceObjectDeferDelete(currentEntry);
currentEntry->UserReference = FALSE;
}
}
PhDereferenceObjectDeferDelete(currentEntry);
break;
}
else
{
PhDereferenceObjectDeferDelete(currentEntry);
}
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
return found;
}
VOID AddNetworkAdapterToListView(
_In_ PDV_NETADAPTER_CONTEXT Context,
_In_ BOOLEAN AdapterPresent,
_In_ IF_INDEX IfIndex,
_In_ IF_LUID Luid,
_In_ PPH_STRING Guid,
_In_ PPH_STRING Description
)
{
DV_NETADAPTER_ID adapterId;
INT lvItemIndex;
BOOLEAN found = FALSE;
PDV_NETADAPTER_ID newId = NULL;
InitializeNetAdapterId(&adapterId, IfIndex, Luid, NULL);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!entry)
continue;
if (EquivalentNetAdapterId(&entry->Id, &adapterId))
{
newId = PhAllocate(sizeof(DV_NETADAPTER_ID));
CopyNetAdapterId(newId, &entry->Id);
if (entry->UserReference)
found = TRUE;
}
PhDereferenceObjectDeferDelete(entry);
if (newId)
break;
}
if (!newId)
{
newId = PhAllocate(sizeof(DV_NETADAPTER_ID));
CopyNetAdapterId(newId, &adapterId);
PhMoveReference(&newId->InterfaceGuid, Guid);
}
lvItemIndex = AddListViewItemGroupId(
Context->ListViewHandle,
AdapterPresent ? 0 : 1,
MAXINT,
Description->Buffer,
newId
);
if (found)
ListView_SetItemState(Context->ListViewHandle, lvItemIndex, ITEM_CHECKED, LVIS_STATEIMAGEMASK);
DeleteNetAdapterId(&adapterId);
}
VOID FreeListViewAdapterEntries(
_In_ PDV_NETADAPTER_CONTEXT Context
)
{
ULONG index = -1;
while ((index = PhFindListViewItemByFlags(
Context->ListViewHandle,
index,
LVNI_ALL
)) != -1)
{
PDV_NETADAPTER_ID param;
if (PhGetListViewItemParam(Context->ListViewHandle, index, &param))
{
DeleteNetAdapterId(param);
PhFree(param);
}
}
}
VOID FindNetworkAdapters(
_In_ PDV_NETADAPTER_CONTEXT Context
)
{
if (Context->UseAlternateMethod)
{
ULONG bufferLength = 0;
PVOID buffer = NULL;
ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
if (WindowsVersion >= WINDOWS_VISTA)
{
flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES;
}
if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &bufferLength) != ERROR_BUFFER_OVERFLOW)
return;
buffer = PhAllocate(bufferLength);
memset(buffer, 0, bufferLength);
if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, buffer, &bufferLength) == ERROR_SUCCESS)
{
Context->EnumeratingAdapters = TRUE;
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (PIP_ADAPTER_ADDRESSES i = buffer; i; i = i->Next)
{
PPH_STRING description;
if (description = PhCreateString(i->Description))
{
AddNetworkAdapterToListView(
Context,
TRUE,
i->IfIndex,
i->Luid,
PhConvertMultiByteToUtf16(i->AdapterName),
description
);
PhDereferenceObject(description);
}
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
Context->EnumeratingAdapters = FALSE;
}
PhFree(buffer);
}
else
{
PPH_LIST deviceList;
HDEVINFO deviceInfoHandle;
SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
if ((deviceInfoHandle = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_NET,
NULL,
NULL,
DIGCF_DEVICEINTERFACE
)) == INVALID_HANDLE_VALUE)
{
return;
}
deviceList = PH_AUTO(PhCreateList(1));
for (ULONG i = 0; SetupDiEnumDeviceInfo(deviceInfoHandle, i, &deviceInfoData); i++)
{
HANDLE keyHandle;
DEVPROPTYPE devicePropertyType;
WCHAR adapterDescription[MAX_PATH] = L"";
// DEVPKEY_Device_DeviceDesc doesn't give us the full adapter name.
// DEVPKEY_Device_FriendlyName does give us the full adapter name but is only
// supported on Windows 8 and above.
// We use our NetworkAdapterQueryName function to query the full adapter name
// from the NDIS driver directly, if that fails then we use one of the above properties.
if (!SetupDiGetDeviceProperty(
deviceInfoHandle,
&deviceInfoData,
WindowsVersion >= WINDOWS_8 ? &DEVPKEY_Device_FriendlyName : &DEVPKEY_Device_DeviceDesc,
&devicePropertyType,
(PBYTE)adapterDescription,
ARRAYSIZE(adapterDescription),
NULL,
0
))
{
continue;
}
if (keyHandle = SetupDiOpenDevRegKey(
deviceInfoHandle,
&deviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE
))
{
PNET_ENUM_ENTRY adapterEntry;
HANDLE deviceHandle;
adapterEntry = PhAllocate(sizeof(NET_ENUM_ENTRY));
memset(adapterEntry, 0, sizeof(NET_ENUM_ENTRY));
adapterEntry->DeviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId");
adapterEntry->DeviceLuid.Info.IfType = RegQueryUlong64(keyHandle, L"*IfType");
adapterEntry->DeviceLuid.Info.NetLuidIndex = RegQueryUlong64(keyHandle, L"NetLuidIndex");
if (NT_SUCCESS(NetworkAdapterCreateHandle(&deviceHandle, adapterEntry->DeviceGuid)))
{
PPH_STRING adapterName;
// Try query the full adapter name
if (adapterName = NetworkAdapterQueryName(deviceHandle, adapterEntry->DeviceGuid))
adapterEntry->DeviceName = adapterName;
adapterEntry->DevicePresent = TRUE;
NtClose(deviceHandle);
}
if (!adapterEntry->DeviceName)
adapterEntry->DeviceName = PhCreateString(adapterDescription);
PhAddItemList(deviceList, adapterEntry);
NtClose(keyHandle);
}
}
SetupDiDestroyDeviceInfoList(deviceInfoHandle);
// Sort the entries
qsort(deviceList->Items, deviceList->Count, sizeof(PVOID), AdapterEntryCompareFunction);
Context->EnumeratingAdapters = TRUE;
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < deviceList->Count; i++)
{
PNET_ENUM_ENTRY entry = deviceList->Items[i];
AddNetworkAdapterToListView(
Context,
entry->DevicePresent,
0,
entry->DeviceLuid,
entry->DeviceGuid,
entry->DeviceName
);
if (entry->DeviceName)
PhDereferenceObject(entry->DeviceName);
// Note: DeviceGuid is disposed by WM_DESTROY.
PhFree(entry);
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
Context->EnumeratingAdapters = FALSE;
}
// HACK: Show all unknown devices.
Context->EnumeratingAdapters = TRUE;
PhAcquireQueuedLockShared(&NetworkAdaptersListLock);
for (ULONG i = 0; i < NetworkAdaptersList->Count; i++)
{
ULONG index = -1;
BOOLEAN found = FALSE;
PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]);
if (!entry)
continue;
while ((index = PhFindListViewItemByFlags(
Context->ListViewHandle,
index,
LVNI_ALL
)) != -1)
{
PDV_NETADAPTER_ID param;
if (PhGetListViewItemParam(Context->ListViewHandle, index, &param))
{
if (EquivalentNetAdapterId(param, &entry->Id))
{
found = TRUE;
}
}
}
if (!found)
{
PPH_STRING description;
if (description = PhCreateString(L"Unknown network adapter"))
{
AddNetworkAdapterToListView(
Context,
FALSE,
entry->Id.InterfaceIndex,
entry->Id.InterfaceLuid,
entry->Id.InterfaceGuid,
description
);
PhDereferenceObject(description);
}
}
PhDereferenceObjectDeferDelete(entry);
}
PhReleaseQueuedLockShared(&NetworkAdaptersListLock);
Context->EnumeratingAdapters = FALSE;
}
PPH_STRING FindNetworkDeviceInstance(
_In_ PPH_STRING DevicePath
)
{
PPH_STRING deviceIdString = NULL;
HANDLE keyHandle;
HDEVINFO deviceInfoHandle;
SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
if ((deviceInfoHandle = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_NET,
NULL,
NULL,
DIGCF_DEVICEINTERFACE
)) == INVALID_HANDLE_VALUE)
{
return NULL;
}
for (ULONG i = 0; SetupDiEnumDeviceInfo(deviceInfoHandle, i, &deviceInfoData); i++)
{
if (keyHandle = SetupDiOpenDevRegKey(
deviceInfoHandle,
&deviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE
))
{
PPH_STRING deviceGuid;
if (deviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId"))
{
if (PhEqualString(deviceGuid, DevicePath, TRUE))
{
deviceIdString = PhCreateStringEx(NULL, 0x100);
SetupDiGetDeviceInstanceId(
deviceInfoHandle,
&deviceInfoData,
deviceIdString->Buffer,
(ULONG)deviceIdString->Length,
NULL
);
PhTrimToNullTerminatorString(deviceIdString);
}
PhDereferenceObject(deviceGuid);
}
NtClose(keyHandle);
}
}
SetupDiDestroyDeviceInfoList(deviceInfoHandle);
return deviceIdString;
}
//VOID LoadNetworkAdapterImages(
// _In_ PDV_NETADAPTER_CONTEXT Context
// )
//{
// HICON smallIcon = NULL;
//
// Context->ImageList = ImageList_Create(
// GetSystemMetrics(SM_CXSMICON),
// GetSystemMetrics(SM_CYSMICON),
// ILC_COLOR32,
// 1,
// 1
// );
//
// // We could use SetupDiLoadClassIcon but this works.
// // Copied from HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\\IconPath
// // The path and index hasn't changed since Win2k.
// ExtractIconEx(
// L"%SystemRoot%\\system32\\setupapi.dll",
// -5,
// NULL,
// &smallIcon,
// 1
// );
//
// if (smallIcon)
// {
// ImageList_AddIcon(Context->ImageList, smallIcon);
// DestroyIcon(smallIcon);
//
// // Set the imagelist only if the image was loaded.
// ListView_SetImageList(
// Context->ListViewHandle,
// Context->ImageList,
// LVSIL_SMALL
// );
// }
//}
INT_PTR CALLBACK NetworkAdapterOptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PDV_NETADAPTER_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PDV_NETADAPTER_CONTEXT)PhAllocate(sizeof(DV_NETADAPTER_CONTEXT));
memset(context, 0, sizeof(DV_NETADAPTER_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PDV_NETADAPTER_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
if (context->OptionsChanged)
NetAdaptersSaveList();
FreeListViewAdapterEntries(context);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_NETADAPTERS_LISTVIEW);
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
ListView_SetExtendedListViewStyleEx(context->ListViewHandle, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
PhSetControlTheme(context->ListViewHandle, L"explorer");
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 350, L"Network Adapters");
PhSetExtendedListView(context->ListViewHandle);
if (WindowsVersion >= WINDOWS_VISTA)
{
ListView_EnableGroupView(context->ListViewHandle, TRUE);
AddListViewGroup(context->ListViewHandle, 0, L"Connected");
AddListViewGroup(context->ListViewHandle, 1, L"Disconnected");
context->UseAlternateMethod = FALSE;
}
else
{
Button_Enable(GetDlgItem(hwndDlg, IDC_SHOW_HIDDEN_ADAPTERS), FALSE);
context->UseAlternateMethod = TRUE;
}
FindNetworkAdapters(context);
context->OptionsChanged = FALSE;
}
break;
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_SHOW_HIDDEN_ADAPTERS:
{
if (WindowsVersion >= WINDOWS_VISTA)
{
context->UseAlternateMethod = !context->UseAlternateMethod;
if (context->UseAlternateMethod)
{
ListView_EnableGroupView(context->ListViewHandle, FALSE);
}
else
{
ListView_EnableGroupView(context->ListViewHandle, TRUE);
}
}
FreeListViewAdapterEntries(context);
ListView_DeleteAllItems(context->ListViewHandle);
FindNetworkAdapters(context);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
if (header->code == LVN_ITEMCHANGED)
{
LPNM_LISTVIEW listView = (LPNM_LISTVIEW)lParam;
if (context->EnumeratingAdapters)
break;
if (listView->uChanged & LVIF_STATE)
{
switch (listView->uNewState & LVIS_STATEIMAGEMASK)
{
case 0x2000: // checked
{
PDV_NETADAPTER_ID param = (PDV_NETADAPTER_ID)listView->lParam;
if (!FindAdapterEntry(param, FALSE))
{
PDV_NETADAPTER_ENTRY entry;
entry = CreateNetAdapterEntry(param);
entry->UserReference = TRUE;
}
context->OptionsChanged = TRUE;
}
break;
case 0x1000: // unchecked
{
PDV_NETADAPTER_ID param = (PDV_NETADAPTER_ID)listView->lParam;
FindAdapterEntry(param, TRUE);
context->OptionsChanged = TRUE;
}
break;
}
}
}
else if (header->code == NM_RCLICK)
{
PDV_NETADAPTER_ENTRY param;
PPH_STRING deviceInstance;
if (param = PhGetSelectedListViewItemParam(context->ListViewHandle))
{
if (deviceInstance = FindNetworkDeviceInstance(param->Id.InterfaceGuid))
{
ShowDeviceMenu(hwndDlg, deviceInstance);
PhDereferenceObject(deviceInstance);
}
}
}
}
break;
}
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,429 @@
#pragma once
#include <pshpack8.h>
#ifdef __cplusplus
extern "C" {
#endif
#if (defined(WIN32) || defined(_WIN32)) && defined(_MSC_VER) && (_MSC_VER > 1399) && !defined(NVAPI_INTERNAL) && !defined(NVAPI_DEPRECATED_OLD)
#ifndef __nvapi_deprecated_function
#define __nvapi_deprecated_function(message) __declspec(deprecated(message))
#endif
#ifndef __nvapi_deprecated_datatype
#define __nvapi_deprecated_datatype(FirstRelease) __declspec(deprecated("Do not use this data type - it is deprecated in release " #FirstRelease "."))
#endif
#else
#ifndef __nvapi_deprecated_function
#define __nvapi_deprecated_function(message)
#endif
#ifndef __nvapi_deprecated_datatype
#define __nvapi_deprecated_datatype(FirstRelease)
#endif
#endif
/* 64-bit types for compilers that support them, plus some obsolete variants */
#if defined(__GNUC__) || defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(__ghs__) || defined(_WIN64)
typedef unsigned long long NvU64; /* 0 to 18446744073709551615 */
typedef long long NvS64; /* -9223372036854775808 to 9223372036854775807 */
#else
typedef unsigned __int64 NvU64; /* 0 to 18446744073709551615 */
typedef __int64 NvS64; /* -9223372036854775808 to 9223372036854775807 */
#endif
// mac os 32-bit still needs this
#if (defined(macintosh) || defined(__APPLE__)) && !defined(__LP64__)
typedef signed long NvS32; /* -2147483648 to 2147483647 */
#else
typedef signed int NvS32; /* -2147483648 to 2147483647 */
#endif
// mac os 32-bit still needs this
#if ( (defined(macintosh) && defined(__LP64__) && (__NVAPI_RESERVED0__)) || (!defined(macintosh) && defined(__NVAPI_RESERVED0__)) )
typedef unsigned int NvU32; /* 0 to 4294967295 */
#else
typedef unsigned long NvU32; /* 0 to 4294967295 */
#endif
typedef signed short NvS16;
typedef unsigned short NvU16;
typedef unsigned char NvU8;
typedef signed char NvS8;
typedef struct _NV_RECT
{
NvU32 left;
NvU32 top;
NvU32 right;
NvU32 bottom;
} NV_RECT;
#define NVAPI_INTERFACE extern __success(return == NVAPI_OK) NvAPI_Status __cdecl
#define NV_DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
//! \addtogroup nvapihandles
//! NVAPI Handles - These handles are retrieved from various calls and passed in to others in NvAPI
//! These are meant to be opaque types. Do not assume they correspond to indices, HDCs,
//! display indexes or anything else.
//!
//! Most handles remain valid until a display re-configuration (display mode set) or GPU
//! reconfiguration (going into or out of SLI modes) occurs. If NVAPI_HANDLE_INVALIDATED
//! is received by an app, it should discard all handles, and re-enumerate them.
//! @{
NV_DECLARE_HANDLE(NvDisplayHandle); //!< Display Device driven by NVIDIA GPU(s) (an attached display)
NV_DECLARE_HANDLE(NvMonitorHandle); //!< Monitor handle
NV_DECLARE_HANDLE(NvUnAttachedDisplayHandle); //!< Unattached Display Device driven by NVIDIA GPU(s)
NV_DECLARE_HANDLE(NvLogicalGpuHandle); //!< One or more physical GPUs acting in concert (SLI)
NV_DECLARE_HANDLE(NvPhysicalGpuHandle); //!< A single physical GPU
NV_DECLARE_HANDLE(NvEventHandle); //!< A handle to an event registration instance
NV_DECLARE_HANDLE(NvVisualComputingDeviceHandle); //!< A handle to a Visual Computing Device
NV_DECLARE_HANDLE(NvHICHandle); //!< A handle to a Host Interface Card
NV_DECLARE_HANDLE(NvGSyncDeviceHandle); //!< A handle to a Sync device
NV_DECLARE_HANDLE(NvVioHandle); //!< A handle to an SDI device
NV_DECLARE_HANDLE(NvTransitionHandle); //!< A handle to address a single transition request
NV_DECLARE_HANDLE(NvAudioHandle); //!< NVIDIA HD Audio Device
NV_DECLARE_HANDLE(Nv3DVPContextHandle); //!< A handle for a 3D Vision Pro (3DVP) context
NV_DECLARE_HANDLE(Nv3DVPTransceiverHandle); //!< A handle for a 3DVP RF transceiver
NV_DECLARE_HANDLE(Nv3DVPGlassesHandle); //!< A handle for a pair of 3DVP RF shutter glasses
NV_DECLARE_HANDLE(NvSourceHandle); //!< Unique source handle on the system
NV_DECLARE_HANDLE(NvTargetHandle); //!< Unique target handle on the system
//! @}
//! \ingroup nvapihandles
//! @{
#define NVAPI_DEFAULT_HANDLE 0
#define NV_BIT(x) (1 << (x))
//! @}
//! \addtogroup nvapitypes
//! @{
#define NVAPI_GENERIC_STRING_MAX 4096
#define NVAPI_LONG_STRING_MAX 256
#define NVAPI_SHORT_STRING_MAX 64
typedef struct _NvSBox
{
NvS32 sX;
NvS32 sY;
NvS32 sWidth;
NvS32 sHeight;
} NvSBox;
#ifndef NvGUID_Defined
#define NvGUID_Defined
typedef struct _NvGUID
{
NvU32 data1;
NvU16 data2;
NvU16 data3;
NvU8 data4[8];
} NvGUID, NvLUID;
#endif //#ifndef NvGUID_Defined
#define NVAPI_MAX_PHYSICAL_GPUS 64
#define NVAPI_MAX_PHYSICAL_BRIDGES 100
#define NVAPI_PHYSICAL_GPUS 32
#define NVAPI_MAX_LOGICAL_GPUS 64
#define NVAPI_MAX_AVAILABLE_GPU_TOPOLOGIES 256
#define NVAPI_MAX_AVAILABLE_SLI_GROUPS 256
#define NVAPI_MAX_GPU_TOPOLOGIES NVAPI_MAX_PHYSICAL_GPUS
#define NVAPI_MAX_GPU_PER_TOPOLOGY 8
#define NVAPI_MAX_DISPLAY_HEADS 2
#define NVAPI_ADVANCED_DISPLAY_HEADS 4
#define NVAPI_MAX_DISPLAYS NVAPI_PHYSICAL_GPUS * NVAPI_ADVANCED_DISPLAY_HEADS
#define NVAPI_MAX_ACPI_IDS 16
#define NVAPI_MAX_VIEW_MODES 8
#define NV_MAX_HEADS 4 //!< Maximum heads, each with NVAPI_DESKTOP_RES resolution
#define NVAPI_MAX_HEADS_PER_GPU 32
#define NV_MAX_HEADS 4 //!< Maximum number of heads, each with #NVAPI_DESKTOP_RES resolution
#define NV_MAX_VID_STREAMS 4 //!< Maximum number of input video streams, each with a #NVAPI_VIDEO_SRC_INFO
#define NV_MAX_VID_PROFILES 4 //!< Maximum number of output video profiles supported
#define NVAPI_SYSTEM_MAX_DISPLAYS NVAPI_MAX_PHYSICAL_GPUS * NV_MAX_HEADS
#define NVAPI_SYSTEM_MAX_HWBCS 128
#define NVAPI_SYSTEM_HWBC_INVALID_ID 0xffffffff
#define NVAPI_MAX_AUDIO_DEVICES 16
typedef char NvAPI_String[NVAPI_GENERIC_STRING_MAX];
typedef char NvAPI_LongString[NVAPI_LONG_STRING_MAX];
typedef char NvAPI_ShortString[NVAPI_SHORT_STRING_MAX];
//! @}
// =========================================================================================
//! NvAPI Version Definition \n
//! Maintain per structure specific version define using the MAKE_NVAPI_VERSION macro. \n
//! Usage: #define NV_GENLOCK_STATUS_VER MAKE_NVAPI_VERSION(NV_GENLOCK_STATUS, 1)
//! \ingroup nvapitypes
// =========================================================================================
#define MAKE_NVAPI_VERSION(typeName,ver) (NvU32)(sizeof(typeName) | ((ver) << 16))
//! \ingroup nvapitypes
#define GET_NVAPI_VERSION(ver) (NvU32)((ver)>>16)
//! \ingroup nvapitypes
#define GET_NVAPI_SIZE(ver) (NvU32)((ver) & 0xffff)
// ====================================================
//! NvAPI Status Values
//! All NvAPI functions return one of these codes.
//! \ingroup nvapistatus
// ====================================================
typedef enum _NvAPI_Status
{
NVAPI_OK = 0, //!< Success. Request is completed.
NVAPI_ERROR = -1, //!< Generic error
NVAPI_LIBRARY_NOT_FOUND = -2, //!< NVAPI support library cannot be loaded.
NVAPI_NO_IMPLEMENTATION = -3, //!< not implemented in current driver installation
NVAPI_API_NOT_INITIALIZED = -4, //!< NvAPI_Initialize has not been called (successfully)
NVAPI_INVALID_ARGUMENT = -5, //!< The argument/parameter value is not valid or NULL.
NVAPI_NVIDIA_DEVICE_NOT_FOUND = -6, //!< No NVIDIA display driver, or NVIDIA GPU driving a display, was found.
NVAPI_END_ENUMERATION = -7, //!< No more items to enumerate
NVAPI_INVALID_HANDLE = -8, //!< Invalid handle
NVAPI_INCOMPATIBLE_STRUCT_VERSION = -9, //!< An argument's structure version is not supported
NVAPI_HANDLE_INVALIDATED = -10, //!< The handle is no longer valid (likely due to GPU or display re-configuration)
NVAPI_OPENGL_CONTEXT_NOT_CURRENT = -11, //!< No NVIDIA OpenGL context is current (but needs to be)
NVAPI_INVALID_POINTER = -14, //!< An invalid pointer, usually NULL, was passed as a parameter
NVAPI_NO_GL_EXPERT = -12, //!< OpenGL Expert is not supported by the current drivers
NVAPI_INSTRUMENTATION_DISABLED = -13, //!< OpenGL Expert is supported, but driver instrumentation is currently disabled
NVAPI_NO_GL_NSIGHT = -15, //!< OpenGL does not support Nsight
NVAPI_EXPECTED_LOGICAL_GPU_HANDLE = -100, //!< Expected a logical GPU handle for one or more parameters
NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE = -101, //!< Expected a physical GPU handle for one or more parameters
NVAPI_EXPECTED_DISPLAY_HANDLE = -102, //!< Expected an NV display handle for one or more parameters
NVAPI_INVALID_COMBINATION = -103, //!< The combination of parameters is not valid.
NVAPI_NOT_SUPPORTED = -104, //!< Requested feature is not supported in the selected GPU
NVAPI_PORTID_NOT_FOUND = -105, //!< No port ID was found for the I2C transaction
NVAPI_EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106, //!< Expected an unattached display handle as one of the input parameters.
NVAPI_INVALID_PERF_LEVEL = -107, //!< Invalid perf level
NVAPI_DEVICE_BUSY = -108, //!< Device is busy; request not fulfilled
NVAPI_NV_PERSIST_FILE_NOT_FOUND = -109, //!< NV persist file is not found
NVAPI_PERSIST_DATA_NOT_FOUND = -110, //!< NV persist data is not found
NVAPI_EXPECTED_TV_DISPLAY = -111, //!< Expected a TV output display
NVAPI_EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112, //!< Expected a TV output on the D Connector - HDTV_EIAJ4120.
NVAPI_NO_ACTIVE_SLI_TOPOLOGY = -113, //!< SLI is not active on this device.
NVAPI_SLI_RENDERING_MODE_NOTALLOWED = -114, //!< Setup of SLI rendering mode is not possible right now.
NVAPI_EXPECTED_DIGITAL_FLAT_PANEL = -115, //!< Expected a digital flat panel.
NVAPI_ARGUMENT_EXCEED_MAX_SIZE = -116, //!< Argument exceeds the expected size.
NVAPI_DEVICE_SWITCHING_NOT_ALLOWED = -117, //!< Inhibit is ON due to one of the flags in NV_GPU_DISPLAY_CHANGE_INHIBIT or SLI active.
NVAPI_TESTING_CLOCKS_NOT_SUPPORTED = -118, //!< Testing of clocks is not supported.
NVAPI_UNKNOWN_UNDERSCAN_CONFIG = -119, //!< The specified underscan config is from an unknown source (e.g. INF)
NVAPI_TIMEOUT_RECONFIGURING_GPU_TOPO = -120, //!< Timeout while reconfiguring GPUs
NVAPI_DATA_NOT_FOUND = -121, //!< Requested data was not found
NVAPI_EXPECTED_ANALOG_DISPLAY = -122, //!< Expected an analog display
NVAPI_NO_VIDLINK = -123, //!< No SLI video bridge is present
NVAPI_REQUIRES_REBOOT = -124, //!< NVAPI requires a reboot for the settings to take effect
NVAPI_INVALID_HYBRID_MODE = -125, //!< The function is not supported with the current Hybrid mode.
NVAPI_MIXED_TARGET_TYPES = -126, //!< The target types are not all the same
NVAPI_SYSWOW64_NOT_SUPPORTED = -127, //!< The function is not supported from 32-bit on a 64-bit system.
NVAPI_IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128, //!< There is no implicit GPU topology active. Use NVAPI_SetHybridMode to change topology.
NVAPI_REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129, //!< Prompt the user to close all non-migratable applications.
NVAPI_OUT_OF_MEMORY = -130, //!< Could not allocate sufficient memory to complete the call.
NVAPI_WAS_STILL_DRAWING = -131, //!< The previous operation that is transferring information to or from this surface is incomplete.
NVAPI_FILE_NOT_FOUND = -132, //!< The file was not found.
NVAPI_TOO_MANY_UNIQUE_STATE_OBJECTS = -133, //!< There are too many unique instances of a particular type of state object.
NVAPI_INVALID_CALL = -134, //!< The method call is invalid. For example, a method's parameter may not be a valid pointer.
NVAPI_D3D10_1_LIBRARY_NOT_FOUND = -135, //!< d3d10_1.dll cannot be loaded.
NVAPI_FUNCTION_NOT_FOUND = -136, //!< Couldn't find the function in the loaded DLL.
NVAPI_INVALID_USER_PRIVILEGE = -137, //!< Current User is not Admin.
NVAPI_EXPECTED_NON_PRIMARY_DISPLAY_HANDLE = -138, //!< The handle corresponds to GDIPrimary.
NVAPI_EXPECTED_COMPUTE_GPU_HANDLE = -139, //!< Setting Physx GPU requires that the GPU is compute-capable.
NVAPI_STEREO_NOT_INITIALIZED = -140, //!< The Stereo part of NVAPI failed to initialize completely. Check if the stereo driver is installed.
NVAPI_STEREO_REGISTRY_ACCESS_FAILED = -141, //!< Access to stereo-related registry keys or values has failed.
NVAPI_STEREO_REGISTRY_PROFILE_TYPE_NOT_SUPPORTED = -142, //!< The given registry profile type is not supported.
NVAPI_STEREO_REGISTRY_VALUE_NOT_SUPPORTED = -143, //!< The given registry value is not supported.
NVAPI_STEREO_NOT_ENABLED = -144, //!< Stereo is not enabled and the function needed it to execute completely.
NVAPI_STEREO_NOT_TURNED_ON = -145, //!< Stereo is not turned on and the function needed it to execute completely.
NVAPI_STEREO_INVALID_DEVICE_INTERFACE = -146, //!< Invalid device interface.
NVAPI_STEREO_PARAMETER_OUT_OF_RANGE = -147, //!< Separation percentage or JPEG image capture quality is out of [0-100] range.
NVAPI_STEREO_FRUSTUM_ADJUST_MODE_NOT_SUPPORTED = -148, //!< The given frustum adjust mode is not supported.
NVAPI_TOPO_NOT_POSSIBLE = -149, //!< The mosaic topology is not possible given the current state of the hardware.
NVAPI_MODE_CHANGE_FAILED = -150, //!< An attempt to do a display resolution mode change has failed.
NVAPI_D3D11_LIBRARY_NOT_FOUND = -151, //!< d3d11.dll/d3d11_beta.dll cannot be loaded.
NVAPI_INVALID_ADDRESS = -152, //!< Address is outside of valid range.
NVAPI_STRING_TOO_SMALL = -153, //!< The pre-allocated string is too small to hold the result.
NVAPI_MATCHING_DEVICE_NOT_FOUND = -154, //!< The input does not match any of the available devices.
NVAPI_DRIVER_RUNNING = -155, //!< Driver is running.
NVAPI_DRIVER_NOTRUNNING = -156, //!< Driver is not running.
NVAPI_ERROR_DRIVER_RELOAD_REQUIRED = -157, //!< A driver reload is required to apply these settings.
NVAPI_SET_NOT_ALLOWED = -158, //!< Intended setting is not allowed.
NVAPI_ADVANCED_DISPLAY_TOPOLOGY_REQUIRED = -159, //!< Information can't be returned due to "advanced display topology".
NVAPI_SETTING_NOT_FOUND = -160, //!< Setting is not found.
NVAPI_SETTING_SIZE_TOO_LARGE = -161, //!< Setting size is too large.
NVAPI_TOO_MANY_SETTINGS_IN_PROFILE = -162, //!< There are too many settings for a profile.
NVAPI_PROFILE_NOT_FOUND = -163, //!< Profile is not found.
NVAPI_PROFILE_NAME_IN_USE = -164, //!< Profile name is duplicated.
NVAPI_PROFILE_NAME_EMPTY = -165, //!< Profile name is empty.
NVAPI_EXECUTABLE_NOT_FOUND = -166, //!< Application not found in the Profile.
NVAPI_EXECUTABLE_ALREADY_IN_USE = -167, //!< Application already exists in the other profile.
NVAPI_DATATYPE_MISMATCH = -168, //!< Data Type mismatch
NVAPI_PROFILE_REMOVED = -169, //!< The profile passed as parameter has been removed and is no longer valid.
NVAPI_UNREGISTERED_RESOURCE = -170, //!< An unregistered resource was passed as a parameter.
NVAPI_ID_OUT_OF_RANGE = -171, //!< The DisplayId corresponds to a display which is not within the normal outputId range.
NVAPI_DISPLAYCONFIG_VALIDATION_FAILED = -172, //!< Display topology is not valid so the driver cannot do a mode set on this configuration.
NVAPI_DPMST_CHANGED = -173, //!< Display Port Multi-Stream topology has been changed.
NVAPI_INSUFFICIENT_BUFFER = -174, //!< Input buffer is insufficient to hold the contents.
NVAPI_ACCESS_DENIED = -175, //!< No access to the caller.
NVAPI_MOSAIC_NOT_ACTIVE = -176, //!< The requested action cannot be performed without Mosaic being enabled.
NVAPI_SHARE_RESOURCE_RELOCATED = -177, //!< The surface is relocated away from video memory.
NVAPI_REQUEST_USER_TO_DISABLE_DWM = -178, //!< The user should disable DWM before calling NvAPI.
NVAPI_D3D_DEVICE_LOST = -179, //!< D3D device status is D3DERR_DEVICELOST or D3DERR_DEVICENOTRESET - the user has to reset the device.
NVAPI_INVALID_CONFIGURATION = -180, //!< The requested action cannot be performed in the current state.
NVAPI_STEREO_HANDSHAKE_NOT_DONE = -181, //!< Call failed as stereo handshake not completed.
NVAPI_EXECUTABLE_PATH_IS_AMBIGUOUS = -182, //!< The path provided was too short to determine the correct NVDRS_APPLICATION
NVAPI_DEFAULT_STEREO_PROFILE_IS_NOT_DEFINED = -183, //!< Default stereo profile is not currently defined
NVAPI_DEFAULT_STEREO_PROFILE_DOES_NOT_EXIST = -184, //!< Default stereo profile does not exist
NVAPI_CLUSTER_ALREADY_EXISTS = -185, //!< A cluster is already defined with the given configuration.
NVAPI_DPMST_DISPLAY_ID_EXPECTED = -186, //!< The input display id is not that of a multi stream enabled connector or a display device in a multi stream topology
NVAPI_INVALID_DISPLAY_ID = -187, //!< The input display id is not valid or the monitor associated to it does not support the current operation
NVAPI_STREAM_IS_OUT_OF_SYNC = -188, //!< While playing secure audio stream, stream goes out of sync
NVAPI_INCOMPATIBLE_AUDIO_DRIVER = -189, //!< Older audio driver version than required
NVAPI_VALUE_ALREADY_SET = -190, //!< Value already set, setting again not allowed.
NVAPI_TIMEOUT = -191, //!< Requested operation timed out
NVAPI_GPU_WORKSTATION_FEATURE_INCOMPLETE = -192, //!< The requested workstation feature set has incomplete driver internal allocation resources
NVAPI_STEREO_INIT_ACTIVATION_NOT_DONE = -193, //!< Call failed because InitActivation was not called.
NVAPI_SYNC_NOT_ACTIVE = -194, //!< The requested action cannot be performed without Sync being enabled.
NVAPI_SYNC_MASTER_NOT_FOUND = -195, //!< The requested action cannot be performed without Sync Master being enabled.
NVAPI_INVALID_SYNC_TOPOLOGY = -196, //!< Invalid displays passed in the NV_GSYNC_DISPLAY pointer.
NVAPI_ECID_SIGN_ALGO_UNSUPPORTED = -197, //!< The specified signing algorithm is not supported. Either an incorrect value was entered or the current installed driver/hardware does not support the input value.
NVAPI_ECID_KEY_VERIFICATION_FAILED = -198, //!< The encrypted public key verification has failed.
} NvAPI_Status;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_SYS_GetDriverAndBranchVersion
//
//! DESCRIPTION: This API returns display driver version and driver-branch string.
//!
//! SUPPORTED OS: Windows XP and higher
//!
//!
//! \param [out] pDriverVersion Contains the driver version after successful return.
//! \param [out] szBuildBranchString Contains the driver-branch string after successful return.
//!
//! \retval ::NVAPI_INVALID_ARGUMENT: either pDriverVersion is NULL or enum index too big
//! \retval ::NVAPI_OK - completed request
//! \retval ::NVAPI_API_NOT_INTIALIZED - NVAPI not initialized
//! \retval ::NVAPI_ERROR - miscellaneous error occurred
//!
//! \ingroup driverapi
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_SYS_GetDriverAndBranchVersion)(_Out_ NvU32* pDriverVersion, _Out_ NvAPI_ShortString szBuildBranchString);
_NvAPI_SYS_GetDriverAndBranchVersion NvAPI_SYS_GetDriverAndBranchVersion;
//! \ingroup driverapi
//! Used in NvAPI_GPU_GetMemoryInfo().
typedef struct _NV_DISPLAY_DRIVER_MEMORY_INFO_V1
{
NvU32 version; //!< Version info
NvU32 dedicatedVideoMemory; //!< Size(in kb) of the physical framebuffer.
NvU32 availableDedicatedVideoMemory; //!< Size(in kb) of the available physical framebuffer for allocating video memory surfaces.
NvU32 systemVideoMemory; //!< Size(in kb) of system memory the driver allocates at load time.
NvU32 sharedSystemMemory; //!< Size(in kb) of shared system memory that driver is allowed to commit for surfaces across all allocations.
} NV_DISPLAY_DRIVER_MEMORY_INFO_V1;
//! \ingroup driverapi
//! Used in NvAPI_GPU_GetMemoryInfo().
typedef struct _NV_DISPLAY_DRIVER_MEMORY_INFO_V2
{
NvU32 version; //!< Version info
NvU32 dedicatedVideoMemory; //!< Size(in kb) of the physical framebuffer.
NvU32 availableDedicatedVideoMemory; //!< Size(in kb) of the available physical framebuffer for allocating video memory surfaces.
NvU32 systemVideoMemory; //!< Size(in kb) of system memory the driver allocates at load time.
NvU32 sharedSystemMemory; //!< Size(in kb) of shared system memory that driver is allowed to commit for surfaces across all allocations.
NvU32 curAvailableDedicatedVideoMemory; //!< Size(in kb) of the current available physical framebuffer for allocating video memory surfaces.
} NV_DISPLAY_DRIVER_MEMORY_INFO_V2;
//! \ingroup driverapi
typedef NV_DISPLAY_DRIVER_MEMORY_INFO_V2 NV_DISPLAY_DRIVER_MEMORY_INFO;
//! \ingroup driverapi
//! Macro for constructing the version field of NV_DISPLAY_DRIVER_MEMORY_INFO_V1
#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER_1 MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_MEMORY_INFO_V1, 1)
//! \ingroup driverapi
//! Macro for constructing the version field of NV_DISPLAY_DRIVER_MEMORY_INFO_V2
#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER_2 MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_MEMORY_INFO_V2, 2)
//! \ingroup driverapi
#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER NV_DISPLAY_DRIVER_MEMORY_INFO_VER_2
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_GetMemoryInfo
//
//! DESCRIPTION: This function retrieves the available driver memory footprint for the specified GPU.
//!
//! SUPPORTED OS: Windows XP and higher
//!
//!
//! TCC_SUPPORTED
//!
//! \since Release: 177
//!
//! \param [in] hPhysicalGpu Handle of the physical GPU for which the memory information is to be extracted.
//! \param [out] pMemoryInfo The memory footprint available in the driver. See NV_DISPLAY_DRIVER_MEMORY_INFO.
//!
//! \retval NVAPI_INVALID_ARGUMENT pMemoryInfo is NULL.
//! \retval NVAPI_OK Call successful.
//! \retval NVAPI_NVIDIA_DEVICE_NOT_FOUND No NVIDIA GPU driving a display was found.
//! \retval NVAPI_INCOMPATIBLE_STRUCT_VERSION NV_DISPLAY_DRIVER_MEMORY_INFO structure version mismatch.
//!
//! \ingroup driverapi
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetMemoryInfo)(NvDisplayHandle hNvDisplay, NV_DISPLAY_DRIVER_MEMORY_INFO *pMemoryInfo);
_NvAPI_GPU_GetMemoryInfo NvAPI_GPU_GetMemoryInfo;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_EnumPhysicalGPUs
//
//! This function returns an array of physical GPU handles.
//! Each handle represents a physical GPU present in the system.
//! That GPU may be part of an SLI configuration, or may not be visible to the OS directly.
//!
//! At least one GPU must be present in the system and running an NVIDIA display driver.
//!
//! The array nvGPUHandle will be filled with physical GPU handle values. The returned
//! gpuCount determines how many entries in the array are valid.
//!
//! \note In drivers older than 105.00, all physical GPU handles get invalidated on a
//! modeset. So the calling applications need to renum the handles after every modeset.\n
//! With drivers 105.00 and up, all physical GPU handles are constant.
//! Physical GPU handles are constant as long as the GPUs are not physically moved and
//! the SBIOS VGA order is unchanged.
//!
//! For GPU handles in TCC MODE please use NvAPI_EnumTCCPhysicalGPUs()
//!
//! SUPPORTED OS: Windows XP and higher, Mac OS X
//!
//!
//! \par Introduced in
//! \since Release: 80
//!
//! \retval NVAPI_INVALID_ARGUMENT nvGPUHandle or pGpuCount is NULL
//! \retval NVAPI_OK One or more handles were returned
//! \retval NVAPI_NVIDIA_DEVICE_NOT_FOUND No NVIDIA GPU driving a display was found
//! \ingroup gpu
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_EnumPhysicalGPUs)(NvPhysicalGpuHandle nvGPUHandle[NVAPI_MAX_PHYSICAL_GPUS], NvU32* pGpuCount);
_NvAPI_EnumPhysicalGPUs NvAPI_EnumPhysicalGPUs;
#ifdef __cplusplus
}
#endif
#include <poppack.h>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,617 @@
/*
* Process Hacker Extra Plugins -
* Nvidia GPU Plugin
*
* Copyright (C) 2015-2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "devices.h"
#include <pshpack8.h>
// These structures and types have been gathered from nvapi leaks and symbols, as well as reverse engineering and guessing.
// rev
#define NVAPI_MAX_USAGES_PER_GPU 0x21
#define NVAPI_MAX_CLOCKS_PER_GPU 0x120
#define NVAPI_MAX_COOLERS_PER_GPU 0x3
#define NVAPI_MIN_COOLER_LEVEL 0x0
#define NVAPI_MAX_COOLER_LEVEL 0x64
#define NVAPI_MAX_COOLER_LEVELS 0x18
#define NVAPI_MAX_PROCESSES 0x80
// rev
typedef PVOID (__cdecl *_NvAPI_QueryInterface)(_In_ NvU32 FunctionOffset);
_NvAPI_QueryInterface NvAPI_QueryInterface;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetShaderPipeCount)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pShaderPipeCount);
_NvAPI_GPU_GetShaderPipeCount NvAPI_GPU_GetShaderPipeCount;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetShaderSubPipeCount)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pShaderSubPipeCount);
_NvAPI_GPU_GetShaderSubPipeCount NvAPI_GPU_GetShaderSubPipeCount;
// rev
typedef enum _NV_RAM_TYPE
{
NV_RAM_TYPE_NONE,
NV_RAM_TYPE_SDRAM,
NV_RAM_TYPE_DDR1,
NV_RAM_TYPE_DDR2,
NV_RAM_TYPE_GDDR2,
NV_RAM_TYPE_GDDR3,
NV_RAM_TYPE_GDDR4,
NV_RAM_TYPE_DDR3,
NV_RAM_TYPE_GDDR5,
NV_RAM_TYPE_LPDDR2
} NV_RAM_TYPE;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetRamType)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NV_RAM_TYPE* pRamType);
_NvAPI_GPU_GetRamType NvAPI_GPU_GetRamType;
// rev
typedef enum _NV_RAM_MAKER
{
NV_RAM_MAKER_NONE,
NV_RAM_MAKER_SAMSUNG,
NV_RAM_MAKER_QIMONDA,
NV_RAM_MAKER_ELPIDA,
NV_RAM_MAKER_ETRON,
NV_RAM_MAKER_NANYA,
NV_RAM_MAKER_HYNIX,
NV_RAM_MAKER_MOSEL,
NV_RAM_MAKER_WINBOND,
NV_RAM_MAKER_ELITE,
NV_RAM_MAKER_MICRON
} NV_RAM_MAKER;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetRamType)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NV_RAM_MAKER* pRamMaker);
_NvAPI_GPU_GetRamType NvAPI_GPU_GetRamMaker;
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_GetRamBusWidth)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pRamBusWidth);
_NvAPI_GPU_GetRamBusWidth NvAPI_GPU_GetRamBusWidth;
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_GetRamBankCount)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pRamBankCount);
_NvAPI_GPU_GetRamBankCount NvAPI_GPU_GetRamBankCount;
typedef enum _NV_FOUNDRY
{
NV_FOUNDRY_NONE,
NV_FOUNDRY_TSMC,
NV_FOUNDRY_UMC,
NV_FOUNDRY_IBM,
NV_FOUNDRY_SMIC,
NV_FOUNDRY_CSM,
NV_FOUNDRY_TOSHIBA
} NV_FOUNDRY;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetFoundry)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NV_FOUNDRY* pFoundry);
_NvAPI_GPU_GetFoundry NvAPI_GPU_GetFoundry;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetFBWidthAndLocation)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pWidth, NvU32* pLocation);
_NvAPI_GPU_GetFBWidthAndLocation NvAPI_GPU_GetFBWidthAndLocation;
// rev (This has a different offset than the NvAPI_GPU_GetMemoryInfo function despite both returning the same struct).
typedef NvAPI_Status (__cdecl *_NvAPI_GetDisplayDriverMemoryInfo)(_In_ NvDisplayHandle NvDispHandle, _Inout_ NV_DISPLAY_DRIVER_MEMORY_INFO* pMemoryInfo);
_NvAPI_GetDisplayDriverMemoryInfo NvAPI_GetDisplayDriverMemoryInfo;
// rev
typedef enum _NV_COOLER_TYPE
{
NVAPI_COOLER_TYPE_NONE = 0,
NVAPI_COOLER_TYPE_FAN,
NVAPI_COOLER_TYPE_WATER,
NVAPI_COOLER_TYPE_LIQUID_NO2,
} NV_COOLER_TYPE;
// rev
typedef enum _NV_COOLER_CONTROLLER
{
NVAPI_COOLER_CONTROLLER_NONE = 0,
NVAPI_COOLER_CONTROLLER_ADI,
NVAPI_COOLER_CONTROLLER_INTERNAL,
} NV_COOLER_CONTROLLER;
// rev
typedef enum _NV_COOLER_POLICY
{
NVAPI_COOLER_POLICY_NONE = 0,
NVAPI_COOLER_POLICY_MANUAL, // Manual adjustment of cooler level. Gets applied right away independent of temperature or performance level.
NVAPI_COOLER_POLICY_PERF, // GPU performance controls the cooler level.
NVAPI_COOLER_POLICY_TEMPERATURE_DISCRETE = 4, // Discrete thermal levels control the cooler level.
NVAPI_COOLER_POLICY_TEMPERATURE_CONTINUOUS = 8, // Cooler level adjusted at continuous thermal levels.
NVAPI_COOLER_POLICY_HYBRID, // Hybrid of performance and temperature levels.
} NV_COOLER_POLICY;
// rev
typedef enum _NV_COOLER_TARGET
{
NVAPI_COOLER_TARGET_NONE = 0,
NVAPI_COOLER_TARGET_GPU,
NVAPI_COOLER_TARGET_MEMORY,
NVAPI_COOLER_TARGET_POWER_SUPPLY = 4,
NVAPI_COOLER_TARGET_ALL = 7 // This cooler cools all of the components related to its target gpu.
} NV_COOLER_TARGET;
// rev
typedef enum _NV_COOLER_CONTROL
{
NVAPI_COOLER_CONTROL_NONE = 0,
NVAPI_COOLER_CONTROL_TOGGLE, // ON/OFF
NVAPI_COOLER_CONTROL_VARIABLE, // Suppports variable control.
} NV_COOLER_CONTROL;
// rev
typedef enum _NV_COOLER_ACTIVITY_LEVEL
{
NVAPI_INACTIVE = 0, // inactive or unsupported
NVAPI_ACTIVE = 1, // active and spinning in case of fan
} NV_COOLER_ACTIVITY_LEVEL;
// rev
typedef struct _NV_GPU_COOLER_SETTINGS
{
NvU32 version; // structure version
NvU32 count; // number of associated coolers with the selected GPU
struct
{
NV_COOLER_TYPE type; // type of cooler - FAN, WATER, LIQUID_NO2...
NV_COOLER_CONTROLLER controller; // internal, ADI...
NvU32 defaultMinLevel; // the min default value % of the cooler
NvU32 defaultMaxLevel; // the max default value % of the cooler
NvU32 currentMinLevel; // the current allowed min value % of the cooler
NvU32 currentMaxLevel; // the current allowed max value % of the cooler
NvU32 currentLevel; // the current value % of the cooler
NV_COOLER_POLICY defaultPolicy; // cooler control policy - auto-perf, auto-thermal, manual, hybrid...
NV_COOLER_POLICY currentPolicy; // cooler control policy - auto-perf, auto-thermal, manual, hybrid...
NV_COOLER_TARGET target; // cooling target - GPU, memory, chipset, powersupply, canoas...
NV_COOLER_CONTROL controlType; // toggle or variable
NV_COOLER_ACTIVITY_LEVEL active; // is the cooler active - fan spinning...
} cooler[NVAPI_MAX_COOLERS_PER_GPU];
} NV_GPU_COOLER_SETTINGS, *PNV_GPU_COOLER_SETTINGS;
#define NV_GPU_COOLER_SETTINGS_VER MAKE_NVAPI_VERSION(NV_GPU_COOLER_SETTINGS, 1)
// rev
typedef struct _NV_GPU_SETCOOLER_LEVEL
{
NvU32 version; //structure version
struct
{
NvU32 currentLevel; // the new value % of the cooler
NV_COOLER_POLICY currentPolicy; // the new cooler control policy - auto-perf, auto-thermal, manual, hybrid...
} cooler[NVAPI_MAX_COOLERS_PER_GPU];
} NV_GPU_SETCOOLER_LEVEL;
#define NV_GPU_SETCOOLER_LEVEL_VER MAKE_NVAPI_VERSION(NV_GPU_SETCOOLER_LEVEL, 1)
// rev
typedef struct _NV_GPU_COOLER_POLICY_TABLE
{
NvU32 version; //structure version
NV_COOLER_POLICY policy; //selected policy to update the cooler levels for, example NVAPI_COOLER_POLICY_PERF
struct
{
NvU32 levelId; // level indicator for a policy
NvU32 currentLevel; // new cooler level for the selected policy level indicator.
NvU32 defaultLevel; // default cooler level for the selected policy level indicator.
} policyCoolerLevel[NVAPI_MAX_COOLER_LEVELS];
} NV_GPU_COOLER_POLICY_TABLE;
#define NV_GPU_COOLER_POLICY_TABLE_VER MAKE_NVAPI_VERSION(NV_GPU_COOLER_POLICY_TABLE, 1)
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_GetCoolerSettings
//
// DESCRIPTION: Retrieves the cooler information of all coolers or a specific cooler associated with the selected GPU.
// Coolers are indexed 0 to NVAPI_MAX_COOLERS_PER_GPU-1.
// To retrieve specific cooler info set the coolerIndex to the appropriate cooler index.
// To retrieve info for all cooler set coolerIndex to NVAPI_COOLER_TARGET_ALL.
//
// PARAMETERS : hPhysicalGPU(IN) - GPU selection.
// coolerIndex(IN) - Explict cooler index selection.
// pCoolerInfo(OUT) - Array of cooler settings.
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetCoolerSettings)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 coolerIndex, NV_GPU_COOLER_SETTINGS* pCoolerInfo);
_NvAPI_GPU_GetCoolerSettings NvAPI_GPU_GetCoolerSettings;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_SetCoolerLevels
//
// DESCRIPTION: Set the cooler levels for all coolers or a specific cooler associated with the selected GPU.
// Coolers are indexed 0 to NVAPI_MAX_COOLERS_PER_GPU-1. Every cooler level with non-zero currentpolicy gets applied.
// The new level should be in the range of minlevel and maxlevel retrieved from GetCoolerSettings API or between
// and NVAPI_MIN_COOLER_LEVEL to MAX_COOLER_LEVEL.
// To set level for a specific cooler set the coolerIndex to the appropriate cooler index.
// To set level for all coolers set coolerIndex to NVAPI_COOLER_TARGET_ALL.
// NOTE: To lock the fan speed independent of the temperature or performance changes set the cooler currentPolicy to
// NVAPI_COOLER_POLICY_MANUAL else set it to the current policy retrieved from the GetCoolerSettings API.
// PARAMETERS: hPhysicalGPU(IN) - GPU selection.
// coolerIndex(IN) - Explict cooler index selection.
// pCoolerLevels(IN) - Updated cooler level and cooler policy.
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_SetCoolerLevels)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 coolerIndex, NV_GPU_SETCOOLER_LEVEL *pCoolerLevels);
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_RestoreCoolerSettings
//
// DESCRIPTION: Restore the modified cooler settings to NVIDIA defaults.
//
// PARAMETERS: hPhysicalGPU(IN) - GPU selection.
// pCoolerIndex(IN) - Array containing absolute cooler indexes to restore. Pass NULL restore all coolers.
// CoolerCount - Number of coolers to restore.
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_RestoreCoolerSettings)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 *pCoolerIndex, NvU32 coolerCount);
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_GetCoolerPolicyTable
//
// DESCRIPTION: Retrieves the table of cooler and policy levels for the selected policy. Supported only for NVAPI_COOLER_POLICY_PERF.
//
// PARAMETERS: hPhysicalGPU(IN) - GPU selection.
// coolerIndex(IN) - cooler index selection.
// pCoolerTable(OUT) - Table of policy levels and associated cooler levels.
// count(OUT) - Count of the number of valid levels for the selected policy.
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetCoolerPolicyTable)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 coolerIndex, NV_GPU_COOLER_POLICY_TABLE *pCoolerTable, NvU32 *count);
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_SetCoolerPolicyTable
//
// DESCRIPTION: Restore the modified cooler settings to NVIDIA defaults. Supported only for NVAPI_COOLER_POLICY_PERF.
//
// PARAMETERS: hPhysicalGPU(IN) - GPU selection.
// coolerIndex(IN) - cooler index selection.
// pCoolerTable(IN) - Updated table of policy levels and associated cooler levels. Every non-zero policy level gets updated.
// count(IN) - Number of valid levels in the policy table.
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_SetCoolerPolicyTable)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 coolerIndex, NV_GPU_COOLER_POLICY_TABLE *pCoolerTable, NvU32 count);
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION NAME: NvAPI_GPU_RestoreCoolerPolicyTable
//
// DESCRIPTION: Restores the perf table policy levels to the defaults.
//
// PARAMETERS: hPhysicalGPU(IN) - GPU selection.
// coolerIndex(IN) - cooler index selection.
// pCoolerIndex(IN) - Array containing absolute cooler indexes to restore. Pass NULL restore all coolers.
// coolerCount - Number of coolers to restore.
// policy - restore for the selected policy
//
///////////////////////////////////////////////////////////////////////////////
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_RestoreCoolerPolicyTable)(_In_ NvPhysicalGpuHandle hPhysicalGpu, NvU32 *pCoolerIndex, NvU32 coolerCount, NV_COOLER_POLICY policy);
// rev - NvAPI_GPU_GetUsages
typedef struct _NV_USAGES_INFO
{
NvU32 version; //!< Structure version
NvU32 usages[NVAPI_MAX_USAGES_PER_GPU];
} NV_USAGES_INFO;
#define NV_USAGES_INFO_VER MAKE_NVAPI_VERSION(NV_USAGES_INFO, 1)
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetUsages)(_In_ NvPhysicalGpuHandle hPhysicalGpu, _Inout_ NV_USAGES_INFO* pUsagesInfo);
_NvAPI_GPU_GetUsages NvAPI_GPU_GetUsages;
// rev - NvAPI_GPU_GetAllClocks
typedef struct _NV_CLOCKS_INFO
{
NvU32 version; //!< Structure version
NvU32 clocks[NVAPI_MAX_CLOCKS_PER_GPU];
} NV_CLOCKS_INFO;
#define NV_CLOCKS_INFO_VER MAKE_NVAPI_VERSION(NV_CLOCKS_INFO, 2)
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetAllClocks)(_In_ NvPhysicalGpuHandle hPhysicalGpu, _Inout_ NV_CLOCKS_INFO* pClocksInfo);
_NvAPI_GPU_GetAllClocks NvAPI_GPU_GetAllClocks;
// rev - NvAPI_GPU_GetVoltageDomainsStatus
typedef struct _NV_VOLTAGE_DOMAINS
{
NvU32 version; //!< Structure version
NvU32 flags; //!< Reserved for future use. Must be set to 0
NvU32 max;
struct
{
NV_GPU_PERF_VOLTAGE_INFO_DOMAIN_ID domainId; //!< ID of the voltage domain
NvU32 mvolt; //!< Voltage in mV
} domain[NVAPI_MAX_GPU_PERF_VOLTAGES];
} NV_VOLTAGE_DOMAINS;
#define NV_VOLTAGE_DOMAIN_INFO_VER MAKE_NVAPI_VERSION(NV_VOLTAGE_DOMAINS, 1)
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_GetVoltageDomainsStatus)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_VOLTAGE_DOMAINS* pVoltageDomainsStatus);
_NvAPI_GPU_GetVoltageDomainsStatus NvAPI_GPU_GetVoltageDomainsStatus;
// rev - NvAPI_GPU_GetVoltages
typedef struct _NV_VOLTAGES_INFO
{
NV_GPU_PERF_VOLTAGE_INFO_DOMAIN_ID domainId; //!< ID of the voltage domain
NvU32 unknown1;
NvU32 max;
struct
{
NvU32 unknown2;
NvU32 mvolt; //!< Voltage in mV
} info[128];
} NV_VOLTAGES_INFO;
// rev
typedef struct _NV_VOLTAGES
{
NvU32 version; //!< Structure version
NvU32 flags; //!< Reserved for future use. Must be set to 0
NvU32 max;
NV_VOLTAGES_INFO voltages[NVAPI_MAX_GPU_PERF_VOLTAGES];
} NV_VOLTAGES;
#define NV_VOLTAGES_INFO_VER MAKE_NVAPI_VERSION(NV_VOLTAGES, 1)
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_GetVoltages)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_VOLTAGES* pPerfVoltages);
_NvAPI_GPU_GetVoltages NvAPI_GPU_GetVoltages;
// rev - NvAPI_GPU_GetPerfClocks
typedef struct _NV_PERF_CLOCKS_UNKNOWN_2
{
NvU32 unknown1;
NvU32 unknown2;
NvU32 unknown3;
NvU32 unknown4;
NvU32 unknown5;
NvU32 unknown6;
NvU32 unknown7;
} NV_PERF_CLOCKS_UNKNOWN_2;
// rev
typedef struct _NV_PERF_CLOCKS_UNKNOWN_1
{
NvU32 unknown1;
NvU32 unknown2;
NV_PERF_CLOCKS_UNKNOWN_2 unknown3[32];
} NV_PERF_CLOCKS_UNKNOWN_1;
// rev
typedef struct _NV_PERF_CLOCKS
{
NvU32 version; //!< Structure version
NvU32 unknown1;
NvU32 unknown2;
NvU32 unknown3;
NvU32 unknown4;
NV_PERF_CLOCKS_UNKNOWN_1 unknown5[12];
} NV_PERF_CLOCKS;
#define NV_PERF_CLOCKS_INFO_VER MAKE_NVAPI_VERSION(NV_PERF_CLOCKS, 1)
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_GetPerfClocks)(_In_ NvPhysicalGpuHandle hPhysicalGPU, INT i, _Inout_ NV_PERF_CLOCKS* pPerfClocks);
_NvAPI_GPU_GetPerfClocks NvAPI_GPU_GetPerfClocks;
// rev - NvAPI_GPU_QueryActiveApps
typedef struct _NV_ACTIVE_APP
{
NvU32 version; //!< Structure version
NvU32 processPID;
NvAPI_LongString processName;
} NV_ACTIVE_APP;
#define NV_ACTIVE_APPS_INFO_VER MAKE_NVAPI_VERSION(NV_ACTIVE_APP, 2)
// rev
typedef NvAPI_Status(__cdecl *_NvAPI_GPU_QueryActiveApps)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_ACTIVE_APP pActiveApps[NVAPI_MAX_PROCESSES], _Inout_ NvU32* pTotal);
_NvAPI_GPU_QueryActiveApps NvAPI_GPU_QueryActiveApps;
// rev - NvAPI_GPU_GetPowerMizerInfo
typedef enum _PowerSourceInfo
{
PowerSourceInfo_Unknown1 = 1,
PowerSourceInfo_Unknown2,
PowerSourceInfo_Unknown3 = 8738
} PowerSourceInfo;
// rev
typedef enum _SelectSource
{
SelectSource_Unknown1 = 1,
SelectSource_Unknown2,
SelectSource_Unknown3
} SelectSource;
// rev
typedef enum _LevelInfo
{
LevelInfo_Unknown1 = 1,
LevelInfo_Unknown2,
LevelInfo_Unknown3,
LevelInfo_Unknown4,
LevelInfo_Unknown5,
LevelInfo_Unknown6,
LevelInfo_Unknown7
} LevelInfo;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetPowerMizerInfo)(_In_ NvPhysicalGpuHandle hPhysicalGPU, PowerSourceInfo powerSourceInfo, SelectSource select, LevelInfo* pLevelInfo);
_NvAPI_GPU_GetPowerMizerInfo NvAPI_GPU_GetPowerMizerInfo;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GetDisplayDriverRegistryPath)(_In_ NvDisplayHandle hNvDisplay, _Inout_ NvAPI_LongString szDriverRegistryPath);
_NvAPI_GetDisplayDriverRegistryPath NvAPI_GetDisplayDriverRegistryPath;
// rev
//typedef NvAPI_Status (__cdecl *_NvAPI_RestartDisplayDriver)(_In_ NvU32 NvDriverIndex);
//_NvAPI_RestartDisplayDriver NvAPI_RestartDisplayDriver;
typedef enum _NV_POWER_TOPOLOGY_FLAGS
{
NV_POWER_TOPOLOGY_FLAG_DISABLED, // Unsure if name is correct
NV_POWER_TOPOLOGY_FLAG_ENABLED // Unsure if name is correct
} NV_POWER_TOPOLOGY_FLAGS;
typedef struct _NV_POWER_TOPOLOGY_1
{
NvU32 unknown1;
NvU32 unknown2;
NvU32 unknown3;
// return this.unknown1 & 1u;
// return (this.unknown1 & 4294967294u) / 2u;
} NV_POWER_TOPOLOGY_1;
typedef struct _NV_POWER_TOPOLOGY_2
{
NV_POWER_TOPOLOGY_FLAGS flags;
NV_POWER_TOPOLOGY_1 unknown;
} NV_POWER_TOPOLOGY_2;
typedef struct _NV_POWER_TOPOLOGY_STATUS
{
NvU32 version; //!< Structure version
NvU32 count;
NV_POWER_TOPOLOGY_2 unknown[4];
} NV_POWER_TOPOLOGY_STATUS;
#define NV_POWER_TOPOLOGY_STATUS_VER MAKE_NVAPI_VERSION(NV_POWER_TOPOLOGY_STATUS, 1)
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_ClientPowerTopologyGetStatus)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_POWER_TOPOLOGY_STATUS* pClientPowerTopologyStatus);
_NvAPI_GPU_ClientPowerTopologyGetStatus NvAPI_GPU_ClientPowerTopologyGetStatus;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetShortName)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NvAPI_ShortString szName);
_NvAPI_GPU_GetShortName NvAPI_GPU_GetShortName;
// rev
typedef struct _NV_ARCH_INFO
{
NvU32 version; //!< Structure version
NvU32 unknown[3];
} NV_ARCH_INFO;
#define NV_ARCH_INFO_VER MAKE_NVAPI_VERSION(NV_ARCH_INFO, 2)
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetArchInfo)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_ARCH_INFO* pArchInfo);
_NvAPI_GPU_GetArchInfo NvAPI_GPU_GetArchInfo;
// rev
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetPartitionCount)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Out_ NvU32* pCount);
_NvAPI_GPU_GetPartitionCount NvAPI_GPU_GetPartitionCount;
typedef struct _NV_PCIE_INFO_UNKNOWN
{
NvU32 unknown0;
NvU32 unknown1;
NvU32 unknown2;
NvU32 unknown3;
NvU32 unknown4;
NvU32 unknown5;
NvU32 unknown6;
NvU32 unknown7;
} NV_PCIE_INFO_UNKNOWN;
typedef struct _NV_PCIE_INFO
{
NvU32 version; //!< Structure version
NV_PCIE_INFO_UNKNOWN info[5];
} NV_PCIE_INFO;
#define NV_PCIE_INFO_VER MAKE_NVAPI_VERSION(NV_PCIE_INFO, 2)
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetPCIEInfo)(_In_ NvPhysicalGpuHandle hPhysicalGPU, _Inout_ NV_PCIE_INFO* pPciInfo);
_NvAPI_GPU_GetPCIEInfo NvAPI_GPU_GetPCIEInfo;
typedef NvAPI_Status (__cdecl *_NvAPI_GetDisplayDriverBuildTitle)(_In_ NvDisplayHandle hNvDisplay, NvAPI_ShortString pDriverBuildTitle);
_NvAPI_GetDisplayDriverBuildTitle NvAPI_GetDisplayDriverBuildTitle;
typedef NvAPI_Status (__cdecl *_NvAPI_GetDisplayDriverCompileType)(_In_ NvDisplayHandle hNvDisplay, NvU32* pDriverCompileType);
_NvAPI_GetDisplayDriverCompileType NvAPI_GetDisplayDriverCompileType;
typedef NvAPI_Status (__cdecl *_NvAPI_GetDisplayDriverSecurityLevel)(_In_ NvDisplayHandle hNvDisplay, NvU32* pDriverSecurityLevel);
_NvAPI_GetDisplayDriverSecurityLevel NvAPI_GetDisplayDriverSecurityLevel;
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetVPECount)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pVPECount);
_NvAPI_GPU_GetVPECount NvAPI_GPU_GetVPECount;
//typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetExtendedMinorRevision)(_In_ NvPhysicalGpuHandle hPhysicalGPU, NvU32* pRamBankCount);
//typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetSerialNumber)(_In_ NvPhysicalGpuHandle hPhysicalGPU, PBYTE pRamBankCount);
typedef NvAPI_Status (__cdecl *_NvAPI_GPU_GetTargetID)(_In_ NvPhysicalGpuHandle hPhysicalGPU, PBYTE pRamBankCount);
_NvAPI_GPU_GetTargetID NvAPI_GPU_GetTargetID;
#include <poppack.h>

View File

@@ -0,0 +1,61 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by HardwareDevices.rc
//
#define IDD_NETADAPTER_OPTIONS 101
#define IDD_NETADAPTER_DIALOG 102
#define IDD_NETADAPTER_PANEL 104
#define IDD_NETADAPTER_DETAILS 105
#define IDD_DISKDRIVE_DETAILS_FILESYSTEM 109
#define IDD_DISKDRIVE_DETAILS_GENERAL 111
#define IDD_GPU_DIALOG 1077
#define IDD_DISKDRIVE_OPTIONS 1013
#define IDD_DISKDRIVE_DIALOG 1014
#define IDD_DISKDRIVE_PANEL 1016
#define IDD_DISKDRIVE_DETAILS_SMART 1017
#define IDC_GRAPH_LAYOUT 103
#define IDC_NETADAPTERS_LISTVIEW 1001
#define IDC_LINK_SPEED 1002
#define IDC_ADAPTERNAME 1003
#define IDC_LAYOUT 1004
#define IDC_LINK_STATE 1005
#define IDC_STAT_BSENT 1006
#define IDC_STAT_BRECEIVED 1007
#define IDC_STAT_BTOTAL 1008
#define IDC_DETAILS 1010
#define IDC_DETAILS_LIST 1011
#define IDC_SHOW_HIDDEN_ADAPTERS 1012
#define IDC_EDIT1 1015
#define IDC_DISKDRIVE_LISTVIEW 1017
#define IDC_DESCRIPTION 1017
#define IDC_DISKMOUNTPATH 1018
#define IDC_TITLE 1019
#define IDC_STAT_BREAD 1020
#define IDC_STAT_BWRITE 1021
#define IDC_STAT_ACTIVE 1023
#define IDC_STAT_RESPONSETIME 1024
#define IDC_STAT_QUEUELENGTH 1025
#define IDC_DISKNAME 1076
#define IDC_GPUNAME 1078
#define IDC_GPU_L 1079
#define IDC_MEMORY_L 1080
#define IDC_SHARED_L 1081
#define IDC_BUS_L 1082
#define IDD_GPU_PANEL 1083
#define IDC_CLOCK_CORE 211
#define IDC_CLOCK_MEMORY 212
#define IDC_FAN_PERCENT 213
#define IDC_TEMP_VALUE 214
#define IDC_CLOCK_SHADER 215
#define IDC_VOLTAGE 217
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_SYMED_VALUE 106
#endif
#endif

File diff suppressed because it is too large Load Diff