add plugins-extra

This commit is contained in:
AirDog46
2025-05-13 19:49:49 +03:00
parent c5fab8aa94
commit 3575d86c17
531 changed files with 70258 additions and 1 deletions

View File

@@ -0,0 +1,2 @@
1.0
* Initial release

View 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
/////////////////////////////////////////////////////////////////////////////

View 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>

View 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>

View 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;
}
}

View 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
);
}

View 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);
}

View 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;
}

View 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_

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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);
}