BOOLEAN PhpCalculateFileHash( _In_ HANDLE FileHandle, _In_ PWSTR HashAlgorithm, _Out_ PUCHAR *FileHash, _Out_ PULONG FileHashLength, _Out_ HANDLE *CatAdminHandle ) { HANDLE catAdminHandle; PUCHAR fileHash; ULONG fileHashLength; if (CryptCATAdminAcquireContext2) { if (!CryptCATAdminAcquireContext2(&catAdminHandle, &DriverActionVerify, HashAlgorithm, NULL, 0)) return FALSE; } else { if (!CryptCATAdminAcquireContext(&catAdminHandle, &DriverActionVerify, 0)) return FALSE; } fileHashLength = 32; fileHash = PhAllocate(fileHashLength); if (CryptCATAdminCalcHashFromFileHandle2) { if (!CryptCATAdminCalcHashFromFileHandle2(catAdminHandle, FileHandle, &fileHashLength, fileHash, 0)) { PhFree(fileHash); fileHash = PhAllocate(fileHashLength); if (!CryptCATAdminCalcHashFromFileHandle2(catAdminHandle, FileHandle, &fileHashLength, fileHash, 0)) { CryptCATAdminReleaseContext(catAdminHandle, 0); PhFree(fileHash); return FALSE; } } } else { if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &fileHashLength, fileHash, 0)) { PhFree(fileHash); fileHash = PhAllocate(fileHashLength); if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &fileHashLength, fileHash, 0)) { CryptCATAdminReleaseContext(catAdminHandle, 0); PhFree(fileHash); return FALSE; } } } *FileHash = fileHash; *FileHashLength = fileHashLength; *CatAdminHandle = catAdminHandle; return TRUE; }
VERIFY_RESULT PhpVerifyFileFromCatalog( _In_ PPH_VERIFY_FILE_INFO Information, _In_ HANDLE FileHandle, _In_opt_ PWSTR HashAlgorithm, _Out_ PCERT_CONTEXT **Signatures, _Out_ PULONG NumberOfSignatures ) { VERIFY_RESULT verifyResult = VrNoSignature; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; WINTRUST_CATALOG_INFO catalogInfo = { 0 }; LARGE_INTEGER fileSize; ULONG fileSizeLimit; PUCHAR fileHash; ULONG fileHashLength; PPH_STRING fileHashTag; HANDLE catAdminHandle; HANDLE catInfoHandle; ULONG i; *Signatures = NULL; *NumberOfSignatures = 0; if (!NT_SUCCESS(PhGetFileSize(FileHandle, &fileSize))) return VrNoSignature; signatures = NULL; numberOfSignatures = 0; if (Information->FileSizeLimitForHash != -1) { fileSizeLimit = PH_VERIFY_DEFAULT_SIZE_LIMIT; if (Information->FileSizeLimitForHash != 0) fileSizeLimit = Information->FileSizeLimitForHash; if (fileSize.QuadPart > fileSizeLimit) return VrNoSignature; } if (PhpCalculateFileHash(FileHandle, HashAlgorithm, &fileHash, &fileHashLength, &catAdminHandle)) { fileHashTag = PhBufferToHexStringEx(fileHash, fileHashLength, TRUE); // Search the system catalogs. catInfoHandle = CryptCATAdminEnumCatalogFromHash( catAdminHandle, fileHash, fileHashLength, 0, NULL ); if (catInfoHandle) { CATALOG_INFO ci = { 0 }; DRIVER_VER_INFO verInfo = { 0 }; if (CryptCATCatalogInfoFromContext(catInfoHandle, &ci, 0)) { // Disable OS version checking by passing in a DRIVER_VER_INFO structure. verInfo.cbStruct = sizeof(DRIVER_VER_INFO); catalogInfo.cbStruct = sizeof(catalogInfo); catalogInfo.pcwszCatalogFilePath = ci.wszCatalogFile; catalogInfo.pcwszMemberFilePath = Information->FileName; catalogInfo.pcwszMemberTag = fileHashTag->Buffer; catalogInfo.pbCalculatedFileHash = fileHash; catalogInfo.cbCalculatedFileHash = fileHashLength; catalogInfo.hCatAdmin = catAdminHandle; verifyResult = PhpVerifyFile(Information, FileHandle, WTD_CHOICE_CATALOG, &catalogInfo, &DriverActionVerify, &verInfo, &signatures, &numberOfSignatures); if (verInfo.pcSignerCertContext) CertFreeCertificateContext_I(verInfo.pcSignerCertContext); } CryptCATAdminReleaseCatalogContext(catAdminHandle, catInfoHandle, 0); } else { // Search any user-supplied catalogs. for (i = 0; i < Information->NumberOfCatalogFileNames; i++) { PhFreeVerifySignatures(signatures, numberOfSignatures); catalogInfo.cbStruct = sizeof(catalogInfo); catalogInfo.pcwszCatalogFilePath = Information->CatalogFileNames[i]; catalogInfo.pcwszMemberFilePath = Information->FileName; catalogInfo.pcwszMemberTag = fileHashTag->Buffer; catalogInfo.pbCalculatedFileHash = fileHash; catalogInfo.cbCalculatedFileHash = fileHashLength; catalogInfo.hCatAdmin = catAdminHandle; verifyResult = PhpVerifyFile(Information, FileHandle, WTD_CHOICE_CATALOG, &catalogInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures); if (verifyResult == VrTrusted) break; } } PhDereferenceObject(fileHashTag); PhFree(fileHash); CryptCATAdminReleaseContext(catAdminHandle, 0); } *Signatures = signatures; *NumberOfSignatures = numberOfSignatures; return verifyResult; }
void mxmlDelete(mxml_node_t *node) /* I - Node to delete */ { int i; /* Looping var */ #ifdef DEBUG fprintf(stderr, "mxmlDelete(node=%p)\n", node); #endif /* DEBUG */ /* * Range check input... */ if (!node) return; /* * Remove the node from its parent, if any... */ mxmlRemove(node); /* * Delete children... */ while (node->child) mxmlDelete(node->child); /* * Now delete any node data... */ switch (node->type) { case MXML_ELEMENT : if (node->value.element.name) PhFree(node->value.element.name); if (node->value.element.num_attrs) { for (i = 0; i < node->value.element.num_attrs; i ++) { if (node->value.element.attrs[i].name) PhFree(node->value.element.attrs[i].name); if (node->value.element.attrs[i].value) PhFree(node->value.element.attrs[i].value); } PhFree(node->value.element.attrs); } break; case MXML_INTEGER : /* Nothing to do */ break; case MXML_OPAQUE : if (node->value.opaque) PhFree(node->value.opaque); break; case MXML_REAL : /* Nothing to do */ break; case MXML_TEXT : if (node->value.text.string) PhFree(node->value.text.string); break; case MXML_CUSTOM : if (node->value.custom.data && node->value.custom.destroy) (*(node->value.custom.destroy))(node->value.custom.data); break; default : break; } /* * Free this node... */ PhFree(node); }
static BOOLEAN NetAdapterSectionCallback( _In_ PPH_SYSINFO_SECTION Section, _In_ PH_SYSINFO_SECTION_MESSAGE Message, _In_opt_ PVOID Parameter1, _In_opt_ PVOID Parameter2 ) { PPH_NETADAPTER_SYSINFO_CONTEXT context = (PPH_NETADAPTER_SYSINFO_CONTEXT)Section->Context; switch (Message) { case SysInfoCreate: { if (PhGetIntegerSetting(SETTING_NAME_ENABLE_NDIS)) { PhCreateFileWin32( &context->DeviceHandle, PhaFormatString(L"\\\\.\\%s", context->AdapterEntry->InterfaceGuid->Buffer)->Buffer, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (context->DeviceHandle) { if (!NetworkAdapterQuerySupported(context->DeviceHandle)) { NtClose(context->DeviceHandle); context->DeviceHandle = NULL; } } } if (WindowsVersion > WINDOWS_VISTA) { if ((context->IphlpHandle = LoadLibrary(L"iphlpapi.dll"))) { context->GetIfEntry2_I = (_GetIfEntry2)GetProcAddress(context->IphlpHandle, "GetIfEntry2"); context->GetInterfaceDescriptionFromGuid_I = (_GetInterfaceDescriptionFromGuid)GetProcAddress(context->IphlpHandle, "NhGetInterfaceDescriptionFromGuid"); } } PhInitializeCircularBuffer_ULONG64(&context->InboundBuffer, PhGetIntegerSetting(L"SampleCount")); PhInitializeCircularBuffer_ULONG64(&context->OutboundBuffer, PhGetIntegerSetting(L"SampleCount")); } return TRUE; case SysInfoDestroy: { if (context->AdapterName) PhDereferenceObject(context->AdapterName); PhDeleteCircularBuffer_ULONG64(&context->InboundBuffer); PhDeleteCircularBuffer_ULONG64(&context->OutboundBuffer); if (context->IphlpHandle) FreeLibrary(context->IphlpHandle); if (context->DeviceHandle) NtClose(context->DeviceHandle); PhFree(context); } return TRUE; case SysInfoTick: { ULONG64 networkInboundSpeed = 0; ULONG64 networkOutboundSpeed = 0; ULONG64 networkInOctets = 0; ULONG64 networkOutOctets = 0; ULONG64 xmitLinkSpeed = 0; ULONG64 rcvLinkSpeed = 0; if (context->DeviceHandle) { NDIS_STATISTICS_INFO interfaceStats; NDIS_LINK_STATE interfaceState; if (NT_SUCCESS(NetworkAdapterQueryStatistics(context->DeviceHandle, &interfaceStats))) { networkInboundSpeed = interfaceStats.ifHCInOctets - context->LastInboundValue; networkOutboundSpeed = interfaceStats.ifHCOutOctets - context->LastOutboundValue; networkInOctets = interfaceStats.ifHCInOctets; networkOutOctets = interfaceStats.ifHCOutOctets; } else { ULONG64 inOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_RCV); ULONG64 outOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_XMIT); networkInboundSpeed = inOctets - context->LastInboundValue; networkOutboundSpeed = outOctets - context->LastOutboundValue; networkInOctets = inOctets; networkOutOctets = outOctets; } if (NT_SUCCESS(NetworkAdapterQueryLinkState(context, &interfaceState))) { xmitLinkSpeed = interfaceState.XmitLinkSpeed; rcvLinkSpeed = interfaceState.RcvLinkSpeed; } // HACK: Pull the Adapter name from the current query. if (context->SysinfoSection->Name.Length == 0) { if (context->AdapterName = NetworkAdapterQueryName(context)) { context->SysinfoSection->Name = context->AdapterName->sr; } } } else { if (context->GetIfEntry2_I) { MIB_IF_ROW2 interfaceRow; interfaceRow = QueryInterfaceRowVista(context); networkInboundSpeed = interfaceRow.InOctets - context->LastInboundValue; networkOutboundSpeed = interfaceRow.OutOctets - context->LastOutboundValue; networkInOctets = interfaceRow.InOctets; networkOutOctets = interfaceRow.OutOctets; xmitLinkSpeed = interfaceRow.TransmitLinkSpeed; rcvLinkSpeed = interfaceRow.ReceiveLinkSpeed; // HACK: Pull the Adapter name from the current query. if (context->SysinfoSection->Name.Length == 0) { if (context->AdapterName = PhCreateString(interfaceRow.Description)) { context->SysinfoSection->Name = context->AdapterName->sr; } } } else { MIB_IFROW interfaceRow; interfaceRow = QueryInterfaceRowXP(context); networkInboundSpeed = interfaceRow.dwInOctets - context->LastInboundValue; networkOutboundSpeed = interfaceRow.dwOutOctets - context->LastOutboundValue; networkInOctets = interfaceRow.dwInOctets; networkOutOctets = interfaceRow.dwOutOctets; xmitLinkSpeed = interfaceRow.dwSpeed; rcvLinkSpeed = interfaceRow.dwSpeed; // HACK: Pull the Adapter name from the current query. if (context->SysinfoSection->Name.Length == 0) { if (context->AdapterName = PhCreateStringFromAnsi(interfaceRow.bDescr)) { context->SysinfoSection->Name = context->AdapterName->sr; } } } } if (!context->HaveFirstSample) { networkInboundSpeed = 0; networkOutboundSpeed = 0; context->HaveFirstSample = TRUE; } PhAddItemCircularBuffer_ULONG64(&context->InboundBuffer, networkInboundSpeed); PhAddItemCircularBuffer_ULONG64(&context->OutboundBuffer, networkOutboundSpeed); context->InboundValue = networkInboundSpeed; context->OutboundValue = networkOutboundSpeed; context->LastInboundValue = networkInOctets; context->LastOutboundValue = networkOutOctets; context->MaxSendSpeed = xmitLinkSpeed; context->MaxReceiveSpeed = rcvLinkSpeed; } return TRUE; case SysInfoCreateDialog: { PPH_SYSINFO_CREATE_DIALOG createDialog = (PPH_SYSINFO_CREATE_DIALOG)Parameter1; createDialog->Instance = PluginInstance->DllBase; createDialog->Template = MAKEINTRESOURCE(IDD_NETADAPTER_DIALOG); createDialog->DialogProc = NetAdapterDialogProc; createDialog->Parameter = context; } return TRUE; case SysInfoGraphGetDrawInfo: { PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)Parameter1; drawInfo->Flags = PH_GRAPH_USE_GRID | PH_GRAPH_USE_LINE_2; Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), PhGetIntegerSetting(L"ColorCpuUser")); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, context->InboundBuffer.Count); if (!Section->GraphState.Valid) { FLOAT maxGraphHeight1 = 0; FLOAT maxGraphHeight2 = 0; for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { Section->GraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->InboundBuffer, i); Section->GraphState.Data2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->OutboundBuffer, i); if (Section->GraphState.Data1[i] > maxGraphHeight1) maxGraphHeight1 = Section->GraphState.Data1[i]; if (Section->GraphState.Data2[i] > maxGraphHeight2) maxGraphHeight2 = Section->GraphState.Data2[i]; } // Scale the data. PhxfDivideSingle2U( Section->GraphState.Data1, maxGraphHeight1, // (FLOAT)context->MaxReceiveSpeed, drawInfo->LineDataCount ); // Scale the data. PhxfDivideSingle2U( Section->GraphState.Data2, maxGraphHeight2, // (FLOAT)context->MaxSendSpeed, drawInfo->LineDataCount ); Section->GraphState.Valid = TRUE; } } return TRUE; case SysInfoGraphGetTooltipText: { PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = (PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT)Parameter1; ULONG64 adapterInboundValue = PhGetItemCircularBuffer_ULONG64( &context->InboundBuffer, getTooltipText->Index ); ULONG64 adapterOutboundValue = PhGetItemCircularBuffer_ULONG64( &context->OutboundBuffer, getTooltipText->Index ); PhSwapReference2(&Section->GraphState.TooltipText, PhFormatString( L"R: %s\nS: %s\n%s", PhaFormatSize(adapterInboundValue, -1)->Buffer, PhaFormatSize(adapterOutboundValue, -1)->Buffer, ((PPH_STRING)PHA_DEREFERENCE(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); getTooltipText->Text = Section->GraphState.TooltipText->sr; } return TRUE; case SysInfoGraphDrawPanel: { PPH_SYSINFO_DRAW_PANEL drawPanel = (PPH_SYSINFO_DRAW_PANEL)Parameter1; drawPanel->Title = PhCreateString(Section->Name.Buffer); drawPanel->SubTitle = PhFormatString( L"R: %s\nS: %s", PhaFormatSize(context->InboundValue, -1)->Buffer, PhaFormatSize(context->OutboundValue, -1)->Buffer ); } return TRUE; } return FALSE; }
HBITMAP PhLoadPngImageFromResource( _In_ PVOID DllBase, _In_ UINT Width, _In_ UINT Height, _In_ PCWSTR Name, _In_ BOOLEAN RGBAImage ) { BOOLEAN success = FALSE; UINT frameCount = 0; ULONG resourceLength = 0; WICInProcPointer resourceBuffer = NULL; HDC screenHdc = NULL; HDC bufferDc = NULL; BITMAPINFO bitmapInfo = { 0 }; HBITMAP bitmapHandle = NULL; PVOID bitmapBuffer = NULL; IWICStream* wicStream = NULL; IWICBitmapSource* wicBitmapSource = NULL; IWICBitmapDecoder* wicDecoder = NULL; IWICBitmapFrameDecode* wicFrame = NULL; IWICImagingFactory* wicFactory = NULL; IWICBitmapScaler* wicScaler = NULL; WICPixelFormatGUID pixelFormat; WICRect rect = { 0, 0, Width, Height }; // Create the ImagingFactory if (FAILED(CoCreateInstance(&CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, &wicFactory))) goto CleanupExit; // Load the resource if (!PhLoadResource(DllBase, Name, L"PNG", &resourceLength, &resourceBuffer)) goto CleanupExit; // Create the Stream if (FAILED(IWICImagingFactory_CreateStream(wicFactory, &wicStream))) goto CleanupExit; // Initialize the Stream from Memory if (FAILED(IWICStream_InitializeFromMemory(wicStream, resourceBuffer, resourceLength))) goto CleanupExit; if (FAILED(IWICImagingFactory_CreateDecoder(wicFactory, &GUID_ContainerFormatPng, NULL, &wicDecoder))) goto CleanupExit; if (FAILED(IWICBitmapDecoder_Initialize(wicDecoder, (IStream*)wicStream, WICDecodeMetadataCacheOnLoad))) goto CleanupExit; // Get the Frame count if (FAILED(IWICBitmapDecoder_GetFrameCount(wicDecoder, &frameCount)) || frameCount < 1) goto CleanupExit; // Get the Frame if (FAILED(IWICBitmapDecoder_GetFrame(wicDecoder, 0, &wicFrame))) goto CleanupExit; // Get the WicFrame image format if (FAILED(IWICBitmapFrameDecode_GetPixelFormat(wicFrame, &pixelFormat))) goto CleanupExit; // Check if the image format is supported: if (IsEqualGUID(&pixelFormat, RGBAImage ? &GUID_WICPixelFormat32bppPRGBA : &GUID_WICPixelFormat32bppPBGRA)) { wicBitmapSource = (IWICBitmapSource*)wicFrame; } else { IWICFormatConverter* wicFormatConverter = NULL; if (FAILED(IWICImagingFactory_CreateFormatConverter(wicFactory, &wicFormatConverter))) goto CleanupExit; if (FAILED(IWICFormatConverter_Initialize( wicFormatConverter, (IWICBitmapSource*)wicFrame, RGBAImage ? &GUID_WICPixelFormat32bppPRGBA : &GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom ))) { IWICFormatConverter_Release(wicFormatConverter); goto CleanupExit; } // Convert the image to the correct format: IWICFormatConverter_QueryInterface(wicFormatConverter, &IID_IWICBitmapSource, &wicBitmapSource); // Cleanup the converter. IWICFormatConverter_Release(wicFormatConverter); // Dispose the old frame now that the converted frame is in wicBitmapSource. IWICBitmapFrameDecode_Release(wicFrame); } bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfo.bmiHeader.biWidth = rect.Width; bitmapInfo.bmiHeader.biHeight = -((LONG)rect.Height); bitmapInfo.bmiHeader.biPlanes = 1; bitmapInfo.bmiHeader.biBitCount = 32; bitmapInfo.bmiHeader.biCompression = BI_RGB; screenHdc = GetDC(NULL); bufferDc = CreateCompatibleDC(screenHdc); bitmapHandle = CreateDIBSection(screenHdc, &bitmapInfo, DIB_RGB_COLORS, &bitmapBuffer, NULL, 0); // Check if it's the same rect as the requested size. //if (width != rect.Width || height != rect.Height) if (FAILED(IWICImagingFactory_CreateBitmapScaler(wicFactory, &wicScaler))) goto CleanupExit; if (FAILED(IWICBitmapScaler_Initialize(wicScaler, wicBitmapSource, rect.Width, rect.Height, WICBitmapInterpolationModeFant))) goto CleanupExit; if (FAILED(IWICBitmapScaler_CopyPixels(wicScaler, &rect, rect.Width * 4, rect.Width * rect.Height * 4, (PBYTE)bitmapBuffer))) goto CleanupExit; success = TRUE; CleanupExit: if (wicScaler) IWICBitmapScaler_Release(wicScaler); if (bufferDc) DeleteDC(bufferDc); if (screenHdc) ReleaseDC(NULL, screenHdc); if (wicBitmapSource) IWICBitmapSource_Release(wicBitmapSource); if (wicStream) IWICStream_Release(wicStream); if (wicDecoder) IWICBitmapDecoder_Release(wicDecoder); if (wicFactory) IWICImagingFactory_Release(wicFactory); if (resourceBuffer) PhFree(resourceBuffer); if (success) return bitmapHandle; DeleteObject(bitmapHandle); return NULL; }
INT_PTR CALLBACK PhpColumnSetEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PCOLUMNSET_DIALOG_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(COLUMNSET_DIALOG_CONTEXT)); memset(context, 0, sizeof(COLUMNSET_DIALOG_CONTEXT)); context->SettingName = PhCreateString((PWSTR)lParam); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PCOLUMNSET_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { context->DialogHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_COLUMNSETLIST); context->RenameButtonHandle = GetDlgItem(hwndDlg, IDC_RENAME); context->MoveUpButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEUP); context->MoveDownButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEDOWN); context->RemoveButtonHandle = GetDlgItem(hwndDlg, IDC_REMOVE); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); PhSetControlTheme(context->ListViewHandle, L"explorer"); PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 250, L"Name"); PhSetExtendedListView(context->ListViewHandle); context->ColumnSetList = PhInitializeColumnSetList(PhGetString(context->SettingName)); for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { PPH_COLUMN_SET_ENTRY entry = context->ColumnSetList->Items[i]; PhAddListViewItem(context->ListViewHandle, MAXINT, entry->Name->Buffer, entry); } Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); } break; case WM_DESTROY: { PhDeleteColumnSetList(context->ColumnSetList); RemoveProp(hwndDlg, PhMakeContextAtom()); PhFree(context); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { if (context->LabelEditActive) break; PhSaveSettingsColumnList(PhGetString(context->SettingName), context->ColumnSetList); EndDialog(hwndDlg, IDOK); } break; case IDC_RENAME: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case IDC_MOVEUP: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemUp(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_MOVEDOWN: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemDown(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_REMOVE: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhRemoveListViewItem(context->ListViewHandle, lvItemIndex); PhClearReference(&entry->Name); PhClearReference(&entry->Setting); PhClearReference(&entry->Sorting); PhFree(entry); } SetFocus(context->ListViewHandle); ListView_SetItemState(context->ListViewHandle, 0, LVNI_SELECTED, LVNI_SELECTED); //ListView_EnsureVisible(context->ListViewHandle, 0, FALSE); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case LVN_ITEMCHANGED: { LPNMLISTVIEW listview = (LPNMLISTVIEW)lParam; INT index; INT lvItemIndex; INT count; index = listview->iItem; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); count = ListView_GetItemCount(context->ListViewHandle); if (count == 0 || index == -1 || lvItemIndex == -1) { Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); break; } if (index != lvItemIndex) break; if (index == 0 && count == 1) { // First and last item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == (count - 1)) { // Last item Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == 0) { // First item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, TRUE); } else { Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, TRUE); } Button_Enable(context->RenameButtonHandle, TRUE); Button_Enable(context->RemoveButtonHandle, TRUE); } break; case LVN_BEGINLABELEDIT: context->LabelEditActive = TRUE; break; case LVN_ENDLABELEDIT: { LV_DISPINFO* lvinfo = (LV_DISPINFO*)lParam; if (lvinfo->item.iItem != -1 && lvinfo->item.pszText) { BOOLEAN found = FALSE; PPH_COLUMN_SET_ENTRY entry; ULONG index; for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { entry = context->ColumnSetList->Items[i]; if (PhEqualStringRef2(&entry->Name->sr, lvinfo->item.pszText, FALSE)) { found = TRUE; break; } } if (!found && PhGetListViewItemParam(context->ListViewHandle, lvinfo->item.iItem, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhMoveReference(&entry->Name, PhCreateString(lvinfo->item.pszText)); ListView_SetItemText(context->ListViewHandle, lvinfo->item.iItem, 0, lvinfo->item.pszText); } } } context->LabelEditActive = FALSE; } break; } } break; } return FALSE; }
LRESULT CALLBACK PhpSearchWndSubclassProc( _In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ UINT_PTR uIdSubclass, _In_ ULONG_PTR dwRefData ) { PEDIT_CONTEXT context = (PEDIT_CONTEXT)dwRefData; switch (uMsg) { case WM_NCDESTROY: { PhpSearchFreeTheme(context); if (context->WindowFont) DeleteObject(context->WindowFont); RemoveWindowSubclass(hWnd, PhpSearchWndSubclassProc, uIdSubclass); PhFree(context); } break; case WM_ERASEBKGND: return 1; case WM_NCCALCSIZE: { LPNCCALCSIZE_PARAMS ncCalcSize = (NCCALCSIZE_PARAMS*)lParam; // Let Windows handle the non-client defaults. DefSubclassProc(hWnd, uMsg, wParam, lParam); // Deflate the client area to accommodate the custom button. ncCalcSize->rgrc[0].right -= context->CXWidth; } return 0; case WM_NCPAINT: { RECT windowRect; // Let Windows handle the non-client defaults. DefSubclassProc(hWnd, uMsg, wParam, lParam); // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Adjust the coordinates (start from 0,0). OffsetRect(&windowRect, -windowRect.left, -windowRect.top); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Draw the button. PhpSearchDrawButton(context, windowRect); } return 0; case WM_NCHITTEST: { POINT windowPoint; RECT windowRect; // Get the screen coordinates of the mouse. if (!GetCursorPos(&windowPoint)) break; // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Check that the mouse is within the inserted button. if (PtInRect(&windowRect, windowPoint)) { return HTBORDER; } } break; case WM_NCLBUTTONDOWN: { POINT windowPoint; RECT windowRect; // Get the screen coordinates of the mouse. if (!GetCursorPos(&windowPoint)) break; // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Check that the mouse is within the inserted button. if (PtInRect(&windowRect, windowPoint)) { context->Pushed = TRUE; SetCapture(hWnd); RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } } break; case WM_LBUTTONUP: { POINT windowPoint; RECT windowRect; // Get the screen coordinates of the mouse. if (!GetCursorPos(&windowPoint)) break; // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Check that the mouse is within the inserted button. if (PtInRect(&windowRect, windowPoint)) { // Forward click notification. //SendMessage(GetParent(context->WindowHandle), WM_COMMAND, MAKEWPARAM(context->CommandID, BN_CLICKED), 0); SetFocus(hWnd); Static_SetText(hWnd, L""); } if (GetCapture() == hWnd) { context->Pushed = FALSE; ReleaseCapture(); } RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } break; case WM_CUT: case WM_CLEAR: case WM_PASTE: case WM_UNDO: case WM_KEYUP: case WM_SETTEXT: case WM_KILLFOCUS: RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); break; case WM_SETTINGCHANGE: case WM_SYSCOLORCHANGE: case WM_THEMECHANGED: { PhpSearchFreeTheme(context); PhpSearchInitializeTheme(context); PhpSearchInitializeFont(context); // Reset the client area margins. SendMessage(hWnd, EM_SETMARGINS, EC_LEFTMARGIN, MAKELPARAM(0, 0)); // Refresh the non-client area. SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); // Force the edit control to update its non-client area. RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } break; case WM_NCMOUSEMOVE: { POINT windowPoint; RECT windowRect; // Get the screen coordinates of the mouse. if (!GetCursorPos(&windowPoint)) break; // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Check that the mouse is within the inserted button. if (PtInRect(&windowRect, windowPoint) && !context->Hot) { TRACKMOUSEEVENT trackMouseEvent; trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); trackMouseEvent.dwFlags = TME_LEAVE | TME_NONCLIENT; trackMouseEvent.hwndTrack = hWnd; trackMouseEvent.dwHoverTime = 0; context->Hot = TRUE; RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); TrackMouseEvent(&trackMouseEvent); } } break; case WM_NCMOUSELEAVE: { if (context->Hot) { context->Hot = FALSE; RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } } break; case WM_MOUSEMOVE: { if ((wParam & MK_LBUTTON) && GetCapture() == hWnd) { POINT windowPoint; RECT windowRect; // Get the screen coordinates of the mouse. if (!GetCursorPos(&windowPoint)) break; // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); // Check that the mouse is within the inserted button. context->Pushed = PtInRect(&windowRect, windowPoint); RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } } break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
VOID PhLoadSymbolsThreadProvider( _In_ PPH_THREAD_PROVIDER ThreadProvider ) { PH_THREAD_SYMBOL_LOAD_CONTEXT loadContext; ULONG64 runId; loadContext.ThreadProvider = ThreadProvider; loadContext.SymbolProvider = ThreadProvider->SymbolProvider; PhAcquireQueuedLockExclusive(&ThreadProvider->LoadSymbolsLock); runId = ThreadProvider->RunId; PhLoadSymbolProviderOptions(ThreadProvider->SymbolProvider); if (ThreadProvider->ProcessId != SYSTEM_IDLE_PROCESS_ID) { if (ThreadProvider->SymbolProvider->IsRealHandle || ThreadProvider->ProcessId == SYSTEM_PROCESS_ID) { loadContext.ProcessId = ThreadProvider->ProcessId; PhEnumGenericModules( ThreadProvider->ProcessId, ThreadProvider->SymbolProvider->ProcessHandle, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } else { // We can't enumerate the process modules. Load // symbols for ntdll.dll and kernel32.dll. loadContext.ProcessId = NtCurrentProcessId(); PhEnumGenericModules( NtCurrentProcessId(), NtCurrentProcess(), 0, LoadBasicSymbolsEnumGenericModulesCallback, &loadContext ); } // Load kernel module symbols as well. if (ThreadProvider->ProcessId != SYSTEM_PROCESS_ID) { loadContext.ProcessId = SYSTEM_PROCESS_ID; PhEnumGenericModules( SYSTEM_PROCESS_ID, NULL, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } } else { // System Idle Process has one thread for each CPU, // each having a start address at KiIdleLoop. We // need to load symbols for the kernel. PRTL_PROCESS_MODULES kernelModules; if (NT_SUCCESS(PhEnumKernelModules(&kernelModules))) { if (kernelModules->NumberOfModules > 0) { PPH_STRING fileName; PPH_STRING newFileName; fileName = PhConvertMultiByteToUtf16(kernelModules->Modules[0].FullPathName); newFileName = PhGetFileName(fileName); PhDereferenceObject(fileName); PhLoadModuleSymbolProvider( ThreadProvider->SymbolProvider, newFileName->Buffer, (ULONG64)kernelModules->Modules[0].ImageBase, kernelModules->Modules[0].ImageSize ); PhDereferenceObject(newFileName); } PhFree(kernelModules); } } ThreadProvider->SymbolsLoadedRunId = runId; PhReleaseQueuedLockExclusive(&ThreadProvider->LoadSymbolsLock); }
INT_PTR CALLBACK DotNetAsmPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PASMPAGE_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { ULONG result = 0; PPH_STRING settings; LARGE_INTEGER timeout; HWND tnHandle; context = PhAllocate(sizeof(ASMPAGE_CONTEXT)); memset(context, 0, sizeof(ASMPAGE_CONTEXT)); propPageContext->Context = context; context->WindowHandle = hwndDlg; context->ProcessItem = processItem; context->ClrVersions = 0; PhGetProcessIsDotNetEx(processItem->ProcessId, NULL, 0, NULL, &context->ClrVersions); context->NodeList = PhCreateList(64); context->NodeRootList = PhCreateList(2); tnHandle = GetDlgItem(hwndDlg, IDC_LIST); context->TnHandle = tnHandle; TreeNew_SetRedraw(tnHandle, FALSE); TreeNew_SetCallback(tnHandle, DotNetAsmTreeNewCallback, context); TreeNew_SetExtendedFlags(tnHandle, TN_FLAG_ITEM_DRAG_SELECT, TN_FLAG_ITEM_DRAG_SELECT); PhSetControlTheme(tnHandle, L"explorer"); SendMessage(TreeNew_GetTooltips(tnHandle), TTM_SETMAXTIPWIDTH, 0, MAXSHORT); PhAddTreeNewColumn(tnHandle, DNATNC_STRUCTURE, TRUE, L"Structure", 240, PH_ALIGN_LEFT, -2, 0); PhAddTreeNewColumn(tnHandle, DNATNC_ID, TRUE, L"ID", 50, PH_ALIGN_RIGHT, 0, DT_RIGHT); PhAddTreeNewColumn(tnHandle, DNATNC_FLAGS, TRUE, L"Flags", 120, PH_ALIGN_LEFT, 1, 0); PhAddTreeNewColumn(tnHandle, DNATNC_PATH, TRUE, L"Path", 600, PH_ALIGN_LEFT, 2, 0); // don't use path ellipsis - the user already has the base file name PhAddTreeNewColumn(tnHandle, DNATNC_NATIVEPATH, TRUE, L"Native Image Path", 600, PH_ALIGN_LEFT, 3, 0); settings = PhGetStringSetting(SETTING_NAME_ASM_TREE_LIST_COLUMNS); PhCmLoadSettings(tnHandle, &settings->sr); PhDereferenceObject(settings); SetCursor(LoadCursor(NULL, IDC_WAIT)); if ( !IsProcessSuspended(processItem->ProcessId) || PhShowMessage(hwndDlg, MB_ICONWARNING | MB_YESNO, L".NET assembly enumeration may not work properly because the process is currently suspended. Do you want to continue?") == IDYES ) { BOOLEAN timeoutReached = FALSE; BOOLEAN nonClrNode = FALSE; ULONG i; if (context->ClrVersions & PH_CLR_VERSION_1_0) { AddFakeClrNode(context, L"CLR v1.0.3705"); // what PE displays } if (context->ClrVersions & PH_CLR_VERSION_1_1) { AddFakeClrNode(context, L"CLR v1.1.4322"); } timeout.QuadPart = -10 * PH_TIMEOUT_SEC; if (context->ClrVersions & PH_CLR_VERSION_2_0) { context->ClrV2Node = AddFakeClrNode(context, L"CLR v2.0.50727"); result = UpdateDotNetTraceInfoWithTimeout(context, TRUE, &timeout); if (result == ERROR_TIMEOUT) { timeoutReached = TRUE; result = ERROR_SUCCESS; } } if (context->ClrVersions & PH_CLR_VERSION_4_ABOVE) { result = UpdateDotNetTraceInfoWithTimeout(context, FALSE, &timeout); if (result == ERROR_TIMEOUT) { timeoutReached = TRUE; result = ERROR_SUCCESS; } } TreeNew_NodesStructured(tnHandle); // If we reached the timeout, check whether we got any data back. if (timeoutReached) { for (i = 0; i < context->NodeList->Count; i++) { PDNA_NODE node = context->NodeList->Items[i]; if (node->Type != DNA_TYPE_CLR) { nonClrNode = TRUE; break; } } if (!nonClrNode) result = ERROR_TIMEOUT; } } else { result = ERROR_INSTALL_SUSPEND; } TreeNew_SetRedraw(tnHandle, TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (result != 0) { ShowWindow(tnHandle, SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_ERROR), SW_SHOW); if (result == ERROR_ACCESS_DENIED) { SetDlgItemText(hwndDlg, IDC_ERROR, L"Unable to start the event tracing session. Make sure Process Hacker is running with administrative privileges."); } else if (result == ERROR_INSTALL_SUSPEND) { SetDlgItemText(hwndDlg, IDC_ERROR, L"Unable to start the event tracing session because the process is suspended."); } else if (result == ERROR_TIMEOUT) { SetDlgItemText(hwndDlg, IDC_ERROR, L"The event tracing session timed out."); } else { SetDlgItemText(hwndDlg, IDC_ERROR, PhaConcatStrings2(L"Unable to start the event tracing session: %s", PhGetStringOrDefault(PhGetWin32Message(result), L"Unknown error"))->Buffer); } } } break; case WM_DESTROY: { PPH_STRING settings; ULONG i; settings = PhCmSaveSettings(context->TnHandle); PhSetStringSetting2(SETTING_NAME_ASM_TREE_LIST_COLUMNS, &settings->sr); PhDereferenceObject(settings); for (i = 0; i < context->NodeList->Count; i++) DestroyNode(context->NodeList->Items[i]); PhDereferenceObject(context->NodeList); PhDereferenceObject(context->NodeRootList); PhFree(context); PhPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { PPH_LAYOUT_ITEM dialogItem; if (dialogItem = PhBeginPropPageLayout(hwndDlg, propPageContext)) { PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_ERROR), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE); PhEndPropPageLayout(hwndDlg, propPageContext); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_COPY: { PPH_STRING text; text = PhGetTreeNewText(context->TnHandle, 0); PhSetClipboardString(context->TnHandle, &text->sr); PhDereferenceObject(text); } break; } } break; } return FALSE; }
INT_PTR CALLBACK PhpMemoryResultsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_RESULTS_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_RESULTS_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhRegisterDialog(hwndDlg); { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"Results - %s (%u)", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId))->Buffer); PhDereferenceObject(processItem); } } lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 120, L"Address"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Length"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Result"); PhLoadListViewColumnsFromSetting(L"MemResultsListViewColumns", lvHandle); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 250; rect.bottom = 180; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } ListView_SetItemCount(lvHandle, context->Results->Count); SetDlgItemText(hwndDlg, IDC_INTRO, PhaFormatString(L"%s results.", PhaFormatUInt64(context->Results->Count, TRUE)->Buffer)->Buffer); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemResultsPosition"); windowRectangle.Size = PhGetIntegerPairSetting(L"MemResultsSize"); PhAdjustRectangleToWorkingArea(hwndDlg, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemResultsPosition", windowRectangle.Position); PhSetIntegerPairSetting(L"MemResultsSize", windowRectangle.Size); } } break; case WM_DESTROY: { PhSaveWindowPlacementToSetting(L"MemResultsPosition", L"MemResultsSize", hwndDlg); PhSaveListViewColumnsToSetting(L"MemResultsListViewColumns", GetDlgItem(hwndDlg, IDC_LIST)); PhDeleteLayoutManager(&context->LayoutManager); PhUnregisterDialog(hwndDlg); RemoveProp(hwndDlg, PhMakeContextAtom()); PhDereferenceMemoryResults((PPH_MEMORY_RESULT *)context->Results->Items, context->Results->Count); PhDereferenceObject(context->Results); PhFree(context); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_COPY: { HWND lvHandle; PPH_STRING string; ULONG selectedCount; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); selectedCount = ListView_GetSelectedCount(lvHandle); if (selectedCount == 0) { // User didn't select anything, so copy all items. string = PhpGetStringForSelectedResults(lvHandle, context->Results, TRUE); PhSetStateAllListViewItems(lvHandle, LVIS_SELECTED, LVIS_SELECTED); } else { string = PhpGetStringForSelectedResults(lvHandle, context->Results, FALSE); } PhSetClipboardString(hwndDlg, &string->sr); PhDereferenceObject(string); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)lvHandle, 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"Search Results.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; PPH_STRING string; fileName = PhGetFileDialogFileName(fileDialog); PhAutoDereferenceObject(fileName); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhWritePhTextHeader(fileStream); string = PhpGetStringForSelectedResults(GetDlgItem(hwndDlg, IDC_LIST), context->Results, TRUE); PhWriteStringAsUtf8FileStreamEx(fileStream, string->Buffer, string->Length); PhDereferenceObject(string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_FILTER: { PPH_EMENU menu; RECT buttonRect; POINT point; PPH_EMENU_ITEM selectedItem; ULONG filterType = 0; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_MEMFILTER), 0); GetClientRect(GetDlgItem(hwndDlg, IDC_FILTER), &buttonRect); point.x = 0; point.y = buttonRect.bottom; ClientToScreen(GetDlgItem(hwndDlg, IDC_FILTER), &point); selectedItem = PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y); if (selectedItem) { switch (selectedItem->Id) { case ID_FILTER_CONTAINS: filterType = FILTER_CONTAINS; break; case ID_FILTER_CONTAINS_CASEINSENSITIVE: filterType = FILTER_CONTAINS_IGNORECASE; break; case ID_FILTER_REGEX: filterType = FILTER_REGEX; break; case ID_FILTER_REGEX_CASEINSENSITIVE: filterType = FILTER_REGEX_IGNORECASE; break; } } if (filterType != 0) FilterResults(hwndDlg, context, filterType); PhDestroyEMenu(menu); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhHandleListViewNotifyForCopy(lParam, lvHandle); switch (header->code) { case LVN_GETDISPINFO: { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)header; if (dispInfo->item.mask & LVIF_TEXT) { PPH_MEMORY_RESULT result = context->Results->Items[dispInfo->item.iItem]; switch (dispInfo->item.iSubItem) { case 0: { WCHAR addressString[PH_PTR_STR_LEN_1]; PhPrintPointer(addressString, result->Address); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, addressString, _TRUNCATE ); } break; case 1: { WCHAR lengthString[PH_INT32_STR_LEN_1]; PhPrintUInt32(lengthString, (ULONG)result->Length); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, lengthString, _TRUNCATE ); } break; case 2: wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, result->Display.Buffer, _TRUNCATE ); break; } } } break; case NM_DBLCLK: { if (header->hwndFrom == lvHandle) { INT index; if ((index = ListView_GetNextItem( lvHandle, -1, LVNI_SELECTED )) != -1) { NTSTATUS status; PPH_MEMORY_RESULT result = context->Results->Items[index]; HANDLE processHandle; MEMORY_BASIC_INFORMATION basicInfo; PPH_SHOWMEMORYEDITOR showMemoryEditor; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, context->ProcessId ))) { if (NT_SUCCESS(status = NtQueryVirtualMemory( processHandle, result->Address, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = context->ProcessId; showMemoryEditor->BaseAddress = basicInfo.BaseAddress; showMemoryEditor->RegionSize = basicInfo.RegionSize; showMemoryEditor->SelectOffset = (ULONG)((ULONG_PTR)result->Address - (ULONG_PTR)basicInfo.BaseAddress); showMemoryEditor->SelectLength = (ULONG)result->Length; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } NtClose(processHandle); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to edit memory", status, 0); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
int __cdecl main(int argc, char *argv[]) { static PH_COMMAND_LINE_OPTION options[] = { { FI_ARG_HELP, L"h", NoArgumentType }, { FI_ARG_ACTION, L"a", MandatoryArgumentType }, { FI_ARG_NATIVE, L"N", NoArgumentType }, { FI_ARG_PATTERN, L"p", MandatoryArgumentType }, { FI_ARG_CASESENSITIVE, L"C", NoArgumentType }, { FI_ARG_OUTPUT, L"o", MandatoryArgumentType }, { FI_ARG_FORCE, L"f", NoArgumentType }, { FI_ARG_LENGTH, L"L", MandatoryArgumentType } }; PH_STRINGREF commandLine; NTSTATUS status = STATUS_SUCCESS; if (!NT_SUCCESS(PhInitializePhLibEx(0, 0, 0))) return 1; PhUnicodeStringToStringRef(&NtCurrentPeb()->ProcessParameters->CommandLine, &commandLine); if (!PhParseCommandLine( &commandLine, options, sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION), PH_COMMAND_LINE_IGNORE_FIRST_PART, FiCommandLineCallback, NULL ) || FiArgHelp) { FiPrintHelp(); return 0; } if (!FiArgFileName && ( FiArgAction && PhEqualString2(FiArgAction, L"dir", TRUE) )) { FiArgFileName = PhCreateStringFromUnicodeString(&NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath); } if (!FiArgAction) { FiPrintHelp(); return 1; } else if (PhEqualString2(FiArgAction, L"map", TRUE)) { WCHAR deviceNameBuffer[7] = L"\\??\\ :"; ULONG i; WCHAR targetNameBuffer[0x100]; UNICODE_STRING targetName; targetName.Buffer = targetNameBuffer; targetName.MaximumLength = sizeof(targetNameBuffer); for (i = 0; i < 26; i++) { HANDLE linkHandle; OBJECT_ATTRIBUTES oa; UNICODE_STRING deviceName; deviceNameBuffer[4] = (WCHAR)('A' + i); deviceName.Buffer = deviceNameBuffer; deviceName.Length = 6 * sizeof(WCHAR); InitializeObjectAttributes( &oa, &deviceName, OBJ_CASE_INSENSITIVE, NULL, NULL ); if (NT_SUCCESS(NtOpenSymbolicLinkObject( &linkHandle, SYMBOLIC_LINK_QUERY, &oa ))) { if (NT_SUCCESS(NtQuerySymbolicLinkObject( linkHandle, &targetName, NULL ))) { wprintf(L"%c: %.*s\n", 'A' + i, targetName.Length / 2, targetName.Buffer); } NtClose(linkHandle); } } } else if (!FiArgFileName) { wprintf(L"Error: file name missing.\n"); FiPrintHelp(); return 1; } else if (PhEqualString2(FiArgAction, L"hash", TRUE)) { HANDLE fileHandle; LARGE_INTEGER fileSize; IO_STATUS_BLOCK isb; ULONG mode; if (!FiArgOutput) mode = HASH_MD5; else if (PhEqualString2(FiArgOutput, L"md5", TRUE)) mode = HASH_MD5; else if (PhEqualString2(FiArgOutput, L"sha1", TRUE)) mode = HASH_SHA1; else if (PhEqualString2(FiArgOutput, L"crc32", TRUE)) mode = HASH_CRC32; else { wprintf(L"Invalid hash algorithm. Possibilities: md5, sha1, crc32\n"); return 1; } if (FiCreateFile( &fileHandle, FILE_GENERIC_READ, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY )) { if (NT_SUCCESS(status = PhGetFileSize(fileHandle, &fileSize))) { MD5_CTX md5Context; A_SHA_CTX shaContext; ULONG crc; UCHAR buffer[PAGE_SIZE * 4]; ULONG64 bytesRemaining; bytesRemaining = fileSize.QuadPart; switch (mode) { case HASH_MD5: MD5Init(&md5Context); break; case HASH_SHA1: A_SHAInit(&shaContext); break; case HASH_CRC32: crc = 0; break; } while (bytesRemaining) { status = NtReadFile( fileHandle, NULL, NULL, NULL, &isb, buffer, sizeof(buffer), NULL, NULL ); if (!NT_SUCCESS(status)) break; switch (mode) { case HASH_MD5: MD5Update(&md5Context, buffer, (ULONG)isb.Information); break; case HASH_SHA1: A_SHAUpdate(&shaContext, buffer, (ULONG)isb.Information); break; case HASH_CRC32: crc = PhCrc32(crc, buffer, isb.Information); break; } bytesRemaining -= (ULONG)isb.Information; } if (status == STATUS_END_OF_FILE) status = STATUS_SUCCESS; switch (mode) { case HASH_MD5: { MD5Final(&md5Context); wprintf(L"%s", PhBufferToHexString(md5Context.digest, 16)->Buffer); } break; case HASH_SHA1: { UCHAR hash[20]; A_SHAFinal(&shaContext, hash); wprintf(L"%s", PhBufferToHexString(hash, 20)->Buffer); } break; case HASH_CRC32: { wprintf(L"%08x", crc); } break; } if (!NT_SUCCESS(status)) wprintf(L"Warning: I/O error encountered: %s\n", PhGetNtMessage(status)->Buffer); } NtClose(fileHandle); } if (!NT_SUCCESS(status)) { wprintf(L"Error: %s\n", PhGetNtMessage(status)->Buffer); return 1; } } else if (PhEqualString2(FiArgAction, L"execute", TRUE)) { if (FiArgNative) { if (!NT_SUCCESS(status = PhCreateProcess( FiFormatFileName(FiArgFileName)->Buffer, FiArgOutput ? &FiArgOutput->sr : NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL ))) { wprintf(L"Error: %s\n", PhGetNtMessage(status)->Buffer); return 1; } } else { if (!NT_SUCCESS(status = PhCreateProcessWin32( FiArgFileName->Buffer, PhGetString(FiArgOutput), NULL, NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath.Buffer, PH_CREATE_PROCESS_NEW_CONSOLE, NULL, NULL, NULL ))) { wprintf(L"Error: %s\n", PhGetNtMessage(status)->Buffer); return 1; } } } else if (PhEqualString2(FiArgAction, L"del", TRUE)) { HANDLE fileHandle; if (FiCreateFile( &fileHandle, DELETE | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT )) { FILE_DISPOSITION_INFORMATION dispositionInfo; IO_STATUS_BLOCK isb; dispositionInfo.DeleteFile = TRUE; if (!NT_SUCCESS(status = NtSetInformationFile(fileHandle, &isb, &dispositionInfo, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation))) { wprintf(L"Error deleting file: %s\n", PhGetNtMessage(status)->Buffer); } NtClose(fileHandle); } } else if (PhEqualString2(FiArgAction, L"touch", TRUE)) { HANDLE fileHandle; if (FiCreateFile( &fileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) { NtClose(fileHandle); } } else if (PhEqualString2(FiArgAction, L"mkdir", TRUE)) { HANDLE fileHandle; if (FiCreateFile( &fileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FiArgFileName, FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) { NtClose(fileHandle); } } else if (PhEqualString2(FiArgAction, L"rename", TRUE)) { HANDLE fileHandle; PPH_STRING newFileName; if (!FiArgOutput) { wprintf(L"Error: new file name missing.\n"); FiPrintHelp(); return 1; } newFileName = FiFormatFileName(FiArgOutput); if (FiCreateFile( &fileHandle, DELETE | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) { PFILE_RENAME_INFORMATION renameInfo; ULONG renameInfoSize; IO_STATUS_BLOCK isb; renameInfoSize = FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName) + (ULONG)newFileName->Length; renameInfo = PhAllocate(renameInfoSize); renameInfo->ReplaceIfExists = FiArgForce; renameInfo->RootDirectory = NULL; renameInfo->FileNameLength = (ULONG)newFileName->Length; memcpy(renameInfo->FileName, newFileName->Buffer, newFileName->Length); status = NtSetInformationFile(fileHandle, &isb, renameInfo, renameInfoSize, FileRenameInformation); PhFree(renameInfo); if (!NT_SUCCESS(status)) { wprintf(L"Error renaming file: %s\n", PhGetNtMessage(status)->Buffer); } NtClose(fileHandle); } } else if (PhEqualString2(FiArgAction, L"copy", TRUE)) { HANDLE fileHandle; HANDLE outFileHandle; LARGE_INTEGER fileSize; FILE_BASIC_INFORMATION basicInfo; if (!FiArgOutput) { wprintf(L"Error: output file name missing.\n"); FiPrintHelp(); return 1; } if (FiCreateFile( &fileHandle, FILE_READ_ATTRIBUTES | FILE_READ_DATA | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT ) && FiCreateFile( &outFileHandle, FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | SYNCHRONIZE, FiArgOutput, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, !FiArgForce ? FILE_CREATE : FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT )) { #define COPY_BUFFER_SIZE 0x10000 IO_STATUS_BLOCK isb; PVOID buffer; ULONG64 bytesToCopy = FiArgLength; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize))) { PhSetFileSize(outFileHandle, &fileSize); } buffer = PhAllocatePage(COPY_BUFFER_SIZE, NULL); if (!buffer) { wprintf(L"Error allocating buffer.\n"); return 1; } while (bytesToCopy) { status = NtReadFile( fileHandle, NULL, NULL, NULL, &isb, buffer, bytesToCopy >= COPY_BUFFER_SIZE ? COPY_BUFFER_SIZE : (ULONG)bytesToCopy, NULL, NULL ); if (status == STATUS_END_OF_FILE) { break; } else if (!NT_SUCCESS(status)) { wprintf(L"Error reading from file: %s\n", PhGetNtMessage(status)->Buffer); break; } status = NtWriteFile( outFileHandle, NULL, NULL, NULL, &isb, buffer, (ULONG)isb.Information, // number of bytes read NULL, NULL ); if (!NT_SUCCESS(status)) { wprintf(L"Error writing to output file: %s\n", PhGetNtMessage(status)->Buffer); break; } bytesToCopy -= (ULONG)isb.Information; } PhFreePage(buffer); // Copy basic attributes over. if (NT_SUCCESS(NtQueryInformationFile( fileHandle, &isb, &basicInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation ))) { NtSetInformationFile( outFileHandle, &isb, &basicInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation ); } NtClose(fileHandle); NtClose(outFileHandle); } } else if (PhEqualString2(FiArgAction, L"dir", TRUE)) { HANDLE fileHandle; UNICODE_STRING pattern; PPH_STRING totalSize, totalAllocSize; if (FiCreateFile( &fileHandle, FILE_LIST_DIRECTORY | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) { FipDirFileCount = 0; FipDirDirCount = 0; FipDirTotalSize = 0; FipDirTotalAllocSize = 0; if (FiArgPattern) PhStringRefToUnicodeString(&FiArgPattern->sr, &pattern); PhEnumDirectoryFile( fileHandle, FiArgPattern ? &pattern : NULL, FipEnumDirectoryFileForDir, NULL ); NtClose(fileHandle); totalSize = PhFormatUInt64(FipDirTotalSize, TRUE); totalAllocSize = PhFormatUInt64(FipDirTotalAllocSize, TRUE); wprintf( L"%12I64u file(s) %11s bytes\n" L"%12I64u dir(s) %11s bytes allocated\n", FipDirFileCount, totalSize->Buffer, FipDirDirCount, totalAllocSize->Buffer ); PhDereferenceObject(totalSize); PhDereferenceObject(totalAllocSize); } } else if (PhEqualString2(FiArgAction, L"streams", TRUE)) { HANDLE fileHandle; PVOID streams; PFILE_STREAM_INFORMATION stream; if (FiCreateFile( &fileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FiArgFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) { if (NT_SUCCESS(PhEnumFileStreams(fileHandle, &streams))) { stream = PH_FIRST_STREAM(streams); while (stream) { PPH_STRING size, allocationSize; size = PhFormatUInt64(stream->StreamSize.QuadPart, TRUE); allocationSize = PhFormatUInt64(stream->StreamAllocationSize.QuadPart, TRUE); wprintf( L"%11s %11s %.*s\n", size->Buffer, allocationSize->Buffer, stream->StreamNameLength / 2, stream->StreamName ); PhDereferenceObject(size); PhDereferenceObject(allocationSize); stream = PH_NEXT_STREAM(stream); } } NtClose(fileHandle); } } else { wprintf(L"Error: invalid action \"%s\".\n", FiArgAction->Buffer); FiPrintHelp(); return 1; } }
VOID ToolbarLoadButtonSettings( VOID ) { INT buttonCount; ULONG64 countInteger; PPH_STRING settingsString; PTBBUTTON buttonArray; PH_STRINGREF remaining; PH_STRINGREF part; settingsString = PhGetStringSetting(SETTING_NAME_TOOLBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } // Query the number of buttons to insert if (!PhSplitStringRefAtChar(&remaining, '|', &part, &remaining)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } if (!PhStringToInteger64(&part, 10, &countInteger)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } buttonCount = (INT)countInteger; // Allocate the button array buttonArray = PhAllocate(buttonCount * sizeof(TBBUTTON)); memset(buttonArray, 0, buttonCount * sizeof(TBBUTTON)); for (INT index = 0; index < buttonCount; index++) { ULONG64 commandInteger; PH_STRINGREF commandIdPart; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &commandIdPart, &remaining); PhStringToInteger64(&commandIdPart, 10, &commandInteger); buttonArray[index].idCommand = (INT)commandInteger; buttonArray[index].iBitmap = I_IMAGECALLBACK; buttonArray[index].fsState = TBSTATE_ENABLED; if (commandInteger) { buttonArray[index].fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE; } else { buttonArray[index].fsStyle = BTNS_SEP; } } SendMessage(ToolBarHandle, TB_ADDBUTTONS, buttonCount, (LPARAM)buttonArray); PhFree(buttonArray); PhDereferenceObject(settingsString); }
LRESULT CALLBACK PhpPropSheetWndProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PPH_PROCESS_PROPSHEETCONTEXT propSheetContext; WNDPROC oldWndProc; propSheetContext = PhGetWindowContext(hwnd, 0xF); if (!propSheetContext) return 0; oldWndProc = propSheetContext->PropSheetWindowHookProc; switch (uMsg) { case WM_DESTROY: { HWND tabControl; TCITEM tabItem; WCHAR text[128]; // Save the window position and size. PhSaveWindowPlacementToSetting(L"ProcPropPosition", L"ProcPropSize", hwnd); // Save the selected tab. tabControl = PropSheet_GetTabControl(hwnd); tabItem.mask = TCIF_TEXT; tabItem.pszText = text; tabItem.cchTextMax = RTL_NUMBER_OF(text) - 1; if (TabCtrl_GetItem(tabControl, TabCtrl_GetCurSel(tabControl), &tabItem)) { PhSetStringSetting(L"ProcPropPage", text); } } break; case WM_NCDESTROY: { PhUnregisterWindowCallback(hwnd); SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc); PhRemoveWindowContext(hwnd, 0xF); PhDeleteLayoutManager(&propSheetContext->LayoutManager); PhFree(propSheetContext); } break; case WM_SYSCOMMAND: { // Note: Clicking the X on the taskbar window thumbnail preview doens't close modeless property sheets // when there are more than 1 window and the window doesn't have focus... The MFC, ATL and WTL libraries // check if the propsheet is modeless and SendMessage WM_CLOSE and so we'll implement the same solution. (dmex) switch (wParam & 0xFFF0) { case SC_CLOSE: { PostMessage(hwnd, WM_CLOSE, 0, 0); //SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); //return TRUE; } break; } } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: // Prevent the OK button from working (even though // it's already hidden). This prevents the Enter // key from closing the dialog box. return 0; } } break; case WM_SIZE: { if (!IsMinimized(hwnd)) { PhLayoutManagerLayout(&propSheetContext->LayoutManager); } } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); }
NTSTATUS PhpThreadProviderLoadSymbols( __in PVOID Parameter ) { PPH_THREAD_PROVIDER threadProvider = (PPH_THREAD_PROVIDER)Parameter; PH_THREAD_SYMBOL_LOAD_CONTEXT loadContext; loadContext.ThreadProvider = threadProvider; loadContext.SymbolProvider = threadProvider->SymbolProvider; PhLoadSymbolProviderOptions(threadProvider->SymbolProvider); if (threadProvider->ProcessId != SYSTEM_IDLE_PROCESS_ID) { if ( threadProvider->SymbolProvider->IsRealHandle || threadProvider->ProcessId == SYSTEM_PROCESS_ID ) { loadContext.ProcessId = threadProvider->ProcessId; PhEnumGenericModules( threadProvider->ProcessId, threadProvider->SymbolProvider->ProcessHandle, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } else { // We can't enumerate the process modules. Load // symbols for ntdll.dll and kernel32.dll. loadContext.ProcessId = NtCurrentProcessId(); PhEnumGenericModules( NtCurrentProcessId(), NtCurrentProcess(), 0, LoadBasicSymbolsEnumGenericModulesCallback, &loadContext ); } // Load kernel module symbols as well. if (threadProvider->ProcessId != SYSTEM_PROCESS_ID) { loadContext.ProcessId = SYSTEM_PROCESS_ID; PhEnumGenericModules( SYSTEM_PROCESS_ID, NULL, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } } else { // System Idle Process has one thread for each CPU, // each having a start address at KiIdleLoop. We // need to load symbols for the kernel. PRTL_PROCESS_MODULES kernelModules; if (NT_SUCCESS(PhEnumKernelModules(&kernelModules))) { if (kernelModules->NumberOfModules > 0) { PPH_STRING fileName; PPH_STRING newFileName; fileName = PhCreateStringFromAnsi(kernelModules->Modules[0].FullPathName); newFileName = PhGetFileName(fileName); PhDereferenceObject(fileName); PhLoadModuleSymbolProvider( threadProvider->SymbolProvider, newFileName->Buffer, (ULONG64)kernelModules->Modules[0].ImageBase, kernelModules->Modules[0].ImageSize ); PhDereferenceObject(newFileName); } PhFree(kernelModules); } } // Check if the process has services - we'll need to know before getting service tag/name // information. if (WINDOWS_HAS_SERVICE_TAGS) { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(threadProvider->ProcessId)) { threadProvider->HasServices = processItem->ServiceList && processItem->ServiceList->Count != 0; PhDereferenceObject(processItem); } } PhSetEvent(&threadProvider->SymbolsLoadedEvent); PhDereferenceObject(threadProvider); return STATUS_SUCCESS; }
VOID PhpThreadProviderUpdate( __in PPH_THREAD_PROVIDER ThreadProvider, __in PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = (HANDLE)i; } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PPVOID)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhSwapReference2(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { ULONG64 cycles; PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhSwapReference2( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if ( threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress ) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }
static INT_PTR CALLBACK PhpThreadStackDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; PTHREAD_STACK_CONTEXT threadStackContext; PPH_STRING title; HWND lvHandle; PPH_LAYOUT_MANAGER layoutManager; threadStackContext = (PTHREAD_STACK_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)threadStackContext); title = PhFormatString(L"Stack - thread %u", HandleToUlong(threadStackContext->ThreadId)); SetWindowText(hwndDlg, title->Buffer); PhDereferenceObject(title); lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 30, L" "); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 300, L"Name"); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhLoadListViewColumnsFromSetting(L"ThreadStackListViewColumns", lvHandle); threadStackContext->ListViewHandle = lvHandle; layoutManager = PhAllocate(sizeof(PH_LAYOUT_MANAGER)); PhInitializeLayoutManager(layoutManager, hwndDlg); SetProp(hwndDlg, L"LayoutManager", (HANDLE)layoutManager); PhAddLayoutItem(layoutManager, lvHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_REFRESH), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 190; rect.bottom = 120; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } PhLoadWindowPlacementFromSetting(NULL, L"ThreadStackWindowSize", hwndDlg); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackInitializing; control.UniqueKey = threadStackContext; control.u.Initializing.ProcessId = threadStackContext->ProcessId; control.u.Initializing.ThreadId = threadStackContext->ThreadId; control.u.Initializing.ThreadHandle = threadStackContext->ThreadHandle; control.u.Initializing.SymbolProvider = threadStackContext->SymbolProvider; control.u.Initializing.CustomWalk = FALSE; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); threadStackContext->CustomWalk = control.u.Initializing.CustomWalk; } status = PhpRefreshThreadStack(hwndDlg, threadStackContext); if (status == STATUS_ABANDONED) EndDialog(hwndDlg, IDCANCEL); else if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to load the stack", status, 0); } break; case WM_DESTROY: { PPH_LAYOUT_MANAGER layoutManager; PTHREAD_STACK_CONTEXT threadStackContext; ULONG i; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhDeleteLayoutManager(layoutManager); PhFree(layoutManager); threadStackContext = (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackUninitializing; control.UniqueKey = threadStackContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } for (i = 0; i < threadStackContext->List->Count; i++) PhpFreeThreadStackItem(threadStackContext->List->Items[i]); PhSaveListViewColumnsToSetting(L"ThreadStackListViewColumns", GetDlgItem(hwndDlg, IDC_LIST)); PhSaveWindowPlacementToSetting(NULL, L"ThreadStackWindowSize", hwndDlg); RemoveProp(hwndDlg, PhMakeContextAtom()); RemoveProp(hwndDlg, L"LayoutManager"); } break; case WM_COMMAND: { INT id = LOWORD(wParam); switch (id) { case IDCANCEL: // Esc and X button to close case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_REFRESH: { NTSTATUS status; if (!NT_SUCCESS(status = PhpRefreshThreadStack( hwndDlg, (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()) ))) { PhShowStatus(hwndDlg, L"Unable to load the stack", status, 0); } } break; case IDC_COPY: { HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); if (ListView_GetSelectedCount(lvHandle) == 0) PhSetStateAllListViewItems(lvHandle, LVIS_SELECTED, LVIS_SELECTED); PhCopyListView(lvHandle); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)lvHandle, TRUE); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case LVN_GETINFOTIP: { LPNMLVGETINFOTIP getInfoTip = (LPNMLVGETINFOTIP)header; HWND lvHandle; PTHREAD_STACK_CONTEXT threadStackContext; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); threadStackContext = (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); if (header->hwndFrom == lvHandle) { PTHREAD_STACK_ITEM stackItem; PPH_THREAD_STACK_FRAME stackFrame; if (PhGetListViewItemParam(lvHandle, getInfoTip->iItem, &stackItem)) { PH_STRING_BUILDER stringBuilder; PPH_STRING fileName; PH_SYMBOL_LINE_INFORMATION lineInfo; stackFrame = &stackItem->StackFrame; PhInitializeStringBuilder(&stringBuilder, 40); PhAppendFormatStringBuilder( &stringBuilder, L"Stack: 0x%Ix, Frame: 0x%Ix\n", stackFrame->StackAddress, stackFrame->FrameAddress ); // There are no params for kernel-mode stack traces. if ((ULONG_PTR)stackFrame->PcAddress <= PhSystemBasicInformation.MaximumUserModeAddress) { PhAppendFormatStringBuilder( &stringBuilder, L"Parameters: 0x%Ix, 0x%Ix, 0x%Ix, 0x%Ix\n", stackFrame->Params[0], stackFrame->Params[1], stackFrame->Params[2], stackFrame->Params[3] ); } if (PhGetLineFromAddress( threadStackContext->SymbolProvider, (ULONG64)stackFrame->PcAddress, &fileName, NULL, &lineInfo )) { PhAppendFormatStringBuilder( &stringBuilder, L"File: %s: line %u\n", fileName->Buffer, lineInfo.LineNumber ); PhDereferenceObject(fileName); } if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackGetTooltip; control.UniqueKey = threadStackContext; control.u.GetTooltip.StackFrame = stackFrame; control.u.GetTooltip.StringBuilder = &stringBuilder; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } PhCopyListViewInfoTip(getInfoTip, &stringBuilder.String->sr); PhDeleteStringBuilder(&stringBuilder); } } } 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; }
static DWORD WINAPI SearchProcessThread(LPVOID param) { const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" }; char tmp[MAX_PATH]; NTSTATUS status = STATUS_SUCCESS; PSYSTEM_HANDLE_INFORMATION_EX handles = NULL; POBJECT_NAME_INFORMATION buffer = NULL; ULONG_PTR i; ULONG_PTR pid[2]; ULONG_PTR last_access_denied_pid = 0; ULONG bufferSize; USHORT wHandleNameLen; WCHAR *wHandleName = NULL; HANDLE dupHandle = NULL; HANDLE processHandle = NULL; BOOLEAN bFound = FALSE, bGotExePath, verbose = !_bQuiet; ULONG access_rights = 0; DWORD size; char exe_path[MAX_PATH] = { 0 }; wchar_t wexe_path[MAX_PATH]; int cur_pid; PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll); PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll); PF_INIT_OR_SET_STATUS(NtClose, NtDll); StrArrayClear(&BlockingProcess); if (NT_SUCCESS(status)) status = PhCreateHeap(); if (NT_SUCCESS(status)) status = PhEnumHandlesEx(&handles); if (!NT_SUCCESS(status)) { uprintf("Warning: Could not enumerate process handles: %s", NtStatusError(status)); goto out; } pid[0] = (ULONG_PTR)0; cur_pid = 1; wHandleName = utf8_to_wchar(_HandleName); wHandleNameLen = (USHORT)wcslen(wHandleName); bufferSize = 0x200; buffer = PhAllocate(bufferSize); if (buffer == NULL) goto out; for (i = 0; ; i++) { ULONG attempts = 8; PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = (i < handles->NumberOfHandles) ? &handles->Handles[i] : NULL; if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) { pfNtClose(dupHandle); dupHandle = NULL; } // Update the current handle's process PID and compare against last // Note: Be careful about not trying to overflow our list! pid[cur_pid] = (handleInfo != NULL) ? handleInfo->UniqueProcessId : -1; if (pid[0] != pid[1]) { cur_pid = (cur_pid + 1) % 2; // If we're switching process and found a match, print it if (bFound) { vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]); static_sprintf(tmp, "● %s (%s)", exe_path, access_rights_str[access_rights & 0x7]); StrArrayAdd(&BlockingProcess, tmp, TRUE); bFound = FALSE; access_rights = 0; } // Close the previous handle if (processHandle != NULL) { if (processHandle != NtCurrentProcess()) pfNtClose(processHandle); processHandle = NULL; } } CHECK_FOR_USER_CANCEL; // Exit loop condition if (i >= handles->NumberOfHandles) break; // Don't bother with processes we can't access if (handleInfo->UniqueProcessId == last_access_denied_pid) continue; // Filter out handles that aren't opened with Read (bit 0), Write (bit 1) or Execute (bit 5) access if ((handleInfo->GrantedAccess & 0x23) == 0) continue; // Open the process to which the handle we are after belongs, if not already opened if (pid[0] != pid[1]) { status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, (HANDLE)handleInfo->UniqueProcessId); // There exists some processes we can't access if (!NT_SUCCESS(status)) { uuprintf("SearchProcess: Could not open process %ld: %s", handleInfo->UniqueProcessId, NtStatusError(status)); processHandle = NULL; if (status == STATUS_ACCESS_DENIED) { last_access_denied_pid = handleInfo->UniqueProcessId; } continue; } } // Now duplicate this handle onto our own process, so that we can access its properties if (processHandle == NtCurrentProcess()) { if (_bIgnoreSelf) continue; dupHandle = (HANDLE)handleInfo->HandleValue; } else { status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue, NtCurrentProcess(), &dupHandle, 0, 0, 0); if (!NT_SUCCESS(status)) continue; } // Filter non-storage handles. We're not interested in them and they make NtQueryObject() freeze if (GetFileType(dupHandle) != FILE_TYPE_DISK) continue; // A loop is needed because the I/O subsystem likes to give us the wrong return lengths... do { ULONG returnSize; // TODO: We might potentially still need a timeout on ObjectName queries, as PH does... status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize); if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_BUFFER_TOO_SMALL) { uuprintf("SearchProcess: Realloc from %d to %d", bufferSize, returnSize); bufferSize = returnSize; PhFree(buffer); buffer = PhAllocate(bufferSize); } else { break; } } while (--attempts); if (!NT_SUCCESS(status)) { uuprintf("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s", handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status)); continue; } // Don't bother comparing if we are looking for full match and the length is different if ((!_bPartialMatch) && (wHandleNameLen != buffer->Name.Length)) continue; // Likewise, if we are looking for a partial match and the current length is smaller if ((_bPartialMatch) && (wHandleNameLen > buffer->Name.Length)) continue; // Match against our target string if (wcsncmp(wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0) continue; // If we are here, we have a process accessing our target! bFound = TRUE; // Keep a mask of all the access rights being used access_rights |= handleInfo->GrantedAccess; // The Executable bit is in a place we don't like => reposition it if (access_rights & 0x20) access_rights = (access_rights & 0x03) | 0x04; access_mask |= (BYTE) (access_rights & 0x7) + 0x80; // Bit 7 is always set if a process was found // If this is the very first process we find, print a header if (exe_path[0] == 0) vuprintf("WARNING: The following process(es) or service(s) are accessing %s:", _HandleName); // First, we try to get the executable path using GetModuleFileNameEx bGotExePath = (GetModuleFileNameExU(processHandle, 0, exe_path, MAX_PATH - 1) != 0); // The above may not work on Windows 7, so try QueryFullProcessImageName (Vista or later) if (!bGotExePath) { size = MAX_PATH; PF_INIT(QueryFullProcessImageNameW, kernel32); if ( (pfQueryFullProcessImageNameW != NULL) && (bGotExePath = pfQueryFullProcessImageNameW(processHandle, 0, wexe_path, &size)) ) wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path)); } // Still nothing? Try GetProcessImageFileName. Note that GetProcessImageFileName uses // '\Device\Harddisk#\Partition#\' instead drive letters if (!bGotExePath) { bGotExePath = (GetProcessImageFileNameW(processHandle, wexe_path, MAX_PATH) != 0); if (bGotExePath) wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path)); } // Complete failure => Just craft a default process name that includes the PID if (!bGotExePath) { safe_sprintf(exe_path, MAX_PATH, "Unknown_Process_%" PRIu64, (ULONGLONG)handleInfo->UniqueProcessId); } } out: if (exe_path[0] != 0) vuprintf("You should close these applications before attempting to reformat the drive."); else vuprintf("NOTE: Could not identify the process(es) or service(s) accessing %s", _HandleName); free(wHandleName); PhFree(buffer); PhFree(handles); PhDestroyHeap(); ExitThread(0); }
static INT_PTR CALLBACK NetworkPingWndProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PNETWORK_OUTPUT_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PNETWORK_OUTPUT_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context"); } if (context == NULL) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PH_RECTANGLE windowRectangle; PPH_LAYOUT_ITEM panelItem; // We have already set the group boxes to have WS_EX_TRANSPARENT to fix // the drawing issue that arises when using WS_CLIPCHILDREN. However // in removing the flicker from the graphs the group boxes will now flicker. // It's a good tradeoff since no one stares at the group boxes. PhSetWindowStyle(hwndDlg, WS_CLIPCHILDREN, WS_CLIPCHILDREN); context->WindowHandle = hwndDlg; context->ParentHandle = GetParent(hwndDlg); context->StatusHandle = GetDlgItem(hwndDlg, IDC_MAINTEXT); context->MaxPingTimeout = PhGetIntegerSetting(SETTING_NAME_PING_TIMEOUT); windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_PING_WINDOW_POSITION); windowRectangle.Size = PhGetIntegerPairSetting(SETTING_NAME_PING_WINDOW_SIZE); // Create the font handle. context->FontHandle = InitializeFont(context->StatusHandle); // Create the graph control. context->PingGraphHandle = CreateWindow( PH_GRAPH_CLASSNAME, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); Graph_SetTooltip(context->PingGraphHandle, TRUE); // Load the Process Hacker icon. context->IconHandle = (HICON)LoadImage( NtCurrentPeb()->ImageBaseAddress, MAKEINTRESOURCE(PHAPP_IDI_PROCESSHACKER), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED ); // Set window icon. if (context->IconHandle) SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)context->IconHandle); // Initialize the WorkQueue with a maximum of 20 threads (fix pinging slow-links with a high interval update). PhInitializeWorkQueue(&context->PingWorkQueue, 0, 20, 5000); PhInitializeGraphState(&context->PingGraphState); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhInitializeCircularBuffer_ULONG(&context->PingHistory, PhGetIntegerSetting(L"SampleCount")); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_PANEL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_AVG), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MIN), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MAX), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_SENT), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_LOST), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BAD_HASH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ANON_ADDR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); panelItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PING_LAYOUT), NULL, PH_ANCHOR_ALL); PhAddLayoutItemEx(&context->LayoutManager, context->PingGraphHandle, NULL, PH_ANCHOR_ALL, panelItem->Margin); // Load window settings. if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0) PhCenterWindow(hwndDlg, GetParent(hwndDlg)); else { PhLoadWindowPlacementFromSetting(SETTING_NAME_PING_WINDOW_POSITION, SETTING_NAME_PING_WINDOW_SIZE, hwndDlg); } // Initialize window layout. PhLayoutManagerLayout(&context->LayoutManager); // Convert IP Address to string format. if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE) { RtlIpv4AddressToString(&context->IpAddress.InAddr, context->IpAddressString); } else { RtlIpv6AddressToString(&context->IpAddress.In6Addr, context->IpAddressString); } SetWindowText(hwndDlg, PhaFormatString(L"Ping %s", context->IpAddressString)->Buffer); SetWindowText(context->StatusHandle, PhaFormatString(L"Pinging %s with 32 bytes of data:", context->IpAddressString)->Buffer); PhRegisterCallback( PhGetGeneralCallback(GeneralCallbackProcessesUpdated), NetworkPingUpdateHandler, context, &context->ProcessesUpdatedRegistration ); } return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: PostQuitMessage(0); break; } } break; case WM_DESTROY: { PhUnregisterCallback( PhGetGeneralCallback(GeneralCallbackProcessesUpdated), &context->ProcessesUpdatedRegistration ); PhSaveWindowPlacementToSetting( SETTING_NAME_PING_WINDOW_POSITION, SETTING_NAME_PING_WINDOW_SIZE, hwndDlg ); if (context->PingGraphHandle) DestroyWindow(context->PingGraphHandle); if (context->IconHandle) DestroyIcon(context->IconHandle); if (context->FontHandle) DeleteObject(context->FontHandle); PhDeleteWorkQueue(&context->PingWorkQueue); PhDeleteGraphState(&context->PingGraphState); PhDeleteLayoutManager(&context->LayoutManager); RemoveProp(hwndDlg, L"Context"); PhFree(context); } break; case WM_SIZE: PhLayoutManagerLayout(&context->LayoutManager); break; case WM_SIZING: PhResizingMinimumSize((PRECT)lParam, wParam, 420, 250); break; case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: { HDC hDC = (HDC)wParam; HWND hwndChild = (HWND)lParam; // Check for our static label and change the color. if (GetDlgCtrlID(hwndChild) == IDC_MAINTEXT) { SetTextColor(hDC, RGB(19, 112, 171)); } // Set a transparent background for the control backcolor. SetBkMode(hDC, TRANSPARENT); // set window background color. return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); } break; case WM_PING_UPDATE: { ULONG i = 0; ULONG maxGraphHeight = 0; ULONG pingAvgValue = 0; PhNetworkPingUpdateGraph(context); for (i = 0; i < context->PingHistory.Count; i++) { maxGraphHeight = maxGraphHeight + PhGetItemCircularBuffer_ULONG(&context->PingHistory, i); pingAvgValue = maxGraphHeight / context->PingHistory.Count; } SetDlgItemText(hwndDlg, IDC_ICMP_AVG, PhaFormatString( L"Average: %lums", pingAvgValue)->Buffer); SetDlgItemText(hwndDlg, IDC_ICMP_MIN, PhaFormatString( L"Minimum: %lums", context->PingMinMs)->Buffer); SetDlgItemText(hwndDlg, IDC_ICMP_MAX, PhaFormatString( L"Maximum: %lums", context->PingMaxMs)->Buffer); SetDlgItemText(hwndDlg, IDC_PINGS_SENT, PhaFormatString( L"Pings Sent: %lu", context->PingSentCount)->Buffer); SetDlgItemText(hwndDlg, IDC_PINGS_LOST, PhaFormatString( L"Pings Lost: %lu (%.0f%%)", context->PingLossCount, ((FLOAT)context->PingLossCount / context->PingSentCount * 100) )->Buffer); SetDlgItemText(hwndDlg, IDC_BAD_HASH, PhaFormatString( L"Bad Hashes: %lu", context->HashFailCount)->Buffer); SetDlgItemText(hwndDlg, IDC_ANON_ADDR, PhaFormatString( L"Anon Replies: %lu", context->UnknownAddrCount)->Buffer); } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), PhGetIntegerSetting(L"ColorCpuUser")); if (header->hwndFrom == context->PingGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc = Graph_GetBufferedContext(context->PingGraphHandle); PhMoveReference(&context->PingGraphState.Text, PhFormatString(L"Ping: %lums", context->CurrentPingMs) ); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->PingGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } PhGraphStateGetDrawInfo( &context->PingGraphState, getDrawInfo, context->PingHistory.Count ); if (!context->PingGraphState.Valid) { ULONG i; FLOAT max = 0; for (i = 0; i < drawInfo->LineDataCount; i++) { FLOAT data1; context->PingGraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->PingHistory, i); if (max < data1) max = data1; } // Minimum scaling of timeout (1000ms default). if (max < (FLOAT)context->MaxPingTimeout) max = (FLOAT)context->MaxPingTimeout; // Scale the data. PhxfDivideSingle2U( context->PingGraphState.Data1, max, drawInfo->LineDataCount ); context->PingGraphState.Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam; if (getTooltipText->Index < getTooltipText->TotalCount) { if (header->hwndFrom == context->PingGraphHandle) { if (context->PingGraphState.TooltipIndex != getTooltipText->Index) { ULONG pingMs = PhGetItemCircularBuffer_ULONG(&context->PingHistory, getTooltipText->Index); PhMoveReference(&context->PingGraphState.TooltipText, PhFormatString(L"Ping: %lums", pingMs) ); } getTooltipText->Text = context->PingGraphState.TooltipText->sr; } } } break; } } break; } return FALSE; }
VOID PhShowServiceProperties( __in HWND ParentWindowHandle, __in PPH_SERVICE_ITEM ServiceItem ) { PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) }; PROPSHEETPAGE propSheetPage; HPROPSHEETPAGE pages[32]; SERVICE_PROPERTIES_CONTEXT context; PH_STD_OBJECT_SECURITY stdObjectSecurity; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; propSheetHeader.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP | PSH_PROPTITLE; propSheetHeader.hwndParent = ParentWindowHandle; propSheetHeader.pszCaption = ServiceItem->Name->Buffer; propSheetHeader.nPages = 0; propSheetHeader.nStartPage = 0; propSheetHeader.phpage = pages; // General memset(&context, 0, sizeof(SERVICE_PROPERTIES_CONTEXT)); context.ServiceItem = ServiceItem; context.Ready = FALSE; context.Dirty = FALSE; memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE)); propSheetPage.dwSize = sizeof(PROPSHEETPAGE); propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_SRVGENERAL); propSheetPage.pfnDlgProc = PhpServiceGeneralDlgProc; propSheetPage.lParam = (LPARAM)&context; pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage); // Security stdObjectSecurity.OpenObject = PhpOpenService; stdObjectSecurity.ObjectType = L"Service"; stdObjectSecurity.Context = ServiceItem; if (PhGetAccessEntries(L"Service", &accessEntries, &numberOfAccessEntries)) { pages[propSheetHeader.nPages++] = PhCreateSecurityPage( ServiceItem->Name->Buffer, PhStdGetObjectSecurity, PhStdSetObjectSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries ); PhFree(accessEntries); } if (PhPluginsEnabled) { PH_PLUGIN_OBJECT_PROPERTIES objectProperties; objectProperties.Parameter = ServiceItem; objectProperties.NumberOfPages = propSheetHeader.nPages; objectProperties.MaximumNumberOfPages = sizeof(pages) / sizeof(HPROPSHEETPAGE); objectProperties.Pages = pages; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackServicePropertiesInitializing), &objectProperties); propSheetHeader.nPages = objectProperties.NumberOfPages; } PropertySheet(&propSheetHeader); }
static BOOLEAN EtpUpdateWsWatch( _In_ HWND hwndDlg, _In_ PWS_WATCH_CONTEXT Context ) { NTSTATUS status; BOOLEAN result; ULONG returnLength; PPROCESS_WS_WATCH_INFORMATION_EX wsWatchInfo; // Query WS watch information. if (!Context->Buffer) return FALSE; status = NtQueryInformationProcess( Context->ProcessHandle, ProcessWorkingSetWatchEx, Context->Buffer, Context->BufferSize, &returnLength ); if (status == STATUS_UNSUCCESSFUL) { // WS Watch is not enabled. return FALSE; } if (status == STATUS_NO_MORE_ENTRIES) { // There were no new faults, but we still need to process symbol lookup results. result = TRUE; goto SkipBuffer; } if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) { PhFree(Context->Buffer); Context->Buffer = PhAllocate(returnLength); Context->BufferSize = returnLength; status = NtQueryInformationProcess( Context->ProcessHandle, ProcessWorkingSetWatchEx, Context->Buffer, Context->BufferSize, &returnLength ); } if (!NT_SUCCESS(status)) { // Error related to the buffer size. Try again later. result = FALSE; goto SkipBuffer; } // Update the hashtable and list view. ExtendedListView_SetRedraw(Context->ListViewHandle, FALSE); wsWatchInfo = Context->Buffer; while (wsWatchInfo->BasicInfo.FaultingPc) { PPVOID entry; WCHAR buffer[PH_INT32_STR_LEN_1]; INT lvItemIndex; ULONG newCount; // Update the count in the entry for this instruction pointer, or add a new entry if it doesn't exist. entry = PhFindItemSimpleHashtable(Context->Hashtable, wsWatchInfo->BasicInfo.FaultingPc); if (entry) { newCount = PtrToUlong(*entry) + 1; *entry = UlongToPtr(newCount); lvItemIndex = PhFindListViewItemByParam(Context->ListViewHandle, -1, wsWatchInfo->BasicInfo.FaultingPc); } else { PPH_STRING basicSymbol; newCount = 1; PhAddItemSimpleHashtable(Context->Hashtable, wsWatchInfo->BasicInfo.FaultingPc, UlongToPtr(1)); // Get a basic symbol name (module+offset). basicSymbol = EtpGetBasicSymbol(Context->SymbolProvider, (ULONG64)wsWatchInfo->BasicInfo.FaultingPc); lvItemIndex = PhAddListViewItem(Context->ListViewHandle, MAXINT, basicSymbol->Buffer, wsWatchInfo->BasicInfo.FaultingPc); PhDereferenceObject(basicSymbol); // Queue a full symbol lookup. EtpQueueSymbolLookup(Context, wsWatchInfo->BasicInfo.FaultingPc); } // Update the count in the list view item. PhPrintUInt32(buffer, newCount); PhSetListViewSubItem( Context->ListViewHandle, lvItemIndex, 1, buffer ); wsWatchInfo++; } ExtendedListView_SetRedraw(Context->ListViewHandle, TRUE); result = TRUE; SkipBuffer: EtpProcessSymbolLookupResults(hwndDlg, Context); ExtendedListView_SortItems(Context->ListViewHandle); return result; }
INT_PTR CALLBACK EtpWsWatchDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PWS_WATCH_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PWS_WATCH_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PWS_WATCH_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); context->WindowHandle = hwndDlg; context->ListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 340, L"Instruction"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Count"); PhSetExtendedListView(lvHandle); ExtendedListView_SetSort(lvHandle, 1, DescendingSortOrder); context->Hashtable = PhCreateSimpleHashtable(64); context->BufferSize = 0x2000; context->Buffer = PhAllocate(context->BufferSize); PhInitializeQueuedLock(&context->ResultListLock); context->SymbolProvider = PhCreateSymbolProvider(context->ProcessItem->ProcessId); PhLoadSymbolProviderOptions(context->SymbolProvider); if (!context->SymbolProvider || !context->SymbolProvider->IsRealHandle) { PhShowError(hwndDlg, L"Unable to open the process."); EndDialog(hwndDlg, IDCANCEL); break; } context->ProcessHandle = context->SymbolProvider->ProcessHandle; // Load symbols for both process and kernel modules. context->LoadingSymbolsForProcessId = context->ProcessItem->ProcessId; PhEnumGenericModules( NULL, context->ProcessHandle, 0, EnumGenericModulesCallback, context ); context->LoadingSymbolsForProcessId = SYSTEM_PROCESS_ID; PhEnumGenericModules( SYSTEM_PROCESS_ID, NULL, 0, EnumGenericModulesCallback, context ); context->Enabled = EtpUpdateWsWatch(hwndDlg, context); if (context->Enabled) { // WS Watch is already enabled for the process. Enable updating. EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE), FALSE); ShowWindow(GetDlgItem(hwndDlg, IDC_WSWATCHENABLED), SW_SHOW); SetTimer(hwndDlg, 1, 1000, NULL); } else { // WS Watch has not yet been enabled for the process. } } break; case WM_DESTROY: { context->Destroying = TRUE; PhDereferenceObject(context->Hashtable); if (context->Buffer) { PhFree(context->Buffer); context->Buffer = NULL; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_ENABLE: { NTSTATUS status; HANDLE processHandle; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_SET_INFORMATION, context->ProcessItem->ProcessId ))) { status = NtSetInformationProcess( processHandle, ProcessWorkingSetWatchEx, NULL, 0 ); NtClose(processHandle); } if (NT_SUCCESS(status)) { EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE), FALSE); ShowWindow(GetDlgItem(hwndDlg, IDC_WSWATCHENABLED), SW_SHOW); SetTimer(hwndDlg, 1, 1000, NULL); } else { PhShowStatus(hwndDlg, L"Unable to enable WS watch", status, 0); } } break; } } break; case WM_NOTIFY: { PhHandleListViewNotifyForCopy(lParam, context->ListViewHandle); } break; case WM_TIMER: { switch (wParam) { case 1: { EtpUpdateWsWatch(hwndDlg, context); } break; } } break; } return FALSE; }
BOOLEAN EtpRefreshUnloadedDlls( __in HWND hwndDlg, __in PUNLOADED_DLLS_CONTEXT Context ) { NTSTATUS status; PULONG elementSize; PULONG elementCount; PVOID eventTrace; HANDLE processHandle = NULL; ULONG eventTraceSize; ULONG capturedElementSize; ULONG capturedElementCount; PVOID capturedEventTracePointer; PVOID capturedEventTrace = NULL; ULONG i; PVOID currentEvent; HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); ListView_DeleteAllItems(lvHandle); RtlGetUnloadEventTraceEx(&elementSize, &elementCount, &eventTrace); if (!NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_VM_READ, Context->ProcessItem->ProcessId))) goto CleanupExit; // We have the pointers for the unload event trace information. // Since ntdll is loaded at the same base address across all processes, // we can read the information in. if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, elementSize, &capturedElementSize, sizeof(ULONG), NULL ))) goto CleanupExit; if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, elementCount, &capturedElementCount, sizeof(ULONG), NULL ))) goto CleanupExit; if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, eventTrace, &capturedEventTracePointer, sizeof(PVOID), NULL ))) goto CleanupExit; if (!capturedEventTracePointer) goto CleanupExit; // no events if (capturedElementCount > 0x4000) capturedElementCount = 0x4000; eventTraceSize = capturedElementSize * capturedElementCount; capturedEventTrace = PhAllocateSafe(eventTraceSize); if (!capturedEventTrace) { status = STATUS_NO_MEMORY; goto CleanupExit; } if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, capturedEventTracePointer, capturedEventTrace, eventTraceSize, NULL ))) goto CleanupExit; currentEvent = capturedEventTrace; ExtendedListView_SetRedraw(lvHandle, FALSE); for (i = 0; i < capturedElementCount; i++) { PRTL_UNLOAD_EVENT_TRACE rtlEvent = currentEvent; INT lvItemIndex; WCHAR buffer[128]; PPH_STRING string; LARGE_INTEGER time; SYSTEMTIME systemTime; if (!rtlEvent->BaseAddress) break; PhPrintUInt32(buffer, rtlEvent->Sequence); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, buffer, rtlEvent); // Name if (PhCopyUnicodeStringZ(rtlEvent->ImageName, sizeof(rtlEvent->ImageName) / sizeof(WCHAR), buffer, sizeof(buffer) / sizeof(WCHAR), NULL)) { PhSetListViewSubItem(lvHandle, lvItemIndex, 1, buffer); } // Base Address PhPrintPointer(buffer, rtlEvent->BaseAddress); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, buffer); // Size string = PhFormatSize(rtlEvent->SizeOfImage, -1); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, string->Buffer); PhDereferenceObject(string); // Time Stamp RtlSecondsSince1970ToTime(rtlEvent->TimeDateStamp, &time); PhLargeIntegerToLocalSystemTime(&systemTime, &time); string = PhFormatDateTime(&systemTime); PhSetListViewSubItem(lvHandle, lvItemIndex, 4, string->Buffer); PhDereferenceObject(string); // Checksum PhPrintPointer(buffer, UlongToPtr(rtlEvent->CheckSum)); PhSetListViewSubItem(lvHandle, lvItemIndex, 5, buffer); currentEvent = PTR_ADD_OFFSET(currentEvent, capturedElementSize); } ExtendedListView_SortItems(lvHandle); ExtendedListView_SetRedraw(lvHandle, TRUE); if (Context->CapturedEventTrace) PhFree(Context->CapturedEventTrace); Context->CapturedEventTrace = capturedEventTrace; CleanupExit: if (processHandle) NtClose(processHandle); if (NT_SUCCESS(status)) { return TRUE; } else { PhShowStatus(hwndDlg, L"Unable to retrieve unload event trace information", status, 0); return FALSE; } }
PVOID PhEnumServices( __in SC_HANDLE ScManagerHandle, __in_opt ULONG Type, __in_opt ULONG State, __out PULONG Count ) { static ULONG initialBufferSize = 0x8000; LOGICAL result; PVOID buffer; ULONG bufferSize; ULONG returnLength; ULONG servicesReturned; if (!Type) Type = SERVICE_DRIVER | SERVICE_WIN32; if (!State) State = SERVICE_STATE_ALL; bufferSize = initialBufferSize; buffer = PhAllocate(bufferSize); if (!(result = EnumServicesStatusEx( ScManagerHandle, SC_ENUM_PROCESS_INFO, Type, State, buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL ))) { if (GetLastError() == ERROR_MORE_DATA) { PhFree(buffer); bufferSize += returnLength; buffer = PhAllocate(bufferSize); result = EnumServicesStatusEx( ScManagerHandle, SC_ENUM_PROCESS_INFO, Type, State, buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL ); } if (!result) { PhFree(buffer); return NULL; } } if (bufferSize <= 0x10000) initialBufferSize = bufferSize; *Count = servicesReturned; return buffer; }
INT WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ INT nCmdShow ) { LONG result; #ifdef DEBUG PHP_BASE_THREAD_DBG dbg; #endif HANDLE currentTokenHandle; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #ifndef DEBUG SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); #endif PhInstanceHandle = (HINSTANCE)NtCurrentPeb()->ImageBaseAddress; if (!NT_SUCCESS(PhInitializePhLib())) return 1; if (!PhInitializeAppSystem()) return 1; PhInitializeCommonControls(); currentTokenHandle = PhGetOwnTokenAttributes().TokenHandle; if (currentTokenHandle) { PTOKEN_USER tokenUser; if (NT_SUCCESS(PhGetTokenUser(currentTokenHandle, &tokenUser))) { PhCurrentUserName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL); PhFree(tokenUser); } } PhLocalSystemName = PhGetSidFullName(&PhSeLocalSystemSid, TRUE, NULL); // There has been a report of the above call failing. if (!PhLocalSystemName) PhLocalSystemName = PhCreateString(L"NT AUTHORITY\\SYSTEM"); PhApplicationFileName = PhGetApplicationFileName(); PhApplicationDirectory = PhGetApplicationDirectory(); // Just in case if (!PhApplicationFileName) PhApplicationFileName = PhCreateString(L"ProcessHacker.exe"); if (!PhApplicationDirectory) PhApplicationDirectory = PhReferenceEmptyString(); PhpProcessStartupParameters(); PhSettingsInitialization(); PhpEnablePrivileges(); if (PhStartupParameters.RunAsServiceMode) { RtlExitUserProcess(PhRunAsServiceStart(PhStartupParameters.RunAsServiceMode)); } PhpInitializeSettings(); // Activate a previous instance if required. if (PhGetIntegerSetting(L"AllowOnlyOneInstance") && !PhStartupParameters.NewInstance && !PhStartupParameters.ShowOptions && !PhStartupParameters.CommandMode && !PhStartupParameters.PhSvc) { PhActivatePreviousInstance(); } if (PhGetIntegerSetting(L"EnableKph") && !PhStartupParameters.NoKph && !PhIsExecutingInWow64()) PhInitializeKph(); if (PhStartupParameters.CommandMode && PhStartupParameters.CommandType && PhStartupParameters.CommandAction) { NTSTATUS status; status = PhCommandModeStart(); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) { PhShowStatus(NULL, L"Unable to execute the command", status, 0); } RtlExitUserProcess(status); } #ifdef DEBUG dbg.ClientId = NtCurrentTeb()->ClientId; dbg.StartAddress = wWinMain; dbg.Parameter = NULL; InsertTailList(&PhDbgThreadListHead, &dbg.ListEntry); TlsSetValue(PhDbgThreadDbgTlsIndex, &dbg); #endif PhInitializeAutoPool(&BaseAutoPool); PhEmInitialization(); PhGuiSupportInitialization(); PhTreeNewInitialization(); PhGraphControlInitialization(); PhHexEditInitialization(); PhColorBoxInitialization(); PhSmallIconSize.X = GetSystemMetrics(SM_CXSMICON); PhSmallIconSize.Y = GetSystemMetrics(SM_CYSMICON); PhLargeIconSize.X = GetSystemMetrics(SM_CXICON); PhLargeIconSize.Y = GetSystemMetrics(SM_CYICON); if (PhStartupParameters.ShowOptions) { // Elevated options dialog for changing the value of Replace Task Manager with Process Hacker. PhShowOptionsDialog(PhStartupParameters.WindowHandle); RtlExitUserProcess(STATUS_SUCCESS); } #ifndef DEBUG if (PhIsExecutingInWow64() && !PhStartupParameters.PhSvc) { PhShowWarning( NULL, L"You are attempting to run the 32-bit version of Process Hacker on 64-bit Windows. " L"Most features will not work correctly.\n\n" L"Please run the 64-bit version of Process Hacker instead." ); } #endif PhPluginsEnabled = PhGetIntegerSetting(L"EnablePlugins") && !PhStartupParameters.NoPlugins; if (PhPluginsEnabled) { PhPluginsInitialization(); PhLoadPlugins(); } if (PhStartupParameters.PhSvc) { MSG message; // Turn the feedback cursor off. PostMessage(NULL, WM_NULL, 0, 0); GetMessage(&message, NULL, 0, 0); RtlExitUserProcess(PhSvcMain(NULL, NULL, NULL)); } // Create a mutant for the installer. { HANDLE mutantHandle; OBJECT_ATTRIBUTES oa; UNICODE_STRING mutantName; RtlInitUnicodeString(&mutantName, L"\\BaseNamedObjects\\ProcessHacker2Mutant"); InitializeObjectAttributes( &oa, &mutantName, 0, NULL, NULL ); NtCreateMutant(&mutantHandle, MUTANT_ALL_ACCESS, &oa, FALSE); } // Set priority. { PROCESS_PRIORITY_CLASS priorityClass; priorityClass.Foreground = FALSE; priorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; if (PhStartupParameters.PriorityClass != 0) priorityClass.PriorityClass = (UCHAR)PhStartupParameters.PriorityClass; NtSetInformationProcess(NtCurrentProcess(), ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); } if (!PhMainWndInitialization(nCmdShow)) { PhShowError(NULL, L"Unable to initialize the main window."); return 1; } PhDrainAutoPool(&BaseAutoPool); result = PhMainMessageLoop(); RtlExitUserProcess(result); }
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); } 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 PhModuleProviderUpdate( _In_ PVOID Object ) { PPH_MODULE_PROVIDER moduleProvider = (PPH_MODULE_PROVIDER)Object; PPH_LIST modules; ULONG i; // If we didn't get a handle when we created the provider, // abort (unless this is the System process - in that case // we don't need a handle). if (!moduleProvider->ProcessHandle && moduleProvider->ProcessId != SYSTEM_PROCESS_ID) goto UpdateExit; modules = PhCreateList(20); moduleProvider->RunStatus = PhEnumGenericModules( moduleProvider->ProcessId, moduleProvider->ProcessHandle, PH_ENUM_GENERIC_MAPPED_FILES | PH_ENUM_GENERIC_MAPPED_IMAGES, EnumModulesCallback, modules ); // Look for removed modules. { PPH_LIST modulesToRemove = NULL; ULONG enumerationKey = 0; PPH_MODULE_ITEM *moduleItem; while (PhEnumHashtable(moduleProvider->ModuleHashtable, (PVOID *)&moduleItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the module still exists. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; if ((*moduleItem)->BaseAddress == module->BaseAddress && PhEqualString((*moduleItem)->FileName, module->FileName, TRUE)) { found = TRUE; break; } } if (!found) { // Raise the module removed event. PhInvokeCallback(&moduleProvider->ModuleRemovedEvent, *moduleItem); if (!modulesToRemove) modulesToRemove = PhCreateList(2); PhAddItemList(modulesToRemove, *moduleItem); } } if (modulesToRemove) { PhAcquireFastLockExclusive(&moduleProvider->ModuleHashtableLock); for (i = 0; i < modulesToRemove->Count; i++) { PhpRemoveModuleItem( moduleProvider, (PPH_MODULE_ITEM)modulesToRemove->Items[i] ); } PhReleaseFastLockExclusive(&moduleProvider->ModuleHashtableLock); PhDereferenceObject(modulesToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_MODULE_QUERY_DATA data; entry = RtlInterlockedFlushSList(&moduleProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_MODULE_QUERY_DATA, ListEntry); entry = entry->Next; data->ModuleItem->VerifyResult = data->VerifyResult; data->ModuleItem->VerifySignerName = data->VerifySignerName; data->ModuleItem->JustProcessed = TRUE; PhDereferenceObject(data->ModuleItem); PhFree(data); } } // Look for new modules. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; PPH_MODULE_ITEM moduleItem; moduleItem = PhReferenceModuleItem(moduleProvider, module->BaseAddress); if (!moduleItem) { moduleItem = PhCreateModuleItem(); moduleItem->BaseAddress = module->BaseAddress; PhPrintPointer(moduleItem->BaseAddressString, moduleItem->BaseAddress); moduleItem->Size = module->Size; moduleItem->Flags = module->Flags; moduleItem->Type = module->Type; moduleItem->LoadReason = module->LoadReason; moduleItem->LoadCount = module->LoadCount; moduleItem->LoadTime = module->LoadTime; moduleItem->Name = module->Name; PhReferenceObject(moduleItem->Name); moduleItem->FileName = module->FileName; PhReferenceObject(moduleItem->FileName); PhInitializeImageVersionInfo( &moduleItem->VersionInfo, PhGetString(moduleItem->FileName) ); moduleItem->IsFirst = i == 0; // Fix up the load count. If this is not an ordinary DLL or kernel module, set the load count to 0. if (moduleItem->Type != PH_MODULE_TYPE_MODULE && moduleItem->Type != PH_MODULE_TYPE_WOW64_MODULE && moduleItem->Type != PH_MODULE_TYPE_KERNEL_MODULE) { moduleItem->LoadCount = 0; } if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE || moduleItem->Type == PH_MODULE_TYPE_MAPPED_IMAGE) { PH_REMOTE_MAPPED_IMAGE remoteMappedImage; // Note: // On Windows 7 the LDRP_IMAGE_NOT_AT_BASE flag doesn't appear to be used // anymore. Instead we'll check ImageBase in the image headers. We read this in // from the process' memory because: // // 1. It (should be) faster than opening the file and mapping it in, and // 2. It contains the correct original image base relocated by ASLR, if present. moduleItem->Flags &= ~LDRP_IMAGE_NOT_AT_BASE; if (NT_SUCCESS(PhLoadRemoteMappedImage(moduleProvider->ProcessHandle, moduleItem->BaseAddress, &remoteMappedImage))) { moduleItem->ImageTimeDateStamp = remoteMappedImage.NtHeaders->FileHeader.TimeDateStamp; moduleItem->ImageCharacteristics = remoteMappedImage.NtHeaders->FileHeader.Characteristics; if (remoteMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { if ((ULONG_PTR)((PIMAGE_OPTIONAL_HEADER32)&remoteMappedImage.NtHeaders->OptionalHeader)->ImageBase != (ULONG_PTR)moduleItem->BaseAddress) moduleItem->Flags |= LDRP_IMAGE_NOT_AT_BASE; moduleItem->ImageDllCharacteristics = ((PIMAGE_OPTIONAL_HEADER32)&remoteMappedImage.NtHeaders->OptionalHeader)->DllCharacteristics; } else if (remoteMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { if ((ULONG_PTR)((PIMAGE_OPTIONAL_HEADER64)&remoteMappedImage.NtHeaders->OptionalHeader)->ImageBase != (ULONG_PTR)moduleItem->BaseAddress) moduleItem->Flags |= LDRP_IMAGE_NOT_AT_BASE; moduleItem->ImageDllCharacteristics = ((PIMAGE_OPTIONAL_HEADER64)&remoteMappedImage.NtHeaders->OptionalHeader)->DllCharacteristics; } PhUnloadRemoteMappedImage(&remoteMappedImage); } } if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_KERNEL_MODULE || moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE || moduleItem->Type == PH_MODULE_TYPE_MAPPED_IMAGE) { // See if the file has already been verified; if not, queue for verification. moduleItem->VerifyResult = PhVerifyFileCached(moduleItem->FileName, NULL, &moduleItem->VerifySignerName, TRUE); if (moduleItem->VerifyResult == VrUnknown) PhpQueueModuleQuery(moduleProvider, moduleItem); } // Add the module item to the hashtable. PhAcquireFastLockExclusive(&moduleProvider->ModuleHashtableLock); PhAddEntryHashtable(moduleProvider->ModuleHashtable, &moduleItem); PhReleaseFastLockExclusive(&moduleProvider->ModuleHashtableLock); // Raise the module added event. PhInvokeCallback(&moduleProvider->ModuleAddedEvent, moduleItem); } else { BOOLEAN modified = FALSE; if (moduleItem->JustProcessed) modified = TRUE; moduleItem->JustProcessed = FALSE; if (modified) PhInvokeCallback(&moduleProvider->ModuleModifiedEvent, moduleItem); PhDereferenceObject(moduleItem); } } // Free the modules list. for (i = 0; i < modules->Count; i++) { PPH_MODULE_INFO module = modules->Items[i]; PhDereferenceObject(module->Name); PhDereferenceObject(module->FileName); PhFree(module); } PhDereferenceObject(modules); UpdateExit: PhInvokeCallback(&moduleProvider->UpdatedEvent, NULL); }
INT_PTR CALLBACK PhpMemoryEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_EDITOR_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_EDITOR_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)PH_LOAD_SHARED_ICON_SMALL(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER))); SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)PH_LOAD_SHARED_ICON_LARGE(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER))); if (context->Title) { SetWindowText(hwndDlg, context->Title->Buffer); } else { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)", processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId), context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer); PhDereferenceObject(processItem); } } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { PhShowError(context->OwnerHandle, L"Unable to edit the memory region because it is too large."); return TRUE; } if (!NT_SUCCESS(status = PhOpenProcess( &context->ProcessHandle, PROCESS_VM_READ, context->ProcessId ))) { PhShowStatus(context->OwnerHandle, L"Unable to open the process", status, 0); return TRUE; } context->Buffer = PhAllocatePage(context->RegionSize, NULL); if (!context->Buffer) { PhShowError(context->OwnerHandle, L"Unable to allocate memory for the buffer."); return TRUE; } if (!NT_SUCCESS(status = NtReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(context->OwnerHandle, L"Unable to read memory", status, 0); return TRUE; } PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BYTESPERROW), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 290; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY); PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL); HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition"); windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair; PhAdjustRectangleToWorkingArea(NULL, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemEditPosition", windowRectangle.Position); PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size); } { PWSTR bytesPerRowStrings[7]; ULONG i; ULONG bytesPerRow; for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++) bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer; PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW), bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR)); bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow"); if (bytesPerRow >= 4) { HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW), PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE); } } context->LoadCompleted = TRUE; } break; case WM_DESTROY: { if (context->LoadCompleted) { PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg); PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links); PhUnregisterDialog(hwndDlg); } RemoveProp(hwndDlg, PhMakeContextAtom()); PhDeleteLayoutManager(&context->LayoutManager); if (context->Buffer) PhFreePage(context->Buffer); if (context->ProcessHandle) NtClose(context->ProcessHandle); PhClearReference(&context->Title); if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress); PhFree(context); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_PROCESS_ITEM processItem; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId))) { PhSetFileDialogFileName(fileDialog, PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer, context->BaseAddress, context->RegionSize)->Buffer); PhDereferenceObject(processItem); } else { PhSetFileDialogFileName(fileDialog, L"Memory.bin"); } 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 ))) { status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_GOTO: { PPH_STRING selectedChoice = NULL; while (PhaChoiceDialog( hwndDlg, L"Go to Offset", L"Enter an offset:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemEditGotoChoices" )) { ULONG64 offset; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &offset)) { if (offset >= context->RegionSize) { PhShowError(hwndDlg, L"The offset is too large."); continue; } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset); break; } } } break; case IDC_WRITE: { NTSTATUS status; if (!context->WriteAccess) { HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ | PROCESS_VM_WRITE, context->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } if (context->ProcessHandle) NtClose(context->ProcessHandle); context->ProcessHandle = processHandle; context->WriteAccess = TRUE; } if (!NT_SUCCESS(status = NtWriteVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to write memory", status, 0); } } break; case IDC_REREAD: { NTSTATUS status; if (!NT_SUCCESS(status = NtReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to read memory", status, 0); } InvalidateRect(context->HexEditHandle, NULL, TRUE); } break; case IDC_BYTESPERROW: if (HIWORD(wParam) == CBN_SELCHANGE) { PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW); PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 bytesPerRow64; if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart)) { if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64)) { PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64); HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SELECT_OFFSET: { HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII); HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam); } break; } return FALSE; }
INT_PTR CALLBACK PhpServiceGeneralDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)propSheetPage->lParam; PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; // HACK PhCenterWindow(GetParent(hwndDlg), GetParent(GetParent(hwndDlg))); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_TYPE), PhServiceTypeStrings, sizeof(PhServiceTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhServiceStartTypeStrings, sizeof(PhServiceStartTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhServiceErrorControlStrings, sizeof(PhServiceErrorControlStrings) / sizeof(WCHAR *)); SetDlgItemText(hwndDlg, IDC_DESCRIPTION, serviceItem->DisplayName->Buffer); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_TYPE), -1, PhGetServiceTypeString(serviceItem->Type)); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_STARTTYPE), -1, PhGetServiceStartTypeString(serviceItem->StartType)); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), -1, PhGetServiceErrorControlString(serviceItem->ErrorControl)); serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG); if (serviceHandle) { LPQUERY_SERVICE_CONFIG config; PPH_STRING description; BOOLEAN delayedStart; if (config = PhGetServiceConfig(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_GROUP, config->lpLoadOrderGroup); SetDlgItemText(hwndDlg, IDC_BINARYPATH, config->lpBinaryPathName); SetDlgItemText(hwndDlg, IDC_USERACCOUNT, config->lpServiceStartName); PhFree(config); } if (description = PhGetServiceDescription(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_DESCRIPTION, description->Buffer); PhDereferenceObject(description); } if ( WindowsVersion >= WINDOWS_VISTA && PhGetServiceDelayedAutoStart(serviceHandle, &delayedStart) ) { context->OldDelayedStart = delayedStart; if (delayedStart) Button_SetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART), BST_CHECKED); } CloseServiceHandle(serviceHandle); } SetDlgItemText(hwndDlg, IDC_PASSWORD, L"password"); Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_UNCHECKED); SetDlgItemText(hwndDlg, IDC_SERVICEDLL, L"N/A"); { HANDLE keyHandle; PPH_STRING keyName; keyName = PhConcatStrings( 3, L"System\\CurrentControlSet\\Services\\", serviceItem->Name->Buffer, L"\\Parameters" ); if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { PPH_STRING serviceDllString; if (serviceDllString = PhQueryRegistryString(keyHandle, L"ServiceDll")) { PPH_STRING expandedString; if (expandedString = PhExpandEnvironmentStrings(&serviceDllString->sr)) { SetDlgItemText(hwndDlg, IDC_SERVICEDLL, expandedString->Buffer); PhDereferenceObject(expandedString); } PhDereferenceObject(serviceDllString); } NtClose(keyHandle); } PhDereferenceObject(keyName); } PhpRefreshControls(hwndDlg); context->Ready = TRUE; } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); switch (LOWORD(wParam)) { case IDCANCEL: { // Workaround for property sheet + multiline edit: http://support.microsoft.com/kb/130765 SendMessage(GetParent(hwndDlg), uMsg, wParam, lParam); } break; case IDC_PASSWORD: { if (HIWORD(wParam) == EN_CHANGE) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_CHECKED); } } break; case IDC_DELAYEDSTART: { context->Dirty = TRUE; } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.sys)", L"*.exe;*.sys" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_BINARYPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_BINARYPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } switch (HIWORD(wParam)) { case EN_CHANGE: case CBN_SELCHANGE: { PhpRefreshControls(hwndDlg); if (context->Ready) context->Dirty = TRUE; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_QUERYINITIALFOCUS: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_STARTTYPE)); } return TRUE; case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { NTSTATUS status; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; PPH_STRING newServiceTypeString; PPH_STRING newServiceStartTypeString; PPH_STRING newServiceErrorControlString; ULONG newServiceType; ULONG newServiceStartType; ULONG newServiceErrorControl; PPH_STRING newServiceGroup; PPH_STRING newServiceBinaryPath; PPH_STRING newServiceUserAccount; PPH_STRING newServicePassword; SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); if (!context->Dirty) { return TRUE; } newServiceTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_TYPE))); newServiceStartTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_STARTTYPE))); newServiceErrorControlString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_ERRORCONTROL))); newServiceType = PhGetServiceTypeInteger(newServiceTypeString->Buffer); newServiceStartType = PhGetServiceStartTypeInteger(newServiceStartTypeString->Buffer); newServiceErrorControl = PhGetServiceErrorControlInteger(newServiceErrorControlString->Buffer); newServiceGroup = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_GROUP))); newServiceBinaryPath = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_BINARYPATH))); newServiceUserAccount = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_USERACCOUNT))); if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK)) == BST_CHECKED) { newServicePassword = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); } else { newServicePassword = NULL; } if (newServiceType == SERVICE_KERNEL_DRIVER && newServiceUserAccount->Length == 0) { newServiceUserAccount = NULL; } serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_CHANGE_CONFIG); if (serviceHandle) { if (ChangeServiceConfig( serviceHandle, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL )) { if (WindowsVersion >= WINDOWS_VISTA) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { PhSetServiceDelayedAutoStart(serviceHandle, newDelayedStart); } } PhMarkNeedsConfigUpdateServiceItem(serviceItem); 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 = PhSvcCallChangeServiceConfig( serviceItem->Name->Buffer, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL ))) { if (WindowsVersion >= WINDOWS_VISTA) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { SERVICE_DELAYED_AUTO_START_INFO info; info.fDelayedAutostart = newDelayedStart; PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &info ); } } PhMarkNeedsConfigUpdateServiceItem(serviceItem); } PhUiDisconnectFromPhSvc(); if (!NT_SUCCESS(status)) { SetLastError(PhNtStatusToDosError(status)); goto ErrorCase; } } else { // User cancelled elevation. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } else { goto ErrorCase; } } goto Cleanup; ErrorCase: if (PhShowMessage( hwndDlg, MB_ICONERROR | MB_RETRYCANCEL, L"Unable to change service configuration: %s", ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(GetLastError())))->Buffer ) == IDRETRY) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } Cleanup: if (newServicePassword) { RtlSecureZeroMemory(newServicePassword->Buffer, newServicePassword->Length); PhDereferenceObject(newServicePassword); } } 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; }
static NTSTATUS PhNetworkPingThreadStart( _In_ PVOID Parameter ) { HANDLE icmpHandle = INVALID_HANDLE_VALUE; ULONG icmpCurrentPingMs = 0; ULONG icmpCurrentPingTtl = 0; ULONG icmpReplyCount = 0; ULONG icmpReplyLength = 0; PVOID icmpReplyBuffer = NULL; PPH_STRING phVersion = NULL; PPH_BYTES icmpEchoBuffer = NULL; IP_OPTION_INFORMATION pingOptions = { 255, // Time To Live 0, // Type Of Service IP_FLAG_DF, // IP header flags 0 // Size of options data }; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; __try { // Query PH version. if ((phVersion = PhGetPhVersion()) == NULL) __leave; // Create ICMP echo buffer. if ((icmpEchoBuffer = PhFormatAnsiString("processhacker_%S_0x0D06F00D_x1", phVersion->Buffer)) == NULL) __leave; if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE) { SOCKADDR_IN6 icmp6LocalAddr = { 0 }; SOCKADDR_IN6 icmp6RemoteAddr = { 0 }; PICMPV6_ECHO_REPLY icmp6ReplyStruct = NULL; // Create ICMPv6 handle. if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv6-ANY address. icmp6LocalAddr.sin6_addr = in6addr_any; icmp6LocalAddr.sin6_family = AF_INET6; // Set Remote IPv6 address. icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr; icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port); // Allocate ICMPv6 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv6 ping... icmpReplyCount = Icmp6SendEcho2( icmpHandle, NULL, NULL, NULL, &icmp6LocalAddr, &icmp6RemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmp6ReplyStruct = (PICMPV6_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyCount > 0 && icmp6ReplyStruct) { BOOLEAN icmpPacketSignature = FALSE; if (icmp6ReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (_memicmp( icmp6ReplyStruct->Address.sin6_addr, context->IpAddress.In6Addr.u.Word, sizeof(icmp6ReplyStruct->Address.sin6_addr) ) != 0) { InterlockedIncrement(&context->UnknownAddrCount); } //if (icmp6ReplyStruct->DataSize == icmpEchoBuffer->MaximumLength) //{ // icmpPacketSignature = (_memicmp( // icmpEchoBuffer->Buffer, // icmp6ReplyStruct->Data, // icmp6ReplyStruct->DataSize // ) == 0); //} //if (icmpPacketSignature != TRUE) //{ // InterlockedIncrement(&context->HashFailCount); //} icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime; //icmpCurrentPingTtl = icmp6ReplyStruct->Options.Ttl; } else { InterlockedIncrement(&context->PingLossCount); } } else { IPAddr icmpLocalAddr = 0; IPAddr icmpRemoteAddr = 0; PICMP_ECHO_REPLY icmpReplyStruct = NULL; // Create ICMPv4 handle. if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE) __leave; // Set Local IPv4-ANY address. icmpLocalAddr = in4addr_any.s_addr; // Set Remote IPv4 address. icmpRemoteAddr = context->IpAddress.InAddr.s_addr; // Allocate ICMPv4 message. icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer); icmpReplyBuffer = PhAllocate(icmpReplyLength); memset(icmpReplyBuffer, 0, icmpReplyLength); InterlockedIncrement(&context->PingSentCount); // Send ICMPv4 ping... //if (WindowsVersion > WINDOWS_VISTA) //{ // // Vista SP1 and up we can specify the source address: // icmpReplyCount = IcmpSendEcho2Ex( // icmpHandle, // NULL, // NULL, // NULL, // icmpLocalAddr, // icmpRemoteAddr, // icmpEchoBuffer->Buffer, // icmpEchoBuffer->MaximumLength, // &pingOptions, // icmpReplyBuffer, // icmpReplyLength, // context->MaxPingTimeout // ); //} icmpReplyCount = IcmpSendEcho2( icmpHandle, NULL, NULL, NULL, icmpRemoteAddr, icmpEchoBuffer->Buffer, (USHORT)icmpEchoBuffer->Length, &pingOptions, icmpReplyBuffer, icmpReplyLength, context->MaxPingTimeout ); icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer; if (icmpReplyStruct && icmpReplyCount > 0) { BOOLEAN icmpPacketSignature = FALSE; if (icmpReplyStruct->Status != IP_SUCCESS) { InterlockedIncrement(&context->PingLossCount); } if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr) { InterlockedIncrement(&context->UnknownAddrCount); } if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length) { icmpPacketSignature = (_memicmp( icmpEchoBuffer->Buffer, icmpReplyStruct->Data, icmpReplyStruct->DataSize ) == 0); } icmpCurrentPingMs = icmpReplyStruct->RoundTripTime; icmpCurrentPingTtl = icmpReplyStruct->Options.Ttl; if (!icmpPacketSignature) { InterlockedIncrement(&context->HashFailCount); } } else { InterlockedIncrement(&context->PingLossCount); } } InterlockedIncrement(&context->PingRecvCount); if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs) context->PingMinMs = icmpCurrentPingMs; if (icmpCurrentPingMs > context->PingMaxMs) context->PingMaxMs = icmpCurrentPingMs; context->CurrentPingMs = icmpCurrentPingMs; PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs); } __finally { if (phVersion) { PhDereferenceObject(phVersion); } if (icmpEchoBuffer) { PhDereferenceObject(icmpEchoBuffer); } if (icmpHandle != INVALID_HANDLE_VALUE) { IcmpCloseHandle(icmpHandle); } if (icmpReplyBuffer) { PhFree(icmpReplyBuffer); } } PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0); return STATUS_SUCCESS; }