mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
added handle statistics window
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3464 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -6,6 +6,7 @@ Process Hacker
|
||||
* Can now unload 32-bit modules on 64-bit systems
|
||||
* Tasks are shown in tooltips for taskeng.exe/taskhost.exe processes
|
||||
* Run As can now start processes elevated
|
||||
* Handle count by type
|
||||
* CSV export
|
||||
* Relative start times
|
||||
* FIXED:
|
||||
|
||||
@@ -1219,13 +1219,14 @@ BEGIN
|
||||
RTEXT "Static",IDC_ZIOOTHER_V,184,57,63,8,SS_ENDELLIPSIS
|
||||
RTEXT "Static",IDC_ZIOOTHERBYTES_V,184,67,63,8,SS_ENDELLIPSIS
|
||||
RTEXT "Static",IDC_ZIOPRIORITY_V,184,77,63,8,SS_ENDELLIPSIS
|
||||
GROUPBOX "Other",IDC_STATIC,131,92,122,43
|
||||
GROUPBOX "Other",IDC_STATIC,131,92,122,60
|
||||
LTEXT "Handles",IDC_STATIC,138,102,26,8
|
||||
LTEXT "GDI Handles",IDC_STATIC,138,112,40,8
|
||||
LTEXT "USER Handles",IDC_STATIC,138,122,46,8
|
||||
RTEXT "Static",IDC_ZHANDLES_V,193,102,54,8,SS_ENDELLIPSIS
|
||||
RTEXT "Static",IDC_ZGDIHANDLES_V,193,112,54,8,SS_ENDELLIPSIS
|
||||
RTEXT "Static",IDC_ZUSERHANDLES_V,193,122,54,8,SS_ENDELLIPSIS
|
||||
PUSHBUTTON "Details",IDC_DETAILS,137,133,50,14
|
||||
END
|
||||
|
||||
IDD_OPTADVANCED DIALOGEX 0, 0, 250, 85
|
||||
@@ -1457,6 +1458,15 @@ BEGIN
|
||||
PUSHBUTTON "Cleanup",IDC_CLEANUP,7,239,50,14
|
||||
END
|
||||
|
||||
IDD_HANDLESTATS DIALOGEX 0, 0, 219, 175
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Handle Statistics"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Close",IDOK,162,154,50,14
|
||||
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,205,143
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -1881,6 +1891,14 @@ BEGIN
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 253
|
||||
END
|
||||
|
||||
IDD_HANDLESTATS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 212
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 168
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
@@ -720,6 +720,10 @@
|
||||
RelativePath=".\hndlprv.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\hndlstat.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\infodlg.c"
|
||||
>
|
||||
|
||||
@@ -257,7 +257,7 @@ __assumeLocked VOID PhpRemoveHandleItem(
|
||||
PhDereferenceObject(HandleItem);
|
||||
}
|
||||
|
||||
NTSTATUS PhpEnumHandlesGeneric(
|
||||
NTSTATUS PhEnumHandlesGeneric(
|
||||
__in HANDLE ProcessId,
|
||||
__in HANDLE ProcessHandle,
|
||||
__out PSYSTEM_HANDLE_INFORMATION_EX *Handles,
|
||||
@@ -399,7 +399,7 @@ VOID PhHandleProviderUpdate(
|
||||
if (!handleProvider->ProcessHandle)
|
||||
return;
|
||||
|
||||
if (!NT_SUCCESS(PhpEnumHandlesGeneric(
|
||||
if (!NT_SUCCESS(PhEnumHandlesGeneric(
|
||||
handleProvider->ProcessId,
|
||||
handleProvider->ProcessHandle,
|
||||
&handleInfo,
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* handle statistics window
|
||||
*
|
||||
* Copyright (C) 2010 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 <phapp.h>
|
||||
|
||||
typedef struct _HANDLE_STATISTICS_ENTRY
|
||||
{
|
||||
PPH_STRING Name;
|
||||
ULONG Count;
|
||||
} HANDLE_STATISTICS_ENTRY, *PHANDLE_STATISTICS_ENTRY;
|
||||
|
||||
typedef struct _HANDLE_STATISTICS_CONTEXT
|
||||
{
|
||||
HANDLE ProcessId;
|
||||
HANDLE ProcessHandle;
|
||||
|
||||
PSYSTEM_HANDLE_INFORMATION_EX Handles;
|
||||
HANDLE_STATISTICS_ENTRY Entries[MAX_OBJECT_TYPE_NUMBER];
|
||||
} HANDLE_STATISTICS_CONTEXT, *PHANDLE_STATISTICS_CONTEXT;
|
||||
|
||||
INT_PTR CALLBACK PhpHandleStatisticsDlgProc(
|
||||
__in HWND hwndDlg,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
);
|
||||
|
||||
VOID PhShowHandleStatisticsDialog(
|
||||
__in HWND ParentWindowHandle,
|
||||
__in HANDLE ProcessId
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE_STATISTICS_CONTEXT context;
|
||||
BOOLEAN filterNeeded;
|
||||
ULONG i;
|
||||
|
||||
context.ProcessId = ProcessId;
|
||||
|
||||
if (!NT_SUCCESS(status = PhOpenProcess(
|
||||
&context.ProcessHandle,
|
||||
PROCESS_DUP_HANDLE,
|
||||
ProcessId
|
||||
)))
|
||||
{
|
||||
PhShowStatus(ParentWindowHandle, L"Unable to open the process", status, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
status = PhEnumHandlesGeneric(
|
||||
context.ProcessId,
|
||||
context.ProcessHandle,
|
||||
&context.Handles,
|
||||
&filterNeeded
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
NtClose(context.ProcessHandle);
|
||||
PhShowStatus(ParentWindowHandle, L"Unable to enumerate process handles", status, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&context.Entries, 0, sizeof(context.Entries));
|
||||
|
||||
DialogBoxParam(
|
||||
PhInstanceHandle,
|
||||
MAKEINTRESOURCE(IDD_HANDLESTATS),
|
||||
ParentWindowHandle,
|
||||
PhpHandleStatisticsDlgProc,
|
||||
(LPARAM)&context
|
||||
);
|
||||
|
||||
for (i = 0; i < MAX_OBJECT_TYPE_NUMBER; i++)
|
||||
{
|
||||
if (context.Entries[i].Name)
|
||||
PhDereferenceObject(context.Entries[i].Name);
|
||||
}
|
||||
|
||||
PhFree(context.Handles);
|
||||
NtClose(context.ProcessHandle);
|
||||
}
|
||||
|
||||
static INT NTAPI PhpTypeCountCompareFunction(
|
||||
__in PVOID Item1,
|
||||
__in PVOID Item2,
|
||||
__in PVOID Context
|
||||
)
|
||||
{
|
||||
PHANDLE_STATISTICS_ENTRY entry1 = Item1;
|
||||
PHANDLE_STATISTICS_ENTRY entry2 = Item2;
|
||||
|
||||
return uintcmp(entry1->Count, entry2->Count);
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK PhpHandleStatisticsDlgProc(
|
||||
__in HWND hwndDlg,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
PHANDLE_STATISTICS_CONTEXT context = (PHANDLE_STATISTICS_CONTEXT)lParam;
|
||||
HANDLE processId;
|
||||
ULONG_PTR i;
|
||||
HWND lvHandle;
|
||||
|
||||
processId = context->ProcessId;
|
||||
|
||||
for (i = 0; i < context->Handles->NumberOfHandles; i++)
|
||||
{
|
||||
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo;
|
||||
PHANDLE_STATISTICS_ENTRY entry;
|
||||
PPH_STRING typeName;
|
||||
|
||||
handleInfo = &context->Handles->Handles[i];
|
||||
|
||||
if (handleInfo->UniqueProcessId != (ULONG_PTR)processId)
|
||||
continue;
|
||||
if (handleInfo->ObjectTypeIndex >= MAX_OBJECT_TYPE_NUMBER)
|
||||
continue;
|
||||
|
||||
entry = &context->Entries[handleInfo->ObjectTypeIndex];
|
||||
|
||||
if (!entry->Name)
|
||||
{
|
||||
typeName = NULL;
|
||||
PhGetHandleInformation(
|
||||
context->ProcessHandle,
|
||||
(HANDLE)handleInfo->HandleValue,
|
||||
handleInfo->ObjectTypeIndex,
|
||||
NULL,
|
||||
&typeName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
entry->Name = typeName;
|
||||
}
|
||||
|
||||
entry->Count++;
|
||||
}
|
||||
|
||||
lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
|
||||
PhSetListViewStyle(lvHandle, FALSE, TRUE);
|
||||
PhSetControlTheme(lvHandle, L"explorer");
|
||||
PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 140, L"Type");
|
||||
PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Count");
|
||||
|
||||
PhSetExtendedListView(lvHandle);
|
||||
ExtendedListView_SetCompareFunction(lvHandle, 1, PhpTypeCountCompareFunction);
|
||||
|
||||
for (i = 0; i < MAX_OBJECT_TYPE_NUMBER; i++)
|
||||
{
|
||||
PHANDLE_STATISTICS_ENTRY entry;
|
||||
PPH_STRING unknownType;
|
||||
PPH_STRING countString;
|
||||
INT lvItemIndex;
|
||||
|
||||
entry = &context->Entries[i];
|
||||
|
||||
if (entry->Count == 0)
|
||||
continue;
|
||||
|
||||
unknownType = NULL;
|
||||
|
||||
if (!entry->Name)
|
||||
unknownType = PhFormatString(L"(unknown: %u)", i);
|
||||
|
||||
countString = PhFormatUInt64(entry->Count, TRUE);
|
||||
|
||||
lvItemIndex = PhAddListViewItem(
|
||||
lvHandle,
|
||||
MAXINT,
|
||||
entry->Name ? entry->Name->Buffer : unknownType->Buffer,
|
||||
entry
|
||||
);
|
||||
PhSetListViewSubItem(lvHandle, lvItemIndex, 1, countString->Buffer);
|
||||
|
||||
PhDereferenceObject(countString);
|
||||
|
||||
if (unknownType)
|
||||
PhDereferenceObject(unknownType);
|
||||
}
|
||||
|
||||
ExtendedListView_SortItems(lvHandle);
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
case IDOK:
|
||||
EndDialog(hwndDlg, IDOK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
PhHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1210,6 +1210,13 @@ VOID PhShowHandleProperties(
|
||||
__in PPH_HANDLE_ITEM HandleItem
|
||||
);
|
||||
|
||||
// hndlstat
|
||||
|
||||
VOID PhShowHandleStatisticsDialog(
|
||||
__in HWND ParentWindowHandle,
|
||||
__in HANDLE ProcessId
|
||||
);
|
||||
|
||||
// infodlg
|
||||
|
||||
VOID PhShowInformationDialog(
|
||||
|
||||
@@ -629,6 +629,13 @@ VOID PhDereferenceAllHandleItems(
|
||||
__in PPH_HANDLE_PROVIDER HandleProvider
|
||||
);
|
||||
|
||||
NTSTATUS PhEnumHandlesGeneric(
|
||||
__in HANDLE ProcessId,
|
||||
__in HANDLE ProcessHandle,
|
||||
__out PSYSTEM_HANDLE_INFORMATION_EX *Handles,
|
||||
__out PBOOLEAN FilterNeeded
|
||||
);
|
||||
|
||||
VOID PhHandleProviderUpdate(
|
||||
__in PVOID Object
|
||||
);
|
||||
|
||||
@@ -1195,6 +1195,18 @@ INT_PTR CALLBACK PhpProcessStatisticsDlgProc(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_DETAILS:
|
||||
{
|
||||
PhShowHandleStatisticsDialog(hwndDlg, processItem->ProcessId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR header = (LPNMHDR)lParam;
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
#define IDD_MEMSTRING 185
|
||||
#define IDD_OPTGRAPHS 186
|
||||
#define IDD_PLUGINS 187
|
||||
#define IDD_HANDLESTATS 188
|
||||
#define IDC_TERMINATE 1003
|
||||
#define IDC_FILEICON 1005
|
||||
#define IDC_FILE 1006
|
||||
@@ -192,6 +193,7 @@
|
||||
#define IDC_CLEAR 1079
|
||||
#define IDC_GOTO 1079
|
||||
#define IDC_OPTIONS 1079
|
||||
#define IDC_DETAILS 1079
|
||||
#define IDC_EDITDEP 1080
|
||||
#define IDC_VIEWPARENTPROCESS 1081
|
||||
#define IDC_OPENFILENAME 1082
|
||||
@@ -610,9 +612,9 @@
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 188
|
||||
#define _APS_NEXT_RESOURCE_VALUE 189
|
||||
#define _APS_NEXT_COMMAND_VALUE 40232
|
||||
#define _APS_NEXT_CONTROL_VALUE 1260
|
||||
#define _APS_NEXT_CONTROL_VALUE 1261
|
||||
#define _APS_NEXT_SYMED_VALUE 131
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -55,8 +55,7 @@ HANDLE PhQueryObjectStartEvent = NULL;
|
||||
HANDLE PhQueryObjectCompletedEvent = NULL;
|
||||
PH_QUERY_OBJECT_CONTEXT PhQueryObjectContext;
|
||||
|
||||
#define MAX_OBJECT_TYPE_NUMBER 256
|
||||
PPH_STRING PhObjectTypeNames[MAX_OBJECT_TYPE_NUMBER + 1];
|
||||
PPH_STRING PhObjectTypeNames[MAX_OBJECT_TYPE_NUMBER];
|
||||
PPH_GET_CLIENT_ID_NAME PhHandleGetClientIdName = PhStdGetClientIdName;
|
||||
|
||||
static PPH_STRING HkcuPrefix;
|
||||
@@ -171,7 +170,7 @@ NTSTATUS PhpGetObjectTypeName(
|
||||
// If the cache contains the object type name, use it. Otherwise,
|
||||
// query the type name.
|
||||
|
||||
if (ObjectTypeNumber != -1 && ObjectTypeNumber <= MAX_OBJECT_TYPE_NUMBER)
|
||||
if (ObjectTypeNumber != -1 && ObjectTypeNumber < MAX_OBJECT_TYPE_NUMBER)
|
||||
typeName = PhObjectTypeNames[ObjectTypeNumber];
|
||||
|
||||
if (typeName)
|
||||
@@ -928,7 +927,7 @@ NTSTATUS PhGetHandleInformation(
|
||||
|
||||
if (Handle == NULL || Handle == NtCurrentProcess() || Handle == NtCurrentThread())
|
||||
return STATUS_INVALID_HANDLE;
|
||||
if (ObjectTypeNumber != -1 && ObjectTypeNumber > MAX_OBJECT_TYPE_NUMBER)
|
||||
if (ObjectTypeNumber != -1 && ObjectTypeNumber >= MAX_OBJECT_TYPE_NUMBER)
|
||||
return STATUS_INVALID_PARAMETER_3;
|
||||
|
||||
// Duplicate the handle if we're not using KPH.
|
||||
|
||||
@@ -1074,6 +1074,8 @@ NTSTATUS PhEnumAccounts(
|
||||
|
||||
// hndlinfo
|
||||
|
||||
#define MAX_OBJECT_TYPE_NUMBER 257
|
||||
|
||||
VOID PhHandleInfoInitialization();
|
||||
|
||||
typedef PPH_STRING (NTAPI *PPH_GET_CLIENT_ID_NAME)(
|
||||
|
||||
Reference in New Issue
Block a user