From e3317f25c44f3e09e5934bc5faaae3bbbb64967d Mon Sep 17 00:00:00 2001 From: wj32 Date: Sat, 20 Aug 2011 06:51:52 +0000 Subject: [PATCH] * 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 --- 2.x/trunk/CHANGELOG.txt | 2 + 2.x/trunk/ProcessHacker/include/mainwndp.h | 2 +- 2.x/trunk/ProcessHacker/include/phapp.h | 12 + 2.x/trunk/ProcessHacker/include/uimodels.h | 1 + 2.x/trunk/ProcessHacker/mainwnd.c | 71 +- 2.x/trunk/ProcessHacker/sdk/phapppub.h | 41 + 2.x/trunk/ProcessHacker/thrdlist.c | 4 +- 2.x/trunk/phlib/include/cpysave.h | 1 + 2.x/trunk/phlib/include/emenu.h | 7 + 2.x/trunk/plugins-extra/AvgCpuPlugin/main.c | 10 +- 2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt | 1 + .../plugins/ExtendedTools/ExtendedTools.rc | 12 + .../ExtendedTools/ExtendedTools.vcxproj | 7 + .../ExtendedTools.vcxproj.filters | 9 + 2.x/trunk/plugins/ExtendedTools/disktab.c | 858 ++++++++++++++++++ 2.x/trunk/plugins/ExtendedTools/disktabp.h | 126 +++ 2.x/trunk/plugins/ExtendedTools/etwdisk.c | 545 +++++++++++ 2.x/trunk/plugins/ExtendedTools/etwmon.c | 237 ++++- 2.x/trunk/plugins/ExtendedTools/etwmon.h | 82 +- 2.x/trunk/plugins/ExtendedTools/etwprprp.c | 2 +- 2.x/trunk/plugins/ExtendedTools/etwstat.c | 2 + 2.x/trunk/plugins/ExtendedTools/etwsys.c | 2 +- 2.x/trunk/plugins/ExtendedTools/exttools.h | 97 +- 2.x/trunk/plugins/ExtendedTools/main.c | 17 +- 2.x/trunk/plugins/ExtendedTools/resource.h | 10 +- 2.x/trunk/plugins/ExtendedTools/treeext.c | 8 +- 26 files changed, 2066 insertions(+), 100 deletions(-) create mode 100644 2.x/trunk/plugins/ExtendedTools/disktab.c create mode 100644 2.x/trunk/plugins/ExtendedTools/disktabp.h create mode 100644 2.x/trunk/plugins/ExtendedTools/etwdisk.c diff --git a/2.x/trunk/CHANGELOG.txt b/2.x/trunk/CHANGELOG.txt index 5c288a185..dd2f9367b 100644 --- a/2.x/trunk/CHANGELOG.txt +++ b/2.x/trunk/CHANGELOG.txt @@ -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: diff --git a/2.x/trunk/ProcessHacker/include/mainwndp.h b/2.x/trunk/ProcessHacker/include/mainwndp.h index 2f717bc01..438a4f2a1 100644 --- a/2.x/trunk/ProcessHacker/include/mainwndp.h +++ b/2.x/trunk/ProcessHacker/include/mainwndp.h @@ -233,7 +233,7 @@ VOID PhMwpNotifyTabControl( ); VOID PhMwpSelectionChangedTabControl( - VOID + __in ULONG OldIndex ); PPH_ADDITIONAL_TAB_PAGE PhMwpAddTabPage( diff --git a/2.x/trunk/ProcessHacker/include/phapp.h b/2.x/trunk/ProcessHacker/include/phapp.h index 47fe94b17..8a542d40c 100644 --- a/2.x/trunk/ProcessHacker/include/phapp.h +++ b/2.x/trunk/ProcessHacker/include/phapp.h @@ -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 diff --git a/2.x/trunk/ProcessHacker/include/uimodels.h b/2.x/trunk/ProcessHacker/include/uimodels.h index eeffde39e..837365be9 100644 --- a/2.x/trunk/ProcessHacker/include/uimodels.h +++ b/2.x/trunk/ProcessHacker/include/uimodels.h @@ -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; diff --git a/2.x/trunk/ProcessHacker/mainwnd.c b/2.x/trunk/ProcessHacker/mainwnd.c index 7b8180d95..8952ead00 100644 --- a/2.x/trunk/ProcessHacker/mainwnd.c +++ b/2.x/trunk/ProcessHacker/mainwnd.c @@ -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( diff --git a/2.x/trunk/ProcessHacker/sdk/phapppub.h b/2.x/trunk/ProcessHacker/sdk/phapppub.h index d603761a7..47bb4f6c1 100644 --- a/2.x/trunk/ProcessHacker/sdk/phapppub.h +++ b/2.x/trunk/ProcessHacker/sdk/phapppub.h @@ -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 diff --git a/2.x/trunk/ProcessHacker/thrdlist.c b/2.x/trunk/ProcessHacker/thrdlist.c index f90b65165..48b21d76b 100644 --- a/2.x/trunk/ProcessHacker/thrdlist.c +++ b/2.x/trunk/ProcessHacker/thrdlist.c @@ -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)); diff --git a/2.x/trunk/phlib/include/cpysave.h b/2.x/trunk/phlib/include/cpysave.h index e3482dcf3..12faa3b83 100644 --- a/2.x/trunk/phlib/include/cpysave.h +++ b/2.x/trunk/phlib/include/cpysave.h @@ -32,6 +32,7 @@ PPH_FULL_STRING PhGetTreeNewText( __in ULONG MaximumNumberOfColumns ); +PHLIBAPI PPH_LIST PhGetGenericTreeNewLines( __in HWND TreeNewHandle, __in ULONG Mode diff --git a/2.x/trunk/phlib/include/emenu.h b/2.x/trunk/phlib/include/emenu.h index 6f3fc9534..1f4a0d0ff 100644 --- a/2.x/trunk/phlib/include/emenu.h +++ b/2.x/trunk/phlib/include/emenu.h @@ -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, diff --git a/2.x/trunk/plugins-extra/AvgCpuPlugin/main.c b/2.x/trunk/plugins-extra/AvgCpuPlugin/main.c index 2a411af2d..abbe729ad 100644 --- a/2.x/trunk/plugins-extra/AvgCpuPlugin/main.c +++ b/2.x/trunk/plugins-extra/AvgCpuPlugin/main.c @@ -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); diff --git a/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt b/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt index 9522d87e0..d0eb84101 100644 --- a/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt +++ b/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt @@ -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 diff --git a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.rc b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.rc index 28fed0802..0e9cf1bf5 100644 --- a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.rc +++ b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.rc @@ -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 ///////////////////////////////////////////////////////////////////////////// diff --git a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj index bdcbe1eb9..d01b30555 100644 --- a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj +++ b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj @@ -84,6 +84,7 @@ EditAndContinue StdCall true + true ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies) @@ -107,6 +108,7 @@ ProgramDatabase StdCall true + true ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies) @@ -128,6 +130,7 @@ ProgramDatabase StdCall true + true ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies) @@ -155,6 +158,7 @@ ProgramDatabase StdCall true + true ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies) @@ -168,6 +172,8 @@ + + @@ -183,6 +189,7 @@ + diff --git a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj.filters b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj.filters index 3de8851c4..9fd7af168 100644 --- a/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj.filters +++ b/2.x/trunk/plugins/ExtendedTools/ExtendedTools.vcxproj.filters @@ -54,6 +54,12 @@ Source Files + + Source Files + + + Source Files + @@ -65,6 +71,9 @@ Header Files + + Header Files + diff --git a/2.x/trunk/plugins/ExtendedTools/disktab.c b/2.x/trunk/plugins/ExtendedTools/disktab.c new file mode 100644 index 000000000..9913124d2 --- /dev/null +++ b/2.x/trunk/plugins/ExtendedTools/disktab.c @@ -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 . + */ + +#include "exttools.h" +#include "etwmon.h" +#include "resource.h" +#include +#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); +} diff --git a/2.x/trunk/plugins/ExtendedTools/disktabp.h b/2.x/trunk/plugins/ExtendedTools/disktabp.h new file mode 100644 index 000000000..c905d4e1b --- /dev/null +++ b/2.x/trunk/plugins/ExtendedTools/disktabp.h @@ -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 diff --git a/2.x/trunk/plugins/ExtendedTools/etwdisk.c b/2.x/trunk/plugins/ExtendedTools/etwdisk.c new file mode 100644 index 000000000..f39537012 --- /dev/null +++ b/2.x/trunk/plugins/ExtendedTools/etwdisk.c @@ -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 . + */ + +#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++; +} diff --git a/2.x/trunk/plugins/ExtendedTools/etwmon.c b/2.x/trunk/plugins/ExtendedTools/etwmon.c index 4f2b5e3cf..83faa615b 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwmon.c +++ b/2.x/trunk/plugins/ExtendedTools/etwmon.c @@ -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; +} diff --git a/2.x/trunk/plugins/ExtendedTools/etwmon.h b/2.x/trunk/plugins/ExtendedTools/etwmon.h index 8e75fcb16..935f85789 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwmon.h +++ b/2.x/trunk/plugins/ExtendedTools/etwmon.h @@ -3,45 +3,42 @@ #include -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 diff --git a/2.x/trunk/plugins/ExtendedTools/etwprprp.c b/2.x/trunk/plugins/ExtendedTools/etwprprp.c index 17b6ac797..06350f117 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwprprp.c +++ b/2.x/trunk/plugins/ExtendedTools/etwprprp.c @@ -45,7 +45,7 @@ INT_PTR CALLBACK EtpDiskNetworkPageDlgProc( __in LPARAM lParam ); -VOID EtEtwProcessPropertiesInitializing( +VOID EtProcessEtwPropertiesInitializing( __in PVOID Parameter ) { diff --git a/2.x/trunk/plugins/ExtendedTools/etwstat.c b/2.x/trunk/plugins/ExtendedTools/etwstat.c index 83cef31b3..39e316c56 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwstat.c +++ b/2.x/trunk/plugins/ExtendedTools/etwstat.c @@ -33,6 +33,8 @@ VOID NTAPI NetworkItemsUpdatedCallback( __in_opt PVOID Context ); +VOID EtpUpdateDiskInformation(); + static PH_CALLBACK_REGISTRATION EtpProcessesUpdatedCallbackRegistration; static PH_CALLBACK_REGISTRATION EtpNetworkItemsUpdatedCallbackRegistration; diff --git a/2.x/trunk/plugins/ExtendedTools/etwsys.c b/2.x/trunk/plugins/ExtendedTools/etwsys.c index 8bd88bce2..79560e04b 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwsys.c +++ b/2.x/trunk/plugins/ExtendedTools/etwsys.c @@ -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) { diff --git a/2.x/trunk/plugins/ExtendedTools/exttools.h b/2.x/trunk/plugins/ExtendedTools/exttools.h index b7510a3e2..7b2cc1068 100644 --- a/2.x/trunk/plugins/ExtendedTools/exttools.h +++ b/2.x/trunk/plugins/ExtendedTools/exttools.h @@ -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 diff --git a/2.x/trunk/plugins/ExtendedTools/main.c b/2.x/trunk/plugins/ExtendedTools/main.c index 26e55b5a7..64ce96560 100644 --- a/2.x/trunk/plugins/ExtendedTools/main.c +++ b/2.x/trunk/plugins/ExtendedTools/main.c @@ -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( diff --git a/2.x/trunk/plugins/ExtendedTools/resource.h b/2.x/trunk/plugins/ExtendedTools/resource.h index d792a87ea..c0fb9ef87 100644 --- a/2.x/trunk/plugins/ExtendedTools/resource.h +++ b/2.x/trunk/plugins/ExtendedTools/resource.h @@ -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 diff --git a/2.x/trunk/plugins/ExtendedTools/treeext.c b/2.x/trunk/plugins/ExtendedTools/treeext.c index 842b7ad4d..d80f694e0 100644 --- a/2.x/trunk/plugins/ExtendedTools/treeext.c +++ b/2.x/trunk/plugins/ExtendedTools/treeext.c @@ -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 ) {