mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
* ExtendedTools: added Disk tab
* AvgCpuPlugin: fixed calculation bug * fixed network list saving * added callbacks to PH_ADDITIONAL_TAB_PAGE * moved PhUnloadPlugins() call to allow plugins to save settings * fixed thread list bug git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4485 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -10,6 +10,7 @@ Process Hacker
|
||||
* Extended header context menu
|
||||
* Removed tooltip text truncation
|
||||
* Updated ExtendedTools plugin:
|
||||
* Added Disk tab
|
||||
* Added Hard Faults, Hard Faults Delta and Peak Threads
|
||||
columns to process tree list
|
||||
* Added Firewall Status column
|
||||
@@ -24,6 +25,7 @@ Process Hacker
|
||||
* Fixed state highlighting bug
|
||||
* Fixed command line propagation for -elevate
|
||||
* Fixed tree list mouse wheel handling
|
||||
* Fixed saving network list
|
||||
|
||||
2.19
|
||||
* NEW/IMPROVED:
|
||||
|
||||
@@ -233,7 +233,7 @@ VOID PhMwpNotifyTabControl(
|
||||
);
|
||||
|
||||
VOID PhMwpSelectionChangedTabControl(
|
||||
VOID
|
||||
__in ULONG OldIndex
|
||||
);
|
||||
|
||||
PPH_ADDITIONAL_TAB_PAGE PhMwpAddTabPage(
|
||||
|
||||
@@ -295,14 +295,17 @@ typedef struct _PH_TN_COLUMN_MENU_DATA
|
||||
#define PH_TN_COLUMN_MENU_SIZE_COLUMN_TO_FIT_ID ((ULONG)-3)
|
||||
#define PH_TN_COLUMN_MENU_SIZE_ALL_COLUMNS_TO_FIT_ID ((ULONG)-4)
|
||||
|
||||
PHAPPAPI
|
||||
VOID PhInitializeTreeNewColumnMenu(
|
||||
__inout PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
|
||||
PHAPPAPI
|
||||
BOOLEAN PhHandleTreeNewColumnMenu(
|
||||
__inout PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
|
||||
PHAPPAPI
|
||||
VOID PhDeleteTreeNewColumnMenu(
|
||||
__in PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
@@ -461,6 +464,13 @@ typedef HWND (NTAPI *PPH_TAB_PAGE_CREATE_FUNCTION)(
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
typedef VOID (NTAPI *PPH_TAB_PAGE_CALLBACK_FUNCTION)(
|
||||
__in PVOID Parameter1,
|
||||
__in PVOID Parameter2,
|
||||
__in PVOID Parameter3,
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
typedef struct _PH_ADDITIONAL_TAB_PAGE
|
||||
{
|
||||
PWSTR Text;
|
||||
@@ -468,6 +478,8 @@ typedef struct _PH_ADDITIONAL_TAB_PAGE
|
||||
PPH_TAB_PAGE_CREATE_FUNCTION CreateFunction;
|
||||
HWND WindowHandle;
|
||||
INT Index;
|
||||
PPH_TAB_PAGE_CALLBACK_FUNCTION SelectionChangedCallback;
|
||||
PPH_TAB_PAGE_CALLBACK_FUNCTION SaveContentCallback;
|
||||
} PH_ADDITIONAL_TAB_PAGE, *PPH_ADDITIONAL_TAB_PAGE;
|
||||
|
||||
#define PH_NOTIFY_MINIMUM 0x1
|
||||
|
||||
@@ -589,6 +589,7 @@ typedef struct _PH_THREAD_NODE
|
||||
|
||||
WCHAR CpuUsageText[PH_INT32_STR_LEN_1];
|
||||
PPH_STRING CyclesDeltaText; // used for Context Switches Delta as well
|
||||
PPH_STRING StartAddressText;
|
||||
PPH_STRING PriorityText;
|
||||
} PH_THREAD_NODE, *PPH_THREAD_NODE;
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ static INT ProcessesTabIndex;
|
||||
static INT ServicesTabIndex;
|
||||
static INT NetworkTabIndex;
|
||||
static INT MaxTabIndex;
|
||||
static INT OldTabIndex;
|
||||
static PPH_LIST AdditionalTabPageList = NULL;
|
||||
static HWND ProcessTreeListHandle;
|
||||
static HWND ServiceTreeListHandle;
|
||||
@@ -240,7 +241,7 @@ BOOLEAN PhMainWndInitialization(
|
||||
PhLogInitialization();
|
||||
PhQueueItemGlobalWorkQueue(PhMwpDelayedLoadFunction, NULL);
|
||||
|
||||
PhMwpSelectionChangedTabControl();
|
||||
PhMwpSelectionChangedTabControl(-1);
|
||||
|
||||
// Perform a layout.
|
||||
SendMessage(PhMainWndHandle, WM_SIZE, 0, 0);
|
||||
@@ -605,6 +606,11 @@ VOID PhMwpOnDestroy(
|
||||
ULONG mask;
|
||||
ULONG i;
|
||||
|
||||
// Notify plugins that we are shutting down.
|
||||
|
||||
if (PhPluginsEnabled)
|
||||
PhUnloadPlugins();
|
||||
|
||||
if (!PhMainWndExiting)
|
||||
ProcessHacker_SaveAllSettings(PhMainWndHandle);
|
||||
|
||||
@@ -619,11 +625,6 @@ VOID PhMwpOnDestroy(
|
||||
PhRemoveNotifyIcon(i);
|
||||
}
|
||||
|
||||
// Notify plugins that we are shutting down.
|
||||
|
||||
if (PhPluginsEnabled)
|
||||
PhUnloadPlugins();
|
||||
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
@@ -763,7 +764,6 @@ VOID PhMwpOnCommand(
|
||||
{
|
||||
ULONG mode;
|
||||
ULONG selectedTab;
|
||||
PPH_LIST lines = NULL;
|
||||
|
||||
if (PhEndsWithString2(fileName, L".csv", TRUE))
|
||||
mode = PH_EXPORT_MODE_CSV;
|
||||
@@ -775,27 +775,35 @@ VOID PhMwpOnCommand(
|
||||
selectedTab = TabCtrl_GetCurSel(TabControlHandle);
|
||||
|
||||
if (selectedTab == ProcessesTabIndex)
|
||||
{
|
||||
PhWriteProcessTree(fileStream, mode);
|
||||
}
|
||||
else if (selectedTab == ServicesTabIndex)
|
||||
{
|
||||
PhWriteServiceList(fileStream, mode);
|
||||
}
|
||||
else if (selectedTab == NetworkTabIndex)
|
||||
lines = PhGetListViewLines(NetworkTreeListHandle, mode);
|
||||
|
||||
if (lines)
|
||||
{
|
||||
PhWriteNetworkList(fileStream, mode);
|
||||
}
|
||||
else if (AdditionalTabPageList)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < lines->Count; i++)
|
||||
for (i = 0; i < AdditionalTabPageList->Count; i++)
|
||||
{
|
||||
PPH_STRING line;
|
||||
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
|
||||
|
||||
line = lines->Items[i];
|
||||
PhWriteStringAsAnsiFileStream(fileStream, &line->sr);
|
||||
PhDereferenceObject(line);
|
||||
PhWriteStringAsAnsiFileStream2(fileStream, L"\r\n");
|
||||
if (tabPage->Index == selectedTab)
|
||||
{
|
||||
if (tabPage->SaveContentCallback)
|
||||
{
|
||||
tabPage->SaveContentCallback(fileStream, UlongToPtr(mode), NULL, tabPage->Context);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PhDereferenceObject(lines);
|
||||
}
|
||||
|
||||
PhDereferenceObject(fileStream);
|
||||
@@ -2934,14 +2942,18 @@ VOID PhMwpNotifyTabControl(
|
||||
__in NMHDR *Header
|
||||
)
|
||||
{
|
||||
if (Header->code == TCN_SELCHANGE)
|
||||
if (Header->code == TCN_SELCHANGING)
|
||||
{
|
||||
PhMwpSelectionChangedTabControl();
|
||||
OldTabIndex = TabCtrl_GetCurSel(TabControlHandle);
|
||||
}
|
||||
else if (Header->code == TCN_SELCHANGE)
|
||||
{
|
||||
PhMwpSelectionChangedTabControl(OldTabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
VOID PhMwpSelectionChangedTabControl(
|
||||
VOID
|
||||
__in ULONG OldIndex
|
||||
)
|
||||
{
|
||||
INT selectedIndex;
|
||||
@@ -2989,6 +3001,18 @@ VOID PhMwpSelectionChangedTabControl(
|
||||
{
|
||||
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
|
||||
|
||||
if (tabPage->SelectionChangedCallback)
|
||||
{
|
||||
if (tabPage->Index == OldIndex)
|
||||
{
|
||||
tabPage->SelectionChangedCallback((PVOID)FALSE, 0, 0, tabPage->Context);
|
||||
}
|
||||
else if (tabPage->Index == selectedIndex)
|
||||
{
|
||||
tabPage->SelectionChangedCallback((PVOID)TRUE, 0, 0, tabPage->Context);
|
||||
}
|
||||
}
|
||||
|
||||
ShowWindow(tabPage->WindowHandle, selectedIndex == tabPage->Index ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
}
|
||||
@@ -3025,8 +3049,11 @@ VOID PhMwpSelectTabPage(
|
||||
__in ULONG Index
|
||||
)
|
||||
{
|
||||
INT oldIndex;
|
||||
|
||||
oldIndex = TabCtrl_GetCurSel(TabControlHandle);
|
||||
TabCtrl_SetCurSel(TabControlHandle, Index);
|
||||
PhMwpSelectionChangedTabControl();
|
||||
PhMwpSelectionChangedTabControl(oldIndex);
|
||||
}
|
||||
|
||||
static int __cdecl IconProcessesCpuUsageCompare(
|
||||
|
||||
@@ -395,6 +395,38 @@ PhWritePhTextHeader(
|
||||
__inout PPH_FILE_STREAM FileStream
|
||||
);
|
||||
|
||||
typedef struct _PH_TN_COLUMN_MENU_DATA
|
||||
{
|
||||
HWND TreeNewHandle;
|
||||
PPH_TREENEW_HEADER_MOUSE_EVENT MouseEvent;
|
||||
ULONG DefaultSortColumn;
|
||||
PH_SORT_ORDER DefaultSortOrder;
|
||||
|
||||
struct _PH_EMENU_ITEM *Menu;
|
||||
struct _PH_EMENU_ITEM *Selection;
|
||||
ULONG ProcessedId;
|
||||
} PH_TN_COLUMN_MENU_DATA, *PPH_TN_COLUMN_MENU_DATA;
|
||||
|
||||
#define PH_TN_COLUMN_MENU_HIDE_COLUMN_ID ((ULONG)-1)
|
||||
#define PH_TN_COLUMN_MENU_CHOOSE_COLUMNS_ID ((ULONG)-2)
|
||||
#define PH_TN_COLUMN_MENU_SIZE_COLUMN_TO_FIT_ID ((ULONG)-3)
|
||||
#define PH_TN_COLUMN_MENU_SIZE_ALL_COLUMNS_TO_FIT_ID ((ULONG)-4)
|
||||
|
||||
PHAPPAPI
|
||||
VOID PhInitializeTreeNewColumnMenu(
|
||||
__inout PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
|
||||
PHAPPAPI
|
||||
BOOLEAN PhHandleTreeNewColumnMenu(
|
||||
__inout PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
|
||||
PHAPPAPI
|
||||
VOID PhDeleteTreeNewColumnMenu(
|
||||
__in PPH_TN_COLUMN_MENU_DATA Data
|
||||
);
|
||||
|
||||
// mainwnd
|
||||
|
||||
#define PH_MAINWND_CLASS_NAME L"ProcessHacker"
|
||||
@@ -462,6 +494,13 @@ typedef HWND (NTAPI *PPH_TAB_PAGE_CREATE_FUNCTION)(
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
typedef VOID (NTAPI *PPH_TAB_PAGE_CALLBACK_FUNCTION)(
|
||||
__in PVOID Parameter1,
|
||||
__in PVOID Parameter2,
|
||||
__in PVOID Parameter3,
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
typedef struct _PH_ADDITIONAL_TAB_PAGE
|
||||
{
|
||||
PWSTR Text;
|
||||
@@ -469,6 +508,8 @@ typedef struct _PH_ADDITIONAL_TAB_PAGE
|
||||
PPH_TAB_PAGE_CREATE_FUNCTION CreateFunction;
|
||||
HWND WindowHandle;
|
||||
INT Index;
|
||||
PPH_TAB_PAGE_CALLBACK_FUNCTION SelectionChangedCallback;
|
||||
PPH_TAB_PAGE_CALLBACK_FUNCTION SaveContentCallback;
|
||||
} PH_ADDITIONAL_TAB_PAGE, *PPH_ADDITIONAL_TAB_PAGE;
|
||||
|
||||
#define PH_NOTIFY_MINIMUM 0x1
|
||||
|
||||
@@ -302,6 +302,7 @@ VOID PhpDestroyThreadNode(
|
||||
PhEmCallObjectOperation(EmThreadNodeType, ThreadNode, EmObjectDelete);
|
||||
|
||||
if (ThreadNode->CyclesDeltaText) PhDereferenceObject(ThreadNode->CyclesDeltaText);
|
||||
if (ThreadNode->StartAddressText) PhDereferenceObject(ThreadNode->StartAddressText);
|
||||
if (ThreadNode->PriorityText) PhDereferenceObject(ThreadNode->PriorityText);
|
||||
|
||||
PhDereferenceObject(ThreadNode->ThreadItem);
|
||||
@@ -551,7 +552,8 @@ BOOLEAN NTAPI PhpThreadTreeNewCallback(
|
||||
}
|
||||
break;
|
||||
case PHTHTLC_STARTADDRESS:
|
||||
getCellText->Text = PhGetStringRef(threadItem->StartAddressString);
|
||||
PhSwapReference(&node->StartAddressText, threadItem->StartAddressString);
|
||||
getCellText->Text = PhGetStringRef(node->StartAddressText);
|
||||
break;
|
||||
case PHTHTLC_PRIORITY:
|
||||
PhSwapReference2(&node->PriorityText, PhGetThreadPriorityWin32String(threadItem->PriorityWin32));
|
||||
|
||||
@@ -32,6 +32,7 @@ PPH_FULL_STRING PhGetTreeNewText(
|
||||
__in ULONG MaximumNumberOfColumns
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LIST PhGetGenericTreeNewLines(
|
||||
__in HWND TreeNewHandle,
|
||||
__in ULONG Mode
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef struct _PH_EMENU_ITEM
|
||||
|
||||
typedef struct _PH_EMENU_ITEM PH_EMENU, *PPH_EMENU;
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhCreateEMenuItem(
|
||||
__in ULONG Flags,
|
||||
__in ULONG Id,
|
||||
@@ -90,8 +91,10 @@ VOID PhRemoveAllEMenuItems(
|
||||
__inout PPH_EMENU_ITEM Parent
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU PhCreateEMenu();
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDestroyEMenu(
|
||||
__in PPH_EMENU Menu
|
||||
);
|
||||
@@ -122,6 +125,7 @@ VOID PhPopupMenuToEMenuItem(
|
||||
__in HMENU PopupMenu
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhLoadResourceEMenuItem(
|
||||
__inout PPH_EMENU_ITEM MenuItem,
|
||||
__in HINSTANCE InstanceHandle,
|
||||
@@ -132,6 +136,7 @@ VOID PhLoadResourceEMenuItem(
|
||||
#define PH_EMENU_SHOW_NONOTIFY 0x1
|
||||
#define PH_EMENU_SHOW_LEFTRIGHT 0x2
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhShowEMenu(
|
||||
__in PPH_EMENU Menu,
|
||||
__in HWND WindowHandle,
|
||||
@@ -143,6 +148,7 @@ PPH_EMENU_ITEM PhShowEMenu(
|
||||
|
||||
// Convenience functions
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhSetFlagsEMenuItem(
|
||||
__in PPH_EMENU_ITEM Item,
|
||||
__in ULONG Id,
|
||||
@@ -159,6 +165,7 @@ FORCEINLINE BOOLEAN PhEnableEMenuItem(
|
||||
return PhSetFlagsEMenuItem(Item, Id, PH_EMENU_DISABLED, Enable ? 0 : PH_EMENU_DISABLED);
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetFlagsAllEMenuItems(
|
||||
__in PPH_EMENU_ITEM Item,
|
||||
__in ULONG Mask,
|
||||
|
||||
@@ -214,10 +214,9 @@ VOID ProcessesUpdatedHandler(
|
||||
do
|
||||
{
|
||||
sum += extension->CpuHistory[i];
|
||||
i++;
|
||||
|
||||
if (i != HISTORY_SIZE)
|
||||
i++;
|
||||
else
|
||||
if (i == HISTORY_SIZE)
|
||||
i = 0;
|
||||
} while (--count != 0);
|
||||
|
||||
@@ -237,10 +236,9 @@ VOID ProcessesUpdatedHandler(
|
||||
do
|
||||
{
|
||||
sum += extension->CpuHistory[i];
|
||||
i++;
|
||||
|
||||
if (i != HISTORY_SIZE)
|
||||
i++;
|
||||
else
|
||||
if (i == HISTORY_SIZE)
|
||||
i = 0;
|
||||
} while (--count != 0);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
1.5
|
||||
* Added Disk tab
|
||||
* Added Hard Faults, Hard Faults Delta and Peak Threads columns
|
||||
to process tree list
|
||||
* Added Firewall Status column to network list
|
||||
|
||||
@@ -372,6 +372,18 @@ BEGIN
|
||||
END
|
||||
END
|
||||
|
||||
IDR_DISK MENU
|
||||
BEGIN
|
||||
POPUP "Disk"
|
||||
BEGIN
|
||||
MENUITEM "&Go to Process\aEnter", ID_DISK_GOTOPROCESS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Open &File Location\aCtrl+Enter", ID_DISK_OPENFILELOCATION
|
||||
MENUITEM "&Copy\aCtrl+C", ID_DISK_COPY
|
||||
MENUITEM "P&roperties", ID_DISK_PROPERTIES
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (Australia) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -107,6 +108,7 @@
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -128,6 +130,7 @@
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -155,6 +158,7 @@
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
@@ -168,6 +172,8 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="disktab.c" />
|
||||
<ClCompile Include="etwdisk.c" />
|
||||
<ClCompile Include="etwmon.c" />
|
||||
<ClCompile Include="treeext.c" />
|
||||
<ClCompile Include="etwstat.c" />
|
||||
@@ -183,6 +189,7 @@
|
||||
<ClCompile Include="wswatch.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="disktabp.h" />
|
||||
<ClInclude Include="etwmon.h" />
|
||||
<ClInclude Include="exttools.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
<ClCompile Include="treeext.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="etwdisk.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="disktab.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h">
|
||||
@@ -65,6 +71,9 @@
|
||||
<ClInclude Include="etwmon.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="disktabp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CHANGELOG.txt" />
|
||||
|
||||
@@ -0,0 +1,858 @@
|
||||
/*
|
||||
* Process Hacker Extended Tools -
|
||||
* ETW disk monitoring
|
||||
*
|
||||
* Copyright (C) 2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Process Hacker is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "exttools.h"
|
||||
#include "etwmon.h"
|
||||
#include "resource.h"
|
||||
#include <colmgr.h>
|
||||
#include "disktabp.h"
|
||||
|
||||
static BOOLEAN DiskTreeNewCreated = FALSE;
|
||||
static HWND DiskTreeNewHandle;
|
||||
static ULONG DiskTreeNewSortColumn;
|
||||
static PH_SORT_ORDER DiskTreeNewSortOrder;
|
||||
|
||||
static PPH_HASHTABLE DiskNodeHashtable; // hashtable of all nodes
|
||||
static PPH_LIST DiskNodeList; // list of all nodes
|
||||
|
||||
static PH_CALLBACK_REGISTRATION DiskItemAddedRegistration;
|
||||
static PH_CALLBACK_REGISTRATION DiskItemModifiedRegistration;
|
||||
static PH_CALLBACK_REGISTRATION DiskItemRemovedRegistration;
|
||||
static PH_CALLBACK_REGISTRATION DiskItemsUpdatedRegistration;
|
||||
static BOOLEAN DiskNeedsRedraw = FALSE;
|
||||
|
||||
VOID EtInitializeDiskTab()
|
||||
{
|
||||
PH_ADDITIONAL_TAB_PAGE tabPage;
|
||||
|
||||
memset(&tabPage, 0, sizeof(PH_ADDITIONAL_TAB_PAGE));
|
||||
tabPage.Text = L"Disk";
|
||||
tabPage.CreateFunction = EtpDiskTabCreateFunction;
|
||||
tabPage.Index = MAXINT;
|
||||
tabPage.SaveContentCallback = EtpDiskTabSaveContentCallback;
|
||||
ProcessHacker_AddTabPage(PhMainWndHandle, &tabPage);
|
||||
}
|
||||
|
||||
HWND NTAPI EtpDiskTabCreateFunction(
|
||||
__in PVOID Context
|
||||
)
|
||||
{
|
||||
HWND hwnd;
|
||||
|
||||
hwnd = CreateWindow(
|
||||
PH_TREENEW_CLASSNAME,
|
||||
NULL,
|
||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER | TN_STYLE_ICONS | TN_STYLE_DOUBLE_BUFFERED,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
3,
|
||||
PhMainWndHandle,
|
||||
(HMENU)PhPluginReserveIds(1),
|
||||
PluginInstance->DllBase,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!hwnd)
|
||||
return NULL;
|
||||
|
||||
DiskTreeNewCreated = TRUE;
|
||||
|
||||
DiskNodeHashtable = PhCreateHashtable(
|
||||
sizeof(PET_DISK_NODE),
|
||||
EtpDiskNodeHashtableCompareFunction,
|
||||
EtpDiskNodeHashtableHashFunction,
|
||||
100
|
||||
);
|
||||
DiskNodeList = PhCreateList(100);
|
||||
|
||||
EtInitializeDiskTreeList(hwnd);
|
||||
|
||||
PhRegisterCallback(
|
||||
&EtDiskItemAddedEvent,
|
||||
EtpDiskItemAddedHandler,
|
||||
NULL,
|
||||
&DiskItemAddedRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
&EtDiskItemModifiedEvent,
|
||||
EtpDiskItemModifiedHandler,
|
||||
NULL,
|
||||
&DiskItemModifiedRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
&EtDiskItemRemovedEvent,
|
||||
EtpDiskItemRemovedHandler,
|
||||
NULL,
|
||||
&DiskItemRemovedRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
&EtDiskItemsUpdatedEvent,
|
||||
EtpDiskItemsUpdatedHandler,
|
||||
NULL,
|
||||
&DiskItemsUpdatedRegistration
|
||||
);
|
||||
|
||||
EtInitializeDiskInformation();
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
VOID NTAPI EtpDiskTabSaveContentCallback(
|
||||
__in PVOID Parameter1,
|
||||
__in PVOID Parameter2,
|
||||
__in PVOID Parameter3,
|
||||
__in PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_FILE_STREAM fileStream = Parameter1;
|
||||
ULONG mode = PtrToUlong(Parameter2);
|
||||
|
||||
EtWriteDiskList(fileStream, mode);
|
||||
}
|
||||
|
||||
BOOLEAN EtpDiskNodeHashtableCompareFunction(
|
||||
__in PVOID Entry1,
|
||||
__in PVOID Entry2
|
||||
)
|
||||
{
|
||||
PET_DISK_NODE diskNode1 = *(PET_DISK_NODE *)Entry1;
|
||||
PET_DISK_NODE diskNode2 = *(PET_DISK_NODE *)Entry2;
|
||||
|
||||
return diskNode1->DiskItem == diskNode2->DiskItem;
|
||||
}
|
||||
|
||||
ULONG EtpDiskNodeHashtableHashFunction(
|
||||
__in PVOID Entry
|
||||
)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
return PhHashInt32((ULONG)(*(PET_DISK_NODE *)Entry)->DiskItem);
|
||||
#else
|
||||
return PhHashInt64((ULONG64)(*(PET_DISK_NODE *)Entry)->DiskItem);
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EtInitializeDiskTreeList(
|
||||
__in HWND hwnd
|
||||
)
|
||||
{
|
||||
DiskTreeNewHandle = hwnd;
|
||||
PhSetControlTheme(DiskTreeNewHandle, L"explorer");
|
||||
SendMessage(TreeNew_GetTooltips(DiskTreeNewHandle), TTM_SETDELAYTIME, TTDT_AUTOPOP, 0x7fff);
|
||||
|
||||
TreeNew_SetCallback(hwnd, EtpDiskTreeNewCallback, NULL);
|
||||
|
||||
TreeNew_SetRedraw(hwnd, FALSE);
|
||||
|
||||
// Default columns
|
||||
PhAddTreeNewColumn(hwnd, ETDSTNC_NAME, TRUE, L"Name", 100, PH_ALIGN_LEFT, 0, 0);
|
||||
PhAddTreeNewColumn(hwnd, ETDSTNC_FILE, TRUE, L"File", 400, PH_ALIGN_LEFT, 1, 0);
|
||||
PhAddTreeNewColumnEx(hwnd, ETDSTNC_READRATEAVERAGE, TRUE, L"Read Rate Average", 70, PH_ALIGN_RIGHT, 2, DT_RIGHT, TRUE);
|
||||
PhAddTreeNewColumnEx(hwnd, ETDSTNC_WRITERATEAVERAGE, TRUE, L"Write Rate Average", 70, PH_ALIGN_RIGHT, 3, DT_RIGHT, TRUE);
|
||||
PhAddTreeNewColumnEx(hwnd, ETDSTNC_TOTALRATEAVERAGE, TRUE, L"Total Rate Average", 70, PH_ALIGN_RIGHT, 4, DT_RIGHT, TRUE);
|
||||
|
||||
TreeNew_SetRedraw(hwnd, TRUE);
|
||||
|
||||
TreeNew_SetSort(hwnd, ETDSTNC_TOTALRATEAVERAGE, DescendingSortOrder);
|
||||
|
||||
EtLoadSettingsDiskTreeList();
|
||||
}
|
||||
|
||||
VOID EtLoadSettingsDiskTreeList()
|
||||
{
|
||||
PPH_STRING settings;
|
||||
PH_INTEGER_PAIR sortSettings;
|
||||
|
||||
settings = PhGetStringSetting(SETTING_NAME_DISK_TREE_LIST_COLUMNS);
|
||||
PhCmLoadSettings(DiskTreeNewHandle, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
sortSettings = PhGetIntegerPairSetting(SETTING_NAME_DISK_TREE_LIST_SORT);
|
||||
TreeNew_SetSort(DiskTreeNewHandle, (ULONG)sortSettings.X, (PH_SORT_ORDER)sortSettings.Y);
|
||||
}
|
||||
|
||||
VOID EtSaveSettingsDiskTreeList()
|
||||
{
|
||||
PPH_STRING settings;
|
||||
PH_INTEGER_PAIR sortSettings;
|
||||
ULONG sortColumn;
|
||||
PH_SORT_ORDER sortOrder;
|
||||
|
||||
if (!DiskTreeNewCreated)
|
||||
return;
|
||||
|
||||
settings = PhCmSaveSettings(DiskTreeNewHandle);
|
||||
PhSetStringSetting2(SETTING_NAME_DISK_TREE_LIST_COLUMNS, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
TreeNew_GetSort(DiskTreeNewHandle, &sortColumn, &sortOrder);
|
||||
sortSettings.X = sortColumn;
|
||||
sortSettings.Y = sortOrder;
|
||||
PhSetIntegerPairSetting(SETTING_NAME_DISK_TREE_LIST_SORT, sortSettings);
|
||||
}
|
||||
|
||||
PET_DISK_NODE EtAddDiskNode(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
)
|
||||
{
|
||||
PET_DISK_NODE diskNode;
|
||||
|
||||
diskNode = PhAllocate(sizeof(ET_DISK_NODE));
|
||||
memset(diskNode, 0, sizeof(ET_DISK_NODE));
|
||||
PhInitializeTreeNewNode(&diskNode->Node);
|
||||
|
||||
diskNode->DiskItem = DiskItem;
|
||||
PhReferenceObject(DiskItem);
|
||||
|
||||
memset(diskNode->TextCache, 0, sizeof(PH_STRINGREF) * ETDSTNC_MAXIMUM);
|
||||
diskNode->Node.TextCache = diskNode->TextCache;
|
||||
diskNode->Node.TextCacheSize = ETDSTNC_MAXIMUM;
|
||||
|
||||
diskNode->ProcessNameText = EtpGetDiskItemProcessName(DiskItem);
|
||||
|
||||
PhAddEntryHashtable(DiskNodeHashtable, &diskNode);
|
||||
PhAddItemList(DiskNodeList, diskNode);
|
||||
|
||||
TreeNew_NodesStructured(DiskTreeNewHandle);
|
||||
|
||||
return diskNode;
|
||||
}
|
||||
|
||||
PET_DISK_NODE EtFindDiskNode(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
)
|
||||
{
|
||||
ET_DISK_NODE lookupDiskNode;
|
||||
PET_DISK_NODE lookupDiskNodePtr = &lookupDiskNode;
|
||||
PET_DISK_NODE *diskNode;
|
||||
|
||||
lookupDiskNode.DiskItem = DiskItem;
|
||||
|
||||
diskNode = (PET_DISK_NODE *)PhFindEntryHashtable(
|
||||
DiskNodeHashtable,
|
||||
&lookupDiskNodePtr
|
||||
);
|
||||
|
||||
if (diskNode)
|
||||
return *diskNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID EtRemoveDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
)
|
||||
{
|
||||
ULONG index;
|
||||
|
||||
// Remove from the hashtable/list and cleanup.
|
||||
|
||||
PhRemoveEntryHashtable(DiskNodeHashtable, &DiskNode);
|
||||
|
||||
if ((index = PhFindItemList(DiskNodeList, DiskNode)) != -1)
|
||||
PhRemoveItemList(DiskNodeList, index);
|
||||
|
||||
if (DiskNode->ProcessNameText) PhDereferenceObject(DiskNode->ProcessNameText);
|
||||
if (DiskNode->ReadRateAverageText) PhDereferenceObject(DiskNode->ReadRateAverageText);
|
||||
if (DiskNode->WriteRateAverageText) PhDereferenceObject(DiskNode->WriteRateAverageText);
|
||||
if (DiskNode->TotalRateAverageText) PhDereferenceObject(DiskNode->TotalRateAverageText);
|
||||
if (DiskNode->TooltipText) PhDereferenceObject(DiskNode->TooltipText);
|
||||
|
||||
PhDereferenceObject(DiskNode->DiskItem);
|
||||
|
||||
PhFree(DiskNode);
|
||||
|
||||
TreeNew_NodesStructured(DiskTreeNewHandle);
|
||||
}
|
||||
|
||||
VOID EtUpdateDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
)
|
||||
{
|
||||
memset(DiskNode->TextCache, 0, sizeof(PH_STRINGREF) * ETDSTNC_MAXIMUM);
|
||||
PhSwapReference(&DiskNode->TooltipText, NULL);
|
||||
|
||||
PhInvalidateTreeNewNode(&DiskNode->Node, TN_CACHE_ICON);
|
||||
TreeNew_NodesStructured(DiskTreeNewHandle);
|
||||
}
|
||||
|
||||
VOID EtpFormatRate(
|
||||
__in ULONG64 ValuePerPeriod,
|
||||
__inout PPH_STRING *Buffer,
|
||||
__out PPH_STRINGREF String
|
||||
)
|
||||
{
|
||||
ULONG64 number;
|
||||
|
||||
number = ValuePerPeriod;
|
||||
number *= 1000;
|
||||
number /= PhGetIntegerSetting(L"UpdateInterval");
|
||||
|
||||
if (number != 0)
|
||||
{
|
||||
PH_FORMAT format[2];
|
||||
|
||||
PhInitFormatSize(&format[0], number);
|
||||
PhInitFormatS(&format[1], L"/s");
|
||||
PhSwapReference2(Buffer, PhFormat(format, 2, 0));
|
||||
*String = (*Buffer)->sr;
|
||||
}
|
||||
}
|
||||
|
||||
#define SORT_FUNCTION(Column) EtpDiskTreeNewCompare##Column
|
||||
|
||||
#define BEGIN_SORT_FUNCTION(Column) static int __cdecl EtpDiskTreeNewCompare##Column( \
|
||||
__in const void *_elem1, \
|
||||
__in const void *_elem2 \
|
||||
) \
|
||||
{ \
|
||||
PET_DISK_NODE node1 = *(PET_DISK_NODE *)_elem1; \
|
||||
PET_DISK_NODE node2 = *(PET_DISK_NODE *)_elem2; \
|
||||
PET_DISK_ITEM diskItem1 = node1->DiskItem; \
|
||||
PET_DISK_ITEM diskItem2 = node2->DiskItem; \
|
||||
int sortResult = 0;
|
||||
|
||||
#define END_SORT_FUNCTION \
|
||||
if (sortResult == 0) \
|
||||
sortResult = PhCompareString(diskItem1->FileNameWin32, diskItem2->FileNameWin32, TRUE); \
|
||||
\
|
||||
return PhModifySort(sortResult, DiskTreeNewSortOrder); \
|
||||
}
|
||||
|
||||
BEGIN_SORT_FUNCTION(Process)
|
||||
{
|
||||
sortResult = PhCompareString(node1->ProcessNameText, node2->ProcessNameText, TRUE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(File)
|
||||
{
|
||||
sortResult = PhCompareString(diskItem1->FileNameWin32, diskItem2->FileNameWin32, TRUE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(ReadRateAverage)
|
||||
{
|
||||
sortResult = uint64cmp(diskItem1->ReadAverage, diskItem2->ReadAverage);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(WriteRateAverage)
|
||||
{
|
||||
sortResult = uint64cmp(diskItem1->WriteAverage, diskItem2->WriteAverage);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(TotalRateAverage)
|
||||
{
|
||||
sortResult = uint64cmp(diskItem1->ReadAverage + diskItem1->WriteAverage, diskItem2->ReadAverage + diskItem2->WriteAverage);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BOOLEAN NTAPI EtpDiskTreeNewCallback(
|
||||
__in HWND hwnd,
|
||||
__in PH_TREENEW_MESSAGE Message,
|
||||
__in_opt PVOID Parameter1,
|
||||
__in_opt PVOID Parameter2,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
PET_DISK_NODE node;
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
case TreeNewGetChildren:
|
||||
{
|
||||
PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
|
||||
|
||||
if (!getChildren->Node)
|
||||
{
|
||||
static PVOID sortFunctions[] =
|
||||
{
|
||||
SORT_FUNCTION(Process),
|
||||
SORT_FUNCTION(File),
|
||||
SORT_FUNCTION(ReadRateAverage),
|
||||
SORT_FUNCTION(WriteRateAverage),
|
||||
SORT_FUNCTION(TotalRateAverage)
|
||||
};
|
||||
int (__cdecl *sortFunction)(const void *, const void *);
|
||||
|
||||
if (DiskTreeNewSortColumn < ETDSTNC_MAXIMUM)
|
||||
sortFunction = sortFunctions[DiskTreeNewSortColumn];
|
||||
else
|
||||
sortFunction = NULL;
|
||||
|
||||
if (sortFunction)
|
||||
{
|
||||
qsort(DiskNodeList->Items, DiskNodeList->Count, sizeof(PVOID), sortFunction);
|
||||
}
|
||||
|
||||
getChildren->Children = (PPH_TREENEW_NODE *)DiskNodeList->Items;
|
||||
getChildren->NumberOfChildren = DiskNodeList->Count;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewIsLeaf:
|
||||
{
|
||||
PPH_TREENEW_IS_LEAF isLeaf = Parameter1;
|
||||
|
||||
isLeaf->IsLeaf = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetCellText:
|
||||
{
|
||||
PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
|
||||
PET_DISK_ITEM diskItem;
|
||||
|
||||
node = (PET_DISK_NODE)getCellText->Node;
|
||||
diskItem = node->DiskItem;
|
||||
|
||||
switch (getCellText->Id)
|
||||
{
|
||||
case ETDSTNC_NAME:
|
||||
getCellText->Text = node->ProcessNameText->sr;
|
||||
break;
|
||||
case ETDSTNC_FILE:
|
||||
getCellText->Text = diskItem->FileNameWin32->sr;
|
||||
break;
|
||||
case ETDSTNC_READRATEAVERAGE:
|
||||
EtpFormatRate(diskItem->ReadAverage, &node->ReadRateAverageText, &getCellText->Text);
|
||||
break;
|
||||
case ETDSTNC_WRITERATEAVERAGE:
|
||||
EtpFormatRate(diskItem->WriteAverage, &node->WriteRateAverageText, &getCellText->Text);
|
||||
break;
|
||||
case ETDSTNC_TOTALRATEAVERAGE:
|
||||
EtpFormatRate(diskItem->ReadAverage + diskItem->WriteAverage, &node->TotalRateAverageText, &getCellText->Text);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
getCellText->Flags = TN_CACHE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetNodeIcon:
|
||||
{
|
||||
PPH_TREENEW_GET_NODE_ICON getNodeIcon = Parameter1;
|
||||
|
||||
node = (PET_DISK_NODE)getNodeIcon->Node;
|
||||
|
||||
if (node->DiskItem->ProcessIconValid)
|
||||
{
|
||||
// TODO: Check if the icon handle is actually valid, since the process item
|
||||
// might get destroyed while the disk node is still valid.
|
||||
getNodeIcon->Icon = node->DiskItem->ProcessIcon;
|
||||
}
|
||||
else
|
||||
{
|
||||
PhGetStockApplicationIcon(&getNodeIcon->Icon, NULL);
|
||||
}
|
||||
|
||||
getNodeIcon->Flags = TN_CACHE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetCellTooltip:
|
||||
{
|
||||
PPH_TREENEW_GET_CELL_TOOLTIP getCellTooltip = Parameter1;
|
||||
PPH_PROCESS_ITEM processItem;
|
||||
|
||||
node = (PET_DISK_NODE)getCellTooltip->Node;
|
||||
|
||||
if (getCellTooltip->Column->Id != 0)
|
||||
return FALSE;
|
||||
|
||||
if (!node->TooltipText)
|
||||
{
|
||||
if (processItem = PhReferenceProcessItem(node->DiskItem->ProcessId))
|
||||
{
|
||||
node->TooltipText = PhCreateString(L"TODO"); // TODO
|
||||
PhDereferenceObject(processItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PhIsNullOrEmptyString(node->TooltipText))
|
||||
{
|
||||
getCellTooltip->Text = node->TooltipText->sr;
|
||||
getCellTooltip->Unfolding = FALSE;
|
||||
getCellTooltip->MaximumWidth = 550;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewSortChanged:
|
||||
{
|
||||
TreeNew_GetSort(hwnd, &DiskTreeNewSortColumn, &DiskTreeNewSortOrder);
|
||||
// Force a rebuild to sort the items.
|
||||
TreeNew_NodesStructured(hwnd);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewKeyDown:
|
||||
{
|
||||
PPH_TREENEW_KEY_EVENT keyEvent = Parameter1;
|
||||
|
||||
switch (keyEvent->VirtualKey)
|
||||
{
|
||||
case 'C':
|
||||
if (GetKeyState(VK_CONTROL) < 0)
|
||||
EtHandleDiskCommand(ID_DISK_COPY);
|
||||
break;
|
||||
case VK_RETURN:
|
||||
EtHandleDiskCommand(ID_DISK_GOTOPROCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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_EMENU_SHOW_NONOTIFY,
|
||||
PH_ALIGN_LEFT | PH_ALIGN_TOP, data.MouseEvent->ScreenLocation.x, data.MouseEvent->ScreenLocation.y);
|
||||
PhHandleTreeNewColumnMenu(&data);
|
||||
PhDeleteTreeNewColumnMenu(&data);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewLeftDoubleClick:
|
||||
{
|
||||
EtHandleDiskCommand(ID_DISK_GOTOPROCESS);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewContextMenu:
|
||||
{
|
||||
PPH_TREENEW_MOUSE_EVENT mouseEvent = Parameter1;
|
||||
|
||||
EtShowDiskContextMenu(mouseEvent->Location);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewDestroying:
|
||||
{
|
||||
EtSaveSettingsDiskTreeList();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PPH_STRING EtpGetDiskItemProcessName(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
)
|
||||
{
|
||||
PH_FORMAT format[4];
|
||||
|
||||
if (!DiskItem->ProcessId)
|
||||
return PhCreateString(L"No Process");
|
||||
|
||||
PhInitFormatS(&format[1], L" (");
|
||||
PhInitFormatU(&format[2], (ULONG)DiskItem->ProcessId);
|
||||
PhInitFormatC(&format[3], ')');
|
||||
|
||||
if (DiskItem->ProcessName)
|
||||
PhInitFormatSR(&format[0], DiskItem->ProcessName->sr);
|
||||
else
|
||||
PhInitFormatS(&format[0], L"Unknown Process");
|
||||
|
||||
return PhFormat(format, 4, 96);
|
||||
}
|
||||
|
||||
PET_DISK_ITEM EtGetSelectedDiskItem()
|
||||
{
|
||||
PET_DISK_ITEM diskItem = NULL;
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < DiskNodeList->Count; i++)
|
||||
{
|
||||
PET_DISK_NODE node = DiskNodeList->Items[i];
|
||||
|
||||
if (node->Node.Selected)
|
||||
{
|
||||
diskItem = node->DiskItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return diskItem;
|
||||
}
|
||||
|
||||
VOID EtGetSelectedDiskItems(
|
||||
__out PET_DISK_ITEM **DiskItems,
|
||||
__out PULONG NumberOfDiskItems
|
||||
)
|
||||
{
|
||||
PPH_LIST list;
|
||||
ULONG i;
|
||||
|
||||
list = PhCreateList(2);
|
||||
|
||||
for (i = 0; i < DiskNodeList->Count; i++)
|
||||
{
|
||||
PET_DISK_NODE node = DiskNodeList->Items[i];
|
||||
|
||||
if (node->Node.Selected)
|
||||
{
|
||||
PhAddItemList(list, node->DiskItem);
|
||||
}
|
||||
}
|
||||
|
||||
*DiskItems = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
|
||||
*NumberOfDiskItems = list->Count;
|
||||
|
||||
PhDereferenceObject(list);
|
||||
}
|
||||
|
||||
VOID EtDeselectAllDiskNodes()
|
||||
{
|
||||
TreeNew_DeselectRange(DiskTreeNewHandle, 0, -1);
|
||||
}
|
||||
|
||||
VOID EtSelectAndEnsureVisibleDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
)
|
||||
{
|
||||
EtDeselectAllDiskNodes();
|
||||
|
||||
if (!DiskNode->Node.Visible)
|
||||
return;
|
||||
|
||||
TreeNew_SetFocusNode(DiskTreeNewHandle, &DiskNode->Node);
|
||||
TreeNew_SetMarkNode(DiskTreeNewHandle, &DiskNode->Node);
|
||||
TreeNew_SelectRange(DiskTreeNewHandle, DiskNode->Node.Index, DiskNode->Node.Index);
|
||||
TreeNew_EnsureVisible(DiskTreeNewHandle, &DiskNode->Node);
|
||||
}
|
||||
|
||||
VOID EtCopyDiskList()
|
||||
{
|
||||
PPH_FULL_STRING text;
|
||||
|
||||
text = PhGetTreeNewText(DiskTreeNewHandle, ETDSTNC_MAXIMUM);
|
||||
PhSetClipboardStringEx(DiskTreeNewHandle, text->Buffer, text->Length);
|
||||
PhDereferenceObject(text);
|
||||
}
|
||||
|
||||
VOID EtWriteDiskList(
|
||||
__inout PPH_FILE_STREAM FileStream,
|
||||
__in ULONG Mode
|
||||
)
|
||||
{
|
||||
PPH_LIST lines;
|
||||
ULONG i;
|
||||
|
||||
lines = PhGetGenericTreeNewLines(DiskTreeNewHandle, Mode);
|
||||
|
||||
for (i = 0; i < lines->Count; i++)
|
||||
{
|
||||
PPH_STRING line;
|
||||
|
||||
line = lines->Items[i];
|
||||
PhWriteStringAsAnsiFileStream(FileStream, &line->sr);
|
||||
PhDereferenceObject(line);
|
||||
PhWriteStringAsAnsiFileStream2(FileStream, L"\r\n");
|
||||
}
|
||||
|
||||
PhDereferenceObject(lines);
|
||||
}
|
||||
|
||||
VOID EtHandleDiskCommand(
|
||||
__in ULONG Id
|
||||
)
|
||||
{
|
||||
switch (Id)
|
||||
{
|
||||
case ID_DISK_GOTOPROCESS:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID EtpInitializeDiskMenu(
|
||||
__in PPH_EMENU Menu,
|
||||
__in PET_DISK_ITEM *DiskItems,
|
||||
__in ULONG NumberOfDiskItems
|
||||
)
|
||||
{
|
||||
if (NumberOfDiskItems == 0)
|
||||
{
|
||||
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
}
|
||||
else if (NumberOfDiskItems == 1)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
PhEnableEMenuItem(Menu, ID_DISK_COPY, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
VOID EtShowDiskContextMenu(
|
||||
__in POINT Location
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM *diskItems;
|
||||
ULONG numberOfDiskItems;
|
||||
|
||||
EtGetSelectedDiskItems(&diskItems, &numberOfDiskItems);
|
||||
|
||||
if (numberOfDiskItems != 0)
|
||||
{
|
||||
PPH_EMENU menu;
|
||||
PPH_EMENU_ITEM item;
|
||||
|
||||
menu = PhCreateEMenu();
|
||||
PhLoadResourceEMenuItem(menu, PluginInstance->DllBase, MAKEINTRESOURCE(IDR_DISK), 0);
|
||||
PhSetFlagsEMenuItem(menu, ID_DISK_GOTOPROCESS, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
|
||||
|
||||
EtpInitializeDiskMenu(menu, diskItems, numberOfDiskItems);
|
||||
|
||||
item = PhShowEMenu(
|
||||
menu,
|
||||
PhMainWndHandle,
|
||||
PH_EMENU_SHOW_LEFTRIGHT,
|
||||
PH_ALIGN_LEFT | PH_ALIGN_TOP,
|
||||
Location.x,
|
||||
Location.y
|
||||
);
|
||||
|
||||
if (item)
|
||||
{
|
||||
EtHandleDiskCommand(item->Id);
|
||||
}
|
||||
|
||||
PhDestroyEMenu(menu);
|
||||
}
|
||||
|
||||
PhFree(diskItems);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpDiskItemAddedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = (PET_DISK_ITEM)Parameter;
|
||||
|
||||
PhReferenceObject(diskItem);
|
||||
ProcessHacker_Invoke(PhMainWndHandle, EtpOnDiskItemAdded, diskItem);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpDiskItemModifiedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
ProcessHacker_Invoke(PhMainWndHandle, EtpOnDiskItemModified, (PET_DISK_ITEM)Parameter);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpDiskItemRemovedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
ProcessHacker_Invoke(PhMainWndHandle, EtpOnDiskItemRemoved, (PET_DISK_ITEM)Parameter);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpDiskItemsUpdatedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
ProcessHacker_Invoke(PhMainWndHandle, EtpOnDiskItemsUpdated, NULL);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpOnDiskItemAdded(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = Parameter;
|
||||
PET_DISK_NODE diskNode;
|
||||
|
||||
if (!DiskNeedsRedraw)
|
||||
{
|
||||
TreeNew_SetRedraw(DiskTreeNewHandle, FALSE);
|
||||
DiskNeedsRedraw = TRUE;
|
||||
}
|
||||
|
||||
diskNode = EtAddDiskNode(diskItem);
|
||||
PhDereferenceObject(diskItem);
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpOnDiskItemModified(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = Parameter;
|
||||
|
||||
EtUpdateDiskNode(EtFindDiskNode(diskItem));
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpOnDiskItemRemoved(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = Parameter;
|
||||
|
||||
if (!DiskNeedsRedraw)
|
||||
{
|
||||
TreeNew_SetRedraw(DiskTreeNewHandle, FALSE);
|
||||
DiskNeedsRedraw = TRUE;
|
||||
}
|
||||
|
||||
EtRemoveDiskNode(EtFindDiskNode(diskItem));
|
||||
}
|
||||
|
||||
static VOID NTAPI EtpOnDiskItemsUpdated(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (DiskNeedsRedraw)
|
||||
{
|
||||
TreeNew_SetRedraw(DiskTreeNewHandle, TRUE);
|
||||
DiskNeedsRedraw = FALSE;
|
||||
}
|
||||
|
||||
// Text invalidation
|
||||
|
||||
for (i = 0; i < DiskNodeList->Count; i++)
|
||||
{
|
||||
PET_DISK_NODE node = DiskNodeList->Items[i];
|
||||
|
||||
// The name and file name never change, so we don't invalidate that.
|
||||
memset(&node->TextCache[2], 0, sizeof(PH_STRINGREF) * (ETDSTNC_MAXIMUM - 2));
|
||||
}
|
||||
|
||||
InvalidateRect(DiskTreeNewHandle, NULL, FALSE);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#ifndef DISKTABP_H
|
||||
#define DISKTABP_H
|
||||
|
||||
HWND NTAPI EtpDiskTabCreateFunction(
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI EtpDiskTabSaveContentCallback(
|
||||
__in PVOID Parameter1,
|
||||
__in PVOID Parameter2,
|
||||
__in PVOID Parameter3,
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
BOOLEAN EtpDiskNodeHashtableCompareFunction(
|
||||
__in PVOID Entry1,
|
||||
__in PVOID Entry2
|
||||
);
|
||||
|
||||
ULONG EtpDiskNodeHashtableHashFunction(
|
||||
__in PVOID Entry
|
||||
);
|
||||
|
||||
VOID EtInitializeDiskTreeList(
|
||||
__in HWND hwnd
|
||||
);
|
||||
|
||||
PET_DISK_NODE EtAddDiskNode(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
);
|
||||
|
||||
PET_DISK_NODE EtFindDiskNode(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
);
|
||||
|
||||
VOID EtRemoveDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
);
|
||||
|
||||
VOID EtUpdateDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
);
|
||||
|
||||
BOOLEAN NTAPI EtpDiskTreeNewCallback(
|
||||
__in HWND hwnd,
|
||||
__in PH_TREENEW_MESSAGE Message,
|
||||
__in_opt PVOID Parameter1,
|
||||
__in_opt PVOID Parameter2,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
PPH_STRING EtpGetDiskItemProcessName(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
);
|
||||
|
||||
PET_DISK_ITEM EtGetSelectedDiskItem();
|
||||
|
||||
VOID EtGetSelectedDiskItems(
|
||||
__out PET_DISK_ITEM **DiskItems,
|
||||
__out PULONG NumberOfDiskItems
|
||||
);
|
||||
|
||||
VOID EtDeselectAllDiskNodes();
|
||||
|
||||
VOID EtSelectAndEnsureVisibleDiskNode(
|
||||
__in PET_DISK_NODE DiskNode
|
||||
);
|
||||
|
||||
VOID EtCopyDiskList();
|
||||
|
||||
VOID EtWriteDiskList(
|
||||
__inout PPH_FILE_STREAM FileStream,
|
||||
__in ULONG Mode
|
||||
);
|
||||
|
||||
VOID EtHandleDiskCommand(
|
||||
__in ULONG Id
|
||||
);
|
||||
|
||||
VOID EtpInitializeDiskMenu(
|
||||
__in PPH_EMENU Menu,
|
||||
__in PET_DISK_ITEM *DiskItems,
|
||||
__in ULONG NumberOfDiskItems
|
||||
);
|
||||
|
||||
VOID EtShowDiskContextMenu(
|
||||
__in POINT Location
|
||||
);
|
||||
|
||||
VOID NTAPI EtpDiskItemAddedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI EtpDiskItemModifiedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI EtpDiskItemRemovedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI EtpDiskItemsUpdatedHandler(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI EtpOnDiskItemAdded(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
VOID NTAPI EtpOnDiskItemModified(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
VOID NTAPI EtpOnDiskItemRemoved(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
VOID NTAPI EtpOnDiskItemsUpdated(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
* Process Hacker Extended Tools -
|
||||
* ETW disk monitoring
|
||||
*
|
||||
* Copyright (C) 2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Process Hacker is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "exttools.h"
|
||||
#include "etwmon.h"
|
||||
|
||||
typedef struct _ETP_DISK_PACKET
|
||||
{
|
||||
SINGLE_LIST_ENTRY ListEntry;
|
||||
ET_ETW_DISK_EVENT Event;
|
||||
PPH_STRING FileName;
|
||||
} ETP_DISK_PACKET, *PETP_DISK_PACKET;
|
||||
|
||||
VOID NTAPI EtpDiskItemDeleteProcedure(
|
||||
__in PVOID Object,
|
||||
__in ULONG Flags
|
||||
);
|
||||
|
||||
BOOLEAN NTAPI EtpDiskHashtableCompareFunction(
|
||||
__in PVOID Entry1,
|
||||
__in PVOID Entry2
|
||||
);
|
||||
|
||||
ULONG NTAPI EtpDiskHashtableHashFunction(
|
||||
__in PVOID Entry
|
||||
);
|
||||
|
||||
VOID NTAPI ProcessesUpdatedCallback(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
BOOLEAN EtDiskEnabled = FALSE;
|
||||
|
||||
PPH_OBJECT_TYPE EtDiskItemType;
|
||||
PPH_HASHTABLE EtDiskHashtable;
|
||||
PH_QUEUED_LOCK EtDiskHashtableLock = PH_QUEUED_LOCK_INIT;
|
||||
LIST_ENTRY EtDiskAgeListHead;
|
||||
PH_CALLBACK_DECLARE(EtDiskItemAddedEvent);
|
||||
PH_CALLBACK_DECLARE(EtDiskItemModifiedEvent);
|
||||
PH_CALLBACK_DECLARE(EtDiskItemRemovedEvent);
|
||||
PH_CALLBACK_DECLARE(EtDiskItemsUpdatedEvent);
|
||||
|
||||
PH_FREE_LIST EtDiskPacketFreeList;
|
||||
SLIST_HEADER EtDiskPacketListHead;
|
||||
PPH_HASHTABLE EtFileNameHashtable;
|
||||
PH_QUEUED_LOCK EtFileNameHashtableLock = PH_QUEUED_LOCK_INIT;
|
||||
|
||||
static PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration;
|
||||
|
||||
VOID EtInitializeDiskInformation()
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
EtDiskEnabled = TRUE;
|
||||
|
||||
if (!NT_SUCCESS(status = PhCreateObjectType(
|
||||
&EtDiskItemType,
|
||||
L"DiskItem",
|
||||
0,
|
||||
EtpDiskItemDeleteProcedure
|
||||
)))
|
||||
PhRaiseStatus(status);
|
||||
|
||||
EtDiskHashtable = PhCreateHashtable(
|
||||
sizeof(PET_DISK_ITEM),
|
||||
EtpDiskHashtableCompareFunction,
|
||||
EtpDiskHashtableHashFunction,
|
||||
128
|
||||
);
|
||||
InitializeListHead(&EtDiskAgeListHead);
|
||||
|
||||
PhInitializeFreeList(&EtDiskPacketFreeList, sizeof(ETP_DISK_PACKET), 64);
|
||||
RtlInitializeSListHead(&EtDiskPacketListHead);
|
||||
EtFileNameHashtable = PhCreateSimpleHashtable(128);
|
||||
|
||||
// Collect all existing file names.
|
||||
EtStartEtwRundown();
|
||||
|
||||
PhRegisterCallback(
|
||||
&PhProcessesUpdatedEvent,
|
||||
ProcessesUpdatedCallback,
|
||||
NULL,
|
||||
&ProcessesUpdatedCallbackRegistration
|
||||
);
|
||||
}
|
||||
|
||||
PET_DISK_ITEM EtCreateDiskItem()
|
||||
{
|
||||
PET_DISK_ITEM diskItem;
|
||||
|
||||
if (!NT_SUCCESS(PhCreateObject(
|
||||
&diskItem,
|
||||
sizeof(ET_DISK_ITEM),
|
||||
0,
|
||||
EtDiskItemType
|
||||
)))
|
||||
return NULL;
|
||||
|
||||
memset(diskItem, 0, sizeof(ET_DISK_ITEM));
|
||||
|
||||
return diskItem;
|
||||
}
|
||||
|
||||
VOID NTAPI EtpDiskItemDeleteProcedure(
|
||||
__in PVOID Object,
|
||||
__in ULONG Flags
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = Object;
|
||||
|
||||
if (diskItem->FileName) PhDereferenceObject(diskItem->FileName);
|
||||
if (diskItem->FileNameWin32) PhDereferenceObject(diskItem->FileNameWin32);
|
||||
if (diskItem->ProcessName) PhDereferenceObject(diskItem->ProcessName);
|
||||
}
|
||||
|
||||
// Copied from srvprv.c
|
||||
/**
|
||||
* Generates a hash code for a string, case-insensitive.
|
||||
*
|
||||
* \param String The string.
|
||||
* \param Count The number of characters to hash.
|
||||
*/
|
||||
FORCEINLINE ULONG EtpHashStringIgnoreCase(
|
||||
__in PWSTR String,
|
||||
__in ULONG Count
|
||||
)
|
||||
{
|
||||
ULONG hash = Count;
|
||||
|
||||
if (Count == 0)
|
||||
return 0;
|
||||
|
||||
do
|
||||
{
|
||||
hash = RtlUpcaseUnicodeChar(*String) + (hash << 6) + (hash << 16) - hash;
|
||||
String++;
|
||||
} while (--Count != 0);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
BOOLEAN NTAPI EtpDiskHashtableCompareFunction(
|
||||
__in PVOID Entry1,
|
||||
__in PVOID Entry2
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem1 = *(PET_DISK_ITEM *)Entry1;
|
||||
PET_DISK_ITEM diskItem2 = *(PET_DISK_ITEM *)Entry2;
|
||||
|
||||
return diskItem1->ProcessId == diskItem2->ProcessId && PhEqualString(diskItem1->FileName, diskItem2->FileName, TRUE);
|
||||
}
|
||||
|
||||
ULONG NTAPI EtpDiskHashtableHashFunction(
|
||||
__in PVOID Entry
|
||||
)
|
||||
{
|
||||
PET_DISK_ITEM diskItem = *(PET_DISK_ITEM *)Entry;
|
||||
|
||||
return ((ULONG)diskItem->ProcessId / 4) ^ EtpHashStringIgnoreCase(diskItem->FileName->Buffer, diskItem->FileName->Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
PET_DISK_ITEM EtReferenceDiskItem(
|
||||
__in HANDLE ProcessId,
|
||||
__in PPH_STRING FileName
|
||||
)
|
||||
{
|
||||
ET_DISK_ITEM lookupDiskItem;
|
||||
PET_DISK_ITEM lookupDiskItemPtr = &lookupDiskItem;
|
||||
PET_DISK_ITEM *diskItemPtr;
|
||||
PET_DISK_ITEM diskItem;
|
||||
|
||||
lookupDiskItem.ProcessId = ProcessId;
|
||||
lookupDiskItem.FileName = FileName;
|
||||
|
||||
PhAcquireQueuedLockShared(&EtDiskHashtableLock);
|
||||
|
||||
diskItemPtr = (PET_DISK_ITEM *)PhFindEntryHashtable(
|
||||
EtDiskHashtable,
|
||||
&lookupDiskItemPtr
|
||||
);
|
||||
|
||||
if (diskItemPtr)
|
||||
{
|
||||
diskItem = *diskItemPtr;
|
||||
PhReferenceObject(diskItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
diskItem = NULL;
|
||||
}
|
||||
|
||||
PhReleaseQueuedLockShared(&EtDiskHashtableLock);
|
||||
|
||||
return diskItem;
|
||||
}
|
||||
|
||||
__assumeLocked VOID EtpRemoveDiskItem(
|
||||
__in PET_DISK_ITEM DiskItem
|
||||
)
|
||||
{
|
||||
RemoveEntryList(&DiskItem->AgeListEntry);
|
||||
PhRemoveEntryHashtable(EtDiskHashtable, &DiskItem);
|
||||
PhDereferenceObject(DiskItem);
|
||||
}
|
||||
|
||||
VOID EtDiskProcessDiskEvent(
|
||||
__in PET_ETW_DISK_EVENT Event
|
||||
)
|
||||
{
|
||||
PETP_DISK_PACKET packet;
|
||||
|
||||
if (!EtDiskEnabled)
|
||||
return;
|
||||
|
||||
packet = PhAllocateFromFreeList(&EtDiskPacketFreeList);
|
||||
memcpy(&packet->Event, Event, sizeof(ET_ETW_DISK_EVENT));
|
||||
packet->FileName = EtFileObjectToFileName(Event->FileObject);
|
||||
RtlInterlockedPushEntrySList(&EtDiskPacketListHead, &packet->ListEntry);
|
||||
}
|
||||
|
||||
VOID EtDiskProcessFileEvent(
|
||||
__in PET_ETW_FILE_EVENT Event
|
||||
)
|
||||
{
|
||||
PH_KEY_VALUE_PAIR pair;
|
||||
PPH_KEY_VALUE_PAIR realPair;
|
||||
|
||||
if (!EtDiskEnabled)
|
||||
return;
|
||||
|
||||
if (Event->Type == EtEtwFileCreateType || Event->Type == EtEtwFileRundownType)
|
||||
{
|
||||
pair.Key = Event->FileObject;
|
||||
pair.Value = NULL;
|
||||
|
||||
PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock);
|
||||
|
||||
realPair = PhAddEntryHashtableEx(EtFileNameHashtable, &pair, NULL);
|
||||
PhSwapReference2(&realPair->Value, PhCreateStringEx(Event->FileName.Buffer, Event->FileName.Length));
|
||||
|
||||
PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock);
|
||||
}
|
||||
else if (Event->Type == EtEtwFileDeleteType)
|
||||
{
|
||||
pair.Key = Event->FileObject;
|
||||
|
||||
PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock);
|
||||
|
||||
realPair = PhFindEntryHashtable(EtFileNameHashtable, &pair);
|
||||
|
||||
if (realPair)
|
||||
{
|
||||
PhDereferenceObject(realPair->Value);
|
||||
PhRemoveEntryHashtable(EtFileNameHashtable, &pair);
|
||||
}
|
||||
|
||||
PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock);
|
||||
}
|
||||
}
|
||||
|
||||
PPH_STRING EtFileObjectToFileName(
|
||||
__in PVOID FileObject
|
||||
)
|
||||
{
|
||||
PH_KEY_VALUE_PAIR pair;
|
||||
PPH_KEY_VALUE_PAIR realPair;
|
||||
PPH_STRING fileName;
|
||||
|
||||
pair.Key = FileObject;
|
||||
fileName = NULL;
|
||||
|
||||
PhAcquireQueuedLockShared(&EtFileNameHashtableLock);
|
||||
|
||||
realPair = PhFindEntryHashtable(EtFileNameHashtable, &pair);
|
||||
|
||||
if (realPair)
|
||||
{
|
||||
fileName = realPair->Value;
|
||||
PhReferenceObject(fileName);
|
||||
}
|
||||
|
||||
PhReleaseQueuedLockShared(&EtFileNameHashtableLock);
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
VOID EtpProcessDiskPacket(
|
||||
__in PETP_DISK_PACKET Packet,
|
||||
__in ULONG RunId
|
||||
)
|
||||
{
|
||||
PET_ETW_DISK_EVENT diskEvent;
|
||||
PET_DISK_ITEM diskItem;
|
||||
BOOLEAN added = FALSE;
|
||||
|
||||
diskEvent = &Packet->Event;
|
||||
|
||||
// We only process non-zero read/write events.
|
||||
if (diskEvent->Type != EtEtwDiskReadType && diskEvent->Type != EtEtwDiskWriteType)
|
||||
return;
|
||||
if (diskEvent->TransferSize == 0)
|
||||
return;
|
||||
|
||||
// Ignore packets with no file name - this is useless to the user.
|
||||
if (!Packet->FileName)
|
||||
return;
|
||||
|
||||
diskItem = EtReferenceDiskItem(diskEvent->ClientId.UniqueProcess, Packet->FileName);
|
||||
|
||||
if (!diskItem)
|
||||
{
|
||||
PPH_PROCESS_ITEM processItem;
|
||||
|
||||
// Disk item not found (or the address was re-used), create it.
|
||||
|
||||
diskItem = EtCreateDiskItem();
|
||||
|
||||
diskItem->ProcessId = diskEvent->ClientId.UniqueProcess;
|
||||
diskItem->FileName = Packet->FileName;
|
||||
PhReferenceObject(Packet->FileName);
|
||||
diskItem->FileNameWin32 = PhGetFileName(diskItem->FileName);
|
||||
|
||||
if (processItem = PhReferenceProcessItem(diskItem->ProcessId))
|
||||
{
|
||||
diskItem->ProcessName = processItem->ProcessName;
|
||||
PhReferenceObject(processItem->ProcessName);
|
||||
|
||||
if (PhTestEvent(&processItem->Stage1Event))
|
||||
{
|
||||
diskItem->ProcessIcon = processItem->SmallIcon;
|
||||
diskItem->ProcessIconValid = TRUE;
|
||||
}
|
||||
|
||||
PhDereferenceObject(processItem);
|
||||
}
|
||||
|
||||
// Add the disk item to the age list.
|
||||
diskItem->AddTime = RunId;
|
||||
diskItem->FreshTime = RunId;
|
||||
InsertHeadList(&EtDiskAgeListHead, &diskItem->AgeListEntry);
|
||||
|
||||
// Add the disk item to the hashtable.
|
||||
PhAcquireQueuedLockExclusive(&EtDiskHashtableLock);
|
||||
PhAddEntryHashtable(EtDiskHashtable, &diskItem);
|
||||
PhReleaseQueuedLockExclusive(&EtDiskHashtableLock);
|
||||
|
||||
// Raise the disk item added event.
|
||||
PhInvokeCallback(&EtDiskItemAddedEvent, diskItem);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
// Accumulate statistics for this update period.
|
||||
if (diskEvent->Type == EtEtwDiskReadType)
|
||||
diskItem->ReadDelta += diskEvent->TransferSize;
|
||||
else
|
||||
diskItem->WriteDelta += diskEvent->TransferSize;
|
||||
|
||||
if (!added)
|
||||
{
|
||||
if (diskItem->FreshTime != RunId)
|
||||
{
|
||||
diskItem->FreshTime = RunId;
|
||||
RemoveEntryList(&diskItem->AgeListEntry);
|
||||
InsertHeadList(&EtDiskAgeListHead, &diskItem->AgeListEntry);
|
||||
}
|
||||
|
||||
PhDereferenceObject(diskItem);
|
||||
}
|
||||
}
|
||||
|
||||
ULONG64 EtpCalculateAverage(
|
||||
__in PULONG64 Buffer,
|
||||
__in ULONG BufferSize,
|
||||
__in ULONG BufferPosition,
|
||||
__in ULONG BufferCount,
|
||||
__in ULONG NumberToConsider
|
||||
)
|
||||
{
|
||||
ULONG64 sum;
|
||||
ULONG i;
|
||||
ULONG count;
|
||||
|
||||
sum = 0;
|
||||
i = BufferPosition;
|
||||
|
||||
if (NumberToConsider > BufferCount)
|
||||
NumberToConsider = BufferCount;
|
||||
|
||||
if (NumberToConsider == 0)
|
||||
return 0;
|
||||
|
||||
count = NumberToConsider;
|
||||
|
||||
do
|
||||
{
|
||||
sum += Buffer[i];
|
||||
i++;
|
||||
|
||||
if (i == BufferSize)
|
||||
i = 0;
|
||||
} while (--count != 0);
|
||||
|
||||
return sum / NumberToConsider;
|
||||
}
|
||||
|
||||
static VOID NTAPI ProcessesUpdatedCallback(
|
||||
__in_opt PVOID Parameter,
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
static ULONG runCount = 0;
|
||||
|
||||
PSINGLE_LIST_ENTRY listEntry;
|
||||
PLIST_ENTRY ageListEntry;
|
||||
|
||||
// Process incoming disk event packets.
|
||||
|
||||
listEntry = RtlInterlockedFlushSList(&EtDiskPacketListHead);
|
||||
|
||||
while (listEntry)
|
||||
{
|
||||
PETP_DISK_PACKET packet;
|
||||
|
||||
packet = CONTAINING_RECORD(listEntry, ETP_DISK_PACKET, ListEntry);
|
||||
listEntry = listEntry->Next;
|
||||
|
||||
EtpProcessDiskPacket(packet, runCount);
|
||||
|
||||
if (packet->FileName)
|
||||
PhDereferenceObject(packet->FileName);
|
||||
|
||||
PhFreeToFreeList(&EtDiskPacketFreeList, packet);
|
||||
}
|
||||
|
||||
// Remove old entries.
|
||||
|
||||
ageListEntry = EtDiskAgeListHead.Blink;
|
||||
|
||||
while (ageListEntry != &EtDiskAgeListHead)
|
||||
{
|
||||
PET_DISK_ITEM diskItem;
|
||||
|
||||
diskItem = CONTAINING_RECORD(ageListEntry, ET_DISK_ITEM, AgeListEntry);
|
||||
ageListEntry = ageListEntry->Blink;
|
||||
|
||||
if (runCount - diskItem->FreshTime < HISTORY_SIZE) // must compare like this to avoid overflow/underflow problems
|
||||
break;
|
||||
|
||||
PhInvokeCallback(&EtDiskItemRemovedEvent, diskItem);
|
||||
|
||||
PhAcquireQueuedLockExclusive(&EtDiskHashtableLock);
|
||||
EtpRemoveDiskItem(diskItem);
|
||||
PhReleaseQueuedLockExclusive(&EtDiskHashtableLock);
|
||||
}
|
||||
|
||||
// Update existing items.
|
||||
|
||||
ageListEntry = EtDiskAgeListHead.Flink;
|
||||
|
||||
while (ageListEntry != &EtDiskAgeListHead)
|
||||
{
|
||||
PET_DISK_ITEM diskItem;
|
||||
|
||||
diskItem = CONTAINING_RECORD(ageListEntry, ET_DISK_ITEM, AgeListEntry);
|
||||
|
||||
// Update statistics.
|
||||
|
||||
if (diskItem->HistoryPosition != 0)
|
||||
diskItem->HistoryPosition--;
|
||||
else
|
||||
diskItem->HistoryPosition = HISTORY_SIZE - 1;
|
||||
|
||||
diskItem->ReadHistory[diskItem->HistoryPosition] = diskItem->ReadDelta;
|
||||
diskItem->WriteHistory[diskItem->HistoryPosition] = diskItem->WriteDelta;
|
||||
|
||||
if (diskItem->HistoryCount < HISTORY_SIZE)
|
||||
diskItem->HistoryCount++;
|
||||
|
||||
diskItem->ReadTotal += diskItem->ReadDelta;
|
||||
diskItem->WriteTotal += diskItem->WriteDelta;
|
||||
diskItem->ReadDelta = 0;
|
||||
diskItem->WriteDelta = 0;
|
||||
diskItem->ReadAverage = EtpCalculateAverage(diskItem->ReadHistory, HISTORY_SIZE, diskItem->HistoryPosition, diskItem->HistoryCount, HISTORY_SIZE);
|
||||
diskItem->WriteAverage = EtpCalculateAverage(diskItem->WriteHistory, HISTORY_SIZE, diskItem->HistoryPosition, diskItem->HistoryCount, HISTORY_SIZE);
|
||||
|
||||
if (diskItem->AddTime != runCount)
|
||||
{
|
||||
BOOLEAN modified = FALSE;
|
||||
PPH_PROCESS_ITEM processItem;
|
||||
|
||||
if (!diskItem->ProcessName || !diskItem->ProcessIconValid)
|
||||
{
|
||||
if (processItem = PhReferenceProcessItem(diskItem->ProcessId))
|
||||
{
|
||||
if (!diskItem->ProcessName)
|
||||
{
|
||||
diskItem->ProcessName = processItem->ProcessName;
|
||||
PhReferenceObject(processItem->ProcessName);
|
||||
modified = TRUE;
|
||||
}
|
||||
|
||||
if (!diskItem->ProcessIconValid && PhTestEvent(&processItem->Stage1Event))
|
||||
{
|
||||
diskItem->ProcessIcon = processItem->SmallIcon;
|
||||
diskItem->ProcessIconValid = TRUE;
|
||||
modified = TRUE;
|
||||
}
|
||||
|
||||
PhDereferenceObject(processItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
// Raise the disk item modified event.
|
||||
PhInvokeCallback(&EtDiskItemModifiedEvent, diskItem);
|
||||
}
|
||||
}
|
||||
|
||||
ageListEntry = ageListEntry->Flink;
|
||||
}
|
||||
|
||||
PhInvokeCallback(&EtDiskItemsUpdatedEvent, NULL);
|
||||
runCount++;
|
||||
}
|
||||
@@ -35,24 +35,44 @@ NTSTATUS EtpEtwMonitorThreadStart(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
ULONG NTAPI EtpRundownEtwBufferCallback(
|
||||
__in PEVENT_TRACE_LOGFILE Buffer
|
||||
);
|
||||
|
||||
VOID NTAPI EtpRundownEtwEventCallback(
|
||||
__in PEVENT_RECORD EventRecord
|
||||
);
|
||||
|
||||
NTSTATUS EtpRundownEtwMonitorThreadStart(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
static GUID SystemTraceControlGuid_I = { 0x9e814aad, 0x3204, 0x11d2, { 0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39 } };
|
||||
static GUID KernelRundownGuid_I = { 0x3b9c9951, 0x3480, 0x4220, { 0x93, 0x77, 0x9c, 0x8e, 0x51, 0x84, 0xf5, 0xcd } };
|
||||
static GUID DiskIoGuid_I = { 0x3d6fa8d4, 0xfe05, 0x11d0, { 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c } };
|
||||
static GUID FileIoGuid_I = { 0x90cbdc39, 0x4a3e, 0x11d1, { 0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3 } };
|
||||
static GUID TcpIpGuid_I = { 0x9a280ac0, 0xc8e0, 0x11d1, { 0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2 } };
|
||||
static GUID UdpIpGuid_I = { 0xbf3a50c5, 0xa9c9, 0x4988, { 0xa0, 0x05, 0x2d, 0xf0, 0xb7, 0xc8, 0x0f, 0x80 } };
|
||||
|
||||
// ETW interfacing layer
|
||||
// ETW tracing layer
|
||||
|
||||
BOOLEAN EtEtwEnabled;
|
||||
static PH_STRINGREF EtpLoggerName = PH_STRINGREF_INIT(KERNEL_LOGGER_NAME);
|
||||
static TRACEHANDLE EtpSessionHandle;
|
||||
static TRACEHANDLE EtpTraceHandle;
|
||||
static PEVENT_TRACE_PROPERTIES EtpTraceProperties;
|
||||
static EVENT_TRACE_LOGFILE EtpLogFile;
|
||||
static BOOLEAN EtpEtwActive;
|
||||
static BOOLEAN EtpStartedSession;
|
||||
static BOOLEAN EtpEtwExiting;
|
||||
static HANDLE EtpEtwMonitorThreadHandle;
|
||||
|
||||
// ETW rundown layer
|
||||
|
||||
static PH_STRINGREF EtpRundownLoggerName = PH_STRINGREF_INIT(L"PhEtRundownLogger");
|
||||
static TRACEHANDLE EtpRundownSessionHandle;
|
||||
static PEVENT_TRACE_PROPERTIES EtpRundownTraceProperties;
|
||||
static BOOLEAN EtpRundownActive;
|
||||
static HANDLE EtpRundownEtwMonitorThreadHandle;
|
||||
|
||||
VOID EtEtwMonitorInitialization()
|
||||
{
|
||||
if (PhElevated && PhGetIntegerSetting(SETTING_NAME_ENABLE_ETW_MONITOR))
|
||||
@@ -71,6 +91,12 @@ VOID EtEtwMonitorUninitialization()
|
||||
EtpEtwExiting = TRUE;
|
||||
EtStopEtwSession();
|
||||
}
|
||||
|
||||
if (EtpRundownActive)
|
||||
{
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
VOID EtStartEtwSession()
|
||||
@@ -92,7 +118,7 @@ VOID EtStartEtwSession()
|
||||
EtpTraceProperties->MinimumBuffers = 1;
|
||||
EtpTraceProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
||||
EtpTraceProperties->FlushTimer = 1;
|
||||
EtpTraceProperties->EnableFlags = EVENT_TRACE_FLAG_DISK_IO | EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
||||
EtpTraceProperties->EnableFlags = EVENT_TRACE_FLAG_DISK_IO | EVENT_TRACE_FLAG_DISK_FILE_IO | EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
||||
EtpTraceProperties->LogFileNameOffset = 0;
|
||||
EtpTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
||||
|
||||
@@ -165,6 +191,7 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
ET_ETW_DISK_EVENT diskEvent;
|
||||
|
||||
memset(&diskEvent, 0, sizeof(ET_ETW_DISK_EVENT));
|
||||
diskEvent.Type = -1;
|
||||
|
||||
switch (EventTrace->Header.Class.Type)
|
||||
{
|
||||
@@ -178,7 +205,7 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
break;
|
||||
}
|
||||
|
||||
if (diskEvent.Type != 0)
|
||||
if (diskEvent.Type != -1)
|
||||
{
|
||||
DiskIo_TypeGroup1 *data = EventTrace->MofData;
|
||||
|
||||
@@ -189,8 +216,45 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
}
|
||||
|
||||
diskEvent.TransferSize = data->TransferSize;
|
||||
diskEvent.FileObject = (PVOID)data->FileObject;
|
||||
diskEvent.HighResResponseTime = data->HighResResponseTime;
|
||||
|
||||
EtProcessDiskEvent(&diskEvent);
|
||||
EtDiskProcessDiskEvent(&diskEvent);
|
||||
}
|
||||
}
|
||||
else if (memcmp(&EventTrace->Header.Guid, &FileIoGuid_I, sizeof(GUID)) == 0)
|
||||
{
|
||||
// FileIo
|
||||
|
||||
ET_ETW_FILE_EVENT fileEvent;
|
||||
|
||||
memset(&fileEvent, 0, sizeof(ET_ETW_FILE_EVENT));
|
||||
fileEvent.Type = -1;
|
||||
|
||||
switch (EventTrace->Header.Class.Type)
|
||||
{
|
||||
case 0: // Name
|
||||
fileEvent.Type = EtEtwFileNameType;
|
||||
break;
|
||||
case 32: // FileCreate
|
||||
fileEvent.Type = EtEtwFileCreateType;
|
||||
break;
|
||||
case 35: // FileDelete
|
||||
fileEvent.Type = EtEtwFileDeleteType;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileEvent.Type != -1)
|
||||
{
|
||||
FileIo_Name *data = EventTrace->MofData;
|
||||
|
||||
fileEvent.FileObject = (PVOID)data->FileObject;
|
||||
PhInitializeStringRef(&fileEvent.FileName, data->FileName);
|
||||
|
||||
EtDiskProcessFileEvent(&fileEvent);
|
||||
}
|
||||
}
|
||||
else if (
|
||||
@@ -203,22 +267,23 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
ET_ETW_NETWORK_EVENT networkEvent;
|
||||
|
||||
memset(&networkEvent, 0, sizeof(ET_ETW_NETWORK_EVENT));
|
||||
networkEvent.Type = -1;
|
||||
|
||||
switch (EventTrace->Header.Class.Type)
|
||||
{
|
||||
case 10: // send
|
||||
case EVENT_TRACE_TYPE_SEND: // send
|
||||
networkEvent.Type = EtEtwNetworkSendType;
|
||||
networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE;
|
||||
break;
|
||||
case 11: // receive
|
||||
case EVENT_TRACE_TYPE_RECEIVE: // receive
|
||||
networkEvent.Type = EtEtwNetworkReceiveType;
|
||||
networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE;
|
||||
break;
|
||||
case 26: // send ipv6
|
||||
case EVENT_TRACE_TYPE_SEND + 16: // send ipv6
|
||||
networkEvent.Type = EtEtwNetworkSendType;
|
||||
networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE;
|
||||
break;
|
||||
case 27: // receive ipv6
|
||||
case EVENT_TRACE_TYPE_RECEIVE + 16: // receive ipv6
|
||||
networkEvent.Type = EtEtwNetworkReceiveType;
|
||||
networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE;
|
||||
break;
|
||||
@@ -229,7 +294,7 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
else
|
||||
networkEvent.ProtocolType |= PH_UDP_PROTOCOL_TYPE;
|
||||
|
||||
if (networkEvent.Type != 0)
|
||||
if (networkEvent.Type != -1)
|
||||
{
|
||||
PH_IP_ENDPOINT source;
|
||||
PH_IP_ENDPOINT destination;
|
||||
@@ -273,29 +338,30 @@ VOID NTAPI EtpEtwEventCallback(
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI EtpEtwMonitorThreadStart(
|
||||
NTSTATUS EtpEtwMonitorThreadStart(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
ULONG result;
|
||||
EVENT_TRACE_LOGFILE logFile;
|
||||
TRACEHANDLE traceHandle;
|
||||
|
||||
memset(&EtpLogFile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
||||
EtpLogFile.LoggerName = EtpLoggerName.Buffer;
|
||||
EtpLogFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME;
|
||||
EtpLogFile.BufferCallback = EtpEtwBufferCallback;
|
||||
EtpLogFile.EventCallback = EtpEtwEventCallback;
|
||||
EtpLogFile.IsKernelTrace = TRUE;
|
||||
memset(&logFile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
||||
logFile.LoggerName = EtpLoggerName.Buffer;
|
||||
logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME;
|
||||
logFile.BufferCallback = EtpEtwBufferCallback;
|
||||
logFile.EventCallback = EtpEtwEventCallback;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
EtpTraceHandle = OpenTrace(&EtpLogFile);
|
||||
traceHandle = OpenTrace(&logFile);
|
||||
|
||||
if (EtpTraceHandle != INVALID_PROCESSTRACE_HANDLE)
|
||||
if (traceHandle != INVALID_PROCESSTRACE_HANDLE)
|
||||
{
|
||||
while (!EtpEtwExiting && (result = ProcessTrace(&EtpTraceHandle, 1, NULL, NULL)) == ERROR_SUCCESS)
|
||||
while (!EtpEtwExiting && (result = ProcessTrace(&traceHandle, 1, NULL, NULL)) == ERROR_SUCCESS)
|
||||
NOTHING;
|
||||
|
||||
CloseTrace(EtpTraceHandle);
|
||||
CloseTrace(traceHandle);
|
||||
}
|
||||
|
||||
if (EtpEtwExiting)
|
||||
@@ -315,3 +381,132 @@ NTSTATUS NTAPI EtpEtwMonitorThreadStart(
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG EtStartEtwRundown()
|
||||
{
|
||||
ULONG result;
|
||||
ULONG bufferSize;
|
||||
|
||||
bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + EtpRundownLoggerName.Length + sizeof(WCHAR);
|
||||
|
||||
if (!EtpRundownTraceProperties)
|
||||
EtpRundownTraceProperties = PhAllocate(bufferSize);
|
||||
|
||||
memset(EtpRundownTraceProperties, 0, sizeof(EVENT_TRACE_PROPERTIES));
|
||||
|
||||
EtpRundownTraceProperties->Wnode.BufferSize = bufferSize;
|
||||
EtpRundownTraceProperties->Wnode.ClientContext = 1;
|
||||
EtpRundownTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
||||
EtpRundownTraceProperties->MinimumBuffers = 1;
|
||||
EtpRundownTraceProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
||||
EtpRundownTraceProperties->FlushTimer = 1;
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
EtpRundownTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
||||
|
||||
result = StartTrace(&EtpRundownSessionHandle, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties);
|
||||
|
||||
if (result == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
|
||||
// ControlTrace screws up the structure.
|
||||
EtpRundownTraceProperties->Wnode.BufferSize = bufferSize;
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
EtpRundownTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
||||
result = StartTrace(&EtpRundownSessionHandle, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties);
|
||||
}
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = EnableTraceEx(&KernelRundownGuid_I, NULL, EtpRundownSessionHandle, 1, 0, 0x10, 0, 0, NULL);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
|
||||
return result;
|
||||
}
|
||||
|
||||
EtpRundownActive = TRUE;
|
||||
EtpRundownEtwMonitorThreadHandle = PhCreateThread(0, EtpRundownEtwMonitorThreadStart, NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ULONG NTAPI EtpRundownEtwBufferCallback(
|
||||
__in PEVENT_TRACE_LOGFILE Buffer
|
||||
)
|
||||
{
|
||||
return !EtpEtwExiting;
|
||||
}
|
||||
|
||||
VOID NTAPI EtpRundownEtwEventCallback(
|
||||
__in PEVENT_RECORD EventRecord
|
||||
)
|
||||
{
|
||||
// TODO: Find a way to call CloseTrace when the enumeration finishes so we can
|
||||
// stop the trace cleanly.
|
||||
|
||||
if (memcmp(&EventRecord->EventHeader.ProviderId, &FileIoGuid_I, sizeof(GUID)) == 0)
|
||||
{
|
||||
// FileIo
|
||||
|
||||
ET_ETW_FILE_EVENT fileEvent;
|
||||
|
||||
memset(&fileEvent, 0, sizeof(ET_ETW_FILE_EVENT));
|
||||
fileEvent.Type = -1;
|
||||
|
||||
switch (EventRecord->EventHeader.EventDescriptor.Opcode)
|
||||
{
|
||||
case 36: // FileRundown
|
||||
fileEvent.Type = EtEtwFileRundownType;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileEvent.Type != -1)
|
||||
{
|
||||
FileIo_Name *data = EventRecord->UserData;
|
||||
|
||||
fileEvent.FileObject = (PVOID)data->FileObject;
|
||||
PhInitializeStringRef(&fileEvent.FileName, data->FileName);
|
||||
|
||||
EtDiskProcessFileEvent(&fileEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS EtpRundownEtwMonitorThreadStart(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
EVENT_TRACE_LOGFILE logFile;
|
||||
TRACEHANDLE traceHandle;
|
||||
|
||||
memset(&logFile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
||||
logFile.LoggerName = EtpRundownLoggerName.Buffer;
|
||||
logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
|
||||
logFile.BufferCallback = EtpRundownEtwBufferCallback;
|
||||
logFile.EventRecordCallback = EtpRundownEtwEventCallback;
|
||||
logFile.Context = &traceHandle;
|
||||
|
||||
traceHandle = OpenTrace(&logFile);
|
||||
|
||||
if (traceHandle != INVALID_PROCESSTRACE_HANDLE)
|
||||
{
|
||||
ProcessTrace(&traceHandle, 1, NULL, NULL);
|
||||
|
||||
if (traceHandle != 0)
|
||||
CloseTrace(traceHandle);
|
||||
|
||||
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
||||
ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
|
||||
}
|
||||
|
||||
NtClose(EtpRundownEtwMonitorThreadHandle);
|
||||
EtpRundownEtwMonitorThreadHandle = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -3,45 +3,42 @@
|
||||
|
||||
#include <evntcons.h>
|
||||
|
||||
typedef ULONG wmi_uint32;
|
||||
typedef ULONG wmi_IPAddrV4;
|
||||
typedef IN6_ADDR wmi_IPAddrV6;
|
||||
typedef USHORT wmi_Port;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wmi_uint32 LowPart;
|
||||
wmi_uint32 HighPart;
|
||||
} wmi_uint64;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wmi_uint32 DiskNumber;
|
||||
wmi_uint32 IrpFlags;
|
||||
wmi_uint32 TransferSize;
|
||||
wmi_uint32 ResponseTime;
|
||||
wmi_uint64 ByteOffset;
|
||||
// Other members not included.
|
||||
ULONG DiskNumber;
|
||||
ULONG IrpFlags;
|
||||
ULONG TransferSize;
|
||||
ULONG ResponseTime;
|
||||
ULONG64 ByteOffset;
|
||||
ULONG_PTR FileObject;
|
||||
ULONG_PTR Irp;
|
||||
ULONG64 HighResResponseTime;
|
||||
} DiskIo_TypeGroup1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wmi_uint32 PID;
|
||||
wmi_uint32 size;
|
||||
wmi_IPAddrV4 daddr;
|
||||
wmi_IPAddrV4 saddr;
|
||||
wmi_Port dport;
|
||||
wmi_Port sport;
|
||||
ULONG_PTR FileObject;
|
||||
WCHAR FileName[1];
|
||||
} FileIo_Name;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG PID;
|
||||
ULONG size;
|
||||
ULONG daddr;
|
||||
ULONG saddr;
|
||||
USHORT dport;
|
||||
USHORT sport;
|
||||
} TcpIpOrUdpIp_IPV4_Header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wmi_uint32 PID;
|
||||
wmi_uint32 size;
|
||||
wmi_IPAddrV6 daddr;
|
||||
wmi_IPAddrV6 saddr;
|
||||
wmi_Port dport;
|
||||
wmi_Port sport;
|
||||
ULONG PID;
|
||||
ULONG size;
|
||||
IN6_ADDR daddr;
|
||||
IN6_ADDR saddr;
|
||||
USHORT dport;
|
||||
USHORT sport;
|
||||
} TcpIpOrUdpIp_IPV6_Header;
|
||||
|
||||
// etwmon
|
||||
@@ -56,12 +53,18 @@ VOID EtStopEtwSession();
|
||||
|
||||
VOID EtFlushEtwSession();
|
||||
|
||||
ULONG EtStartEtwRundown();
|
||||
|
||||
// etwstat
|
||||
|
||||
typedef enum _ET_ETW_EVENT_TYPE
|
||||
{
|
||||
EtEtwDiskReadType = 1,
|
||||
EtEtwDiskWriteType,
|
||||
EtEtwFileNameType,
|
||||
EtEtwFileCreateType,
|
||||
EtEtwFileDeleteType,
|
||||
EtEtwFileRundownType,
|
||||
EtEtwNetworkReceiveType,
|
||||
EtEtwNetworkSendType
|
||||
} ET_ETW_EVENT_TYPE;
|
||||
@@ -71,8 +74,17 @@ typedef struct _ET_ETW_DISK_EVENT
|
||||
ET_ETW_EVENT_TYPE Type;
|
||||
CLIENT_ID ClientId;
|
||||
ULONG TransferSize;
|
||||
PVOID FileObject;
|
||||
ULONG64 HighResResponseTime;
|
||||
} ET_ETW_DISK_EVENT, *PET_ETW_DISK_EVENT;
|
||||
|
||||
typedef struct _ET_ETW_FILE_EVENT
|
||||
{
|
||||
ET_ETW_EVENT_TYPE Type;
|
||||
PVOID FileObject;
|
||||
PH_STRINGREF FileName;
|
||||
} ET_ETW_FILE_EVENT, *PET_ETW_FILE_EVENT;
|
||||
|
||||
typedef struct _ET_ETW_NETWORK_EVENT
|
||||
{
|
||||
ET_ETW_EVENT_TYPE Type;
|
||||
@@ -83,6 +95,8 @@ typedef struct _ET_ETW_NETWORK_EVENT
|
||||
PH_IP_ENDPOINT RemoteEndpoint;
|
||||
} ET_ETW_NETWORK_EVENT, *PET_ETW_NETWORK_EVENT;
|
||||
|
||||
// etwstat
|
||||
|
||||
VOID EtProcessDiskEvent(
|
||||
__in PET_ETW_DISK_EVENT Event
|
||||
);
|
||||
@@ -91,4 +105,14 @@ VOID EtProcessNetworkEvent(
|
||||
__in PET_ETW_NETWORK_EVENT Event
|
||||
);
|
||||
|
||||
// etwdisk
|
||||
|
||||
VOID EtDiskProcessDiskEvent(
|
||||
__in PET_ETW_DISK_EVENT Event
|
||||
);
|
||||
|
||||
VOID EtDiskProcessFileEvent(
|
||||
__in PET_ETW_FILE_EVENT Event
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ INT_PTR CALLBACK EtpDiskNetworkPageDlgProc(
|
||||
__in LPARAM lParam
|
||||
);
|
||||
|
||||
VOID EtEtwProcessPropertiesInitializing(
|
||||
VOID EtProcessEtwPropertiesInitializing(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,8 @@ VOID NTAPI NetworkItemsUpdatedCallback(
|
||||
__in_opt PVOID Context
|
||||
);
|
||||
|
||||
VOID EtpUpdateDiskInformation();
|
||||
|
||||
static PH_CALLBACK_REGISTRATION EtpProcessesUpdatedCallbackRegistration;
|
||||
static PH_CALLBACK_REGISTRATION EtpNetworkItemsUpdatedCallbackRegistration;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static PH_GRAPH_STATE NetworkGraphState;
|
||||
static RECT EtpNormalGraphTextMargin = { 5, 5, 5, 5 };
|
||||
static RECT EtpNormalGraphTextPadding = { 3, 3, 3, 3 };
|
||||
|
||||
VOID EtEtwShowSystemDialog()
|
||||
VOID EtShowEtwSystemDialog()
|
||||
{
|
||||
if (!EtpEtwSysWindowHandle)
|
||||
{
|
||||
|
||||
@@ -11,22 +11,107 @@ extern HWND ProcessTreeNewHandle;
|
||||
extern HWND NetworkTreeNewHandle;
|
||||
|
||||
#define SETTING_PREFIX L"ProcessHacker.ExtendedTools."
|
||||
#define SETTING_NAME_DISK_TREE_LIST_COLUMNS (SETTING_PREFIX L"DiskTreeListColumns")
|
||||
#define SETTING_NAME_DISK_TREE_LIST_SORT (SETTING_PREFIX L"DiskTreeListSort")
|
||||
#define SETTING_NAME_ENABLE_ETW_MONITOR (SETTING_PREFIX L"EnableEtwMonitor")
|
||||
#define SETTING_NAME_ETWSYS_ALWAYS_ON_TOP (SETTING_PREFIX L"EtwSysAlwaysOnTop")
|
||||
#define SETTING_NAME_ETWSYS_WINDOW_POSITION (SETTING_PREFIX L"EtwSysWindowPosition")
|
||||
#define SETTING_NAME_ETWSYS_WINDOW_SIZE (SETTING_PREFIX L"EtwSysWindowSize")
|
||||
#define SETTING_NAME_MEMORY_LISTS_WINDOW_POSITION (SETTING_PREFIX L"MemoryListsWindowPosition")
|
||||
|
||||
#define HISTORY_SIZE 60
|
||||
|
||||
typedef struct _ET_DISK_ITEM
|
||||
{
|
||||
LIST_ENTRY AgeListEntry;
|
||||
ULONG AddTime;
|
||||
ULONG FreshTime;
|
||||
|
||||
HANDLE ProcessId;
|
||||
PPH_STRING FileName;
|
||||
PPH_STRING FileNameWin32;
|
||||
|
||||
PPH_STRING ProcessName;
|
||||
HICON ProcessIcon;
|
||||
BOOLEAN ProcessIconValid;
|
||||
|
||||
ULONG64 ReadTotal;
|
||||
ULONG64 WriteTotal;
|
||||
ULONG64 ReadDelta;
|
||||
ULONG64 WriteDelta;
|
||||
ULONG64 ReadAverage;
|
||||
ULONG64 WriteAverage;
|
||||
|
||||
ULONG64 ReadHistory[HISTORY_SIZE];
|
||||
ULONG64 WriteHistory[HISTORY_SIZE];
|
||||
ULONG HistoryCount;
|
||||
ULONG HistoryPosition;
|
||||
} ET_DISK_ITEM, *PET_DISK_ITEM;
|
||||
|
||||
// etwmon
|
||||
|
||||
extern BOOLEAN EtEtwEnabled;
|
||||
|
||||
// etwdisk
|
||||
|
||||
extern BOOLEAN EtDiskEnabled;
|
||||
|
||||
extern PPH_OBJECT_TYPE EtDiskItemType;
|
||||
extern PH_CALLBACK EtDiskItemAddedEvent;
|
||||
extern PH_CALLBACK EtDiskItemModifiedEvent;
|
||||
extern PH_CALLBACK EtDiskItemRemovedEvent;
|
||||
extern PH_CALLBACK EtDiskItemsUpdatedEvent;
|
||||
|
||||
VOID EtInitializeDiskInformation();
|
||||
|
||||
PET_DISK_ITEM EtCreateDiskItem();
|
||||
|
||||
PET_DISK_ITEM EtReferenceDiskItem(
|
||||
__in HANDLE ProcessId,
|
||||
__in PPH_STRING FileName
|
||||
);
|
||||
|
||||
PPH_STRING EtFileObjectToFileName(
|
||||
__in PVOID FileObject
|
||||
);
|
||||
|
||||
// etwprprp
|
||||
|
||||
VOID EtEtwProcessPropertiesInitializing(
|
||||
VOID EtProcessEtwPropertiesInitializing(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
// disktab
|
||||
|
||||
#define ETDSTNC_NAME 0
|
||||
#define ETDSTNC_FILE 1
|
||||
#define ETDSTNC_READRATEAVERAGE 2
|
||||
#define ETDSTNC_WRITERATEAVERAGE 3
|
||||
#define ETDSTNC_TOTALRATEAVERAGE 4
|
||||
#define ETDSTNC_MAXIMUM 5
|
||||
|
||||
typedef struct _ET_DISK_NODE
|
||||
{
|
||||
PH_TREENEW_NODE Node;
|
||||
|
||||
PET_DISK_ITEM DiskItem;
|
||||
|
||||
PH_STRINGREF TextCache[ETDSTNC_MAXIMUM];
|
||||
|
||||
PPH_STRING ProcessNameText;
|
||||
PPH_STRING ReadRateAverageText;
|
||||
PPH_STRING WriteRateAverageText;
|
||||
PPH_STRING TotalRateAverageText;
|
||||
|
||||
PPH_STRING TooltipText;
|
||||
} ET_DISK_NODE, *PET_DISK_NODE;
|
||||
|
||||
VOID EtInitializeDiskTab();
|
||||
|
||||
VOID EtLoadSettingsDiskTreeList();
|
||||
|
||||
VOID EtSaveSettingsDiskTreeList();
|
||||
|
||||
// treeext
|
||||
|
||||
#define ETPRTNC_DISKREADS 1
|
||||
@@ -54,11 +139,11 @@ VOID EtEtwProcessPropertiesInitializing(
|
||||
#define ETPRTNC_PEAKTHREADS 23
|
||||
#define ETPRTNC_MAXIMUM 23
|
||||
|
||||
VOID EtEtwProcessTreeNewInitializing(
|
||||
VOID EtProcessTreeNewInitializing(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
VOID EtEtwProcessTreeNewMessage(
|
||||
VOID EtProcessTreeNewMessage(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
@@ -75,11 +160,11 @@ VOID EtEtwProcessTreeNewMessage(
|
||||
#define ETNETNC_FIREWALLSTATUS 11
|
||||
#define ETNETNC_MAXIMUM 11
|
||||
|
||||
VOID EtEtwNetworkTreeNewInitializing(
|
||||
VOID EtNetworkTreeNewInitializing(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
VOID EtEtwNetworkTreeNewMessage(
|
||||
VOID EtNetworkTreeNewMessage(
|
||||
__in PVOID Parameter
|
||||
);
|
||||
|
||||
@@ -122,7 +207,7 @@ VOID EtEtwStatisticsUninitialization();
|
||||
|
||||
// etwsys
|
||||
|
||||
VOID EtEtwShowSystemDialog();
|
||||
VOID EtShowEtwSystemDialog();
|
||||
|
||||
// memlists
|
||||
|
||||
|
||||
@@ -281,6 +281,8 @@ LOGICAL DllMain(
|
||||
{
|
||||
static PH_SETTING_CREATE settings[] =
|
||||
{
|
||||
{ StringSettingType, SETTING_NAME_DISK_TREE_LIST_COLUMNS, L"" },
|
||||
{ IntegerPairSettingType, SETTING_NAME_DISK_TREE_LIST_SORT, L"4,2" }, // 4, DescendingSortOrder
|
||||
{ IntegerSettingType, SETTING_NAME_ENABLE_ETW_MONITOR, L"1" },
|
||||
{ IntegerSettingType, SETTING_NAME_ETWSYS_ALWAYS_ON_TOP, L"0" },
|
||||
{ IntegerPairSettingType, SETTING_NAME_ETWSYS_WINDOW_POSITION, L"400,400" },
|
||||
@@ -310,6 +312,7 @@ VOID NTAPI UnloadCallback(
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
EtSaveSettingsDiskTreeList();
|
||||
EtEtwStatisticsUninitialization();
|
||||
}
|
||||
|
||||
@@ -332,7 +335,7 @@ VOID NTAPI MenuItemCallback(
|
||||
{
|
||||
case ID_VIEW_DISKANDNETWORK:
|
||||
{
|
||||
EtEtwShowSystemDialog();
|
||||
EtShowEtwSystemDialog();
|
||||
}
|
||||
break;
|
||||
case ID_VIEW_MEMORYLISTS:
|
||||
@@ -375,9 +378,9 @@ VOID NTAPI TreeNewMessageCallback(
|
||||
PPH_PLUGIN_TREENEW_MESSAGE message = Parameter;
|
||||
|
||||
if (message->TreeNewHandle == ProcessTreeNewHandle)
|
||||
EtEtwProcessTreeNewMessage(Parameter);
|
||||
EtProcessTreeNewMessage(Parameter);
|
||||
else if (message->TreeNewHandle == NetworkTreeNewHandle)
|
||||
EtEtwNetworkTreeNewMessage(Parameter);
|
||||
EtNetworkTreeNewMessage(Parameter);
|
||||
}
|
||||
|
||||
VOID NTAPI MainWindowShowingCallback(
|
||||
@@ -391,6 +394,8 @@ VOID NTAPI MainWindowShowingCallback(
|
||||
{
|
||||
// This will get inserted before Memory Lists.
|
||||
PhPluginAddMenuItem(PluginInstance, PH_MENU_ITEM_LOCATION_VIEW, L"System Information", ID_VIEW_DISKANDNETWORK, L"Disk and Network", NULL);
|
||||
|
||||
EtInitializeDiskTab();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +404,7 @@ VOID NTAPI ProcessPropertiesInitializingCallback(
|
||||
__in_opt PVOID Context
|
||||
)
|
||||
{
|
||||
EtEtwProcessPropertiesInitializing(Parameter);
|
||||
EtProcessEtwPropertiesInitializing(Parameter);
|
||||
}
|
||||
|
||||
VOID NTAPI HandlePropertiesInitializingCallback(
|
||||
@@ -516,7 +521,7 @@ VOID NTAPI ProcessTreeNewInitializingCallback(
|
||||
PPH_PLUGIN_TREENEW_INFORMATION treeNewInfo = Parameter;
|
||||
|
||||
ProcessTreeNewHandle = treeNewInfo->TreeNewHandle;
|
||||
EtEtwProcessTreeNewInitializing(Parameter);
|
||||
EtProcessTreeNewInitializing(Parameter);
|
||||
}
|
||||
|
||||
VOID NTAPI NetworkTreeNewInitializingCallback(
|
||||
@@ -527,7 +532,7 @@ VOID NTAPI NetworkTreeNewInitializingCallback(
|
||||
PPH_PLUGIN_TREENEW_INFORMATION treeNewInfo = Parameter;
|
||||
|
||||
NetworkTreeNewHandle = treeNewInfo->TreeNewHandle;
|
||||
EtEtwNetworkTreeNewInitializing(Parameter);
|
||||
EtNetworkTreeNewInitializing(Parameter);
|
||||
}
|
||||
|
||||
static VOID NTAPI ProcessesUpdatedCallback(
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#define IDD_OPTIONS 109
|
||||
#define IDD_WSWATCH 110
|
||||
#define IDR_EMPTYMEMLISTS 111
|
||||
#define IDR_MENU1 112
|
||||
#define IDR_DISK 112
|
||||
#define IDC_LIST 1001
|
||||
#define IDC_REFRESH 1002
|
||||
#define IDC_SEQUENCENUMBER 1003
|
||||
@@ -78,13 +80,17 @@
|
||||
#define ID_EMPTY_EMPTYMODIFIEDPAGELIST 40002
|
||||
#define ID_EMPTY_EMPTYSTANDBYLIST 40003
|
||||
#define ID_EMPTY_EMPTYPRIORITY0STANDBYLIST 40004
|
||||
#define ID_DISK_GOTOPROCESS 40005
|
||||
#define ID_DISK_COPY 40006
|
||||
#define ID_DISK_PROPERTIES 40007
|
||||
#define ID_DISK_OPENFILELOCATION 40008
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 112
|
||||
#define _APS_NEXT_COMMAND_VALUE 40005
|
||||
#define _APS_NEXT_RESOURCE_VALUE 113
|
||||
#define _APS_NEXT_COMMAND_VALUE 40009
|
||||
#define _APS_NEXT_CONTROL_VALUE 1052
|
||||
#define _APS_NEXT_SYMED_VALUE 109
|
||||
#endif
|
||||
|
||||
@@ -82,7 +82,7 @@ VOID EtpAddTreeNewColumn(
|
||||
);
|
||||
}
|
||||
|
||||
VOID EtEtwProcessTreeNewInitializing(
|
||||
VOID EtProcessTreeNewInitializing(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ VOID EtEtwProcessTreeNewInitializing(
|
||||
}
|
||||
}
|
||||
|
||||
VOID EtEtwProcessTreeNewMessage(
|
||||
VOID EtProcessTreeNewMessage(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
@@ -350,7 +350,7 @@ LONG EtpProcessTreeNewSortFunction(
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID EtEtwNetworkTreeNewInitializing(
|
||||
VOID EtNetworkTreeNewInitializing(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
@@ -390,7 +390,7 @@ VOID EtpUpdateFirewallStatus(
|
||||
}
|
||||
}
|
||||
|
||||
VOID EtEtwNetworkTreeNewMessage(
|
||||
VOID EtNetworkTreeNewMessage(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user