static PPH_PROCESS_ITEM PhpCreateProcessItemForHiddenProcess( _In_ PPH_HIDDEN_PROCESS_ENTRY Entry ) { NTSTATUS status; PPH_PROCESS_ITEM processItem; PPH_PROCESS_ITEM idleProcessItem; HANDLE processHandle; PROCESS_BASIC_INFORMATION basicInfo; KERNEL_USER_TIMES times; PROCESS_PRIORITY_CLASS priorityClass; ULONG handleCount; HANDLE processHandle2; if (Entry->Type == NormalProcess) { processItem = PhReferenceProcessItem(Entry->ProcessId); if (processItem) return processItem; } processItem = PhCreateProcessItem(Entry->ProcessId); // Mark the process as terminated if necessary. if (Entry->Type == TerminatedProcess) processItem->State |= PH_PROCESS_ITEM_REMOVED; // We need a process record. Just use the record of System Idle Process. if (idleProcessItem = PhReferenceProcessItem(SYSTEM_IDLE_PROCESS_ID)) { processItem->Record = idleProcessItem->Record; PhReferenceProcessRecord(processItem->Record); } else { PhDereferenceObject(processItem); return NULL; } // Set up the file name and process name. PhSwapReference(&processItem->FileName, Entry->FileName); if (processItem->FileName) { processItem->ProcessName = PhGetBaseName(processItem->FileName); } else { processItem->ProcessName = PhCreateString(L"Unknown"); } if (ProcessesMethod == BruteForceScanMethod) { status = PhOpenProcess( &processHandle, ProcessQueryAccess, Entry->ProcessId ); } else { status = PhOpenProcessByCsrHandles( &processHandle, ProcessQueryAccess, Entry->ProcessId ); } if (NT_SUCCESS(status)) { // Basic information and not-so-dynamic information processItem->QueryHandle = processHandle; if (NT_SUCCESS(PhGetProcessBasicInformation(processHandle, &basicInfo))) { processItem->ParentProcessId = basicInfo.InheritedFromUniqueProcessId; processItem->BasePriority = basicInfo.BasePriority; } PhGetProcessSessionId(processHandle, &processItem->SessionId); PhPrintUInt32(processItem->ParentProcessIdString, HandleToUlong(processItem->ParentProcessId)); PhPrintUInt32(processItem->SessionIdString, processItem->SessionId); if (NT_SUCCESS(PhGetProcessTimes(processHandle, ×))) { processItem->CreateTime = times.CreateTime; processItem->KernelTime = times.KernelTime; processItem->UserTime = times.UserTime; } // TODO: Token information? if (NT_SUCCESS(NtQueryInformationProcess( processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS), NULL ))) { processItem->PriorityClass = priorityClass.PriorityClass; } if (NT_SUCCESS(NtQueryInformationProcess( processHandle, ProcessHandleCount, &handleCount, sizeof(ULONG), NULL ))) { processItem->NumberOfHandles = handleCount; } } // Stage 1 // Some copy and paste magic here... if (processItem->FileName) { // Small icon, large icon. ExtractIconEx( processItem->FileName->Buffer, 0, &processItem->LargeIcon, &processItem->SmallIcon, 1 ); // Version info. PhInitializeImageVersionInfo(&processItem->VersionInfo, processItem->FileName->Buffer); } // Use the default EXE icon if we didn't get the file's icon. { if (!processItem->SmallIcon || !processItem->LargeIcon) { if (processItem->SmallIcon) { DestroyIcon(processItem->SmallIcon); processItem->SmallIcon = NULL; } else if (processItem->LargeIcon) { DestroyIcon(processItem->LargeIcon); processItem->LargeIcon = NULL; } PhGetStockApplicationIcon(&processItem->SmallIcon, &processItem->LargeIcon); processItem->SmallIcon = DuplicateIcon(NULL, processItem->SmallIcon); processItem->LargeIcon = DuplicateIcon(NULL, processItem->LargeIcon); } } // POSIX, command line status = PhOpenProcess( &processHandle2, ProcessQueryAccess | PROCESS_VM_READ, Entry->ProcessId ); if (NT_SUCCESS(status)) { BOOLEAN isPosix = FALSE; PPH_STRING commandLine; ULONG i; status = PhGetProcessIsPosix(processHandle2, &isPosix); processItem->IsPosix = isPosix; if (!NT_SUCCESS(status) || !isPosix) { status = PhGetProcessCommandLine(processHandle2, &commandLine); if (NT_SUCCESS(status)) { // Some command lines (e.g. from taskeng.exe) have nulls in them. // Since Windows can't display them, we'll replace them with // spaces. for (i = 0; i < (ULONG)commandLine->Length / 2; i++) { if (commandLine->Buffer[i] == 0) commandLine->Buffer[i] = ' '; } } } else { // Get the POSIX command line. status = PhGetProcessPosixCommandLine(processHandle2, &commandLine); } if (NT_SUCCESS(status)) { processItem->CommandLine = commandLine; } NtClose(processHandle2); } // TODO: Other stage 1 tasks. PhSetEvent(&processItem->Stage1Event); return processItem; }
NTSTATUS PhSvcApiRequestThreadStart( __in PVOID Parameter ) { NTSTATUS status; PHSVC_THREAD_CONTEXT threadContext; HANDLE portHandle; PVOID portContext; PHSVC_API_MSG receiveMessage; PPHSVC_API_MSG replyMessage; CSHORT messageType; PPHSVC_CLIENT client; threadContext.CurrentClient = NULL; threadContext.OldClient = NULL; TlsSetValue(PhSvcApiThreadContextTlsIndex, &threadContext); portHandle = PhSvcApiPortHandle; replyMessage = NULL; while (TRUE) { status = NtReplyWaitReceivePort( portHandle, &portContext, (PPORT_MESSAGE)replyMessage, (PPORT_MESSAGE)&receiveMessage ); portHandle = PhSvcApiPortHandle; replyMessage = NULL; if (!NT_SUCCESS(status)) { // Client probably died. continue; } messageType = receiveMessage.h.u2.s2.Type; if (messageType == LPC_CONNECTION_REQUEST) { PhSvcHandleConnectionRequest(&receiveMessage); continue; } if (!portContext) continue; client = (PPHSVC_CLIENT)portContext; threadContext.CurrentClient = client; if (messageType == LPC_REQUEST) { PhSvcDispatchApiCall(client, &receiveMessage, &replyMessage, &portHandle); } else if (messageType == LPC_PORT_CLOSED) { PhDereferenceObject(client); if (_InterlockedDecrement(&PhSvcApiNumberOfClients) == 0) { NtSetEvent(PhSvcTimeoutStandbyEventHandle, NULL); } } assert(!threadContext.OldClient); } }
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 (processNode->ProcessItem->ProcessName) { if (WordMatchStringRef(&processNode->ProcessItem->ProcessName->sr)) return TRUE; } if (processNode->ProcessItem->FileName) { if (WordMatchStringRef(&processNode->ProcessItem->FileName->sr)) return TRUE; } if (processNode->ProcessItem->CommandLine) { if (WordMatchStringRef(&processNode->ProcessItem->CommandLine->sr)) return TRUE; } if (processNode->ProcessItem->VersionInfo.CompanyName) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.CompanyName->sr)) return TRUE; } if (processNode->ProcessItem->VersionInfo.FileDescription) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.FileDescription->sr)) return TRUE; } if (processNode->ProcessItem->VersionInfo.FileVersion) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.FileVersion->sr)) return TRUE; } if (processNode->ProcessItem->VersionInfo.ProductName) { if (WordMatchStringRef(&processNode->ProcessItem->VersionInfo.ProductName->sr)) return TRUE; } if (processNode->ProcessItem->UserName) { if (WordMatchStringRef(&processNode->ProcessItem->UserName->sr)) return TRUE; } if (processNode->ProcessItem->IntegrityString) { if (WordMatchStringZ(processNode->ProcessItem->IntegrityString)) return TRUE; } if (processNode->ProcessItem->JobName) { if (WordMatchStringRef(&processNode->ProcessItem->JobName->sr)) return TRUE; } if (processNode->ProcessItem->VerifySignerName) { if (WordMatchStringRef(&processNode->ProcessItem->VerifySignerName->sr)) return TRUE; } if (processNode->ProcessItem->ProcessIdString[0] != 0) { if (WordMatchStringZ(processNode->ProcessItem->ProcessIdString)) return TRUE; } if (processNode->ProcessItem->ParentProcessIdString[0] != 0) { if (WordMatchStringZ(processNode->ProcessItem->ParentProcessIdString)) return TRUE; } if (processNode->ProcessItem->SessionIdString[0] != 0) { if (WordMatchStringZ(processNode->ProcessItem->SessionIdString)) return TRUE; } if (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"UpdateIsDotNet") && processNode->ProcessItem->UpdateIsDotNet) { return TRUE; } 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"IsPosix") && processNode->ProcessItem->IsPosix) { 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 != 0) { 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++) { serviceItem = serviceList->Items[i]; if (serviceItem->Name) { if (WordMatchStringRef(&serviceItem->Name->sr)) { matched = TRUE; break; } } if (serviceItem->DisplayName) { if (WordMatchStringRef(&serviceItem->DisplayName->sr)) { matched = TRUE; break; } } if (serviceItem->ProcessIdString[0] != 0) { if (WordMatchStringZ(serviceItem->ProcessIdString)) { matched = TRUE; break; } } } PhDereferenceObjects(serviceList->Items, serviceList->Count); PhDereferenceObject(serviceList); if (matched) return TRUE; } return FALSE; }
INT_PTR CALLBACK NetworkAdapterOptionsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PDV_NETADAPTER_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = PhAllocateZero(sizeof(DV_NETADAPTER_CONTEXT)); PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); } else { context = PhGetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); if (uMsg == WM_DESTROY) { PhDeleteLayoutManager(&context->LayoutManager); if (context->OptionsChanged) NetAdaptersSaveList(); FreeListViewAdapterEntries(context); PhRemoveWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); PhFree(context); } } if (context == NULL) return FALSE; switch (uMsg) { case WM_INITDIALOG: { context->ListViewHandle = GetDlgItem(hwndDlg, IDC_NETADAPTERS_LISTVIEW); PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); ListView_SetExtendedListViewStyleEx(context->ListViewHandle, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); PhSetControlTheme(context->ListViewHandle, L"explorer"); PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 350, L"Network Adapters"); PhSetExtendedListView(context->ListViewHandle); LoadNetworkAdapterImages(context); ListView_EnableGroupView(context->ListViewHandle, TRUE); PhAddListViewGroup(context->ListViewHandle, 0, L"Connected"); PhAddListViewGroup(context->ListViewHandle, 1, L"Disconnected"); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SHOW_HIDDEN_ADAPTERS), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); FindNetworkAdapters(context); context->OptionsChanged = FALSE; } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); ExtendedListView_SetColumnWidth(context->ListViewHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_SHOW_HIDDEN_ADAPTERS: { context->UseAlternateMethod = !context->UseAlternateMethod; if (context->UseAlternateMethod) { ListView_EnableGroupView(context->ListViewHandle, FALSE); } else { ListView_EnableGroupView(context->ListViewHandle, TRUE); } FreeListViewAdapterEntries(context); ListView_DeleteAllItems(context->ListViewHandle); FindNetworkAdapters(context); ExtendedListView_SetColumnWidth(context->ListViewHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; if (header->code == LVN_ITEMCHANGED) { LPNM_LISTVIEW listView = (LPNM_LISTVIEW)lParam; if (!PhTryAcquireReleaseQueuedLockExclusive(&NetworkAdaptersListLock)) break; if (listView->uChanged & LVIF_STATE) { switch (listView->uNewState & LVIS_STATEIMAGEMASK) { case INDEXTOSTATEIMAGEMASK(2): // checked { PDV_NETADAPTER_ID param = (PDV_NETADAPTER_ID)listView->lParam; if (!FindAdapterEntry(param, FALSE)) { PDV_NETADAPTER_ENTRY entry; entry = CreateNetAdapterEntry(param); entry->UserReference = TRUE; } context->OptionsChanged = TRUE; } break; case INDEXTOSTATEIMAGEMASK(1): // unchecked { PDV_NETADAPTER_ID param = (PDV_NETADAPTER_ID)listView->lParam; FindAdapterEntry(param, TRUE); context->OptionsChanged = TRUE; } break; } } } else if (header->code == NM_RCLICK) { PDV_NETADAPTER_ENTRY param; PPH_STRING deviceInstance; if (param = PhGetSelectedListViewItemParam(context->ListViewHandle)) { if (deviceInstance = FindNetworkDeviceInstance(param->AdapterId.InterfaceGuid)) { ShowDeviceMenu(hwndDlg, deviceInstance); PhDereferenceObject(deviceInstance); } } } } break; } return FALSE; }
static INT_PTR CALLBACK PhpAboutDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PPH_STRING appName; #if (PHAPP_VERSION_REVISION != 0) appName = PhFormatString( L"Process Hacker %u.%u.%u", PHAPP_VERSION_MAJOR, PHAPP_VERSION_MINOR, PHAPP_VERSION_REVISION ); #else appName = PhFormatString( L"Process Hacker %u.%u", PHAPP_VERSION_MAJOR, PHAPP_VERSION_MINOR ); #endif SetDlgItemText(hwndDlg, IDC_ABOUT_NAME, appName->Buffer); PhDereferenceObject(appName); SetDlgItemText(hwndDlg, IDC_CREDITS, L" Installer by XhmikosR\n" L"Thanks to:\n" L" dmex\n" L" Donors - thank you for your support!\n" L" <a href=\"http://forum.sysinternals.com\">Sysinternals Forums</a>\n" L" <a href=\"http://www.reactos.org\">ReactOS</a>\n" L"Process Hacker uses the following components:\n" L" <a href=\"http://www.minixml.org\">Mini-XML</a> by Michael Sweet\n" L" <a href=\"http://www.pcre.org\">PCRE</a>\n" L" MD5 code by Jouni Malinen\n" L" SHA1 code by Filip Navara, based on code by Steve Reid\n" L" <a href=\"http://www.famfamfam.com/lab/icons/silk\">Silk icons</a>\n" ); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_DIAGNOSTICS: { PhShowInformationDialog(hwndDlg, PH_AUTO_T(PH_STRING, PhGetDiagnosticsString())->Buffer); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_CLICK: { switch (header->idFrom) { case IDC_CREDITS: case IDC_LINK_SF: PhShellExecute(hwndDlg, ((PNMLINK)header)->item.szUrl, NULL); break; } } break; } } break; } return FALSE; }
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; }
PPH_STRING FindNetworkDeviceInstance( _In_ PPH_STRING DevicePath ) { PPH_STRING deviceInstanceString = NULL; 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 NULL; } 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 NULL; } for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { HKEY keyHandle; 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) { continue; } if (CM_Locate_DevNode( &deviceInstanceHandle, deviceInstanceId, CM_LOCATE_DEVNODE_PHANTOM ) != CR_SUCCESS) { continue; } if (CM_Open_DevInst_Key( deviceInstanceHandle, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &keyHandle, CM_REGISTRY_SOFTWARE ) == CR_SUCCESS) { PPH_STRING deviceGuid; if (deviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId")) { if (PhEqualString(deviceGuid, DevicePath, TRUE)) { deviceInstanceString = PhCreateString(deviceInstanceId); PhDereferenceObject(deviceGuid); NtClose(keyHandle); break; } PhDereferenceObject(deviceGuid); } NtClose(keyHandle); } } PhFree(deviceInterfaceList); return deviceInstanceString; }
BOOLEAN QueryUpdateData( _Inout_ PPH_UPDATER_CONTEXT Context ) { BOOLEAN success = FALSE; PPH_HTTP_CONTEXT httpContext = NULL; PPH_BYTES jsonString = NULL; PVOID jsonObject = NULL; if (!PhHttpSocketCreate(&httpContext, NULL)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"wj32.org", PH_HTTP_DEFAULT_HTTPS_PORT )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, L"/processhacker/nightly.php?phupdater", PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } { PPH_STRING versionHeader; PPH_STRING windowsHeader; if (versionHeader = UpdateVersionString()) { PhHttpSocketAddRequestHeaders(httpContext, versionHeader->Buffer, (ULONG)versionHeader->Length / sizeof(WCHAR)); PhDereferenceObject(versionHeader); } if (windowsHeader = UpdateWindowsString()) { PhHttpSocketAddRequestHeaders(httpContext, windowsHeader->Buffer, (ULONG)windowsHeader->Length / sizeof(WCHAR)); PhDereferenceObject(windowsHeader); } } if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketEndRequest(httpContext)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; Context->Version = PhGetJsonValueAsString(jsonObject, "version"); Context->RelDate = PhGetJsonValueAsString(jsonObject, "updated"); Context->SetupFileDownloadUrl = PhGetJsonValueAsString(jsonObject, "setup_url"); Context->SetupFileLength = PhFormatSize(PhGetJsonValueAsLong64(jsonObject, "setup_length"), 2); Context->SetupFileHash = PhGetJsonValueAsString(jsonObject, "setup_hash"); Context->SetupFileSignature = PhGetJsonValueAsString(jsonObject, "setup_sig"); Context->BuildMessage = PhGetJsonValueAsString(jsonObject, "changelog"); PhFreeJsonParser(jsonObject); if (PhIsNullOrEmptyString(Context->Version)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->RelDate)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileDownloadUrl)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileLength)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileHash)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileSignature)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->BuildMessage)) goto CleanupExit; success = TRUE; CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonString) PhDereferenceObject(jsonString); if (success && !PhIsNullOrEmptyString(Context->BuildMessage)) { PH_STRING_BUILDER sb; PhInitializeStringBuilder(&sb, 0x100); for (SIZE_T i = 0; i < Context->BuildMessage->Length / sizeof(WCHAR); i++) { if (Context->BuildMessage->Data[i] == '\n') PhAppendStringBuilder2(&sb, L"\r\n"); else PhAppendCharStringBuilder(&sb, Context->BuildMessage->Data[i]); } PhMoveReference(&Context->BuildMessage, PhFinalStringBuilderString(&sb)); } return success; }
NTSTATUS UpdateDownloadThread( _In_ PVOID Parameter ) { BOOLEAN downloadSuccess = FALSE; BOOLEAN hashSuccess = FALSE; BOOLEAN signatureSuccess = FALSE; HANDLE tempFileHandle = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING downloadHostPath = NULL; PPH_STRING downloadUrlPath = NULL; PUPDATER_HASH_CONTEXT hashContext = NULL; USHORT httpPort = 0; LARGE_INTEGER timeNow; LARGE_INTEGER timeStart; ULONG64 timeTicks = 0; ULONG64 timeBitsPerSecond = 0; PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)Parameter; SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Initializing download request..."); if (!PhHttpSocketParseUrl( context->SetupFileDownloadUrl, &downloadHostPath, &downloadUrlPath, &httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Create the local path string. context->SetupFilePath = UpdaterParseDownloadFileName(downloadUrlPath); if (PhIsNullOrEmptyString(context->SetupFilePath)) goto CleanupExit; // Create temporary output file. if (!NT_SUCCESS(PhCreateFileWin32( &tempFileHandle, PhGetString(context->SetupFilePath), FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Connecting..."); if (!PhHttpSocketCreate(&httpContext, NULL)) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, PhGetString(downloadHostPath), httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, PhGetString(downloadUrlPath), PH_HTTP_FLAG_REFRESH | (httpPort == PH_HTTP_DEFAULT_HTTPS_PORT ? PH_HTTP_FLAG_SECURE : 0) )) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Sending download request..."); if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Waiting for response..."); if (!PhHttpSocketEndRequest(httpContext)) { context->ErrorCode = GetLastError(); goto CleanupExit; } else { ULONG bytesDownloaded = 0; ULONG downloadedBytes = 0; ULONG contentLength = 0; PPH_STRING status; IO_STATUS_BLOCK isb; BYTE buffer[PAGE_SIZE]; status = PhFormatString(L"Downloading update %s...", PhGetStringOrEmpty(context->Version)); SendMessage(context->DialogHandle, TDM_SET_MARQUEE_PROGRESS_BAR, FALSE, 0); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)status->Buffer); PhDereferenceObject(status); if (!PhHttpSocketQueryHeaderUlong( httpContext, PH_HTTP_QUERY_CONTENT_LENGTH, &contentLength )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Initialize hash algorithm. if (!(hashContext = UpdaterInitializeHash())) goto CleanupExit; // Zero the buffer. memset(buffer, 0, PAGE_SIZE); // Start the clock. PhQuerySystemTime(&timeStart); // Download the data. while (PhHttpSocketReadData(httpContext, buffer, PAGE_SIZE, &bytesDownloaded)) { // If we get zero bytes, the file was uploaded or there was an error if (bytesDownloaded == 0) break; // If the dialog was closed, just cleanup and exit if (!UpdateDialogThreadHandle) goto CleanupExit; // Update the hash of bytes we downloaded. UpdaterUpdateHash(hashContext, buffer, bytesDownloaded); // Write the downloaded bytes to disk. if (!NT_SUCCESS(NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesDownloaded, NULL, NULL ))) { goto CleanupExit; } downloadedBytes += (DWORD)isb.Information; // Check the number of bytes written are the same we downloaded. if (bytesDownloaded != isb.Information) goto CleanupExit; // Query the current time PhQuerySystemTime(&timeNow); // Calculate the number of ticks timeTicks = (timeNow.QuadPart - timeStart.QuadPart) / PH_TICKS_PER_SEC; timeBitsPerSecond = downloadedBytes / __max(timeTicks, 1); // TODO: Update on timer callback. { FLOAT percent = ((FLOAT)downloadedBytes / contentLength * 100); PPH_STRING totalLength = PhFormatSize(contentLength, -1); PPH_STRING totalDownloaded = PhFormatSize(downloadedBytes, -1); PPH_STRING totalSpeed = PhFormatSize(timeBitsPerSecond, -1); PPH_STRING statusMessage = PhFormatString( L"Downloaded: %s of %s (%.0f%%)\r\nSpeed: %s/s", PhGetStringOrEmpty(totalDownloaded), PhGetStringOrEmpty(totalLength), percent, PhGetStringOrEmpty(totalSpeed) ); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_CONTENT, (LPARAM)statusMessage->Buffer); SendMessage(context->DialogHandle, TDM_SET_PROGRESS_BAR_POS, (WPARAM)percent, 0); PhDereferenceObject(statusMessage); PhDereferenceObject(totalSpeed); PhDereferenceObject(totalLength); PhDereferenceObject(totalDownloaded); } } if (UpdaterVerifyHash(hashContext, context->SetupFileHash)) { hashSuccess = TRUE; } if (UpdaterVerifySignature(hashContext, context->SetupFileSignature)) { signatureSuccess = TRUE; } if (hashSuccess && signatureSuccess) { downloadSuccess = TRUE; } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (hashContext) UpdaterDestroyHash(hashContext); if (tempFileHandle) NtClose(tempFileHandle); if (downloadHostPath) PhDereferenceObject(downloadHostPath); if (downloadUrlPath) PhDereferenceObject(downloadUrlPath); if (UpdateDialogThreadHandle) { if (downloadSuccess && hashSuccess && signatureSuccess) { ShowUpdateInstallDialog(context); } else if (downloadSuccess) { if (signatureSuccess) ShowUpdateFailedDialog(context, TRUE, FALSE); else if (hashSuccess) ShowUpdateFailedDialog(context, FALSE, TRUE); else ShowUpdateFailedDialog(context, FALSE, FALSE); } else { ShowUpdateFailedDialog(context, FALSE, FALSE); } } PhDereferenceObject(context); return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpOptionsAdvancedDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhpPageInit(hwndDlg); PhpAdvancedPageLoad(hwndDlg); if (PhStartupParameters.ShowOptions) { // Disable all controls except for Replace Task Manager. EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEWARNINGS), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEKERNELMODEDRIVER), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_HIDEUNNAMEDHANDLES), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLESTAGE2), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLENETWORKRESOLVE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PROPAGATECPUUSAGE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTLABEL), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC), FALSE); } else { if (WindowsVersion < WINDOWS_7) EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE); // cycle-based CPU usage not available before Windows 7 } } break; case WM_DESTROY: { if (OldTaskMgrDebugger) PhDereferenceObject(OldTaskMgrDebugger); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_CHANGE: { HANDLE threadHandle; RECT windowRect; // Save the options so they don't get "overwritten" when // WM_PH_CHILD_EXIT gets sent. PhpAdvancedPageSave(hwndDlg); GetWindowRect(GetParent(hwndDlg), &windowRect); WindowHandleForElevate = hwndDlg; threadHandle = PhCreateThread(0, PhpElevateAdvancedThreadStart, PhFormatString( L"-showoptions -hwnd %Ix -point %u,%u", (ULONG_PTR)GetParent(hwndDlg), windowRect.left + 20, windowRect.top + 20 )); if (threadHandle) NtClose(threadHandle); } break; case IDC_SAMPLECOUNTAUTOMATIC: { EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), Button_GetCheck(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC)) != BST_CHECKED); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_APPLY: { PhpAdvancedPageSave(hwndDlg); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; case WM_PH_CHILD_EXIT: { PhpAdvancedPageLoad(hwndDlg); } break; } return FALSE; }
INT_PTR CALLBACK PhpOptionsSymbolsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhpPageInit(hwndDlg); SetDlgItemText(hwndDlg, IDC_DBGHELPPATH, PhaGetStringSetting(L"DbgHelpPath")->Buffer); SetDlgItemText(hwndDlg, IDC_DBGHELPSEARCHPATH, PhaGetStringSetting(L"DbgHelpSearchPath")->Buffer); SetDlgItemCheckForSetting(hwndDlg, IDC_UNDECORATESYMBOLS, L"DbgHelpUndecorate"); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"dbghelp.dll", L"dbghelp.dll" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PhaGetDlgItemText(hwndDlg, IDC_DBGHELPPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_DBGHELPPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_APPLY: { PPH_STRING dbgHelpPath; PPH_STRING existingDbgHelpPath; dbgHelpPath = PhaGetDlgItemText(hwndDlg, IDC_DBGHELPPATH); existingDbgHelpPath = PhAutoDereferenceObject(PhGetStringSetting(L"DbgHelpPath")); if (!PhEqualString(dbgHelpPath, existingDbgHelpPath, TRUE)) RestartRequired = TRUE; PhSetStringSetting2(L"DbgHelpPath", &dbgHelpPath->sr); PhSetStringSetting2(L"DbgHelpSearchPath", &(PhaGetDlgItemText(hwndDlg, IDC_DBGHELPSEARCHPATH)->sr)); SetSettingForDlgItemCheck(hwndDlg, IDC_UNDECORATESYMBOLS, L"DbgHelpUndecorate"); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; } return FALSE; }
VOID PhpAdvancedPageSave( _In_ HWND hwndDlg ) { ULONG sampleCount; SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLEKERNELMODEDRIVER, L"EnableKph"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLESTAGE2, L"EnableStage2"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve"); SetSettingForDlgItemCheck(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage"); SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips"); if (WindowsVersion >= WINDOWS_7) SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage"); sampleCount = GetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, NULL, FALSE); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic"); if (sampleCount == 0) sampleCount = 1; if (sampleCount != PhGetIntegerSetting(L"SampleCount")) RestartRequired = TRUE; PhSetIntegerSetting(L"SampleCount", sampleCount); // Replace Task Manager if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER))) { NTSTATUS status; HANDLE taskmgrKeyHandle; BOOLEAN replaceTaskMgr; UNICODE_STRING valueName; replaceTaskMgr = Button_GetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER)) == BST_CHECKED; if (OldReplaceTaskMgr != replaceTaskMgr) { // We should have created the key back in PhpAdvancedPageLoad, which is why // we're opening the key here. if (NT_SUCCESS(PhOpenKey( &taskmgrKeyHandle, KEY_WRITE, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0 ))) { RtlInitUnicodeString(&valueName, L"Debugger"); if (replaceTaskMgr) { PPH_STRING quotedFileName; quotedFileName = PhConcatStrings(3, L"\"", PhApplicationFileName->Buffer, L"\""); status = NtSetValueKey(taskmgrKeyHandle, &valueName, 0, REG_SZ, quotedFileName->Buffer, (ULONG)quotedFileName->Length + 2); PhDereferenceObject(quotedFileName); } else { status = NtDeleteValueKey(taskmgrKeyHandle, &valueName); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to replace Task Manager", status, 0); NtClose(taskmgrKeyHandle); } } } }
VOID PhpAdvancedPageLoad( _In_ HWND hwndDlg ) { HWND changeButton; SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEKERNELMODEDRIVER, L"EnableKph"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLESTAGE2, L"EnableStage2"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve"); SetDlgItemCheckForSetting(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips"); if (WindowsVersion >= WINDOWS_7) SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage"); SetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, PhGetIntegerSetting(L"SampleCount"), FALSE); SetDlgItemCheckForSetting(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic"); if (PhGetIntegerSetting(L"SampleCountAutomatic")) EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE); // Replace Task Manager changeButton = GetDlgItem(hwndDlg, IDC_CHANGE); if (PhElevated) { ShowWindow(changeButton, SW_HIDE); } else { SendMessage(changeButton, BCM_SETSHIELD, 0, TRUE); } { HANDLE taskmgrKeyHandle = NULL; ULONG disposition; BOOLEAN success = FALSE; BOOLEAN alreadyReplaced = FALSE; // See if we can write to the key. if (NT_SUCCESS(PhCreateKey( &taskmgrKeyHandle, KEY_READ | KEY_WRITE, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0, 0, &disposition ))) { success = TRUE; } if (taskmgrKeyHandle || NT_SUCCESS(PhOpenKey( &taskmgrKeyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0 ))) { if (OldTaskMgrDebugger) PhDereferenceObject(OldTaskMgrDebugger); if (OldTaskMgrDebugger = PhQueryRegistryString(taskmgrKeyHandle, L"Debugger")) { alreadyReplaced = PathMatchesPh(OldTaskMgrDebugger); } NtClose(taskmgrKeyHandle); } if (!success) EnableWindow(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), FALSE); OldReplaceTaskMgr = alreadyReplaced; Button_SetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), alreadyReplaced ? BST_CHECKED : BST_UNCHECKED); } }
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; }
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); }
INT_PTR CALLBACK PhpHandleGeneralDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PHANDLE_PROPERTIES_CONTEXT context = (PHANDLE_PROPERTIES_CONTEXT)propSheetPage->lParam; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; HANDLE processHandle; OBJECT_BASIC_INFORMATION basicInfo; BOOLEAN haveBasicInfo = FALSE; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); SetDlgItemText(hwndDlg, IDC_NAME, PhGetString(context->HandleItem->BestObjectName)); SetDlgItemText(hwndDlg, IDC_TYPE, context->HandleItem->TypeName->Buffer); SetDlgItemText(hwndDlg, IDC_ADDRESS, context->HandleItem->ObjectString); if (PhGetAccessEntries( context->HandleItem->TypeName->Buffer, &accessEntries, &numberOfAccessEntries )) { PPH_STRING accessString; PPH_STRING grantedAccessString; accessString = PhGetAccessString( context->HandleItem->GrantedAccess, accessEntries, numberOfAccessEntries ); if (accessString->Length != 0) { grantedAccessString = PhFormatString( L"%s (%s)", context->HandleItem->GrantedAccessString, accessString->Buffer ); SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, grantedAccessString->Buffer); PhDereferenceObject(grantedAccessString); } else { SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, context->HandleItem->GrantedAccessString); } PhDereferenceObject(accessString); PhFree(accessEntries); } else { SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, context->HandleItem->GrantedAccessString); } if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, context->ProcessId ))) { if (NT_SUCCESS(PhGetHandleInformation( processHandle, context->HandleItem->Handle, -1, &basicInfo, NULL, NULL, NULL ))) { SetDlgItemInt(hwndDlg, IDC_REFERENCES, basicInfo.PointerCount, FALSE); SetDlgItemInt(hwndDlg, IDC_HANDLES, basicInfo.HandleCount, FALSE); SetDlgItemInt(hwndDlg, IDC_PAGED, basicInfo.PagedPoolCharge, FALSE); SetDlgItemInt(hwndDlg, IDC_NONPAGED, basicInfo.NonPagedPoolCharge, FALSE); haveBasicInfo = TRUE; } NtClose(processHandle); } if (!haveBasicInfo) { SetDlgItemText(hwndDlg, IDC_REFERENCES, L"Unknown"); SetDlgItemText(hwndDlg, IDC_HANDLES, L"Unknown"); SetDlgItemText(hwndDlg, IDC_PAGED, L"Unknown"); SetDlgItemText(hwndDlg, IDC_NONPAGED, L"Unknown"); } } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_QUERYINITIALFOCUS: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_BASICINFORMATION)); } return TRUE; } } break; } return FALSE; }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // Handle load errors. // In certain startup modes we want to ignore all plugin load errors. if (LoadErrors && LoadErrors->Count != 0 && !PhStartupParameters.PhSvc) { PH_STRING_BUILDER sb; ULONG i; PPHP_PLUGIN_LOAD_ERROR loadError; PPH_STRING baseName; PhInitializeStringBuilder(&sb, 100); PhAppendStringBuilder2(&sb, L"Unable to load the following plugin(s):\n\n"); for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhAppendFormatStringBuilder(&sb, L"%s: %s\n", baseName->Buffer, PhGetStringOrDefault(loadError->ErrorMessage, L"An unknown error occurred.")); PhDereferenceObject(baseName); } PhAppendStringBuilder2(&sb, L"\nDo you want to disable the above plugin(s)?"); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, sb.String->Buffer ) == IDYES) { ULONG i; for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhSetPluginDisabled(&baseName->sr, TRUE); PhDereferenceObject(baseName); } } PhDeleteStringBuilder(&sb); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad, TRUE); }
static INT_PTR CALLBACK PhpInformationDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PINFORMATION_CONTEXT context = (PINFORMATION_CONTEXT)lParam; PPH_LAYOUT_MANAGER layoutManager; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); SetDlgItemText(hwndDlg, IDC_TEXT, context->String); layoutManager = PhAllocate(sizeof(PH_LAYOUT_MANAGER)); PhInitializeLayoutManager(layoutManager, hwndDlg); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_TEXT), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 200; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } SetProp(hwndDlg, L"LayoutManager", (HANDLE)layoutManager); SetProp(hwndDlg, L"String", (HANDLE)context->String); SendMessage(hwndDlg, WM_NEXTDLGCTL, (LPARAM)GetDlgItem(hwndDlg, IDOK), TRUE); } break; case WM_DESTROY: { PPH_LAYOUT_MANAGER layoutManager; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhDeleteLayoutManager(layoutManager); PhFree(layoutManager); RemoveProp(hwndDlg, L"String"); RemoveProp(hwndDlg, L"LayoutManager"); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_COPY: { HWND editControl; LONG selStart; LONG selEnd; PWSTR buffer; PH_STRINGREF string; editControl = GetDlgItem(hwndDlg, IDC_TEXT); SendMessage(editControl, EM_GETSEL, (WPARAM)&selStart, (LPARAM)&selEnd); buffer = (PWSTR)GetProp(hwndDlg, L"String"); if (selStart == selEnd) { // Select and copy the entire string. PhInitializeStringRefLongHint(&string, buffer); Edit_SetSel(editControl, 0, -1); } else { string.Buffer = buffer + selStart; string.Length = (selEnd - selStart) * 2; } PhSetClipboardString(hwndDlg, &string); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)editControl, TRUE); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Information.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PH_STRINGREF string; PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhInitializeStringRef(&string, (PWSTR)GetProp(hwndDlg, L"String")); PhWriteStringAsUtf8FileStream(fileStream, &string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; } } break; case WM_SIZE: { PPH_LAYOUT_MANAGER layoutManager; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhLayoutManagerLayout(layoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
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); }
PSTR VirusTotalSendHttpRequest( _In_ PPH_BYTES JsonArray ) { HANDLE fileHandle = INVALID_HANDLE_VALUE; HINTERNET httpSessionHandle = NULL; HINTERNET connectHandle = NULL; HINTERNET requestHandle = NULL; PSTR subRequestBuffer = NULL; PPH_STRING phVersion = NULL; PPH_STRING userAgent = NULL; PPH_STRING urlString = NULL; phVersion = PhGetPhVersion(); userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer); if (!(httpSessionHandle = WinHttpOpen( userAgent->Buffer, WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ))) { goto CleanupExit; } if (WindowsVersion >= WINDOWS_8_1) { WinHttpSetOption( httpSessionHandle, WINHTTP_OPTION_DECOMPRESSION, &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, sizeof(ULONG) ); } if (!(connectHandle = WinHttpConnect( httpSessionHandle, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0 ))) { goto CleanupExit; } PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlString = PhFormatString( L"%s%s%s%s%S", L"/partners", L"/sysinternals", L"/file-reports", L"?apikey=", resourceString->Buffer ); PhClearReference(&resourceString); if (!(requestHandle = WinHttpOpenRequest( connectHandle, L"POST", PhGetString(urlString), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE ))) { PhClearReference(&urlString); goto CleanupExit; } PhClearReference(&urlString); if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0)) { goto CleanupExit; } if (!WinHttpSendRequest( requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, JsonArray->Buffer, (ULONG)JsonArray->Length, (ULONG)JsonArray->Length, 0 )) { goto CleanupExit; } if (WinHttpReceiveResponse(requestHandle, NULL)) { BYTE buffer[PAGE_SIZE]; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; allocatedLength = sizeof(buffer); subRequestBuffer = PhAllocate(allocatedLength); dataLength = 0; while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength)) { if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } memcpy(subRequestBuffer + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } // Ensure that the buffer is null-terminated. subRequestBuffer[dataLength] = 0; } CleanupExit: if (requestHandle) WinHttpCloseHandle(requestHandle); if (connectHandle) WinHttpCloseHandle(connectHandle); if (httpSessionHandle) WinHttpCloseHandle(httpSessionHandle); if (JsonArray) PhDereferenceObject(JsonArray); return subRequestBuffer; }
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); }
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; }
INT_PTR CALLBACK PhpProcessThreadsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_THREADS_CONTEXT threadsContext; HWND tnHandle; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { threadsContext = (PPH_THREADS_CONTEXT)propPageContext->Context; if (threadsContext) tnHandle = threadsContext->ListContext.TreeNewHandle; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { threadsContext = propPageContext->Context = PhAllocate(PhEmGetObjectSize(EmThreadsContextType, sizeof(PH_THREADS_CONTEXT))); // The thread provider has a special registration mechanism. threadsContext->Provider = PhCreateThreadProvider( processItem->ProcessId ); PhRegisterCallback( &threadsContext->Provider->ThreadAddedEvent, ThreadAddedHandler, threadsContext, &threadsContext->AddedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadModifiedEvent, ThreadModifiedHandler, threadsContext, &threadsContext->ModifiedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadRemovedEvent, ThreadRemovedHandler, threadsContext, &threadsContext->RemovedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->UpdatedEvent, ThreadsUpdatedHandler, threadsContext, &threadsContext->UpdatedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, ThreadsLoadingStateChangedHandler, threadsContext, &threadsContext->LoadingStateChangedEventRegistration ); threadsContext->WindowHandle = hwndDlg; // Initialize the list. tnHandle = GetDlgItem(hwndDlg, IDC_LIST); BringWindowToTop(tnHandle); PhInitializeThreadList(hwndDlg, tnHandle, &threadsContext->ListContext); TreeNew_SetEmptyText(tnHandle, &EmptyThreadsText, 0); PhInitializeProviderEventQueue(&threadsContext->EventQueue, 100); // Use Cycles instead of Context Switches on Vista and above, but only when we can // open the process, since cycle time information requires sufficient access to the // threads. if (WINDOWS_HAS_CYCLE_TIME) { HANDLE processHandle; PROCESS_EXTENDED_BASIC_INFORMATION extendedBasicInfo; // We make a distinction between PROCESS_QUERY_INFORMATION and PROCESS_QUERY_LIMITED_INFORMATION since // the latter can be used when opening audiodg.exe even though we can't access its threads using // THREAD_QUERY_LIMITED_INFORMATION. if (processItem->ProcessId == SYSTEM_IDLE_PROCESS_ID) { threadsContext->ListContext.UseCycleTime = TRUE; } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; NtClose(processHandle); } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_LIMITED_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; // We can't use cycle time for protected processes (without KProcessHacker). if (NT_SUCCESS(PhGetProcessExtendedBasicInformation(processHandle, &extendedBasicInfo)) && extendedBasicInfo.IsProtectedProcess) { threadsContext->ListContext.UseCycleTime = FALSE; } NtClose(processHandle); } } if (processItem->ServiceList && processItem->ServiceList->Count != 0 && WINDOWS_HAS_SERVICE_TAGS) threadsContext->ListContext.HasServices = TRUE; PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectCreate); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; treeNewInfo.SystemContext = threadsContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewInitializing), &treeNewInfo); } PhLoadSettingsThreadList(&threadsContext->ListContext); PhThreadProviderInitialUpdate(threadsContext->Provider); PhRegisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); SET_BUTTON_ICON(IDC_OPENSTARTMODULE, PH_LOAD_SHARED_ICON_SMALL(MAKEINTRESOURCE(IDI_FOLDER))); } break; case WM_DESTROY: { PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectDelete); PhUnregisterCallback( &threadsContext->Provider->ThreadAddedEvent, &threadsContext->AddedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadModifiedEvent, &threadsContext->ModifiedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadRemovedEvent, &threadsContext->RemovedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->UpdatedEvent, &threadsContext->UpdatedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, &threadsContext->LoadingStateChangedEventRegistration ); PhUnregisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); PhSetTerminatingThreadProvider(threadsContext->Provider); PhDereferenceObject(threadsContext->Provider); PhDeleteProviderEventQueue(&threadsContext->EventQueue); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewUninitializing), &treeNewInfo); } PhSaveSettingsThreadList(&threadsContext->ListContext); PhDeleteThreadList(&threadsContext->ListContext); PhFree(threadsContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); #define ADD_BL_ITEM(Id) \ PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, Id), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM) // Thread details area { ULONG id; for (id = IDC_STATICBL1; id <= IDC_STATICBL11; id++) ADD_BL_ITEM(id); // Not in sequence ADD_BL_ITEM(IDC_STATICBL12); } PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_STARTMODULE), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_OPENSTARTMODULE), dialogItem, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); ADD_BL_ITEM(IDC_STARTED); ADD_BL_ITEM(IDC_KERNELTIME); ADD_BL_ITEM(IDC_USERTIME); ADD_BL_ITEM(IDC_CONTEXTSWITCHES); ADD_BL_ITEM(IDC_CYCLES); ADD_BL_ITEM(IDC_STATE); ADD_BL_ITEM(IDC_PRIORITY); ADD_BL_ITEM(IDC_BASEPRIORITY); ADD_BL_ITEM(IDC_IOPRIORITY); ADD_BL_ITEM(IDC_PAGEPRIORITY); ADD_BL_ITEM(IDC_IDEALPROCESSOR); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { INT id = LOWORD(wParam); switch (id) { case ID_SHOWCONTEXTMENU: { PhShowThreadContextMenu(hwndDlg, processItem, threadsContext, (PPH_TREENEW_CONTEXT_MENU)lParam); } break; case ID_THREAD_INSPECT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider); PhShowThreadStackDialog( hwndDlg, threadsContext->Provider->ProcessId, threadItem->ThreadId, threadsContext->Provider ); PhDereferenceObject(threadsContext->Provider); } } break; case ID_THREAD_TERMINATE: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); if (PhUiTerminateThreads(hwndDlg, threads, numberOfThreads)) PhDeselectAllThreadNodes(&threadsContext->ListContext); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_SUSPEND: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiSuspendThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_RESUME: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiResumeThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_AFFINITY: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadItem); PhShowProcessAffinityDialog(hwndDlg, NULL, threadItem); PhDereferenceObject(threadItem); } } break; case ID_THREAD_PERMISSIONS: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); PH_STD_OBJECT_SECURITY stdObjectSecurity; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; if (threadItem) { stdObjectSecurity.OpenObject = PhpThreadPermissionsOpenThread; stdObjectSecurity.ObjectType = L"Thread"; stdObjectSecurity.Context = threadItem->ThreadId; if (PhGetAccessEntries(L"Thread", &accessEntries, &numberOfAccessEntries)) { PhEditSecurity( hwndDlg, PhaFormatString(L"Thread %u", HandleToUlong(threadItem->ThreadId))->Buffer, PhStdGetObjectSecurity, PhStdSetObjectSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries ); PhFree(accessEntries); } } } break; case ID_THREAD_TOKEN: { NTSTATUS status; PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); HANDLE threadHandle; if (threadItem) { if (NT_SUCCESS(status = PhOpenThread( &threadHandle, ThreadQueryAccess, threadItem->ThreadId ))) { PhShowTokenProperties( hwndDlg, PhpOpenThreadTokenObject, (PVOID)threadHandle, NULL ); NtClose(threadHandle); } else { PhShowStatus(hwndDlg, L"Unable to open the thread", status, 0); } } } break; case ID_ANALYZE_WAIT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider->SymbolProvider); PhUiAnalyzeWaitThread( hwndDlg, processItem->ProcessId, threadItem->ThreadId, threadsContext->Provider->SymbolProvider ); PhDereferenceObject(threadsContext->Provider->SymbolProvider); } } break; case ID_PRIORITY_TIMECRITICAL: case ID_PRIORITY_HIGHEST: case ID_PRIORITY_ABOVENORMAL: case ID_PRIORITY_NORMAL: case ID_PRIORITY_BELOWNORMAL: case ID_PRIORITY_LOWEST: case ID_PRIORITY_IDLE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG threadPriorityWin32; switch (id) { case ID_PRIORITY_TIMECRITICAL: threadPriorityWin32 = THREAD_PRIORITY_TIME_CRITICAL; break; case ID_PRIORITY_HIGHEST: threadPriorityWin32 = THREAD_PRIORITY_HIGHEST; break; case ID_PRIORITY_ABOVENORMAL: threadPriorityWin32 = THREAD_PRIORITY_ABOVE_NORMAL; break; case ID_PRIORITY_NORMAL: threadPriorityWin32 = THREAD_PRIORITY_NORMAL; break; case ID_PRIORITY_BELOWNORMAL: threadPriorityWin32 = THREAD_PRIORITY_BELOW_NORMAL; break; case ID_PRIORITY_LOWEST: threadPriorityWin32 = THREAD_PRIORITY_LOWEST; break; case ID_PRIORITY_IDLE: threadPriorityWin32 = THREAD_PRIORITY_IDLE; break; } PhReferenceObject(threadItem); PhUiSetPriorityThread(hwndDlg, threadItem, threadPriorityWin32); PhDereferenceObject(threadItem); } } break; case ID_IOPRIORITY_VERYLOW: case ID_IOPRIORITY_LOW: case ID_IOPRIORITY_NORMAL: case ID_IOPRIORITY_HIGH: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { IO_PRIORITY_HINT ioPriority; switch (id) { case ID_IOPRIORITY_VERYLOW: ioPriority = IoPriorityVeryLow; break; case ID_IOPRIORITY_LOW: ioPriority = IoPriorityLow; break; case ID_IOPRIORITY_NORMAL: ioPriority = IoPriorityNormal; break; case ID_IOPRIORITY_HIGH: ioPriority = IoPriorityHigh; break; } PhReferenceObject(threadItem); PhUiSetIoPriorityThread(hwndDlg, threadItem, ioPriority); PhDereferenceObject(threadItem); } } break; case ID_PAGEPRIORITY_VERYLOW: case ID_PAGEPRIORITY_LOW: case ID_PAGEPRIORITY_MEDIUM: case ID_PAGEPRIORITY_BELOWNORMAL: case ID_PAGEPRIORITY_NORMAL: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG pagePriority; switch (id) { case ID_PAGEPRIORITY_VERYLOW: pagePriority = MEMORY_PRIORITY_VERY_LOW; break; case ID_PAGEPRIORITY_LOW: pagePriority = MEMORY_PRIORITY_LOW; break; case ID_PAGEPRIORITY_MEDIUM: pagePriority = MEMORY_PRIORITY_MEDIUM; break; case ID_PAGEPRIORITY_BELOWNORMAL: pagePriority = MEMORY_PRIORITY_BELOW_NORMAL; break; case ID_PAGEPRIORITY_NORMAL: pagePriority = MEMORY_PRIORITY_NORMAL; break; } PhReferenceObject(threadItem); PhUiSetPagePriorityThread(hwndDlg, threadItem, pagePriority); PhDereferenceObject(threadItem); } } break; case ID_THREAD_COPY: { PPH_STRING text; text = PhGetTreeNewText(tnHandle, 0); PhSetClipboardString(tnHandle, &text->sr); PhDereferenceObject(text); } break; case IDC_OPENSTARTMODULE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem && threadItem->StartAddressFileName) { PhShellExploreFile(hwndDlg, threadItem->StartAddressFileName->Buffer); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_SETACTIVE: break; case PSN_KILLACTIVE: // Can't disable, it screws up the deltas. break; } } break; case WM_PH_THREADS_UPDATED: { ULONG upToRunId = (ULONG)wParam; BOOLEAN firstRun = !!lParam; PPH_PROVIDER_EVENT events; ULONG count; ULONG i; events = PhFlushProviderEventQueue(&threadsContext->EventQueue, upToRunId, &count); if (events) { TreeNew_SetRedraw(tnHandle, FALSE); for (i = 0; i < count; i++) { PH_PROVIDER_EVENT_TYPE type = PH_PROVIDER_EVENT_TYPE(events[i]); PPH_THREAD_ITEM threadItem = PH_PROVIDER_EVENT_OBJECT(events[i]); switch (type) { case ProviderAddedEvent: PhAddThreadNode(&threadsContext->ListContext, threadItem, firstRun); PhDereferenceObject(threadItem); break; case ProviderModifiedEvent: PhUpdateThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; case ProviderRemovedEvent: PhRemoveThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; } } PhFree(events); } PhTickThreadNodes(&threadsContext->ListContext); if (count != 0) TreeNew_SetRedraw(tnHandle, TRUE); if (propPageContext->PropContext->SelectThreadId) { PPH_THREAD_NODE threadNode; if (threadNode = PhFindThreadNode(&threadsContext->ListContext, propPageContext->PropContext->SelectThreadId)) { if (threadNode->Node.Visible) { TreeNew_SetFocusNode(tnHandle, &threadNode->Node); TreeNew_SetMarkNode(tnHandle, &threadNode->Node); TreeNew_SelectRange(tnHandle, threadNode->Node.Index, threadNode->Node.Index); TreeNew_EnsureVisible(tnHandle, &threadNode->Node); } } propPageContext->PropContext->SelectThreadId = NULL; } PhpUpdateThreadDetails(hwndDlg, threadsContext, FALSE); } break; case WM_PH_THREAD_SELECTION_CHANGED: { PhpUpdateThreadDetails(hwndDlg, threadsContext, TRUE); } break; } return FALSE; }
// NOTE: This function does not use the SCM due to major performance issues. // For now just query this information from the registry but it might be out-of-sync // with any recent services changes until the SCM flushes its cache. NTSTATUS QueryServiceFileName( _In_ PPH_STRINGREF ServiceName, _Out_ PPH_STRING *ServiceFileName, _Out_ PPH_STRING *ServiceBinaryPath ) { static PH_STRINGREF servicesKeyName = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Services\\"); static PH_STRINGREF typeKeyName = PH_STRINGREF_INIT(L"Type"); NTSTATUS status; HANDLE keyHandle; ULONG serviceType = 0; PPH_STRING keyName; PPH_STRING binaryPath; PPH_STRING fileName; keyName = PhConcatStringRef2(&servicesKeyName, ServiceName); binaryPath = NULL; fileName = NULL; if (NT_SUCCESS(status = PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { PPH_STRING serviceImagePath; PKEY_VALUE_PARTIAL_INFORMATION buffer; if (NT_SUCCESS(status = PhQueryValueKey( keyHandle, &typeKeyName, KeyValuePartialInformation, &buffer ))) { if ( buffer->Type == REG_DWORD && buffer->DataLength == sizeof(ULONG) ) { serviceType = *(PULONG)buffer->Data; } PhFree(buffer); } if (serviceImagePath = PhQueryRegistryString(keyHandle, L"ImagePath")) { PPH_STRING expandedString; if (expandedString = PhExpandEnvironmentStrings(&serviceImagePath->sr)) { binaryPath = expandedString; PhDereferenceObject(serviceImagePath); } else { binaryPath = serviceImagePath; } } else { status = STATUS_NOT_FOUND; } NtClose(keyHandle); } if (NT_SUCCESS(status)) { PhGetServiceDllParameter(ServiceName, &fileName); if (!fileName) { if (serviceType & SERVICE_WIN32) { PH_STRINGREF dummyFileName; PH_STRINGREF dummyArguments; PhParseCommandLineFuzzy(&binaryPath->sr, &dummyFileName, &dummyArguments, &fileName); if (!fileName) PhSwapReference(&fileName, binaryPath); } else { fileName = PhGetFileName(binaryPath); } } *ServiceFileName = fileName; *ServiceBinaryPath = binaryPath; } else { if (binaryPath) PhDereferenceObject(binaryPath); } PhDereferenceObject(keyName); return status; }
VOID NTAPI MenuItemCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_ITEM menuItem = Parameter; switch (menuItem->Id) { case ID_VIEW_WINDOWS: { WE_WINDOW_SELECTOR selector; selector.Type = WeWindowSelectorAll; WeShowWindowsDialog(WE_PhMainWndHandle, &selector); } break; case ID_VIEW_DESKTOPWINDOWS: { PPH_LIST desktopNames; PPH_STRING selectedChoice = NULL; desktopNames = PhCreateList(4); EnumDesktops(GetProcessWindowStation(), WepEnumDesktopProc, (LPARAM)desktopNames); if (PhaChoiceDialog( WE_PhMainWndHandle, L"Desktop Windows", L"Display windows for the following desktop:", (PWSTR *)desktopNames->Items, desktopNames->Count, NULL, PH_CHOICE_DIALOG_CHOICE, &selectedChoice, NULL, NULL )) { WE_WINDOW_SELECTOR selector; selector.Type = WeWindowSelectorDesktop; PhReferenceObject(selectedChoice); selector.Desktop.DesktopName = selectedChoice; WeShowWindowsDialog(WE_PhMainWndHandle, &selector); } PhDereferenceObject(desktopNames); } break; case ID_PROCESS_WINDOWS: { WE_WINDOW_SELECTOR selector; selector.Type = WeWindowSelectorProcess; selector.Process.ProcessId = ((PPH_PROCESS_ITEM)menuItem->Context)->ProcessId; WeShowWindowsDialog(WE_PhMainWndHandle, &selector); } break; case ID_THREAD_WINDOWS: { WE_WINDOW_SELECTOR selector; selector.Type = WeWindowSelectorThread; selector.Thread.ThreadId = ((PPH_THREAD_ITEM)menuItem->Context)->ThreadId; WeShowWindowsDialog(WE_PhMainWndHandle, &selector); } break; } }
INT_PTR CALLBACK EspServiceRecoveryDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PSERVICE_RECOVERY_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(SERVICE_RECOVERY_CONTEXT)); memset(context, 0, sizeof(SERVICE_RECOVERY_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam; context->ServiceItem = serviceItem; EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE)); EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SECONDFAILURE)); EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES)); status = EspLoadRecoveryInfo(hwndDlg, context); if (status == STATUS_SOME_NOT_MAPPED) { if (context->NumberOfActions > 3) { PhShowWarning( hwndDlg, L"The service has %lu failure actions configured, but this program only supports editing 3. " L"If you save the recovery information using this program, the additional failure actions will be lost.", context->NumberOfActions ); } } else if (!NT_SUCCESS(status)) { SetDlgItemText(hwndDlg, IDC_RESETFAILCOUNT, L"0"); if (WindowsVersion >= WINDOWS_VISTA) { context->EnableFlagCheckBox = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS), TRUE); } PhShowWarning(hwndDlg, L"Unable to query service recovery information: %s", ((PPH_STRING)PhAutoDereferenceObject(PhGetNtMessage(status)))->Buffer); } EspFixControls(hwndDlg, context); context->Ready = TRUE; } break; case WM_DESTROY: { PhClearReference(&context->RebootMessage); PhFree(context); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_FIRSTFAILURE: case IDC_SECONDFAILURE: case IDC_SUBSEQUENTFAILURES: { if (HIWORD(wParam) == CBN_SELCHANGE) { EspFixControls(hwndDlg, context); } } break; case IDC_RESTARTCOMPUTEROPTIONS: { DialogBoxParam( PluginInstance->DllBase, MAKEINTRESOURCE(IDD_RESTARTCOMP), hwndDlg, RestartComputerDlgProc, (LPARAM)context ); } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.cmd;*.bat)", L"*.exe;*.cmd;*.bat" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhaGetDlgItemText(hwndDlg, IDC_RUNPROGRAM); PhSetFileDialogFileName(fileDialog, fileName->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_RUNPROGRAM, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; case IDC_ENABLEFORERRORSTOPS: { context->Dirty = TRUE; } break; } switch (HIWORD(wParam)) { case EN_CHANGE: case CBN_SELCHANGE: { if (context->Ready) context->Dirty = TRUE; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { NTSTATUS status; PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; ULONG restartServiceAfter; SERVICE_FAILURE_ACTIONS failureActions; SC_ACTION actions[3]; ULONG i; BOOLEAN enableRestart = FALSE; SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); if (!context->Dirty) { return TRUE; } // Build the failure actions structure. failureActions.dwResetPeriod = GetDlgItemInt(hwndDlg, IDC_RESETFAILCOUNT, NULL, FALSE) * 60 * 60 * 24; failureActions.lpRebootMsg = PhGetStringOrEmpty(context->RebootMessage); failureActions.lpCommand = PhaGetDlgItemText(hwndDlg, IDC_RUNPROGRAM)->Buffer; failureActions.cActions = 3; failureActions.lpsaActions = actions; actions[0].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE)); actions[1].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SECONDFAILURE)); actions[2].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES)); restartServiceAfter = GetDlgItemInt(hwndDlg, IDC_RESTARTSERVICEAFTER, NULL, FALSE) * 1000 * 60; for (i = 0; i < 3; i++) { switch (actions[i].Type) { case SC_ACTION_RESTART: actions[i].Delay = restartServiceAfter; enableRestart = TRUE; break; case SC_ACTION_REBOOT: actions[i].Delay = context->RebootAfter; break; case SC_ACTION_RUN_COMMAND: actions[i].Delay = 0; break; } } // Try to save the changes. serviceHandle = PhOpenService( serviceItem->Name->Buffer, SERVICE_CHANGE_CONFIG | (enableRestart ? SERVICE_START : 0) // SC_ACTION_RESTART requires SERVICE_START ); if (serviceHandle) { if (ChangeServiceConfig2( serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, &failureActions )) { if (context->EnableFlagCheckBox) { SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag; failureActionsFlag.fFailureActionsOnNonCrashFailures = Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS)) == BST_CHECKED; ChangeServiceConfig2( serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &failureActionsFlag ); } CloseServiceHandle(serviceHandle); } else { CloseServiceHandle(serviceHandle); goto ErrorCase; } } else { if (GetLastError() == ERROR_ACCESS_DENIED && !PhElevated) { // Elevate using phsvc. if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { if (NT_SUCCESS(status = PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_FAILURE_ACTIONS, &failureActions ))) { if (context->EnableFlagCheckBox) { SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag; failureActionsFlag.fFailureActionsOnNonCrashFailures = Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS)) == BST_CHECKED; PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &failureActionsFlag ); } } PhUiDisconnectFromPhSvc(); if (!NT_SUCCESS(status)) { SetLastError(PhNtStatusToDosError(status)); goto ErrorCase; } } else { // User cancelled elevation. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } else { goto ErrorCase; } } return TRUE; ErrorCase: if (PhShowMessage( hwndDlg, MB_ICONERROR | MB_RETRYCANCEL, L"Unable to change service recovery information: %s", ((PPH_STRING)PhAutoDereferenceObject(PhGetWin32Message(GetLastError())))->Buffer ) == IDRETRY) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } return TRUE; } } 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; }
INT_PTR CALLBACK RestartComputerDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PSERVICE_RECOVERY_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PSERVICE_RECOVERY_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { SetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, context->RebootAfter / (1000 * 60), FALSE); // ms to min Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), context->RebootMessage ? BST_CHECKED : BST_UNCHECKED); SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, PhGetString(context->RebootMessage)); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_RESTARTCOMPAFTER), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_RESTARTCOMPAFTER), 0, -1); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { context->RebootAfter = GetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, NULL, FALSE) * 1000 * 60; if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE)) == BST_CHECKED) PhMoveReference(&context->RebootMessage, PhGetWindowText(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE))); else PhClearReference(&context->RebootMessage); context->Dirty = TRUE; EndDialog(hwndDlg, IDOK); } break; case IDC_USEDEFAULTMESSAGE: { PPH_STRING message; PWSTR computerName; ULONG bufferSize; BOOLEAN allocated = TRUE; // Get the computer name. bufferSize = 64; computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR)); if (!GetComputerName(computerName, &bufferSize)) { PhFree(computerName); computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR)); if (!GetComputerName(computerName, &bufferSize)) { PhFree(computerName); computerName = L"(unknown)"; allocated = FALSE; } } // This message is exactly the same as the one in the Services console, // except the double spaces are replaced by single spaces. message = PhFormatString( L"Your computer is connected to the computer named %s. " L"The %s service on %s has ended unexpectedly. " L"%s will restart automatically, and then you can reestablish the connection.", computerName, context->ServiceItem->Name->Buffer, computerName, computerName ); SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, message->Buffer); PhDereferenceObject(message); if (allocated) PhFree(computerName); Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), BST_CHECKED); } break; case IDC_RESTARTMESSAGE: { if (HIWORD(wParam) == EN_CHANGE) { // A zero length restart message disables it, so we might as well uncheck the box. Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE)) != 0 ? BST_CHECKED : BST_UNCHECKED); } } break; } } break; } return FALSE; }
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; }
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; }