Exemple #1
0
VOID PhpUpdateThreadDetails(
    _In_ HWND hwndDlg,
    _In_ PPH_THREADS_CONTEXT Context,
    _In_ BOOLEAN Force
    )
{
    PPH_THREAD_ITEM *threads;
    ULONG numberOfThreads;
    PPH_THREAD_ITEM threadItem;
    PPH_STRING startModule = NULL;
    PPH_STRING started = NULL;
    WCHAR kernelTime[PH_TIMESPAN_STR_LEN_1] = L"N/A";
    WCHAR userTime[PH_TIMESPAN_STR_LEN_1] = L"N/A";
    PPH_STRING contextSwitches = NULL;
    PPH_STRING cycles = NULL;
    PPH_STRING state = NULL;
    WCHAR priority[PH_INT32_STR_LEN_1] = L"N/A";
    WCHAR basePriority[PH_INT32_STR_LEN_1] = L"N/A";
    PWSTR ioPriority = L"N/A";
    PWSTR pagePriority = L"N/A";
    WCHAR idealProcessor[PH_INT32_STR_LEN + 1 + PH_INT32_STR_LEN + 1] = L"N/A";
    HANDLE threadHandle;
    SYSTEMTIME time;
    IO_PRIORITY_HINT ioPriorityInteger;
    ULONG pagePriorityInteger;
    PROCESSOR_NUMBER idealProcessorNumber;
    ULONG suspendCount;

    PhGetSelectedThreadItems(&Context->ListContext, &threads, &numberOfThreads);

    if (numberOfThreads == 1)
        threadItem = threads[0];
    else
        threadItem = NULL;

    PhFree(threads);

    if (numberOfThreads != 1 && !Force)
        return;

    if (numberOfThreads == 1)
    {
        startModule = threadItem->StartAddressFileName;

        PhLargeIntegerToLocalSystemTime(&time, &threadItem->CreateTime);
        started = PhaFormatDateTime(&time);

        PhPrintTimeSpan(kernelTime, threadItem->KernelTime.QuadPart, PH_TIMESPAN_HMSM);
        PhPrintTimeSpan(userTime, threadItem->UserTime.QuadPart, PH_TIMESPAN_HMSM);

        contextSwitches = PhaFormatUInt64(threadItem->ContextSwitchesDelta.Value, TRUE);

        if (WINDOWS_HAS_CYCLE_TIME)
            cycles = PhaFormatUInt64(threadItem->CyclesDelta.Value, TRUE);

        if (threadItem->State != Waiting)
        {
            if ((ULONG)threadItem->State < MaximumThreadState)
                state = PhaCreateString(PhKThreadStateNames[(ULONG)threadItem->State]);
            else
                state = PhaCreateString(L"Unknown");
        }
        else
        {
            if ((ULONG)threadItem->WaitReason < MaximumWaitReason)
                state = PhaConcatStrings2(L"Wait:", PhKWaitReasonNames[(ULONG)threadItem->WaitReason]);
            else
                state = PhaCreateString(L"Waiting");
        }

        PhPrintInt32(priority, threadItem->Priority);
        PhPrintInt32(basePriority, threadItem->BasePriority);

        if (NT_SUCCESS(PhOpenThread(&threadHandle, ThreadQueryAccess, threadItem->ThreadId)))
        {
            if (NT_SUCCESS(PhGetThreadIoPriority(threadHandle, &ioPriorityInteger)) &&
                ioPriorityInteger < MaxIoPriorityTypes)
            {
                ioPriority = PhIoPriorityHintNames[ioPriorityInteger];
            }

            if (NT_SUCCESS(PhGetThreadPagePriority(threadHandle, &pagePriorityInteger)) &&
                pagePriorityInteger <= MEMORY_PRIORITY_NORMAL)
            {
                pagePriority = PhPagePriorityNames[pagePriorityInteger];
            }

            if (NT_SUCCESS(NtQueryInformationThread(threadHandle, ThreadIdealProcessorEx, &idealProcessorNumber, sizeof(PROCESSOR_NUMBER), NULL)))
            {
                PH_FORMAT format[3];

                PhInitFormatU(&format[0], idealProcessorNumber.Group);
                PhInitFormatC(&format[1], ':');
                PhInitFormatU(&format[2], idealProcessorNumber.Number);
                PhFormatToBuffer(format, 3, idealProcessor, sizeof(idealProcessor), NULL);
            }

            if (threadItem->WaitReason == Suspended && NT_SUCCESS(NtQueryInformationThread(threadHandle, ThreadSuspendCount, &suspendCount, sizeof(ULONG), NULL)))
            {
                PH_FORMAT format[4];

                PhInitFormatSR(&format[0], state->sr);
                PhInitFormatS(&format[1], L" (");
                PhInitFormatU(&format[2], suspendCount);
                PhInitFormatS(&format[3], L")");
                state = PH_AUTO(PhFormat(format, 4, 30));
            }

            NtClose(threadHandle);
        }
    }

    if (Force)
    {
        // These don't change...

        SetDlgItemText(hwndDlg, IDC_STARTMODULE, PhGetStringOrEmpty(startModule));
        EnableWindow(GetDlgItem(hwndDlg, IDC_OPENSTARTMODULE), !!startModule);

        SetDlgItemText(hwndDlg, IDC_STARTED, PhGetStringOrDefault(started, L"N/A"));
    }

    SetDlgItemText(hwndDlg, IDC_KERNELTIME, kernelTime);
    SetDlgItemText(hwndDlg, IDC_USERTIME, userTime);
    SetDlgItemText(hwndDlg, IDC_CONTEXTSWITCHES, PhGetStringOrDefault(contextSwitches, L"N/A"));
    SetDlgItemText(hwndDlg, IDC_CYCLES, PhGetStringOrDefault(cycles, L"N/A"));
    SetDlgItemText(hwndDlg, IDC_STATE, PhGetStringOrDefault(state, L"N/A"));
    SetDlgItemText(hwndDlg, IDC_PRIORITY, priority);
    SetDlgItemText(hwndDlg, IDC_BASEPRIORITY, basePriority);
    SetDlgItemText(hwndDlg, IDC_IOPRIORITY, ioPriority);
    SetDlgItemText(hwndDlg, IDC_PAGEPRIORITY, pagePriority);
    SetDlgItemText(hwndDlg, IDC_IDEALPROCESSOR, idealProcessor);
}
INT_PTR CALLBACK DotNetAsmPageDlgProc(
    __in HWND hwndDlg,
    __in UINT uMsg,
    __in WPARAM wParam,
    __in LPARAM lParam
)
{
    LPPROPSHEETPAGE propSheetPage;
    PPH_PROCESS_PROPPAGECONTEXT propPageContext;
    PPH_PROCESS_ITEM processItem;
    PASMPAGE_CONTEXT context;

    if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem))
    {
        context = propPageContext->Context;
    }
    else
    {
        return FALSE;
    }

    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        ULONG result = 0;
        PPH_STRING settings;
        LARGE_INTEGER timeout;
        HWND tnHandle;

        context = PhAllocate(sizeof(ASMPAGE_CONTEXT));
        memset(context, 0, sizeof(ASMPAGE_CONTEXT));
        propPageContext->Context = context;
        context->WindowHandle = hwndDlg;
        context->ProcessItem = processItem;

        context->ClrVersions = 0;
        PhGetProcessIsDotNetEx(processItem->ProcessId, NULL, 0, NULL, &context->ClrVersions);

        context->NodeList = PhCreateList(64);
        context->NodeRootList = PhCreateList(2);

        tnHandle = GetDlgItem(hwndDlg, IDC_LIST);
        context->TnHandle = tnHandle;

        TreeNew_SetRedraw(tnHandle, FALSE);

        TreeNew_SetCallback(tnHandle, DotNetAsmTreeNewCallback, context);
        TreeNew_SetExtendedFlags(tnHandle, TN_FLAG_ITEM_DRAG_SELECT, TN_FLAG_ITEM_DRAG_SELECT);
        PhSetControlTheme(tnHandle, L"explorer");
        SendMessage(TreeNew_GetTooltips(tnHandle), TTM_SETMAXTIPWIDTH, 0, MAXSHORT);
        PhAddTreeNewColumn(tnHandle, DNATNC_STRUCTURE, TRUE, L"Structure", 240, PH_ALIGN_LEFT, -2, 0);
        PhAddTreeNewColumn(tnHandle, DNATNC_ID, TRUE, L"ID", 50, PH_ALIGN_RIGHT, 0, DT_RIGHT);
        PhAddTreeNewColumn(tnHandle, DNATNC_FLAGS, TRUE, L"Flags", 120, PH_ALIGN_LEFT, 1, 0);
        PhAddTreeNewColumn(tnHandle, DNATNC_PATH, TRUE, L"Path", 600, PH_ALIGN_LEFT, 2, 0); // don't use path ellipsis - the user already has the base file name
        PhAddTreeNewColumn(tnHandle, DNATNC_NATIVEPATH, TRUE, L"Native Image Path", 600, PH_ALIGN_LEFT, 3, 0);

        settings = PhGetStringSetting(SETTING_NAME_ASM_TREE_LIST_COLUMNS);
        PhCmLoadSettings(tnHandle, &settings->sr);
        PhDereferenceObject(settings);

        SetCursor(LoadCursor(NULL, IDC_WAIT));

        if (context->ClrVersions & PH_CLR_VERSION_1_0)
        {
            AddFakeClrNode(context, L"CLR v1.0.3705"); // what PE displays
        }

        if (context->ClrVersions & PH_CLR_VERSION_1_1)
        {
            AddFakeClrNode(context, L"CLR v1.1.4322");
        }

        timeout.QuadPart = -10 * PH_TIMEOUT_SEC;

        if (context->ClrVersions & PH_CLR_VERSION_2_0)
        {
            context->ClrV2Node = AddFakeClrNode(context, L"CLR v2.0.50727");
            result = UpdateDotNetTraceInfoWithTimeout(context, TRUE, &timeout);
        }

        if (context->ClrVersions & PH_CLR_VERSION_4_ABOVE)
        {
            result = UpdateDotNetTraceInfoWithTimeout(context, FALSE, &timeout);
        }

        TreeNew_NodesStructured(tnHandle);

        TreeNew_SetRedraw(tnHandle, TRUE);
        SetCursor(LoadCursor(NULL, IDC_ARROW));

        if (result != 0)
        {
            ShowWindow(tnHandle, SW_HIDE);
            ShowWindow(GetDlgItem(hwndDlg, IDC_ERROR), SW_SHOW);

            if (result == ERROR_ACCESS_DENIED)
            {
                SetDlgItemText(hwndDlg, IDC_ERROR, L"Unable to start the event tracing session. Make sure Process Hacker is running with administrative privileges.");
            }
            else
            {
                SetDlgItemText(hwndDlg, IDC_ERROR,
                               PhaConcatStrings2(L"Unable to start the event tracing session: %s", PhGetStringOrDefault(PhGetWin32Message(result), L"Unknown error"))->Buffer);
            }
        }
    }
    break;
    case WM_DESTROY:
    {
        PPH_STRING settings;
        ULONG i;

        settings = PhCmSaveSettings(context->TnHandle);
        PhSetStringSetting2(SETTING_NAME_ASM_TREE_LIST_COLUMNS, &settings->sr);
        PhDereferenceObject(settings);

        for (i = 0; i < context->NodeList->Count; i++)
            DestroyNode(context->NodeList->Items[i]);

        PhDereferenceObject(context->NodeList);
        PhDereferenceObject(context->NodeRootList);
        PhFree(context);

        PhPropPageDlgProcDestroy(hwndDlg);
    }
    break;
    case WM_SHOWWINDOW:
    {
        PPH_LAYOUT_ITEM dialogItem;

        if (dialogItem = PhBeginPropPageLayout(hwndDlg, propPageContext))
        {
            PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL);
            PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_ERROR), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
            PhEndPropPageLayout(hwndDlg, propPageContext);
        }
    }
    break;
    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case ID_COPY:
        {
            PPH_STRING text;

            text = PhGetTreeNewText(context->TnHandle, 0);
            PhSetClipboardStringEx(context->TnHandle, text->Buffer, text->Length);
            PhDereferenceObject(text);
        }
        break;
        }
    }
    break;
    }

    return FALSE;
}