VOID PhModuleProviderUpdate( _In_ PVOID Object ) { PPH_MODULE_PROVIDER moduleProvider = (PPH_MODULE_PROVIDER)Object; PPH_LIST modules; ULONG i; // If we didn't get a handle when we created the provider, // abort (unless this is the System process - in that case // we don't need a handle). if (!moduleProvider->ProcessHandle && moduleProvider->ProcessId != SYSTEM_PROCESS_ID) goto UpdateExit; modules = PhCreateList(20); moduleProvider->RunStatus = PhEnumGenericModules( moduleProvider->ProcessId, moduleProvider->ProcessHandle, PH_ENUM_GENERIC_MAPPED_FILES | PH_ENUM_GENERIC_MAPPED_IMAGES, EnumModulesCallback, modules ); // Look for removed modules. { PPH_LIST modulesToRemove = NULL; ULONG enumerationKey = 0; PPH_MODULE_ITEM *moduleItem; while (PhEnumHashtable(moduleProvider->ModuleHashtable, (PVOID *)&moduleItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the module still exists. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; if ((*moduleItem)->BaseAddress == module->BaseAddress && PhEqualString((*moduleItem)->FileName, module->FileName, TRUE)) { found = TRUE; break; } } if (!found) { // Raise the module removed event. PhInvokeCallback(&moduleProvider->ModuleRemovedEvent, *moduleItem); if (!modulesToRemove) modulesToRemove = PhCreateList(2); PhAddItemList(modulesToRemove, *moduleItem); } } if (modulesToRemove) { PhAcquireFastLockExclusive(&moduleProvider->ModuleHashtableLock); for (i = 0; i < modulesToRemove->Count; i++) { PhpRemoveModuleItem( moduleProvider, (PPH_MODULE_ITEM)modulesToRemove->Items[i] ); } PhReleaseFastLockExclusive(&moduleProvider->ModuleHashtableLock); PhDereferenceObject(modulesToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_MODULE_QUERY_DATA data; entry = RtlInterlockedFlushSList(&moduleProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_MODULE_QUERY_DATA, ListEntry); entry = entry->Next; data->ModuleItem->VerifyResult = data->VerifyResult; data->ModuleItem->VerifySignerName = data->VerifySignerName; data->ModuleItem->JustProcessed = TRUE; PhDereferenceObject(data->ModuleItem); PhFree(data); } } // Look for new modules. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; PPH_MODULE_ITEM moduleItem; moduleItem = PhReferenceModuleItem(moduleProvider, module->BaseAddress); if (!moduleItem) { moduleItem = PhCreateModuleItem(); moduleItem->BaseAddress = module->BaseAddress; PhPrintPointer(moduleItem->BaseAddressString, moduleItem->BaseAddress); moduleItem->Size = module->Size; moduleItem->Flags = module->Flags; moduleItem->Type = module->Type; moduleItem->LoadReason = module->LoadReason; moduleItem->LoadCount = module->LoadCount; moduleItem->LoadTime = module->LoadTime; moduleItem->Name = module->Name; PhReferenceObject(moduleItem->Name); moduleItem->FileName = module->FileName; PhReferenceObject(moduleItem->FileName); PhInitializeImageVersionInfo( &moduleItem->VersionInfo, PhGetString(moduleItem->FileName) ); moduleItem->IsFirst = i == 0; // Fix up the load count. If this is not an ordinary DLL or kernel module, set the load count to 0. if (moduleItem->Type != PH_MODULE_TYPE_MODULE && moduleItem->Type != PH_MODULE_TYPE_WOW64_MODULE && moduleItem->Type != PH_MODULE_TYPE_KERNEL_MODULE) { moduleItem->LoadCount = 0; } if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE || moduleItem->Type == PH_MODULE_TYPE_MAPPED_IMAGE) { PH_REMOTE_MAPPED_IMAGE remoteMappedImage; // Note: // On Windows 7 the LDRP_IMAGE_NOT_AT_BASE flag doesn't appear to be used // anymore. Instead we'll check ImageBase in the image headers. We read this in // from the process' memory because: // // 1. It (should be) faster than opening the file and mapping it in, and // 2. It contains the correct original image base relocated by ASLR, if present. moduleItem->Flags &= ~LDRP_IMAGE_NOT_AT_BASE; if (NT_SUCCESS(PhLoadRemoteMappedImage(moduleProvider->ProcessHandle, moduleItem->BaseAddress, &remoteMappedImage))) { moduleItem->ImageTimeDateStamp = remoteMappedImage.NtHeaders->FileHeader.TimeDateStamp; moduleItem->ImageCharacteristics = remoteMappedImage.NtHeaders->FileHeader.Characteristics; if (remoteMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { if ((ULONG_PTR)((PIMAGE_OPTIONAL_HEADER32)&remoteMappedImage.NtHeaders->OptionalHeader)->ImageBase != (ULONG_PTR)moduleItem->BaseAddress) moduleItem->Flags |= LDRP_IMAGE_NOT_AT_BASE; moduleItem->ImageDllCharacteristics = ((PIMAGE_OPTIONAL_HEADER32)&remoteMappedImage.NtHeaders->OptionalHeader)->DllCharacteristics; } else if (remoteMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { if ((ULONG_PTR)((PIMAGE_OPTIONAL_HEADER64)&remoteMappedImage.NtHeaders->OptionalHeader)->ImageBase != (ULONG_PTR)moduleItem->BaseAddress) moduleItem->Flags |= LDRP_IMAGE_NOT_AT_BASE; moduleItem->ImageDllCharacteristics = ((PIMAGE_OPTIONAL_HEADER64)&remoteMappedImage.NtHeaders->OptionalHeader)->DllCharacteristics; } PhUnloadRemoteMappedImage(&remoteMappedImage); } } if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_KERNEL_MODULE || moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE || moduleItem->Type == PH_MODULE_TYPE_MAPPED_IMAGE) { // See if the file has already been verified; if not, queue for verification. moduleItem->VerifyResult = PhVerifyFileCached(moduleItem->FileName, NULL, &moduleItem->VerifySignerName, TRUE); if (moduleItem->VerifyResult == VrUnknown) PhpQueueModuleQuery(moduleProvider, moduleItem); } // Add the module item to the hashtable. PhAcquireFastLockExclusive(&moduleProvider->ModuleHashtableLock); PhAddEntryHashtable(moduleProvider->ModuleHashtable, &moduleItem); PhReleaseFastLockExclusive(&moduleProvider->ModuleHashtableLock); // Raise the module added event. PhInvokeCallback(&moduleProvider->ModuleAddedEvent, moduleItem); } else { BOOLEAN modified = FALSE; if (moduleItem->JustProcessed) modified = TRUE; moduleItem->JustProcessed = FALSE; if (modified) PhInvokeCallback(&moduleProvider->ModuleModifiedEvent, moduleItem); PhDereferenceObject(moduleItem); } } // Free the modules list. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; PhDereferenceObject(module->Name); PhDereferenceObject(module->FileName); PhFree(module); } PhDereferenceObject(modules); UpdateExit: PhInvokeCallback(&moduleProvider->UpdatedEvent, NULL); }
PPH_STRING PhGetProcessTooltipText( _In_ PPH_PROCESS_ITEM Process, _Out_opt_ PULONG ValidToTickCount ) { PH_STRING_BUILDER stringBuilder; ULONG validForMs = 60 * 60 * 1000; // 1 hour PPH_STRING tempString; PH_KNOWN_PROCESS_TYPE knownProcessType = UnknownProcessType; PhInitializeStringBuilder(&stringBuilder, 200); // Command line if (Process->CommandLine) { tempString = PhEllipsisString(Process->CommandLine, 100 * 10); // This is necessary because the tooltip control seems to use some kind of O(n^9999) word-wrapping // algorithm. PhpAppendStringWithLineBreaks(&stringBuilder, &tempString->sr, 100, NULL); PhAppendCharStringBuilder(&stringBuilder, '\n'); PhDereferenceObject(tempString); } // File information tempString = PhFormatImageVersionInfo( Process->FileName, &Process->VersionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"File:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); // Known command line information if (Process->QueryHandle) PhGetProcessKnownType(Process->QueryHandle, &knownProcessType); if (Process->CommandLine && Process->QueryHandle) { PH_KNOWN_PROCESS_COMMAND_LINE knownCommandLine; if (knownProcessType != UnknownProcessType && PhaGetProcessKnownCommandLine( Process->CommandLine, knownProcessType, &knownCommandLine )) { switch (knownProcessType & KnownProcessTypeMask) { case ServiceHostProcessType: PhAppendStringBuilder2(&stringBuilder, L"Service group name:\n "); PhAppendStringBuilder(&stringBuilder, &knownCommandLine.ServiceHost.GroupName->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); break; case RunDllAsAppProcessType: { PH_IMAGE_VERSION_INFO versionInfo; if (PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.RunDllAsApp.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.RunDllAsApp.FileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"Run DLL target file:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; case ComSurrogateProcessType: { PH_IMAGE_VERSION_INFO versionInfo; PPH_STRING guidString; PhAppendStringBuilder2(&stringBuilder, L"COM target:\n"); if (knownCommandLine.ComSurrogate.Name) { PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &knownCommandLine.ComSurrogate.Name->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (guidString = PhFormatGuid(&knownCommandLine.ComSurrogate.Guid)) { PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &guidString->sr); PhDereferenceObject(guidString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (knownCommandLine.ComSurrogate.FileName && PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.ComSurrogate.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.ComSurrogate.FileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"COM target file:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; } } } // Services if (Process->ServiceList && Process->ServiceList->Count != 0) { ULONG enumerationKey = 0; PPH_SERVICE_ITEM serviceItem; PPH_LIST serviceList; ULONG i; // Copy the service list into our own list so we can sort it. serviceList = PhCreateList(Process->ServiceList->Count); PhAcquireQueuedLockShared(&Process->ServiceListLock); while (PhEnumPointerList( Process->ServiceList, &enumerationKey, &serviceItem )) { PhReferenceObject(serviceItem); PhAddItemList(serviceList, serviceItem); } PhReleaseQueuedLockShared(&Process->ServiceListLock); qsort(serviceList->Items, serviceList->Count, sizeof(PPH_SERVICE_ITEM), ServiceForTooltipCompare); PhAppendStringBuilder2(&stringBuilder, L"Services:\n"); // Add the services. for (i = 0; i < serviceList->Count; i++) { serviceItem = serviceList->Items[i]; PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &serviceItem->Name->sr); PhAppendStringBuilder2(&stringBuilder, L" ("); PhAppendStringBuilder(&stringBuilder, &serviceItem->DisplayName->sr); PhAppendStringBuilder2(&stringBuilder, L")\n"); } PhDereferenceObjects(serviceList->Items, serviceList->Count); PhDereferenceObject(serviceList); } // Tasks, Drivers switch (knownProcessType & KnownProcessTypeMask) { case TaskHostProcessType: { PH_STRING_BUILDER tasks; PhInitializeStringBuilder(&tasks, 40); PhpFillRunningTasks(Process, &tasks); if (tasks.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Tasks:\n"); PhAppendStringBuilder(&stringBuilder, &tasks.String->sr); } PhDeleteStringBuilder(&tasks); } break; case UmdfHostProcessType: { PH_STRING_BUILDER drivers; PhInitializeStringBuilder(&drivers, 40); PhpFillUmdfDrivers(Process, &drivers); if (drivers.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Drivers:\n"); PhAppendStringBuilder(&stringBuilder, &drivers.String->sr); } PhDeleteStringBuilder(&drivers); validForMs = 10 * 1000; // 10 seconds } break; } // Plugin if (PhPluginsEnabled) { PH_PLUGIN_GET_TOOLTIP_TEXT getTooltipText; getTooltipText.Parameter = Process; getTooltipText.StringBuilder = &stringBuilder; getTooltipText.ValidForMs = validForMs; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackGetProcessTooltipText), &getTooltipText); validForMs = getTooltipText.ValidForMs; } // Notes { PH_STRING_BUILDER notes; PhInitializeStringBuilder(¬es, 40); if (Process->FileName) { if (Process->VerifyResult == VrTrusted) { if (!PhIsNullOrEmptyString(Process->VerifySignerName)) PhAppendFormatStringBuilder(¬es, L" Signer: %s\n", Process->VerifySignerName->Buffer); else PhAppendStringBuilder2(¬es, L" Signed.\n"); } else if (Process->VerifyResult == VrUnknown) { // Nothing } else if (Process->VerifyResult != VrNoSignature) { PhAppendStringBuilder2(¬es, L" Signature invalid.\n"); } } if (Process->IsPacked) { PhAppendFormatStringBuilder( ¬es, L" Image is probably packed (%u imports over %u modules).\n", Process->ImportFunctions, Process->ImportModules ); } if ((ULONG_PTR)Process->ConsoleHostProcessId & ~3) { CLIENT_ID clientId; PWSTR description = L"Console host"; PPH_STRING clientIdString; clientId.UniqueProcess = (HANDLE)((ULONG_PTR)Process->ConsoleHostProcessId & ~3); clientId.UniqueThread = NULL; if ((ULONG_PTR)Process->ConsoleHostProcessId & 2) description = L"Console application"; clientIdString = PhGetClientIdName(&clientId); PhAppendFormatStringBuilder(¬es, L" %s: %s\n", description, clientIdString->Buffer); PhDereferenceObject(clientIdString); } if (Process->PackageFullName) { PhAppendFormatStringBuilder(¬es, L" Package name: %s\n", Process->PackageFullName->Buffer); } if (Process->IsDotNet) PhAppendStringBuilder2(¬es, L" Process is managed (.NET).\n"); if (Process->IsElevated) PhAppendStringBuilder2(¬es, L" Process is elevated.\n"); if (Process->IsImmersive) PhAppendStringBuilder2(¬es, L" Process is a Modern UI app.\n"); if (Process->IsInJob) PhAppendStringBuilder2(¬es, L" Process is in a job.\n"); if (Process->IsPosix) PhAppendStringBuilder2(¬es, L" Process is POSIX.\n"); if (Process->IsWow64) PhAppendStringBuilder2(¬es, L" Process is 32-bit (WOW64).\n"); if (notes.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Notes:\n"); PhAppendStringBuilder(&stringBuilder, ¬es.String->sr); } PhDeleteStringBuilder(¬es); } if (ValidToTickCount) *ValidToTickCount = GetTickCount() + validForMs; // Remove the trailing newline. if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
INT_PTR CALLBACK EtpModuleServicesDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PMODULE_SERVICES_CONTEXT context = (PMODULE_SERVICES_CONTEXT)lParam; ULONG win32Result; PQUERY_TAG_INFORMATION I_QueryTagInformation; TAG_INFO_NAMES_REFERENCING_MODULE namesReferencingModule; PPH_LIST serviceList; PPH_SERVICE_ITEM *serviceItems; HWND serviceListHandle; RECT rect; PPH_PROCESS_ITEM processItem; PPH_STRING message; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); I_QueryTagInformation = PhGetModuleProcAddress(L"advapi32.dll", "I_QueryTagInformation"); if (!I_QueryTagInformation) { PhShowError(hwndDlg, L"Unable to query services because the feature is not supported by the operating system."); EndDialog(hwndDlg, IDCANCEL); return FALSE; } memset(&namesReferencingModule, 0, sizeof(TAG_INFO_NAMES_REFERENCING_MODULE)); namesReferencingModule.InParams.dwPid = HandleToUlong(context->ProcessId); namesReferencingModule.InParams.pszModule = context->ModuleName; win32Result = I_QueryTagInformation(NULL, eTagInfoLevelNamesReferencingModule, &namesReferencingModule); if (win32Result == ERROR_NO_MORE_ITEMS) win32Result = 0; if (win32Result != 0) { PhShowStatus(hwndDlg, L"Unable to query services", 0, win32Result); EndDialog(hwndDlg, IDCANCEL); return FALSE; } serviceList = PhCreateList(16); if (namesReferencingModule.OutParams.pmszNames) { PPH_SERVICE_ITEM serviceItem; PWSTR serviceName; ULONG nameLength; serviceName = namesReferencingModule.OutParams.pmszNames; while (TRUE) { nameLength = (ULONG)PhCountStringZ(serviceName); if (nameLength == 0) break; if (serviceItem = PhReferenceServiceItem(serviceName)) PhAddItemList(serviceList, serviceItem); serviceName += nameLength + 1; } LocalFree(namesReferencingModule.OutParams.pmszNames); } serviceItems = PhAllocateCopy(serviceList->Items, serviceList->Count * sizeof(PPH_SERVICE_ITEM)); PhDereferenceObject(serviceList); serviceListHandle = PhCreateServiceListControl(hwndDlg, serviceItems, serviceList->Count); // Position the control. GetWindowRect(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), &rect); MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2); MoveWindow(serviceListHandle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, FALSE); ShowWindow(serviceListHandle, SW_SHOW); if (processItem = PhReferenceProcessItem(context->ProcessId)) { message = PhFormatString(L"Services referencing %s in %s:", context->ModuleName, processItem->ProcessName->Buffer); PhDereferenceObject(processItem); } else { message = PhFormatString(L"Services referencing %s:", context->ModuleName); } SetDlgItemText(hwndDlg, IDC_MESSAGE, message->Buffer); PhDereferenceObject(message); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; } return FALSE; }
INT_PTR CALLBACK EspServiceDependentsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PSERVICE_LIST_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT)); memset(context, 0, sizeof(SERVICE_LIST_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam; HWND serviceListHandle; PPH_LIST serviceList; SC_HANDLE serviceHandle; ULONG win32Result = 0; BOOLEAN success = FALSE; PPH_SERVICE_ITEM *services; SetDlgItemText(hwndDlg, IDC_MESSAGE, L"The following services depend on this service:"); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL); if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_ENUMERATE_DEPENDENTS)) { LPENUM_SERVICE_STATUS dependentServices; ULONG numberOfDependentServices; if (dependentServices = EsEnumDependentServices(serviceHandle, 0, &numberOfDependentServices)) { ULONG i; PPH_SERVICE_ITEM dependentService; serviceList = PhCreateList(8); success = TRUE; for (i = 0; i < numberOfDependentServices; i++) { if (dependentService = PhReferenceServiceItem(dependentServices[i].lpServiceName)) PhAddItemList(serviceList, dependentService); } services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count); serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count); context->ServiceListHandle = serviceListHandle; EspLayoutServiceListControl(hwndDlg, serviceListHandle); ShowWindow(serviceListHandle, SW_SHOW); PhDereferenceObject(serviceList); PhFree(dependentServices); } else { win32Result = GetLastError(); } CloseServiceHandle(serviceHandle); } else { win32Result = GetLastError(); } if (!success) { SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependents: ", ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer); ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW); } } break; case WM_DESTROY: { PhDeleteLayoutManager(&context->LayoutManager); PhFree(context); } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); if (context->ServiceListHandle) EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle); } break; } return FALSE; }
VOID NTAPI DotNetEventCallback( _In_ PEVENT_RECORD EventRecord ) { PASMPAGE_CONTEXT context = EventRecord->UserContext; PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; if (UlongToHandle(eventHeader->ProcessId) == context->ProcessItem->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; } } } }
static VOID FilterResults( _In_ HWND hwndDlg, _In_ PMEMORY_RESULTS_CONTEXT Context, _In_ ULONG Type ) { PPH_STRING selectedChoice = NULL; PPH_LIST results; pcre2_code *compiledExpression; pcre2_match_data *matchData; results = Context->Results; SetCursor(LoadCursor(NULL, IDC_WAIT)); while (PhaChoiceDialog( hwndDlg, L"Filter", L"Enter the filter pattern:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemFilterChoices" )) { PPH_LIST newResults = NULL; ULONG i; if (Type == FILTER_CONTAINS || Type == FILTER_CONTAINS_IGNORECASE) { newResults = PhCreateList(1024); if (Type == FILTER_CONTAINS) { for (i = 0; i < results->Count; i++) { PPH_MEMORY_RESULT result = results->Items[i]; if (wcsstr(result->Display.Buffer, selectedChoice->Buffer)) { PhReferenceMemoryResult(result); PhAddItemList(newResults, result); } } } else { PPH_STRING upperChoice; upperChoice = PhaUpperString(selectedChoice); for (i = 0; i < results->Count; i++) { PPH_MEMORY_RESULT result = results->Items[i]; PWSTR upperDisplay; upperDisplay = PhAllocateForMemorySearch(result->Display.Length + sizeof(WCHAR)); // Copy the null terminator as well. memcpy(upperDisplay, result->Display.Buffer, result->Display.Length + sizeof(WCHAR)); _wcsupr(upperDisplay); if (wcsstr(upperDisplay, upperChoice->Buffer)) { PhReferenceMemoryResult(result); PhAddItemList(newResults, result); } PhFreeForMemorySearch(upperDisplay); } } } else if (Type == FILTER_REGEX || Type == FILTER_REGEX_IGNORECASE) { int errorCode; PCRE2_SIZE errorOffset; compiledExpression = pcre2_compile( selectedChoice->Buffer, selectedChoice->Length / sizeof(WCHAR), (Type == FILTER_REGEX_IGNORECASE ? PCRE2_CASELESS : 0) | PCRE2_DOTALL, &errorCode, &errorOffset, NULL ); if (!compiledExpression) { PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", PhGetStringOrDefault(PH_AUTO(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), errorOffset ); continue; } matchData = pcre2_match_data_create_from_pattern(compiledExpression, NULL); newResults = PhCreateList(1024); for (i = 0; i < results->Count; i++) { PPH_MEMORY_RESULT result = results->Items[i]; if (pcre2_match( compiledExpression, result->Display.Buffer, result->Display.Length / sizeof(WCHAR), 0, 0, matchData, NULL ) >= 0) { PhReferenceMemoryResult(result); PhAddItemList(newResults, result); } } pcre2_match_data_free(matchData); pcre2_code_free(compiledExpression); } if (newResults) { PhShowMemoryResultsDialog(Context->ProcessId, newResults); PhDereferenceMemoryResults((PPH_MEMORY_RESULT *)newResults->Items, newResults->Count); PhDereferenceObject(newResults); break; } } SetCursor(LoadCursor(NULL, IDC_ARROW)); }
INT_PTR CALLBACK PhpColumnsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PCOLUMNS_DIALOG_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PCOLUMNS_DIALOG_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PCOLUMNS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { ULONG count; ULONG total; ULONG i; PPH_LIST displayOrderList; context->InactiveList = GetDlgItem(hwndDlg, IDC_INACTIVE); context->ActiveList = GetDlgItem(hwndDlg, IDC_ACTIVE); if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { PH_TREENEW_COLUMN column; count = 0; total = TreeNew_GetColumnCount(context->ControlHandle); i = 0; displayOrderList = PhCreateList(total); while (count < total) { if (TreeNew_GetColumn(context->ControlHandle, i, &column)) { PPH_TREENEW_COLUMN copy; if (column.Fixed) { i++; total--; continue; } copy = PhAllocateCopy(&column, sizeof(PH_TREENEW_COLUMN)); PhAddItemList(context->Columns, copy); count++; if (column.Visible) { PhAddItemList(displayOrderList, copy); } else { ListBox_AddString(context->InactiveList, column.Text); } } i++; } qsort(displayOrderList->Items, displayOrderList->Count, sizeof(PVOID), PhpColumnsCompareDisplayIndexTn); } for (i = 0; i < displayOrderList->Count; i++) { if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { PPH_TREENEW_COLUMN copy = displayOrderList->Items[i]; ListBox_AddString(context->ActiveList, copy->Text); } } PhDereferenceObject(displayOrderList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } break; case WM_DESTROY: { ULONG i; for (i = 0; i < context->Columns->Count; i++) PhFree(context->Columns->Items[i]); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { #define ORDER_LIMIT 100 PPH_LIST activeList; ULONG activeCount; ULONG i; INT orderArray[ORDER_LIMIT]; INT maxOrder; memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; activeCount = ListBox_GetCount(context->ActiveList); activeList = PhCreateList(activeCount); for (i = 0; i < activeCount; i++) PhAddItemList(activeList, PhGetListBoxString(context->ActiveList, i)); if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { // Apply visiblity settings. TreeNew_SetRedraw(context->ControlHandle, FALSE); for (i = 0; i < context->Columns->Count; i++) { PPH_TREENEW_COLUMN column = context->Columns->Items[i]; ULONG index; index = IndexOfStringInList(activeList, column->Text); column->Visible = index != -1; column->DisplayIndex = index; // the active list box order is the actual display order TreeNew_SetColumn(context->ControlHandle, TN_COLUMN_FLAG_VISIBLE, column); } // Do a second pass to create the order array. This is because the ViewIndex of each column // were unstable in the previous pass since we were both adding and removing columns. for (i = 0; i < context->Columns->Count; i++) { PPH_TREENEW_COLUMN column = context->Columns->Items[i]; PH_TREENEW_COLUMN tempColumn; if (column->Visible) { if (column->DisplayIndex < ORDER_LIMIT) { TreeNew_GetColumn(context->ControlHandle, column->Id, &tempColumn); orderArray[column->DisplayIndex] = tempColumn.s.ViewIndex; if ((ULONG)maxOrder < column->DisplayIndex + 1) maxOrder = column->DisplayIndex + 1; } } } // Apply display order. TreeNew_SetColumnOrderArray(context->ControlHandle, maxOrder, orderArray); TreeNew_SetRedraw(context->ControlHandle, TRUE); PhDereferenceObject(activeList); InvalidateRect(context->ControlHandle, NULL, FALSE); } EndDialog(hwndDlg, IDOK); } break; case IDC_INACTIVE: { switch (HIWORD(wParam)) { case LBN_DBLCLK: { SendMessage(hwndDlg, WM_COMMAND, IDC_SHOW, 0); } break; case LBN_SELCHANGE: { INT sel = ListBox_GetCurSel(context->InactiveList); EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW), sel != -1); } break; } } break; case IDC_ACTIVE: { switch (HIWORD(wParam)) { case LBN_DBLCLK: { SendMessage(hwndDlg, WM_COMMAND, IDC_HIDE, 0); } break; case LBN_SELCHANGE: { INT sel = ListBox_GetCurSel(context->ActiveList); INT count = ListBox_GetCount(context->ActiveList); EnableWindow(GetDlgItem(hwndDlg, IDC_HIDE), sel != -1 && count != 1); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0 && sel != -1); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1 && sel != -1); } break; } } break; case IDC_SHOW: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->InactiveList); count = ListBox_GetCount(context->InactiveList); if (string = PhGetListBoxString(context->InactiveList, sel)) { ListBox_DeleteString(context->InactiveList, sel); ListBox_AddString(context->ActiveList, string->Buffer); PhDereferenceObject(string); count--; if (sel >= count - 1) sel = count - 1; ListBox_SetCurSel(context->InactiveList, sel); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } } break; case IDC_HIDE: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (count != 1) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_AddString(context->InactiveList, string->Buffer); PhDereferenceObject(string); count--; if (sel >= count - 1) sel = count - 1; ListBox_SetCurSel(context->ActiveList, sel); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } } } break; case IDC_MOVEUP: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (sel != 0) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_InsertString(context->ActiveList, sel - 1, string->Buffer); PhDereferenceObject(string); sel -= 1; ListBox_SetCurSel(context->ActiveList, sel); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); } } } break; case IDC_MOVEDOWN: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (sel != count - 1) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_InsertString(context->ActiveList, sel + 1, string->Buffer); PhDereferenceObject(string); sel += 1; ListBox_SetCurSel(context->ActiveList, sel); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); } } } break; } } break; } return FALSE; }
NTSTATUS NTAPI VirusTotalProcessApiThread( _In_ PVOID Parameter ) { LONG priority; IO_PRIORITY_HINT ioPriority; // TODO: Workqueue support. priority = THREAD_PRIORITY_LOWEST; ioPriority = IoPriorityVeryLow; NtSetInformationThread(NtCurrentThread(), ThreadBasePriority, &priority, sizeof(LONG)); NtSetInformationThread(NtCurrentThread(), ThreadIoPriority, &ioPriority, sizeof(IO_PRIORITY_HINT)); Sleep(10 * 1000); do { ULONG i; INT64 resultLength; PSTR jsonArrayToSendString; PSTR jsonApiResult = NULL; PVOID jsonArray; PVOID rootJsonObject = NULL; PVOID dataJsonObject; PPH_LIST resultTempList = NULL; PPH_LIST virusTotalResults = NULL; jsonArray = CreateJsonArray(); resultTempList = PhCreateList(30); PhAcquireQueuedLockExclusive(&ProcessListLock); for (i = 0; i < VirusTotalList->Count; i++) { PVIRUSTOTAL_FILE_HASH_ENTRY extension = VirusTotalList->Items[i]; if (resultTempList->Count >= 30) break; if (!extension->Stage1) { extension->Stage1 = TRUE; PhAddItemList(resultTempList, extension); } } PhReleaseQueuedLockExclusive(&ProcessListLock); if (resultTempList->Count == 0) { Sleep(30 * 1000); // Wait 30 seconds goto CleanupExit; } for (i = 0; i < resultTempList->Count; i++) { VirusTotalBuildJsonArray(resultTempList->Items[i], jsonArray); } if (!(jsonArrayToSendString = GetJsonArrayString(jsonArray))) goto CleanupExit; if (!(jsonApiResult = VirusTotalSendHttpRequest(PhCreateBytes(jsonArrayToSendString)))) goto CleanupExit; if (!(rootJsonObject = CreateJsonParser(jsonApiResult))) goto CleanupExit; if (!(dataJsonObject = JsonGetObject(rootJsonObject, "data"))) goto CleanupExit; if (!(resultLength = GetJsonValueAsUlong(rootJsonObject, "result"))) goto CleanupExit; if (virusTotalResults = VirusTotalJsonToResultList(dataJsonObject)) { for (i = 0; i < virusTotalResults->Count; i++) { PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i]; if (result->Found) { PVIRUSTOTAL_FILE_HASH_ENTRY entry = VirusTotalGetCachedResultFromHash(result->FileHash); if (entry && !entry->Processed) { entry->Processed = TRUE; entry->Found = result->Found; entry->Positives = result->Positives; entry->Total = result->Total; if (!FindProcessDbObject(&entry->FileName->sr)) { CreateProcessDbObject( entry->FileName, entry->Positives, entry->Total, result->FileHash ); } } } } } CleanupExit: if (virusTotalResults) { for (i = 0; i < virusTotalResults->Count; i++) { PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i]; // PhClearReference(&result->Permalink); // PhClearReference(&result->FileHash); // PhClearReference(&result->DetectionRatio); // PhFree(result); } PhDereferenceObject(virusTotalResults); } if (rootJsonObject) { CleanupJsonParser(rootJsonObject); } if (jsonArray) { CleanupJsonParser(jsonArray); } if (jsonApiResult) { PhFree(jsonApiResult); } if (resultTempList) { // Re-queue items without any results from VirusTotal. //for (i = 0; i < resultTempList->Count; i++) //{ // PVIRUSTOTAL_FILE_HASH_ENTRY result = resultTempList->Items[i]; // PPROCESS_EXTENSION extension = result->Extension; // // if (extension->Retries > 3) // continue; // // if (PhIsNullOrEmptyString(result->FileResult)) // { // extension->Stage1 = FALSE; // } // // extension->Retries++; //} PhDereferenceObject(resultTempList); } Sleep(5 * 1000); // Wait 5 seconds } while (VirusTotalHandle); return STATUS_SUCCESS; }
VOID FindNetworkAdapters( _In_ PDV_NETADAPTER_CONTEXT Context ) { if (Context->UseAlternateMethod) { ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_ALL_INTERFACES; ULONG bufferLength = 0; PVOID buffer; if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &bufferLength) != ERROR_BUFFER_OVERFLOW) return; buffer = PhAllocate(bufferLength); memset(buffer, 0, bufferLength); if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, buffer, &bufferLength) == ERROR_SUCCESS) { PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (PIP_ADAPTER_ADDRESSES i = buffer; i; i = i->Next) { PPH_STRING description; if (description = PhCreateString(i->Description)) { AddNetworkAdapterToListView( Context, TRUE, i->IfIndex, i->Luid, PhConvertMultiByteToUtf16(i->AdapterName), description ); PhDereferenceObject(description); } } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } PhFree(buffer); } else { static PH_STRINGREF devicePathSr = PH_STRINGREF_INIT(L"\\\\.\\"); PPH_LIST deviceList; PWSTR deviceInterfaceList; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DEVINTERFACE_NET, NULL, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { return; } deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR)); memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR)); if (CM_Get_Device_Interface_List( (PGUID)&GUID_DEVINTERFACE_NET, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return; } deviceList = PH_AUTO(PhCreateList(1)); for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { HKEY keyHandle; DEVINST deviceInstanceHandle; PPH_STRING deviceDescription = NULL; if (!QueryNetworkDeviceInterfaceDescription(deviceInterface, &deviceInstanceHandle, &deviceDescription)) continue; if (CM_Open_DevInst_Key( deviceInstanceHandle, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &keyHandle, CM_REGISTRY_SOFTWARE ) == CR_SUCCESS) { PNET_ENUM_ENTRY adapterEntry; HANDLE deviceHandle; adapterEntry = PhAllocate(sizeof(NET_ENUM_ENTRY)); memset(adapterEntry, 0, sizeof(NET_ENUM_ENTRY)); adapterEntry->DeviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId"); adapterEntry->DeviceInterface = PhConcatStringRef2(&devicePathSr, &adapterEntry->DeviceGuid->sr); adapterEntry->DeviceLuid.Info.IfType = PhQueryRegistryUlong64(keyHandle, L"*IfType"); adapterEntry->DeviceLuid.Info.NetLuidIndex = PhQueryRegistryUlong64(keyHandle, L"NetLuidIndex"); if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, PhGetString(adapterEntry->DeviceInterface), FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { PPH_STRING adapterName; // Try query the full adapter name adapterName = NetworkAdapterQueryName(deviceHandle, adapterEntry->DeviceGuid); if (adapterName) adapterEntry->DeviceName = adapterName; adapterEntry->DevicePresent = TRUE; NtClose(deviceHandle); } if (!adapterEntry->DeviceName) adapterEntry->DeviceName = PhCreateString2(&deviceDescription->sr); PhAddItemList(deviceList, adapterEntry); NtClose(keyHandle); } PhClearReference(&deviceDescription); } // Cleanup. PhFree(deviceInterfaceList); // Sort the entries qsort(deviceList->Items, deviceList->Count, sizeof(PVOID), AdapterEntryCompareFunction); PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < deviceList->Count; i++) { PNET_ENUM_ENTRY entry = deviceList->Items[i]; AddNetworkAdapterToListView( Context, entry->DevicePresent, 0, entry->DeviceLuid, entry->DeviceGuid, entry->DeviceName ); if (entry->DeviceName) PhDereferenceObject(entry->DeviceName); if (entry->DeviceInterface) PhDereferenceObject(entry->DeviceInterface); // Note: DeviceGuid is disposed by WM_DESTROY. PhFree(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } // HACK: Show all unknown devices. PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < NetworkAdaptersList->Count; i++) { ULONG index = ULONG_MAX; BOOLEAN found = FALSE; PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]); if (!entry) continue; while ((index = PhFindListViewItemByFlags( Context->ListViewHandle, index, LVNI_ALL )) != ULONG_MAX) { PDV_NETADAPTER_ID param; if (PhGetListViewItemParam(Context->ListViewHandle, index, ¶m)) { if (EquivalentNetAdapterId(param, &entry->AdapterId)) { found = TRUE; } } } if (!found) { PPH_STRING description; MIB_IF_ROW2 interfaceRow; memset(&interfaceRow, 0, sizeof(MIB_IF_ROW2)); interfaceRow.InterfaceLuid = entry->AdapterId.InterfaceLuid; interfaceRow.InterfaceIndex = entry->AdapterId.InterfaceIndex; // HACK: Try query the description from the interface entry (if it exists). if (GetIfEntry2(&interfaceRow) == NO_ERROR) description = PhCreateString(interfaceRow.Description); else description = PhCreateString(L"Unknown network adapter"); if (description) { AddNetworkAdapterToListView( Context, FALSE, entry->AdapterId.InterfaceIndex, entry->AdapterId.InterfaceLuid, entry->AdapterId.InterfaceGuid, description ); PhDereferenceObject(description); } } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); }
NTSTATUS PhpEnumHiddenProcessesBruteForce( _In_ PPH_ENUM_HIDDEN_PROCESSES_CALLBACK Callback, _In_opt_ PVOID Context ) { NTSTATUS status; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; PPH_LIST pids; ULONG pid; BOOLEAN stop = FALSE; if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) return status; pids = PhCreateList(40); process = PH_FIRST_PROCESS(processes); do { PhAddItemList(pids, process->UniqueProcessId); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); for (pid = 8; pid <= 65536; pid += 4) { NTSTATUS status2; HANDLE processHandle; PH_HIDDEN_PROCESS_ENTRY entry; KERNEL_USER_TIMES times; PPH_STRING fileName; status2 = PhOpenProcess( &processHandle, ProcessQueryAccess, UlongToHandle(pid) ); if (NT_SUCCESS(status2)) { entry.ProcessId = UlongToHandle(pid); if (NT_SUCCESS(status2 = PhGetProcessTimes( processHandle, × )) && NT_SUCCESS(status2 = PhGetProcessImageFileName( processHandle, &fileName ))) { entry.FileName = PhGetFileName(fileName); PhDereferenceObject(fileName); if (times.ExitTime.QuadPart != 0) entry.Type = TerminatedProcess; else if (PhFindItemList(pids, UlongToHandle(pid)) != -1) entry.Type = NormalProcess; else entry.Type = HiddenProcess; if (!Callback(&entry, Context)) stop = TRUE; PhDereferenceObject(entry.FileName); } NtClose(processHandle); } // Use an alternative method if we don't have sufficient access. if (status2 == STATUS_ACCESS_DENIED && WindowsVersion >= WINDOWS_VISTA) { if (NT_SUCCESS(status2 = PhGetProcessImageFileNameByProcessId(UlongToHandle(pid), &fileName))) { entry.ProcessId = UlongToHandle(pid); entry.FileName = PhGetFileName(fileName); PhDereferenceObject(fileName); if (PhFindItemList(pids, UlongToHandle(pid)) != -1) entry.Type = NormalProcess; else entry.Type = HiddenProcess; if (!Callback(&entry, Context)) stop = TRUE; PhDereferenceObject(entry.FileName); } } if (status2 == STATUS_INVALID_CID || status2 == STATUS_INVALID_PARAMETER) status2 = STATUS_SUCCESS; if (!NT_SUCCESS(status2)) { entry.ProcessId = UlongToHandle(pid); entry.FileName = NULL; entry.Type = UnknownProcess; if (!Callback(&entry, Context)) stop = TRUE; } if (stop) break; } PhDereferenceObject(pids); return status; }
BOOLEAN EtpInitializeD3DStatistics( VOID ) { LOGICAL result; HDEVINFO deviceInfoSet; ULONG memberIndex; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; SP_DEVINFO_DATA deviceInfoData; ULONG detailDataSize; D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; deviceInfoSet = SetupDiGetClassDevsW_I(&GUID_DISPLAY_DEVICE_ARRIVAL_I, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!deviceInfoSet) return FALSE; memberIndex = 0; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); while (SetupDiEnumDeviceInterfaces_I(deviceInfoSet, NULL, &GUID_DISPLAY_DEVICE_ARRIVAL_I, memberIndex, &deviceInterfaceData)) { detailDataSize = 0x100; detailData = PhAllocate(detailDataSize); detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!(result = SetupDiGetDeviceInterfaceDetailW_I(deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData)) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { PhFree(detailData); detailData = PhAllocate(detailDataSize); if (detailDataSize >= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)) detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); result = SetupDiGetDeviceInterfaceDetailW_I(deviceInfoSet, &deviceInterfaceData, detailData, detailDataSize, &detailDataSize, &deviceInfoData); } if (result) { openAdapterFromDeviceName.pDeviceName = detailData->DevicePath; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName_I(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics_I(&queryStatistics))) { PETP_GPU_ADAPTER gpuAdapter; ULONG i; gpuAdapter = EtpAllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); gpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; gpuAdapter->Description = EtpQueryDeviceDescription(deviceInfoSet, &deviceInfoData); gpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; gpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap(&gpuAdapter->ApertureBitMap, gpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments); PhAddItemList(EtpGpuAdapterList, gpuAdapter); EtGpuTotalNodeCount += gpuAdapter->NodeCount; EtGpuTotalSegmentCount += gpuAdapter->SegmentCount; gpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += gpuAdapter->NodeCount; for (i = 0; i < gpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics_I(&queryStatistics))) { ULONG64 commitLimit; ULONG aperture; commitLimit = queryStatistics.QueryResult.SegmentInformation.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformation.Aperture; if (aperture) EtGpuSharedLimit += commitLimit; else EtGpuDedicatedLimit += commitLimit; if (aperture) RtlSetBits(&gpuAdapter->ApertureBitMap, i, 1); } } } } } PhFree(detailData); memberIndex++; } SetupDiDestroyDeviceInfoList_I(deviceInfoSet); EtGpuNodeBitMapBuffer = PhAllocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); RtlSetBits(&EtGpuNodeBitMap, 0, 1); EtGpuNodeBitMapBitsSet = 1; return TRUE; }
NTSTATUS PhEnumCsrProcessHandles( _In_ PPH_ENUM_CSR_PROCESS_HANDLES_CALLBACK Callback, _In_opt_ PVOID Context ) { NTSTATUS status; PHANDLE csrProcessHandles; ULONG numberOfCsrProcessHandles; ULONG i; BOOLEAN stop = FALSE; PPH_LIST pids; if (!NT_SUCCESS(status = PhpOpenCsrProcesses( &csrProcessHandles, &numberOfCsrProcessHandles ))) return status; pids = PhCreateList(40); for (i = 0; i < numberOfCsrProcessHandles; i++) { PKPH_PROCESS_HANDLE_INFORMATION handles; ULONG j; if (stop) break; if (NT_SUCCESS(KphEnumerateProcessHandles2(csrProcessHandles[i], &handles))) { for (j = 0; j < handles->HandleCount; j++) { PH_CSR_HANDLE_INFO handle; handle.CsrProcessHandle = csrProcessHandles[i]; handle.Handle = handles->Handles[j].Handle; // Get the process ID associated with the handle. // This call will fail if the handle is not a // process or thread handle. if (!NT_SUCCESS(PhpGetCsrHandleProcessId(&handle))) continue; // Avoid duplicate PIDs. if (PhFindItemList(pids, handle.ProcessId) != -1) continue; PhAddItemList(pids, handle.ProcessId); if (!Callback(&handle, Context)) { stop = TRUE; break; } } PhFree(handles); } } PhDereferenceObject(pids); for (i = 0; i < numberOfCsrProcessHandles; i++) NtClose(csrProcessHandles[i]); PhFree(csrProcessHandles); return status; }
BOOLEAN DiskDriveQueryImminentFailure( _In_ HANDLE DeviceHandle, _Out_ PPH_LIST* DiskSmartAttributes ) { IO_STATUS_BLOCK isb; STORAGE_PREDICT_FAILURE storagePredictFailure; memset(&storagePredictFailure, 0, sizeof(STORAGE_PREDICT_FAILURE)); // * IOCTL_STORAGE_PREDICT_FAILURE returns an opaque 512-byte vendor-specific information block, which // in all cases contains SMART attribute information (2 bytes header + 12 bytes each attribute). // * This works without admin rights but doesn't support other features like logs and self-tests. // * It works for (S)ATA devices but not for USB. if (NT_SUCCESS(NtDeviceIoControlFile( DeviceHandle, NULL, NULL, NULL, &isb, IOCTL_STORAGE_PREDICT_FAILURE, // https://msdn.microsoft.com/en-us/library/ff560587.aspx NULL, 0, &storagePredictFailure, sizeof(storagePredictFailure) ))) { PPH_LIST diskAttributeList; //USHORT structureVersion = (USHORT)(storagePredictFailure.VendorSpecific[0] * 256 + storagePredictFailure.VendorSpecific[1]); //USHORT majorVersion = HIBYTE(structureVersion); //USHORT minorVersion = LOBYTE(structureVersion); //TODO: include storagePredictFailure.PredictFailure; diskAttributeList = PhCreateList(30); //An attribute is a one-byte value ranging from 1 to 253 (FDh). //The initial default value is 100 (64h). //The value and the intertretation of the value are vendor-specific. //Attribute values are read-only to the host. //A device may report up to 30 attributes to the host. //Values of 00h, FEh and FFh are invalid. //When attribute values are updated by the device depends on the specific attribute. Some are updated as //the disk operates, some are only updated during SMART self-tests, or at special events like power-on or //unloading the heads of a disk drive, etc //Each attribute may have an associated threshhold. When the value exceeds the threshhold, the attribute //triggers a SMART ‘threshhold exceeded’ event. This event indicates that either the disk is expected to fail //in less than 24 hours or it has exceeded its design or usage lifetime. //When an attribute value is greater than or equal to the threshhold, the threshhold is considered to be //exceeded. A flag is set indicating that failure is likely. //There is no standard way for a host to read or change attribute threshholds. //See the SMART(RETURN STATUS) command for information about how a device reports that a //threshhold has been exceeded. // TODO: Query Threshholds. for (UCHAR i = 0; i < 30; ++i) { PSMART_ATTRIBUTE attribute = (PSMART_ATTRIBUTE)(storagePredictFailure.VendorSpecific + i * sizeof(SMART_ATTRIBUTE) + SMART_HEADER_SIZE); // Attribute values 0x00, 0xFE, 0xFF are invalid. // There is no requirement that attributes be in any particular order. if ( attribute->Id != 0x00 && attribute->Id != 0xFE && attribute->Id != 0xFF ) { PSMART_ATTRIBUTES info = PhAllocate(sizeof(SMART_ATTRIBUTES)); memset(info, 0, sizeof(SMART_ATTRIBUTES)); info->AttributeId = attribute->Id; info->CurrentValue = attribute->CurrentValue; info->WorstValue = attribute->WorstValue; // TODO: These flag offsets might be off-by-one. info->Advisory = (attribute->Flags & 0x1) == 0x0; info->FailureImminent = (attribute->Flags & 0x1) == 0x1; info->OnlineDataCollection = (attribute->Flags & 0x2) == 0x2; info->Performance = (attribute->Flags & 0x3) == 0x3; info->ErrorRate = (attribute->Flags & 0x4) == 0x4; info->EventCount = (attribute->Flags & 0x5) == 0x5; info->SelfPreserving = (attribute->Flags & 0x6) == 0x6; info->RawValue = MAKELONG( MAKEWORD(attribute->RawValue[0], attribute->RawValue[1]), MAKEWORD(attribute->RawValue[2], attribute->RawValue[3]) ); // Missing 2 raw values. PhAddItemList(diskAttributeList, info); } } *DiskSmartAttributes = diskAttributeList; return TRUE; } return FALSE; }
/** * Converts an EMENU to a Windows menu object. * * \param MenuHandle A handle to a Windows menu object. * \param Menu The menu item to convert. The items are appended to \a MenuHandle. * \param Flags A combination of the following: * \li \c PH_EMENU_CONVERT_ID Automatically assigns a unique identifier to each converted menu item. * The resulting mappings are placed in \a Data. * \param Data Additional data resulting from the conversion. The data structure must be initialized * by PhInitializeEMenuData() prior to calling this function. */ VOID PhEMenuToHMenu2( _In_ HMENU MenuHandle, _In_ PPH_EMENU_ITEM Menu, _In_ ULONG Flags, _Inout_opt_ PPH_EMENU_DATA Data ) { ULONG i; PPH_EMENU_ITEM item; MENUITEMINFO menuItemInfo; for (i = 0; i < Menu->Items->Count; i++) { item = Menu->Items->Items[i]; memset(&menuItemInfo, 0, sizeof(MENUITEMINFO)); menuItemInfo.cbSize = sizeof(MENUITEMINFO); // Type menuItemInfo.fMask = MIIM_FTYPE | MIIM_STATE; if (item->Flags & PH_EMENU_SEPARATOR) { menuItemInfo.fType = MFT_SEPARATOR; } else { menuItemInfo.fType = MFT_STRING; menuItemInfo.fMask |= MIIM_STRING; menuItemInfo.dwTypeData = item->Text; } PhMapFlags1( &menuItemInfo.fType, item->Flags, EMenuTypeMappings, sizeof(EMenuTypeMappings) / sizeof(PH_FLAG_MAPPING) ); // Bitmap if (item->Bitmap) { menuItemInfo.fMask |= MIIM_BITMAP; menuItemInfo.hbmpItem = item->Bitmap; } // Id if (Flags & PH_EMENU_CONVERT_ID) { ULONG id; if (Data) { PhAddItemList(Data->IdToItem, item); id = Data->IdToItem->Count; menuItemInfo.fMask |= MIIM_ID; menuItemInfo.wID = id; } } else { if (item->Id) { menuItemInfo.fMask |= MIIM_ID; menuItemInfo.wID = item->Id; } } // State PhMapFlags1( &menuItemInfo.fState, item->Flags, EMenuStateMappings, sizeof(EMenuStateMappings) / sizeof(PH_FLAG_MAPPING) ); // Context menuItemInfo.fMask |= MIIM_DATA; menuItemInfo.dwItemData = (ULONG_PTR)item; // Submenu if (item->Items && item->Items->Count != 0) { menuItemInfo.fMask |= MIIM_SUBMENU; menuItemInfo.hSubMenu = PhEMenuToHMenu(item, Flags, Data); } InsertMenuItem(MenuHandle, MAXINT, TRUE, &menuItemInfo); } }
BOOLEAN NTAPI PhpCommandLineOptionCallback( _In_opt_ PPH_COMMAND_LINE_OPTION Option, _In_opt_ PPH_STRING Value, _In_opt_ PVOID Context ) { ULONG64 integer; if (Option) { switch (Option->Id) { case PH_ARG_SETTINGS: PhSwapReference(&PhStartupParameters.SettingsFileName, Value); break; case PH_ARG_NOSETTINGS: PhStartupParameters.NoSettings = TRUE; break; case PH_ARG_SHOWVISIBLE: PhStartupParameters.ShowVisible = TRUE; break; case PH_ARG_SHOWHIDDEN: PhStartupParameters.ShowHidden = TRUE; break; case PH_ARG_COMMANDMODE: PhStartupParameters.CommandMode = TRUE; break; case PH_ARG_COMMANDTYPE: PhSwapReference(&PhStartupParameters.CommandType, Value); break; case PH_ARG_COMMANDOBJECT: PhSwapReference(&PhStartupParameters.CommandObject, Value); break; case PH_ARG_COMMANDACTION: PhSwapReference(&PhStartupParameters.CommandAction, Value); break; case PH_ARG_COMMANDVALUE: PhSwapReference(&PhStartupParameters.CommandValue, Value); break; case PH_ARG_RUNASSERVICEMODE: PhSwapReference(&PhStartupParameters.RunAsServiceMode, Value); break; case PH_ARG_NOKPH: PhStartupParameters.NoKph = TRUE; break; case PH_ARG_INSTALLKPH: PhStartupParameters.InstallKph = TRUE; break; case PH_ARG_UNINSTALLKPH: PhStartupParameters.UninstallKph = TRUE; break; case PH_ARG_DEBUG: PhStartupParameters.Debug = TRUE; break; case PH_ARG_HWND: if (PhStringToInteger64(&Value->sr, 16, &integer)) PhStartupParameters.WindowHandle = (HWND)(ULONG_PTR)integer; break; case PH_ARG_POINT: { PH_STRINGREF xString; PH_STRINGREF yString; if (PhSplitStringRefAtChar(&Value->sr, ',', &xString, &yString)) { LONG64 x; LONG64 y; if (PhStringToInteger64(&xString, 10, &x) && PhStringToInteger64(&yString, 10, &y)) { PhStartupParameters.Point.x = (LONG)x; PhStartupParameters.Point.y = (LONG)y; } } } break; case PH_ARG_SHOWOPTIONS: PhStartupParameters.ShowOptions = TRUE; break; case PH_ARG_PHSVC: PhStartupParameters.PhSvc = TRUE; break; case PH_ARG_NOPLUGINS: PhStartupParameters.NoPlugins = TRUE; break; case PH_ARG_NEWINSTANCE: PhStartupParameters.NewInstance = TRUE; break; case PH_ARG_ELEVATE: PhStartupParameters.Elevate = TRUE; break; case PH_ARG_SILENT: PhStartupParameters.Silent = TRUE; break; case PH_ARG_HELP: PhStartupParameters.Help = TRUE; break; case PH_ARG_SELECTPID: if (PhStringToInteger64(&Value->sr, 0, &integer)) PhStartupParameters.SelectPid = (ULONG)integer; break; case PH_ARG_PRIORITY: if (PhEqualString2(Value, L"r", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; else if (PhEqualString2(Value, L"h", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; else if (PhEqualString2(Value, L"n", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; else if (PhEqualString2(Value, L"l", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; break; case PH_ARG_PLUGIN: if (!PhStartupParameters.PluginParameters) PhStartupParameters.PluginParameters = PhCreateList(3); PhAddItemList(PhStartupParameters.PluginParameters, PhReferenceObject(Value)); break; case PH_ARG_SELECTTAB: PhSwapReference(&PhStartupParameters.SelectTab, Value); break; case PH_ARG_SYSINFO: PhSwapReference(&PhStartupParameters.SysInfo, Value ? Value : PhReferenceEmptyString()); break; } } else { PPH_STRING upperValue; upperValue = PhDuplicateString(Value); _wcsupr(upperValue->Buffer); if (PhFindStringInString(upperValue, 0, L"TASKMGR.EXE") != -1) { // User probably has Process Hacker replacing Task Manager. Force // the main window to start visible. PhStartupParameters.ShowVisible = TRUE; } PhDereferenceObject(upperValue); } return TRUE; }
PPH_LIST EnumerateAppDomainIpcBlockWow64( _In_ HANDLE ProcessHandle, _In_ AppDomainEnumerationIPCBlock_Wow64* AppDomainIpcBlock ) { LARGE_INTEGER timeout; SIZE_T appDomainInfoBlockLength; HANDLE legacyPrivateBlockMutexHandle = NULL; AppDomainEnumerationIPCBlock_Wow64 tempBlock; AppDomainInfo_Wow64* appDomainInfoBlock = NULL; PPH_LIST appDomainsList = PhCreateList(1); // If the mutex isn't filled in, the CLR is either starting up or shutting down if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } // Dup the valid mutex handle into this process. if (!NT_SUCCESS(NtDuplicateObject( ProcessHandle, UlongToHandle(AppDomainIpcBlock->Mutex), NtCurrentProcess(), &legacyPrivateBlockMutexHandle, GENERIC_ALL, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ))) { goto CleanupExit; } // Acquire the mutex, only waiting two seconds. // We can't actually gaurantee that the target put a mutex object in here. if (NtWaitForSingleObject( legacyPrivateBlockMutexHandle, FALSE, PhTimeoutFromMilliseconds(&timeout, 2000) ) == STATUS_WAIT_0) { // Make sure the mutex handle is still valid. If its not, then we lost a shutdown race. if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } } else { // Again, landing here is most probably a shutdown race. goto CleanupExit; } // Beware: If the target pid is not properly honoring the mutex, the data in the IPC block may still shift underneath us. // If we get here, then hMutex is held by this process. // Make a copy of the IPC block so that we can gaurantee that it's not changing on us. memcpy(&tempBlock, AppDomainIpcBlock, sizeof(AppDomainEnumerationIPCBlock_Wow64)); // It's possible the process will not have any appdomains. if ((tempBlock.ListOfAppDomains == 0) != (tempBlock.SizeInBytes == 0)) { goto CleanupExit; } // All the data in the IPC block is signed integers. They should never be negative, // so check that now. if ((tempBlock.TotalSlots < 0) || (tempBlock.NumOfUsedSlots < 0) || (tempBlock.LastFreedSlot < 0) || (tempBlock.SizeInBytes < 0) || (tempBlock.ProcessNameLengthInBytes < 0)) { goto CleanupExit; } // Allocate memory to read the remote process' memory into appDomainInfoBlockLength = tempBlock.SizeInBytes; // Check other invariants. if (appDomainInfoBlockLength != tempBlock.TotalSlots * sizeof(AppDomainInfo_Wow64)) { goto CleanupExit; } appDomainInfoBlock = (AppDomainInfo_Wow64*)PhAllocate(appDomainInfoBlockLength); memset(appDomainInfoBlock, 0, appDomainInfoBlockLength); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(tempBlock.ListOfAppDomains), appDomainInfoBlock, appDomainInfoBlockLength, NULL ))) { PhFree(appDomainInfoBlock); goto CleanupExit; } // Collect all the AppDomain names into a list of strings. for (INT i = 0; i < tempBlock.NumOfUsedSlots; i++) { SIZE_T appDomainNameLength; PVOID appDomainName; if (!appDomainInfoBlock[i].AppDomainName) continue; // Should be positive, and at least have a null-terminator character. if (appDomainInfoBlock[i].NameLengthInBytes <= 1) continue; // Make sure buffer has right geometry. if (appDomainInfoBlock[i].NameLengthInBytes < 0) continue; // If it's not on a WCHAR boundary, then we may have a 1-byte buffer-overflow. appDomainNameLength = appDomainInfoBlock[i].NameLengthInBytes / sizeof(WCHAR); if ((appDomainNameLength * sizeof(WCHAR)) != appDomainInfoBlock[i].NameLengthInBytes) continue; // It should at least have 1 char for the null terminator. if (appDomainNameLength < 1) continue; // We know the string is a well-formed null-terminated string, // but beyond that, we can't verify that the data is actually truthful. appDomainName = PhAllocate(appDomainInfoBlock[i].NameLengthInBytes + 1); memset(appDomainName, 0, appDomainInfoBlock[i].NameLengthInBytes + 1); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(appDomainInfoBlock[i].AppDomainName), appDomainName, appDomainInfoBlock[i].NameLengthInBytes, NULL ))) { PhFree(appDomainName); continue; } PhAddItemList(appDomainsList, appDomainName); } CleanupExit: if (appDomainInfoBlock) { PhFree(appDomainInfoBlock); } if (legacyPrivateBlockMutexHandle) { NtReleaseMutant(legacyPrivateBlockMutexHandle, NULL); NtClose(legacyPrivateBlockMutexHandle); } return appDomainsList; }
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++; }
INT_PTR CALLBACK EspServiceDependenciesDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PSERVICE_LIST_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT)); memset(context, 0, sizeof(SERVICE_LIST_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam; HWND serviceListHandle; PPH_LIST serviceList; SC_HANDLE serviceHandle; ULONG win32Result = 0; BOOLEAN success = FALSE; PPH_SERVICE_ITEM *services; SetDlgItemText(hwndDlg, IDC_MESSAGE, L"This service depends on the following services:"); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL); if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG)) { LPQUERY_SERVICE_CONFIG serviceConfig; if (serviceConfig = PhGetServiceConfig(serviceHandle)) { PWSTR dependency; PPH_SERVICE_ITEM dependencyService; dependency = serviceConfig->lpDependencies; serviceList = PhCreateList(8); success = TRUE; if (dependency) { ULONG dependencyLength; while (TRUE) { dependencyLength = (ULONG)wcslen(dependency); if (dependencyLength == 0) break; if (dependency[0] == SC_GROUP_IDENTIFIER) goto ContinueLoop; if (dependencyService = PhReferenceServiceItem(dependency)) PhAddItemList(serviceList, dependencyService); ContinueLoop: dependency += dependencyLength + 1; } } services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count); serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count); context->ServiceListHandle = serviceListHandle; EspLayoutServiceListControl(hwndDlg, serviceListHandle); ShowWindow(serviceListHandle, SW_SHOW); PhDereferenceObject(serviceList); PhFree(serviceConfig); } else { win32Result = GetLastError(); } CloseServiceHandle(serviceHandle); } else { win32Result = GetLastError(); } if (!success) { SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependencies: ", ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer); ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW); } } break; case WM_DESTROY: { PhDeleteLayoutManager(&context->LayoutManager); PhFree(context); } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); if (context->ServiceListHandle) EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle); } break; } return FALSE; }
BOOLEAN ProcessTreeFilterCallback( _In_ PPH_TREENEW_NODE Node, _In_opt_ PVOID Context ) { PPH_PROCESS_NODE processNode = (PPH_PROCESS_NODE)Node; if (PhIsNullOrEmptyString(SearchboxText)) return TRUE; if (!PhIsNullOrEmptyString(processNode->ProcessItem->ProcessName)) { if (WordMatchStringRef(&processNode->ProcessItem->ProcessName->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->FileName)) { if (WordMatchStringRef(&processNode->ProcessItem->FileName->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->CommandLine)) { if (WordMatchStringRef(&processNode->ProcessItem->CommandLine->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->VersionInfo.CompanyName)) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.CompanyName->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->VersionInfo.FileDescription)) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.FileDescription->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->VersionInfo.FileVersion)) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.FileVersion->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->VersionInfo.ProductName)) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.ProductName->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->UserName)) { if (WordMatchStringRef(&processNode->ProcessItem->UserName->sr)) return TRUE; } if (processNode->ProcessItem->IntegrityString) { if (WordMatchStringZ(processNode->ProcessItem->IntegrityString)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->JobName)) { if (WordMatchStringRef(&processNode->ProcessItem->JobName->sr)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->VerifySignerName)) { if (WordMatchStringRef(&processNode->ProcessItem->VerifySignerName->sr)) return TRUE; } if (processNode->ProcessItem->ProcessIdString[0]) { if (WordMatchStringZ(processNode->ProcessItem->ProcessIdString)) return TRUE; } if (processNode->ProcessItem->ParentProcessIdString[0]) { if (WordMatchStringZ(processNode->ProcessItem->ParentProcessIdString)) return TRUE; } if (processNode->ProcessItem->SessionIdString[0]) { if (WordMatchStringZ(processNode->ProcessItem->SessionIdString)) return TRUE; } if (!PhIsNullOrEmptyString(processNode->ProcessItem->PackageFullName)) { if (WordMatchStringRef(&processNode->ProcessItem->PackageFullName->sr)) return TRUE; } if (WordMatchStringZ(PhGetProcessPriorityClassString(processNode->ProcessItem->PriorityClass))) { return TRUE; } if (processNode->ProcessItem->VerifyResult != VrUnknown) { switch (processNode->ProcessItem->VerifyResult) { case VrNoSignature: if (WordMatchStringZ(L"NoSignature")) return TRUE; break; case VrTrusted: if (WordMatchStringZ(L"Trusted")) return TRUE; break; case VrExpired: if (WordMatchStringZ(L"Expired")) return TRUE; break; case VrRevoked: if (WordMatchStringZ(L"Revoked")) return TRUE; break; case VrDistrust: if (WordMatchStringZ(L"Distrust")) return TRUE; break; case VrSecuritySettings: if (WordMatchStringZ(L"SecuritySettings")) return TRUE; break; case VrBadSignature: if (WordMatchStringZ(L"BadSignature")) return TRUE; break; default: if (WordMatchStringZ(L"Unknown")) return TRUE; break; } } if (WINDOWS_HAS_UAC && processNode->ProcessItem->ElevationType != TokenElevationTypeDefault) { switch (processNode->ProcessItem->ElevationType) { case TokenElevationTypeLimited: if (WordMatchStringZ(L"Limited")) return TRUE; break; case TokenElevationTypeFull: if (WordMatchStringZ(L"Full")) return TRUE; break; default: if (WordMatchStringZ(L"Unknown")) return TRUE; break; } } if (WordMatchStringZ(L"IsBeingDebugged") && processNode->ProcessItem->IsBeingDebugged) { return TRUE; } if (WordMatchStringZ(L"IsDotNet") && processNode->ProcessItem->IsDotNet) { return TRUE; } if (WordMatchStringZ(L"IsElevated") && processNode->ProcessItem->IsElevated) { return TRUE; } if (WordMatchStringZ(L"IsInJob") && processNode->ProcessItem->IsInJob) { return TRUE; } if (WordMatchStringZ(L"IsInSignificantJob") && processNode->ProcessItem->IsInSignificantJob) { return TRUE; } if (WordMatchStringZ(L"IsPacked") && processNode->ProcessItem->IsPacked) { return TRUE; } if (WordMatchStringZ(L"IsSuspended") && processNode->ProcessItem->IsSuspended) { return TRUE; } if (WordMatchStringZ(L"IsWow64") && processNode->ProcessItem->IsWow64) { return TRUE; } if (WordMatchStringZ(L"IsImmersive") && processNode->ProcessItem->IsImmersive) { return TRUE; } if (processNode->ProcessItem->ServiceList && processNode->ProcessItem->ServiceList->Count) { ULONG enumerationKey = 0; PPH_SERVICE_ITEM serviceItem; PPH_LIST serviceList; ULONG i; BOOLEAN matched = FALSE; // Copy the service list so we can search it. serviceList = PhCreateList(processNode->ProcessItem->ServiceList->Count); PhAcquireQueuedLockShared(&processNode->ProcessItem->ServiceListLock); while (PhEnumPointerList( processNode->ProcessItem->ServiceList, &enumerationKey, &serviceItem )) { PhReferenceObject(serviceItem); PhAddItemList(serviceList, serviceItem); } PhReleaseQueuedLockShared(&processNode->ProcessItem->ServiceListLock); for (i = 0; i < serviceList->Count; i++) { PPH_STRING serviceFileName = NULL; PPH_STRING serviceBinaryPath = NULL; serviceItem = serviceList->Items[i]; if (!PhIsNullOrEmptyString(serviceItem->Name)) { if (WordMatchStringRef(&serviceItem->Name->sr)) { matched = TRUE; break; } } if (!PhIsNullOrEmptyString(serviceItem->DisplayName)) { if (WordMatchStringRef(&serviceItem->DisplayName->sr)) { matched = TRUE; break; } } if (serviceItem->ProcessId) { WCHAR processIdString[PH_INT32_STR_LEN_1]; PhPrintUInt32(processIdString, HandleToUlong(serviceItem->ProcessId)); if (WordMatchStringZ(processIdString)) { matched = TRUE; break; } } if (NT_SUCCESS(QueryServiceFileName( &serviceItem->Name->sr, &serviceFileName, &serviceBinaryPath ))) { if (serviceFileName) { if (WordMatchStringRef(&serviceFileName->sr)) { matched = TRUE; } PhDereferenceObject(serviceFileName); } if (serviceBinaryPath) { if (WordMatchStringRef(&serviceBinaryPath->sr)) { matched = TRUE; } PhDereferenceObject(serviceBinaryPath); } if (matched) break; } } PhDereferenceObjects(serviceList->Items, serviceList->Count); PhDereferenceObject(serviceList); if (matched) return TRUE; } return FALSE; }
BOOLEAN EtpInitializeD3DStatistics( VOID ) { PWSTR deviceInterfaceList; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName; D3DKMT_QUERYSTATISTICS queryStatistics; D3DKMT_CLOSEADAPTER closeAdapter; if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DISPLAY_DEVICE_ARRIVAL, 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_DISPLAY_DEVICE_ARRIVAL, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return FALSE; } for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { memset(&openAdapterFromDeviceName, 0, sizeof(D3DKMT_OPENADAPTERFROMDEVICENAME)); openAdapterFromDeviceName.pDeviceName = deviceInterface; if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName(&openAdapterFromDeviceName))) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER; queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { PETP_GPU_ADAPTER gpuAdapter; ULONG i; gpuAdapter = EtpAllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments); gpuAdapter->AdapterLuid = openAdapterFromDeviceName.AdapterLuid; gpuAdapter->Description = EtpQueryDeviceDescription(deviceInterface); gpuAdapter->NodeCount = queryStatistics.QueryResult.AdapterInformation.NodeCount; gpuAdapter->SegmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments; RtlInitializeBitMap(&gpuAdapter->ApertureBitMap, gpuAdapter->ApertureBitMapBuffer, queryStatistics.QueryResult.AdapterInformation.NbSegments); PhAddItemList(EtpGpuAdapterList, gpuAdapter); EtGpuTotalNodeCount += gpuAdapter->NodeCount; EtGpuTotalSegmentCount += gpuAdapter->SegmentCount; gpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex; EtGpuNextNodeIndex += gpuAdapter->NodeCount; for (i = 0; i < gpuAdapter->SegmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { ULONG64 commitLimit; ULONG aperture; if (WindowsVersion >= WINDOWS_8) { commitLimit = queryStatistics.QueryResult.SegmentInformation.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformation.Aperture; } else { commitLimit = queryStatistics.QueryResult.SegmentInformationV1.CommitLimit; aperture = queryStatistics.QueryResult.SegmentInformationV1.Aperture; } if (aperture) EtGpuSharedLimit += commitLimit; else EtGpuDedicatedLimit += commitLimit; if (aperture) RtlSetBits(&gpuAdapter->ApertureBitMap, i, 1); } } } memset(&closeAdapter, 0, sizeof(D3DKMT_CLOSEADAPTER)); closeAdapter.hAdapter = openAdapterFromDeviceName.hAdapter; D3DKMTCloseAdapter(&closeAdapter); } } PhFree(deviceInterfaceList); EtGpuNodeBitMapBuffer = PhAllocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount)); RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount); RtlSetBits(&EtGpuNodeBitMap, 0, 1); EtGpuNodeBitMapBitsSet = 1; return TRUE; }