NTSTATUS PhpGetObjectName(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __out PPH_STRING *ObjectName
    )
{
    NTSTATUS status;
    POBJECT_NAME_INFORMATION buffer;
    ULONG bufferSize;
    ULONG attempts = 8;

    bufferSize = 0x200;
    buffer = PhAllocate(bufferSize);

    // A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
    do
    {
        if (KphIsConnected())
        {
            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectNameInformation,
                buffer,
                bufferSize,
                &bufferSize
                );
        }
        else
        {
            status = NtQueryObject(
                Handle,
                ObjectNameInformation,
                buffer,
                bufferSize,
                &bufferSize
                );
        }

        if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH ||
            status == STATUS_BUFFER_TOO_SMALL)
        {
            PhFree(buffer);
            buffer = PhAllocate(bufferSize);
        }
        else
        {
            break;
        }
    } while (--attempts);

    if (NT_SUCCESS(status))
    {
        *ObjectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length);
    }

    PhFree(buffer);

    return status;
}
Exemple #2
0
VOID PhShowHiddenProcessesDialog(
    VOID
    )
{
    if (!KphIsConnected())
    {
        PhShowWarning(
            PhMainWndHandle,
            L"Hidden process detection cannot function properly without KProcessHacker. "
            L"Make sure Process Hacker is running with administrative privileges."
            );
    }

    if (!PhHiddenProcessesWindowHandle)
    {
        PhHiddenProcessesWindowHandle = CreateDialog(
            PhInstanceHandle,
            MAKEINTRESOURCE(IDD_HIDDENPROCESSES),
            PhMainWndHandle,
            PhpHiddenProcessesDlgProc
            );
    }

    if (!IsWindowVisible(PhHiddenProcessesWindowHandle))
        ShowWindow(PhHiddenProcessesWindowHandle, SW_SHOW);
    else
        SetForegroundWindow(PhHiddenProcessesWindowHandle);
}
Exemple #3
0
static NTSTATUS NTAPI TerminatorTTGeneric(
    _In_ HANDLE ProcessId,
    _In_ BOOLEAN UseKph,
    _In_ BOOLEAN UseKphDangerous
    )
{
    NTSTATUS status;
    PVOID processes;
    PSYSTEM_PROCESS_INFORMATION process;
    ULONG i;

    if ((UseKph || UseKphDangerous) && !KphIsConnected())
        return STATUS_NOT_SUPPORTED;

    if (!NT_SUCCESS(status = PhEnumProcesses(&processes)))
        return status;

    process = PhFindProcessInformation(processes, ProcessId);

    if (!process)
    {
        PhFree(processes);
        return STATUS_INVALID_CID;
    }

    for (i = 0; i < process->NumberOfThreads; i++)
    {
        HANDLE threadHandle;

        if (NT_SUCCESS(PhOpenThread(
            &threadHandle,
            THREAD_TERMINATE,
            process->Threads[i].ClientId.UniqueThread
            )))
        {
            if (UseKphDangerous)
                KphTerminateThreadUnsafe(threadHandle, STATUS_SUCCESS);
            else if (UseKph)
                KphTerminateThread(threadHandle, STATUS_SUCCESS);
            else
                NtTerminateThread(threadHandle, STATUS_SUCCESS);

            NtClose(threadHandle);
        }
    }

    PhFree(processes);

    return STATUS_SUCCESS;
}
NTSTATUS PhpGetObjectBasicInformation(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __out POBJECT_BASIC_INFORMATION BasicInformation
    )
{
    NTSTATUS status;

    if (KphIsConnected())
    {
        status = KphQueryInformationObject(
            ProcessHandle,
            Handle,
            KphObjectBasicInformation,
            BasicInformation,
            sizeof(OBJECT_BASIC_INFORMATION),
            NULL
            );

        if (NT_SUCCESS(status))
        {
            // The object was referenced in KProcessHacker, so
            // we need to subtract 1 from the pointer count.
            BasicInformation->PointerCount -= 1;
        }
    }
    else
    {
        status = NtQueryObject(
            Handle,
            ObjectBasicInformation,
            BasicInformation,
            sizeof(OBJECT_BASIC_INFORMATION),
            NULL
            );

        if (NT_SUCCESS(status))
        {
            // The object was referenced in NtQueryObject and
            // a handle was opened to the object. We need to
            // subtract 1 from the pointer count, then subtract
            // 1 from both counts.
            BasicInformation->HandleCount -= 1;
            BasicInformation->PointerCount -= 2;
        }
    }

    return status;
}
Exemple #5
0
static NTSTATUS PhpDuplicateHandleFromProcess(
    _Out_ PHANDLE Handle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_opt_ PVOID Context
    )
{
    NTSTATUS status;
    PHANDLE_PROPERTIES_CONTEXT context = Context;
    HANDLE processHandle;

    if (!NT_SUCCESS(status = PhOpenProcess(
        &processHandle,
        PROCESS_DUP_HANDLE,
        context->ProcessId
        )))
        return status;

    if (KphIsConnected() && PhEqualString2(context->HandleItem->TypeName, L"File", TRUE))
    {
        status = PhCallKphDuplicateObjectWithTimeout(
            processHandle,
            context->HandleItem->Handle,
            NtCurrentProcess(),
            Handle,
            DesiredAccess,
            0,
            0
            );
    }
    else
    {
        status = PhDuplicateObject(
            processHandle,
            context->HandleItem->Handle,
            NtCurrentProcess(),
            Handle,
            DesiredAccess,
            0,
            0
            );
    }

    NtClose(processHandle);

    return status;
}
Exemple #6
0
static NTSTATUS NTAPI TerminatorTP3(
    _In_ HANDLE ProcessId
    )
{
    NTSTATUS status;
    HANDLE processHandle;

    if (!KphIsConnected())
        return STATUS_NOT_SUPPORTED;

    if (NT_SUCCESS(status = PhOpenProcess(
        &processHandle,
        SYNCHRONIZE, // KPH doesn't require any access for this operation
        ProcessId
        )))
    {
        status = KphTerminateProcess(processHandle, STATUS_SUCCESS);

        NtClose(processHandle);
    }

    return status;
}
Exemple #7
0
VOID PhSipInitializeMemoryDialog(
    VOID
    )
{
    PhInitializeDelta(&PagedAllocsDelta);
    PhInitializeDelta(&PagedFreesDelta);
    PhInitializeDelta(&NonPagedAllocsDelta);
    PhInitializeDelta(&NonPagedFreesDelta);
    PhInitializeDelta(&PageFaultsDelta);
    PhInitializeDelta(&PageReadsDelta);
    PhInitializeDelta(&PagefileWritesDelta);
    PhInitializeDelta(&MappedWritesDelta);

    PhInitializeGraphState(&CommitGraphState);
    PhInitializeGraphState(&PhysicalGraphState);

    MemoryTicked = 0;

    if (!MmAddressesInitialized && KphIsConnected())
    {
        PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), PhSipLoadMmAddresses, NULL);
        MmAddressesInitialized = TRUE;
    }
}
Exemple #8
0
static NTSTATUS PhpFindObjectsThreadStart(
    _In_ PVOID Parameter
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSYSTEM_HANDLE_INFORMATION_EX handles;
    PPH_HASHTABLE processHandleHashtable;
    PVOID processes;
    PSYSTEM_PROCESS_INFORMATION process;
    ULONG i;

    // Refuse to search with no filter.
    if (SearchString->Length == 0)
        goto Exit;

    // Try to get a search pointer from the search string.
    UseSearchPointer = PhStringToInteger64(&SearchString->sr, 0, &SearchPointer);

    _wcsupr(SearchString->Buffer);

    if (NT_SUCCESS(status = PhEnumHandlesEx(&handles)))
    {
        static PH_INITONCE initOnce = PH_INITONCE_INIT;
        static ULONG fileObjectTypeIndex = -1;

        BOOLEAN useWorkQueue = FALSE;
        PH_WORK_QUEUE workQueue;
        processHandleHashtable = PhCreateSimpleHashtable(8);

        if (!KphIsConnected() && WindowsVersion >= WINDOWS_VISTA)
        {
            useWorkQueue = TRUE;
            PhInitializeWorkQueue(&workQueue, 1, 20, 1000);

            if (PhBeginInitOnce(&initOnce))
            {
                UNICODE_STRING fileTypeName;

                RtlInitUnicodeString(&fileTypeName, L"File");
                fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName);
                PhEndInitOnce(&initOnce);
            }
        }

        for (i = 0; i < handles->NumberOfHandles; i++)
        {
            PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = &handles->Handles[i];
            PVOID *processHandlePtr;
            HANDLE processHandle;

            if (SearchStop)
                break;

            // Open a handle to the process if we don't already have one.

            processHandlePtr = PhFindItemSimpleHashtable(
                processHandleHashtable,
                (PVOID)handleInfo->UniqueProcessId
                );

            if (processHandlePtr)
            {
                processHandle = (HANDLE)*processHandlePtr;
            }
            else
            {
                if (NT_SUCCESS(PhOpenProcess(
                    &processHandle,
                    PROCESS_DUP_HANDLE,
                    (HANDLE)handleInfo->UniqueProcessId
                    )))
                {
                    PhAddItemSimpleHashtable(
                        processHandleHashtable,
                        (PVOID)handleInfo->UniqueProcessId,
                        processHandle
                        );
                }
                else
                {
                    continue;
                }
            }

            if (useWorkQueue && handleInfo->ObjectTypeIndex == (USHORT)fileObjectTypeIndex)
            {
                PSEARCH_HANDLE_CONTEXT searchHandleContext;

                searchHandleContext = PhAllocate(sizeof(SEARCH_HANDLE_CONTEXT));
                searchHandleContext->NeedToFree = TRUE;
                searchHandleContext->HandleInfo = handleInfo;
                searchHandleContext->ProcessHandle = processHandle;
                PhQueueItemWorkQueue(&workQueue, SearchHandleFunction, searchHandleContext);
            }
            else
            {
                SEARCH_HANDLE_CONTEXT searchHandleContext;

                searchHandleContext.NeedToFree = FALSE;
                searchHandleContext.HandleInfo = handleInfo;
                searchHandleContext.ProcessHandle = processHandle;
                SearchHandleFunction(&searchHandleContext);
            }
        }

        if (useWorkQueue)
        {
            PhWaitForWorkQueue(&workQueue);
            PhDeleteWorkQueue(&workQueue);
        }

        {
            PPH_KEY_VALUE_PAIR entry;

            i = 0;

            while (PhEnumHashtable(processHandleHashtable, &entry, &i))
                NtClose((HANDLE)entry->Value);
        }

        PhDereferenceObject(processHandleHashtable);
        PhFree(handles);
    }

    if (NT_SUCCESS(PhEnumProcesses(&processes)))
    {
        process = PH_FIRST_PROCESS(processes);

        do
        {
            PhEnumGenericModules(
                process->UniqueProcessId,
                NULL,
                PH_ENUM_GENERIC_MAPPED_FILES | PH_ENUM_GENERIC_MAPPED_IMAGES,
                EnumModulesCallback,
                (PVOID)process->UniqueProcessId
                );
        } while (process = PH_NEXT_PROCESS(process));

        PhFree(processes);
    }

Exit:
    PostMessage(PhFindObjectsWindowHandle, WM_PH_SEARCH_FINISHED, status, 0);

    return STATUS_SUCCESS;
}
VOID PhShowThreadStackDialog(
    _In_ HWND ParentWindowHandle,
    _In_ HANDLE ProcessId,
    _In_ HANDLE ThreadId,
    _In_ PPH_SYMBOL_PROVIDER SymbolProvider
    )
{
    NTSTATUS status;
    THREAD_STACK_CONTEXT threadStackContext;
    HANDLE threadHandle = NULL;

    // If the user is trying to view a system thread stack
    // but KProcessHacker is not loaded, show an error message.
    if (ProcessId == SYSTEM_PROCESS_ID && !KphIsConnected())
    {
        PhShowError(ParentWindowHandle, KPH_ERROR_MESSAGE);
        return;
    }

    memset(&threadStackContext, 0, sizeof(THREAD_STACK_CONTEXT));
    threadStackContext.ProcessId = ProcessId;
    threadStackContext.ThreadId = ThreadId;
    threadStackContext.SymbolProvider = SymbolProvider;

    if (!NT_SUCCESS(status = PhOpenThread(
        &threadHandle,
        THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME,
        ThreadId
        )))
    {
        if (KphIsConnected())
        {
            status = PhOpenThread(
                &threadHandle,
                ThreadQueryAccess,
                ThreadId
                );
        }
    }

    if (!NT_SUCCESS(status))
    {
        PhShowStatus(ParentWindowHandle, L"Unable to open the thread", status, 0);
        return;
    }

    threadStackContext.ThreadHandle = threadHandle;
    threadStackContext.List = PhCreateList(10);
    threadStackContext.NewList = PhCreateList(10);
    PhInitializeQueuedLock(&threadStackContext.StatusLock);

    DialogBoxParam(
        PhInstanceHandle,
        MAKEINTRESOURCE(IDD_THRDSTACK),
        ParentWindowHandle,
        PhpThreadStackDlgProc,
        (LPARAM)&threadStackContext
        );

    PhSwapReference(&threadStackContext.StatusMessage, NULL);
    PhDereferenceObject(threadStackContext.NewList);
    PhDereferenceObject(threadStackContext.List);

    if (threadStackContext.ThreadHandle)
        NtClose(threadStackContext.ThreadHandle);
}
Exemple #10
0
VOID PhpThreadProviderUpdate(
    __in PPH_THREAD_PROVIDER ThreadProvider,
    __in PVOID ProcessInformation
    )
{
    PPH_THREAD_PROVIDER threadProvider = ThreadProvider;
    PSYSTEM_PROCESS_INFORMATION process;
    SYSTEM_PROCESS_INFORMATION localProcess;
    PSYSTEM_THREAD_INFORMATION threads;
    ULONG numberOfThreads;
    ULONG i;

    process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId);

    if (!process)
    {
        // The process doesn't exist anymore. Pretend it does but
        // has no threads.
        process = &localProcess;
        process->NumberOfThreads = 0;
    }

    threads = process->Threads;
    numberOfThreads = process->NumberOfThreads;

    // System Idle Process has one thread per CPU.
    // They all have a TID of 0, but we can't have
    // multiple TIDs, so we'll assign unique TIDs.
    if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID)
    {
        for (i = 0; i < numberOfThreads; i++)
        {
            threads[i].ClientId.UniqueThread = (HANDLE)i;
        }
    }

    // Look for dead threads.
    {
        PPH_LIST threadsToRemove = NULL;
        ULONG enumerationKey = 0;
        PPH_THREAD_ITEM *threadItem;

        while (PhEnumHashtable(threadProvider->ThreadHashtable, (PPVOID)&threadItem, &enumerationKey))
        {
            BOOLEAN found = FALSE;

            // Check if the thread still exists.
            for (i = 0; i < numberOfThreads; i++)
            {
                PSYSTEM_THREAD_INFORMATION thread = &threads[i];

                if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread)
                {
                    found = TRUE;
                    break;
                }
            }

            if (!found)
            {
                // Raise the thread removed event.
                PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem);

                if (!threadsToRemove)
                    threadsToRemove = PhCreateList(2);

                PhAddItemList(threadsToRemove, *threadItem);
            }
        }

        if (threadsToRemove)
        {
            PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock);

            for (i = 0; i < threadsToRemove->Count; i++)
            {
                PhpRemoveThreadItem(
                    threadProvider,
                    (PPH_THREAD_ITEM)threadsToRemove->Items[i]
                    );
            }

            PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock);
            PhDereferenceObject(threadsToRemove);
        }
    }

    // Go through the queued thread query data.
    {
        PSLIST_ENTRY entry;
        PPH_THREAD_QUERY_DATA data;

        entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead);

        while (entry)
        {
            data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry);
            entry = entry->Next;

            if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString)
            {
                PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString);
                data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel;
            }

            PhSwapReference2(&data->ThreadItem->ServiceName, data->ServiceName);

            data->ThreadItem->JustResolved = TRUE;

            if (data->StartAddressString) PhDereferenceObject(data->StartAddressString);
            PhDereferenceObject(data->ThreadItem);
            PhFree(data);
        }
    }

    // Look for new threads and update existing ones.
    for (i = 0; i < numberOfThreads; i++)
    {
        PSYSTEM_THREAD_INFORMATION thread = &threads[i];
        PPH_THREAD_ITEM threadItem;

        threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread);

        if (!threadItem)
        {
            ULONG64 cycles;
            PVOID startAddress = NULL;

            threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread);

            threadItem->CreateTime = thread->CreateTime;
            threadItem->KernelTime = thread->KernelTime;
            threadItem->UserTime = thread->UserTime;

            PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches);
            threadItem->Priority = thread->Priority;
            threadItem->BasePriority = thread->BasePriority;
            threadItem->State = (KTHREAD_STATE)thread->ThreadState;
            threadItem->WaitReason = thread->WaitReason;

            // Try to open a handle to the thread.
            if (!NT_SUCCESS(PhOpenThread(
                &threadItem->ThreadHandle,
                THREAD_QUERY_INFORMATION,
                threadItem->ThreadId
                )))
            {
                PhOpenThread(
                    &threadItem->ThreadHandle,
                    ThreadQueryAccess,
                    threadItem->ThreadId
                    );
            }

            // Get the cycle count.
            if (NT_SUCCESS(PhpGetThreadCycleTime(
                threadProvider,
                threadItem,
                &cycles
                )))
            {
                PhUpdateDelta(&threadItem->CyclesDelta, cycles);
            }

            // Initialize the CPU time deltas.
            PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart);
            PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart);

            // Try to get the start address.

            if (threadItem->ThreadHandle)
            {
                NtQueryInformationThread(
                    threadItem->ThreadHandle,
                    ThreadQuerySetWin32StartAddress,
                    &startAddress,
                    sizeof(PVOID),
                    NULL
                    );
            }

            if (!startAddress)
                startAddress = thread->StartAddress;

            threadItem->StartAddress = (ULONG64)startAddress;

            // Get the Win32 priority.
            threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle);

            if (PhTestEvent(&threadProvider->SymbolsLoadedEvent))
            {
                threadItem->StartAddressString = PhpGetThreadBasicStartAddress(
                    threadProvider,
                    threadItem->StartAddress,
                    &threadItem->StartAddressResolveLevel
                    );
            }

            if (!threadItem->StartAddressString)
            {
                threadItem->StartAddressResolveLevel = PhsrlAddress;
                threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2);
                PhPrintPointer(
                    threadItem->StartAddressString->Buffer,
                    (PVOID)threadItem->StartAddress
                    );
                PhTrimToNullTerminatorString(threadItem->StartAddressString);
            }

            PhpQueueThreadQuery(threadProvider, threadItem);

            // Is it a GUI thread?

            if (threadItem->ThreadHandle && KphIsConnected())
            {
                PVOID win32Thread;

                if (NT_SUCCESS(KphQueryInformationThread(
                    threadItem->ThreadHandle,
                    KphThreadWin32Thread,
                    &win32Thread,
                    sizeof(PVOID),
                    NULL
                    )))
                {
                    threadItem->IsGuiThread = win32Thread != NULL;
                }
            }

            // Add the thread item to the hashtable.
            PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock);
            PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem);
            PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock);

            // Raise the thread added event.
            PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem);
        }
        else
        {
            BOOLEAN modified = FALSE;

            if (threadItem->JustResolved)
                modified = TRUE;

            threadItem->KernelTime = thread->KernelTime;
            threadItem->UserTime = thread->UserTime;

            threadItem->Priority = thread->Priority;
            threadItem->BasePriority = thread->BasePriority;

            threadItem->State = (KTHREAD_STATE)thread->ThreadState;

            if (threadItem->WaitReason != thread->WaitReason)
            {
                threadItem->WaitReason = thread->WaitReason;
                modified = TRUE;
            }

            // If the resolve level is only at address, it probably
            // means symbols weren't loaded the last time we
            // tried to get the start address. Try again.
            if (threadItem->StartAddressResolveLevel == PhsrlAddress)
            {
                if (PhTestEvent(&threadProvider->SymbolsLoadedEvent))
                {
                    PPH_STRING newStartAddressString;

                    newStartAddressString = PhpGetThreadBasicStartAddress(
                        threadProvider,
                        threadItem->StartAddress,
                        &threadItem->StartAddressResolveLevel
                        );

                    PhSwapReference2(
                        &threadItem->StartAddressString,
                        newStartAddressString
                        );

                    modified = TRUE;
                }
            }

            // If we couldn't resolve the start address to a
            // module+offset, use the StartAddress instead
            // of the Win32StartAddress and try again.
            // Note that we check the resolve level again
            // because we may have changed it in the previous
            // block.
            if (
                threadItem->JustResolved &&
                threadItem->StartAddressResolveLevel == PhsrlAddress
                )
            {
                if (threadItem->StartAddress != (ULONG64)thread->StartAddress)
                {
                    threadItem->StartAddress = (ULONG64)thread->StartAddress;
                    PhpQueueThreadQuery(threadProvider, threadItem);
                }
            }

            // Update the context switch count.
            {
                ULONG oldDelta;

                oldDelta = threadItem->ContextSwitchesDelta.Delta;
                PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches);

                if (threadItem->ContextSwitchesDelta.Delta != oldDelta)
                {
                    modified = TRUE;
                }
            }

            // Update the cycle count.
            {
                ULONG64 cycles;
                ULONG64 oldDelta;

                oldDelta = threadItem->CyclesDelta.Delta;

                if (NT_SUCCESS(PhpGetThreadCycleTime(
                    threadProvider,
                    threadItem,
                    &cycles
                    )))
                {
                    PhUpdateDelta(&threadItem->CyclesDelta, cycles);

                    if (threadItem->CyclesDelta.Delta != oldDelta)
                    {
                        modified = TRUE;
                    }
                }
            }

            // Update the CPU time deltas.
            PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart);
            PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart);

            // Update the CPU usage.
            // If the cycle time isn't available, we'll fall back to using the CPU time.
            if (PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle))
            {
                threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta;
            }
            else
            {
                threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) /
                    (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta);
            }

            // Update the Win32 priority.
            {
                LONG oldPriorityWin32 = threadItem->PriorityWin32;

                threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle);

                if (threadItem->PriorityWin32 != oldPriorityWin32)
                {
                    modified = TRUE;
                }
            }

            // Update the GUI thread status.

            if (threadItem->ThreadHandle && KphIsConnected())
            {
                PVOID win32Thread;

                if (NT_SUCCESS(KphQueryInformationThread(
                    threadItem->ThreadHandle,
                    KphThreadWin32Thread,
                    &win32Thread,
                    sizeof(PVOID),
                    NULL
                    )))
                {
                    BOOLEAN oldIsGuiThread = threadItem->IsGuiThread;

                    threadItem->IsGuiThread = win32Thread != NULL;

                    if (threadItem->IsGuiThread != oldIsGuiThread)
                        modified = TRUE;
                }
            }

            threadItem->JustResolved = FALSE;

            if (modified)
            {
                // Raise the thread modified event.
                PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem);
            }

            PhDereferenceObject(threadItem);
        }
    }

    PhInvokeCallback(&threadProvider->UpdatedEvent, NULL);
    threadProvider->RunId++;
}
Exemple #11
0
VOID PhSipUpdateMemoryPanel(
    VOID
    )
{
    PWSTR pagedLimit;
    PWSTR nonPagedLimit;
    SYSTEM_MEMORY_LIST_INFORMATION memoryListInfo;

    // Commit charge

    SetDlgItemText(MemoryPanel, IDC_ZCOMMITCURRENT_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.CommittedPages, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZCOMMITPEAK_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.PeakCommitment, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZCOMMITLIMIT_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.CommitLimit, PAGE_SIZE), -1)->Buffer);

    // Physical memory

    SetDlgItemText(MemoryPanel, IDC_ZPHYSICALCURRENT_V,
        PhaFormatSize(UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages - PhPerfInformation.AvailablePages, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZPHYSICALTOTAL_V,
        PhaFormatSize(UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages, PAGE_SIZE), -1)->Buffer);

    if (InstalledMemory != 0)
    {
        SetDlgItemText(MemoryPanel, IDC_ZPHYSICALRESERVED_V,
            PhaFormatSize(InstalledMemory * 1024 - UInt32x32To64(PhSystemBasicInformation.NumberOfPhysicalPages, PAGE_SIZE), -1)->Buffer);
    }
    else
    {
        SetDlgItemText(MemoryPanel, IDC_ZPHYSICALRESERVED_V, L"-");
    }

    SetDlgItemText(MemoryPanel, IDC_ZPHYSICALCACHEWS_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemCachePage, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZPHYSICALKERNELWS_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemCodePage, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZPHYSICALDRIVERWS_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentSystemDriverPage, PAGE_SIZE), -1)->Buffer);

    // Paged pool

    SetDlgItemText(MemoryPanel, IDC_ZPAGEDWORKINGSET_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.ResidentPagedPoolPage, PAGE_SIZE), -1)->Buffer);
    SetDlgItemText(MemoryPanel, IDC_ZPAGEDVIRTUALSIZE_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.PagedPoolPages, PAGE_SIZE), -1)->Buffer);

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGEDALLOCSDELTA_V, PhaFormatUInt64(PagedAllocsDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGEDALLOCSDELTA_V, L"-");

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGEDFREESDELTA_V, PhaFormatUInt64(PagedFreesDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGEDFREESDELTA_V, L"-");

    // Non-paged pool

    SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDUSAGE_V,
        PhaFormatSize(UInt32x32To64(PhPerfInformation.NonPagedPoolPages, PAGE_SIZE), -1)->Buffer);

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDALLOCSDELTA_V, PhaFormatUInt64(PagedAllocsDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDALLOCSDELTA_V, L"-");

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDFREESDELTA_V, PhaFormatUInt64(NonPagedFreesDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDFREESDELTA_V, L"-");

    // Pools (KPH)

    if (MmAddressesInitialized && (MmSizeOfPagedPoolInBytes || MmMaximumNonPagedPoolInBytes))
    {
        SIZE_T paged;
        SIZE_T nonPaged;

        PhSipGetPoolLimits(&paged, &nonPaged);

        if (paged != -1)
            pagedLimit = PhaFormatSize(paged, -1)->Buffer;
        else
            pagedLimit = L"N/A";

        if (nonPaged != -1)
            nonPagedLimit = PhaFormatSize(nonPaged, -1)->Buffer;
        else
            nonPagedLimit = L"N/A";
    }
    else
    {
        if (!KphIsConnected())
        {
            pagedLimit = nonPagedLimit = L"no driver";
        }
        else
        {
            pagedLimit = nonPagedLimit = L"no symbols";
        }
    }

    SetDlgItemText(MemoryPanel, IDC_ZPAGEDLIMIT_V, pagedLimit);
    SetDlgItemText(MemoryPanel, IDC_ZNONPAGEDLIMIT_V, nonPagedLimit);

    // Paging

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFAULTSDELTA_V, PhaFormatUInt64(PageFaultsDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFAULTSDELTA_V, L"-");

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEREADSDELTA_V, PhaFormatUInt64(PageReadsDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEREADSDELTA_V, L"-");

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFILEWRITESDELTA_V, PhaFormatUInt64(PagefileWritesDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGPAGEFILEWRITESDELTA_V, L"-");

    if (MemoryTicked > 1)
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGMAPPEDWRITESDELTA_V, PhaFormatUInt64(MappedWritesDelta.Delta, TRUE)->Buffer);
    else
        SetDlgItemText(MemoryPanel, IDC_ZPAGINGMAPPEDWRITESDELTA_V, L"-");

    // Memory lists

    if (NT_SUCCESS(NtQuerySystemInformation(
        SystemMemoryListInformation,
        &memoryListInfo,
        sizeof(SYSTEM_MEMORY_LIST_INFORMATION),
        NULL
        )))
    {
        ULONG_PTR standbyPageCount;
        ULONG_PTR repurposedPageCount;
        ULONG i;

        standbyPageCount = 0;
        repurposedPageCount = 0;

        for (i = 0; i < 8; i++)
        {
            standbyPageCount += memoryListInfo.PageCountByPriority[i];
            repurposedPageCount += memoryListInfo.RepurposedPagesByPriority[i];
        }

        SetDlgItemText(MemoryPanel, IDC_ZLISTZEROED_V, PhaFormatSize((ULONG64)memoryListInfo.ZeroPageCount * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTFREE_V, PhaFormatSize((ULONG64)memoryListInfo.FreePageCount * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIED_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCount * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDNOWRITE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedNoWritePageCount * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY_V, PhaFormatSize((ULONG64)standbyPageCount * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY0_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[0] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY1_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[1] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY2_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[2] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY3_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[3] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY4_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[4] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY5_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[5] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY6_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[6] * PAGE_SIZE, -1)->Buffer);
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY7_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[7] * PAGE_SIZE, -1)->Buffer);

        if (WindowsVersion >= WINDOWS_8)
            SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCountPageFile * PAGE_SIZE, -1)->Buffer);
        else
            SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A");
    }
    else
    {
        SetDlgItemText(MemoryPanel, IDC_ZLISTZEROED_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTFREE_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIED_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDNOWRITE_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY0_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY1_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY2_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY3_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY4_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY5_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY6_V, L"N/A");
        SetDlgItemText(MemoryPanel, IDC_ZLISTSTANDBY7_V, L"N/A");
    }
}
NTSTATUS PhpGetBestObjectName(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __in PPH_STRING ObjectName,
    __in PPH_STRING TypeName,
    __out PPH_STRING *BestObjectName
    )
{
    NTSTATUS status;
    PPH_STRING bestObjectName = NULL;
    PPH_GET_CLIENT_ID_NAME handleGetClientIdName;

    if (PhEqualString2(TypeName, L"EtwRegistration", TRUE))
    {
        if (KphIsConnected())
        {
            ETWREG_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectEtwRegBasicInformation,
                &basicInfo,
                sizeof(ETWREG_BASIC_INFORMATION),
                NULL
                );

            if (NT_SUCCESS(status))
            {
                static PH_STRINGREF publishersKeyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\");

                PPH_STRING guidString;
                PPH_STRING keyName;
                HANDLE keyHandle;
                PPH_STRING publisherName = NULL;

                guidString = PhFormatGuid(&basicInfo.Guid);

                // We should perform a lookup on the GUID to get the publisher name.

                keyName = PhConcatStringRef2(&publishersKeyName, &guidString->sr);

                if (NT_SUCCESS(PhOpenKey(
                    &keyHandle,
                    KEY_READ,
                    PH_KEY_LOCAL_MACHINE,
                    &keyName->sr,
                    0
                    )))
                {
                    publisherName = PhQueryRegistryString(keyHandle, NULL);

                    if (publisherName && publisherName->Length == 0)
                    {
                        PhDereferenceObject(publisherName);
                        publisherName = NULL;
                    }

                    NtClose(keyHandle);
                }

                PhDereferenceObject(keyName);

                if (publisherName)
                {
                    bestObjectName = publisherName;
                    PhDereferenceObject(guidString);
                }
                else
                {
                    bestObjectName = guidString;
                }
            }
        }
    }
    else if (PhEqualString2(TypeName, L"File", TRUE))
    {
        // Convert the file name to a DOS file name.
        bestObjectName = PhResolveDevicePrefix(ObjectName);

        if (!bestObjectName)
        {
            bestObjectName = ObjectName;
            PhReferenceObject(ObjectName);
        }
    }
    else if (PhEqualString2(TypeName, L"Key", TRUE))
    {
        bestObjectName = PhFormatNativeKeyName(ObjectName);
    }
    else if (PhEqualString2(TypeName, L"Process", TRUE))
    {
        CLIENT_ID clientId;

        clientId.UniqueThread = NULL;

        if (KphIsConnected())
        {
            PROCESS_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectProcessBasicInformation,
                &basicInfo,
                sizeof(PROCESS_BASIC_INFORMATION),
                NULL
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId.UniqueProcess = basicInfo.UniqueProcessId;
        }
        else
        {
            HANDLE dupHandle;
            PROCESS_BASIC_INFORMATION basicInfo;

            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                ProcessQueryAccess,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            status = PhGetProcessBasicInformation(dupHandle, &basicInfo);
            NtClose(dupHandle);

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId.UniqueProcess = basicInfo.UniqueProcessId;
        }

        handleGetClientIdName = PhHandleGetClientIdName;

        if (handleGetClientIdName)
            bestObjectName = handleGetClientIdName(&clientId);
    }
    else if (PhEqualString2(TypeName, L"Thread", TRUE))
    {
        CLIENT_ID clientId;

        if (KphIsConnected())
        {
            THREAD_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectThreadBasicInformation,
                &basicInfo,
                sizeof(THREAD_BASIC_INFORMATION),
                NULL
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId = basicInfo.ClientId;
        }
        else
        {
            HANDLE dupHandle;
            THREAD_BASIC_INFORMATION basicInfo;

            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                ThreadQueryAccess,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            status = PhGetThreadBasicInformation(dupHandle, &basicInfo);
            NtClose(dupHandle);

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId = basicInfo.ClientId;
        }

        handleGetClientIdName = PhHandleGetClientIdName;

        if (handleGetClientIdName)
            bestObjectName = handleGetClientIdName(&clientId);
    }
    else if (PhEqualString2(TypeName, L"TmEn", TRUE))
    {
        HANDLE dupHandle;
        ENLISTMENT_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            ENLISTMENT_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetEnlistmentBasicInformation(dupHandle, &basicInfo);
        NtClose(dupHandle);

        if (NT_SUCCESS(status))
        {
            bestObjectName = PhFormatGuid(&basicInfo.EnlistmentId);
        }
    }
    else if (PhEqualString2(TypeName, L"TmRm", TRUE))
    {
        HANDLE dupHandle;
        GUID guid;
        PPH_STRING description;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            RESOURCEMANAGER_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetResourceManagerBasicInformation(
            dupHandle,
            &guid,
            &description
            );
        NtClose(dupHandle);

        if (NT_SUCCESS(status))
        {
            if (!PhIsNullOrEmptyString(description))
            {
                bestObjectName = description;
            }
            else
            {
                bestObjectName = PhFormatGuid(&guid);

                if (description)
                    PhDereferenceObject(description);
            }
        }
    }
    else if (PhEqualString2(TypeName, L"TmTm", TRUE))
    {
        HANDLE dupHandle;
        PPH_STRING logFileName = NULL;
        TRANSACTIONMANAGER_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TRANSACTIONMANAGER_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTransactionManagerLogFileName(
            dupHandle,
            &logFileName
            );

        if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(logFileName))
        {
            bestObjectName = PhGetFileName(logFileName);
            PhDereferenceObject(logFileName);
        }
        else
        {
            if (logFileName)
                PhDereferenceObject(logFileName);

            status = PhGetTransactionManagerBasicInformation(
                dupHandle,
                &basicInfo
                );

            if (NT_SUCCESS(status))
            {
                bestObjectName = PhFormatGuid(&basicInfo.TmIdentity);
            }
        }

        NtClose(dupHandle);
    }
    else if (PhEqualString2(TypeName, L"TmTx", TRUE))
    {
        HANDLE dupHandle;
        PPH_STRING description = NULL;
        TRANSACTION_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TRANSACTION_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTransactionPropertiesInformation(
            dupHandle,
            NULL,
            NULL,
            &description
            );

        if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(description))
        {
            bestObjectName = description;
        }
        else
        {
            if (description)
                PhDereferenceObject(description);

            status = PhGetTransactionBasicInformation(
                dupHandle,
                &basicInfo
                );

            if (NT_SUCCESS(status))
            {
                bestObjectName = PhFormatGuid(&basicInfo.TransactionId);
            }
        }

        NtClose(dupHandle);
    }
    else if (PhEqualString2(TypeName, L"Token", TRUE))
    {
        HANDLE dupHandle;
        PTOKEN_USER tokenUser = NULL;
        TOKEN_STATISTICS statistics = { 0 };

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TOKEN_QUERY,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTokenUser(dupHandle, &tokenUser);
        PhGetTokenStatistics(dupHandle, &statistics);

        if (NT_SUCCESS(status))
        {
            PPH_STRING fullName;

            fullName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL);

            if (fullName)
            {
                PH_FORMAT format[3];

                PhInitFormatSR(&format[0], fullName->sr);
                PhInitFormatS(&format[1], L": 0x");
                PhInitFormatX(&format[2], statistics.AuthenticationId.LowPart);

                bestObjectName = PhFormat(format, 3, fullName->Length + 8 + 16);
                PhDereferenceObject(fullName);
            }

            PhFree(tokenUser);
        }

        NtClose(dupHandle);
    }

CleanupExit:

    if (!bestObjectName)
    {
        bestObjectName = ObjectName;
        PhReferenceObject(ObjectName);
    }

    *BestObjectName = bestObjectName;

    return STATUS_SUCCESS;
}
NTSTATUS PhpGetObjectTypeName(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __in ULONG ObjectTypeNumber,
    __out PPH_STRING *TypeName
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PPH_STRING typeName = NULL;

    // If the cache contains the object type name, use it. Otherwise,
    // query the type name.

    if (ObjectTypeNumber != -1 && ObjectTypeNumber < MAX_OBJECT_TYPE_NUMBER)
        typeName = PhObjectTypeNames[ObjectTypeNumber];

    if (typeName)
    {
        PhReferenceObject(typeName);
    }
    else
    {
        POBJECT_TYPE_INFORMATION buffer;
        ULONG returnLength = 0;
        PPH_STRING oldTypeName;

        // Get the needed buffer size.
        if (KphIsConnected())
        {
            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectTypeInformation,
                NULL,
                0,
                &returnLength
                );
        }
        else
        {
            status = NtQueryObject(
                Handle,
                ObjectTypeInformation,
                NULL,
                0,
                &returnLength
                );
        }

        if (returnLength == 0)
            return status;

        buffer = PhAllocate(returnLength);

        if (KphIsConnected())
        {
            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectTypeInformation,
                buffer,
                returnLength,
                &returnLength
                );
        }
        else
        {
            status = NtQueryObject(
                Handle,
                ObjectTypeInformation,
                buffer,
                returnLength,
                &returnLength
                );
        }

        if (!NT_SUCCESS(status))
        {
            PhFree(buffer);
            return status;
        }

        // Create a copy of the type name.
        typeName = PhCreateStringEx(buffer->TypeName.Buffer, buffer->TypeName.Length);

        if (ObjectTypeNumber != -1 && ObjectTypeNumber < MAX_OBJECT_TYPE_NUMBER)
        {
            // Try to store the type name in the cache.
            oldTypeName = _InterlockedCompareExchangePointer(
                &PhObjectTypeNames[ObjectTypeNumber],
                typeName,
                NULL
                );

            // Add a reference if we stored the type name
            // successfully.
            if (!oldTypeName)
                PhReferenceObject(typeName);
        }

        PhFree(buffer);
    }

    // At this point typeName should contain a type name
    // with one additional reference.

    *TypeName = typeName;

    return status;
}
/**
 * Gets information for a handle.
 *
 * \param ProcessHandle A handle to the process in which the
 * handle resides.
 * \param Handle The handle value.
 * \param ObjectTypeNumber The object type number of the handle.
 * You can specify -1 for this parameter if the object type number
 * is not known.
 * \param Flags Reserved.
 * \param SubStatus A variable which receives the NTSTATUS value of
 * the last component that fails. If all operations succeed, the
 * value will be STATUS_SUCCESS. If the function returns an error
 * status, this variable is not set.
 * \param BasicInformation A variable which receives basic
 * information about the object.
 * \param TypeName A variable which receives the object type name.
 * \param ObjectName A variable which receives the object name.
 * \param BestObjectName A variable which receives the formatted
 * object name.
 * \param ExtraInformation Reserved.
 *
 * \retval STATUS_INVALID_HANDLE The handle specified in
 * \c ProcessHandle or \c Handle is invalid.
 * \retval STATUS_INVALID_PARAMETER_3 The value specified in
 * \c ObjectTypeNumber is invalid.
 *
 * \remarks If \a BasicInformation or \a TypeName are specified,
 * the function will fail if either cannot be queried. \a ObjectName,
 * \a BestObjectName and \a ExtraInformation will return NULL if they
 * cannot be queried.
 */
NTSTATUS PhGetHandleInformationEx(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __in ULONG ObjectTypeNumber,
    __reserved ULONG Flags,
    __out_opt PNTSTATUS SubStatus,
    __out_opt POBJECT_BASIC_INFORMATION BasicInformation,
    __out_opt PPH_STRING *TypeName,
    __out_opt PPH_STRING *ObjectName,
    __out_opt PPH_STRING *BestObjectName,
    __reserved PVOID *ExtraInformation
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    NTSTATUS subStatus = STATUS_SUCCESS;
    HANDLE dupHandle = NULL;
    PPH_STRING typeName = NULL;
    PPH_STRING objectName = NULL;
    PPH_STRING bestObjectName = NULL;

    if (Handle == NULL || Handle == NtCurrentProcess() || Handle == NtCurrentThread())
        return STATUS_INVALID_HANDLE;
    if (ObjectTypeNumber != -1 && ObjectTypeNumber >= MAX_OBJECT_TYPE_NUMBER)
        return STATUS_INVALID_PARAMETER_3;

    // Duplicate the handle if we're not using KPH.
    if (!KphIsConnected())
    {
        // However, we obviously don't need to duplicate it
        // if the handle is in the current process.
        if (ProcessHandle != NtCurrentProcess())
        {
            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                0,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                return status;
        }
        else
        {
            dupHandle = Handle;
        }
    }

    // Get basic information.
    if (BasicInformation)
    {
        status = PhpGetObjectBasicInformation(
            ProcessHandle,
            KphIsConnected() ? Handle : dupHandle,
            BasicInformation
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;
    }

    // Exit early if we don't need to get any other information.
    if (!TypeName && !ObjectName && !BestObjectName)
        goto CleanupExit;

    // Get the type name.
    status = PhpGetObjectTypeName(
        ProcessHandle,
        KphIsConnected() ? Handle : dupHandle,
        ObjectTypeNumber,
        &typeName
        );

    if (!NT_SUCCESS(status))
        goto CleanupExit;

    // Exit early if we don't need to get the object name.
    if (!ObjectName && !BestObjectName)
        goto CleanupExit;

    // Get the object name.
    // If we're dealing with a file handle we must take
    // special precautions so we don't hang.
    if (PhEqualString2(typeName, L"File", TRUE) && !KphIsConnected())
    {
        // 0: Query normally.
        // 1: Hack.
        // 2: Fail.
        ULONG hackLevel = 1;

        // We can't use the hack on XP because hanging threads
        // can't even be terminated!
        if (WindowsVersion <= WINDOWS_XP)
            hackLevel = 2;

        if (hackLevel == 0)
        {
            status = PhpGetObjectName(
                ProcessHandle,
                KphIsConnected() ? Handle : dupHandle,
                &objectName
                );
        }
        else if (hackLevel == 1)
        {
            POBJECT_NAME_INFORMATION buffer;

            buffer = PhAllocate(0x800);

            status = PhQueryObjectNameHack(
                dupHandle,
                buffer,
                0x800,
                NULL
                );

            if (NT_SUCCESS(status))
                objectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length);

            PhFree(buffer);
        }
        else
        {
            // Pretend the file object has no name.
            objectName = PhReferenceEmptyString();
            status = STATUS_SUCCESS;
        }
    }
    else
    {
        // Query the object normally.
        status = PhpGetObjectName(
            ProcessHandle,
            KphIsConnected() ? Handle : dupHandle,
            &objectName
            );
    }

    if (!NT_SUCCESS(status))
    {
        subStatus = status;
        status = STATUS_SUCCESS;
        goto CleanupExit;
    }

    // Exit early if we don't need to get the best object name.
    if (!BestObjectName)
        goto CleanupExit;

    status = PhpGetBestObjectName(
        ProcessHandle,
        Handle,
        objectName,
        typeName,
        &bestObjectName
        );

    if (!NT_SUCCESS(status))
    {
        subStatus = status;
        status = STATUS_SUCCESS;
        goto CleanupExit;
    }

CleanupExit:

    if (NT_SUCCESS(status))
    {
        if (SubStatus)
        {
            *SubStatus = subStatus;
        }

        if (TypeName && typeName)
        {
            *TypeName = typeName;
            PhReferenceObject(typeName);
        }

        if (ObjectName && objectName)
        {
            *ObjectName = objectName;
            PhReferenceObject(objectName);
        }

        if (BestObjectName && bestObjectName)
        {
            *BestObjectName = bestObjectName;
            PhReferenceObject(bestObjectName);
        }
    }

    if (dupHandle && ProcessHandle != NtCurrentProcess())
        NtClose(dupHandle);
    if (typeName)
        PhDereferenceObject(typeName);
    if (objectName)
        PhDereferenceObject(objectName);
    if (bestObjectName)
        PhDereferenceObject(bestObjectName);

    return status;
}
Exemple #15
0
VOID PhShowHandleObjectProperties1(
    _In_ HWND hWnd,
    _In_ PPH_HANDLE_ITEM_INFO Info
    )
{
    if (PhIsNullOrEmptyString(Info->TypeName))
        return;

    if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) ||
        PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE))
    {
        if (Info->BestObjectName)
        {
            PhShellExecuteUserString(
                PhMainWndHandle,
                L"FileBrowseExecutable",
                Info->BestObjectName->Buffer,
                FALSE,
                L"Make sure the Explorer executable file is present."
                );
        }
        else
            PhShowError(hWnd, L"Unable to open file location because the object is unnamed.");
    }
    else if (PhEqualString2(Info->TypeName, L"Key", TRUE))
    {
        if (Info->BestObjectName)
            PhShellOpenKey2(hWnd, Info->BestObjectName);
        else
            PhShowError(hWnd, L"Unable to open key because the object is unnamed.");
    }
    else if (PhEqualString2(Info->TypeName, L"Process", TRUE))
    {
        HANDLE processHandle;
        HANDLE processId;
        PPH_PROCESS_ITEM targetProcessItem;

        processId = NULL;

        if (KphIsConnected())
        {
            if (NT_SUCCESS(PhOpenProcess(
                &processHandle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId
                )))
            {
                PROCESS_BASIC_INFORMATION basicInfo;

                if (NT_SUCCESS(KphQueryInformationObject(
                    processHandle,
                    Info->Handle,
                    KphObjectProcessBasicInformation,
                    &basicInfo,
                    sizeof(PROCESS_BASIC_INFORMATION),
                    NULL
                    )))
                {
                    processId = basicInfo.UniqueProcessId;
                }

                NtClose(processHandle);
            }
        }
        else
        {
            HANDLE handle;
            PROCESS_BASIC_INFORMATION basicInfo;

            if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
                &handle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId,
                Info->Handle
                )))
            {
                if (NT_SUCCESS(PhGetProcessBasicInformation(handle, &basicInfo)))
                    processId = basicInfo.UniqueProcessId;

                NtClose(handle);
            }
        }

        if (processId)
        {
            targetProcessItem = PhReferenceProcessItem(processId);

            if (targetProcessItem)
            {
                ProcessHacker_ShowProcessProperties(PhMainWndHandle, targetProcessItem);
                PhDereferenceObject(targetProcessItem);
            }
            else
            {
                PhShowError(hWnd, L"The process does not exist.");
            }
        }
    }
    else if (PhEqualString2(Info->TypeName, L"Section", TRUE))
    {
        NTSTATUS status;
        HANDLE handle = NULL;
        BOOLEAN readOnly = FALSE;

        if (!NT_SUCCESS(status = PhpDuplicateHandleFromProcessItem(
            &handle,
            SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
            Info->ProcessId,
            Info->Handle
            )))
        {
            status = PhpDuplicateHandleFromProcessItem(
                &handle,
                SECTION_QUERY | SECTION_MAP_READ,
                Info->ProcessId,
                Info->Handle
                );
            readOnly = TRUE;
        }

        if (handle)
        {
            PPH_STRING sectionName = NULL;
            SECTION_BASIC_INFORMATION basicInfo;
            SIZE_T viewSize = PH_MAX_SECTION_EDIT_SIZE;
            PVOID viewBase = NULL;
            BOOLEAN tooBig = FALSE;

            PhGetHandleInformation(NtCurrentProcess(), handle, ULONG_MAX, NULL, NULL, NULL, &sectionName);

            if (NT_SUCCESS(status = PhGetSectionBasicInformation(handle, &basicInfo)))
            {
                if (basicInfo.MaximumSize.QuadPart <= PH_MAX_SECTION_EDIT_SIZE)
                    viewSize = (SIZE_T)basicInfo.MaximumSize.QuadPart;
                else
                    tooBig = TRUE;

                status = NtMapViewOfSection(
                    handle,
                    NtCurrentProcess(),
                    &viewBase,
                    0,
                    0,
                    NULL,
                    &viewSize,
                    ViewShare,
                    0,
                    readOnly ? PAGE_READONLY : PAGE_READWRITE
                    );

                if (status == STATUS_SECTION_PROTECTION && !readOnly)
                {
                    status = NtMapViewOfSection(
                        handle,
                        NtCurrentProcess(),
                        &viewBase,
                        0,
                        0,
                        NULL,
                        &viewSize,
                        ViewShare,
                        0,
                        PAGE_READONLY
                        );
                }

                if (NT_SUCCESS(status))
                {
                    PPH_SHOW_MEMORY_EDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOW_MEMORY_EDITOR));

                    if (tooBig)
                        PhShowWarning(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available for editing.");

                    memset(showMemoryEditor, 0, sizeof(PH_SHOW_MEMORY_EDITOR));
                    showMemoryEditor->ProcessId = NtCurrentProcessId();
                    showMemoryEditor->BaseAddress = viewBase;
                    showMemoryEditor->RegionSize = viewSize;
                    showMemoryEditor->SelectOffset = ULONG_MAX;
                    showMemoryEditor->SelectLength = 0;
                    showMemoryEditor->Title = sectionName ? PhConcatStrings2(L"Section - ", sectionName->Buffer) : PhCreateString(L"Section");
                    showMemoryEditor->Flags = PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION;
                    ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor);
                }
                else
                {
                    PhShowStatus(hWnd, L"Unable to map a view of the section.", status, 0);
                }
            }

            PhClearReference(&sectionName);

            NtClose(handle);
        }

        if (!NT_SUCCESS(status))
        {
            PhShowStatus(hWnd, L"Unable to query the section.", status, 0);
        }
    }
    else if (PhEqualString2(Info->TypeName, L"Thread", TRUE))
    {
        HANDLE processHandle;
        CLIENT_ID clientId;
        PPH_PROCESS_ITEM targetProcessItem;
        PPH_PROCESS_PROPCONTEXT propContext;

        clientId.UniqueProcess = NULL;
        clientId.UniqueThread = NULL;

        if (KphIsConnected())
        {
            if (NT_SUCCESS(PhOpenProcess(
                &processHandle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId
                )))
            {
                THREAD_BASIC_INFORMATION basicInfo;

                if (NT_SUCCESS(KphQueryInformationObject(
                    processHandle,
                    Info->Handle,
                    KphObjectThreadBasicInformation,
                    &basicInfo,
                    sizeof(THREAD_BASIC_INFORMATION),
                    NULL
                    )))
                {
                    clientId = basicInfo.ClientId;
                }

                NtClose(processHandle);
            }
        }
        else
        {
            HANDLE handle;
            THREAD_BASIC_INFORMATION basicInfo;

            if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
                &handle,
                THREAD_QUERY_LIMITED_INFORMATION,
                Info->ProcessId,
                Info->Handle
                )))
            {
                if (NT_SUCCESS(PhGetThreadBasicInformation(handle, &basicInfo)))
                    clientId = basicInfo.ClientId;

                NtClose(handle);
            }
        }

        if (clientId.UniqueProcess)
        {
            targetProcessItem = PhReferenceProcessItem(clientId.UniqueProcess);

            if (targetProcessItem)
            {
                propContext = PhCreateProcessPropContext(NULL, targetProcessItem);
                PhDereferenceObject(targetProcessItem);
                PhSetSelectThreadIdProcessPropContext(propContext, clientId.UniqueThread);
                ProcessHacker_Invoke(PhMainWndHandle, PhpShowProcessPropContext, propContext);
            }
            else
            {
                PhShowError(hWnd, L"The process does not exist.");
            }
        }
    }
}