add plugins-extra
This commit is contained in:
2
plugins-extra/PoolMonPlugin/CHANGELOG.txt
Normal file
2
plugins-extra/PoolMonPlugin/CHANGELOG.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
1.0
|
||||
* Initial release
|
||||
164
plugins-extra/PoolMonPlugin/PoolMonPlugin.rc
Normal file
164
plugins-extra/PoolMonPlugin/PoolMonPlugin.rc
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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,0,0,0
|
||||
PRODUCTVERSION 1,0,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", "NT Pool Table plugin for Process Hacker"
|
||||
VALUE "FileVersion", "1.0"
|
||||
VALUE "InternalName", "dmex.PoolMonPlugin"
|
||||
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
|
||||
VALUE "OriginalFilename", "PoolMonPlugin.dll"
|
||||
VALUE "ProductName", "NT Pool Table plugin for Process Hacker"
|
||||
VALUE "ProductVersion", "1.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0xc09, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_POOL DIALOGEX 0, 0, 641, 383
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "Pool Table"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_POOLTREE,"PhTreeNew",WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP | 0xa,4,3,633,353,WS_EX_CLIENTEDGE
|
||||
EDITTEXT IDC_SEARCH,4,362,169,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Clear",IDC_CLEAR,180,362,50,14
|
||||
DEFPUSHBUTTON "Close",IDCANCEL,587,362,50,14
|
||||
END
|
||||
|
||||
IDD_BIGPOOL DIALOGEX 0, 0, 469, 273
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CAPTION "Large Pool Allocations"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Close",IDCANCEL,413,252,50,14
|
||||
CONTROL "",IDC_BIGPOOLLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,455,243
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_POOL, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 637
|
||||
TOPMARGIN, 3
|
||||
BOTTOMMARGIN, 376
|
||||
END
|
||||
|
||||
IDD_BIGPOOL, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 462
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 266
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AFX_DIALOG_LAYOUT
|
||||
//
|
||||
|
||||
IDD_POOL AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
IDD_BIGPOOL AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TXT
|
||||
//
|
||||
|
||||
IDR_TXT_POOLTAGS TXT "resources\\pooltag.txt"
|
||||
|
||||
#endif // English (Australia) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
117
plugins-extra/PoolMonPlugin/PoolMonPlugin.vcxproj
Normal file
117
plugins-extra/PoolMonPlugin/PoolMonPlugin.vcxproj
Normal file
@@ -0,0 +1,117 @@
|
||||
<?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>{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}</ProjectGuid>
|
||||
<RootNamespace>PoolMonPlugin</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectName>PoolMonPlugin</ProjectName>
|
||||
<WindowsTargetPlatformVersion>10.0.14393.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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\ExtraPlugins.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\ExtraPlugins.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\ExtraPlugins.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\ExtraPlugins.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_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="db.c" />
|
||||
<ClCompile Include="dialogpool.c" />
|
||||
<ClCompile Include="dialogbigpool.c" />
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="pooltable.c" />
|
||||
<ClCompile Include="treepool.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PoolMonPlugin.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CHANGELOG.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="resources\pooltag.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
55
plugins-extra/PoolMonPlugin/PoolMonPlugin.vcxproj.filters
Normal file
55
plugins-extra/PoolMonPlugin/PoolMonPlugin.vcxproj.filters
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CHANGELOG.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{802108be-ae96-47c3-8d93-884ed6dd096a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{3e65ffb8-3f3e-40d7-b3ca-d55cae8edb16}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{b98dd849-bbfe-4b41-8c48-f65680da5c00}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="db.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="treepool.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pooltable.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dialogpool.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dialogbigpool.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="PoolMonPlugin.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="resources\pooltag.txt">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
329
plugins-extra/PoolMonPlugin/db.c
Normal file
329
plugins-extra/PoolMonPlugin/db.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
PPH_STRING TrimString(
|
||||
_In_ PPH_STRING String
|
||||
)
|
||||
{
|
||||
static PH_STRINGREF whitespace = PH_STRINGREF_INIT(L" \t");
|
||||
PH_STRINGREF sr = String->sr;
|
||||
PhTrimStringRef(&sr, &whitespace, 0);
|
||||
return PhCreateString2(&sr);
|
||||
}
|
||||
|
||||
PPH_STRING FindPoolTagFilePath(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
ULONG Folder;
|
||||
PWSTR AppendPath;
|
||||
} locations[] =
|
||||
{
|
||||
#ifdef _WIN64
|
||||
{ CSIDL_PROGRAM_FILESX86, L"\\Windows Kits\\10\\Debuggers\\x64\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILESX86, L"\\Windows Kits\\8.1\\Debuggers\\x64\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILESX86, L"\\Windows Kits\\8.0\\Debuggers\\x64\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILES, L"\\Debugging Tools for Windows (x64)\\triage\\pooltag.txt" }
|
||||
#else
|
||||
{ CSIDL_PROGRAM_FILES, L"\\Windows Kits\\10\\Debuggers\\x86\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILES, L"\\Windows Kits\\8.1\\Debuggers\\x86\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILES, L"\\Windows Kits\\8.0\\Debuggers\\x86\\triage\\pooltag.txt" },
|
||||
{ CSIDL_PROGRAM_FILES, L"\\Debugging Tools for Windows (x86)\\triage\\pooltag.txt" }
|
||||
#endif
|
||||
};
|
||||
|
||||
PPH_STRING path;
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < sizeof(locations) / sizeof(locations[0]); i++)
|
||||
{
|
||||
path = PhGetKnownLocation(locations[i].Folder, locations[i].AppendPath);
|
||||
|
||||
if (path)
|
||||
{
|
||||
if (RtlDoesFileExists_U(path->Buffer))
|
||||
return path;
|
||||
|
||||
PhDereferenceObject(path);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN PmPoolTagListHashtableEqualFunction(
|
||||
_In_ PVOID Entry1,
|
||||
_In_ PVOID Entry2
|
||||
)
|
||||
{
|
||||
PPOOL_TAG_LIST_ENTRY poolTagNode1 = *(PPOOL_TAG_LIST_ENTRY *)Entry1;
|
||||
PPOOL_TAG_LIST_ENTRY poolTagNode2 = *(PPOOL_TAG_LIST_ENTRY *)Entry2;
|
||||
|
||||
return poolTagNode1->TagUlong == poolTagNode2->TagUlong;
|
||||
}
|
||||
|
||||
ULONG PmPoolTagListHashtableHashFunction(
|
||||
_In_ PVOID Entry
|
||||
)
|
||||
{
|
||||
return (*(PPOOL_TAG_LIST_ENTRY*)Entry)->TagUlong;
|
||||
}
|
||||
|
||||
PPOOL_TAG_LIST_ENTRY FindPoolTagListEntry(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ ULONG PoolTag
|
||||
)
|
||||
{
|
||||
POOL_TAG_LIST_ENTRY lookupWindowNode;
|
||||
PPOOL_TAG_LIST_ENTRY lookupWindowNodePtr = &lookupWindowNode;
|
||||
PPOOL_TAG_LIST_ENTRY *windowNode;
|
||||
|
||||
lookupWindowNode.TagUlong = PoolTag;
|
||||
|
||||
windowNode = (PPOOL_TAG_LIST_ENTRY*)PhFindEntryHashtable(
|
||||
Context->PoolTagDbHashtable,
|
||||
&lookupWindowNodePtr
|
||||
);
|
||||
|
||||
if (windowNode)
|
||||
return *windowNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID LoadPoolTagDatabase(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
static PH_STRINGREF skipPoolTagFileHeader = PH_STRINGREF_INIT(L"\r\n\r\n");
|
||||
static PH_STRINGREF skipPoolTagFileLine = PH_STRINGREF_INIT(L"\r\n");
|
||||
|
||||
PPH_STRING poolTagFilePath;
|
||||
HANDLE fileHandle = NULL;
|
||||
LARGE_INTEGER fileSize;
|
||||
ULONG stringBufferLength;
|
||||
PSTR stringBuffer;
|
||||
PPH_STRING utf16StringBuffer = NULL;
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
Context->PoolTagDbList = PhCreateList(100);
|
||||
Context->PoolTagDbHashtable = PhCreateHashtable(
|
||||
sizeof(PPOOL_TAG_LIST_ENTRY),
|
||||
PmPoolTagListHashtableEqualFunction,
|
||||
PmPoolTagListHashtableHashFunction,
|
||||
100
|
||||
);
|
||||
|
||||
if (poolTagFilePath = FindPoolTagFilePath())
|
||||
{
|
||||
if (!NT_SUCCESS(PhCreateFileWin32(
|
||||
&fileHandle,
|
||||
poolTagFilePath->Buffer,
|
||||
FILE_GENERIC_READ,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
||||
)))
|
||||
{
|
||||
PhDereferenceObject(poolTagFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)))
|
||||
{
|
||||
NtClose(fileHandle);
|
||||
PhDereferenceObject(poolTagFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileSize.QuadPart == 0)
|
||||
{
|
||||
NtClose(fileHandle);
|
||||
PhDereferenceObject(poolTagFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
stringBufferLength = (ULONG)fileSize.QuadPart + 1;
|
||||
stringBuffer = PhAllocate(stringBufferLength);
|
||||
memset(stringBuffer, 0, stringBufferLength);
|
||||
|
||||
if (NT_SUCCESS(NtReadFile(
|
||||
fileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&isb,
|
||||
stringBuffer,
|
||||
(ULONG)fileSize.QuadPart,
|
||||
NULL,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
utf16StringBuffer = PhZeroExtendToUtf16(stringBuffer);
|
||||
}
|
||||
|
||||
PhFree(stringBuffer);
|
||||
NtClose(fileHandle);
|
||||
PhDereferenceObject(poolTagFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
HRSRC resourceHandle;
|
||||
|
||||
// Find the resource
|
||||
if (resourceHandle = FindResource(
|
||||
PluginInstance->DllBase,
|
||||
MAKEINTRESOURCE(IDR_TXT_POOLTAGS),
|
||||
L"TXT")
|
||||
)
|
||||
{
|
||||
ULONG resourceLength;
|
||||
HGLOBAL resourceBuffer;
|
||||
PSTR utf16Buffer;
|
||||
|
||||
// Get the resource length
|
||||
resourceLength = SizeofResource(PluginInstance->DllBase, resourceHandle);
|
||||
|
||||
// Load the resource
|
||||
if (resourceBuffer = LoadResource(PluginInstance->DllBase, resourceHandle))
|
||||
{
|
||||
utf16Buffer = (PSTR)LockResource(resourceBuffer);
|
||||
|
||||
utf16StringBuffer = PhZeroExtendToUtf16Ex(utf16Buffer, resourceLength);
|
||||
}
|
||||
|
||||
FreeResource(resourceBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (utf16StringBuffer)
|
||||
{
|
||||
PH_STRINGREF firstPart;
|
||||
PH_STRINGREF remainingPart;
|
||||
PH_STRINGREF poolTagPart;
|
||||
PH_STRINGREF binaryNamePart;
|
||||
PH_STRINGREF descriptionPart;
|
||||
|
||||
remainingPart = utf16StringBuffer->sr;
|
||||
|
||||
PhSplitStringRefAtString(&remainingPart, &skipPoolTagFileHeader, TRUE, &firstPart, &remainingPart);
|
||||
|
||||
while (remainingPart.Length != 0)
|
||||
{
|
||||
PhSplitStringRefAtString(&remainingPart, &skipPoolTagFileLine, TRUE, &firstPart, &remainingPart);
|
||||
|
||||
if (firstPart.Length != 0)
|
||||
{
|
||||
PPOOL_TAG_LIST_ENTRY entry;
|
||||
PPH_STRING poolTagString;
|
||||
PPH_STRING poolTag;
|
||||
PPH_STRING binaryName;
|
||||
PPH_STRING description;
|
||||
|
||||
if (!PhSplitStringRefAtChar(&firstPart, '-', &poolTagPart, &firstPart))
|
||||
continue;
|
||||
if (!PhSplitStringRefAtChar(&firstPart, '-', &binaryNamePart, &firstPart))
|
||||
continue;
|
||||
// Note: Some entries don't have descriptions
|
||||
PhSplitStringRefAtChar(&firstPart, '-', &descriptionPart, &firstPart);
|
||||
|
||||
poolTag = PhCreateString2(&poolTagPart);
|
||||
binaryName = PhCreateString2(&binaryNamePart);
|
||||
description = PhCreateString2(&descriptionPart);
|
||||
|
||||
entry = PhAllocate(sizeof(POOL_TAG_LIST_ENTRY));
|
||||
memset(entry, 0, sizeof(POOL_TAG_LIST_ENTRY));
|
||||
|
||||
// Strip leading/trailing space characters.
|
||||
poolTagString = TrimString(poolTag);
|
||||
entry->BinaryNameString = TrimString(binaryName);
|
||||
entry->DescriptionString = TrimString(description);
|
||||
|
||||
// Convert the poolTagString to ULONG
|
||||
PhConvertUtf16ToUtf8Buffer(
|
||||
entry->Tag,
|
||||
sizeof(entry->Tag),
|
||||
NULL,
|
||||
poolTagString->Buffer,
|
||||
poolTagString->Length
|
||||
);
|
||||
|
||||
PhAddEntryHashtable(Context->PoolTagDbHashtable, &entry);
|
||||
PhAddItemList(Context->PoolTagDbList, entry);
|
||||
|
||||
PhDereferenceObject(description);
|
||||
PhDereferenceObject(binaryName);
|
||||
PhDereferenceObject(poolTag);
|
||||
PhDereferenceObject(poolTagString);
|
||||
}
|
||||
}
|
||||
|
||||
PhDereferenceObject(utf16StringBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
VOID FreePoolTagDatabase(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
for (ULONG i = 0; i < Context->PoolTagDbList->Count; i++)
|
||||
{
|
||||
PPOOL_TAG_LIST_ENTRY entry = Context->PoolTagDbList->Items[i];
|
||||
|
||||
PhDereferenceObject(entry->DescriptionString);
|
||||
PhDereferenceObject(entry->BinaryNameString);
|
||||
PhFree(entry);
|
||||
}
|
||||
|
||||
PhClearHashtable(Context->PoolTagDbHashtable);
|
||||
PhClearList(Context->PoolTagDbList);
|
||||
}
|
||||
|
||||
VOID UpdatePoolTagBinaryName(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOL_ITEM PoolEntry,
|
||||
_In_ ULONG TagUlong
|
||||
)
|
||||
{
|
||||
PPOOL_TAG_LIST_ENTRY client;
|
||||
|
||||
if (client = FindPoolTagListEntry(Context, TagUlong))
|
||||
{
|
||||
PoolEntry->BinaryNameString = client->BinaryNameString;
|
||||
PoolEntry->DescriptionString = client->DescriptionString;
|
||||
|
||||
if (PhStartsWithString2(PoolEntry->BinaryNameString, L"nt!", FALSE))
|
||||
{
|
||||
PoolEntry->Type = TPOOLTAG_TREE_ITEM_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
//if (PhEndsWithString2(PoolEntry->BinaryNameString, L".sys", FALSE))
|
||||
//PoolEntry->Type = TPOOLTAG_TREE_ITEM_TYPE_DRIVER;
|
||||
}
|
||||
}
|
||||
|
||||
178
plugins-extra/PoolMonPlugin/dialogbigpool.c
Normal file
178
plugins-extra/PoolMonPlugin/dialogbigpool.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
VOID UpdateBigPoolTable(
|
||||
_Inout_ PBIGPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PSYSTEM_BIGPOOL_INFORMATION bigPoolTable;
|
||||
ULONG i;
|
||||
|
||||
if (!NT_SUCCESS(EnumBigPoolTable(&bigPoolTable)))
|
||||
return;
|
||||
|
||||
for (i = 0; i < bigPoolTable->Count; i++)
|
||||
{
|
||||
INT itemIndex;
|
||||
SYSTEM_BIGPOOL_ENTRY poolTagInfo;
|
||||
WCHAR virtualAddressString[PH_PTR_STR_LEN_1] = L"";
|
||||
|
||||
poolTagInfo = bigPoolTable->AllocatedInfo[i];
|
||||
|
||||
if (poolTagInfo.TagUlong != Context->TagUlong)
|
||||
continue;
|
||||
|
||||
PhPrintPointer(virtualAddressString, poolTagInfo.VirtualAddress);
|
||||
itemIndex = PhAddListViewItem(
|
||||
Context->ListviewHandle,
|
||||
MAXINT,
|
||||
virtualAddressString,
|
||||
NULL
|
||||
);
|
||||
|
||||
PhSetListViewSubItem(
|
||||
Context->ListviewHandle,
|
||||
itemIndex,
|
||||
1,
|
||||
PhaFormatSize(poolTagInfo.SizeInBytes, -1)->Buffer
|
||||
);
|
||||
|
||||
if (poolTagInfo.NonPaged)
|
||||
{
|
||||
PhSetListViewSubItem(
|
||||
Context->ListviewHandle,
|
||||
itemIndex,
|
||||
2,
|
||||
L"Yes"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhSetListViewSubItem(
|
||||
Context->ListviewHandle,
|
||||
itemIndex,
|
||||
2,
|
||||
L"No"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PhFree(bigPoolTable);
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK BigPoolMonDlgProc(
|
||||
_In_ HWND hwndDlg,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PBIGPOOLTAG_CONTEXT context;
|
||||
|
||||
if (uMsg == WM_INITDIALOG)
|
||||
{
|
||||
context = PhAllocate(sizeof(BIGPOOLTAG_CONTEXT));
|
||||
memset(context, 0, sizeof(BIGPOOLTAG_CONTEXT));
|
||||
|
||||
context->TagUlong = ((PPOOL_ITEM)lParam)->TagUlong;
|
||||
PhZeroExtendToUtf16Buffer(context->Tag, sizeof(context->Tag), context->TagString);
|
||||
|
||||
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
||||
}
|
||||
else
|
||||
{
|
||||
context = (PBIGPOOLTAG_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_BIGPOOLLIST);
|
||||
|
||||
PhCenterWindow(hwndDlg, NULL);
|
||||
|
||||
SetWindowText(hwndDlg, PhaFormatString(L"Large Allocations (%s)", context->TagString)->Buffer);
|
||||
|
||||
PhRegisterDialog(hwndDlg);
|
||||
PhSetListViewStyle(context->ListviewHandle, FALSE, TRUE);
|
||||
PhSetControlTheme(context->ListviewHandle, L"explorer");
|
||||
PhAddListViewColumn(context->ListviewHandle, 0, 0, 0, LVCFMT_LEFT, 150, L"Address");
|
||||
PhAddListViewColumn(context->ListviewHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Size");
|
||||
PhAddListViewColumn(context->ListviewHandle, 2, 2, 2, LVCFMT_LEFT, 100, L"NonPaged");
|
||||
PhSetExtendedListView(context->ListviewHandle);
|
||||
|
||||
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
||||
PhAddLayoutItem(&context->LayoutManager, context->ListviewHandle, NULL, PH_ANCHOR_ALL);
|
||||
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDCANCEL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
|
||||
//PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
||||
|
||||
UpdateBigPoolTable(context);
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
PhLayoutManagerLayout(&context->LayoutManager);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
//PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
||||
|
||||
PhDeleteLayoutManager(&context->LayoutManager);
|
||||
PhUnregisterDialog(hwndDlg);
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
EndDialog(hwndDlg, IDOK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID ShowBigPoolDialog(
|
||||
_In_ PPOOL_ITEM PoolItem
|
||||
)
|
||||
{
|
||||
DialogBoxParam(
|
||||
PluginInstance->DllBase,
|
||||
MAKEINTRESOURCE(IDD_BIGPOOL),
|
||||
NULL,
|
||||
BigPoolMonDlgProc,
|
||||
(LPARAM)PoolItem
|
||||
);
|
||||
}
|
||||
423
plugins-extra/PoolMonPlugin/dialogpool.c
Normal file
423
plugins-extra/PoolMonPlugin/dialogpool.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
static HWND PoolTagDialogHandle = NULL;
|
||||
static HANDLE PoolTagDialogThreadHandle = NULL;
|
||||
static PH_EVENT PoolTagDialogInitializedEvent = PH_EVENT_INIT;
|
||||
|
||||
VOID UpdatePoolTagTable(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PSYSTEM_POOLTAG_INFORMATION poolTagTable;
|
||||
ULONG i;
|
||||
|
||||
if (!NT_SUCCESS(EnumPoolTagTable(&poolTagTable)))
|
||||
{
|
||||
PhDereferenceObject(Context);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < poolTagTable->Count; i++)
|
||||
{
|
||||
PPOOLTAG_ROOT_NODE node;
|
||||
SYSTEM_POOLTAG poolTagInfo;
|
||||
|
||||
poolTagInfo = poolTagTable->TagInfo[i];
|
||||
|
||||
if (node = PmFindPoolTagNode(Context, poolTagInfo.TagUlong))
|
||||
{
|
||||
PhUpdateDelta(&node->PoolItem->PagedAllocsDelta, poolTagInfo.PagedAllocs);
|
||||
PhUpdateDelta(&node->PoolItem->PagedFreesDelta, poolTagInfo.PagedFrees);
|
||||
PhUpdateDelta(&node->PoolItem->PagedCurrentDelta, poolTagInfo.PagedAllocs - poolTagInfo.PagedFrees);
|
||||
PhUpdateDelta(&node->PoolItem->PagedTotalSizeDelta, poolTagInfo.PagedUsed);
|
||||
PhUpdateDelta(&node->PoolItem->NonPagedAllocsDelta, poolTagInfo.NonPagedAllocs);
|
||||
PhUpdateDelta(&node->PoolItem->NonPagedFreesDelta, poolTagInfo.NonPagedFrees);
|
||||
PhUpdateDelta(&node->PoolItem->NonPagedCurrentDelta, poolTagInfo.NonPagedAllocs - poolTagInfo.NonPagedFrees);
|
||||
PhUpdateDelta(&node->PoolItem->NonPagedTotalSizeDelta, poolTagInfo.NonPagedUsed);
|
||||
|
||||
PmUpdatePoolTagNode(Context, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
PPOOL_ITEM entry;
|
||||
|
||||
entry = PhCreateAlloc(sizeof(POOL_ITEM));
|
||||
memset(entry, 0, sizeof(POOL_ITEM));
|
||||
|
||||
entry->TagUlong = poolTagInfo.TagUlong;
|
||||
PhZeroExtendToUtf16Buffer(poolTagInfo.Tag, sizeof(poolTagInfo.Tag), entry->TagString);
|
||||
|
||||
PhUpdateDelta(&entry->PagedAllocsDelta, poolTagInfo.PagedAllocs);
|
||||
PhUpdateDelta(&entry->PagedFreesDelta, poolTagInfo.PagedFrees);
|
||||
PhUpdateDelta(&entry->PagedCurrentDelta, poolTagInfo.PagedAllocs - poolTagInfo.PagedFrees);
|
||||
PhUpdateDelta(&entry->PagedTotalSizeDelta, poolTagInfo.PagedUsed);
|
||||
PhUpdateDelta(&entry->NonPagedAllocsDelta, poolTagInfo.NonPagedAllocs);
|
||||
PhUpdateDelta(&entry->NonPagedFreesDelta, poolTagInfo.NonPagedFrees);
|
||||
PhUpdateDelta(&entry->NonPagedCurrentDelta, poolTagInfo.NonPagedAllocs - poolTagInfo.NonPagedFrees);
|
||||
PhUpdateDelta(&entry->NonPagedTotalSizeDelta, poolTagInfo.NonPagedUsed);
|
||||
|
||||
UpdatePoolTagBinaryName(Context, entry, poolTagInfo.TagUlong);
|
||||
|
||||
PmAddPoolTagNode(Context, entry);
|
||||
}
|
||||
}
|
||||
|
||||
TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
PhDereferenceObject(Context);
|
||||
|
||||
PhFree(poolTagTable);
|
||||
}
|
||||
|
||||
BOOLEAN WordMatchStringRef(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPH_STRINGREF Text
|
||||
)
|
||||
{
|
||||
PH_STRINGREF part;
|
||||
PH_STRINGREF remainingPart;
|
||||
|
||||
remainingPart = Context->SearchboxText->sr;
|
||||
|
||||
while (remainingPart.Length != 0)
|
||||
{
|
||||
PhSplitStringRefAtChar(&remainingPart, '|', &part, &remainingPart);
|
||||
|
||||
if (part.Length != 0)
|
||||
{
|
||||
if (PhFindStringInStringRef(Text, &part, TRUE) != -1)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN WordMatchStringZ(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PWSTR Text
|
||||
)
|
||||
{
|
||||
PH_STRINGREF text;
|
||||
|
||||
PhInitializeStringRef(&text, Text);
|
||||
return WordMatchStringRef(Context, &text);
|
||||
}
|
||||
|
||||
BOOLEAN PoolTagTreeFilterCallback(
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPOOLTAG_CONTEXT context = Context;
|
||||
PPOOLTAG_ROOT_NODE poolNode = (PPOOLTAG_ROOT_NODE)Node;
|
||||
|
||||
if (PhIsNullOrEmptyString(context->SearchboxText))
|
||||
return TRUE;
|
||||
|
||||
if (poolNode->PoolItem->TagString[0] != 0)
|
||||
{
|
||||
if (WordMatchStringZ(context, poolNode->PoolItem->TagString))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!PhIsNullOrEmptyString(poolNode->PoolItem->BinaryNameString))
|
||||
{
|
||||
if (WordMatchStringRef(context, &poolNode->PoolItem->BinaryNameString->sr))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!PhIsNullOrEmptyString(poolNode->PoolItem->DescriptionString))
|
||||
{
|
||||
if (WordMatchStringRef(context, &poolNode->PoolItem->DescriptionString->sr))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID NTAPI ProcessesUpdatedCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPOOLTAG_CONTEXT context = Context;
|
||||
|
||||
context->ProcessesUpdatedCount++;
|
||||
|
||||
if (context->ProcessesUpdatedCount < 2)
|
||||
return;
|
||||
|
||||
PhReferenceObject(context);
|
||||
UpdatePoolTagTable(Context);
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK PoolMonDlgProc(
|
||||
_In_ HWND hwndDlg,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PPOOLTAG_CONTEXT context;
|
||||
|
||||
if (uMsg == WM_INITDIALOG)
|
||||
{
|
||||
context = PhCreateAlloc(sizeof(POOLTAG_CONTEXT));
|
||||
memset(context, 0, sizeof(POOLTAG_CONTEXT));
|
||||
|
||||
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
||||
}
|
||||
else
|
||||
{
|
||||
context = (PPOOLTAG_CONTEXT)GetProp(hwndDlg, L"Context");
|
||||
|
||||
if (uMsg == WM_DESTROY)
|
||||
{
|
||||
RemoveProp(hwndDlg, L"Context");
|
||||
PhDereferenceObject(context);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
context->ParentWindowHandle = hwndDlg;
|
||||
context->TreeNewHandle = GetDlgItem(hwndDlg, IDC_POOLTREE);
|
||||
context->SearchboxHandle = GetDlgItem(hwndDlg, IDC_SEARCH);
|
||||
|
||||
PhRegisterDialog(hwndDlg);
|
||||
PhCenterWindow(hwndDlg, PhMainWndHandle);
|
||||
|
||||
PmInitializePoolTagTree(context);
|
||||
|
||||
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
||||
PhAddLayoutItem(&context->LayoutManager, context->TreeNewHandle, NULL, PH_ANCHOR_ALL);
|
||||
PhAddLayoutItem(&context->LayoutManager, context->SearchboxHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
|
||||
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_CLEAR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
|
||||
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDCANCEL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
|
||||
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
||||
|
||||
context->SearchboxText = PhReferenceEmptyString();
|
||||
context->TreeFilterEntry = PhAddTreeNewFilter(
|
||||
&context->FilterSupport,
|
||||
PoolTagTreeFilterCallback,
|
||||
context
|
||||
);
|
||||
|
||||
LoadPoolTagDatabase(context);
|
||||
|
||||
PhReferenceObject(context);
|
||||
UpdatePoolTagTable(context);
|
||||
TreeNew_AutoSizeColumn(context->TreeNewHandle, TREE_COLUMN_ITEM_DESCRIPTION, TN_AUTOSIZE_REMAINING_SPACE);
|
||||
|
||||
PhRegisterCallback(
|
||||
&PhProcessesUpdatedEvent,
|
||||
ProcessesUpdatedCallback,
|
||||
context,
|
||||
&context->ProcessesUpdatedCallbackRegistration
|
||||
);
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
PhLayoutManagerLayout(&context->LayoutManager);
|
||||
TreeNew_AutoSizeColumn(context->TreeNewHandle, TREE_COLUMN_ITEM_DESCRIPTION, TN_AUTOSIZE_REMAINING_SPACE);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
PhUnregisterCallback(
|
||||
&PhProcessesUpdatedEvent,
|
||||
&context->ProcessesUpdatedCallbackRegistration
|
||||
);
|
||||
|
||||
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
|
||||
PmSaveSettingsTreeList(context);
|
||||
|
||||
PhDeleteLayoutManager(&context->LayoutManager);
|
||||
PhUnregisterDialog(hwndDlg);
|
||||
|
||||
PhDeleteTreeNewFilterSupport(&context->FilterSupport);
|
||||
|
||||
PmDeletePoolTagTree(context);
|
||||
FreePoolTagDatabase(context);
|
||||
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
break;
|
||||
case POOL_TABLE_SHOWDIALOG:
|
||||
{
|
||||
if (IsMinimized(hwndDlg))
|
||||
ShowWindow(hwndDlg, SW_RESTORE);
|
||||
else
|
||||
ShowWindow(hwndDlg, SW_SHOW);
|
||||
|
||||
SetForegroundWindow(hwndDlg);
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
DestroyWindow(hwndDlg);
|
||||
break;
|
||||
case IDC_CLEAR:
|
||||
{
|
||||
SetFocus(context->SearchboxHandle);
|
||||
Static_SetText(context->SearchboxHandle, L"");
|
||||
}
|
||||
break;
|
||||
case IDC_SEARCH:
|
||||
{
|
||||
PPH_STRING newSearchboxText;
|
||||
|
||||
if (GET_WM_COMMAND_CMD(wParam, lParam) != EN_CHANGE)
|
||||
break;
|
||||
|
||||
newSearchboxText = PH_AUTO(PhGetWindowText(context->SearchboxHandle));
|
||||
|
||||
if (!PhEqualString(context->SearchboxText, newSearchboxText, FALSE))
|
||||
{
|
||||
// Cache the current search text for our callback.
|
||||
PhSwapReference(&context->SearchboxText, newSearchboxText);
|
||||
|
||||
PhApplyTreeNewFilters(&context->FilterSupport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case POOL_TABLE_SHOWCONTEXTMENU:
|
||||
{
|
||||
PPH_EMENU menu;
|
||||
PPOOLTAG_ROOT_NODE selectedNode;
|
||||
PPH_EMENU_ITEM selectedItem;
|
||||
PPH_TREENEW_MOUSE_EVENT mouseEvent = (PPH_TREENEW_MOUSE_EVENT)lParam;
|
||||
|
||||
if (selectedNode = PmGetSelectedPoolTagNode(context))
|
||||
{
|
||||
menu = PhCreateEMenu();
|
||||
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"Show allocations", NULL, NULL), -1);
|
||||
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
|
||||
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 2, L"Edit description...", NULL, NULL), -1);
|
||||
|
||||
selectedItem = PhShowEMenu(
|
||||
menu,
|
||||
hwndDlg,
|
||||
PH_EMENU_SHOW_LEFTRIGHT,
|
||||
PH_ALIGN_LEFT | PH_ALIGN_TOP,
|
||||
mouseEvent->Location.x,
|
||||
mouseEvent->Location.y
|
||||
);
|
||||
|
||||
if (selectedItem && selectedItem->Id != -1)
|
||||
{
|
||||
switch (selectedItem->Id)
|
||||
{
|
||||
case 1:
|
||||
ShowBigPoolDialog(selectedNode->PoolItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PhDestroyEMenu(menu);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS ShowPoolMonDialogThread(
|
||||
_In_ PVOID Parameter
|
||||
)
|
||||
{
|
||||
BOOL result;
|
||||
MSG message;
|
||||
PH_AUTO_POOL autoPool;
|
||||
|
||||
PhInitializeAutoPool(&autoPool);
|
||||
|
||||
PoolTagDialogHandle = CreateDialog(
|
||||
PluginInstance->DllBase,
|
||||
MAKEINTRESOURCE(IDD_POOL),
|
||||
NULL,
|
||||
PoolMonDlgProc
|
||||
);
|
||||
|
||||
PhSetEvent(&PoolTagDialogInitializedEvent);
|
||||
|
||||
PostMessage(PoolTagDialogHandle, POOL_TABLE_SHOWDIALOG, 0, 0);
|
||||
|
||||
while (result = GetMessage(&message, NULL, 0, 0))
|
||||
{
|
||||
if (result == -1)
|
||||
break;
|
||||
|
||||
if (!IsDialogMessage(PoolTagDialogHandle, &message))
|
||||
{
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
|
||||
PhDrainAutoPool(&autoPool);
|
||||
}
|
||||
|
||||
PhDeleteAutoPool(&autoPool);
|
||||
|
||||
if (PoolTagDialogThreadHandle)
|
||||
{
|
||||
NtClose(PoolTagDialogThreadHandle);
|
||||
PoolTagDialogThreadHandle = NULL;
|
||||
}
|
||||
|
||||
PhResetEvent(&PoolTagDialogInitializedEvent);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
VOID ShowPoolMonDialog(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (!PoolTagDialogThreadHandle)
|
||||
{
|
||||
if (!(PoolTagDialogThreadHandle = PhCreateThread(0, ShowPoolMonDialogThread, NULL)))
|
||||
{
|
||||
PhShowStatus(PhMainWndHandle, L"Unable to create the pool monitor window.", 0, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
PhWaitForEvent(&PoolTagDialogInitializedEvent, NULL);
|
||||
}
|
||||
|
||||
PostMessage(PoolTagDialogHandle, POOL_TABLE_SHOWDIALOG, 0, 0);
|
||||
}
|
||||
148
plugins-extra/PoolMonPlugin/main.c
Normal file
148
plugins-extra/PoolMonPlugin/main.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
PPH_PLUGIN PluginInstance;
|
||||
|
||||
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginUnloadCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
|
||||
|
||||
VOID NTAPI LoadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
VOID NTAPI UnloadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
VOID NTAPI MainMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
|
||||
PPH_EMENU_ITEM systemMenu;
|
||||
|
||||
if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS)
|
||||
return;
|
||||
|
||||
if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0)))
|
||||
{
|
||||
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1);
|
||||
PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"System", NULL), -1);
|
||||
}
|
||||
|
||||
PhInsertEMenuItem(systemMenu, PhPluginCreateEMenuItem(PluginInstance, 0, POOL_TABLE_MENUITEM, L"Pool Table", NULL), -1);
|
||||
}
|
||||
|
||||
VOID NTAPI MenuItemCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_PLUGIN_MENU_ITEM menuItem = (PPH_PLUGIN_MENU_ITEM)Parameter;
|
||||
|
||||
switch (menuItem->Id)
|
||||
{
|
||||
case POOL_TABLE_MENUITEM:
|
||||
{
|
||||
ShowPoolMonDialog();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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[] =
|
||||
{
|
||||
{ IntegerPairSettingType, SETTING_NAME_WINDOW_POSITION, L"350,350" },
|
||||
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOW_SIZE, L"@96|510,380" },
|
||||
{ StringSettingType, SETTING_NAME_TREE_LIST_COLUMNS, L"" },
|
||||
{ IntegerPairSettingType, SETTING_NAME_TREE_LIST_SORT, L"0,0" }
|
||||
};
|
||||
|
||||
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
|
||||
|
||||
if (!PluginInstance)
|
||||
return FALSE;
|
||||
|
||||
info->Author = L"dmex";
|
||||
info->DisplayName = L"Pool Table";
|
||||
info->Description = L"Plugin for viewing the NT Pool Table via the Tools menu.";
|
||||
info->HasOptions = FALSE;
|
||||
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
|
||||
LoadCallback,
|
||||
NULL,
|
||||
&PluginLoadCallbackRegistration
|
||||
);
|
||||
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackUnload),
|
||||
UnloadCallback,
|
||||
NULL,
|
||||
&PluginUnloadCallbackRegistration
|
||||
);
|
||||
|
||||
PhRegisterCallback(
|
||||
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
|
||||
MainMenuInitializingCallback,
|
||||
NULL,
|
||||
&MainMenuInitializingCallbackRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
|
||||
MenuItemCallback,
|
||||
NULL,
|
||||
&PluginMenuItemCallbackRegistration
|
||||
);
|
||||
|
||||
PhAddSettings(settings, ARRAYSIZE(settings));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
245
plugins-extra/PoolMonPlugin/main.h
Normal file
245
plugins-extra/PoolMonPlugin/main.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _PM_H_
|
||||
#define _PM_H_
|
||||
|
||||
#define CINTERFACE
|
||||
#define COBJMACROS
|
||||
#include <phdk.h>
|
||||
#include <phappresource.h>
|
||||
#include <shlobj.h>
|
||||
#include <symprv.h>
|
||||
#include <windowsx.h>
|
||||
#include <workqueue.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define PLUGIN_NAME L"dmex.PoolMonPlugin"
|
||||
#define SETTING_NAME_WINDOW_POSITION (PLUGIN_NAME L".WindowPosition")
|
||||
#define SETTING_NAME_WINDOW_SIZE (PLUGIN_NAME L".WindowSize")
|
||||
#define SETTING_NAME_TREE_LIST_COLUMNS (PLUGIN_NAME L".TreeViewColumns")
|
||||
#define SETTING_NAME_TREE_LIST_SORT (PLUGIN_NAME L".TreeViewSort")
|
||||
|
||||
#define POOL_TABLE_MENUITEM 1
|
||||
#define POOL_TABLE_SHOWDIALOG (WM_APP + 1)
|
||||
#define POOL_TABLE_SHOWCONTEXTMENU (WM_APP + 2)
|
||||
|
||||
extern PPH_PLUGIN PluginInstance;
|
||||
|
||||
typedef enum _POOLTAG_TREE_ITEM_TYPE
|
||||
{
|
||||
TPOOLTAG_TREE_ITEM_TYPE_NONE,
|
||||
TPOOLTAG_TREE_ITEM_TYPE_OBJECT,
|
||||
TPOOLTAG_TREE_ITEM_TYPE_DRIVER,
|
||||
} POOLTAG_TREE_ITEM_TYPE;
|
||||
|
||||
typedef struct _POOL_TAG_LIST_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
|
||||
union
|
||||
{
|
||||
UCHAR Tag[4];
|
||||
ULONG TagUlong;
|
||||
};
|
||||
|
||||
PPH_STRING BinaryNameString;
|
||||
PPH_STRING DescriptionString;
|
||||
} POOL_TAG_LIST_ENTRY, *PPOOL_TAG_LIST_ENTRY;
|
||||
|
||||
typedef struct _POOL_ITEM
|
||||
{
|
||||
ULONG TagUlong;
|
||||
WCHAR TagString[5];
|
||||
|
||||
PPH_STRING BinaryNameString;
|
||||
PPH_STRING DescriptionString;
|
||||
POOLTAG_TREE_ITEM_TYPE Type;
|
||||
|
||||
PH_UINT64_DELTA PagedAllocsDelta;
|
||||
PH_UINT64_DELTA PagedFreesDelta;
|
||||
PH_UINT64_DELTA PagedCurrentDelta;
|
||||
PH_UINT64_DELTA PagedTotalSizeDelta;
|
||||
PH_UINT64_DELTA NonPagedAllocsDelta;
|
||||
PH_UINT64_DELTA NonPagedFreesDelta;
|
||||
PH_UINT64_DELTA NonPagedCurrentDelta;
|
||||
PH_UINT64_DELTA NonPagedTotalSizeDelta;
|
||||
} POOL_ITEM, *PPOOL_ITEM;
|
||||
|
||||
typedef enum _POOLTAG_TREE_COLUMN_ITEM_NAME
|
||||
{
|
||||
TREE_COLUMN_ITEM_TAG,
|
||||
TREE_COLUMN_ITEM_DRIVER,
|
||||
TREE_COLUMN_ITEM_DESCRIPTION,
|
||||
TREE_COLUMN_ITEM_PAGEDALLOC,
|
||||
TREE_COLUMN_ITEM_PAGEDFREE,
|
||||
TREE_COLUMN_ITEM_PAGEDCURRENT,
|
||||
TREE_COLUMN_ITEM_PAGEDTOTAL,
|
||||
TREE_COLUMN_ITEM_NONPAGEDALLOC,
|
||||
TREE_COLUMN_ITEM_NONPAGEDFREE,
|
||||
TREE_COLUMN_ITEM_NONPAGEDCURRENT,
|
||||
TREE_COLUMN_ITEM_NONPAGEDTOTAL,
|
||||
TREE_COLUMN_ITEM_MAXIMUM
|
||||
} POOLTAG_TREE_COLUMN_ITEM_NAME;
|
||||
|
||||
typedef struct _POOLTAG_ROOT_NODE
|
||||
{
|
||||
PH_TREENEW_NODE Node;
|
||||
PH_STRINGREF TextCache[TREE_COLUMN_ITEM_MAXIMUM];
|
||||
|
||||
ULONG TagUlong;
|
||||
PPOOL_ITEM PoolItem;
|
||||
|
||||
PPH_STRING PagedAllocsDeltaString;
|
||||
PPH_STRING PagedFreesDeltaString;
|
||||
PPH_STRING PagedLiveDeltaString;
|
||||
PPH_STRING PagedCurrentDeltaString;
|
||||
PPH_STRING PagedTotalSizeDeltaString;
|
||||
PPH_STRING NonPagedAllocsDeltaString;
|
||||
PPH_STRING NonPagedFreesDeltaString;
|
||||
PPH_STRING NonPagedLiveDeltaString;
|
||||
PPH_STRING NonPagedCurrentDeltaString;
|
||||
PPH_STRING NonPagedTotalSizeDeltaString;
|
||||
} POOLTAG_ROOT_NODE, *PPOOLTAG_ROOT_NODE;
|
||||
|
||||
typedef struct _POOLTAG_CONTEXT
|
||||
{
|
||||
HWND ParentWindowHandle;
|
||||
HWND SearchboxHandle;
|
||||
HWND TreeNewHandle;
|
||||
PH_LAYOUT_MANAGER LayoutManager;
|
||||
ULONG ProcessesUpdatedCount;
|
||||
PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration;
|
||||
|
||||
PPH_STRING SearchboxText;
|
||||
PH_TN_FILTER_SUPPORT FilterSupport;
|
||||
PPH_TN_FILTER_ENTRY TreeFilterEntry;
|
||||
|
||||
PPH_LIST PoolTagDbList;
|
||||
PPH_HASHTABLE PoolTagDbHashtable;
|
||||
|
||||
ULONG TreeNewSortColumn;
|
||||
PH_SORT_ORDER TreeNewSortOrder;
|
||||
PPH_HASHTABLE NodeHashtable;
|
||||
PPH_LIST NodeList;
|
||||
PPH_LIST NodeRootList;
|
||||
} POOLTAG_CONTEXT, *PPOOLTAG_CONTEXT;
|
||||
|
||||
// dialog.c
|
||||
|
||||
VOID ShowPoolMonDialog(
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
|
||||
typedef struct _BIGPOOLTAG_CONTEXT
|
||||
{
|
||||
HWND WindowHandle;
|
||||
HWND ListviewHandle;
|
||||
PH_LAYOUT_MANAGER LayoutManager;
|
||||
|
||||
union
|
||||
{
|
||||
UCHAR Tag[4];
|
||||
ULONG TagUlong;
|
||||
};
|
||||
WCHAR TagString[5];
|
||||
|
||||
} BIGPOOLTAG_CONTEXT, *PBIGPOOLTAG_CONTEXT;
|
||||
|
||||
VOID ShowBigPoolDialog(
|
||||
_In_ PPOOL_ITEM PoolItem
|
||||
);
|
||||
|
||||
|
||||
|
||||
VOID PmLoadSettingsTreeList(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PmSaveSettingsTreeList(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PmInitializePoolTagTree(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PmDeletePoolTagTree(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmFindPoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ ULONG PoolTag
|
||||
);
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmAddPoolTagNode(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOL_ITEM PoolItem
|
||||
);
|
||||
|
||||
VOID PmUpdatePoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOLTAG_ROOT_NODE WindowNode
|
||||
);
|
||||
|
||||
struct _PH_TN_FILTER_SUPPORT*
|
||||
NTAPI
|
||||
PmGetFilterSupportTreeList(
|
||||
VOID
|
||||
);
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmGetSelectedPoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
// pool.c
|
||||
|
||||
NTSTATUS EnumPoolTagTable(
|
||||
_Out_ PVOID* Buffer
|
||||
);
|
||||
|
||||
NTSTATUS EnumBigPoolTable(
|
||||
_Out_ PVOID* Buffer
|
||||
);
|
||||
|
||||
|
||||
// db.c
|
||||
|
||||
VOID LoadPoolTagDatabase(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID FreePoolTagDatabase(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID UpdatePoolTagBinaryName(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOL_ITEM PoolEntry,
|
||||
_In_ ULONG TagUlong
|
||||
);
|
||||
|
||||
#endif _PM_H_
|
||||
108
plugins-extra/PoolMonPlugin/pooltable.c
Normal file
108
plugins-extra/PoolMonPlugin/pooltable.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
NTSTATUS EnumPoolTagTable(
|
||||
_Out_ PVOID* Buffer
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
ULONG attempts;
|
||||
|
||||
bufferSize = 0x100;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
status = NtQuerySystemInformation(
|
||||
SystemPoolTagInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
attempts = 0;
|
||||
|
||||
while (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 8)
|
||||
{
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
status = NtQuerySystemInformation(
|
||||
SystemPoolTagInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
*Buffer = buffer;
|
||||
else
|
||||
PhFree(buffer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS EnumBigPoolTable(
|
||||
_Out_ PVOID* Buffer
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
ULONG attempts;
|
||||
|
||||
bufferSize = 0x100;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
status = NtQuerySystemInformation(
|
||||
SystemBigPoolInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
attempts = 0;
|
||||
|
||||
while (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 8)
|
||||
{
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
status = NtQuerySystemInformation(
|
||||
SystemBigPoolInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
*Buffer = buffer;
|
||||
else
|
||||
PhFree(buffer);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
22
plugins-extra/PoolMonPlugin/resource.h
Normal file
22
plugins-extra/PoolMonPlugin/resource.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by PoolMonPlugin.rc
|
||||
//
|
||||
#define IDD_POOL 101
|
||||
#define IDR_TXT_POOLTAGS 104
|
||||
#define IDD_BIGPOOL 105
|
||||
#define IDC_POOLTREE 1001
|
||||
#define IDC_SEARCH 1002
|
||||
#define IDC_CLEAR 1003
|
||||
#define IDC_BIGPOOLLIST 1004
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 107
|
||||
#define _APS_NEXT_COMMAND_VALUE 40006
|
||||
#define _APS_NEXT_CONTROL_VALUE 1005
|
||||
#define _APS_NEXT_SYMED_VALUE 103
|
||||
#endif
|
||||
#endif
|
||||
4345
plugins-extra/PoolMonPlugin/resources/pooltag.txt
Normal file
4345
plugins-extra/PoolMonPlugin/resources/pooltag.txt
Normal file
File diff suppressed because it is too large
Load Diff
589
plugins-extra/PoolMonPlugin/treepool.c
Normal file
589
plugins-extra/PoolMonPlugin/treepool.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Process Hacker Extra Plugins -
|
||||
* Pool Table 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 "main.h"
|
||||
|
||||
#define SORT_FUNCTION(Column) PmPoolTreeNewCompare##Column
|
||||
#define BEGIN_SORT_FUNCTION(Column) static int __cdecl PmPoolTreeNewCompare##Column( \
|
||||
_In_ void *_context, \
|
||||
_In_ const void *_elem1, \
|
||||
_In_ const void *_elem2 \
|
||||
) \
|
||||
{ \
|
||||
PPOOLTAG_ROOT_NODE node1 = *(PPOOLTAG_ROOT_NODE*)_elem1; \
|
||||
PPOOLTAG_ROOT_NODE node2 = *(PPOOLTAG_ROOT_NODE*)_elem2; \
|
||||
PPOOL_ITEM poolItem1 = node1->PoolItem; \
|
||||
PPOOL_ITEM poolItem2 = node2->PoolItem; \
|
||||
int sortResult = 0;
|
||||
|
||||
#define END_SORT_FUNCTION \
|
||||
if (sortResult == 0) \
|
||||
sortResult = uintptrcmp((ULONG_PTR)poolItem1->TagUlong, (ULONG_PTR)poolItem2->TagUlong); \
|
||||
\
|
||||
return PhModifySort(sortResult, ((PPOOLTAG_CONTEXT)_context)->TreeNewSortOrder); \
|
||||
}
|
||||
|
||||
VOID PmLoadSettingsTreeList(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PPH_STRING settings;
|
||||
PH_INTEGER_PAIR sortSettings;
|
||||
|
||||
settings = PhGetStringSetting(SETTING_NAME_TREE_LIST_COLUMNS);
|
||||
PhCmLoadSettings(Context->TreeNewHandle, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
sortSettings = PhGetIntegerPairSetting(SETTING_NAME_TREE_LIST_SORT);
|
||||
TreeNew_SetSort(Context->TreeNewHandle, (ULONG)sortSettings.X, (PH_SORT_ORDER)sortSettings.Y);
|
||||
}
|
||||
|
||||
VOID PmSaveSettingsTreeList(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PPH_STRING settings;
|
||||
PH_INTEGER_PAIR sortSettings;
|
||||
ULONG sortColumn;
|
||||
PH_SORT_ORDER sortOrder;
|
||||
|
||||
settings = PhCmSaveSettings(Context->TreeNewHandle);
|
||||
PhSetStringSetting2(SETTING_NAME_TREE_LIST_COLUMNS, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
TreeNew_GetSort(Context->TreeNewHandle, &sortColumn, &sortOrder);
|
||||
sortSettings.X = sortColumn;
|
||||
sortSettings.Y = sortOrder;
|
||||
PhSetIntegerPairSetting(SETTING_NAME_TREE_LIST_SORT, sortSettings);
|
||||
}
|
||||
|
||||
BOOLEAN PmPoolTagNodeHashtableEqualFunction(
|
||||
_In_ PVOID Entry1,
|
||||
_In_ PVOID Entry2
|
||||
)
|
||||
{
|
||||
PPOOLTAG_ROOT_NODE poolTagNode1 = *(PPOOLTAG_ROOT_NODE *)Entry1;
|
||||
PPOOLTAG_ROOT_NODE poolTagNode2 = *(PPOOLTAG_ROOT_NODE *)Entry2;
|
||||
|
||||
return poolTagNode1->TagUlong == poolTagNode2->TagUlong;
|
||||
}
|
||||
|
||||
ULONG PmPoolTagNodeHashtableHashFunction(
|
||||
_In_ PVOID Entry
|
||||
)
|
||||
{
|
||||
return (*(PPOOLTAG_ROOT_NODE*)Entry)->TagUlong;
|
||||
}
|
||||
|
||||
VOID PmDestroyPoolTagNode(
|
||||
_In_ PPOOLTAG_ROOT_NODE PoolTagNode
|
||||
)
|
||||
{
|
||||
PhClearReference(&PoolTagNode->PagedAllocsDeltaString);
|
||||
PhClearReference(&PoolTagNode->PagedFreesDeltaString);
|
||||
PhClearReference(&PoolTagNode->PagedCurrentDeltaString);
|
||||
PhClearReference(&PoolTagNode->PagedTotalSizeDeltaString);
|
||||
PhClearReference(&PoolTagNode->NonPagedAllocsDeltaString);
|
||||
PhClearReference(&PoolTagNode->NonPagedFreesDeltaString);
|
||||
PhClearReference(&PoolTagNode->NonPagedCurrentDeltaString);
|
||||
PhClearReference(&PoolTagNode->NonPagedTotalSizeDeltaString);
|
||||
|
||||
PhFree(PoolTagNode);
|
||||
}
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmAddPoolTagNode(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOL_ITEM PoolItem
|
||||
)
|
||||
{
|
||||
PPOOLTAG_ROOT_NODE poolTagNode;
|
||||
|
||||
poolTagNode = PhAllocate(sizeof(POOLTAG_ROOT_NODE));
|
||||
memset(poolTagNode, 0, sizeof(POOLTAG_ROOT_NODE));
|
||||
PhInitializeTreeNewNode(&poolTagNode->Node);
|
||||
|
||||
poolTagNode->PoolItem = PoolItem;
|
||||
poolTagNode->TagUlong = PoolItem->TagUlong;
|
||||
|
||||
memset(poolTagNode->TextCache, 0, sizeof(PH_STRINGREF) * TREE_COLUMN_ITEM_MAXIMUM);
|
||||
poolTagNode->Node.TextCache = poolTagNode->TextCache;
|
||||
poolTagNode->Node.TextCacheSize = TREE_COLUMN_ITEM_MAXIMUM;
|
||||
|
||||
PhAddEntryHashtable(Context->NodeHashtable, &poolTagNode);
|
||||
PhAddItemList(Context->NodeList, poolTagNode);
|
||||
|
||||
if (Context->FilterSupport.FilterList)
|
||||
poolTagNode->Node.Visible = PhApplyTreeNewFiltersToNode(&Context->FilterSupport, &poolTagNode->Node);
|
||||
|
||||
return poolTagNode;
|
||||
}
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmFindPoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ ULONG PoolTag
|
||||
)
|
||||
{
|
||||
POOLTAG_ROOT_NODE lookupWindowNode;
|
||||
PPOOLTAG_ROOT_NODE lookupWindowNodePtr = &lookupWindowNode;
|
||||
PPOOLTAG_ROOT_NODE *windowNode;
|
||||
|
||||
lookupWindowNode.TagUlong = PoolTag;
|
||||
|
||||
windowNode = (PPOOLTAG_ROOT_NODE*)PhFindEntryHashtable(
|
||||
Context->NodeHashtable,
|
||||
&lookupWindowNodePtr
|
||||
);
|
||||
|
||||
if (windowNode)
|
||||
return *windowNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID PmRemovePoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOLTAG_ROOT_NODE PoolTagNode
|
||||
)
|
||||
{
|
||||
ULONG index = 0;
|
||||
|
||||
// Remove from hashtable/list and cleanup.
|
||||
PhRemoveEntryHashtable(Context->NodeHashtable, &PoolTagNode);
|
||||
|
||||
if ((index = PhFindItemList(Context->NodeList, PoolTagNode)) != -1)
|
||||
{
|
||||
PhRemoveItemList(Context->NodeList, index);
|
||||
}
|
||||
|
||||
PmDestroyPoolTagNode(PoolTagNode);
|
||||
|
||||
//TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
}
|
||||
|
||||
VOID PmUpdatePoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_In_ PPOOLTAG_ROOT_NODE PoolTagNode
|
||||
)
|
||||
{
|
||||
memset(PoolTagNode->TextCache, 0, sizeof(PH_STRINGREF) * TREE_COLUMN_ITEM_MAXIMUM);
|
||||
|
||||
PhInvalidateTreeNewNode(&PoolTagNode->Node, TN_CACHE_COLOR);
|
||||
//TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
}
|
||||
|
||||
BEGIN_SORT_FUNCTION(Name)
|
||||
{
|
||||
sortResult = PhCompareStringZ(poolItem1->TagString, poolItem2->TagString, FALSE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(Type)
|
||||
{
|
||||
sortResult = PhCompareStringWithNull(poolItem1->BinaryNameString, poolItem2->BinaryNameString, FALSE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(Description)
|
||||
{
|
||||
sortResult = PhCompareStringWithNull(poolItem1->DescriptionString, poolItem2->DescriptionString, TRUE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(PagedAlloc)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->PagedAllocsDelta.Value, poolItem2->PagedAllocsDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(PagedFree)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->PagedFreesDelta.Value, poolItem2->PagedFreesDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(PagedCurrent)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->PagedCurrentDelta.Value, poolItem2->PagedCurrentDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(PagedTotal)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->PagedTotalSizeDelta.Value, poolItem2->PagedTotalSizeDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(NonPagedAlloc)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->NonPagedAllocsDelta.Value, poolItem2->NonPagedAllocsDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(NonPagedFree)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->NonPagedFreesDelta.Value, poolItem2->NonPagedFreesDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(NonPagedCurrent)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->NonPagedCurrentDelta.Value, poolItem2->NonPagedCurrentDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(NonPagedTotal)
|
||||
{
|
||||
sortResult = uint64cmp(poolItem1->NonPagedTotalSizeDelta.Value, poolItem2->NonPagedTotalSizeDelta.Value);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BOOLEAN NTAPI PmPoolTagTreeNewCallback(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_opt_ PVOID Parameter1,
|
||||
_In_opt_ PVOID Parameter2,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPOOLTAG_CONTEXT context;
|
||||
PPOOLTAG_ROOT_NODE node;
|
||||
|
||||
context = Context;
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
case TreeNewGetChildren:
|
||||
{
|
||||
PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
|
||||
|
||||
node = (PPOOLTAG_ROOT_NODE)getChildren->Node;
|
||||
|
||||
if (!getChildren->Node)
|
||||
{
|
||||
static PVOID sortFunctions[] =
|
||||
{
|
||||
SORT_FUNCTION(Name),
|
||||
SORT_FUNCTION(Type),
|
||||
SORT_FUNCTION(Description),
|
||||
SORT_FUNCTION(PagedAlloc),
|
||||
SORT_FUNCTION(PagedFree),
|
||||
SORT_FUNCTION(PagedCurrent),
|
||||
SORT_FUNCTION(PagedTotal),
|
||||
SORT_FUNCTION(NonPagedAlloc),
|
||||
SORT_FUNCTION(NonPagedFree),
|
||||
SORT_FUNCTION(NonPagedCurrent),
|
||||
SORT_FUNCTION(NonPagedTotal),
|
||||
};
|
||||
int (__cdecl *sortFunction)(void *, const void *, const void *);
|
||||
|
||||
if (context->TreeNewSortColumn < TREE_COLUMN_ITEM_MAXIMUM)
|
||||
sortFunction = sortFunctions[context->TreeNewSortColumn];
|
||||
else
|
||||
sortFunction = NULL;
|
||||
|
||||
if (sortFunction)
|
||||
{
|
||||
qsort_s(context->NodeList->Items, context->NodeList->Count, sizeof(PVOID), sortFunction, context);
|
||||
}
|
||||
|
||||
getChildren->Children = (PPH_TREENEW_NODE *)context->NodeList->Items;
|
||||
getChildren->NumberOfChildren = context->NodeList->Count;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewIsLeaf:
|
||||
{
|
||||
PPH_TREENEW_IS_LEAF isLeaf = (PPH_TREENEW_IS_LEAF)Parameter1;
|
||||
|
||||
node = (PPOOLTAG_ROOT_NODE)isLeaf->Node;
|
||||
|
||||
isLeaf->IsLeaf = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetCellText:
|
||||
{
|
||||
PPH_TREENEW_GET_CELL_TEXT getCellText = (PPH_TREENEW_GET_CELL_TEXT)Parameter1;
|
||||
PPOOL_ITEM poolItem;
|
||||
|
||||
node = (PPOOLTAG_ROOT_NODE)getCellText->Node;
|
||||
poolItem = node->PoolItem;
|
||||
|
||||
switch (getCellText->Id)
|
||||
{
|
||||
case TREE_COLUMN_ITEM_TAG:
|
||||
PhInitializeStringRefLongHint(&getCellText->Text, poolItem->TagString);
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_DRIVER:
|
||||
PhInitializeStringRefLongHint(&getCellText->Text, PhGetStringOrEmpty(poolItem->BinaryNameString));
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_DESCRIPTION:
|
||||
PhInitializeStringRefLongHint(&getCellText->Text, PhGetStringOrEmpty(poolItem->DescriptionString));
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_PAGEDALLOC:
|
||||
{
|
||||
if (poolItem->PagedAllocsDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->PagedAllocsDeltaString, PhFormatUInt64(poolItem->PagedAllocsDelta.Value, TRUE));
|
||||
getCellText->Text = node->PagedAllocsDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_PAGEDFREE:
|
||||
{
|
||||
if (poolItem->PagedFreesDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->PagedFreesDeltaString, PhFormatUInt64(poolItem->PagedFreesDelta.Value, TRUE));
|
||||
getCellText->Text = node->PagedFreesDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_PAGEDCURRENT:
|
||||
{
|
||||
if (poolItem->PagedCurrentDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->PagedCurrentDeltaString, PhFormatUInt64(poolItem->PagedCurrentDelta.Value, TRUE));
|
||||
getCellText->Text = node->PagedCurrentDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_PAGEDTOTAL:
|
||||
{
|
||||
if (poolItem->PagedTotalSizeDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->PagedTotalSizeDeltaString, PhFormatSize(poolItem->PagedTotalSizeDelta.Value, -1));
|
||||
getCellText->Text = node->PagedTotalSizeDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_NONPAGEDALLOC:
|
||||
{
|
||||
if (poolItem->NonPagedAllocsDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->NonPagedAllocsDeltaString, PhFormatUInt64(poolItem->NonPagedAllocsDelta.Value, TRUE));
|
||||
getCellText->Text = node->NonPagedAllocsDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_NONPAGEDFREE:
|
||||
{
|
||||
if (poolItem->NonPagedFreesDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->NonPagedFreesDeltaString, PhFormatUInt64(poolItem->NonPagedFreesDelta.Value, TRUE));
|
||||
getCellText->Text = node->NonPagedFreesDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_NONPAGEDCURRENT:
|
||||
{
|
||||
if (poolItem->NonPagedCurrentDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->NonPagedCurrentDeltaString, PhFormatUInt64(poolItem->NonPagedCurrentDelta.Value, TRUE));
|
||||
getCellText->Text = node->NonPagedCurrentDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TREE_COLUMN_ITEM_NONPAGEDTOTAL:
|
||||
{
|
||||
if (poolItem->NonPagedTotalSizeDelta.Value != 0)
|
||||
{
|
||||
PhMoveReference(&node->NonPagedTotalSizeDeltaString, PhFormatSize(poolItem->NonPagedTotalSizeDelta.Value, -1));
|
||||
getCellText->Text = node->NonPagedTotalSizeDeltaString->sr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
getCellText->Flags = TN_CACHE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetNodeColor:
|
||||
{
|
||||
PPH_TREENEW_GET_NODE_COLOR getNodeColor = (PPH_TREENEW_GET_NODE_COLOR)Parameter1;
|
||||
node = (PPOOLTAG_ROOT_NODE)getNodeColor->Node;
|
||||
|
||||
switch (node->PoolItem->Type)
|
||||
{
|
||||
case TPOOLTAG_TREE_ITEM_TYPE_OBJECT:
|
||||
getNodeColor->BackColor = RGB(204, 255, 255);
|
||||
break;
|
||||
case TPOOLTAG_TREE_ITEM_TYPE_DRIVER:
|
||||
getNodeColor->BackColor = RGB(170, 204, 255);
|
||||
break;
|
||||
}
|
||||
|
||||
getNodeColor->Flags = TN_CACHE | TN_AUTO_FORECOLOR;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewSortChanged:
|
||||
{
|
||||
TreeNew_GetSort(hwnd, &context->TreeNewSortColumn, &context->TreeNewSortOrder);
|
||||
// Force a rebuild to sort the items.
|
||||
TreeNew_NodesStructured(hwnd);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewContextMenu:
|
||||
{
|
||||
PPH_TREENEW_MOUSE_EVENT mouseEvent = (PPH_TREENEW_MOUSE_EVENT)Parameter1;
|
||||
|
||||
SendMessage(
|
||||
context->ParentWindowHandle,
|
||||
WM_COMMAND,
|
||||
POOL_TABLE_SHOWCONTEXTMENU,
|
||||
(LPARAM)mouseEvent
|
||||
);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewHeaderRightClick:
|
||||
{
|
||||
PH_TN_COLUMN_MENU_DATA data;
|
||||
|
||||
data.TreeNewHandle = hwnd;
|
||||
data.MouseEvent = Parameter1;
|
||||
data.DefaultSortColumn = 0;
|
||||
data.DefaultSortOrder = AscendingSortOrder;
|
||||
PhInitializeTreeNewColumnMenu(&data);
|
||||
|
||||
data.Selection = PhShowEMenu(data.Menu, hwnd, PH_EMENU_SHOW_LEFTRIGHT,
|
||||
PH_ALIGN_LEFT | PH_ALIGN_TOP, data.MouseEvent->ScreenLocation.x, data.MouseEvent->ScreenLocation.y);
|
||||
PhHandleTreeNewColumnMenu(&data);
|
||||
PhDeleteTreeNewColumnMenu(&data);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID PmClearPoolTagTree(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
PmDestroyPoolTagNode(Context->NodeList->Items[i]);
|
||||
|
||||
PhClearHashtable(Context->NodeHashtable);
|
||||
PhClearList(Context->NodeList);
|
||||
}
|
||||
|
||||
PPOOLTAG_ROOT_NODE PmGetSelectedPoolTagNode(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PPOOLTAG_ROOT_NODE windowNode = NULL;
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
{
|
||||
windowNode = Context->NodeList->Items[i];
|
||||
|
||||
if (windowNode->Node.Selected)
|
||||
return windowNode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID PmGetSelectedPoolTagNodes(
|
||||
_In_ PPOOLTAG_CONTEXT Context,
|
||||
_Out_ PPOOLTAG_ROOT_NODE **PoolTags,
|
||||
_Out_ PULONG NumberOfPoolTags
|
||||
)
|
||||
{
|
||||
PPH_LIST list;
|
||||
ULONG i;
|
||||
|
||||
list = PhCreateList(2);
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
{
|
||||
PPOOLTAG_ROOT_NODE node = (PPOOLTAG_ROOT_NODE)Context->NodeList->Items[i];
|
||||
|
||||
if (node->Node.Selected)
|
||||
{
|
||||
PhAddItemList(list, node);
|
||||
}
|
||||
}
|
||||
|
||||
*PoolTags = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
|
||||
*NumberOfPoolTags = list->Count;
|
||||
|
||||
PhDereferenceObject(list);
|
||||
}
|
||||
|
||||
VOID PmInitializePoolTagTree(
|
||||
_Inout_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
Context->NodeList = PhCreateList(100);
|
||||
Context->NodeHashtable = PhCreateHashtable(
|
||||
sizeof(PPOOLTAG_ROOT_NODE),
|
||||
PmPoolTagNodeHashtableEqualFunction,
|
||||
PmPoolTagNodeHashtableHashFunction,
|
||||
100
|
||||
);
|
||||
|
||||
PhSetControlTheme(Context->TreeNewHandle, L"explorer");
|
||||
|
||||
TreeNew_SetCallback(Context->TreeNewHandle, PmPoolTagTreeNewCallback, Context);
|
||||
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_TAG, TRUE, L"Tag Name", 50, PH_ALIGN_LEFT, -2, 0);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_DRIVER, TRUE, L"Driver", 82, PH_ALIGN_LEFT, 0, 0);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_DESCRIPTION, TRUE, L"Description", 140, PH_ALIGN_LEFT, 1, 0);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_PAGEDALLOC, TRUE, L"Paged Allocations", 80, PH_ALIGN_RIGHT, 2, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_PAGEDFREE, TRUE, L"Paged Frees", 80, PH_ALIGN_RIGHT, 3, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_PAGEDCURRENT, TRUE, L"Paged Current", 80, PH_ALIGN_RIGHT, 4, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_PAGEDTOTAL, TRUE, L"Paged Bytes Total", 80, PH_ALIGN_LEFT, 5, 0);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_NONPAGEDALLOC, TRUE, L"Non-paged Allocations", 80, PH_ALIGN_RIGHT, 6, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_NONPAGEDFREE, TRUE, L"Non-paged Frees", 80, PH_ALIGN_RIGHT, 7, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_NONPAGEDCURRENT, TRUE, L"Non-paged Current", 80, PH_ALIGN_RIGHT, 8, DT_RIGHT);
|
||||
PhAddTreeNewColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_NONPAGEDTOTAL, TRUE, L"Non-paged Bytes Total", 80, PH_ALIGN_LEFT, 9, 0);
|
||||
|
||||
TreeNew_SetTriState(Context->TreeNewHandle, TRUE);
|
||||
TreeNew_SetSort(Context->TreeNewHandle, TREE_COLUMN_ITEM_NONPAGEDTOTAL, DescendingSortOrder);
|
||||
|
||||
PmLoadSettingsTreeList(Context);
|
||||
|
||||
PhInitializeTreeNewFilterSupport(&Context->FilterSupport, Context->TreeNewHandle, Context->NodeList);
|
||||
}
|
||||
|
||||
VOID PmDeletePoolTagTree(
|
||||
_In_ PPOOLTAG_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PPH_STRING settings;
|
||||
|
||||
settings = PhCmSaveSettings(Context->TreeNewHandle);
|
||||
PhSetStringSetting2(SETTING_NAME_TREE_LIST_COLUMNS, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
for (ULONG i = 0; i < Context->NodeList->Count; i++)
|
||||
{
|
||||
PmDestroyPoolTagNode(Context->NodeList->Items[i]);
|
||||
}
|
||||
|
||||
PhDereferenceObject(Context->NodeHashtable);
|
||||
PhDereferenceObject(Context->NodeList);
|
||||
}
|
||||
Reference in New Issue
Block a user