PPH_STRING GetRuntimeNameByAddressClrProcess( _In_ PCLR_PROCESS_SUPPORT Support, _In_ ULONG64 Address, _Out_opt_ PULONG64 Displacement ) { PPH_STRING buffer; ULONG bufferLength; ULONG returnLength; ULONG64 displacement; bufferLength = 33; buffer = PhCreateStringEx(NULL, (bufferLength - 1) * 2); returnLength = 0; if (!SUCCEEDED(IXCLRDataProcess_GetRuntimeNameByAddress( Support->DataProcess, Address, 0, bufferLength, &returnLength, buffer->Buffer, &displacement ))) { PhDereferenceObject(buffer); return NULL; } // Try again if our buffer was too small. if (returnLength > bufferLength) { PhDereferenceObject(buffer); bufferLength = returnLength; buffer = PhCreateStringEx(NULL, (bufferLength - 1) * 2); if (!SUCCEEDED(IXCLRDataProcess_GetRuntimeNameByAddress( Support->DataProcess, Address, 0, bufferLength, &returnLength, buffer->Buffer, &displacement ))) { PhDereferenceObject(buffer); return NULL; } } if (Displacement) *Displacement = displacement; buffer->Length = (returnLength - 1) * 2; return buffer; }
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; }
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; }
PPH_STRING PhGetListBoxString( _In_ HWND hwnd, _In_ INT Index ) { PPH_STRING string; ULONG length; if (Index == -1) { Index = ListBox_GetCurSel(hwnd); if (Index == -1) return NULL; } length = ListBox_GetTextLen(hwnd, Index); if (length == LB_ERR) return NULL; if (length == 0) return PhReferenceEmptyString(); string = PhCreateStringEx(NULL, length * 2); if (ListBox_GetText(hwnd, Index, string->Buffer) != LB_ERR) { return string; } else { PhDereferenceObject(string); return NULL; } }
static BOOLEAN EnumPluginsDirectoryCallback( _In_ PFILE_DIRECTORY_INFORMATION Information, _In_opt_ PVOID Context ) { PH_STRINGREF baseName; PPH_STRING fileName; baseName.Buffer = Information->FileName; baseName.Length = Information->FileNameLength; if (PhEndsWithStringRef2(&baseName, L".dll", TRUE)) { if (!PhIsPluginDisabled(&baseName)) { fileName = PhCreateStringEx(NULL, PluginsDirectory->Length + Information->FileNameLength); memcpy(fileName->Buffer, PluginsDirectory->Buffer, PluginsDirectory->Length); memcpy(&fileName->Buffer[PluginsDirectory->Length / 2], Information->FileName, Information->FileNameLength); PhLoadPlugin(fileName); PhDereferenceObject(fileName); } } return TRUE; }
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; }
PPH_STRING KhspQueryFileName( _In_ LONGLONG ScanId, _In_ USHORT FileNameLength) { HRESULT result; PWCHAR buffer; DWORD bytesReturned; PPH_STRING fileName; struct { ULONG Command; LONGLONG ScanId; } input = { HsCmdQueryFileName, ScanId }; buffer = PhAllocate(FileNameLength); result = FilterSendMessage( HsKhsPortHandle, &input, sizeof(input), buffer, FileNameLength, &bytesReturned); if (SUCCEEDED(result)) fileName = PhCreateStringEx(buffer, FileNameLength); else fileName = NULL; PhFree(buffer); return fileName; }
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 } }
PPH_STRING GetNameXClrDataAppDomain( __in PVOID AppDomain ) { IXCLRDataAppDomain *appDomain; PPH_STRING buffer; ULONG bufferLength; ULONG returnLength; appDomain = AppDomain; bufferLength = 33; buffer = PhCreateStringEx(NULL, (bufferLength - 1) * 2); returnLength = 0; if (!SUCCEEDED(IXCLRDataAppDomain_GetName(appDomain, bufferLength, &returnLength, buffer->Buffer))) { PhDereferenceObject(buffer); return NULL; } // Try again if our buffer was too small. if (returnLength > bufferLength) { PhDereferenceObject(buffer); bufferLength = returnLength; buffer = PhCreateStringEx(NULL, (bufferLength - 1) * 2); if (!SUCCEEDED(IXCLRDataAppDomain_GetName(appDomain, bufferLength, &returnLength, buffer->Buffer))) { PhDereferenceObject(buffer); return NULL; } } buffer->Length = (returnLength - 1) * 2; return buffer; }
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; }
PPH_STRING GetSystemTemp(VOID) { PPH_STRING dirPath; ULONG dirPathLength; // Query the directory length... dirPathLength = GetTempPath(0, NULL); // Allocate the string... dirPath = PhCreateStringEx(NULL, dirPathLength * sizeof(TCHAR)); // Query the directory path... if (!GetTempPath(dirPath->Length, dirPath->Buffer)) { PhDereferenceObject(dirPath); return NULL; } return dirPath; }
VOID EtDiskProcessFileEvent( __in PET_ETW_FILE_EVENT Event ) { PH_KEY_VALUE_PAIR pair; PPH_KEY_VALUE_PAIR realPair; if (!EtDiskEnabled) return; if (Event->Type == EtEtwFileCreateType || Event->Type == EtEtwFileRundownType) { pair.Key = Event->FileObject; pair.Value = NULL; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhAddEntryHashtableEx(EtFileNameHashtable, &pair, NULL); PhSwapReference2(&realPair->Value, PhCreateStringEx(Event->FileName.Buffer, Event->FileName.Length)); PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } else if (Event->Type == EtEtwFileDeleteType) { pair.Key = Event->FileObject; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhFindEntryHashtable(EtFileNameHashtable, &pair); if (realPair) { PhDereferenceObject(realPair->Value); PhRemoveEntryHashtable(EtFileNameHashtable, &pair); } PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } }
PDB_OBJECT CreateDbObject( _In_ ULONG Tag, _In_ PPH_STRINGREF Name, _In_opt_ PPH_STRING Comment ) { PDB_OBJECT object; BOOLEAN added; PDB_OBJECT *realObject; object = PhAllocate(sizeof(DB_OBJECT)); memset(object, 0, sizeof(DB_OBJECT)); object->Tag = Tag; object->Key = *Name; object->BackColor = ULONG_MAX; realObject = PhAddEntryHashtableEx(ObjectDb, &object, &added); if (added) { object->Name = PhCreateStringEx(Name->Buffer, Name->Length); object->Key = object->Name->sr; if (Comment) PhSetReference(&object->Comment, Comment); else object->Comment = PhReferenceEmptyString(); } else { PhFree(object); object = *realObject; if (Comment) PhSwapReference(&object->Comment, Comment); } return object; }
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; }
PPH_STRING PhpResizeFormatBuffer( _In_ PPH_STRING String, _Inout_ PSIZE_T AllocatedLength, _In_ SIZE_T UsedLength, _In_ SIZE_T NeededLength ) { PPH_STRING newString; SIZE_T allocatedLength; allocatedLength = *AllocatedLength; allocatedLength *= 2; if (allocatedLength < UsedLength + NeededLength) allocatedLength = UsedLength + NeededLength; newString = PhCreateStringEx(NULL, allocatedLength); memcpy(newString->Buffer, String->Buffer, UsedLength); PhDereferenceObject(String); *AllocatedLength = allocatedLength; return newString; }
/** * 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; }
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; }
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); }
static VOID RemoveAppCompatEntry( _In_ HANDLE ParentKey ) { static PH_STRINGREF keyName = PH_STRINGREF_INIT(L"ProcessHacker.exe"); ULONG bufferLength; KEY_FULL_INFORMATION fullInfo; memset(&fullInfo, 0, sizeof(KEY_FULL_INFORMATION)); if (!NT_SUCCESS(NtQueryKey( ParentKey, KeyFullInformation, &fullInfo, sizeof(KEY_FULL_INFORMATION), &bufferLength ))) { return; } for (ULONG i = 0; i < fullInfo.Values; i++) { PPH_STRING value; PKEY_VALUE_FULL_INFORMATION buffer; bufferLength = sizeof(KEY_VALUE_FULL_INFORMATION); buffer = PhAllocate(bufferLength); memset(buffer, 0, bufferLength); if (NT_SUCCESS(NtEnumerateValueKey( ParentKey, i, KeyValueFullInformation, buffer, bufferLength, &bufferLength ))) { PhFree(buffer); break; } //bufferLength = bufferLength; buffer = PhReAllocate(buffer, bufferLength); memset(buffer, 0, bufferLength); if (!NT_SUCCESS(NtEnumerateValueKey( ParentKey, i, KeyValueFullInformation, buffer, bufferLength, &bufferLength ))) { PhFree(buffer); break; } if (value = PhCreateStringEx(buffer->Name, buffer->NameLength)) { UNICODE_STRING us; PhStringRefToUnicodeString(&value->sr, &us); if (PhEndsWithStringRef(&value->sr, &keyName, TRUE)) { NtDeleteValueKey(ParentKey, &us); } PhDereferenceObject(value); } PhFree(buffer); } }
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; }
VOID PhSetPluginDisabled( _In_ PPH_STRINGREF BaseName, _In_ BOOLEAN Disable ) { BOOLEAN found; PPH_STRING disabled; ULONG foundIndex; PPH_STRING newDisabled; disabled = PhGetStringSetting(L"DisabledPlugins"); found = PhpLocateDisabledPlugin(disabled, BaseName, &foundIndex); if (Disable && !found) { // We need to add the plugin to the disabled list. if (disabled->Length != 0) { // We have other disabled plugins. Append a pipe character followed by the plugin name. newDisabled = PhCreateStringEx(NULL, disabled->Length + sizeof(WCHAR) + BaseName->Length); memcpy(newDisabled->Buffer, disabled->Buffer, disabled->Length); newDisabled->Buffer[disabled->Length / 2] = '|'; memcpy(&newDisabled->Buffer[disabled->Length / 2 + 1], BaseName->Buffer, BaseName->Length); PhSetStringSetting2(L"DisabledPlugins", &newDisabled->sr); PhDereferenceObject(newDisabled); } else { // This is the first disabled plugin. PhSetStringSetting2(L"DisabledPlugins", BaseName); } } else if (!Disable && found) { ULONG removeCount; // We need to remove the plugin from the disabled list. removeCount = (ULONG)BaseName->Length / 2; if (foundIndex + (ULONG)BaseName->Length / 2 < (ULONG)disabled->Length / 2) { // Remove the following pipe character as well. removeCount++; } else if (foundIndex != 0) { // Remove the preceding pipe character as well. foundIndex--; removeCount++; } newDisabled = PhCreateStringEx(NULL, disabled->Length - removeCount * sizeof(WCHAR)); memcpy(newDisabled->Buffer, disabled->Buffer, foundIndex * sizeof(WCHAR)); memcpy(&newDisabled->Buffer[foundIndex], &disabled->Buffer[foundIndex + removeCount], disabled->Length - removeCount * sizeof(WCHAR) - foundIndex * sizeof(WCHAR)); PhSetStringSetting2(L"DisabledPlugins", &newDisabled->sr); PhDereferenceObject(newDisabled); } PhDereferenceObject(disabled); }
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++; }
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; }
ULONG PhGetWindowTextEx( _In_ HWND hwnd, _In_ ULONG Flags, _Out_opt_ PPH_STRING *Text ) { PPH_STRING string; ULONG length; if (Flags & PH_GET_WINDOW_TEXT_INTERNAL) { if (Flags & PH_GET_WINDOW_TEXT_LENGTH_ONLY) { WCHAR buffer[32]; length = InternalGetWindowText(hwnd, buffer, sizeof(buffer) / sizeof(WCHAR)); } else { // TODO: Resize the buffer until we get the entire thing. string = PhCreateStringEx(NULL, 256 * sizeof(WCHAR)); length = InternalGetWindowText(hwnd, string->Buffer, (ULONG)string->Length / sizeof(WCHAR) + 1); string->Length = length * sizeof(WCHAR); if (Text) *Text = string; else PhDereferenceObject(string); } return length; } else { length = GetWindowTextLength(hwnd); if (length == 0 || (Flags & PH_GET_WINDOW_TEXT_LENGTH_ONLY)) { if (Text) *Text = PhReferenceEmptyString(); return length; } string = PhCreateStringEx(NULL, length * sizeof(WCHAR)); if (GetWindowText(hwnd, string->Buffer, (ULONG)string->Length / sizeof(WCHAR) + 1)) { if (Text) *Text = string; else PhDereferenceObject(string); return length; } else { if (Text) *Text = PhReferenceEmptyString(); PhDereferenceObject(string); return 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; }
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; }
VOID NTAPI DotNetEventCallback( _In_ PEVENT_RECORD EventRecord ) { PASMPAGE_QUERY_CONTEXT context = EventRecord->UserContext; PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; if (UlongToHandle(eventHeader->ProcessId) == context->ProcessId) { // .NET 4.0+ switch (eventDescriptor->Id) { case RuntimeInformationDCStart: { PRuntimeInformationRundown data = EventRecord->UserData; PDNA_NODE node; PPH_STRING startupFlagsString; PPH_STRING startupModeString; // Check for duplicates. if (FindClrNode(context, data->ClrInstanceID)) break; node = AddNode(context); node->Type = DNA_TYPE_CLR; node->u.Clr.ClrInstanceID = data->ClrInstanceID; node->u.Clr.DisplayName = PhFormatString(L"CLR v%u.%u.%u.%u", data->VMMajorVersion, data->VMMinorVersion, data->VMBuildNumber, data->VMQfeNumber); node->StructureText = node->u.Clr.DisplayName->sr; node->IdText = PhFormatString(L"%u", data->ClrInstanceID); startupFlagsString = FlagsToString(data->StartupFlags, StartupFlagsMap, sizeof(StartupFlagsMap)); startupModeString = FlagsToString(data->StartupMode, StartupModeMap, sizeof(StartupModeMap)); if (startupFlagsString->Length != 0 && startupModeString->Length != 0) { node->FlagsText = PhConcatStrings(3, startupFlagsString->Buffer, L", ", startupModeString->Buffer); PhDereferenceObject(startupFlagsString); PhDereferenceObject(startupModeString); } else if (startupFlagsString->Length != 0) { node->FlagsText = startupFlagsString; PhDereferenceObject(startupModeString); } else if (startupModeString->Length != 0) { node->FlagsText = startupModeString; PhDereferenceObject(startupFlagsString); } if (data->CommandLine[0]) node->PathText = PhCreateString(data->CommandLine); PhAddItemList(context->NodeRootList, node); } break; case AppDomainDCStart_V1: { PAppDomainLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T appDomainNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; appDomainNameLength = PhCountStringZ(data->AppDomainName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AppDomainLoadUnloadRundown_V1, AppDomainName) + appDomainNameLength + sizeof(WCHAR) + sizeof(ULONG)); // Find the CLR node to add the AppDomain node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) { // Check for duplicates. if (FindAppDomainNode(parentNode, data->AppDomainID)) break; node = AddNode(context); node->Type = DNA_TYPE_APPDOMAIN; node->u.AppDomain.AppDomainID = data->AppDomainID; node->u.AppDomain.DisplayName = PhConcatStrings2(L"AppDomain: ", data->AppDomainName); node->StructureText = node->u.AppDomain.DisplayName->sr; node->IdText = PhFormatString(L"%I64u", data->AppDomainID); node->FlagsText = FlagsToString(data->AppDomainFlags, AppDomainFlagsMap, sizeof(AppDomainFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case AssemblyDCStart_V1: { PAssemblyLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T fullyQualifiedAssemblyNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; PH_STRINGREF remainingPart; fullyQualifiedAssemblyNameLength = PhCountStringZ(data->FullyQualifiedAssemblyName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AssemblyLoadUnloadRundown_V1, FullyQualifiedAssemblyName) + fullyQualifiedAssemblyNameLength + sizeof(WCHAR)); // Find the AppDomain node to add the Assembly node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) parentNode = FindAppDomainNode(parentNode, data->AppDomainID); if (parentNode) { // Check for duplicates. if (FindAssemblyNode(parentNode, data->AssemblyID)) break; node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->u.Assembly.AssemblyID = data->AssemblyID; node->u.Assembly.FullyQualifiedAssemblyName = PhCreateStringEx(data->FullyQualifiedAssemblyName, fullyQualifiedAssemblyNameLength); // Display only the assembly name, not the whole fully qualified name. if (!PhSplitStringRefAtChar(&node->u.Assembly.FullyQualifiedAssemblyName->sr, ',', &node->StructureText, &remainingPart)) node->StructureText = node->u.Assembly.FullyQualifiedAssemblyName->sr; node->IdText = PhFormatString(L"%I64u", data->AssemblyID); node->FlagsText = FlagsToString(data->AssemblyFlags, AssemblyFlagsMap, sizeof(AssemblyFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case ModuleDCStart_V1: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; USHORT clrInstanceID; PDNA_NODE node; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)moduleNativePath + moduleNativePathLength + sizeof(WCHAR)); // Find the Assembly node to set the path on. node = FindClrNode(context, clrInstanceID); if (node) node = FindAssemblyNode2(node, data->AssemblyID); if (node) { PhMoveReference(&node->PathText, PhCreateStringEx(moduleILPath, moduleILPathLength)); if (moduleNativePathLength != 0) PhMoveReference(&node->NativePathText, PhCreateStringEx(moduleNativePath, moduleNativePathLength)); } } break; case DCStartComplete_V1: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } // .NET 2.0 if (eventDescriptor->Id == 0) { switch (eventDescriptor->Opcode) { case CLR_MODULEDCSTART_OPCODE: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; PDNA_NODE node; ULONG_PTR indexOfBackslash; ULONG_PTR indexOfLastDot; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); if (context->ClrV2Node && (moduleILPathLength != 0 || moduleNativePathLength != 0)) { node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->FlagsText = FlagsToString(data->ModuleFlags, ModuleFlagsMap, sizeof(ModuleFlagsMap)); node->PathText = PhCreateStringEx(moduleILPath, moduleILPathLength); if (moduleNativePathLength != 0) node->NativePathText = PhCreateStringEx(moduleNativePath, moduleNativePathLength); // Use the name between the last backslash and the last dot for the structure column text. // (E.g. C:\...\AcmeSoft.BigLib.dll -> AcmeSoft.BigLib) indexOfBackslash = PhFindLastCharInString(node->PathText, 0, '\\'); indexOfLastDot = PhFindLastCharInString(node->PathText, 0, '.'); if (indexOfBackslash != -1) { node->StructureText.Buffer = node->PathText->Buffer + indexOfBackslash + 1; if (indexOfLastDot != -1 && indexOfLastDot > indexOfBackslash) { node->StructureText.Length = (indexOfLastDot - indexOfBackslash - 1) * sizeof(WCHAR); } else { node->StructureText.Length = node->PathText->Length - indexOfBackslash * sizeof(WCHAR) - sizeof(WCHAR); } } else { node->StructureText = node->PathText->sr; } PhAddItemList(context->ClrV2Node->Children, node); } } break; case CLR_METHODDC_DCSTARTCOMPLETE_OPCODE: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } } } }
NTSTATUS EspLoadOtherInfo( _In_ HWND hwndDlg, _In_ PSERVICE_OTHER_CONTEXT Context ) { NTSTATUS status = STATUS_SUCCESS; SC_HANDLE serviceHandle; ULONG returnLength; SERVICE_PRESHUTDOWN_INFO preshutdownInfo; LPSERVICE_REQUIRED_PRIVILEGES_INFO requiredPrivilegesInfo; SERVICE_SID_INFO sidInfo; SERVICE_LAUNCH_PROTECTED_INFO launchProtectedInfo; if (!(serviceHandle = PhOpenService(Context->ServiceItem->Name->Buffer, SERVICE_QUERY_CONFIG))) return NTSTATUS_FROM_WIN32(GetLastError()); // Preshutdown timeout if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_PRESHUTDOWN_INFO, (PBYTE)&preshutdownInfo, sizeof(SERVICE_PRESHUTDOWN_INFO), &returnLength )) { SetDlgItemInt(hwndDlg, IDC_PRESHUTDOWNTIMEOUT, preshutdownInfo.dwPreshutdownTimeout, FALSE); Context->PreshutdownTimeoutValid = TRUE; } // Required privileges if (requiredPrivilegesInfo = PhQueryServiceVariableSize(serviceHandle, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO)) { PWSTR privilege; ULONG privilegeLength; INT lvItemIndex; PH_STRINGREF privilegeSr; PPH_STRING privilegeString; PPH_STRING displayName; privilege = requiredPrivilegesInfo->pmszRequiredPrivileges; if (privilege) { while (TRUE) { privilegeLength = (ULONG)PhCountStringZ(privilege); if (privilegeLength == 0) break; privilegeString = PhCreateStringEx(privilege, privilegeLength * sizeof(WCHAR)); PhAddItemList(Context->PrivilegeList, privilegeString); lvItemIndex = PhAddListViewItem(Context->PrivilegesLv, MAXINT, privilege, privilegeString); privilegeSr.Buffer = privilege; privilegeSr.Length = privilegeLength * sizeof(WCHAR); if (PhLookupPrivilegeDisplayName(&privilegeSr, &displayName)) { PhSetListViewSubItem(Context->PrivilegesLv, lvItemIndex, 1, displayName->Buffer); PhDereferenceObject(displayName); } privilege += privilegeLength + 1; } } ExtendedListView_SortItems(Context->PrivilegesLv); PhFree(requiredPrivilegesInfo); Context->RequiredPrivilegesValid = TRUE; } // SID type if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_SERVICE_SID_INFO, (PBYTE)&sidInfo, sizeof(SERVICE_SID_INFO), &returnLength )) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_SIDTYPE), EspGetServiceSidTypeString(sidInfo.dwServiceSidType), FALSE); Context->SidTypeValid = TRUE; } // Launch protected if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_LAUNCH_PROTECTED, (PBYTE)&launchProtectedInfo, sizeof(SERVICE_LAUNCH_PROTECTED_INFO), &returnLength )) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_PROTECTION), EspGetServiceLaunchProtectedString(launchProtectedInfo.dwLaunchProtected), FALSE); Context->LaunchProtectedValid = TRUE; Context->OriginalLaunchProtected = launchProtectedInfo.dwLaunchProtected; } CloseServiceHandle(serviceHandle); return status; }
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; }
NTSTATUS NetworkPingThreadStart( _In_ PVOID Parameter ) { HANDLE icmpHandle = INVALID_HANDLE_VALUE; ULONG icmpCurrentPingMs = 0; ULONG icmpReplyCount = 0; ULONG icmpReplyLength = 0; PVOID icmpReplyBuffer = NULL; PPH_BYTES icmpEchoBuffer = NULL; IP_OPTION_INFORMATION pingOptions = { 255, // Time To Live 0, // Type Of Service IP_FLAG_DF, // IP header flags 0 // Size of options data }; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; __try { // Create ICMP echo buffer. if (context->PingSize > 0 && context->PingSize != 32) { PPH_STRING randString; randString = PhCreateStringEx(NULL, context->PingSize * 2 + 2); // Create a random string to fill the buffer. PhGenerateRandomAlphaString(randString->Buffer, (ULONG)randString->Length / sizeof(WCHAR)); icmpEchoBuffer = PhConvertUtf16ToMultiByte(randString->Buffer); PhDereferenceObject(randString); } else { PPH_STRING version; // We're using a default length, query the PH version and use the previous buffer format. version = PhGetPhVersion(); if (version) { icmpEchoBuffer = FormatAnsiString("processhacker_%S_0x0D06F00D_x1", version->Buffer); PhDereferenceObject(version); } } if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE) { SOCKADDR_IN6 icmp6LocalAddr = { 0 }; SOCKADDR_IN6 icmp6RemoteAddr = { 0 }; PICMPV6_ECHO_REPLY2 icmp6ReplyStruct = NULL; // Create ICMPv6 handle. if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv6-ANY address. icmp6LocalAddr.sin6_addr = in6addr_any; icmp6LocalAddr.sin6_family = AF_INET6; // Set Remote IPv6 address. icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr; icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port); // Allocate ICMPv6 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv6 ping... icmpReplyCount = Icmp6SendEcho2( icmpHandle, NULL, NULL, NULL, &icmp6LocalAddr, &icmp6RemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmp6ReplyStruct = (PICMPV6_ECHO_REPLY2)icmpReplyBuffer; if (icmpReplyCount > 0 && icmp6ReplyStruct) { BOOLEAN icmpPacketSignature = FALSE; if (icmp6ReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (_memicmp( icmp6ReplyStruct->Address.sin6_addr, context->IpAddress.In6Addr.u.Word, sizeof(icmp6ReplyStruct->Address.sin6_addr) ) != 0) { InterlockedIncrement(&context->UnknownAddrCount); } icmpPacketSignature = _memicmp( icmpEchoBuffer->Buffer, icmp6ReplyStruct->Data, icmpEchoBuffer->Length ) == 0; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime; } else { InterlockedIncrement(&context->PingLossCount); } } else { IPAddr icmpLocalAddr = 0; IPAddr icmpRemoteAddr = 0; PICMP_ECHO_REPLY icmpReplyStruct = NULL; // Create ICMPv4 handle. if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv4-ANY address. icmpLocalAddr = in4addr_any.s_addr; // Set Remote IPv4 address. icmpRemoteAddr = context->IpAddress.InAddr.s_addr; // Allocate ICMPv4 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv4 ping... icmpReplyCount = IcmpSendEcho2Ex( icmpHandle, NULL, NULL, NULL, icmpLocalAddr, icmpRemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyStruct && icmpReplyCount > 0) { BOOLEAN icmpPacketSignature = FALSE; if (icmpReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr) { InterlockedIncrement(&context->UnknownAddrCount); } if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length) { icmpPacketSignature = _memicmp( icmpEchoBuffer->Buffer, icmpReplyStruct->Data, icmpReplyStruct->DataSize ) == 0; } icmpCurrentPingMs = icmpReplyStruct->RoundTripTime; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } } else { InterlockedIncrement(&context->PingLossCount); } } InterlockedIncrement(&context->PingRecvCount); if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs) context->PingMinMs = icmpCurrentPingMs; if (icmpCurrentPingMs > context->PingMaxMs) context->PingMaxMs = icmpCurrentPingMs; context->CurrentPingMs = icmpCurrentPingMs; PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs); } __finally { if (icmpEchoBuffer) { PhDereferenceObject(icmpEchoBuffer); } if (icmpHandle != INVALID_HANDLE_VALUE) { IcmpCloseHandle(icmpHandle); } if (icmpReplyBuffer) { PhFree(icmpReplyBuffer); } } PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0); return STATUS_SUCCESS; }