From 9fa8c8128797106d66cf7ae1595a71d597d33818 Mon Sep 17 00:00:00 2001 From: Dart Vanya Date: Wed, 20 Nov 2024 07:28:05 +0300 Subject: [PATCH] objmgr cleanup and improvements - Handles tab Refresh (F5) button added. - EtTreeViewFindItem add reverse scan for more reliable result. - [Resolver] Extract Section information for more kernel objects using driver. --- SystemInformer/main.c | 4 - phlib/delayhook.c | 10 + phlib/include/guisup.h | 3 +- phlib/theme.c | 15 - plugins/ExtendedTools/ExtendedTools.rc | 9 +- plugins/ExtendedTools/exttools.h | 3 +- plugins/ExtendedTools/objmgr.c | 444 +++++++++++++------------ plugins/ExtendedTools/objprp.c | 299 ++++++++++++----- 8 files changed, 456 insertions(+), 331 deletions(-) diff --git a/SystemInformer/main.c b/SystemInformer/main.c index c06e70f37a8c..9383b853bc97 100644 --- a/SystemInformer/main.c +++ b/SystemInformer/main.c @@ -40,10 +40,6 @@ VOID PhInitializeCommonControls( VOID ); -VOID PhInitializeSuperclassControls( // delayhook.c - VOID - ); - BOOLEAN PhInitializeAppSystem( VOID ); diff --git a/phlib/delayhook.c b/phlib/delayhook.c index b2317a296eea..d1dfa0828b0f 100644 --- a/phlib/delayhook.c +++ b/phlib/delayhook.c @@ -2158,6 +2158,16 @@ VOID PhInitializeSuperclassControls( if (PhEnableThemeAcrylicSupport) PhEnableThemeAcrylicSupport = PhIsThemeTransparencyEnabled(); + // If PreferredAppMode is not set, PhShouldAppsUseDarkMode returns current Windows app color mode. + // When app mode set to always dark/light all subsequent calls to PhShouldAppsUseDarkMode always ignore + // the current Windows app color mode and return: + // AppMode = PreferredAppModeDarkAlways always return TRUE + // AppMode = PreferredAppModeLightAlways always return FALSE + // + // It's very convenient because all new opened windows (especially plugin windows) will always have same theme + // even if the system theme was changed while SI is running. To update theme in this case SI restart is required. + PhSetPreferredAppMode(PhEnableThemeSupport ? PreferredAppModeDarkAlways : PreferredAppModeLightAlways); + if (PhEnableThemeSupport || PhEnableStreamerMode) { if (WindowsVersion >= WINDOWS_11) diff --git a/phlib/include/guisup.h b/phlib/include/guisup.h index cd0d7099180b..d2502e3e2341 100644 --- a/phlib/include/guisup.h +++ b/phlib/include/guisup.h @@ -241,7 +241,8 @@ typedef enum _PreferredAppMode { PreferredAppModeDisabled, PreferredAppModeDarkOnDark, - PreferredAppModeDarkAlways + PreferredAppModeDarkAlways, + PreferredAppModeLightAlways } PreferredAppMode; PHLIBAPI diff --git a/phlib/theme.c b/phlib/theme.c index 4305c67442ea..b5ba46b42d7f 100644 --- a/phlib/theme.c +++ b/phlib/theme.c @@ -160,21 +160,6 @@ VOID PhInitializeWindowTheme( _In_ BOOLEAN EnableThemeSupport ) { - if (EnableThemeSupport && WindowsVersion >= WINDOWS_10_RS5) - { - static PH_INITONCE initOnce = PH_INITONCE_INIT; - - if (PhBeginInitOnce(&initOnce)) - { - PhSetPreferredAppMode(PreferredAppModeDarkAlways); - - //if (FlushMenuThemes_I) - // FlushMenuThemes_I(); - - PhEndInitOnce(&initOnce); - } - } - PhInitializeThemeWindowFrame(WindowHandle); if (!PhThemeWindowBackgroundBrush) diff --git a/plugins/ExtendedTools/ExtendedTools.rc b/plugins/ExtendedTools/ExtendedTools.rc index e192b80f5a8d..699aed8ad408 100644 --- a/plugins/ExtendedTools/ExtendedTools.rc +++ b/plugins/ExtendedTools/ExtendedTools.rc @@ -485,10 +485,11 @@ BEGIN CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,286,262 LTEXT "Total handles found:",IDC_STATIC,10,273,67,8 LTEXT "100000",IDC_OBJ_HANDLESTOTAL,78,273,32,8 - LTEXT "By address:",IDC_STATIC,137,273,39,8 - LTEXT "100000",IDC_OBJ_HANDLESBYOBJECT,177,273,27,8 - LTEXT "By name:", IDC_OBJ_HANDLESBYNAME_L,235,273,31,8 - LTEXT "100000",IDC_OBJ_HANDLESBYNAME,267,273,27,8 + LTEXT "By address:",IDC_STATIC,110,273,39,8 + LTEXT "100000",IDC_OBJ_HANDLESBYOBJECT,150,273,27,8 + LTEXT "By name:", IDC_OBJ_HANDLESBYNAME_L,182,273,31,8 + LTEXT "100000",IDC_OBJ_HANDLESBYNAME,214,273,27,8 + PUSHBUTTON "Refresh (F5)",IDC_REFRESH,245,271,48,13 END IDD_OBJWINSTA DIALOGEX 0, 0, 260, 200 diff --git a/plugins/ExtendedTools/exttools.h b/plugins/ExtendedTools/exttools.h index a068c18203bb..a166f1722f14 100644 --- a/plugins/ExtendedTools/exttools.h +++ b/plugins/ExtendedTools/exttools.h @@ -1662,7 +1662,8 @@ VOID EtShowObjectManagerDialog( NTSTATUS EtDuplicateHandleFromProcessEx( _Out_ PHANDLE Handle, _In_ ACCESS_MASK DesiredAccess, - _In_ HANDLE ProcessId, + _In_opt_ HANDLE ProcessId, + _In_opt_ HANDLE ProcessHandle, _In_ HANDLE SourceHandle ); diff --git a/plugins/ExtendedTools/objmgr.c b/plugins/ExtendedTools/objmgr.c index aca2d3e671f7..66ff6d822c23 100644 --- a/plugins/ExtendedTools/objmgr.c +++ b/plugins/ExtendedTools/objmgr.c @@ -31,13 +31,13 @@ PPH_HASHTABLE EtObjectManagerPropWindows = NULL; HICON EtObjectManagerPropIcon = NULL; // Cached type indexes -ULONG EtAlpcPortTypeIndex; -ULONG EtDeviceTypeIndex; -ULONG EtFilterPortTypeIndex; -ULONG EtFileTypeIndex; -ULONG EtKeyTypeIndex; -ULONG EtSectionTypeIndex; -ULONG EtWinStaTypeIndex; +ULONG EtAlpcPortTypeIndex = ULONG_MAX; +ULONG EtDeviceTypeIndex = ULONG_MAX; +ULONG EtFilterPortTypeIndex = ULONG_MAX; +ULONG EtFileTypeIndex = ULONG_MAX; +ULONG EtKeyTypeIndex = ULONG_MAX; +ULONG EtSectionTypeIndex = ULONG_MAX; +ULONG EtWinStaTypeIndex = ULONG_MAX; // Columns @@ -74,15 +74,15 @@ typedef enum _ET_OBJECT_TYPE typedef struct _ET_OBJECT_ENTRY { + ET_OBJECT_TYPE EtObjectType; PPH_STRING Name; PPH_STRING TypeName; PPH_STRING Target; + BOOLEAN TargetIsResolving; + BOOLEAN TargetIsInfoOnly; PPH_STRING TargetDrvLow; PPH_STRING TargetDrvUp; - ET_OBJECT_TYPE EtObjectType; - BOOL TargetIsResolving; CLIENT_ID TargetClientId; - BOOLEAN TargetIsInfoOnly; } ET_OBJECT_ENTRY, *POBJECT_ENTRY; typedef struct _ET_OBJECT_CONTEXT @@ -92,6 +92,7 @@ typedef struct _ET_OBJECT_CONTEXT HWND ListViewHandle; HWND TreeViewHandle; HWND SearchBoxHandle; + HWND PathControlHandle; PH_LAYOUT_MANAGER LayoutManager; HTREEITEM RootTreeObject; @@ -117,21 +118,21 @@ typedef struct _HANDLE_OPEN_CONTEXT { PPH_STRING CurrentPath; POBJECT_ENTRY Object; -} HANDLE_OPEN_CONTEXT, * PHANDLE_OPEN_CONTEXT; + PPH_STRING FullName; +} HANDLE_OPEN_CONTEXT, *PHANDLE_OPEN_CONTEXT; typedef struct _RESOLVER_THREAD_CONTEXT { - BOOL Break; POBJECT_CONTEXT Context; -} RESOLVER_THREAD_CONTEXT, * PRESOLVER_THREAD_CONTEXT; + BOOL Break; +} RESOLVER_THREAD_CONTEXT, *PRESOLVER_THREAD_CONTEXT; typedef struct _RESOLVER_WORK_THREAD_CONTEXT { POBJECT_CONTEXT Context; POBJECT_ENTRY entry; INT ItemIndex; - //BOOLEAN SortItems; -} RESOLVER_WORK_THREAD_CONTEXT, * PRESOLVER_WORK_THREAD_CONTEXT; +} RESOLVER_WORK_THREAD_CONTEXT, *PRESOLVER_WORK_THREAD_CONTEXT; NTSTATUS EtTreeViewEnumDirectoryObjects( _In_ HWND TreeViewHandle, @@ -280,19 +281,23 @@ HTREEITEM EtTreeViewAddItem( HTREEITEM EtTreeViewFindItem( _In_ HWND TreeViewHandle, _In_ HTREEITEM ParentTreeItem, - _In_ PPH_STRINGREF Name + _In_ PPH_STRINGREF Name, + _In_ BOOLEAN Reverse ) { HTREEITEM current; + HTREEITEM sibling; HTREEITEM child; PPH_STRING directory; ULONG children; - for ( - current = TreeView_GetChild(TreeViewHandle, ParentTreeItem); - current; - current = TreeView_GetNextSibling(TreeViewHandle, current) - ) + current = TreeView_GetChild(TreeViewHandle, ParentTreeItem); + + if (Reverse) + while (sibling = TreeView_GetNextSibling(TreeViewHandle, current)) + current = sibling; + + do { if (PhGetTreeViewItemParam(TreeViewHandle, current, &directory, &children)) { @@ -303,13 +308,17 @@ HTREEITEM EtTreeViewFindItem( if (children) { - if (child = EtTreeViewFindItem(TreeViewHandle, current, Name)) + if (child = EtTreeViewFindItem(TreeViewHandle, current, Name, Reverse)) { return child; } } } - } + } while (current = + !Reverse ? + TreeView_GetNextSibling(TreeViewHandle, current) : + TreeView_GetPrevSibling(TreeViewHandle, current) + ); return NULL; } @@ -523,7 +532,7 @@ static BOOLEAN NTAPI EtEnumCurrentDirectoryObjectsCallback( { if (PhEqualStringRef(TypeName, &DirectoryObjectType, TRUE)) { - if (!EtTreeViewFindItem(Context->TreeViewHandle, Context->SelectedTreeItem, Name)) + if (!EtTreeViewFindItem(Context->TreeViewHandle, Context->SelectedTreeItem, Name, FALSE)) { EtTreeViewAddItem(Context->TreeViewHandle, Context->SelectedTreeItem, TRUE, Name); } @@ -720,10 +729,9 @@ NTSTATUS EtpTargetResolverThreadStart( ULONG sortColumn; PH_SORT_ORDER sortOrder; - PhInitializeWorkQueue(&workQueue, 1, 20, 1000); + ExtendedListView_SetColumnWidth(context->ListViewHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); - ExtendedListView_GetSort(context->ListViewHandle, &sortColumn, &sortOrder); - BOOLEAN sortItems = sortOrder != NoSortOrder && sortColumn == 2; + PhInitializeWorkQueue(&workQueue, 1, 20, 1000); for (ULONG i = 0; i < context->CurrentDirectoryList->Count; i++) { @@ -740,7 +748,6 @@ NTSTATUS EtpTargetResolverThreadStart( workContext->Context = context; workContext->entry = entry; workContext->ItemIndex = PhFindListViewItemByParam(context->ListViewHandle, INT_ERROR, entry); - //workContext->SortItems = SortItems; PhQueueItemWorkQueue(&workQueue, EtpTargetResolverWorkThreadStart, workContext); } @@ -759,7 +766,8 @@ NTSTATUS EtpTargetResolverThreadStart( } else { - if (sortItems) + ExtendedListView_GetSort(context->ListViewHandle, &sortColumn, &sortOrder); + if (sortOrder != NoSortOrder && sortColumn == 2) { ExtendedListView_SortItems(context->ListViewHandle); @@ -771,6 +779,8 @@ NTSTATUS EtpTargetResolverThreadStart( if (curentFilter) PhDereferenceObject(curentFilter); + //ExtendedListView_SetColumnWidth(context->ListViewHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); + context->BreakResolverThread = NULL; status = STATUS_SUCCESS; } @@ -795,6 +805,7 @@ NTSTATUS EtpTargetResolverWorkThreadStart( objectContext.CurrentPath = PhReferenceObject(context->CurrentPath); objectContext.Object = entry; + objectContext.FullName = NULL; switch (entry->EtObjectType) { @@ -869,9 +880,10 @@ NTSTATUS EtpTargetResolverWorkThreadStart( ULONG_PTR column_pos = PhFindLastCharInString(devicePdoName, 0, L':'); devicePdoName2 = PhSubstring(devicePdoName, 0, column_pos + 1); devicePdoName2->Buffer[column_pos - 4] = L'[', devicePdoName2->Buffer[column_pos] = L']'; - PhMoveReference(&entry->Target, devicePdoName2); - entry->TargetIsInfoOnly = TRUE; PhDereferenceObject(devicePdoName); + + entry->TargetIsInfoOnly = TRUE; + PhMoveReference(&entry->Target, devicePdoName2); } } @@ -926,7 +938,6 @@ NTSTATUS EtpTargetResolverWorkThreadStart( entry->TargetClientId.UniqueThread = clientId.UniqueThread; } } - NtClose(processId == NtCurrentProcessId() ? objectHandle : processHandle); } } @@ -948,7 +959,6 @@ NTSTATUS EtpTargetResolverWorkThreadStart( entry->TargetClientId.UniqueThread = ownerInfo.ClientId.UniqueThread; } } - NtClose(objectHandle); } } @@ -998,10 +1008,10 @@ NTSTATUS EtpTargetResolverWorkThreadStart( break; case EtObjectDriver: { - PPH_STRING driverName; - if (NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, READ_CONTROL, 0))) { + PPH_STRING driverName; + if (NT_SUCCESS(status = PhGetDriverImageFileName(objectHandle, &driverName))) { PhMoveReference(&entry->Target, driverName); @@ -1012,13 +1022,21 @@ NTSTATUS EtpTargetResolverWorkThreadStart( break; case EtObjectSection: { - PPH_STRING fileName; - PPH_STRING newFileName; - SECTION_BASIC_INFORMATION basicInfo; + HANDLE processId = NtCurrentProcessId(); + HANDLE processHandle = NtCurrentProcess(); - if (NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, SECTION_QUERY | SECTION_MAP_READ, 0))) + if (!NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, SECTION_QUERY | SECTION_MAP_READ, 0))) { - if (NT_SUCCESS(status = PhGetSectionFileName(objectHandle, &fileName))) + status = EtObjectManagerOpenRealObject(&objectHandle, &objectContext, 0, &processId); + } + + if (NT_SUCCESS(status)) + { + PPH_STRING fileName; + PPH_STRING newFileName; + SECTION_BASIC_INFORMATION basicInfo; + + if (NT_SUCCESS(PhGetSectionFileName(objectHandle, &fileName))) { if (newFileName = PhResolveDevicePrefix(&fileName->sr)) PhMoveReference(&fileName, newFileName); @@ -1027,7 +1045,33 @@ NTSTATUS EtpTargetResolverWorkThreadStart( } else { - if (NT_SUCCESS(status = PhGetSectionBasicInformation(objectHandle, &basicInfo))) + if (processId != NtCurrentProcessId()) + { + if (KsiLevel() >= KphLevelMed && + NT_SUCCESS(status = PhOpenProcess( + &processHandle, + PROCESS_QUERY_LIMITED_INFORMATION, + processId + ))) + { + status = KphQueryInformationObject( + processHandle, + objectHandle, + KphObjectSectionBasicInformation, + &basicInfo, + sizeof(basicInfo), + NULL + ); + NtClose(processHandle); + } + } + else + { + status = PhGetSectionBasicInformation(objectHandle, &basicInfo); + NtClose(objectHandle); + } + + if (NT_SUCCESS(status)) { PH_FORMAT format[4]; PWSTR sectionType = L"Unknown"; @@ -1050,18 +1094,16 @@ NTSTATUS EtpTargetResolverWorkThreadStart( entry->Target = PhFormat(format, 4, 0); } } - - NtClose(objectHandle); } } break; case EtObjectEvent: { - EVENT_BASIC_INFORMATION basicInfo; - PWSTR eventType = NULL; - if (NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, EVENT_QUERY_STATE, 0))) { + EVENT_BASIC_INFORMATION basicInfo; + PWSTR eventType = NULL; + if (NT_SUCCESS(PhGetEventBasicInformation(objectHandle, &basicInfo))) { switch (basicInfo.EventType) @@ -1086,10 +1128,10 @@ NTSTATUS EtpTargetResolverWorkThreadStart( break; case EtObjectTimer: { - TIMER_BASIC_INFORMATION basicInfo; - if (NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, TIMER_QUERY_STATE, 0))) { + TIMER_BASIC_INFORMATION basicInfo; + if (NT_SUCCESS(PhGetTimerBasicInformation(objectHandle, &basicInfo))) { if (basicInfo.TimerState) @@ -1102,10 +1144,10 @@ NTSTATUS EtpTargetResolverWorkThreadStart( break; case EtObjectSemaphore: { - SEMAPHORE_BASIC_INFORMATION basicInfo; - if (NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, SEMAPHORE_QUERY_STATE, 0))) { + SEMAPHORE_BASIC_INFORMATION basicInfo; + if (NT_SUCCESS(PhGetSemaphoreBasicInformation(objectHandle, &basicInfo))) { entry->Target = PhFormatString(L"Current count: %d/%d", basicInfo.CurrentCount, basicInfo.MaximumCount); @@ -1120,8 +1162,6 @@ NTSTATUS EtpTargetResolverWorkThreadStart( // Target was successfully resolved, redraw list entry entry->TargetIsResolving = FALSE; ListView_RedrawItems(context->ListViewHandle, threadContext->ItemIndex, threadContext->ItemIndex); - //if (threadContext->SortItems) - // ExtendedListView_SortItems(Context->ListViewHandle); PhDereferenceObject(objectContext.CurrentPath); PhFree(threadContext); @@ -1174,17 +1214,16 @@ NTSTATUS EtEnumCurrentDirectoryObjects( PhShowStatus(Context->WindowHandle, L"Unable to query directory object.", status, 0); } - PhSetWindowText(GetDlgItem(Context->WindowHandle, IDC_OBJMGR_PATH), PhGetString(Context->CurrentPath)); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJMGR_PATH, PhGetString(Context->CurrentPath)); PhPrintUInt32(string, Context->CurrentDirectoryList->Count); - PhSetWindowText(GetDlgItem(Context->WindowHandle, IDC_OBJMGR_COUNT), string); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJMGR_COUNT, string); // Apply current filter and sort PPH_STRING curentFilter = PH_AUTO(PhGetWindowText(Context->SearchBoxHandle)); if (!PhIsNullOrEmptyString(curentFilter)) { - EtpObjectManagerSearchControlCallback( // HACK - (ULONG_PTR)PhGetWindowContext(Context->SearchBoxHandle, SHRT_MAX), Context); + EtpObjectManagerSearchControlCallback((ULONG_PTR)PhGetWindowContext(Context->SearchBoxHandle, SHRT_MAX), Context); // HACK } ExtendedListView_GetSort(Context->ListViewHandle, &sortColumn, &sortOrder); @@ -1239,51 +1278,22 @@ VOID EtObjectManagerFreeListViewItems( PhClearList(Context->CurrentDirectoryList); } -NTSTATUS EtDuplicateHandleFromProcess( - _Out_ PHANDLE Handle, - _In_ ACCESS_MASK DesiredAccess, - _In_ HANDLE ProcessHandle, - _In_ HANDLE SourceHandle - ) -{ - NTSTATUS status; - - if (KsiLevel() == KphLevelMax) - { - status = KphDuplicateObject( - ProcessHandle, - SourceHandle, - DesiredAccess, - Handle - ); - } - else - { - status = NtDuplicateObject( - ProcessHandle, - SourceHandle, - NtCurrentProcess(), - Handle, - DesiredAccess, - 0, - 0 - ); - } - - return status; -} - NTSTATUS EtDuplicateHandleFromProcessEx( _Out_ PHANDLE Handle, _In_ ACCESS_MASK DesiredAccess, - _In_ HANDLE ProcessId, + _In_opt_ HANDLE ProcessId, + _In_opt_ HANDLE ProcessHandle, _In_ HANDLE SourceHandle ) { - NTSTATUS status; + NTSTATUS status = STATUS_INVALID_PARAMETER; HANDLE processHandle; - if (NT_SUCCESS(status = PhOpenProcess( + *Handle = NULL; + processHandle = ProcessHandle; + + if (ProcessHandle || + ProcessId && NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, ProcessId @@ -1298,12 +1308,15 @@ NTSTATUS EtDuplicateHandleFromProcessEx( 0, 0 ); - NtClose(processHandle); + if (!ProcessHandle) NtClose(processHandle); } if (!NT_SUCCESS(status) && KsiLevel() == KphLevelMax) { - if (NT_SUCCESS(status = PhOpenProcess( + processHandle = ProcessHandle; + + if (ProcessHandle || + ProcessId && NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_LIMITED_INFORMATION, ProcessId @@ -1315,7 +1328,7 @@ NTSTATUS EtDuplicateHandleFromProcessEx( DesiredAccess, Handle ); - NtClose(processHandle); + if (!ProcessHandle) NtClose(processHandle); } } @@ -1665,7 +1678,7 @@ NTSTATUS EtObjectManagerOpenHandle( // Open real FilterConnectionPort // Open real \REGISTRY key // -// If OwnerProcessId is specified and handle can't be duplicated returns UniqueProcessId and HandleValue instead. +// If OwnerProcessId is specified returns UniqueProcessId and HandleValue instead. // This allows to extract object information through driver APIs even for objects with kernel only access (OBJ_KERNEL_HANDLE). NTSTATUS EtObjectManagerOpenRealObject( _Out_ PHANDLE Handle, @@ -1708,7 +1721,7 @@ NTSTATUS EtObjectManagerOpenRealObject( targetIndex = EtWinStaTypeIndex; break; default: - targetIndex = PhGetObjectTypeNumberZ(PhGetString(Context->Object->TypeName)); + targetIndex = PhGetObjectTypeNumber(&Context->Object->TypeName->sr); } if (Context->Object->EtObjectType == EtObjectDirectory) @@ -1729,12 +1742,10 @@ NTSTATUS EtObjectManagerOpenRealObject( if (handleInfo->ObjectTypeIndex == targetIndex) { // Open a handle to the process if we don't already have one. - processHandlePtr = PhFindItemSimpleHashtable( + if (processHandlePtr = PhFindItemSimpleHashtable( processHandleHashtable, (PVOID)handleInfo->UniqueProcessId - ); - - if (processHandlePtr) + )) { processHandle = *processHandlePtr; } @@ -1770,16 +1781,28 @@ NTSTATUS EtObjectManagerOpenRealObject( { if (PhEqualString(objectName, fullName, TRUE)) { - if (!NT_SUCCESS(status = EtDuplicateHandleFromProcess( + if (OwnerProcessId) + { + *OwnerProcessId = (HANDLE)handleInfo->UniqueProcessId; + *Handle = (HANDLE)handleInfo->HandleValue; + status = STATUS_SUCCESS; + + PhDereferenceObject(objectName); + break; + } + + if (!NT_SUCCESS(status = EtDuplicateHandleFromProcessEx( &objectHandle, DesiredAccess, + NULL, processHandle, (HANDLE)handleInfo->HandleValue ))) { - status = EtDuplicateHandleFromProcess( + status = EtDuplicateHandleFromProcessEx( &objectHandle, 0, + NULL, processHandle, (HANDLE)handleInfo->HandleValue ); @@ -1789,12 +1812,6 @@ NTSTATUS EtObjectManagerOpenRealObject( { *Handle = objectHandle; } - else if (OwnerProcessId) - { - *OwnerProcessId = (HANDLE)handleInfo->UniqueProcessId; - *Handle = (HANDLE)handleInfo->HandleValue; - status = STATUS_SUCCESS; - } PhDereferenceObject(objectName); break; @@ -1838,10 +1855,9 @@ NTSTATUS EtObjectManagerHandleCloseCallback( { PHANDLE_OPEN_CONTEXT context = Context; - if (context->CurrentPath) - { - PhClearReference(&context->CurrentPath); - } + if (context->CurrentPath) PhClearReference(&context->CurrentPath); + if (context->FullName) PhClearReference(&context->FullName); + if (context->Object) { PhClearReference(&context->Object->Name); @@ -1969,7 +1985,6 @@ NTSTATUS EtObjectManagerGetHandleInfoEx( } VOID NTAPI EtpObjectManagerObjectProperties( - _In_ HWND hwndDlg, _In_ POBJECT_CONTEXT Context, _In_ POBJECT_ENTRY Entry ) @@ -1984,6 +1999,7 @@ VOID NTAPI EtpObjectManagerObjectProperties( objectContext.CurrentPath = PhReferenceObject(Context->CurrentPath); objectContext.Object = Entry; + objectContext.FullName = NULL; if (Entry->EtObjectType == EtObjectDirectory) objectContext.Object->TypeName = PhCreateString2(&DirectoryObjectType); @@ -1997,7 +2013,7 @@ VOID NTAPI EtpObjectManagerObjectProperties( !NT_SUCCESS(status = EtObjectManagerOpenHandle(&objectHandle, &objectContext, MAXIMUM_ALLOWED, OBJECT_OPENSOURCE_ALL))) { // Can open KernelOnlyAccess object if any opened handles for this object exists (ex. \PowerPort, \Win32kCrossSessionGlobals) - status = EtObjectManagerOpenRealObject(&objectHandle, &objectContext, READ_CONTROL | WRITE_DAC, &processId); + status = EtObjectManagerOpenRealObject(&objectHandle, &objectContext, 0, &processId); } } @@ -2016,11 +2032,11 @@ VOID NTAPI EtpObjectManagerObjectProperties( } if (Entry->EtObjectType == EtObjectDirectory) - handleItem->BestObjectName = PhReferenceObject(Context->CurrentPath); + handleItem->ObjectName = PhReferenceObject(Context->CurrentPath); else - handleItem->BestObjectName = EtGetObjectFullPath(Context->CurrentPath, Entry->Name); + handleItem->ObjectName = EtGetObjectFullPath(Context->CurrentPath, Entry->Name); - handleItem->ObjectName = PhReferenceObject(handleItem->BestObjectName); + handleItem->BestObjectName = PhReferenceObject(handleItem->ObjectName); if (NT_SUCCESS(status)) { @@ -2099,13 +2115,12 @@ VOID NTAPI EtpObjectManagerObjectProperties( EtObjectManagerPropIcon = PhImageListGetIcon(Context->ListImageList, Entry->EtObjectType, ILD_NORMAL | ILD_TRANSPARENT); // Object Manager plugin window - PhShowHandlePropertiesEx(hwndDlg, processId, handleItem, PluginInstance, PhGetString(Entry->TypeName)); + PhShowHandlePropertiesEx(Context->WindowHandle, processId, handleItem, PluginInstance, PhGetString(Entry->TypeName)); PhDereferenceObject(Context->CurrentPath); } VOID NTAPI EtpObjectManagerOpenTarget( - _In_ HWND hwndDlg, _In_ POBJECT_CONTEXT Context, _In_ PPH_STRING Target ) @@ -2116,6 +2131,7 @@ VOID NTAPI EtpObjectManagerOpenTarget( PH_STRINGREF namePart = PhGetStringRef(NULL); HTREEITEM selectedTreeItem; PPH_STRING targetPath; + BOOLEAN reverseScan = FALSE; targetPath = PhReferenceObject(Target); remainingPart = PhGetStringRef(targetPath); @@ -2128,6 +2144,7 @@ VOID NTAPI EtpObjectManagerOpenTarget( { if (PhStartsWithStringRef(&remainingPart, &EtObjectManagerRootDirectoryObject, TRUE)) { +start_scan: while (remainingPart.Length != 0) { PhSplitStringRefAtChar(&remainingPart, OBJ_NAME_PATH_SEPARATOR, &directoryPart, &remainingPart); @@ -2137,7 +2154,8 @@ VOID NTAPI EtpObjectManagerOpenTarget( HTREEITEM directoryItem = EtTreeViewFindItem( Context->TreeViewHandle, selectedTreeItem, - &directoryPart + &directoryPart, + reverseScan ); if (directoryItem) @@ -2149,6 +2167,14 @@ VOID NTAPI EtpObjectManagerOpenTarget( } } } + + if (!reverseScan && !PhStartsWithString(targetPath, PH_AUTO_T(PH_STRING, EtGetSelectedTreeViewPath(Context)), TRUE)) + { + remainingPart = PhGetStringRef(targetPath); + selectedTreeItem = Context->RootTreeObject; + reverseScan = TRUE; + goto start_scan; + } } if (!Context->CurrentPath) @@ -2178,7 +2204,7 @@ VOID NTAPI EtpObjectManagerOpenTarget( (PhDoesFileExist(&Target->sr) || PhDoesFileExistWin32(Target->Buffer))) { PhShellExecuteUserString( - hwndDlg, + Context->WindowHandle, L"FileBrowseExecutable", PhGetString(Target), FALSE, @@ -2187,7 +2213,7 @@ VOID NTAPI EtpObjectManagerOpenTarget( } else { - PhShowStatus(hwndDlg, L"Unable to locate the target.", STATUS_NOT_FOUND, 0); + PhShowStatus(Context->WindowHandle, L"Unable to locate the target.", STATUS_NOT_FOUND, 0); } } } @@ -2218,19 +2244,17 @@ VOID NTAPI EtpObjectManagerOpenTarget( } VOID NTAPI EtpObjectManagerRefresh( - _In_ HWND hwndDlg, _In_ POBJECT_CONTEXT Context ) { - PPH_STRING selectedPath = NULL; - BOOLEAN rootWasSelected = Context->SelectedTreeItem == Context->RootTreeObject; - HWND countControl = GetDlgItem(hwndDlg, IDC_OBJMGR_COUNT); + PPH_STRING currentPath = PhReferenceObject(Context->CurrentPath); PPH_STRING oldSelect = NULL; POBJECT_ENTRY* listviewItems; ULONG numberOfItems; - - if (!rootWasSelected) - selectedPath = EtGetSelectedTreeViewPath(Context); + PH_STRINGREF directoryPart; + PH_STRINGREF remainingPart; + HTREEITEM selectedTreeItem; + BOOLEAN reverseScan = FALSE; PhGetSelectedListViewItemParams(Context->ListViewHandle, &listviewItems, &numberOfItems); if (numberOfItems != 0) @@ -2244,6 +2268,7 @@ VOID NTAPI EtpObjectManagerRefresh( EtCleanupTreeViewItemParams(Context, Context->RootTreeObject); TreeView_DeleteAllItems(Context->TreeViewHandle); + Context->DisableSelChanged = TRUE; Context->RootTreeObject = EtTreeViewAddItem(Context->TreeViewHandle, TVI_ROOT, TRUE, &EtObjectManagerRootDirectoryObject); EtTreeViewEnumDirectoryObjects( @@ -2252,60 +2277,52 @@ VOID NTAPI EtpObjectManagerRefresh( EtObjectManagerRootDirectoryObject ); - if (rootWasSelected) - { - TreeView_SelectItem(Context->TreeViewHandle, Context->RootTreeObject); - } - else - { - PH_STRINGREF directoryPart; - PH_STRINGREF remainingPart; - HTREEITEM selectedTreeItem = NULL; - - Context->DisableSelChanged = TRUE; +start_scan: + remainingPart = PhGetStringRef(currentPath); + selectedTreeItem = Context->RootTreeObject; - directoryPart = PhGetStringRef(NULL); - remainingPart = PhGetStringRef(selectedPath); - selectedTreeItem = Context->RootTreeObject; + while (remainingPart.Length != 0) + { + PhSplitStringRefAtChar(&remainingPart, OBJ_NAME_PATH_SEPARATOR, &directoryPart, &remainingPart); - while (remainingPart.Length != 0) + if (directoryPart.Length != 0) { - PhSplitStringRefAtChar(&remainingPart, OBJ_NAME_PATH_SEPARATOR, &directoryPart, &remainingPart); + HTREEITEM directoryItem = EtTreeViewFindItem( + Context->TreeViewHandle, + selectedTreeItem, + &directoryPart, + reverseScan + ); - if (directoryPart.Length != 0) - { - HTREEITEM directoryItem = EtTreeViewFindItem( - Context->TreeViewHandle, - selectedTreeItem, - &directoryPart - ); - if (directoryItem) - { - TreeView_SelectItem(Context->TreeViewHandle, directoryItem); - selectedTreeItem = directoryItem; - } + if (directoryItem) + { + TreeView_SelectItem(Context->TreeViewHandle, directoryItem); + selectedTreeItem = directoryItem; } } + } - PhDereferenceObject(selectedPath); - - // Will reapply filter and sort - if (selectedTreeItem) - EtpObjectManagerChangeSelection(Context); + // Will reapply filter and sort + EtpObjectManagerChangeSelection(Context); - Context->DisableSelChanged = FALSE; + if (!reverseScan && !PhStartsWithString(currentPath, PH_AUTO_T(PH_STRING, EtGetSelectedTreeViewPath(Context)), TRUE)) + { + reverseScan = TRUE; + goto start_scan; } // Reapply old selection EtpObjectManagerSortAndSelectOld(Context, oldSelect); + Context->DisableSelChanged = FALSE; SendMessage(Context->TreeViewHandle, WM_SETREDRAW, TRUE, 0); ExtendedListView_SetRedraw(Context->ListViewHandle, TRUE); + + PhDereferenceObject(currentPath); } VOID NTAPI EtpObjectManagerOpenSecurity( - _In_ HWND hwndDlg, _In_ POBJECT_CONTEXT Context, _In_ POBJECT_ENTRY Entry ) @@ -2315,22 +2332,24 @@ VOID NTAPI EtpObjectManagerOpenSecurity( objectContext = PhAllocateZero(sizeof(HANDLE_OPEN_CONTEXT)); objectContext->CurrentPath = PhReferenceObject(Context->CurrentPath); objectContext->Object = PhAllocateZero(sizeof(ET_OBJECT_ENTRY)); - objectContext->Object->Name = PhReferenceObject(Entry->Name); objectContext->Object->EtObjectType = Entry->EtObjectType; + objectContext->Object->Name = PhReferenceObject(Entry->Name); switch (Entry->EtObjectType) { case EtObjectDirectory: objectContext->Object->TypeName = PhCreateString2(&DirectoryObjectType); + objectContext->FullName = PhReferenceObject(Context->CurrentPath); break; default: objectContext->Object->TypeName = PhReferenceObject(Entry->TypeName); + objectContext->FullName = EtGetObjectFullPath(Context->CurrentPath, Entry->Name); break; } PhEditSecurity( !!PhGetIntegerSetting(L"ForceNoParent") ? NULL : Context->WindowHandle, - PhGetString(objectContext->Object->Name), + PhGetString(objectContext->FullName), PhGetString(objectContext->Object->TypeName), EtObjectManagerHandleOpenCallback, EtObjectManagerHandleCloseCallback, @@ -2384,7 +2403,7 @@ VOID NTAPI EtpObjectManagerSearchControlCallback( WCHAR string[PH_INT32_STR_LEN_1]; PhPrintUInt32(string, ListView_GetItemCount(context->ListViewHandle)); - PhSetWindowText(GetDlgItem(context->WindowHandle, IDC_OBJMGR_COUNT), string); + PhSetDialogItemText(context->WindowHandle, IDC_OBJMGR_COUNT, string); } VOID NTAPI EtpObjectManagerSortAndSelectOld( @@ -2442,12 +2461,25 @@ INT_PTR CALLBACK WinObjDlgProc( _In_ LPARAM lParam ) { + static PH_INITONCE initOnce = PH_INITONCE_INIT; POBJECT_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = PhAllocateZero(sizeof(ET_OBJECT_CONTEXT)); PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); + + if (PhBeginInitOnce(&initOnce)) + { + EtAlpcPortTypeIndex = PhGetObjectTypeNumberZ(L"ALPC Port"); + EtDeviceTypeIndex = PhGetObjectTypeNumberZ(L"Device"); + EtFilterPortTypeIndex = PhGetObjectTypeNumberZ(L"FilterConnectionPort"); + EtFileTypeIndex = PhGetObjectTypeNumberZ(L"File"); + EtKeyTypeIndex = PhGetObjectTypeNumberZ(L"Key"); + EtSectionTypeIndex = PhGetObjectTypeNumberZ(L"Section"); + EtWinStaTypeIndex = PhGetObjectTypeNumberZ(L"WindowStation"); + PhEndInitOnce(&initOnce); + } } else { @@ -2466,6 +2498,7 @@ INT_PTR CALLBACK WinObjDlgProc( context->TreeViewHandle = GetDlgItem(hwndDlg, IDC_OBJMGR_TREE); context->ListViewHandle = GetDlgItem(hwndDlg, IDC_OBJMGR_LIST); context->SearchBoxHandle = GetDlgItem(hwndDlg, IDC_OBJMGR_SEARCH); + context->PathControlHandle = GetDlgItem(hwndDlg, IDC_OBJMGR_PATH); context->CurrentDirectoryList = PhCreateList(100); if (!EtObjectManagerOwnHandles || !PhReferenceObjectSafe(EtObjectManagerOwnHandles)) EtObjectManagerOwnHandles = PhCreateList(10); @@ -2495,7 +2528,6 @@ INT_PTR CALLBACK WinObjDlgProc( sortSettings = PhGetIntegerPairSetting(SETTING_NAME_OBJMGR_LIST_SORT); ExtendedListView_SetContext(context->ListViewHandle, context); - //ExtendedListView_SetSortFast(context->ListViewHandle, TRUE); ExtendedListView_SetTriState(context->ListViewHandle, TRUE); ExtendedListView_SetSort(context->ListViewHandle, (ULONG)sortSettings.X, (PH_SORT_ORDER)sortSettings.Y); ExtendedListView_SetCompareFunction(context->ListViewHandle, 0, WinObjNameCompareFunction); @@ -2507,7 +2539,7 @@ INT_PTR CALLBACK WinObjDlgProc( PhAddLayoutItem(&context->LayoutManager, context->TreeViewHandle, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, context->SearchBoxHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); - PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_OBJMGR_PATH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT); + PhAddLayoutItem(&context->LayoutManager, context->PathControlHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_OBJMGR_COUNT_L), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_OBJMGR_COUNT), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REFRESH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); @@ -2535,7 +2567,7 @@ INT_PTR CALLBACK WinObjDlgProc( PPH_STRING Target = PH_AUTO(PhGetStringSetting(SETTING_NAME_OBJMGR_LAST_PATH)); - EtpObjectManagerOpenTarget(hwndDlg, context, Target); + EtpObjectManagerOpenTarget(context, Target); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->TreeViewHandle, TRUE); ExtendedListView_SetColumnWidth(context->ListViewHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); @@ -2543,7 +2575,7 @@ INT_PTR CALLBACK WinObjDlgProc( break; case WM_DESTROY: { - PPH_STRING CurrentPath = PhReferenceObject(context->CurrentPath); + PPH_STRING currentPath = PhReferenceObject(context->CurrentPath); PH_INTEGER_PAIR sortSettings; ULONG sortColumn; PH_SORT_ORDER sortOrder; @@ -2570,8 +2602,8 @@ INT_PTR CALLBACK WinObjDlgProc( sortSettings.Y = sortOrder; PhSetIntegerPairSetting(SETTING_NAME_OBJMGR_LIST_SORT, sortSettings); - PhSetStringSetting(SETTING_NAME_OBJMGR_LAST_PATH, PhGetString(CurrentPath)); - PhDereferenceObject(CurrentPath); + PhSetStringSetting(SETTING_NAME_OBJMGR_LAST_PATH, PhGetString(currentPath)); + PhDereferenceObject(currentPath); PhDeleteLayoutManager(&context->LayoutManager); @@ -2610,7 +2642,7 @@ INT_PTR CALLBACK WinObjDlgProc( DestroyWindow(hwndDlg); break; case IDC_REFRESH: - EtpObjectManagerRefresh(hwndDlg, context); + EtpObjectManagerRefresh(context); break; } } @@ -2674,11 +2706,8 @@ INT_PTR CALLBACK WinObjDlgProc( info->uChanged & LVIF_STATE && info->uNewState & (LVIS_ACTIVATING | LVIS_FOCUSED)) { POBJECT_ENTRY entry = (POBJECT_ENTRY)info->lParam; - PPH_STRING fullPath; - fullPath = PH_AUTO(EtGetObjectFullPath(context->CurrentPath, entry->Name)); - - PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJMGR_PATH), PhGetString(fullPath)); + PhSetDialogItemText(hwndDlg, IDC_OBJMGR_PATH, PhGetString(PH_AUTO_T(PH_STRING, EtGetObjectFullPath(context->CurrentPath, entry->Name)))); } } break; @@ -2702,16 +2731,16 @@ INT_PTR CALLBACK WinObjDlgProc( { if (GetKeyState(VK_CONTROL) < 0) { - EtpObjectManagerOpenSecurity(hwndDlg, context, entry); + EtpObjectManagerOpenSecurity(context, entry); } else if (entry->EtObjectType == EtObjectSymLink && !(GetKeyState(VK_SHIFT) < 0)) { if (!PhIsNullOrEmptyString(entry->Target)) - EtpObjectManagerOpenTarget(hwndDlg, context, entry->Target); + EtpObjectManagerOpenTarget(context, entry->Target); } else { - EtpObjectManagerObjectProperties(hwndDlg, context, entry); + EtpObjectManagerObjectProperties(context, entry); } } } @@ -2853,22 +2882,22 @@ INT_PTR CALLBACK WinObjDlgProc( { case IDC_PROPERTIES: { - EtpObjectManagerObjectProperties(hwndDlg, context, entry); + EtpObjectManagerObjectProperties(context, entry); } break; case IDC_OPENLINK: { - EtpObjectManagerOpenTarget(hwndDlg, context, entry->Target); + EtpObjectManagerOpenTarget(context, entry->Target); } break; case IDC_GOTODRIVER: { - EtpObjectManagerOpenTarget(hwndDlg, context, entry->TargetDrvLow); + EtpObjectManagerOpenTarget(context, entry->TargetDrvLow); } break; case IDC_GOTODRIVER2: { - EtpObjectManagerOpenTarget(hwndDlg, context, entry->TargetDrvUp); + EtpObjectManagerOpenTarget(context, entry->TargetDrvUp); } break; case IDC_GOTOPROCESS: @@ -2919,7 +2948,7 @@ INT_PTR CALLBACK WinObjDlgProc( break; case IDC_SECURITY: { - EtpObjectManagerOpenSecurity(hwndDlg, context, entry); + EtpObjectManagerOpenSecurity(context, entry); } break; case IDC_COPY: @@ -2989,12 +3018,12 @@ INT_PTR CALLBACK WinObjDlgProc( { case IDC_PROPERTIES: { - EtpObjectManagerObjectProperties(hwndDlg, context, &entry); + EtpObjectManagerObjectProperties(context, &entry); } break; case IDC_SECURITY: { - EtpObjectManagerOpenSecurity(hwndDlg, context, &entry); + EtpObjectManagerOpenSecurity(context, &entry); } break; case IDC_COPY: @@ -3016,15 +3045,14 @@ INT_PTR CALLBACK WinObjDlgProc( } else if ((HWND)wParam == hwndDlg) { - HWND pathControl = GetDlgItem(hwndDlg, IDC_OBJMGR_PATH); POINT point; RECT pathRect; point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); - GetWindowRect(pathControl, &pathRect); - InflateRect(&pathRect, 0, 3); + GetWindowRect(context->PathControlHandle, &pathRect); + PhInflateRect(&pathRect, 0, 3); if (PtInRect(&pathRect, point)) { @@ -3042,7 +3070,7 @@ INT_PTR CALLBACK WinObjDlgProc( if (item && item->Id == IDC_COPYPATH) { - PhSetClipboardString(hwndDlg, &PH_AUTO_T(PH_STRING, PhGetWindowText(pathControl))->sr); + PhSetClipboardString(hwndDlg, &PH_AUTO_T(PH_STRING, PhGetWindowText(context->PathControlHandle))->sr); } PhDestroyEMenu(menu); @@ -3063,7 +3091,7 @@ INT_PTR CALLBACK WinObjDlgProc( break; case VK_F5: { - EtpObjectManagerRefresh(hwndDlg, context); + EtpObjectManagerRefresh(context); return TRUE; } break; @@ -3078,24 +3106,24 @@ INT_PTR CALLBACK WinObjDlgProc( { if (listviewItems[0]->EtObjectType == EtObjectSymLink && GetKeyState(VK_SHIFT) < 0) { - EtpObjectManagerObjectProperties(hwndDlg, context, listviewItems[0]); + EtpObjectManagerObjectProperties(context, listviewItems[0]); } else if (GetKeyState(VK_CONTROL) < 0) { - EtpObjectManagerOpenSecurity(hwndDlg, context, listviewItems[0]); + EtpObjectManagerOpenSecurity(context, listviewItems[0]); } else { if (listviewItems[0]->EtObjectType == EtObjectSymLink) { if (!PhIsNullOrEmptyString(listviewItems[0]->Target)) - EtpObjectManagerOpenTarget(hwndDlg, context, listviewItems[0]->Target); + EtpObjectManagerOpenTarget(context, listviewItems[0]->Target); else break; } else { - EtpObjectManagerObjectProperties(hwndDlg, context, listviewItems[0]); + EtpObjectManagerObjectProperties(context, listviewItems[0]); } } @@ -3113,7 +3141,7 @@ INT_PTR CALLBACK WinObjDlgProc( if (PhGetTreeViewItemParam(context->TreeViewHandle, context->SelectedTreeItem, &directory, NULL)) { entry.Name = directory; - EtpObjectManagerObjectProperties(hwndDlg, context, &entry); + EtpObjectManagerObjectProperties(context, &entry); return TRUE; } } @@ -3122,7 +3150,7 @@ INT_PTR CALLBACK WinObjDlgProc( if (PhGetTreeViewItemParam(context->TreeViewHandle, context->SelectedTreeItem, &directory, NULL)) { entry.Name = directory; - EtpObjectManagerOpenSecurity(hwndDlg, context, &entry); + EtpObjectManagerOpenSecurity(context, &entry); return TRUE; } } @@ -3198,20 +3226,6 @@ VOID EtShowObjectManagerDialog( _In_ HWND ParentWindowHandle ) { - static PH_INITONCE initOnce = PH_INITONCE_INIT; - - if (PhBeginInitOnce(&initOnce)) - { - EtAlpcPortTypeIndex = PhGetObjectTypeNumberZ(L"ALPC Port"); - EtDeviceTypeIndex = PhGetObjectTypeNumberZ(L"Device"); - EtFilterPortTypeIndex = PhGetObjectTypeNumberZ(L"FilterConnectionPort"); - EtFileTypeIndex = PhGetObjectTypeNumberZ(L"File"); - EtKeyTypeIndex = PhGetObjectTypeNumberZ(L"Key"); - EtSectionTypeIndex = PhGetObjectTypeNumberZ(L"Section"); - EtWinStaTypeIndex = PhGetObjectTypeNumberZ(L"WindowStation"); - PhEndInitOnce(&initOnce); - } - if (!EtObjectManagerDialogThreadHandle) { if (!NT_SUCCESS(PhCreateThreadEx(&EtObjectManagerDialogThreadHandle, EtShowObjectManagerDialogThread, ParentWindowHandle))) diff --git a/plugins/ExtendedTools/objprp.c b/plugins/ExtendedTools/objprp.c index c6f887ac7454..cbee70871ca9 100644 --- a/plugins/ExtendedTools/objprp.c +++ b/plugins/ExtendedTools/objprp.c @@ -42,6 +42,7 @@ typedef struct _COMMON_PAGE_CONTEXT // Handles tab ULONG TotalHandlesCount; ULONG OwnHandlesCount; + BOOLEAN ColumnsAdded; } COMMON_PAGE_CONTEXT, *PCOMMON_PAGE_CONTEXT; typedef struct _ET_HANDLE_ENTRY @@ -561,7 +562,13 @@ VOID EtHandlePropertiesWindowInitialized( PhSetListViewSubItem(context->ListViewHandle, EtListViewRowCache[OBJECT_GENERAL_INDEX_WINSTATYPE], 1, PhGetString(stationType)); } - if (NT_SUCCESS(EtDuplicateHandleFromProcessEx((PHANDLE)&hWinStation, WINSTA_READATTRIBUTES, context->ProcessId, context->HandleItem->Handle))) + if (NT_SUCCESS(EtDuplicateHandleFromProcessEx( + (PHANDLE)&hWinStation, + WINSTA_READATTRIBUTES, + context->ProcessId, + NULL, + context->HandleItem->Handle + ))) { if (GetUserObjectInformation( hWinStation, @@ -590,7 +597,13 @@ VOID EtHandlePropertiesWindowInitialized( EtListViewRowCache[OBJECT_GENERAL_INDEX_DESKTOPHEAP] = PhAddListViewGroupItem(context->ListViewHandle, OBJECT_GENERAL_CATEGORY_DESKTOP, OBJECT_GENERAL_INDEX_DESKTOPHEAP, L"Heap size", NULL); - if (NT_SUCCESS(EtDuplicateHandleFromProcessEx((PHANDLE)&hDesktop, DESKTOP_READOBJECTS, context->ProcessId, context->HandleItem->Handle))) + if (NT_SUCCESS(EtDuplicateHandleFromProcessEx( + (PHANDLE)&hDesktop, + DESKTOP_READOBJECTS, + context->ProcessId, + NULL, + context->HandleItem->Handle + ))) { DWORD nLengthNeeded = 0; ULONG vInfo = 0; @@ -900,7 +913,13 @@ INT_PTR CALLBACK EtpTpWorkerFactoryPageDlgProc( PCOMMON_PAGE_CONTEXT context = (PCOMMON_PAGE_CONTEXT)propSheetPage->lParam; HANDLE workerFactoryHandle; - if (NT_SUCCESS(EtDuplicateHandleFromProcessEx(&workerFactoryHandle, WORKER_FACTORY_QUERY_INFORMATION, context->ProcessId, context->HandleItem->Handle))) + if (NT_SUCCESS(EtDuplicateHandleFromProcessEx( + &workerFactoryHandle, + WORKER_FACTORY_QUERY_INFORMATION, + context->ProcessId, + NULL, + context->HandleItem->Handle + ))) { WORKER_FACTORY_BASIC_INFORMATION basicInfo; @@ -1078,16 +1097,30 @@ static NTSTATUS NTAPI EtpSearchHandleFunction( return STATUS_SUCCESS; } +static NTSTATUS NTAPI EtpUpdateHandleFunction( + _In_ PVOID Parameter + ) +{ + PHANDLE_ENTRY entry = Parameter; + + EtUpdateHandleItem(entry->ProcessId, entry->HandleItem); + + return STATUS_SUCCESS; +} + VOID EtpEnumObjectHandles( _In_ PCOMMON_PAGE_CONTEXT Context ) { + PhSetCursor(PhLoadCursor(NULL, IDC_WAIT)); + COLORREF colorNormal = PhIsThemeSupportEnabled() ? PhGetIntegerSetting(L"ThemeWindowBackgroundColor") : GetSysColor(COLOR_WINDOW); COLORREF colorOwnObject = PhGetIntegerSetting(L"ColorOwnProcesses"); COLORREF colorInherit = PhGetIntegerSetting(L"ColorInheritHandles"); COLORREF colorProtected = PhGetIntegerSetting(L"ColorProtectedHandles"); COLORREF colorProtectedInherit = PhGetIntegerSetting(L"ColorPartiallySuspended"); + WCHAR string[PH_INT64_STR_LEN_1]; PSYSTEM_HANDLE_INFORMATION_EX handles; ULONG_PTR i; ULONG searchTypeIndex; @@ -1125,7 +1158,7 @@ VOID EtpEnumObjectHandles( PPH_STRING objectName; BOOLEAN objectNameMatched; - BOOLEAN useWorkQueue = isDevice && KsiLevel() < KphLevelMed; + BOOLEAN useWorkQueue = KsiLevel() < KphLevelMed && (isDevice || isTypeObject && PhEndsWithString2(Context->HandleItem->ObjectName, L"File", TRUE)); if (useWorkQueue) PhInitializeWorkQueue(&workQueue, 1, 20, 1000); @@ -1236,7 +1269,6 @@ VOID EtpEnumObjectHandles( if (useWorkQueue) { PhWaitForWorkQueue(&workQueue); - PhDeleteWorkQueue(&workQueue); } while (PhEnumHashtable(processHandleHashtable, &procEntry, &j)) @@ -1250,7 +1282,8 @@ VOID EtpEnumObjectHandles( PHANDLE_ENTRY entry; PPH_STRING columnString; CLIENT_ID ClientId = { 0 }; - BOOLEAN nameColumnAdded = FALSE; + + ExtendedListView_SetRedraw(Context->ListViewHandle, FALSE); for (i = 0; i < searchResults->Count; i++) { @@ -1274,7 +1307,8 @@ VOID EtpEnumObjectHandles( lvItemIndex = PhAddListViewItem( Context->ListViewHandle, entry->OwnHandle ? ownHandlesIndex++ : MAXINT, // object own handles first - PhGetString(columnString), entry + PhGetString(columnString), + entry ); PhPrintPointer(value, (PVOID)handleInfo->HandleValue); @@ -1303,35 +1337,57 @@ VOID EtpEnumObjectHandles( if (entry->OwnHandle) entry->Color = colorOwnObject; - if (entry->HandleItem->TypeIndex == EtFileTypeIndex || + if (isTypeObject || + entry->HandleItem->TypeIndex == EtFileTypeIndex || entry->HandleItem->TypeIndex == EtKeyTypeIndex || entry->HandleItem->TypeIndex == EtAlpcPortTypeIndex) { - if (!nameColumnAdded) + if (!Context->ColumnsAdded) { - nameColumnAdded = !!PhAddListViewColumn(Context->ListViewHandle, ETHNLVC_NAME, ETHNLVC_NAME, ETHNLVC_NAME, LVCFMT_LEFT, 200, L"Name"); + Context->ColumnsAdded = !!PhAddListViewColumn(Context->ListViewHandle, ETHNLVC_NAME, ETHNLVC_NAME, ETHNLVC_NAME, LVCFMT_LEFT, 200, L"Name"); PhAddListViewColumn(Context->ListViewHandle, ETHNLVC_ORIGNAME, ETHNLVC_ORIGNAME, ETHNLVC_ORIGNAME, LVCFMT_LEFT, 200, L"Original name"); } - // \ObjectTypes\File -> Handles tab leads to deadlock. TODO add implementation with work queue - //if (entry->HandleItem->TypeIndex == EtFileTypeIndex && KsiLevel() < KphLevelMed) - //{ - // continue; - //} - EtUpdateHandleItem(entry->ProcessId, entry->HandleItem); - PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, ETHNLVC_NAME, PhGetString(entry->HandleItem->BestObjectName)); - PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, ETHNLVC_ORIGNAME, PhGetString(entry->HandleItem->ObjectName)); + if (useWorkQueue && entry->HandleItem->TypeIndex == EtFileTypeIndex) + { + PhQueueItemWorkQueue(&workQueue, EtpUpdateHandleFunction, entry); + } + else + { + EtUpdateHandleItem(entry->ProcessId, entry->HandleItem); + } } else if (entry->HandleItem->TypeIndex == EtSectionTypeIndex) + { EtUpdateHandleItem(entry->ProcessId, entry->HandleItem); + } } PhDereferenceObject(searchResults); PhFree(handles); + if (useWorkQueue) + { + PhWaitForWorkQueue(&workQueue); + PhDeleteWorkQueue(&workQueue); + } + Context->TotalHandlesCount = ListView_GetItemCount(Context->ListViewHandle); Context->OwnHandlesCount = ownHandlesIndex; } + + if (PhEqualString2(Context->HandleItem->TypeName, L"Type", TRUE)) + PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESBYNAME_L, L"By type:"); + + PhPrintUInt32(string, Context->TotalHandlesCount); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL, string); + PhPrintUInt32(string, Context->OwnHandlesCount); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESBYOBJECT, string); + PhPrintUInt32(string, Context->TotalHandlesCount - Context->OwnHandlesCount); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESBYNAME, string); + + ExtendedListView_SetRedraw(Context->ListViewHandle, TRUE); + PhSetCursor(PhLoadCursor(NULL, IDC_ARROW)); } VOID EtUpdateHandleItem( @@ -1365,45 +1421,23 @@ VOID EtUpdateHandleItem( } VOID EtpShowHandleProperties( - _In_ HWND hwndDlg, + _In_ HWND WindowHandle, _In_ PHANDLE_ENTRY Entry ) { EtUpdateHandleItem(Entry->ProcessId, Entry->HandleItem); - PhShowHandlePropertiesEx(hwndDlg, Entry->ProcessId, Entry->HandleItem, (PPH_PLUGIN)((ULONG_PTR)PluginInstance | OBJECT_CHILD_HANDLEPROP_WINDOW), NULL); + PhShowHandlePropertiesEx(WindowHandle, Entry->ProcessId, Entry->HandleItem, (PPH_PLUGIN)((ULONG_PTR)PluginInstance | OBJECT_CHILD_HANDLEPROP_WINDOW), NULL); } -VOID EtpCloseObjectHandles( - _In_ PCOMMON_PAGE_CONTEXT Context, - _In_ PHANDLE_ENTRY* ListviewItems, - _In_ ULONG NumberOfItems +VOID EtpUpdateGeneralTab( + _In_ PCOMMON_PAGE_CONTEXT Context ) { WCHAR string[PH_INT64_STR_LEN_1]; - HWND generalPageList; HANDLE processHandle = NtCurrentProcess(); - BOOLEAN ownHandle; - - for (ULONG i = 0; i < NumberOfItems; i++) - { - if (PhUiCloseHandles(Context->WindowHandle, ListviewItems[i]->ProcessId, &ListviewItems[i]->HandleItem, 1, TRUE)) - { - ownHandle = !!ListviewItems[i]->OwnHandle; - PhRemoveListViewItem(Context->ListViewHandle, PhFindListViewItemByParam(Context->ListViewHandle, INT_ERROR, ListviewItems[i])); - PhClearReference(&ListviewItems[i]->HandleItem); - PhFree(ListviewItems[i]); - - PhPrintUInt32(string, --Context->TotalHandlesCount); - PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL, string); - - Context->OwnHandlesCount -= ownHandle; - PhPrintUInt32(string, ownHandle ? Context->OwnHandlesCount : Context->TotalHandlesCount - Context->OwnHandlesCount); - PhSetDialogItemText(Context->WindowHandle, ownHandle ? IDC_OBJ_HANDLESBYOBJECT : IDC_OBJ_HANDLESBYNAME, string); - } - } + HWND generalPageList; - // Update General page references and handles count if (generalPageList = FindWindowEx(PropSheet_IndexToHwnd(GetParent(Context->WindowHandle), 0), NULL, WC_LISTVIEW, NULL)) // HACK { if (Context->ProcessId == NtCurrentProcessId() || @@ -1438,6 +1472,37 @@ VOID EtpCloseObjectHandles( } } +VOID EtpCloseObjectHandles( + _In_ PCOMMON_PAGE_CONTEXT Context, + _In_ PHANDLE_ENTRY* ListviewItems, + _In_ ULONG NumberOfItems + ) +{ + WCHAR string[PH_INT64_STR_LEN_1]; + BOOLEAN ownHandle; + + for (ULONG i = 0; i < NumberOfItems; i++) + { + if (PhUiCloseHandles(Context->WindowHandle, ListviewItems[i]->ProcessId, &ListviewItems[i]->HandleItem, 1, TRUE)) + { + ownHandle = !!ListviewItems[i]->OwnHandle; + PhRemoveListViewItem(Context->ListViewHandle, PhFindListViewItemByParam(Context->ListViewHandle, INT_ERROR, ListviewItems[i])); + PhClearReference(&ListviewItems[i]->HandleItem); + PhFree(ListviewItems[i]); + + PhPrintUInt32(string, --Context->TotalHandlesCount); + PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL, string); + + Context->OwnHandlesCount -= ownHandle; + PhPrintUInt32(string, ownHandle ? Context->OwnHandlesCount : Context->TotalHandlesCount - Context->OwnHandlesCount); + PhSetDialogItemText(Context->WindowHandle, ownHandle ? IDC_OBJ_HANDLESBYOBJECT : IDC_OBJ_HANDLESBYNAME, string); + } + } + + // Update General page references and handles count + EtpUpdateGeneralTab(Context); +} + static COLORREF NTAPI EtpColorItemColorFunction( _In_ INT Index, _In_ PVOID Param, @@ -1465,7 +1530,7 @@ static NTSTATUS EtpProcessHandleOpenCallback( *Handle = NULL; - return EtDuplicateHandleFromProcessEx(Handle, DesiredAccess, context->ProcessId, context->HandleItem->Handle); + return EtDuplicateHandleFromProcessEx(Handle, DesiredAccess, context->ProcessId, NULL, context->HandleItem->Handle); } static NTSTATUS EtpProcessHandleCloseCallback( @@ -1480,6 +1545,27 @@ static NTSTATUS EtpProcessHandleCloseCallback( return STATUS_SUCCESS; } +VOID EtpHandlesFreeListViewItems( + PCOMMON_PAGE_CONTEXT Context + ) +{ + INT index = INT_ERROR; + + while ((index = PhFindListViewItemByFlags( + Context->ListViewHandle, + index, + LVNI_ALL + )) != INT_ERROR) + { + PHANDLE_ENTRY entry; + if (PhGetListViewItemParam(Context->ListViewHandle, index, &entry)) + { + PhClearReference(&entry->HandleItem); + PhFree(entry); + } + } +} + INT_PTR CALLBACK EtpObjHandlesPageDlgProc( _In_ HWND hwndDlg, @@ -1509,8 +1595,6 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( { case WM_INITDIALOG: { - WCHAR string[PH_INT64_STR_LEN_1]; - context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); @@ -1524,30 +1608,12 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( ExtendedListView_SetSort(context->ListViewHandle, 0, NoSortOrder); ExtendedListView_SetItemColorFunction(context->ListViewHandle, EtpColorItemColorFunction); - ExtendedListView_SetRedraw(context->ListViewHandle, FALSE); - PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - PhSetCursor(PhLoadCursor(NULL, IDC_WAIT)); - EtpEnumObjectHandles(context); - PhSetCursor(PhLoadCursor(NULL, IDC_ARROW)); - PhInitializeWindowTheme(hwndDlg, PhIsThemeSupportEnabled()); - - ExtendedListView_SetRedraw(context->ListViewHandle, TRUE); - - PhPrintUInt32(string, context->TotalHandlesCount); - PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESTOTAL), string); - PhPrintUInt32(string, context->OwnHandlesCount); - PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESBYOBJECT), string); - PhPrintUInt32(string, context->TotalHandlesCount - context->OwnHandlesCount); - PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESBYNAME), string); - - if (PhEqualString2(context->HandleItem->TypeName, L"Type", TRUE)) - PhSetDialogItemText(hwndDlg, IDC_OBJ_HANDLESBYNAME_L, L"By type:"); } break; case WM_SIZE: @@ -1558,21 +1624,7 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( break; case WM_DESTROY: { - INT index = INT_ERROR; - - while ((index = PhFindListViewItemByFlags( - context->ListViewHandle, - index, - LVNI_ALL - )) != INT_ERROR) - { - PHANDLE_ENTRY entry; - if (PhGetListViewItemParam(context->ListViewHandle, index, &entry)) - { - PhClearReference(&entry->HandleItem); - PhFree(entry); - } - } + EtpHandlesFreeListViewItems(context); } break; case WM_NCDESTROY: @@ -1625,6 +1677,9 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( } } break; + case VK_F5: + SendMessage(hwndDlg, WM_COMMAND, IDC_REFRESH, 0); + break; } } break; @@ -1636,11 +1691,9 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( LPNMHDR header = (LPNMHDR)lParam; - if (header->code == NM_DBLCLK) + if (header->code == NM_DBLCLK && + header->hwndFrom == context->ListViewHandle) { - if (header->hwndFrom != context->ListViewHandle) - break; - LPNMITEMACTIVATE info = (LPNMITEMACTIVATE)header; PHANDLE_ENTRY entry; @@ -1662,6 +1715,35 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( } } } + else if (header->code == LVN_GETDISPINFOA && // I don't know why prop sheet sends ANSI message while window is Unicode + header->hwndFrom == context->ListViewHandle) + { + NMLVDISPINFOA* dispInfo = (NMLVDISPINFOA*)header; + + if (header->hwndFrom == context->ListViewHandle && + FlagOn(dispInfo->item.mask, TVIF_TEXT)) + { + PHANDLE_ENTRY entry = (PHANDLE_ENTRY)dispInfo->item.lParam; + + switch (dispInfo->item.iSubItem) + { + case ETHNLVC_NAME: + if (entry->HandleItem->BestObjectName) + { + dispInfo->item.mask |= LVIF_DI_SETITEM; + dispInfo->item.pszText = PH_AUTO_T(PH_BYTES, PhConvertUtf16ToMultiByte(PhGetString(entry->HandleItem->BestObjectName)))->Buffer; + } + break; + case ETHNLVC_ORIGNAME: + if (entry->HandleItem->ObjectName) + { + dispInfo->item.mask |= LVIF_DI_SETITEM; + dispInfo->item.pszText = PH_AUTO_T(PH_BYTES, PhConvertUtf16ToMultiByte(PhGetString(entry->HandleItem->ObjectName)))->Buffer; + } + break; + } + } + } } break; case WM_CONTEXTMENU: @@ -1857,6 +1939,30 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc( } } break; + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + case IDC_REFRESH: + { + ULONG sortColumn; + PH_SORT_ORDER sortOrder; + + EtpHandlesFreeListViewItems(context); + ListView_DeleteAllItems(context->ListViewHandle); + PhSetDialogItemText(context->WindowHandle, IDC_OBJ_HANDLESTOTAL, L""); + PhSetDialogItemText(context->WindowHandle, IDC_OBJ_HANDLESBYOBJECT, L""); + PhSetDialogItemText(context->WindowHandle, IDC_OBJ_HANDLESBYNAME, L""); + + EtpEnumObjectHandles(context); + + ExtendedListView_GetSort(context->ListViewHandle, &sortColumn, &sortOrder); + if (sortOrder != NoSortOrder) + ExtendedListView_SortItems(context->ListViewHandle); + EtpUpdateGeneralTab(context); + } + break; + } + break; } return FALSE; @@ -1969,7 +2075,13 @@ VOID EtpOpenDesktopSecurity( OpenContext->DesktopName = PhReferenceObject(deskName); OpenContext->CurrentWinStation = GetProcessWindowStation(); - if (NT_SUCCESS(EtDuplicateHandleFromProcessEx((PHANDLE)&hWinStation, WINSTA_ENUMDESKTOPS, context->ProcessId, context->HandleItem->Handle))) + if (NT_SUCCESS(EtDuplicateHandleFromProcessEx( + (PHANDLE)&hWinStation, + WINSTA_ENUMDESKTOPS, + context->ProcessId, + NULL, + context->HandleItem->Handle + ))) { if (NtCompareObjects((HANDLE)OpenContext->CurrentWinStation, (HANDLE)hWinStation) == STATUS_NOT_SAME_OBJECT) OpenContext->DesktopWinStation = hWinStation; @@ -2030,7 +2142,13 @@ INT_PTR CALLBACK EtpWinStaPageDlgProc( ExtendedListView_SetRedraw(context->ListViewHandle, FALSE); - if (NT_SUCCESS(EtDuplicateHandleFromProcessEx((PHANDLE)&hWinStation, WINSTA_ENUMDESKTOPS, context->ProcessId, context->HandleItem->Handle))) + if (NT_SUCCESS(EtDuplicateHandleFromProcessEx( + (PHANDLE)&hWinStation, + WINSTA_ENUMDESKTOPS, + context->ProcessId, + NULL, + context->HandleItem->Handle + ))) { HWINSTA currentStation = GetProcessWindowStation(); NTSTATUS status = NtCompareObjects((HANDLE)currentStation, (HANDLE)hWinStation); @@ -2105,20 +2223,19 @@ INT_PTR CALLBACK EtpWinStaPageDlgProc( PPH_EMENU menu; PPH_EMENU_ITEM item; PPH_EMENU_ITEM secMenuItem; - HWND ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); if (point.x == -1 && point.y == -1) - PhGetListViewContextMenuPoint(ListViewHandle, &point); + PhGetListViewContextMenuPoint(context->ListViewHandle, &point); menu = PhCreateEMenu(); PhInsertEMenuItem(menu, secMenuItem = PhCreateEMenuItem(0, IDC_SECURITY, L"&Security\bEnter", NULL, NULL), ULONG_MAX); PhInsertEMenuItem(menu, PhCreateEMenuSeparator(), ULONG_MAX); PhInsertEMenuItem(menu, PhCreateEMenuItem(0, IDC_COPY, L"&Copy\bCtrl+C", NULL, NULL), ULONG_MAX); - PhInsertCopyListViewEMenuItem(menu, IDC_COPY, ListViewHandle); + PhInsertCopyListViewEMenuItem(menu, IDC_COPY, context->ListViewHandle); PhSetFlagsEMenuItem(menu, IDC_SECURITY, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT); if (numberOfItems > 1) PhSetDisabledEMenuItem(secMenuItem); @@ -2137,7 +2254,7 @@ INT_PTR CALLBACK EtpWinStaPageDlgProc( switch (item->Id) { case IDC_COPY: - PhCopyListView(ListViewHandle); + PhCopyListView(context->ListViewHandle); break; case IDC_SECURITY: EtpOpenDesktopSecurity(context, listviewItems[0]);