VOID SetupShowUninstallDialog( VOID ) { PVOID context; TASKDIALOGCONFIG config; PH_AUTO_POOL autoPool; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); PhInitializeAutoPool(&autoPool); context = (PPH_SETUP_CONTEXT)PhCreateAlloc(sizeof(PH_SETUP_CONTEXT)); memset(context, 0, sizeof(PH_SETUP_CONTEXT)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_POSITION_RELATIVE_TO_WINDOW; config.dwCommonButtons = TDCBF_CANCEL_BUTTON; config.pszWindowTitle = PhApplicationName; config.pfCallback = TaskDialogUninstallBootstrapCallback; config.lpCallbackData = (LONG_PTR)context; TaskDialogIndirect(&config, NULL, NULL, NULL); PhDereferenceObject(context); PhDeleteAutoPool(&autoPool); }
NTSTATUS ShowUpdateDialogThread( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; PPH_UPDATER_CONTEXT context; TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) }; if (Parameter) context = (PPH_UPDATER_CONTEXT)Parameter; else context = CreateUpdateContext(FALSE); PhInitializeAutoPool(&autoPool); // Start TaskDialog bootstrap config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED; config.pszContent = L"Initializing..."; config.lpCallbackData = (LONG_PTR)context; config.pfCallback = TaskDialogBootstrapCallback; TaskDialogIndirect(&config, NULL, NULL, NULL); FreeUpdateContext(context); PhDeleteAutoPool(&autoPool); if (UpdateDialogThreadHandle) { NtClose(UpdateDialogThreadHandle); UpdateDialogThreadHandle = NULL; } PhResetEvent(&InitializedEvent); return STATUS_SUCCESS; }
static NTSTATUS WindowThreadStart( __in PVOID Parameter ) { PH_AUTO_POOL autoPool; BOOL result; MSG message; PhInitializeAutoPool(&autoPool); GfxWindowHandle = CreateDialog( PluginInstance->DllBase, MAKEINTRESOURCE(IDD_SYSGFX), NULL, MainWndProc ); PhSetEvent(&InitializedEvent); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(GfxWindowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); PhResetEvent(&InitializedEvent); NtClose(GfxThreadHandle); GfxWindowHandle = NULL; GfxPanelWindowHandle = NULL; GfxThreadHandle = NULL; return STATUS_SUCCESS; }
static NTSTATUS PhNetworkOutputDialogThreadStart( _In_ PVOID Parameter ) { BOOL result; MSG message; HWND windowHandle; PH_AUTO_POOL autoPool; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; PhInitializeAutoPool(&autoPool); windowHandle = CreateDialogParam( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_OUTPUT), PhMainWndHandle, NetworkOutputDlgProc, (LPARAM)Parameter ); ShowWindow(windowHandle, SW_SHOW); SetForegroundWindow(windowHandle); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(context->WindowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); DestroyWindow(windowHandle); return STATUS_SUCCESS; }
NTSTATUS PhNetworkPingDialogThreadStart( _In_ PVOID Parameter ) { BOOL result; MSG message; HWND windowHandle; PH_AUTO_POOL autoPool; PhInitializeAutoPool(&autoPool); windowHandle = CreateDialogParam( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_PINGDIALOG), NULL, NetworkPingWndProc, (LPARAM)Parameter ); ShowWindow(windowHandle, SW_SHOW); SetForegroundWindow(windowHandle); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(windowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }
VOID SetupShowUpdateDialog( VOID ) { PVOID context; TASKDIALOGCONFIG config; PH_AUTO_POOL autoPool; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); PhInitializeAutoPool(&autoPool); context = CreateUpdateContext(); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_POSITION_RELATIVE_TO_WINDOW; config.dwCommonButtons = TDCBF_CANCEL_BUTTON; config.pszWindowTitle = PhApplicationName; config.pfCallback = TaskDialogBootstrapCallback; config.lpCallbackData = (LONG_PTR)context; TaskDialogIndirect(&config, NULL, NULL, NULL); PhDeleteAutoPool(&autoPool); }
NTSTATUS PhpWorkQueueThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; PPH_WORK_QUEUE workQueue = (PPH_WORK_QUEUE)Parameter; PhInitializeAutoPool(&autoPool); while (TRUE) { NTSTATUS status; HANDLE semaphoreHandle; LARGE_INTEGER timeout; PPH_WORK_QUEUE_ITEM workQueueItem = NULL; // Check if we have more threads than the limit. if (workQueue->CurrentThreads > workQueue->MaximumThreads) { BOOLEAN terminate = FALSE; // Lock and re-check. PhAcquireQueuedLockExclusive(&workQueue->StateLock); // Check the minimum as well. if (workQueue->CurrentThreads > workQueue->MaximumThreads && workQueue->CurrentThreads > workQueue->MinimumThreads) { workQueue->CurrentThreads--; terminate = TRUE; } PhReleaseQueuedLockExclusive(&workQueue->StateLock); if (terminate) break; } semaphoreHandle = PhpGetSemaphoreWorkQueue(workQueue); if (!workQueue->Terminating) { // Wait for work. status = NtWaitForSingleObject( semaphoreHandle, FALSE, PhTimeoutFromMilliseconds(&timeout, workQueue->NoWorkTimeout) ); } else { status = STATUS_UNSUCCESSFUL; } if (status == STATUS_WAIT_0 && !workQueue->Terminating) { PLIST_ENTRY listEntry; // Dequeue the work item. PhAcquireQueuedLockExclusive(&workQueue->QueueLock); listEntry = RemoveHeadList(&workQueue->QueueListHead); if (IsListEmpty(&workQueue->QueueListHead)) PhPulseCondition(&workQueue->QueueEmptyCondition); PhReleaseQueuedLockExclusive(&workQueue->QueueLock); // Make sure we got work. if (listEntry != &workQueue->QueueListHead) { workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry); PhpExecuteWorkQueueItem(workQueueItem); _InterlockedDecrement(&workQueue->BusyCount); PhpDestroyWorkQueueItem(workQueueItem); } } else { BOOLEAN terminate = FALSE; // No work arrived before the timeout passed, or we are terminating, or some error // occurred. Terminate the thread. PhAcquireQueuedLockExclusive(&workQueue->StateLock); if (workQueue->Terminating || workQueue->CurrentThreads > workQueue->MinimumThreads) { workQueue->CurrentThreads--; terminate = TRUE; } PhReleaseQueuedLockExclusive(&workQueue->StateLock); if (terminate) break; } PhDrainAutoPool(&autoPool); } PhReleaseRundownProtection(&workQueue->RundownProtect); PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }
static NTSTATUS ShowUpdateDialogThreadStart( __in PVOID Parameter ) { BOOL result; MSG message; PH_AUTO_POOL autoPool; PhInitializeAutoPool(&autoPool); UpdateDialogHandle = CreateDialog( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_UPDATE), PhMainWndHandle, UpdaterWndProc ); PhSetEvent(&InitializedEvent); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(UpdateDialogHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); PhResetEvent(&InitializedEvent); // Ensure global objects are disposed and reset when window closes. if (SetupFilePath) { PhDereferenceObject(SetupFilePath); SetupFilePath = NULL; } if (UpdateCheckThreadHandle) { NtClose(UpdateCheckThreadHandle); UpdateCheckThreadHandle = NULL; } if (DownloadThreadHandle) { NtClose(DownloadThreadHandle); DownloadThreadHandle = NULL; } if (UpdaterDialogThreadHandle) { NtClose(UpdaterDialogThreadHandle); UpdaterDialogThreadHandle = NULL; } if (FontHandle) { DeleteObject(FontHandle); FontHandle = NULL; } FreeXmlData(); if (UpdateDialogHandle) { DestroyWindow(UpdateDialogHandle); UpdateDialogHandle = NULL; } return STATUS_SUCCESS; }
NTSTATUS PhSvcApiRequestThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; NTSTATUS status; PHSVC_THREAD_CONTEXT threadContext; HANDLE portHandle; PVOID portContext; SIZE_T messageSize; PPORT_MESSAGE receiveMessage; PPORT_MESSAGE replyMessage; CSHORT messageType; PPHSVC_CLIENT client; PPHSVC_API_PAYLOAD payload; PhInitializeAutoPool(&autoPool); threadContext.CurrentClient = NULL; threadContext.OldClient = NULL; TlsSetValue(PhSvcApiThreadContextTlsIndex, &threadContext); portHandle = PhSvcApiPortHandle; messageSize = PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG); receiveMessage = PhAllocate(messageSize); replyMessage = NULL; while (TRUE) { status = NtReplyWaitReceivePort( portHandle, &portContext, replyMessage, receiveMessage ); portHandle = PhSvcApiPortHandle; replyMessage = NULL; if (!NT_SUCCESS(status)) { // Client probably died. continue; } messageType = receiveMessage->u2.s2.Type; if (messageType == LPC_CONNECTION_REQUEST) { PhSvcHandleConnectionRequest(receiveMessage); continue; } if (!portContext) continue; client = portContext; threadContext.CurrentClient = client; PhWaitForEvent(&client->ReadyEvent, NULL); if (messageType == LPC_REQUEST) { if (PhIsExecutingInWow64()) payload = &((PPHSVC_API_MSG64)receiveMessage)->p; else payload = &((PPHSVC_API_MSG)receiveMessage)->p; PhSvcDispatchApiCall(client, payload, &portHandle); replyMessage = receiveMessage; } else if (messageType == LPC_PORT_CLOSED) { PhDereferenceObject(client); if (_InterlockedDecrement(&PhSvcApiNumberOfClients) == 0) { NtSetEvent(PhSvcTimeoutStandbyEventHandle, NULL); } } assert(!threadContext.OldClient); PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); }
INT WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ INT nCmdShow ) { LONG result; #ifdef DEBUG PHP_BASE_THREAD_DBG dbg; #endif CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #ifndef DEBUG SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); #endif PhInstanceHandle = (HINSTANCE)NtCurrentPeb()->ImageBaseAddress; if (!NT_SUCCESS(PhInitializePhLib())) return 1; if (!PhInitializeAppSystem()) return 1; PhInitializeCommonControls(); if (PhCurrentTokenQueryHandle) { PTOKEN_USER tokenUser; if (NT_SUCCESS(PhGetTokenUser(PhCurrentTokenQueryHandle, &tokenUser))) { PhCurrentUserName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL); PhFree(tokenUser); } } PhLocalSystemName = PhGetSidFullName(&PhSeLocalSystemSid, TRUE, NULL); // There has been a report of the above call failing. if (!PhLocalSystemName) PhLocalSystemName = PhCreateString(L"NT AUTHORITY\\SYSTEM"); PhApplicationFileName = PhGetApplicationFileName(); PhApplicationDirectory = PhGetApplicationDirectory(); // Just in case if (!PhApplicationFileName) PhApplicationFileName = PhCreateString(L"ProcessHacker.exe"); if (!PhApplicationDirectory) PhApplicationDirectory = PhReferenceEmptyString(); PhpProcessStartupParameters(); PhSettingsInitialization(); PhpEnablePrivileges(); if (PhStartupParameters.RunAsServiceMode) { RtlExitUserProcess(PhRunAsServiceStart(PhStartupParameters.RunAsServiceMode)); } PhpInitializeSettings(); // Activate a previous instance if required. if (PhGetIntegerSetting(L"AllowOnlyOneInstance") && !PhStartupParameters.NewInstance && !PhStartupParameters.ShowOptions && !PhStartupParameters.CommandMode && !PhStartupParameters.PhSvc) { PhActivatePreviousInstance(); } if (PhGetIntegerSetting(L"EnableKph") && !PhStartupParameters.NoKph && !PhIsExecutingInWow64()) PhInitializeKph(); if (PhStartupParameters.CommandMode && PhStartupParameters.CommandType && PhStartupParameters.CommandAction) { NTSTATUS status; status = PhCommandModeStart(); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) { PhShowStatus(NULL, L"Unable to execute the command", status, 0); } RtlExitUserProcess(status); } #ifdef DEBUG dbg.ClientId = NtCurrentTeb()->ClientId; dbg.StartAddress = wWinMain; dbg.Parameter = NULL; InsertTailList(&PhDbgThreadListHead, &dbg.ListEntry); TlsSetValue(PhDbgThreadDbgTlsIndex, &dbg); #endif PhInitializeAutoPool(&BaseAutoPool); PhEmInitialization(); PhGuiSupportInitialization(); PhTreeNewInitialization(); PhGraphControlInitialization(); PhHexEditInitialization(); PhColorBoxInitialization(); PhSmallIconSize.X = GetSystemMetrics(SM_CXSMICON); PhSmallIconSize.Y = GetSystemMetrics(SM_CYSMICON); PhLargeIconSize.X = GetSystemMetrics(SM_CXICON); PhLargeIconSize.Y = GetSystemMetrics(SM_CYICON); if (PhStartupParameters.ShowOptions) { // Elevated options dialog for changing the value of Replace Task Manager with Process Hacker. PhShowOptionsDialog(PhStartupParameters.WindowHandle); RtlExitUserProcess(STATUS_SUCCESS); } #ifndef DEBUG if (PhIsExecutingInWow64() && !PhStartupParameters.PhSvc) { PhShowWarning( NULL, L"You are attempting to run the 32-bit version of Process Hacker on 64-bit Windows. " L"Most features will not work correctly.\n\n" L"Please run the 64-bit version of Process Hacker instead." ); } #endif PhPluginsEnabled = PhGetIntegerSetting(L"EnablePlugins") && !PhStartupParameters.NoPlugins; if (PhPluginsEnabled) { PhPluginsInitialization(); PhLoadPlugins(); } if (PhStartupParameters.PhSvc) { MSG message; // Turn the feedback cursor off. PostMessage(NULL, WM_NULL, 0, 0); GetMessage(&message, NULL, 0, 0); RtlExitUserProcess(PhSvcMain(NULL, NULL, NULL)); } // Create a mutant for the installer. { HANDLE mutantHandle; OBJECT_ATTRIBUTES oa; UNICODE_STRING mutantName; RtlInitUnicodeString(&mutantName, L"\\BaseNamedObjects\\ProcessHacker2Mutant"); InitializeObjectAttributes( &oa, &mutantName, 0, NULL, NULL ); NtCreateMutant(&mutantHandle, MUTANT_ALL_ACCESS, &oa, FALSE); } // Set priority. { PROCESS_PRIORITY_CLASS priorityClass; priorityClass.Foreground = FALSE; priorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; if (PhStartupParameters.PriorityClass != 0) priorityClass.PriorityClass = (UCHAR)PhStartupParameters.PriorityClass; NtSetInformationProcess(NtCurrentProcess(), ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); } if (!PhMainWndInitialization(nCmdShow)) { PhShowError(NULL, L"Unable to initialize the main window."); return 1; } PhDrainAutoPool(&BaseAutoPool); result = PhMainMessageLoop(); RtlExitUserProcess(result); }
PPH_LIST PhGetGenericTreeNewLines( __in HWND TreeNewHandle, __in ULONG Mode ) { PH_AUTO_POOL autoPool; PPH_LIST lines; ULONG rows; ULONG columns; ULONG numberOfNodes; PULONG displayToId; PWSTR *displayToText; PPH_STRING **table; ULONG i; ULONG j; PhInitializeAutoPool(&autoPool); numberOfNodes = TreeNew_GetFlatNodeCount(TreeNewHandle); rows = numberOfNodes + 1; PhMapDisplayIndexTreeNew(TreeNewHandle, &displayToId, &displayToText, &columns); PhaCreateTextTable(&table, rows, columns); for (i = 0; i < columns; i++) table[0][i] = PhaCreateString(displayToText[i]); for (i = 0; i < numberOfNodes; i++) { PPH_TREENEW_NODE node; node = TreeNew_GetFlatNode(TreeNewHandle, i); if (node) { for (j = 0; j < columns; j++) { PH_TREENEW_GET_CELL_TEXT getCellText; getCellText.Node = node; getCellText.Id = displayToId[j]; PhInitializeEmptyStringRef(&getCellText.Text); TreeNew_GetCellText(TreeNewHandle, &getCellText); table[i + 1][j] = PhaCreateStringEx(getCellText.Text.Buffer, getCellText.Text.Length); } } else { for (j = 0; j < columns; j++) { table[i + 1][j] = PHA_DEREFERENCE(PhReferenceEmptyString()); } } } PhFree(displayToText); PhFree(displayToId); lines = PhaFormatTextTable(table, rows, columns, Mode); PhDeleteAutoPool(&autoPool); return lines; }
NTSTATUS SaveDb( VOID ) { PH_AUTO_POOL autoPool; NTSTATUS status; HANDLE fileHandle; mxml_node_t *topNode; ULONG enumerationKey = 0; PDB_OBJECT *object; PhInitializeAutoPool(&autoPool); topNode = mxmlNewElement(MXML_NO_PARENT, "objects"); LockDb(); while (PhEnumHashtable(ObjectDb, (PVOID*)&object, &enumerationKey)) { CreateObjectElement( topNode, &UInt64ToBase10String((*object)->Tag)->sr, &(*object)->Name->sr, &UInt64ToBase10String((*object)->PriorityClass)->sr, &UInt64ToBase10String((*object)->IoPriorityPlusOne)->sr, &(*object)->Comment->sr, &UInt64ToBase10String((*object)->BackColor)->sr, &UInt64ToBase10String((*object)->Collapse)->sr, &UInt64ToBase10String((*object)->AffinityMask)->sr ); PhDrainAutoPool(&autoPool); } UnlockDb(); // Create the directory if it does not exist. { PPH_STRING fullPath; ULONG indexOfFileName; if (fullPath = PH_AUTO(PhGetFullPath(ObjectDbPath->Buffer, &indexOfFileName))) { if (indexOfFileName != -1) SHCreateDirectoryEx(NULL, PhaSubstring(fullPath, 0, indexOfFileName)->Buffer, NULL); } } PhDeleteAutoPool(&autoPool); status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { mxmlDelete(topNode); return status; } mxmlSaveFd(topNode, fileHandle, MXML_NO_CALLBACK); mxmlDelete(topNode); NtClose(fileHandle); return STATUS_SUCCESS; }
BOOLEAN PhModalPropertySheet( _Inout_ PROPSHEETHEADER *Header ) { // PropertySheet incorrectly discards WM_QUIT messages in certain cases, so we will use our own // message loop. An example of this is when GetMessage (called by PropertySheet's message loop) // dispatches a message directly from kernel-mode that causes the property sheet to close. // In that case PropertySheet will retrieve the WM_QUIT message but will ignore it because of // its buggy logic. // This is also a good opportunity to introduce an auto-pool. PH_AUTO_POOL autoPool; HWND oldFocus; HWND topLevelOwner; HWND hwnd; BOOL result; MSG message; PhInitializeAutoPool(&autoPool); oldFocus = GetFocus(); topLevelOwner = Header->hwndParent; while (topLevelOwner && (GetWindowLong(topLevelOwner, GWL_STYLE) & WS_CHILD)) topLevelOwner = GetParent(topLevelOwner); if (topLevelOwner && (topLevelOwner == GetDesktopWindow() || EnableWindow(topLevelOwner, FALSE))) topLevelOwner = NULL; Header->dwFlags |= PSH_MODELESS; hwnd = (HWND)PropertySheet(Header); if (!hwnd) { if (topLevelOwner) EnableWindow(topLevelOwner, TRUE); return FALSE; } while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!PropSheet_IsDialogMessage(hwnd, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); // Destroy the window when necessary. if (!PropSheet_GetCurrentPageHwnd(hwnd)) break; } if (result == 0) PostQuitMessage((INT)message.wParam); if (Header->hwndParent && GetActiveWindow() == hwnd) SetActiveWindow(Header->hwndParent); if (topLevelOwner) EnableWindow(topLevelOwner, TRUE); if (oldFocus && IsWindow(oldFocus)) SetFocus(oldFocus); DestroyWindow(hwnd); PhDeleteAutoPool(&autoPool); return TRUE; }
static NTSTATUS PhpRefreshThreadStackThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; NTSTATUS status; PTHREAD_STACK_CONTEXT threadStackContext = Parameter; CLIENT_ID clientId; BOOLEAN defaultWalk; PhInitializeAutoPool(&autoPool); PhLoadSymbolsThreadProvider(threadStackContext->ThreadProvider); clientId.UniqueProcess = threadStackContext->ProcessId; clientId.UniqueThread = threadStackContext->ThreadId; defaultWalk = TRUE; if (threadStackContext->CustomWalk) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackWalkStack; control.UniqueKey = threadStackContext; control.u.WalkStack.Status = STATUS_UNSUCCESSFUL; control.u.WalkStack.ThreadHandle = threadStackContext->ThreadHandle; control.u.WalkStack.ProcessHandle = threadStackContext->SymbolProvider->ProcessHandle; control.u.WalkStack.ClientId = &clientId; control.u.WalkStack.Flags = PH_WALK_I386_STACK | PH_WALK_AMD64_STACK | PH_WALK_KERNEL_STACK; control.u.WalkStack.Callback = PhpWalkThreadStackCallback; control.u.WalkStack.CallbackContext = threadStackContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); status = control.u.WalkStack.Status; if (NT_SUCCESS(status)) defaultWalk = FALSE; } if (defaultWalk) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.UniqueKey = threadStackContext; if (PhPluginsEnabled) { control.Type = PluginThreadStackBeginDefaultWalkStack; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } status = PhWalkThreadStack( threadStackContext->ThreadHandle, threadStackContext->SymbolProvider->ProcessHandle, &clientId, threadStackContext->SymbolProvider, PH_WALK_I386_STACK | PH_WALK_AMD64_STACK | PH_WALK_KERNEL_STACK, PhpWalkThreadStackCallback, threadStackContext ); if (PhPluginsEnabled) { control.Type = PluginThreadStackEndDefaultWalkStack; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } } if (threadStackContext->NewList->Count != 0) status = STATUS_SUCCESS; threadStackContext->WalkStatus = status; PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_COMPLETED, 0, 0); PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }