Example #1
0
NTSTATUS PhpThreadQueryWorker(
    __in PVOID Parameter
    )
{
    PPH_THREAD_QUERY_DATA data = (PPH_THREAD_QUERY_DATA)Parameter;
    LONG newSymbolsLoading;

    newSymbolsLoading = _InterlockedIncrement(&data->ThreadProvider->SymbolsLoading);

    if (newSymbolsLoading == 1)
        PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)TRUE);

    // We can't resolve the start address until symbols have
    // been loaded.
    PhWaitForEvent(&data->ThreadProvider->SymbolsLoadedEvent, NULL);

    data->StartAddressString = PhGetSymbolFromAddress(
        data->ThreadProvider->SymbolProvider,
        data->ThreadItem->StartAddress,
        &data->StartAddressResolveLevel,
        &data->ThreadItem->StartAddressFileName,
        NULL,
        NULL
        );

    newSymbolsLoading = _InterlockedDecrement(&data->ThreadProvider->SymbolsLoading);

    if (newSymbolsLoading == 0)
        PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)FALSE);

    // Get the service tag, and the service name.
    if (
        WINDOWS_HAS_SERVICE_TAGS &&
        data->ThreadProvider->SymbolProvider->IsRealHandle &&
        data->ThreadItem->ThreadHandle
        )
    {
        PVOID serviceTag;

        if (NT_SUCCESS(PhGetThreadServiceTag(
            data->ThreadItem->ThreadHandle,
            data->ThreadProvider->ProcessHandle,
            &serviceTag
            )))
        {
            data->ServiceName = PhGetServiceNameFromTag(
                data->ThreadProvider->ProcessId,
                serviceTag
                );
        }
    }

    RtlInterlockedPushEntrySList(&data->ThreadProvider->QueryListHead, &data->ListEntry);

    PhDereferenceObject(data->ThreadProvider);

    return STATUS_SUCCESS;
}
Example #2
0
static BOOLEAN NTAPI PhpWalkThreadStackCallback(
    _In_ PPH_THREAD_STACK_FRAME StackFrame,
    _In_opt_ PVOID Context
    )
{
    PTHREAD_STACK_CONTEXT threadStackContext = (PTHREAD_STACK_CONTEXT)Context;
    PPH_STRING symbol;
    PTHREAD_STACK_ITEM item;

    if (threadStackContext->StopWalk)
        return FALSE;

    PhAcquireQueuedLockExclusive(&threadStackContext->StatusLock);
    PhMoveReference(&threadStackContext->StatusMessage,
        PhFormatString(L"Processing frame %u...", threadStackContext->NewList->Count));
    PhReleaseQueuedLockExclusive(&threadStackContext->StatusLock);
    PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_STATUS_UPDATE, 0, 0);

    symbol = PhGetSymbolFromAddress(
        threadStackContext->SymbolProvider,
        (ULONG64)StackFrame->PcAddress,
        NULL,
        NULL,
        NULL,
        NULL
        );

    if (symbol &&
        (StackFrame->Flags & PH_THREAD_STACK_FRAME_I386) &&
        !(StackFrame->Flags & PH_THREAD_STACK_FRAME_FPO_DATA_PRESENT))
    {
        PhMoveReference(&symbol, PhConcatStrings2(symbol->Buffer, L" (No unwind info)"));
    }

    item = PhAllocate(sizeof(THREAD_STACK_ITEM));
    item->StackFrame = *StackFrame;
    item->Index = threadStackContext->NewList->Count;

    if (PhPluginsEnabled)
    {
        PH_PLUGIN_THREAD_STACK_CONTROL control;

        control.Type = PluginThreadStackResolveSymbol;
        control.UniqueKey = threadStackContext;
        control.u.ResolveSymbol.StackFrame = StackFrame;
        control.u.ResolveSymbol.Symbol = symbol;
        PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control);

        symbol = control.u.ResolveSymbol.Symbol;
    }

    item->Symbol = symbol;
    PhAddItemList(threadStackContext->NewList, item);

    return TRUE;
}
Example #3
0
static NTSTATUS EtpSymbolLookupFunction(
    _In_ PVOID Parameter
    )
{
    PSYMBOL_LOOKUP_RESULT result;

    result = Parameter;

    // Don't bother looking up the symbol if the window has already closed.
    if (result->Context->Destroying)
    {
        EtpDereferenceWsWatchContext(result->Context);
        PhFree(result);
        return STATUS_SUCCESS;
    }

    result->Symbol = PhGetSymbolFromAddress(
        result->Context->SymbolProvider,
        (ULONG64)result->Address,
        NULL,
        NULL,
        NULL,
        NULL
        );

    // Fail if we don't have a symbol.
    if (!result->Symbol)
    {
        EtpDereferenceWsWatchContext(result->Context);
        PhFree(result);
        return STATUS_SUCCESS;
    }

    PhAcquireQueuedLockExclusive(&result->Context->ResultListLock);
    PushEntryList(&result->Context->ResultListHead, &result->ListEntry);
    PhReleaseQueuedLockExclusive(&result->Context->ResultListLock);
    EtpDereferenceWsWatchContext(result->Context);

    return STATUS_SUCCESS;
}
Example #4
0
static INT_PTR CALLBACK PhpNetworkStackDlgProc(
    _In_ HWND hwndDlg,
    _In_ UINT uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
    )
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        {
            PNETWORK_STACK_CONTEXT networkStackContext;
            HWND lvHandle;
            PPH_LAYOUT_MANAGER layoutManager;
            PVOID address;
            ULONG i;

            PhCenterWindow(hwndDlg, GetParent(hwndDlg));

            networkStackContext = (PNETWORK_STACK_CONTEXT)lParam;
            SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)networkStackContext);

            lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
            PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 350, L"Name");
            PhSetListViewStyle(lvHandle, FALSE, TRUE);
            PhSetControlTheme(lvHandle, L"explorer");

            networkStackContext->ListViewHandle = lvHandle;

            layoutManager = PhAllocate(sizeof(PH_LAYOUT_MANAGER));
            PhInitializeLayoutManager(layoutManager, hwndDlg);
            SetProp(hwndDlg, L"LayoutManager", (HANDLE)layoutManager);

            PhAddLayoutItem(layoutManager, lvHandle, NULL,
                PH_ANCHOR_ALL);
            PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDOK),
                NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);

            if (MinimumSize.left == -1)
            {
                RECT rect;

                rect.left = 0;
                rect.top = 0;
                rect.right = 190;
                rect.bottom = 120;
                MapDialogRect(hwndDlg, &rect);
                MinimumSize = rect;
                MinimumSize.left = 0;
            }

            for (i = 0; i < PH_NETWORK_OWNER_INFO_SIZE; i++)
            {
                PPH_STRING name;

                address = *(PVOID *)&networkStackContext->NetworkItem->OwnerInfo[i];

                if ((ULONG_PTR)address < PAGE_SIZE) // stop at an invalid address
                    break;

                name = PhGetSymbolFromAddress(
                    networkStackContext->SymbolProvider,
                    (ULONG64)address,
                    NULL,
                    NULL,
                    NULL,
                    NULL
                    );
                PhAddListViewItem(lvHandle, MAXINT, name->Buffer, NULL);
                PhDereferenceObject(name);
            }
        }
        break;
    case WM_DESTROY:
        {
            PPH_LAYOUT_MANAGER layoutManager;
            PNETWORK_STACK_CONTEXT networkStackContext;

            layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager");
            PhDeleteLayoutManager(layoutManager);
            PhFree(layoutManager);

            networkStackContext = (PNETWORK_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());

            RemoveProp(hwndDlg, PhMakeContextAtom());
            RemoveProp(hwndDlg, L"LayoutManager");
        }
        break;
    case WM_COMMAND:
        {
            INT id = LOWORD(wParam);

            switch (id)
            {
            case IDCANCEL: // Esc and X button to close
            case IDOK:
                EndDialog(hwndDlg, IDOK);
                break;
            }
        }
        break;
    case WM_SIZE:
        {
            PPH_LAYOUT_MANAGER layoutManager;

            layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager");
            PhLayoutManagerLayout(layoutManager);
        }
        break;
    case WM_SIZING:
        {
            PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
        }
        break;
    }

    return FALSE;
}
NTSTATUS PhpThreadQueryWorker(
    _In_ PVOID Parameter
    )
{
    PPH_THREAD_QUERY_DATA data = (PPH_THREAD_QUERY_DATA)Parameter;
    LONG newSymbolsLoading;

    if (data->ThreadProvider->Terminating)
        goto Done;

    newSymbolsLoading = _InterlockedIncrement(&data->ThreadProvider->SymbolsLoading);

    if (newSymbolsLoading == 1)
        PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)TRUE);

    if (data->ThreadProvider->SymbolsLoadedRunId == 0)
        PhLoadSymbolsThreadProvider(data->ThreadProvider);

    data->StartAddressString = PhGetSymbolFromAddress(
        data->ThreadProvider->SymbolProvider,
        data->ThreadItem->StartAddress,
        &data->StartAddressResolveLevel,
        &data->ThreadItem->StartAddressFileName,
        NULL,
        NULL
        );

    if (data->StartAddressResolveLevel == PhsrlAddress && data->ThreadProvider->SymbolsLoadedRunId < data->RunId)
    {
        // The process may have loaded new modules, so load symbols for those and try again.

        PhLoadSymbolsThreadProvider(data->ThreadProvider);

        PhClearReference(&data->StartAddressString);
        PhClearReference(&data->ThreadItem->StartAddressFileName);
        data->StartAddressString = PhGetSymbolFromAddress(
            data->ThreadProvider->SymbolProvider,
            data->ThreadItem->StartAddress,
            &data->StartAddressResolveLevel,
            &data->ThreadItem->StartAddressFileName,
            NULL,
            NULL
            );
    }

    newSymbolsLoading = _InterlockedDecrement(&data->ThreadProvider->SymbolsLoading);

    if (newSymbolsLoading == 0)
        PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)FALSE);

    // Check if the process has services - we'll need to know before getting service tag/name
    // information.
    if (WINDOWS_HAS_SERVICE_TAGS && !data->ThreadProvider->HasServicesKnown)
    {
        PPH_PROCESS_ITEM processItem;

        if (processItem = PhReferenceProcessItem(data->ThreadProvider->ProcessId))
        {
            data->ThreadProvider->HasServices = processItem->ServiceList && processItem->ServiceList->Count != 0;
            PhDereferenceObject(processItem);
        }

        data->ThreadProvider->HasServicesKnown = TRUE;
    }

    // Get the service tag, and the service name.
    if (WINDOWS_HAS_SERVICE_TAGS &&
        data->ThreadProvider->SymbolProvider->IsRealHandle &&
        data->ThreadItem->ThreadHandle)
    {
        PVOID serviceTag;

        if (NT_SUCCESS(PhGetThreadServiceTag(
            data->ThreadItem->ThreadHandle,
            data->ThreadProvider->ProcessHandle,
            &serviceTag
            )))
        {
            data->ServiceName = PhGetServiceNameFromTag(
                data->ThreadProvider->ProcessId,
                serviceTag
                );
        }
    }

Done:
    RtlInterlockedPushEntrySList(&data->ThreadProvider->QueryListHead, &data->ListEntry);
    PhDereferenceObject(data->ThreadProvider);

    return STATUS_SUCCESS;
}
Example #6
0
INT_PTR CALLBACK EtpTpWorkerFactoryPageDlgProc(
    __in HWND hwndDlg,
    __in UINT uMsg,
    __in WPARAM wParam,
    __in LPARAM lParam
    )
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        {
            LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
            PCOMMON_PAGE_CONTEXT context = (PCOMMON_PAGE_CONTEXT)propSheetPage->lParam;
            HANDLE workerFactoryHandle;

            if (NT_SUCCESS(EtpDuplicateHandleFromProcess(&workerFactoryHandle, WORKER_FACTORY_QUERY_INFORMATION, context)))
            {
                WORKER_FACTORY_BASIC_INFORMATION basicInfo;

                if (NT_SUCCESS(NtQueryInformationWorkerFactory(
                    workerFactoryHandle,
                    WorkerFactoryBasicInformation,
                    &basicInfo,
                    sizeof(WORKER_FACTORY_BASIC_INFORMATION),
                    NULL
                    )))
                {
                    PPH_SYMBOL_PROVIDER symbolProvider;
                    PPH_STRING symbol = NULL;

                    symbolProvider = PhCreateSymbolProvider(basicInfo.ProcessId);
                    PhLoadSymbolProviderOptions(symbolProvider);

                    if (symbolProvider->IsRealHandle)
                    {
                        PhEnumGenericModules(basicInfo.ProcessId, symbolProvider->ProcessHandle,
                            0, EnumGenericModulesCallback, symbolProvider);

                        symbol = PhGetSymbolFromAddress(symbolProvider, (ULONG64)basicInfo.StartRoutine,
                            NULL, NULL, NULL, NULL);
                    }

                    PhDereferenceObject(symbolProvider);

                    if (symbol)
                    {
                        SetDlgItemText(hwndDlg, IDC_WORKERTHREADSTART,
                            PhaFormatString(L"Worker Thread Start: %s", symbol->Buffer)->Buffer);
                        PhDereferenceObject(symbol);
                    }
                    else
                    {
                        SetDlgItemText(hwndDlg, IDC_WORKERTHREADSTART,
                            PhaFormatString(L"Worker Thread Start: 0x%Ix", basicInfo.StartRoutine)->Buffer);
                    }

                    SetDlgItemText(hwndDlg, IDC_WORKERTHREADCONTEXT,
                        PhaFormatString(L"Worker Thread Context: 0x%Ix", basicInfo.StartParameter)->Buffer);
                }

                NtClose(workerFactoryHandle);
            }
        }
        break;
    }

    return FALSE;
}
Example #7
0
static BOOLEAN NTAPI PhpWalkThreadStackAnalyzeCallback(
    _In_ PPH_THREAD_STACK_FRAME StackFrame,
    _In_opt_ PVOID Context
    )
{
    PANALYZE_WAIT_CONTEXT context = (PANALYZE_WAIT_CONTEXT)Context;
    PPH_STRING name;

    name = PhGetSymbolFromAddress(
        context->SymbolProvider,
        (ULONG64)StackFrame->PcAddress,
        NULL,
        NULL,
        NULL,
        NULL
        );

    if (!name)
        return TRUE;

    context->Found = TRUE;

#define FUNC_MATCH(Name) PhStartsWithString2(name, L##Name, TRUE)
#define NT_FUNC_MATCH(Name) ( \
    PhStartsWithString2(name, L"ntdll.dll!Nt" L##Name, TRUE) || \
    PhStartsWithString2(name, L"ntdll.dll!Zw" L##Name, TRUE) \
    )

    if (!name)
    {
        // Dummy
    }
    else if (FUNC_MATCH("kernel32.dll!Sleep"))
    {
        PhAppendFormatStringBuilder(
            &context->StringBuilder,
            L"Thread is sleeping. Timeout: %lu milliseconds.",
            PtrToUlong(StackFrame->Params[0])
            );
    }
    else if (NT_FUNC_MATCH("DelayExecution"))
    {
        BOOLEAN alertable = !!StackFrame->Params[0];
        PVOID timeoutAddress = StackFrame->Params[1];
        LARGE_INTEGER timeout;

        if (NT_SUCCESS(NtReadVirtualMemory(
            context->ProcessHandle,
            timeoutAddress,
            &timeout,
            sizeof(LARGE_INTEGER),
            NULL
            )))
        {
            if (timeout.QuadPart < 0)
            {
                PhAppendFormatStringBuilder(
                    &context->StringBuilder,
                    L"Thread is sleeping. Timeout: %I64u milliseconds.",
                    -timeout.QuadPart / PH_TIMEOUT_MS
                    );
            }
            else
            {
                // TODO
            }
        }
        else
        {
            PhAppendStringBuilder2(
                &context->StringBuilder,
                L"Thread is sleeping."
                );
        }
    }
    else if (NT_FUNC_MATCH("DeviceIoControlFile"))
    {
        HANDLE handle = (HANDLE)StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for an I/O control request:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (NT_FUNC_MATCH("FsControlFile"))
    {
        HANDLE handle = StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for a FS control request:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (NT_FUNC_MATCH("QueryObject"))
    {
        HANDLE handle = StackFrame->Params[0];

        // Use the KiFastSystemCall args if the handle we have is wrong.
        if ((ULONG_PTR)handle % 4 != 0 || !handle)
            handle = context->PrevParams[1];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is querying an object:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (NT_FUNC_MATCH("ReadFile") || NT_FUNC_MATCH("WriteFile"))
    {
        HANDLE handle = StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for file I/O:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (NT_FUNC_MATCH("RemoveIoCompletion"))
    {
        HANDLE handle = StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for an I/O completion port:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (
        NT_FUNC_MATCH("ReplyWaitReceivePort") ||
        NT_FUNC_MATCH("RequestWaitReplyPort") ||
        NT_FUNC_MATCH("AlpcSendWaitReceivePort")
        )
    {
        HANDLE handle = StackFrame->Params[0];
        PPH_STRING alpcInfo;

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for an ALPC port:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );

        if (alpcInfo = PhpaGetAlpcInformation(context->ThreadId))
        {
            PhAppendStringBuilder2(
                &context->StringBuilder,
                L"\r\n"
                );
            PhAppendStringBuilder(
                &context->StringBuilder,
                &alpcInfo->sr
                );
        }
    }
    else if (
        NT_FUNC_MATCH("SetHighWaitLowEventPair") ||
        NT_FUNC_MATCH("SetLowWaitHighEventPair") ||
        NT_FUNC_MATCH("WaitHighEventPair") ||
        NT_FUNC_MATCH("WaitLowEventPair")
        )
    {
        HANDLE handle = StackFrame->Params[0];

        if ((ULONG_PTR)handle % 4 != 0 || !handle)
            handle = context->PrevParams[1];

        PhAppendFormatStringBuilder(
            &context->StringBuilder,
            L"Thread is waiting (%s) for an event pair:\r\n",
            name->Buffer
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (
        FUNC_MATCH("user32.dll!NtUserGetMessage") ||
        FUNC_MATCH("user32.dll!NtUserWaitMessage")
        )
    {
        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for a USER message.\r\n"
            );
    }
    else if (FUNC_MATCH("user32.dll!NtUserMessageCall"))
    {
        PPH_STRING receiverString;

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is sending a USER message:\r\n"
            );

        receiverString = PhpaGetSendMessageReceiver(context->ThreadId);

        if (receiverString)
        {
            PhAppendStringBuilder(&context->StringBuilder, &receiverString->sr);
            PhAppendStringBuilder2(&context->StringBuilder, L"\r\n");
        }
        else
        {
            PhAppendStringBuilder2(&context->StringBuilder, L"Unknown.\r\n");
        }
    }
    else if (NT_FUNC_MATCH("WaitForDebugEvent"))
    {
        HANDLE handle = StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for a debug event:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (
        NT_FUNC_MATCH("WaitForKeyedEvent") ||
        NT_FUNC_MATCH("ReleaseKeyedEvent")
        )
    {
        HANDLE handle = StackFrame->Params[0];
        PVOID key = StackFrame->Params[1];

        PhAppendFormatStringBuilder(
            &context->StringBuilder,
            L"Thread is waiting (%s) for a keyed event (key 0x%Ix):\r\n",
            name->Buffer,
            key
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (
        NT_FUNC_MATCH("WaitForMultipleObjects") ||
        FUNC_MATCH("kernel32.dll!WaitForMultipleObjects")
        )
    {
        ULONG numberOfHandles = PtrToUlong(StackFrame->Params[0]);
        PVOID addressOfHandles = StackFrame->Params[1];
        WAIT_TYPE waitType = (WAIT_TYPE)StackFrame->Params[2];
        BOOLEAN alertable = !!StackFrame->Params[3];

        if (numberOfHandles > MAXIMUM_WAIT_OBJECTS)
        {
            numberOfHandles = PtrToUlong(context->PrevParams[1]);
            addressOfHandles = context->PrevParams[2];
            waitType = (WAIT_TYPE)context->PrevParams[3];
            alertable = FALSE;
        }

        PhpGetWfmoInformation(
            context->ProcessHandle,
            TRUE, // on x64 this function is only called for WOW64 processes
            numberOfHandles,
            addressOfHandles,
            waitType,
            alertable,
            &context->StringBuilder
            );
    }
    else if (
        NT_FUNC_MATCH("WaitForSingleObject") ||
        FUNC_MATCH("kernel32.dll!WaitForSingleObject")
        )
    {
        HANDLE handle = StackFrame->Params[0];
        BOOLEAN alertable = !!StackFrame->Params[1];

        if ((ULONG_PTR)handle % 4 != 0 || !handle)
        {
            handle = context->PrevParams[1];
            alertable = !!context->PrevParams[2];
        }

        PhAppendFormatStringBuilder(
            &context->StringBuilder,
            L"Thread is waiting (%s) for:\r\n",
            alertable ? L"alertable" : L"non-alertable"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else if (NT_FUNC_MATCH("WaitForWorkViaWorkerFactory"))
    {
        HANDLE handle = StackFrame->Params[0];

        PhAppendStringBuilder2(
            &context->StringBuilder,
            L"Thread is waiting for work from a worker factory:\r\n"
            );
        PhAppendStringBuilder(
            &context->StringBuilder,
            &PhpaGetHandleString(context->ProcessHandle, handle)->sr
            );
    }
    else
    {
        context->Found = FALSE;
    }

    PhDereferenceObject(name);
    memcpy(&context->PrevParams, StackFrame->Params, sizeof(StackFrame->Params));

    return !context->Found;
}