static NTSTATUS PhpRefreshThreadStackThreadStart( _In_ PVOID Parameter ) { NTSTATUS status; PTHREAD_STACK_CONTEXT threadStackContext = Parameter; CLIENT_ID clientId; BOOLEAN defaultWalk; 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) { status = PhWalkThreadStack( threadStackContext->ThreadHandle, threadStackContext->SymbolProvider->ProcessHandle, &clientId, PH_WALK_I386_STACK | PH_WALK_AMD64_STACK | PH_WALK_KERNEL_STACK, PhpWalkThreadStackCallback, threadStackContext ); } if (threadStackContext->NewList->Count != 0) status = STATUS_SUCCESS; threadStackContext->WalkStatus = status; PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_COMPLETED, 0, 0); return STATUS_SUCCESS; }
VOID PhUiAnalyzeWaitThread( _In_ HWND hWnd, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ PPH_SYMBOL_PROVIDER SymbolProvider ) { NTSTATUS status; HANDLE threadHandle; #ifdef _WIN64 HANDLE processHandle; BOOLEAN isWow64; #endif CLIENT_ID clientId; ANALYZE_WAIT_CONTEXT context; #ifdef _WIN64 // Determine if the process is WOW64. If not, we use the passive method. if (!NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_QUERY_LIMITED_INFORMATION, ProcessId))) { PhShowStatus(hWnd, L"Unable to open the process", status, 0); return; } if (!NT_SUCCESS(status = PhGetProcessIsWow64(processHandle, &isWow64)) || !isWow64) { PhpAnalyzeWaitPassive(hWnd, ProcessId, ThreadId); return; } NtClose(processHandle); #endif if (!NT_SUCCESS(status = PhOpenThread( &threadHandle, THREAD_QUERY_LIMITED_INFORMATION | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, ThreadId ))) { PhShowStatus(hWnd, L"Unable to open the thread.", status, 0); return; } memset(&context, 0, sizeof(ANALYZE_WAIT_CONTEXT)); context.ProcessId = ProcessId; context.ThreadId = ThreadId; context.ProcessHandle = SymbolProvider->ProcessHandle; context.SymbolProvider = SymbolProvider; PhInitializeStringBuilder(&context.StringBuilder, 100); clientId.UniqueProcess = ProcessId; clientId.UniqueThread = ThreadId; PhWalkThreadStack( threadHandle, SymbolProvider->ProcessHandle, &clientId, SymbolProvider, PH_WALK_I386_STACK, PhpWalkThreadStackAnalyzeCallback, &context ); NtClose(threadHandle); PhpAnalyzeWaitFallbacks(&context); if (context.Found) { PhShowInformationDialog(hWnd, context.StringBuilder.String->Buffer, 0); } else { PhShowInformation2(hWnd, L"The thread does not appear to be waiting.", L""); } PhDeleteStringBuilder(&context.StringBuilder); }