NTSTATUS PhpGetObjectName( __in HANDLE ProcessHandle, __in HANDLE Handle, __out PPH_STRING *ObjectName ) { NTSTATUS status; POBJECT_NAME_INFORMATION buffer; ULONG bufferSize; ULONG attempts = 8; bufferSize = 0x200; buffer = PhAllocate(bufferSize); // A loop is needed because the I/O subsystem likes to give us the wrong return lengths... do { if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectNameInformation, buffer, bufferSize, &bufferSize ); } else { status = NtQueryObject( Handle, ObjectNameInformation, buffer, bufferSize, &bufferSize ); } if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_BUFFER_TOO_SMALL) { PhFree(buffer); buffer = PhAllocate(bufferSize); } else { break; } } while (--attempts); if (NT_SUCCESS(status)) { *ObjectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length); } PhFree(buffer); return status; }
VOID PhShowHiddenProcessesDialog( VOID ) { if (!KphIsConnected()) { PhShowWarning( PhMainWndHandle, L"Hidden process detection cannot function properly without KProcessHacker. " L"Make sure Process Hacker is running with administrative privileges." ); } if (!PhHiddenProcessesWindowHandle) { PhHiddenProcessesWindowHandle = CreateDialog( PhInstanceHandle, MAKEINTRESOURCE(IDD_HIDDENPROCESSES), PhMainWndHandle, PhpHiddenProcessesDlgProc ); } if (!IsWindowVisible(PhHiddenProcessesWindowHandle)) ShowWindow(PhHiddenProcessesWindowHandle, SW_SHOW); else SetForegroundWindow(PhHiddenProcessesWindowHandle); }
static NTSTATUS NTAPI TerminatorTTGeneric( _In_ HANDLE ProcessId, _In_ BOOLEAN UseKph, _In_ BOOLEAN UseKphDangerous ) { NTSTATUS status; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; ULONG i; if ((UseKph || UseKphDangerous) && !KphIsConnected()) return STATUS_NOT_SUPPORTED; if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) return status; process = PhFindProcessInformation(processes, ProcessId); if (!process) { PhFree(processes); return STATUS_INVALID_CID; } for (i = 0; i < process->NumberOfThreads; i++) { HANDLE threadHandle; if (NT_SUCCESS(PhOpenThread( &threadHandle, THREAD_TERMINATE, process->Threads[i].ClientId.UniqueThread ))) { if (UseKphDangerous) KphTerminateThreadUnsafe(threadHandle, STATUS_SUCCESS); else if (UseKph) KphTerminateThread(threadHandle, STATUS_SUCCESS); else NtTerminateThread(threadHandle, STATUS_SUCCESS); NtClose(threadHandle); } } PhFree(processes); return STATUS_SUCCESS; }
NTSTATUS PhpGetObjectBasicInformation( __in HANDLE ProcessHandle, __in HANDLE Handle, __out POBJECT_BASIC_INFORMATION BasicInformation ) { NTSTATUS status; if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectBasicInformation, BasicInformation, sizeof(OBJECT_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { // The object was referenced in KProcessHacker, so // we need to subtract 1 from the pointer count. BasicInformation->PointerCount -= 1; } } else { status = NtQueryObject( Handle, ObjectBasicInformation, BasicInformation, sizeof(OBJECT_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { // The object was referenced in NtQueryObject and // a handle was opened to the object. We need to // subtract 1 from the pointer count, then subtract // 1 from both counts. BasicInformation->HandleCount -= 1; BasicInformation->PointerCount -= 2; } } return status; }
static NTSTATUS PhpDuplicateHandleFromProcess( _Out_ PHANDLE Handle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ PVOID Context ) { NTSTATUS status; PHANDLE_PROPERTIES_CONTEXT context = Context; HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, context->ProcessId ))) return status; if (KphIsConnected() && PhEqualString2(context->HandleItem->TypeName, L"File", TRUE)) { status = PhCallKphDuplicateObjectWithTimeout( processHandle, context->HandleItem->Handle, NtCurrentProcess(), Handle, DesiredAccess, 0, 0 ); } else { status = PhDuplicateObject( processHandle, context->HandleItem->Handle, NtCurrentProcess(), Handle, DesiredAccess, 0, 0 ); } NtClose(processHandle); return status; }
static NTSTATUS NTAPI TerminatorTP3( _In_ HANDLE ProcessId ) { NTSTATUS status; HANDLE processHandle; if (!KphIsConnected()) return STATUS_NOT_SUPPORTED; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, SYNCHRONIZE, // KPH doesn't require any access for this operation ProcessId ))) { status = KphTerminateProcess(processHandle, STATUS_SUCCESS); NtClose(processHandle); } return status; }
VOID PhSipInitializeMemoryDialog( VOID ) { PhInitializeDelta(&PagedAllocsDelta); PhInitializeDelta(&PagedFreesDelta); PhInitializeDelta(&NonPagedAllocsDelta); PhInitializeDelta(&NonPagedFreesDelta); PhInitializeDelta(&PageFaultsDelta); PhInitializeDelta(&PageReadsDelta); PhInitializeDelta(&PagefileWritesDelta); PhInitializeDelta(&MappedWritesDelta); PhInitializeGraphState(&CommitGraphState); PhInitializeGraphState(&PhysicalGraphState); MemoryTicked = 0; if (!MmAddressesInitialized && KphIsConnected()) { PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), PhSipLoadMmAddresses, NULL); MmAddressesInitialized = TRUE; } }
static NTSTATUS PhpFindObjectsThreadStart( _In_ PVOID Parameter ) { NTSTATUS status = STATUS_SUCCESS; PSYSTEM_HANDLE_INFORMATION_EX handles; PPH_HASHTABLE processHandleHashtable; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; ULONG i; // Refuse to search with no filter. if (SearchString->Length == 0) goto Exit; // Try to get a search pointer from the search string. UseSearchPointer = PhStringToInteger64(&SearchString->sr, 0, &SearchPointer); _wcsupr(SearchString->Buffer); if (NT_SUCCESS(status = PhEnumHandlesEx(&handles))) { static PH_INITONCE initOnce = PH_INITONCE_INIT; static ULONG fileObjectTypeIndex = -1; BOOLEAN useWorkQueue = FALSE; PH_WORK_QUEUE workQueue; processHandleHashtable = PhCreateSimpleHashtable(8); if (!KphIsConnected() && WindowsVersion >= WINDOWS_VISTA) { useWorkQueue = TRUE; PhInitializeWorkQueue(&workQueue, 1, 20, 1000); if (PhBeginInitOnce(&initOnce)) { UNICODE_STRING fileTypeName; RtlInitUnicodeString(&fileTypeName, L"File"); fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName); PhEndInitOnce(&initOnce); } } for (i = 0; i < handles->NumberOfHandles; i++) { PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = &handles->Handles[i]; PVOID *processHandlePtr; HANDLE processHandle; if (SearchStop) break; // Open a handle to the process if we don't already have one. processHandlePtr = PhFindItemSimpleHashtable( processHandleHashtable, (PVOID)handleInfo->UniqueProcessId ); if (processHandlePtr) { processHandle = (HANDLE)*processHandlePtr; } else { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, (HANDLE)handleInfo->UniqueProcessId ))) { PhAddItemSimpleHashtable( processHandleHashtable, (PVOID)handleInfo->UniqueProcessId, processHandle ); } else { continue; } } if (useWorkQueue && handleInfo->ObjectTypeIndex == (USHORT)fileObjectTypeIndex) { PSEARCH_HANDLE_CONTEXT searchHandleContext; searchHandleContext = PhAllocate(sizeof(SEARCH_HANDLE_CONTEXT)); searchHandleContext->NeedToFree = TRUE; searchHandleContext->HandleInfo = handleInfo; searchHandleContext->ProcessHandle = processHandle; PhQueueItemWorkQueue(&workQueue, SearchHandleFunction, searchHandleContext); } else { SEARCH_HANDLE_CONTEXT searchHandleContext; searchHandleContext.NeedToFree = FALSE; searchHandleContext.HandleInfo = handleInfo; searchHandleContext.ProcessHandle = processHandle; SearchHandleFunction(&searchHandleContext); } } if (useWorkQueue) { PhWaitForWorkQueue(&workQueue); PhDeleteWorkQueue(&workQueue); } { PPH_KEY_VALUE_PAIR entry; i = 0; while (PhEnumHashtable(processHandleHashtable, &entry, &i)) NtClose((HANDLE)entry->Value); } PhDereferenceObject(processHandleHashtable); PhFree(handles); } if (NT_SUCCESS(PhEnumProcesses(&processes))) { process = PH_FIRST_PROCESS(processes); do { PhEnumGenericModules( process->UniqueProcessId, NULL, PH_ENUM_GENERIC_MAPPED_FILES | PH_ENUM_GENERIC_MAPPED_IMAGES, EnumModulesCallback, (PVOID)process->UniqueProcessId ); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); } Exit: PostMessage(PhFindObjectsWindowHandle, WM_PH_SEARCH_FINISHED, status, 0); return STATUS_SUCCESS; }
VOID PhShowThreadStackDialog( _In_ HWND ParentWindowHandle, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ PPH_SYMBOL_PROVIDER SymbolProvider ) { NTSTATUS status; THREAD_STACK_CONTEXT threadStackContext; HANDLE threadHandle = NULL; // If the user is trying to view a system thread stack // but KProcessHacker is not loaded, show an error message. if (ProcessId == SYSTEM_PROCESS_ID && !KphIsConnected()) { PhShowError(ParentWindowHandle, KPH_ERROR_MESSAGE); return; } memset(&threadStackContext, 0, sizeof(THREAD_STACK_CONTEXT)); threadStackContext.ProcessId = ProcessId; threadStackContext.ThreadId = ThreadId; threadStackContext.SymbolProvider = SymbolProvider; if (!NT_SUCCESS(status = PhOpenThread( &threadHandle, THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, ThreadId ))) { if (KphIsConnected()) { status = PhOpenThread( &threadHandle, ThreadQueryAccess, ThreadId ); } } if (!NT_SUCCESS(status)) { PhShowStatus(ParentWindowHandle, L"Unable to open the thread", status, 0); return; } threadStackContext.ThreadHandle = threadHandle; threadStackContext.List = PhCreateList(10); threadStackContext.NewList = PhCreateList(10); PhInitializeQueuedLock(&threadStackContext.StatusLock); DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_THRDSTACK), ParentWindowHandle, PhpThreadStackDlgProc, (LPARAM)&threadStackContext ); PhSwapReference(&threadStackContext.StatusMessage, NULL); PhDereferenceObject(threadStackContext.NewList); PhDereferenceObject(threadStackContext.List); if (threadStackContext.ThreadHandle) NtClose(threadStackContext.ThreadHandle); }
VOID PhpThreadProviderUpdate( __in PPH_THREAD_PROVIDER ThreadProvider, __in PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = (HANDLE)i; } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PPVOID)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhSwapReference2(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { ULONG64 cycles; PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhSwapReference2( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if ( threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress ) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }
VOID PhSipUpdateMemoryPanel( VOID ) { PWSTR pagedLimit; PWSTR nonPagedLimit; SYSTEM_MEMORY_LIST_INFORMATION memoryListInfo; // Commit charge SetDlgItemText(MemoryPanel, IDC_ZCOMMITCURRENT_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.CommittedPages, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZCOMMITPEAK_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.PeakCommitment, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZCOMMITLIMIT_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.CommitLimit, PAGE_SIZE), -1)->Buffer); // Physical memory SetDlgItemText(MemoryPanel, IDC_ZPHYSICALCURRENT_V, PhaFormatSize(UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages - PhPerfInformation.AvailablePages, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZPHYSICALTOTAL_V, PhaFormatSize(UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages, PAGE_SIZE), -1)->Buffer); if (InstalledMemory != 0) { SetDlgItemText(MemoryPanel, IDC_ZPHYSICALRESERVED_V, PhaFormatSize(InstalledMemory * 1024 - UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages, PAGE_SIZE), -1)->Buffer); } else { SetDlgItemText(MemoryPanel, IDC_ZPHYSICALRESERVED_V, L"-"); } SetDlgItemText(MemoryPanel, IDC_ZPHYSICALCACHEWS_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemCachePage, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZPHYSICALKERNELWS_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemCodePage, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZPHYSICALDRIVERWS_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemDriverPage, PAGE_SIZE), -1)->Buffer); // Paged pool SetDlgItemText(MemoryPanel, IDC_ZPAGEDWORKINGSET_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentPagedPoolPage, PAGE_SIZE), -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZPAGEDVIRTUALSIZE_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.PagedPoolPages, PAGE_SIZE), -1)->Buffer); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGEDALLOCSDELTA_V, PhaFormatUInt64(PagedAllocsDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGEDALLOCSDELTA_V, L"-"); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGEDFREESDELTA_V, PhaFormatUInt64(PagedFreesDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGEDFREESDELTA_V, L"-"); // Non-paged pool SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDUSAGE_V, PhaFormatSize(UInt32x32To64(PhPerfInformation.NonPagedPoolPages, PAGE_SIZE), -1)->Buffer); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDALLOCSDELTA_V, PhaFormatUInt64(PagedAllocsDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDALLOCSDELTA_V, L"-"); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDFREESDELTA_V, PhaFormatUInt64(NonPagedFreesDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDFREESDELTA_V, L"-"); // Pools (KPH) if (MmAddressesInitialized && (MmSizeOfPagedPoolInBytes || MmMaximumNonPagedPoolInBytes)) { SIZE_T paged; SIZE_T nonPaged; PhSipGetPoolLimits(&paged, &nonPaged); if (paged != -1) pagedLimit = PhaFormatSize(paged, -1)->Buffer; else pagedLimit = L"N/A"; if (nonPaged != -1) nonPagedLimit = PhaFormatSize(nonPaged, -1)->Buffer; else nonPagedLimit = L"N/A"; } else { if (!KphIsConnected()) { pagedLimit = nonPagedLimit = L"no driver"; } else { pagedLimit = nonPagedLimit = L"no symbols"; } } SetDlgItemText(MemoryPanel, IDC_ZPAGEDLIMIT_V, pagedLimit); SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDLIMIT_V, nonPagedLimit); // Paging if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFAULTSDELTA_V, PhaFormatUInt64(PageFaultsDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFAULTSDELTA_V, L"-"); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEREADSDELTA_V, PhaFormatUInt64(PageReadsDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEREADSDELTA_V, L"-"); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFILEWRITESDELTA_V, PhaFormatUInt64(PagefileWritesDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFILEWRITESDELTA_V, L"-"); if (MemoryTicked > 1) SetDlgItemText(MemoryPanel, IDC_ZPAGINGMAPPEDWRITESDELTA_V, PhaFormatUInt64(MappedWritesDelta.Delta, TRUE)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZPAGINGMAPPEDWRITESDELTA_V, L"-"); // Memory lists if (NT_SUCCESS(NtQuerySystemInformation( SystemMemoryListInformation, &memoryListInfo, sizeof(SYSTEM_MEMORY_LIST_INFORMATION), NULL ))) { ULONG_PTR standbyPageCount; ULONG_PTR repurposedPageCount; ULONG i; standbyPageCount = 0; repurposedPageCount = 0; for (i = 0; i < 8; i++) { standbyPageCount += memoryListInfo.PageCountByPriority[i]; repurposedPageCount += memoryListInfo.RepurposedPagesByPriority[i]; } SetDlgItemText(MemoryPanel, IDC_ZLISTZEROED_V, PhaFormatSize((ULONG64)memoryListInfo.ZeroPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTFREE_V, PhaFormatSize((ULONG64)memoryListInfo.FreePageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIED_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDNOWRITE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedNoWritePageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY_V, PhaFormatSize((ULONG64)standbyPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY0_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[0] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY1_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[1] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY2_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[2] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY3_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[3] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY4_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[4] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY5_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[5] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY6_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[6] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY7_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[7] * PAGE_SIZE, -1)->Buffer); if (WindowsVersion >= WINDOWS_8) SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCountPageFile * PAGE_SIZE, -1)->Buffer); else SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A"); } else { SetDlgItemText(MemoryPanel, IDC_ZLISTZEROED_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTFREE_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIED_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDNOWRITE_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY0_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY1_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY2_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY3_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY4_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY5_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY6_V, L"N/A"); SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY7_V, L"N/A"); } }
NTSTATUS PhpGetBestObjectName( __in HANDLE ProcessHandle, __in HANDLE Handle, __in PPH_STRING ObjectName, __in PPH_STRING TypeName, __out PPH_STRING *BestObjectName ) { NTSTATUS status; PPH_STRING bestObjectName = NULL; PPH_GET_CLIENT_ID_NAME handleGetClientIdName; if (PhEqualString2(TypeName, L"EtwRegistration", TRUE)) { if (KphIsConnected()) { ETWREG_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectEtwRegBasicInformation, &basicInfo, sizeof(ETWREG_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { static PH_STRINGREF publishersKeyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\"); PPH_STRING guidString; PPH_STRING keyName; HANDLE keyHandle; PPH_STRING publisherName = NULL; guidString = PhFormatGuid(&basicInfo.Guid); // We should perform a lookup on the GUID to get the publisher name. keyName = PhConcatStringRef2(&publishersKeyName, &guidString->sr); if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { publisherName = PhQueryRegistryString(keyHandle, NULL); if (publisherName && publisherName->Length == 0) { PhDereferenceObject(publisherName); publisherName = NULL; } NtClose(keyHandle); } PhDereferenceObject(keyName); if (publisherName) { bestObjectName = publisherName; PhDereferenceObject(guidString); } else { bestObjectName = guidString; } } } } else if (PhEqualString2(TypeName, L"File", TRUE)) { // Convert the file name to a DOS file name. bestObjectName = PhResolveDevicePrefix(ObjectName); if (!bestObjectName) { bestObjectName = ObjectName; PhReferenceObject(ObjectName); } } else if (PhEqualString2(TypeName, L"Key", TRUE)) { bestObjectName = PhFormatNativeKeyName(ObjectName); } else if (PhEqualString2(TypeName, L"Process", TRUE)) { CLIENT_ID clientId; clientId.UniqueThread = NULL; if (KphIsConnected()) { PROCESS_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectProcessBasicInformation, &basicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(status)) goto CleanupExit; clientId.UniqueProcess = basicInfo.UniqueProcessId; } else { HANDLE dupHandle; PROCESS_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ProcessQueryAccess, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetProcessBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (!NT_SUCCESS(status)) goto CleanupExit; clientId.UniqueProcess = basicInfo.UniqueProcessId; } handleGetClientIdName = PhHandleGetClientIdName; if (handleGetClientIdName) bestObjectName = handleGetClientIdName(&clientId); } else if (PhEqualString2(TypeName, L"Thread", TRUE)) { CLIENT_ID clientId; if (KphIsConnected()) { THREAD_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectThreadBasicInformation, &basicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(status)) goto CleanupExit; clientId = basicInfo.ClientId; } else { HANDLE dupHandle; THREAD_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ThreadQueryAccess, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetThreadBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (!NT_SUCCESS(status)) goto CleanupExit; clientId = basicInfo.ClientId; } handleGetClientIdName = PhHandleGetClientIdName; if (handleGetClientIdName) bestObjectName = handleGetClientIdName(&clientId); } else if (PhEqualString2(TypeName, L"TmEn", TRUE)) { HANDLE dupHandle; ENLISTMENT_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ENLISTMENT_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetEnlistmentBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.EnlistmentId); } } else if (PhEqualString2(TypeName, L"TmRm", TRUE)) { HANDLE dupHandle; GUID guid; PPH_STRING description; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, RESOURCEMANAGER_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetResourceManagerBasicInformation( dupHandle, &guid, &description ); NtClose(dupHandle); if (NT_SUCCESS(status)) { if (!PhIsNullOrEmptyString(description)) { bestObjectName = description; } else { bestObjectName = PhFormatGuid(&guid); if (description) PhDereferenceObject(description); } } } else if (PhEqualString2(TypeName, L"TmTm", TRUE)) { HANDLE dupHandle; PPH_STRING logFileName = NULL; TRANSACTIONMANAGER_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TRANSACTIONMANAGER_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTransactionManagerLogFileName( dupHandle, &logFileName ); if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(logFileName)) { bestObjectName = PhGetFileName(logFileName); PhDereferenceObject(logFileName); } else { if (logFileName) PhDereferenceObject(logFileName); status = PhGetTransactionManagerBasicInformation( dupHandle, &basicInfo ); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.TmIdentity); } } NtClose(dupHandle); } else if (PhEqualString2(TypeName, L"TmTx", TRUE)) { HANDLE dupHandle; PPH_STRING description = NULL; TRANSACTION_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TRANSACTION_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTransactionPropertiesInformation( dupHandle, NULL, NULL, &description ); if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(description)) { bestObjectName = description; } else { if (description) PhDereferenceObject(description); status = PhGetTransactionBasicInformation( dupHandle, &basicInfo ); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.TransactionId); } } NtClose(dupHandle); } else if (PhEqualString2(TypeName, L"Token", TRUE)) { HANDLE dupHandle; PTOKEN_USER tokenUser = NULL; TOKEN_STATISTICS statistics = { 0 }; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TOKEN_QUERY, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTokenUser(dupHandle, &tokenUser); PhGetTokenStatistics(dupHandle, &statistics); if (NT_SUCCESS(status)) { PPH_STRING fullName; fullName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL); if (fullName) { PH_FORMAT format[3]; PhInitFormatSR(&format[0], fullName->sr); PhInitFormatS(&format[1], L": 0x"); PhInitFormatX(&format[2], statistics.AuthenticationId.LowPart); bestObjectName = PhFormat(format, 3, fullName->Length + 8 + 16); PhDereferenceObject(fullName); } PhFree(tokenUser); } NtClose(dupHandle); } CleanupExit: if (!bestObjectName) { bestObjectName = ObjectName; PhReferenceObject(ObjectName); } *BestObjectName = bestObjectName; return STATUS_SUCCESS; }
NTSTATUS PhpGetObjectTypeName( __in HANDLE ProcessHandle, __in HANDLE Handle, __in ULONG ObjectTypeNumber, __out PPH_STRING *TypeName ) { NTSTATUS status = STATUS_SUCCESS; PPH_STRING typeName = NULL; // If the cache contains the object type name, use it. Otherwise, // query the type name. if (ObjectTypeNumber != -1 && ObjectTypeNumber < MAX_OBJECT_TYPE_NUMBER) typeName = PhObjectTypeNames[ObjectTypeNumber]; if (typeName) { PhReferenceObject(typeName); } else { POBJECT_TYPE_INFORMATION buffer; ULONG returnLength = 0; PPH_STRING oldTypeName; // Get the needed buffer size. if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectTypeInformation, NULL, 0, &returnLength ); } else { status = NtQueryObject( Handle, ObjectTypeInformation, NULL, 0, &returnLength ); } if (returnLength == 0) return status; buffer = PhAllocate(returnLength); if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectTypeInformation, buffer, returnLength, &returnLength ); } else { status = NtQueryObject( Handle, ObjectTypeInformation, buffer, returnLength, &returnLength ); } if (!NT_SUCCESS(status)) { PhFree(buffer); return status; } // Create a copy of the type name. typeName = PhCreateStringEx(buffer->TypeName.Buffer, buffer->TypeName.Length); if (ObjectTypeNumber != -1 && ObjectTypeNumber < MAX_OBJECT_TYPE_NUMBER) { // Try to store the type name in the cache. oldTypeName = _InterlockedCompareExchangePointer( &PhObjectTypeNames[ObjectTypeNumber], typeName, NULL ); // Add a reference if we stored the type name // successfully. if (!oldTypeName) PhReferenceObject(typeName); } PhFree(buffer); } // At this point typeName should contain a type name // with one additional reference. *TypeName = typeName; return status; }
/** * Gets information for a handle. * * \param ProcessHandle A handle to the process in which the * handle resides. * \param Handle The handle value. * \param ObjectTypeNumber The object type number of the handle. * You can specify -1 for this parameter if the object type number * is not known. * \param Flags Reserved. * \param SubStatus A variable which receives the NTSTATUS value of * the last component that fails. If all operations succeed, the * value will be STATUS_SUCCESS. If the function returns an error * status, this variable is not set. * \param BasicInformation A variable which receives basic * information about the object. * \param TypeName A variable which receives the object type name. * \param ObjectName A variable which receives the object name. * \param BestObjectName A variable which receives the formatted * object name. * \param ExtraInformation Reserved. * * \retval STATUS_INVALID_HANDLE The handle specified in * \c ProcessHandle or \c Handle is invalid. * \retval STATUS_INVALID_PARAMETER_3 The value specified in * \c ObjectTypeNumber is invalid. * * \remarks If \a BasicInformation or \a TypeName are specified, * the function will fail if either cannot be queried. \a ObjectName, * \a BestObjectName and \a ExtraInformation will return NULL if they * cannot be queried. */ NTSTATUS PhGetHandleInformationEx( __in HANDLE ProcessHandle, __in HANDLE Handle, __in ULONG ObjectTypeNumber, __reserved ULONG Flags, __out_opt PNTSTATUS SubStatus, __out_opt POBJECT_BASIC_INFORMATION BasicInformation, __out_opt PPH_STRING *TypeName, __out_opt PPH_STRING *ObjectName, __out_opt PPH_STRING *BestObjectName, __reserved PVOID *ExtraInformation ) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS subStatus = STATUS_SUCCESS; HANDLE dupHandle = NULL; PPH_STRING typeName = NULL; PPH_STRING objectName = NULL; PPH_STRING bestObjectName = NULL; if (Handle == NULL || Handle == NtCurrentProcess() || Handle == NtCurrentThread()) return STATUS_INVALID_HANDLE; if (ObjectTypeNumber != -1 && ObjectTypeNumber >= MAX_OBJECT_TYPE_NUMBER) return STATUS_INVALID_PARAMETER_3; // Duplicate the handle if we're not using KPH. if (!KphIsConnected()) { // However, we obviously don't need to duplicate it // if the handle is in the current process. if (ProcessHandle != NtCurrentProcess()) { status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, 0, 0, 0 ); if (!NT_SUCCESS(status)) return status; } else { dupHandle = Handle; } } // Get basic information. if (BasicInformation) { status = PhpGetObjectBasicInformation( ProcessHandle, KphIsConnected() ? Handle : dupHandle, BasicInformation ); if (!NT_SUCCESS(status)) goto CleanupExit; } // Exit early if we don't need to get any other information. if (!TypeName && !ObjectName && !BestObjectName) goto CleanupExit; // Get the type name. status = PhpGetObjectTypeName( ProcessHandle, KphIsConnected() ? Handle : dupHandle, ObjectTypeNumber, &typeName ); if (!NT_SUCCESS(status)) goto CleanupExit; // Exit early if we don't need to get the object name. if (!ObjectName && !BestObjectName) goto CleanupExit; // Get the object name. // If we're dealing with a file handle we must take // special precautions so we don't hang. if (PhEqualString2(typeName, L"File", TRUE) && !KphIsConnected()) { // 0: Query normally. // 1: Hack. // 2: Fail. ULONG hackLevel = 1; // We can't use the hack on XP because hanging threads // can't even be terminated! if (WindowsVersion <= WINDOWS_XP) hackLevel = 2; if (hackLevel == 0) { status = PhpGetObjectName( ProcessHandle, KphIsConnected() ? Handle : dupHandle, &objectName ); } else if (hackLevel == 1) { POBJECT_NAME_INFORMATION buffer; buffer = PhAllocate(0x800); status = PhQueryObjectNameHack( dupHandle, buffer, 0x800, NULL ); if (NT_SUCCESS(status)) objectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length); PhFree(buffer); } else { // Pretend the file object has no name. objectName = PhReferenceEmptyString(); status = STATUS_SUCCESS; } } else { // Query the object normally. status = PhpGetObjectName( ProcessHandle, KphIsConnected() ? Handle : dupHandle, &objectName ); } if (!NT_SUCCESS(status)) { subStatus = status; status = STATUS_SUCCESS; goto CleanupExit; } // Exit early if we don't need to get the best object name. if (!BestObjectName) goto CleanupExit; status = PhpGetBestObjectName( ProcessHandle, Handle, objectName, typeName, &bestObjectName ); if (!NT_SUCCESS(status)) { subStatus = status; status = STATUS_SUCCESS; goto CleanupExit; } CleanupExit: if (NT_SUCCESS(status)) { if (SubStatus) { *SubStatus = subStatus; } if (TypeName && typeName) { *TypeName = typeName; PhReferenceObject(typeName); } if (ObjectName && objectName) { *ObjectName = objectName; PhReferenceObject(objectName); } if (BestObjectName && bestObjectName) { *BestObjectName = bestObjectName; PhReferenceObject(bestObjectName); } } if (dupHandle && ProcessHandle != NtCurrentProcess()) NtClose(dupHandle); if (typeName) PhDereferenceObject(typeName); if (objectName) PhDereferenceObject(objectName); if (bestObjectName) PhDereferenceObject(bestObjectName); return status; }
VOID PhShowHandleObjectProperties1( _In_ HWND hWnd, _In_ PPH_HANDLE_ITEM_INFO Info ) { if (PhIsNullOrEmptyString(Info->TypeName)) return; if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) || PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE)) { if (Info->BestObjectName) { PhShellExecuteUserString( PhMainWndHandle, L"FileBrowseExecutable", Info->BestObjectName->Buffer, FALSE, L"Make sure the Explorer executable file is present." ); } else PhShowError(hWnd, L"Unable to open file location because the object is unnamed."); } else if (PhEqualString2(Info->TypeName, L"Key", TRUE)) { if (Info->BestObjectName) PhShellOpenKey2(hWnd, Info->BestObjectName); else PhShowError(hWnd, L"Unable to open key because the object is unnamed."); } else if (PhEqualString2(Info->TypeName, L"Process", TRUE)) { HANDLE processHandle; HANDLE processId; PPH_PROCESS_ITEM targetProcessItem; processId = NULL; if (KphIsConnected()) { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId ))) { PROCESS_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(KphQueryInformationObject( processHandle, Info->Handle, KphObjectProcessBasicInformation, &basicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL ))) { processId = basicInfo.UniqueProcessId; } NtClose(processHandle); } } else { HANDLE handle; PROCESS_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem( &handle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId, Info->Handle ))) { if (NT_SUCCESS(PhGetProcessBasicInformation(handle, &basicInfo))) processId = basicInfo.UniqueProcessId; NtClose(handle); } } if (processId) { targetProcessItem = PhReferenceProcessItem(processId); if (targetProcessItem) { ProcessHacker_ShowProcessProperties(PhMainWndHandle, targetProcessItem); PhDereferenceObject(targetProcessItem); } else { PhShowError(hWnd, L"The process does not exist."); } } } else if (PhEqualString2(Info->TypeName, L"Section", TRUE)) { NTSTATUS status; HANDLE handle = NULL; BOOLEAN readOnly = FALSE; if (!NT_SUCCESS(status = PhpDuplicateHandleFromProcessItem( &handle, SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE, Info->ProcessId, Info->Handle ))) { status = PhpDuplicateHandleFromProcessItem( &handle, SECTION_QUERY | SECTION_MAP_READ, Info->ProcessId, Info->Handle ); readOnly = TRUE; } if (handle) { PPH_STRING sectionName = NULL; SECTION_BASIC_INFORMATION basicInfo; SIZE_T viewSize = PH_MAX_SECTION_EDIT_SIZE; PVOID viewBase = NULL; BOOLEAN tooBig = FALSE; PhGetHandleInformation(NtCurrentProcess(), handle, ULONG_MAX, NULL, NULL, NULL, §ionName); if (NT_SUCCESS(status = PhGetSectionBasicInformation(handle, &basicInfo))) { if (basicInfo.MaximumSize.QuadPart <= PH_MAX_SECTION_EDIT_SIZE) viewSize = (SIZE_T)basicInfo.MaximumSize.QuadPart; else tooBig = TRUE; status = NtMapViewOfSection( handle, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, readOnly ? PAGE_READONLY : PAGE_READWRITE ); if (status == STATUS_SECTION_PROTECTION && !readOnly) { status = NtMapViewOfSection( handle, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, PAGE_READONLY ); } if (NT_SUCCESS(status)) { PPH_SHOW_MEMORY_EDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOW_MEMORY_EDITOR)); if (tooBig) PhShowWarning(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available for editing."); memset(showMemoryEditor, 0, sizeof(PH_SHOW_MEMORY_EDITOR)); showMemoryEditor->ProcessId = NtCurrentProcessId(); showMemoryEditor->BaseAddress = viewBase; showMemoryEditor->RegionSize = viewSize; showMemoryEditor->SelectOffset = ULONG_MAX; showMemoryEditor->SelectLength = 0; showMemoryEditor->Title = sectionName ? PhConcatStrings2(L"Section - ", sectionName->Buffer) : PhCreateString(L"Section"); showMemoryEditor->Flags = PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } else { PhShowStatus(hWnd, L"Unable to map a view of the section.", status, 0); } } PhClearReference(§ionName); NtClose(handle); } if (!NT_SUCCESS(status)) { PhShowStatus(hWnd, L"Unable to query the section.", status, 0); } } else if (PhEqualString2(Info->TypeName, L"Thread", TRUE)) { HANDLE processHandle; CLIENT_ID clientId; PPH_PROCESS_ITEM targetProcessItem; PPH_PROCESS_PROPCONTEXT propContext; clientId.UniqueProcess = NULL; clientId.UniqueThread = NULL; if (KphIsConnected()) { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId ))) { THREAD_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(KphQueryInformationObject( processHandle, Info->Handle, KphObjectThreadBasicInformation, &basicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL ))) { clientId = basicInfo.ClientId; } NtClose(processHandle); } } else { HANDLE handle; THREAD_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem( &handle, THREAD_QUERY_LIMITED_INFORMATION, Info->ProcessId, Info->Handle ))) { if (NT_SUCCESS(PhGetThreadBasicInformation(handle, &basicInfo))) clientId = basicInfo.ClientId; NtClose(handle); } } if (clientId.UniqueProcess) { targetProcessItem = PhReferenceProcessItem(clientId.UniqueProcess); if (targetProcessItem) { propContext = PhCreateProcessPropContext(NULL, targetProcessItem); PhDereferenceObject(targetProcessItem); PhSetSelectThreadIdProcessPropContext(propContext, clientId.UniqueThread); ProcessHacker_Invoke(PhMainWndHandle, PhpShowProcessPropContext, propContext); } else { PhShowError(hWnd, L"The process does not exist."); } } } }