Пример #1
0
PPH_STRING PhpGetCertNameString(
    __in PCERT_NAME_BLOB Blob
    )
{
    PPH_STRING string;
    ULONG bufferSize;

    // CertNameToStr doesn't give us the correct buffer size unless we
    // don't provide a buffer at all.
    bufferSize = CertNameToStr_I(
        X509_ASN_ENCODING,
        Blob,
        CERT_X500_NAME_STR,
        NULL,
        0
        );

    string = PhCreateStringEx(NULL, bufferSize * sizeof(WCHAR));
    CertNameToStr_I(
        X509_ASN_ENCODING,
        Blob,
        CERT_X500_NAME_STR,
        string->Buffer,
        bufferSize
        );

    PhTrimToNullTerminatorString(string);

    return string;
}
Пример #2
0
static PPH_STRING GetCurrentWinStaName(
    VOID
    )
{
    PPH_STRING string;

    string = PhCreateStringEx(NULL, 0x200);

    if (GetUserObjectInformation(
        GetProcessWindowStation(),
        UOI_NAME,
        string->Buffer,
        (ULONG)string->Length + 2,
        NULL
        ))
    {
        PhTrimToNullTerminatorString(string);
        return string;
    }
    else
    {
        PhDereferenceObject(string);
        return PhCreateString(L"WinSta0"); // assume the current window station is WinSta0
    }
}
Пример #3
0
PPH_STRING EtpQueryDeviceDescription(
	_In_ HDEVINFO DeviceInfoSet,
	_In_ PSP_DEVINFO_DATA DeviceInfoData
	)
{
	LOGICAL result;
	PPH_STRING string;
	ULONG bufferSize;

	if (!SetupDiGetDeviceRegistryPropertyW_I)
		return NULL;

	bufferSize = 0x40;
	string = PhCreateStringEx(NULL, bufferSize);

	if (!(result = SetupDiGetDeviceRegistryPropertyW_I(
		DeviceInfoSet,
		DeviceInfoData,
		SPDRP_DEVICEDESC,
		NULL,
		(PBYTE)string->Buffer,
		bufferSize,
		&bufferSize
		)) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
	{
		PhDereferenceObject(string);
		string = PhCreateStringEx(NULL, bufferSize);

		result = SetupDiGetDeviceRegistryPropertyW_I(
			DeviceInfoSet,
			DeviceInfoData,
			SPDRP_DEVICEDESC,
			NULL,
			(PBYTE)string->Buffer,
			bufferSize,
			NULL
			);
	}

	if (!result)
	{
		PhDereferenceObject(string);
		return NULL;
	}

	PhTrimToNullTerminatorString(string);

	return string;
}
Пример #4
0
PPH_STRING PhpGetThreadBasicStartAddress(
    __in PPH_THREAD_PROVIDER ThreadProvider,
    __in ULONG64 Address,
    __out PPH_SYMBOL_RESOLVE_LEVEL ResolveLevel
    )
{
    ULONG64 modBase;
    PPH_STRING fileName = NULL;
    PPH_STRING baseName = NULL;
    PPH_STRING symbol;

    modBase = PhGetModuleFromAddress(
        ThreadProvider->SymbolProvider,
        Address,
        &fileName
        );

    if (fileName == NULL)
    {
        *ResolveLevel = PhsrlAddress;

        symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2);
        PhPrintPointer(symbol->Buffer, (PVOID)Address);
        PhTrimToNullTerminatorString(symbol);
    }
    else
    {
        PH_FORMAT format[3];

        baseName = PhGetBaseName(fileName);
        *ResolveLevel = PhsrlModule;

        PhInitFormatSR(&format[0], baseName->sr);
        PhInitFormatS(&format[1], L"+0x");
        PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase));

        symbol = PhFormat(format, 3, baseName->Length + 6 + 32);
    }

    if (fileName)
        PhDereferenceObject(fileName);
    if (baseName)
        PhDereferenceObject(baseName);

    return symbol;
}
Пример #5
0
static PPH_STRING EtpGetBasicSymbol(
    _In_ PPH_SYMBOL_PROVIDER SymbolProvider,
    _In_ ULONG64 Address
    )
{
    ULONG64 modBase;
    PPH_STRING fileName = NULL;
    PPH_STRING baseName = NULL;
    PPH_STRING symbol;

    modBase = PhGetModuleFromAddress(SymbolProvider, Address, &fileName);

    if (!fileName)
    {
        symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2);
        PhPrintPointer(symbol->Buffer, (PVOID)Address);
        PhTrimToNullTerminatorString(symbol);
    }
    else
    {
        PH_FORMAT format[3];

        baseName = PhGetBaseName(fileName);

        PhInitFormatSR(&format[0], baseName->sr);
        PhInitFormatS(&format[1], L"+0x");
        PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase));

        symbol = PhFormat(format, 3, baseName->Length + 6 + 32);
    }

    if (fileName)
        PhDereferenceObject(fileName);
    if (baseName)
        PhDereferenceObject(baseName);

    return symbol;
}
Пример #6
0
PPH_STRING PhGetSymbolFromAddress(
    _In_ PPH_SYMBOL_PROVIDER SymbolProvider,
    _In_ ULONG64 Address,
    _Out_opt_ PPH_SYMBOL_RESOLVE_LEVEL ResolveLevel,
    _Out_opt_ PPH_STRING *FileName,
    _Out_opt_ PPH_STRING *SymbolName,
    _Out_opt_ PULONG64 Displacement
    )
{
    PSYMBOL_INFOW symbolInfo;
    ULONG nameLength;
    PPH_STRING symbol = NULL;
    PH_SYMBOL_RESOLVE_LEVEL resolveLevel;
    ULONG64 displacement;
    PPH_STRING modFileName = NULL;
    PPH_STRING modBaseName = NULL;
    ULONG64 modBase;
    PPH_STRING symbolName = NULL;

    if (!SymFromAddrW_I && !SymFromAddr_I)
        return NULL;

    if (Address == 0)
    {
        if (ResolveLevel) *ResolveLevel = PhsrlInvalid;
        if (FileName) *FileName = NULL;
        if (SymbolName) *SymbolName = NULL;
        if (Displacement) *Displacement = 0;

        return NULL;
    }

#ifdef PH_SYMBOL_PROVIDER_DELAY_INIT
    PhpRegisterSymbolProvider(SymbolProvider);
#endif

    symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + PH_MAX_SYMBOL_NAME_LEN * 2);
    memset(symbolInfo, 0, sizeof(SYMBOL_INFOW));
    symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW);
    symbolInfo->MaxNameLen = PH_MAX_SYMBOL_NAME_LEN;

    // Get the symbol name.

    PH_LOCK_SYMBOLS();

    // Note that we don't care whether this call
    // succeeds or not, based on the assumption that
    // it will not write to the symbolInfo structure
    // if it fails. We've already zeroed the structure,
    // so we can deal with it.

    if (SymFromAddrW_I)
    {
        SymFromAddrW_I(
            SymbolProvider->ProcessHandle,
            Address,
            &displacement,
            symbolInfo
            );
        nameLength = symbolInfo->NameLen;

        if (nameLength + 1 > PH_MAX_SYMBOL_NAME_LEN)
        {
            PhFree(symbolInfo);
            symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + nameLength * 2 + 2);
            memset(symbolInfo, 0, sizeof(SYMBOL_INFOW));
            symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW);
            symbolInfo->MaxNameLen = nameLength + 1;

            SymFromAddrW_I(
                SymbolProvider->ProcessHandle,
                Address,
                &displacement,
                symbolInfo
                );
        }
    }
    else if (SymFromAddr_I)
    {
        PSYMBOL_INFO symbolInfoA;

        symbolInfoA = PhAllocate(FIELD_OFFSET(SYMBOL_INFO, Name) + PH_MAX_SYMBOL_NAME_LEN);
        memset(symbolInfoA, 0, sizeof(SYMBOL_INFO));
        symbolInfoA->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbolInfoA->MaxNameLen = PH_MAX_SYMBOL_NAME_LEN;

        SymFromAddr_I(
            SymbolProvider->ProcessHandle,
            Address,
            &displacement,
            symbolInfoA
            );
        nameLength = symbolInfoA->NameLen;

        if (nameLength + 1 > PH_MAX_SYMBOL_NAME_LEN)
        {
            PhFree(symbolInfoA);
            symbolInfoA = PhAllocate(FIELD_OFFSET(SYMBOL_INFO, Name) + nameLength + 1);
            memset(symbolInfoA, 0, sizeof(SYMBOL_INFO));
            symbolInfoA->SizeOfStruct = sizeof(SYMBOL_INFO);
            symbolInfoA->MaxNameLen = nameLength + 1;

            SymFromAddr_I(
                SymbolProvider->ProcessHandle,
                Address,
                &displacement,
                symbolInfoA
                );

            // Also reallocate the Unicode-based buffer.
            PhFree(symbolInfo);
            symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + nameLength * 2 + 2);
            memset(symbolInfo, 0, sizeof(SYMBOL_INFOW));
            symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW);
            symbolInfo->MaxNameLen = nameLength + 1;
        }

        PhpSymbolInfoAnsiToUnicode(symbolInfo, symbolInfoA);
        PhFree(symbolInfoA);
    }

    PH_UNLOCK_SYMBOLS();

    // Find the module name.

    if (symbolInfo->ModBase == 0)
    {
        modBase = PhGetModuleFromAddress(
            SymbolProvider,
            Address,
            &modFileName
            );
    }
    else
    {
        PH_SYMBOL_MODULE lookupSymbolModule;
        PPH_AVL_LINKS existingLinks;
        PPH_SYMBOL_MODULE symbolModule;

        lookupSymbolModule.BaseAddress = symbolInfo->ModBase;

        PhAcquireQueuedLockShared(&SymbolProvider->ModulesListLock);

        existingLinks = PhFindElementAvlTree(&SymbolProvider->ModulesSet, &lookupSymbolModule.Links);

        if (existingLinks)
        {
            symbolModule = CONTAINING_RECORD(existingLinks, PH_SYMBOL_MODULE, Links);
            modFileName = symbolModule->FileName;
            PhReferenceObject(modFileName);
        }

        PhReleaseQueuedLockShared(&SymbolProvider->ModulesListLock);
    }

    // If we don't have a module name, return an address.
    if (!modFileName)
    {
        resolveLevel = PhsrlAddress;
        symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2);
        PhPrintPointer(symbol->Buffer, (PVOID)Address);
        PhTrimToNullTerminatorString(symbol);

        goto CleanupExit;
    }

    modBaseName = PhGetBaseName(modFileName);

    // If we have a module name but not a symbol name,
    // return the module plus an offset: module+offset.

    if (symbolInfo->NameLen == 0)
    {
        PH_FORMAT format[3];

        resolveLevel = PhsrlModule;

        PhInitFormatSR(&format[0], modBaseName->sr);
        PhInitFormatS(&format[1], L"+0x");
        PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase));
        symbol = PhFormat(format, 3, modBaseName->Length + 6 + 32);

        goto CleanupExit;
    }

    // If we have everything, return the full symbol
    // name: module!symbol+offset.

    symbolName = PhCreateStringEx(
        symbolInfo->Name,
        symbolInfo->NameLen * 2
        );

    resolveLevel = PhsrlFunction;

    if (displacement == 0)
    {
        PH_FORMAT format[3];

        PhInitFormatSR(&format[0], modBaseName->sr);
        PhInitFormatC(&format[1], '!');
        PhInitFormatSR(&format[2], symbolName->sr);

        symbol = PhFormat(format, 3, modBaseName->Length + 2 + symbolName->Length);
    }
    else
    {
        PH_FORMAT format[5];

        PhInitFormatSR(&format[0], modBaseName->sr);
        PhInitFormatC(&format[1], '!');
        PhInitFormatSR(&format[2], symbolName->sr);
        PhInitFormatS(&format[3], L"+0x");
        PhInitFormatIX(&format[4], (ULONG_PTR)displacement);

        symbol = PhFormat(format, 5, modBaseName->Length + 2 + symbolName->Length + 6 + 32);
    }

CleanupExit:

    if (ResolveLevel)
        *ResolveLevel = resolveLevel;
    if (FileName)
    {
        *FileName = modFileName;

        if (modFileName)
            PhReferenceObject(modFileName);
    }
    if (SymbolName)
    {
        *SymbolName = symbolName;

        if (symbolName)
            PhReferenceObject(symbolName);
    }
    if (Displacement)
        *Displacement = displacement;

    if (modFileName)
        PhDereferenceObject(modFileName);
    if (modBaseName)
        PhDereferenceObject(modBaseName);
    if (symbolName)
        PhDereferenceObject(symbolName);

    PhFree(symbolInfo);

    return symbol;
}
Пример #7
0
BOOLEAN NvGpuDriverIsWHQL(VOID)
{
    BOOLEAN nvGpuDriverIsWHQL = FALSE;
    HANDLE keyHandle = NULL;
    HANDLE keyServiceHandle = NULL;
    PWSTR deviceInterfaceList = NULL;
    ULONG deviceInterfaceListLength = 0;
    PWSTR deviceInterface;
    PPH_STRING keyPath = NULL;
    PPH_STRING matchingDeviceIdString;
    PPH_STRING keyServicePath;
    NvAPI_LongString nvNameAnsiString = "";

    if (!NvAPI_GetDisplayDriverRegistryPath)
        goto CleanupExit;

    if (NvAPI_GetDisplayDriverRegistryPath(NvGpuDisplayHandleList->Items[0], nvNameAnsiString) != NVAPI_OK)
        goto CleanupExit;

    keyPath = PhConvertMultiByteToUtf16(nvNameAnsiString);

    if (!NT_SUCCESS(PhOpenKey(
        &keyHandle,
        KEY_READ,
        PH_KEY_LOCAL_MACHINE,
        &keyPath->sr,
        0
        )))
    {
        goto CleanupExit;
    }

    matchingDeviceIdString = PhQueryRegistryString(keyHandle, L"MatchingDeviceId");
    //keySettingsPath = PhConcatStrings2(keyPath->Buffer, L"\\VolatileSettings");

    //if (NT_SUCCESS(PhOpenKey(
    //    &keySettingsHandle,
    //    KEY_READ,
    //    PH_KEY_LOCAL_MACHINE,
    //    &keySettingsPath->sr,
    //    0
    //    )))
    //{
    //    GUID settingsKey = GUID_DEVINTERFACE_DISPLAY_ADAPTER;
    //    PPH_STRING guidString = PhFormatGuid(&settingsKey);
    //
    //    ULONG dwType = REG_BINARY;
    //    LONG length = DOS_MAX_PATH_LENGTH;
    //
    //    if (RegQueryValueEx(
    //        keySettingsHandle,
    //        guidString->Buffer,
    //        0,
    //        &dwType,
    //        (PBYTE)displayInstancePath,
    //        &length
    //        ) != ERROR_SUCCESS)
    //    {
    //        //__leave;
    //    }
    //
    //    NtClose(keySettingsHandle);
    //    PhDereferenceObject(guidString);
    //}

    if (CM_Get_Device_Interface_List_Size(
        &deviceInterfaceListLength,
        (PGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER,
        NULL,
        CM_GET_DEVICE_INTERFACE_LIST_PRESENT
        ) != CR_SUCCESS)
    {
        return FALSE;
    }

    deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR));
    memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR));

    if (CM_Get_Device_Interface_List(
        (PGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER,
        NULL,
        deviceInterfaceList,
        deviceInterfaceListLength,
        CM_GET_DEVICE_INTERFACE_LIST_PRESENT
        ) != CR_SUCCESS)
    {
        PhFree(deviceInterfaceList);
        return FALSE;
    }

    for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1)
    {
        CONFIGRET result;
        PPH_STRING string;
        ULONG bufferSize;
        DEVPROPTYPE devicePropertyType;
        DEVINST deviceInstanceHandle;
        ULONG deviceInstanceIdLength = MAX_DEVICE_ID_LEN;
        WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN];

        if (CM_Get_Device_Interface_Property(
            deviceInterface,
            &DEVPKEY_Device_InstanceId,
            &devicePropertyType,
            (PBYTE)deviceInstanceId,
            &deviceInstanceIdLength,
            0
            ) != CR_SUCCESS)
        {
            continue;
        }

        if (CM_Locate_DevNode(&deviceInstanceHandle, deviceInstanceId, CM_LOCATE_DEVNODE_NORMAL)!= CR_SUCCESS)
            continue;

        bufferSize = 0x40;
        string = PhCreateStringEx(NULL, bufferSize);

        if ((result = CM_Get_DevNode_Property(
            deviceInstanceHandle,
            &DEVPKEY_Device_MatchingDeviceId,
            &devicePropertyType,
            (PBYTE)string->Buffer,
            &bufferSize,
            0
            )) != CR_SUCCESS)
        {
            PhDereferenceObject(string);
            string = PhCreateStringEx(NULL, bufferSize);

            result = CM_Get_DevNode_Property(
                deviceInstanceHandle,
                &DEVPKEY_Device_MatchingDeviceId,
                &devicePropertyType,
                (PBYTE)string->Buffer,
                &bufferSize,
                0
                );
        }

        if (result != CR_SUCCESS)
        {
            PhDereferenceObject(string);
            continue;
        }

        PhTrimToNullTerminatorString(string);

        if (!PhEqualString(string, matchingDeviceIdString, TRUE))
        {
            PhDereferenceObject(string);
            continue;
        }

        bufferSize = 0x40;
        PhDereferenceObject(string);
        string = PhCreateStringEx(NULL, bufferSize);

        if ((result = CM_Get_DevNode_Property(
            deviceInstanceHandle,
            &DEVPKEY_Device_Service,
            &devicePropertyType,
            (PBYTE)string->Buffer,
            &bufferSize,
            0
            )) != CR_SUCCESS)
        {
            PhDereferenceObject(string);
            string = PhCreateStringEx(NULL, bufferSize);

            result = CM_Get_DevNode_Property(
                deviceInstanceHandle,
                &DEVPKEY_Device_Service,
                &devicePropertyType,
                (PBYTE)string->Buffer,
                &bufferSize,
                0
                );
        }

        if (result != CR_SUCCESS)
        {
            PhDereferenceObject(string);
            continue;
        }

        keyServicePath = PhConcatStrings2(L"System\\CurrentControlSet\\Services\\", string->Buffer);

        if (NT_SUCCESS(PhOpenKey(
            &keyServiceHandle,
            KEY_READ,
            PH_KEY_LOCAL_MACHINE,
            &keyServicePath->sr,
            0
            )))
        {
            PPH_STRING driverNtPathString;
            PPH_STRING driverDosPathString = NULL;

            if (driverNtPathString = PhQueryRegistryString(keyServiceHandle, L"ImagePath"))
            {
                driverDosPathString = PhGetFileName(driverNtPathString);
                PhDereferenceObject(driverNtPathString);
            }

            if (driverDosPathString)
            {
                PPH_STRING fileSignerName = NULL;
                //PH_MAPPED_IMAGE fileMappedImage;
                //
                //if (NT_SUCCESS(PhLoadMappedImage(driverDosPathString->Buffer, NULL, TRUE, &fileMappedImage)))
                //{
                //    LARGE_INTEGER time;
                //    SYSTEMTIME systemTime;
                //    PPH_STRING string;
                //
                //    RtlSecondsSince1970ToTime(fileMappedImage.NtHeaders->FileHeader.TimeDateStamp, &time);
                //    PhLargeIntegerToLocalSystemTime(&systemTime, &time);
                //
                //    string = PhFormatDateTime(&systemTime);
                //    //SetDlgItemText(hwndDlg, IDC_TIMESTAMP, string->Buffer);
                //    PhDereferenceObject(string);
                //
                //    PhUnloadMappedImage(&fileMappedImage);
                //}

                if (PhVerifyFile(driverDosPathString->Buffer, &fileSignerName) == VrTrusted)
                {
                    //if (PhEqualString2(fileSignerName, L"Microsoft Windows Hardware Compatibility Publisher", TRUE))  
                    nvGpuDriverIsWHQL = TRUE;   
                }

                if (fileSignerName)
                    PhDereferenceObject(fileSignerName);

                PhDereferenceObject(driverDosPathString);
            }

            NtClose(keyServiceHandle);
        }
    }

CleanupExit:

    if (keyHandle)
    {
        NtClose(keyHandle);
    }

    if (deviceInterfaceList)
    {
        PhFree(deviceInterfaceList);
    }

    if (keyPath)
    {
        PhDereferenceObject(keyPath);
    }

    return nvGpuDriverIsWHQL;
}
Пример #8
0
PPH_STRING FindDiskDeviceInstance(
    _In_ PPH_STRING DevicePath
    )
{
    PPH_STRING deviceIdString = NULL;
    HDEVINFO deviceInfoHandle;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
    SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) };
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail;
    ULONG deviceInfoLength = 0;

    if ((deviceInfoHandle = SetupDiGetClassDevs(
        &GUID_DEVINTERFACE_DISK,
        NULL,
        NULL,
        DIGCF_DEVICEINTERFACE
        )) == INVALID_HANDLE_VALUE)
    {
        return NULL;
    }

    for (ULONG i = 0; SetupDiEnumDeviceInterfaces(deviceInfoHandle, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++)
    {
        if (SetupDiGetDeviceInterfaceDetail(
            deviceInfoHandle,
            &deviceInterfaceData,
            0,
            0,
            &deviceInfoLength,
            &deviceInfoData
            ) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            continue;
        }

        deviceInterfaceDetail = PhAllocate(deviceInfoLength);
        deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (SetupDiGetDeviceInterfaceDetail(
            deviceInfoHandle,
            &deviceInterfaceData,
            deviceInterfaceDetail,
            deviceInfoLength,
            &deviceInfoLength,
            &deviceInfoData
            ))
        {
            if (PhEqualStringZ(deviceInterfaceDetail->DevicePath, DevicePath->Buffer, TRUE))
            {
                deviceIdString = PhCreateStringEx(NULL, 0x100);

                SetupDiGetDeviceInstanceId(
                    deviceInfoHandle,
                    &deviceInfoData,
                    deviceIdString->Buffer,
                    (ULONG)deviceIdString->Length,
                    NULL
                    );

                PhTrimToNullTerminatorString(deviceIdString);
            }
        }

        PhFree(deviceInterfaceDetail);
    }

    SetupDiDestroyDeviceInfoList(deviceInfoHandle);

    return deviceIdString;
}
Пример #9
0
PPH_STRING BrowseForFolder(
    _In_opt_ HWND DialogHandle,
    _In_opt_ PCWSTR Title
    )
{
    PPH_STRING folderPath = NULL;

    if (WINDOWS_HAS_IFILEDIALOG)
    {
        PVOID fileDialog;

        fileDialog = PhCreateOpenFileDialog();

        PhSetFileDialogOptions(fileDialog, PH_FILEDIALOG_PICKFOLDERS);

        if (PhShowFileDialog(DialogHandle, fileDialog))
        {
            PPH_STRING folderPath;
            PPH_STRING fileDialogFolderPath = PhGetFileDialogFileName(fileDialog);

            folderPath = PhCreateStringEx(fileDialogFolderPath->Buffer, fileDialogFolderPath->Length * 2);

            // Ensure the folder path ends with a slash
            // We must make sure the install path ends with a backslash since
            // this string is wcscat' with our zip extraction paths.
            PathAddBackslash(folderPath->Buffer);

            PhTrimToNullTerminatorString(folderPath);

            PhFreeFileDialog(fileDialog);

            return folderPath;
        }
    }
    else
    {
        PIDLIST_ABSOLUTE shellItemId;
        BROWSEINFO browseInformation;

        memset(&browseInformation, 0, sizeof(BROWSEINFO));

        browseInformation.hwndOwner = DialogHandle;
        browseInformation.lpszTitle = Title;
        browseInformation.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;  // Caller needs to call OleInitialize() before using BIF_NEWDIALOGSTYLE?

        if (shellItemId = SHBrowseForFolder(&browseInformation))
        {
            folderPath = PhCreateStringEx(NULL, MAX_PATH * 2);

            if (SHGetPathFromIDList(shellItemId, folderPath->Buffer))
            {
                // Ensure the folder path ends with a slash
                // We must make sure the install path ends with a backslash since
                // this string is wcscat' with our zip extraction paths.
                PathAddBackslash(folderPath->Buffer);

                PhTrimToNullTerminatorString(folderPath);
            }
            else
            {
                PhClearReference(&folderPath);
            }

            CoTaskMemFree(shellItemId);
        }
    }

    return folderPath;
}
Пример #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++;
}
Пример #11
0
VOID PhpFillUmdfDrivers(
    _In_ PPH_PROCESS_ITEM Process,
    _Inout_ PPH_STRING_BUILDER Drivers
    )
{
    static PH_STRINGREF activeDevices = PH_STRINGREF_INIT(L"ACTIVE_DEVICES");
    static PH_STRINGREF currentControlSetEnum = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Enum\\");

    HANDLE processHandle;
    ULONG flags = 0;
    PVOID environment;
    ULONG environmentLength;
    ULONG enumerationKey;
    PH_ENVIRONMENT_VARIABLE variable;

    if (!NT_SUCCESS(PhOpenProcess(
        &processHandle,
        PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
        Process->ProcessId
        )))
        return;

#ifdef _WIN64
    // Just in case.
    if (Process->IsWow64)
        flags |= PH_GET_PROCESS_ENVIRONMENT_WOW64;
#endif

    if (NT_SUCCESS(PhGetProcessEnvironment(
        processHandle,
        flags,
        &environment,
        &environmentLength
        )))
    {
        enumerationKey = 0;

        while (PhEnumProcessEnvironmentVariables(environment, environmentLength, &enumerationKey, &variable))
        {
            PH_STRINGREF part;
            PH_STRINGREF remainingPart;

            if (!PhEqualStringRef(&variable.Name, &activeDevices, TRUE))
                continue;

            remainingPart = variable.Value;

            while (remainingPart.Length != 0)
            {
                PhSplitStringRefAtChar(&remainingPart, ';', &part, &remainingPart);

                if (part.Length != 0)
                {
                    HANDLE driverKeyHandle;
                    PPH_STRING driverKeyPath;

                    driverKeyPath = PhConcatStringRef2(&currentControlSetEnum, &part);

                    if (NT_SUCCESS(PhOpenKey(
                        &driverKeyHandle,
                        KEY_READ,
                        PH_KEY_LOCAL_MACHINE,
                        &driverKeyPath->sr,
                        0
                        )))
                    {
                        PPH_STRING deviceDesc;
                        PH_STRINGREF deviceName;
                        PPH_STRING hardwareId;

                        if (deviceDesc = PhQueryRegistryString(driverKeyHandle, L"DeviceDesc"))
                        {
                            PH_STRINGREF firstPart;
                            PH_STRINGREF secondPart;

                            if (PhSplitStringRefAtLastChar(&deviceDesc->sr, ';', &firstPart, &secondPart))
                                deviceName = secondPart;
                            else
                                deviceName = deviceDesc->sr;
                        }
                        else
                        {
                            PhInitializeStringRef(&deviceName, L"Unknown Device");
                        }

                        hardwareId = PhQueryRegistryString(driverKeyHandle, L"HardwareID");

                        PhAppendStringBuilder(Drivers, &StandardIndent);
                        PhAppendStringBuilder(Drivers, &deviceName);

                        if (hardwareId)
                        {
                            PhTrimToNullTerminatorString(hardwareId);

                            if (hardwareId->Length != 0)
                            {
                                PhAppendStringBuilder2(Drivers, L" (");
                                PhAppendStringBuilder(Drivers, &hardwareId->sr);
                                PhAppendCharStringBuilder(Drivers, ')');
                            }
                        }

                        PhAppendCharStringBuilder(Drivers, '\n');

                        PhClearReference(&hardwareId);
                        PhClearReference(&deviceDesc);
                        NtClose(driverKeyHandle);
                    }

                    PhDereferenceObject(driverKeyPath);
                }
            }
        }

        PhFreePage(environment);
    }

    NtClose(processHandle);
}
Пример #12
0
VOID LoadNetworkAdapterImages(
    _In_ PDV_NETADAPTER_CONTEXT Context
    )
{
    HICON smallIcon;
    CONFIGRET result;
    ULONG deviceIconPathLength;
    DEVPROPTYPE deviceIconPathPropertyType;
    PPH_STRING deviceIconPath;

    deviceIconPathLength = 0x40;
    deviceIconPath = PhCreateStringEx(NULL, deviceIconPathLength);

    if ((result = CM_Get_Class_Property(
        &GUID_DEVCLASS_NET,
        &DEVPKEY_DeviceClass_IconPath,
        &deviceIconPathPropertyType,
        (PBYTE)deviceIconPath->Buffer,
        &deviceIconPathLength,
        0
        )) != CR_SUCCESS)
    {
        PhDereferenceObject(deviceIconPath);
        deviceIconPath = PhCreateStringEx(NULL, deviceIconPathLength);

        result = CM_Get_Class_Property(
            &GUID_DEVCLASS_NET,
            &DEVPKEY_DeviceClass_IconPath,
            &deviceIconPathPropertyType,
            (PBYTE)deviceIconPath->Buffer,
            &deviceIconPathLength,
            0
            );
    }

    if (result != CR_SUCCESS)
    {
        PhDereferenceObject(deviceIconPath);
        return;
    }

    PhTrimToNullTerminatorString(deviceIconPath);

    {
        PPH_STRING dllIconPath;
        PH_STRINGREF dllPartSr;
        PH_STRINGREF indexPartSr;
        ULONG64 index = 0;

        if (
            PhSplitStringRefAtChar(&deviceIconPath->sr, ',', &dllPartSr, &indexPartSr) && 
            PhStringToInteger64(&indexPartSr, 10, &index)
            )
        {
            if (dllIconPath = PhExpandEnvironmentStrings(&dllPartSr))
            {
                if (PhExtractIconEx(dllIconPath->Buffer, (INT)index, &smallIcon, NULL))
                {
                    Context->ImageList = ImageList_Create(
                        GetSystemMetrics(SM_CXICON),
                        GetSystemMetrics(SM_CYICON),
                        ILC_COLOR32,
                        1,
                        1
                        );

                    ImageList_AddIcon(Context->ImageList, smallIcon);                 
                    ListView_SetImageList(Context->ListViewHandle, Context->ImageList, LVSIL_SMALL);
                    DestroyIcon(smallIcon);
                }

                PhDereferenceObject(dllIconPath);
            }
        }
    }

    PhDereferenceObject(deviceIconPath);
}
Пример #13
0
BOOLEAN QueryNetworkDeviceInterfaceDescription(
    _In_ PWSTR DeviceInterface,
    _Out_ DEVINST *DeviceInstanceHandle,
    _Out_ PPH_STRING *DeviceDescription
    )
{
    CONFIGRET result;
    ULONG bufferSize;
    PPH_STRING deviceDescription;
    DEVPROPTYPE devicePropertyType;
    DEVINST deviceInstanceHandle;
    ULONG deviceInstanceIdLength = MAX_DEVICE_ID_LEN;
    WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN + 1] = L"";

    if (CM_Get_Device_Interface_Property(
        DeviceInterface,
        &DEVPKEY_Device_InstanceId,
        &devicePropertyType,
        (PBYTE)deviceInstanceId,
        &deviceInstanceIdLength,
        0
        ) != CR_SUCCESS)
    {
        return FALSE;
    }

    if (CM_Locate_DevNode(
        &deviceInstanceHandle,
        deviceInstanceId,
        CM_LOCATE_DEVNODE_PHANTOM
        ) != CR_SUCCESS)
    {
        return FALSE;
    }

    bufferSize = 0x40;
    deviceDescription = PhCreateStringEx(NULL, bufferSize);

    // DEVPKEY_Device_DeviceDesc doesn't give us the full adapter name.
    // DEVPKEY_Device_FriendlyName does give us the full adapter name but is only
    //  supported on Windows 8 and above.

    // We use our NetworkAdapterQueryName function to query the full adapter name
    // from the NDIS driver directly, if that fails then we use one of the above properties.

    if ((result = CM_Get_DevNode_Property(
        deviceInstanceHandle,
        WindowsVersion >= WINDOWS_8 ? &DEVPKEY_Device_FriendlyName : &DEVPKEY_Device_DeviceDesc,
        &devicePropertyType,
        (PBYTE)deviceDescription->Buffer,
        &bufferSize,
        0
        )) != CR_SUCCESS)
    {
        PhDereferenceObject(deviceDescription);
        deviceDescription = PhCreateStringEx(NULL, bufferSize);

        result = CM_Get_DevNode_Property(
            deviceInstanceHandle,
            WindowsVersion >= WINDOWS_8 ? &DEVPKEY_Device_FriendlyName : &DEVPKEY_Device_DeviceDesc,
            &devicePropertyType,
            (PBYTE)deviceDescription->Buffer,
            &bufferSize,
            0
            );
    }

    if (result != CR_SUCCESS)
    {
        PhDereferenceObject(deviceDescription);
        return FALSE;
    }

    PhTrimToNullTerminatorString(deviceDescription);

    *DeviceInstanceHandle = deviceInstanceHandle;
    *DeviceDescription = deviceDescription;

    return TRUE;
}
Пример #14
0
PPH_STRING EtpQueryDeviceDescription(
    _In_ PWSTR DeviceInterface
)
{
    CONFIGRET result;
    PPH_STRING string;
    ULONG bufferSize;
    DEVPROPTYPE devicePropertyType;
    DEVINST deviceInstanceHandle;
    ULONG deviceInstanceIdLength = MAX_DEVICE_ID_LEN;
    WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN];

    if (CM_Get_Device_Interface_Property(
                DeviceInterface,
                &DEVPKEY_Device_InstanceId,
                &devicePropertyType,
                (PBYTE)deviceInstanceId,
                &deviceInstanceIdLength,
                0
            ) != CR_SUCCESS)
    {
        return NULL;
    }

    if (CM_Locate_DevNode(
                &deviceInstanceHandle,
                deviceInstanceId,
                CM_LOCATE_DEVNODE_NORMAL
            ) != CR_SUCCESS)
    {
        return NULL;
    }

    bufferSize = 0x40;
    string = PhCreateStringEx(NULL, bufferSize);

    if ((result = CM_Get_DevNode_Property( // CM_Get_DevNode_Registry_Property with CM_DRP_DEVICEDESC??
                      deviceInstanceHandle,
                      &DEVPKEY_Device_DeviceDesc,
                      &devicePropertyType,
                      (PBYTE)string->Buffer,
                      &bufferSize,
                      0
                  )) != CR_SUCCESS)
    {
        PhDereferenceObject(string);
        string = PhCreateStringEx(NULL, bufferSize);

        result = CM_Get_DevNode_Property(
                     deviceInstanceHandle,
                     &DEVPKEY_Device_DeviceDesc,
                     &devicePropertyType,
                     (PBYTE)string->Buffer,
                     &bufferSize,
                     0
                 );
    }

    if (result != CR_SUCCESS)
    {
        PhDereferenceObject(string);
        return NULL;
    }

    PhTrimToNullTerminatorString(string);

    return string;
}