VOID DotNetAsmShowContextMenu( _In_ PASMPAGE_CONTEXT Context, _In_ POINT Location ) { PDNA_NODE node; PPH_EMENU menu; PPH_EMENU_ITEM selectedItem; if (!(node = DotNetAsmGetSelectedEntry(Context))) return; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PluginInstance->DllBase, MAKEINTRESOURCE(IDR_ASSEMBLY_MENU), 0); if (PhIsNullOrEmptyString(node->PathText) || !RtlDoesFileExists_U(node->PathText->Buffer)) { PhSetFlagsEMenuItem(menu, ID_CLR_OPENFILELOCATION, PH_EMENU_DISABLED, PH_EMENU_DISABLED); } selectedItem = PhShowEMenu( menu, Context->WindowHandle, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, Location.x, Location.y ); if (selectedItem && selectedItem->Id != -1) { switch (selectedItem->Id) { case ID_CLR_OPENFILELOCATION: { if (!PhIsNullOrEmptyString(node->PathText) && RtlDoesFileExists_U(node->PathText->Buffer)) { PhShellExploreFile(Context->WindowHandle, node->PathText->Buffer); } } break; case ID_CLR_COPY: { PPH_STRING text; text = PhGetTreeNewText(Context->TnHandle, 0); PhSetClipboardString(Context->TnHandle, &text->sr); PhDereferenceObject(text); } break; } } PhDestroyEMenu(menu); }
INT_PTR CALLBACK PhpProcessThreadsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_THREADS_CONTEXT threadsContext; HWND tnHandle; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { threadsContext = (PPH_THREADS_CONTEXT)propPageContext->Context; if (threadsContext) tnHandle = threadsContext->ListContext.TreeNewHandle; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { threadsContext = propPageContext->Context = PhAllocate(PhEmGetObjectSize(EmThreadsContextType, sizeof(PH_THREADS_CONTEXT))); // The thread provider has a special registration mechanism. threadsContext->Provider = PhCreateThreadProvider( processItem->ProcessId ); PhRegisterCallback( &threadsContext->Provider->ThreadAddedEvent, ThreadAddedHandler, threadsContext, &threadsContext->AddedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadModifiedEvent, ThreadModifiedHandler, threadsContext, &threadsContext->ModifiedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadRemovedEvent, ThreadRemovedHandler, threadsContext, &threadsContext->RemovedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->UpdatedEvent, ThreadsUpdatedHandler, threadsContext, &threadsContext->UpdatedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, ThreadsLoadingStateChangedHandler, threadsContext, &threadsContext->LoadingStateChangedEventRegistration ); threadsContext->WindowHandle = hwndDlg; // Initialize the list. tnHandle = GetDlgItem(hwndDlg, IDC_LIST); BringWindowToTop(tnHandle); PhInitializeThreadList(hwndDlg, tnHandle, &threadsContext->ListContext); TreeNew_SetEmptyText(tnHandle, &EmptyThreadsText, 0); PhInitializeProviderEventQueue(&threadsContext->EventQueue, 100); // Use Cycles instead of Context Switches on Vista and above, but only when we can // open the process, since cycle time information requires sufficient access to the // threads. if (WINDOWS_HAS_CYCLE_TIME) { HANDLE processHandle; PROCESS_EXTENDED_BASIC_INFORMATION extendedBasicInfo; // We make a distinction between PROCESS_QUERY_INFORMATION and PROCESS_QUERY_LIMITED_INFORMATION since // the latter can be used when opening audiodg.exe even though we can't access its threads using // THREAD_QUERY_LIMITED_INFORMATION. if (processItem->ProcessId == SYSTEM_IDLE_PROCESS_ID) { threadsContext->ListContext.UseCycleTime = TRUE; } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; NtClose(processHandle); } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_LIMITED_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; // We can't use cycle time for protected processes (without KProcessHacker). if (NT_SUCCESS(PhGetProcessExtendedBasicInformation(processHandle, &extendedBasicInfo)) && extendedBasicInfo.IsProtectedProcess) { threadsContext->ListContext.UseCycleTime = FALSE; } NtClose(processHandle); } } if (processItem->ServiceList && processItem->ServiceList->Count != 0 && WINDOWS_HAS_SERVICE_TAGS) threadsContext->ListContext.HasServices = TRUE; PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectCreate); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; treeNewInfo.SystemContext = threadsContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewInitializing), &treeNewInfo); } PhLoadSettingsThreadList(&threadsContext->ListContext); PhThreadProviderInitialUpdate(threadsContext->Provider); PhRegisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); SET_BUTTON_ICON(IDC_OPENSTARTMODULE, PH_LOAD_SHARED_ICON_SMALL(MAKEINTRESOURCE(IDI_FOLDER))); } break; case WM_DESTROY: { PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectDelete); PhUnregisterCallback( &threadsContext->Provider->ThreadAddedEvent, &threadsContext->AddedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadModifiedEvent, &threadsContext->ModifiedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadRemovedEvent, &threadsContext->RemovedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->UpdatedEvent, &threadsContext->UpdatedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, &threadsContext->LoadingStateChangedEventRegistration ); PhUnregisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); PhSetTerminatingThreadProvider(threadsContext->Provider); PhDereferenceObject(threadsContext->Provider); PhDeleteProviderEventQueue(&threadsContext->EventQueue); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewUninitializing), &treeNewInfo); } PhSaveSettingsThreadList(&threadsContext->ListContext); PhDeleteThreadList(&threadsContext->ListContext); PhFree(threadsContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); #define ADD_BL_ITEM(Id) \ PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, Id), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM) // Thread details area { ULONG id; for (id = IDC_STATICBL1; id <= IDC_STATICBL11; id++) ADD_BL_ITEM(id); // Not in sequence ADD_BL_ITEM(IDC_STATICBL12); } PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_STARTMODULE), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_OPENSTARTMODULE), dialogItem, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); ADD_BL_ITEM(IDC_STARTED); ADD_BL_ITEM(IDC_KERNELTIME); ADD_BL_ITEM(IDC_USERTIME); ADD_BL_ITEM(IDC_CONTEXTSWITCHES); ADD_BL_ITEM(IDC_CYCLES); ADD_BL_ITEM(IDC_STATE); ADD_BL_ITEM(IDC_PRIORITY); ADD_BL_ITEM(IDC_BASEPRIORITY); ADD_BL_ITEM(IDC_IOPRIORITY); ADD_BL_ITEM(IDC_PAGEPRIORITY); ADD_BL_ITEM(IDC_IDEALPROCESSOR); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { INT id = LOWORD(wParam); switch (id) { case ID_SHOWCONTEXTMENU: { PhShowThreadContextMenu(hwndDlg, processItem, threadsContext, (PPH_TREENEW_CONTEXT_MENU)lParam); } break; case ID_THREAD_INSPECT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider); PhShowThreadStackDialog( hwndDlg, threadsContext->Provider->ProcessId, threadItem->ThreadId, threadsContext->Provider ); PhDereferenceObject(threadsContext->Provider); } } break; case ID_THREAD_TERMINATE: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); if (PhUiTerminateThreads(hwndDlg, threads, numberOfThreads)) PhDeselectAllThreadNodes(&threadsContext->ListContext); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_SUSPEND: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiSuspendThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_RESUME: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiResumeThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_AFFINITY: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadItem); PhShowProcessAffinityDialog(hwndDlg, NULL, threadItem); PhDereferenceObject(threadItem); } } break; case ID_THREAD_PERMISSIONS: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); PH_STD_OBJECT_SECURITY stdObjectSecurity; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; if (threadItem) { stdObjectSecurity.OpenObject = PhpThreadPermissionsOpenThread; stdObjectSecurity.ObjectType = L"Thread"; stdObjectSecurity.Context = threadItem->ThreadId; if (PhGetAccessEntries(L"Thread", &accessEntries, &numberOfAccessEntries)) { PhEditSecurity( hwndDlg, PhaFormatString(L"Thread %u", HandleToUlong(threadItem->ThreadId))->Buffer, PhStdGetObjectSecurity, PhStdSetObjectSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries ); PhFree(accessEntries); } } } break; case ID_THREAD_TOKEN: { NTSTATUS status; PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); HANDLE threadHandle; if (threadItem) { if (NT_SUCCESS(status = PhOpenThread( &threadHandle, ThreadQueryAccess, threadItem->ThreadId ))) { PhShowTokenProperties( hwndDlg, PhpOpenThreadTokenObject, (PVOID)threadHandle, NULL ); NtClose(threadHandle); } else { PhShowStatus(hwndDlg, L"Unable to open the thread", status, 0); } } } break; case ID_ANALYZE_WAIT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider->SymbolProvider); PhUiAnalyzeWaitThread( hwndDlg, processItem->ProcessId, threadItem->ThreadId, threadsContext->Provider->SymbolProvider ); PhDereferenceObject(threadsContext->Provider->SymbolProvider); } } break; case ID_PRIORITY_TIMECRITICAL: case ID_PRIORITY_HIGHEST: case ID_PRIORITY_ABOVENORMAL: case ID_PRIORITY_NORMAL: case ID_PRIORITY_BELOWNORMAL: case ID_PRIORITY_LOWEST: case ID_PRIORITY_IDLE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG threadPriorityWin32; switch (id) { case ID_PRIORITY_TIMECRITICAL: threadPriorityWin32 = THREAD_PRIORITY_TIME_CRITICAL; break; case ID_PRIORITY_HIGHEST: threadPriorityWin32 = THREAD_PRIORITY_HIGHEST; break; case ID_PRIORITY_ABOVENORMAL: threadPriorityWin32 = THREAD_PRIORITY_ABOVE_NORMAL; break; case ID_PRIORITY_NORMAL: threadPriorityWin32 = THREAD_PRIORITY_NORMAL; break; case ID_PRIORITY_BELOWNORMAL: threadPriorityWin32 = THREAD_PRIORITY_BELOW_NORMAL; break; case ID_PRIORITY_LOWEST: threadPriorityWin32 = THREAD_PRIORITY_LOWEST; break; case ID_PRIORITY_IDLE: threadPriorityWin32 = THREAD_PRIORITY_IDLE; break; } PhReferenceObject(threadItem); PhUiSetPriorityThread(hwndDlg, threadItem, threadPriorityWin32); PhDereferenceObject(threadItem); } } break; case ID_IOPRIORITY_VERYLOW: case ID_IOPRIORITY_LOW: case ID_IOPRIORITY_NORMAL: case ID_IOPRIORITY_HIGH: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { IO_PRIORITY_HINT ioPriority; switch (id) { case ID_IOPRIORITY_VERYLOW: ioPriority = IoPriorityVeryLow; break; case ID_IOPRIORITY_LOW: ioPriority = IoPriorityLow; break; case ID_IOPRIORITY_NORMAL: ioPriority = IoPriorityNormal; break; case ID_IOPRIORITY_HIGH: ioPriority = IoPriorityHigh; break; } PhReferenceObject(threadItem); PhUiSetIoPriorityThread(hwndDlg, threadItem, ioPriority); PhDereferenceObject(threadItem); } } break; case ID_PAGEPRIORITY_VERYLOW: case ID_PAGEPRIORITY_LOW: case ID_PAGEPRIORITY_MEDIUM: case ID_PAGEPRIORITY_BELOWNORMAL: case ID_PAGEPRIORITY_NORMAL: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG pagePriority; switch (id) { case ID_PAGEPRIORITY_VERYLOW: pagePriority = MEMORY_PRIORITY_VERY_LOW; break; case ID_PAGEPRIORITY_LOW: pagePriority = MEMORY_PRIORITY_LOW; break; case ID_PAGEPRIORITY_MEDIUM: pagePriority = MEMORY_PRIORITY_MEDIUM; break; case ID_PAGEPRIORITY_BELOWNORMAL: pagePriority = MEMORY_PRIORITY_BELOW_NORMAL; break; case ID_PAGEPRIORITY_NORMAL: pagePriority = MEMORY_PRIORITY_NORMAL; break; } PhReferenceObject(threadItem); PhUiSetPagePriorityThread(hwndDlg, threadItem, pagePriority); PhDereferenceObject(threadItem); } } break; case ID_THREAD_COPY: { PPH_STRING text; text = PhGetTreeNewText(tnHandle, 0); PhSetClipboardString(tnHandle, &text->sr); PhDereferenceObject(text); } break; case IDC_OPENSTARTMODULE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem && threadItem->StartAddressFileName) { PhShellExploreFile(hwndDlg, threadItem->StartAddressFileName->Buffer); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_SETACTIVE: break; case PSN_KILLACTIVE: // Can't disable, it screws up the deltas. break; } } break; case WM_PH_THREADS_UPDATED: { ULONG upToRunId = (ULONG)wParam; BOOLEAN firstRun = !!lParam; PPH_PROVIDER_EVENT events; ULONG count; ULONG i; events = PhFlushProviderEventQueue(&threadsContext->EventQueue, upToRunId, &count); if (events) { TreeNew_SetRedraw(tnHandle, FALSE); for (i = 0; i < count; i++) { PH_PROVIDER_EVENT_TYPE type = PH_PROVIDER_EVENT_TYPE(events[i]); PPH_THREAD_ITEM threadItem = PH_PROVIDER_EVENT_OBJECT(events[i]); switch (type) { case ProviderAddedEvent: PhAddThreadNode(&threadsContext->ListContext, threadItem, firstRun); PhDereferenceObject(threadItem); break; case ProviderModifiedEvent: PhUpdateThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; case ProviderRemovedEvent: PhRemoveThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; } } PhFree(events); } PhTickThreadNodes(&threadsContext->ListContext); if (count != 0) TreeNew_SetRedraw(tnHandle, TRUE); if (propPageContext->PropContext->SelectThreadId) { PPH_THREAD_NODE threadNode; if (threadNode = PhFindThreadNode(&threadsContext->ListContext, propPageContext->PropContext->SelectThreadId)) { if (threadNode->Node.Visible) { TreeNew_SetFocusNode(tnHandle, &threadNode->Node); TreeNew_SetMarkNode(tnHandle, &threadNode->Node); TreeNew_SelectRange(tnHandle, threadNode->Node.Index, threadNode->Node.Index); TreeNew_EnsureVisible(tnHandle, &threadNode->Node); } } propPageContext->PropContext->SelectThreadId = NULL; } PhpUpdateThreadDetails(hwndDlg, threadsContext, FALSE); } break; case WM_PH_THREAD_SELECTION_CHANGED: { PhpUpdateThreadDetails(hwndDlg, threadsContext, TRUE); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessRecordDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PPROCESS_RECORD_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PPROCESS_RECORD_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PPROCESS_RECORD_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); if (uMsg == WM_DESTROY) { RemoveProp(hwndDlg, PhMakeContextAtom()); } } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PH_IMAGE_VERSION_INFO versionInfo; BOOLEAN versionInfoInitialized; PPH_STRING processNameString; PPH_PROCESS_ITEM processItem; if (!PH_IS_FAKE_PROCESS_ID(context->Record->ProcessId)) { processNameString = PhaFormatString(L"%s (%u)", context->Record->ProcessName->Buffer, (ULONG)context->Record->ProcessId); } else { processNameString = context->Record->ProcessName; } PhCenterWindow(hwndDlg, GetParent(hwndDlg)); SetWindowText(hwndDlg, processNameString->Buffer); SetDlgItemText(hwndDlg, IDC_PROCESSNAME, processNameString->Buffer); if (processItem = PhReferenceProcessItemForRecord(context->Record)) { PPH_PROCESS_ITEM parentProcess; if (parentProcess = PhReferenceProcessItemForParent( processItem->ParentProcessId, processItem->ProcessId, &processItem->CreateTime )) { CLIENT_ID clientId; clientId.UniqueProcess = parentProcess->ProcessId; clientId.UniqueThread = NULL; SetDlgItemText(hwndDlg, IDC_PARENT, ((PPH_STRING)PHA_DEREFERENCE(PhGetClientIdNameEx(&clientId, parentProcess->ProcessName)))->Buffer); PhDereferenceObject(parentProcess); } else { SetDlgItemText(hwndDlg, IDC_PARENT, PhaFormatString(L"Non-existent process (%u)", (ULONG)context->Record->ParentProcessId)->Buffer); } PhDereferenceObject(processItem); } else { SetDlgItemText(hwndDlg, IDC_PARENT, PhaFormatString(L"Unknown process (%u)", (ULONG)context->Record->ParentProcessId)->Buffer); EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), FALSE); } memset(&versionInfo, 0, sizeof(PH_IMAGE_VERSION_INFO)); versionInfoInitialized = FALSE; if (context->Record->FileName) { if (PhInitializeImageVersionInfo(&versionInfo, context->Record->FileName->Buffer)) versionInfoInitialized = TRUE; } context->FileIcon = PhGetFileShellIcon(PhGetString(context->Record->FileName), L".exe", TRUE); SendMessage(GetDlgItem(hwndDlg, IDC_OPENFILENAME), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)PH_LOAD_SHARED_IMAGE(MAKEINTRESOURCE(IDB_FOLDER), IMAGE_BITMAP)); SendMessage(GetDlgItem(hwndDlg, IDC_FILEICON), STM_SETICON, (WPARAM)context->FileIcon, 0); SetDlgItemText(hwndDlg, IDC_NAME, PhpGetStringOrNa(versionInfo.FileDescription)); SetDlgItemText(hwndDlg, IDC_COMPANYNAME, PhpGetStringOrNa(versionInfo.CompanyName)); SetDlgItemText(hwndDlg, IDC_VERSION, PhpGetStringOrNa(versionInfo.FileVersion)); SetDlgItemText(hwndDlg, IDC_FILENAME, PhpGetStringOrNa(context->Record->FileName)); if (versionInfoInitialized) PhDeleteImageVersionInfo(&versionInfo); if (!context->Record->FileName) EnableWindow(GetDlgItem(hwndDlg, IDC_OPENFILENAME), FALSE); SetDlgItemText(hwndDlg, IDC_CMDLINE, PhpGetStringOrNa(context->Record->CommandLine)); if (context->Record->CreateTime.QuadPart != 0) SetDlgItemText(hwndDlg, IDC_STARTED, PhapGetRelativeTimeString(&context->Record->CreateTime)->Buffer); else SetDlgItemText(hwndDlg, IDC_STARTED, L"N/A"); if (context->Record->ExitTime.QuadPart != 0) SetDlgItemText(hwndDlg, IDC_TERMINATED, PhapGetRelativeTimeString(&context->Record->ExitTime)->Buffer); else SetDlgItemText(hwndDlg, IDC_TERMINATED, L"N/A"); SetDlgItemInt(hwndDlg, IDC_SESSIONID, context->Record->SessionId, FALSE); } break; case WM_DESTROY: { if (context->FileIcon) DestroyIcon(context->FileIcon); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: { EndDialog(hwndDlg, IDOK); } break; case IDC_OPENFILENAME: { if (context->Record->FileName) PhShellExploreFile(hwndDlg, context->Record->FileName->Buffer); } break; case IDC_PROPERTIES: { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItemForRecord(context->Record)) { ProcessHacker_ShowProcessProperties(PhMainWndHandle, processItem); PhDereferenceObject(processItem); } else { PhShowError(hwndDlg, L"The process has already terminated; only the process record is available."); } } break; } } break; } return FALSE; }