PPH_STRING DiskDriveQueryDosMountPoints( _In_ ULONG DeviceNumber ) { ULONG driveMask; WCHAR deviceNameBuffer[7] = L"\\\\.\\?:"; PH_STRING_BUILDER stringBuilder; PhInitializeStringBuilder(&stringBuilder, MAX_PATH); driveMask = DiskDriveQueryDeviceMap(); // NOTE: This isn't the best way of doing this but it works. for (INT i = 0; i < 0x1A; i++) { if (driveMask & (0x1 << i)) { HANDLE deviceHandle; deviceNameBuffer[4] = (WCHAR)('A' + i); if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, deviceNameBuffer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { ULONG deviceNumber = ULONG_MAX; // Note: Do not initialize to zero. DEVICE_TYPE deviceType = 0; if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber( deviceHandle, &deviceNumber, &deviceType ))) { // BUG: Device numbers are re-used on seperate device controllers and this // causes drive letters to be assigned to disks at those same indexes. // For now, just filter CD_ROM devices but we may need to be a lot more strict and // only allow devices of type FILE_DEVICE_DISK to be scanned for mount points. if (deviceNumber == DeviceNumber && deviceType != FILE_DEVICE_CD_ROM) { PhAppendFormatStringBuilder(&stringBuilder, L"%c: ", deviceNameBuffer[4]); } } NtClose(deviceHandle); } } } if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
PUCHAR PhpReadSignature( _In_ PWSTR FileName, _Out_ PULONG SignatureSize ) { NTSTATUS status; HANDLE fileHandle; PUCHAR signature; ULONG bufferSize; IO_STATUS_BLOCK iosb; if (!NT_SUCCESS(PhCreateFileWin32(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { return NULL; } bufferSize = 1024; signature = PhAllocate(bufferSize); status = NtReadFile(fileHandle, NULL, NULL, NULL, &iosb, signature, bufferSize, NULL, NULL); NtClose(fileHandle); if (NT_SUCCESS(status)) { *SignatureSize = (ULONG)iosb.Information; return signature; } else { PhFree(signature); return NULL; } }
PPH_LIST DiskDriveQueryMountPointHandles( _In_ ULONG DeviceNumber ) { ULONG driveMask; PPH_LIST deviceList; WCHAR deviceNameBuffer[7] = L"\\\\.\\?:"; driveMask = DiskDriveQueryDeviceMap(); deviceList = PhCreateList(2); // NOTE: This isn't the best way of doing this but it works. for (INT i = 0; i < 0x1A; i++) { if (driveMask & (0x1 << i)) { HANDLE deviceHandle; deviceNameBuffer[4] = (WCHAR)('A' + i); if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, deviceNameBuffer, PhGetOwnTokenAttributes().Elevated ? FILE_GENERIC_READ : FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { ULONG deviceNumber = ULONG_MAX; // Note: Do not initialize to zero. DEVICE_TYPE deviceType = 0; if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber( deviceHandle, &deviceNumber, &deviceType ))) { // BUG: Device numbers are re-used on seperate device controllers and this // causes drive letters to be assigned to disks at those same indexes. // For now, just filter CD_ROM devices but we may need to be a lot more strict and // only allow devices of type FILE_DEVICE_DISK to be scanned for mount points. if (deviceNumber == DeviceNumber && deviceType != FILE_DEVICE_CD_ROM) { PDISK_HANDLE_ENTRY entry = PhAllocate(sizeof(DISK_HANDLE_ENTRY)); memset(entry, 0, sizeof(DISK_HANDLE_ENTRY)); entry->DeviceLetter = deviceNameBuffer[4]; entry->DeviceHandle = deviceHandle; PhAddItemList(deviceList, entry); } } } } } return deviceList; }
BOOLEAN UpdaterCheckApplicationDirectory( VOID ) { HANDLE fileHandle; PPH_STRING directory; PPH_STRING file; if (UpdaterCheckKphInstallState()) return FALSE; directory = PhGetApplicationDirectory(); file = PhConcatStrings(2, PhGetStringOrEmpty(directory), L"\\processhacker.update"); if (NT_SUCCESS(PhCreateFileWin32( &fileHandle, PhGetString(file), FILE_GENERIC_WRITE | DELETE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE ))) { PhDereferenceObject(file); PhDereferenceObject(directory); NtClose(fileHandle); return TRUE; } PhDereferenceObject(file); PhDereferenceObject(directory); return FALSE; }
VOID SetupDeleteDirectoryFile(_In_ PWSTR FileName) { HANDLE tempHandle; FILE_DISPOSITION_INFORMATION dispositionInfo; IO_STATUS_BLOCK isb; if (NT_SUCCESS(PhCreateFileWin32( &tempHandle, FileName, FILE_GENERIC_WRITE | DELETE, 0, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT ))) { dispositionInfo.DeleteFile = TRUE; NtSetInformationFile( tempHandle, &isb, &dispositionInfo, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation ); NtClose(tempHandle); } }
NTSTATUS DiskDriveCreateHandle( _Out_ PHANDLE DeviceHandle, _In_ PPH_STRING DevicePath ) { // Some examples of paths that can be used to open the disk device for statistics: // \PhysicalDrive1 // \X: // X:\ // \HarddiskVolume1 // \Harddisk1Partition1 // \Harddisk1\Partition1 // \Volume{a978c827-cf64-44b4-b09a-57a55ef7f49f} // IOCTL_MOUNTMGR_QUERY_POINTS (used by FindFirstVolume and FindFirstVolumeMountPoint) // HKEY_LOCAL_MACHINE\\SYSTEM\\MountedDevices (contains the DosDevice and path used by the SetupAPI with DetailData->DevicePath) // Other methods?? return PhCreateFileWin32( DeviceHandle, DevicePath->Buffer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT // FILE_RANDOM_ACCESS ); }
BOOLEAN PhpCreateProcessMiniDumpWithProgress( _In_ HWND hWnd, _In_ HANDLE ProcessId, _In_ PWSTR FileName, _In_ MINIDUMP_TYPE DumpType ) { NTSTATUS status; PROCESS_MINIDUMP_CONTEXT context; memset(&context, 0, sizeof(PROCESS_MINIDUMP_CONTEXT)); context.ProcessId = ProcessId; context.FileName = FileName; context.DumpType = DumpType; if (!NT_SUCCESS(status = PhOpenProcess( &context.ProcessHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, ProcessId ))) { PhShowStatus(hWnd, L"Unable to open the process", status, 0); return FALSE; } #ifdef _WIN64 PhGetProcessIsWow64(context.ProcessHandle, &context.IsWow64); #endif status = PhCreateFileWin32( &context.FileHandle, FileName, FILE_GENERIC_WRITE | DELETE, 0, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { PhShowStatus(hWnd, L"Unable to access the dump file", status, 0); NtClose(context.ProcessHandle); return FALSE; } DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_PROGRESS), hWnd, PhpProcessMiniDumpDlgProc, (LPARAM)&context ); NtClose(context.FileHandle); NtClose(context.ProcessHandle); return context.Succeeded; }
PPH_STRING DiskDriveQueryDosMountPoints( _In_ ULONG DeviceNumber ) { ULONG driveMask; PH_STRING_BUILDER stringBuilder; WCHAR devicePath[] = L"\\\\.\\?:"; PhInitializeStringBuilder(&stringBuilder, MAX_PATH); driveMask = DiskDriveQueryDeviceMap(); // NOTE: This isn't the best way of doing this but it works (It's also what Task Manager does). for (INT i = 0; i < 0x1A; i++) { if (driveMask & (0x1 << i)) { HANDLE deviceHandle; devicePath[4] = 'A' + i; if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, devicePath, FILE_READ_ATTRIBUTES | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { ULONG deviceNumber = ULONG_MAX; // Note: Do not initialize to zero. if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber( deviceHandle, &deviceNumber, NULL ))); { if (deviceNumber == DeviceNumber) { PhAppendFormatStringBuilder(&stringBuilder, L"%c: ", devicePath[4]); } } NtClose(deviceHandle); } } } if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
VOID VirusTotalBuildJsonArray( _In_ PVIRUSTOTAL_FILE_HASH_ENTRY Entry, _In_ PVOID JsonArray ) { HANDLE fileHandle; FILE_NETWORK_OPEN_INFORMATION fileAttributeInfo; PPH_STRING hashString = NULL; if (NT_SUCCESS(PhQueryFullAttributesFileWin32( Entry->FileName->Buffer, &fileAttributeInfo ))) { Entry->CreationTime = VirusTotalTimeString(&fileAttributeInfo.CreationTime); } if (NT_SUCCESS(PhCreateFileWin32( &fileHandle, Entry->FileName->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT // FILE_OPEN_FOR_BACKUP_INTENT ))) { if (NT_SUCCESS(HashFileAndResetPosition( fileHandle, &fileAttributeInfo.EndOfFile, Sha256HashAlgorithm, &hashString ))) { PVOID entry; Entry->FileHash = hashString; Entry->FileHashAnsi = PhConvertUtf16ToMultiByte(Entry->FileHash->Buffer); entry = PhCreateJsonObject(); PhAddJsonObject(entry, "autostart_location", ""); PhAddJsonObject(entry, "autostart_entry", ""); PhAddJsonObject(entry, "hash", Entry->FileHashAnsi->Buffer); PhAddJsonObject(entry, "image_path", Entry->FileNameAnsi->Buffer); PhAddJsonObject(entry, "creation_datetime", Entry->CreationTime ? Entry->CreationTime->Buffer : ""); PhAddJsonArrayObject(JsonArray, entry); } NtClose(fileHandle); } }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad); }
int json_object_to_file_ext(wchar_t *filename, struct json_object *obj, int flags) { NTSTATUS status; HANDLE fileHandle; IO_STATUS_BLOCK isb; PSTR json_str; if (!(json_str = json_object_to_json_string_ext(obj, flags))) return -1; status = PhCreateFileWin32( &fileHandle, filename, FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return -1; status = NtWriteFile( fileHandle, NULL, NULL, NULL, &isb, json_str, (ULONG)strlen(json_str), NULL, NULL ); if (!NT_SUCCESS(status)) { NtClose(fileHandle); return -1; } NtClose(fileHandle); return 0; }
/** * Deletes a file. * * \param FileName The Win32 file name. */ NTSTATUS PhDeleteFileWin32( _In_ PWSTR FileName ) { NTSTATUS status; HANDLE fileHandle; status = PhCreateFileWin32( &fileHandle, FileName, DELETE, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_DELETE_ON_CLOSE ); if (!NT_SUCCESS(status)) return status; NtClose(fileHandle); return status; }
VOID PhpInitializeSettings( VOID ) { NTSTATUS status; if (!PhStartupParameters.NoSettings) { static PH_STRINGREF settingsSuffix = PH_STRINGREF_INIT(L".settings.xml"); PPH_STRING settingsFileName; // There are three possible locations for the settings file: // 1. The file name given in the command line. // 2. A file named ProcessHacker.exe.settings.xml in the program directory. (This changes // based on the executable file name.) // 3. The default location. // 1. File specified in command line if (PhStartupParameters.SettingsFileName) { // Get an absolute path now. PhSettingsFileName = PhGetFullPath(PhStartupParameters.SettingsFileName->Buffer, NULL); } // 2. File in program directory if (!PhSettingsFileName) { settingsFileName = PhConcatStringRef2(&PhApplicationFileName->sr, &settingsSuffix); if (RtlDoesFileExists_U(settingsFileName->Buffer)) { PhSettingsFileName = settingsFileName; } else { PhDereferenceObject(settingsFileName); } } // 3. Default location if (!PhSettingsFileName) { PhSettingsFileName = PhGetKnownLocation(CSIDL_APPDATA, L"\\Process Hacker 2\\settings.xml"); } if (PhSettingsFileName) { status = PhLoadSettings(PhSettingsFileName->Buffer); // If we didn't find the file, it will be created. Otherwise, // there was probably a parsing error and we don't want to // change anything. if (status == STATUS_FILE_CORRUPT_ERROR) { if (PhShowMessage( NULL, MB_ICONWARNING | MB_YESNO, L"Process Hacker's settings file is corrupt. Do you want to reset it?\n" L"If you select No, the settings system will not function properly." ) == IDYES) { HANDLE fileHandle; IO_STATUS_BLOCK isb; CHAR data[] = "<settings></settings>"; // This used to delete the file. But it's better to keep the file there // and overwrite it with some valid XML, especially with case (2) above. if (NT_SUCCESS(PhCreateFileWin32( &fileHandle, PhSettingsFileName->Buffer, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OVERWRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { NtWriteFile(fileHandle, NULL, NULL, NULL, &isb, data, sizeof(data) - 1, NULL, NULL); NtClose(fileHandle); } } else { // Pretend we don't have a settings store so bad things // don't happen. PhDereferenceObject(PhSettingsFileName); PhSettingsFileName = NULL; } } } } // Apply basic global settings. PhMaxSizeUnit = PhGetIntegerSetting(L"MaxSizeUnit"); if (PhGetIntegerSetting(L"SampleCountAutomatic")) { ULONG sampleCount; sampleCount = (GetSystemMetrics(SM_CXVIRTUALSCREEN) + 1) / 2; if (sampleCount > 2048) sampleCount = 2048; PhSetIntegerSetting(L"SampleCount", sampleCount); } }
NTSTATUS PhLoadSettings( _In_ PWSTR FileName ) { NTSTATUS status; HANDLE fileHandle; LARGE_INTEGER fileSize; mxml_node_t *topNode; mxml_node_t *currentNode; PhpClearIgnoredSettings(); status = PhCreateFileWin32( &fileHandle, FileName, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) && fileSize.QuadPart == 0) { // A blank file is OK. There are no settings to load. NtClose(fileHandle); return status; } topNode = mxmlLoadFd(NULL, fileHandle, MXML_OPAQUE_CALLBACK); NtClose(fileHandle); if (!topNode) return STATUS_FILE_CORRUPT_ERROR; if (topNode->type != MXML_ELEMENT) { mxmlDelete(topNode); return STATUS_FILE_CORRUPT_ERROR; } currentNode = topNode->child; while (currentNode) { PPH_STRING settingName = NULL; if ( currentNode->type == MXML_ELEMENT && currentNode->value.element.num_attrs >= 1 && _stricmp(currentNode->value.element.attrs[0].name, "name") == 0 ) { settingName = PhConvertUtf8ToUtf16(currentNode->value.element.attrs[0].value); } if (settingName) { PPH_STRING settingValue = 0; settingValue = PhpGetOpaqueXmlNodeText(currentNode); PhAcquireQueuedLockExclusive(&PhSettingsLock); { PPH_SETTING setting; setting = PhpLookupSetting(&settingName->sr); if (setting) { PhpFreeSettingValue(setting->Type, setting); if (!PhpSettingFromString( setting->Type, &settingValue->sr, settingValue, setting )) { PhpSettingFromString( setting->Type, &setting->DefaultValue, NULL, setting ); } } else { setting = PhAllocate(sizeof(PH_SETTING)); setting->Name.Buffer = PhAllocateCopy(settingName->Buffer, settingName->Length + sizeof(WCHAR)); setting->Name.Length = settingName->Length; PhReferenceObject(settingValue); setting->u.Pointer = settingValue; PhAddItemList(PhIgnoredSettings, setting); } } PhReleaseQueuedLockExclusive(&PhSettingsLock); PhDereferenceObject(settingValue); PhDereferenceObject(settingName); } currentNode = currentNode->next; } mxmlDelete(topNode); PhUpdateCachedSettings(); return STATUS_SUCCESS; }
VOID FindNetworkAdapters( _In_ PDV_NETADAPTER_CONTEXT Context ) { if (Context->UseAlternateMethod) { ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_ALL_INTERFACES; ULONG bufferLength = 0; PVOID buffer; if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &bufferLength) != ERROR_BUFFER_OVERFLOW) return; buffer = PhAllocate(bufferLength); memset(buffer, 0, bufferLength); if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, buffer, &bufferLength) == ERROR_SUCCESS) { PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (PIP_ADAPTER_ADDRESSES i = buffer; i; i = i->Next) { PPH_STRING description; if (description = PhCreateString(i->Description)) { AddNetworkAdapterToListView( Context, TRUE, i->IfIndex, i->Luid, PhConvertMultiByteToUtf16(i->AdapterName), description ); PhDereferenceObject(description); } } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } PhFree(buffer); } else { static PH_STRINGREF devicePathSr = PH_STRINGREF_INIT(L"\\\\.\\"); PPH_LIST deviceList; PWSTR deviceInterfaceList; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DEVINTERFACE_NET, NULL, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { return; } deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR)); memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR)); if (CM_Get_Device_Interface_List( (PGUID)&GUID_DEVINTERFACE_NET, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return; } deviceList = PH_AUTO(PhCreateList(1)); for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { HKEY keyHandle; DEVINST deviceInstanceHandle; PPH_STRING deviceDescription = NULL; if (!QueryNetworkDeviceInterfaceDescription(deviceInterface, &deviceInstanceHandle, &deviceDescription)) continue; if (CM_Open_DevInst_Key( deviceInstanceHandle, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &keyHandle, CM_REGISTRY_SOFTWARE ) == CR_SUCCESS) { PNET_ENUM_ENTRY adapterEntry; HANDLE deviceHandle; adapterEntry = PhAllocate(sizeof(NET_ENUM_ENTRY)); memset(adapterEntry, 0, sizeof(NET_ENUM_ENTRY)); adapterEntry->DeviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId"); adapterEntry->DeviceInterface = PhConcatStringRef2(&devicePathSr, &adapterEntry->DeviceGuid->sr); adapterEntry->DeviceLuid.Info.IfType = PhQueryRegistryUlong64(keyHandle, L"*IfType"); adapterEntry->DeviceLuid.Info.NetLuidIndex = PhQueryRegistryUlong64(keyHandle, L"NetLuidIndex"); if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, PhGetString(adapterEntry->DeviceInterface), FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { PPH_STRING adapterName; // Try query the full adapter name adapterName = NetworkAdapterQueryName(deviceHandle, adapterEntry->DeviceGuid); if (adapterName) adapterEntry->DeviceName = adapterName; adapterEntry->DevicePresent = TRUE; NtClose(deviceHandle); } if (!adapterEntry->DeviceName) adapterEntry->DeviceName = PhCreateString2(&deviceDescription->sr); PhAddItemList(deviceList, adapterEntry); NtClose(keyHandle); } PhClearReference(&deviceDescription); } // Cleanup. PhFree(deviceInterfaceList); // Sort the entries qsort(deviceList->Items, deviceList->Count, sizeof(PVOID), AdapterEntryCompareFunction); PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < deviceList->Count; i++) { PNET_ENUM_ENTRY entry = deviceList->Items[i]; AddNetworkAdapterToListView( Context, entry->DevicePresent, 0, entry->DeviceLuid, entry->DeviceGuid, entry->DeviceName ); if (entry->DeviceName) PhDereferenceObject(entry->DeviceName); if (entry->DeviceInterface) PhDereferenceObject(entry->DeviceInterface); // Note: DeviceGuid is disposed by WM_DESTROY. PhFree(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } // HACK: Show all unknown devices. PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < NetworkAdaptersList->Count; i++) { ULONG index = ULONG_MAX; BOOLEAN found = FALSE; PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]); if (!entry) continue; while ((index = PhFindListViewItemByFlags( Context->ListViewHandle, index, LVNI_ALL )) != ULONG_MAX) { PDV_NETADAPTER_ID param; if (PhGetListViewItemParam(Context->ListViewHandle, index, ¶m)) { if (EquivalentNetAdapterId(param, &entry->AdapterId)) { found = TRUE; } } } if (!found) { PPH_STRING description; MIB_IF_ROW2 interfaceRow; memset(&interfaceRow, 0, sizeof(MIB_IF_ROW2)); interfaceRow.InterfaceLuid = entry->AdapterId.InterfaceLuid; interfaceRow.InterfaceIndex = entry->AdapterId.InterfaceIndex; // HACK: Try query the description from the interface entry (if it exists). if (GetIfEntry2(&interfaceRow) == NO_ERROR) description = PhCreateString(interfaceRow.Description); else description = PhCreateString(L"Unknown network adapter"); if (description) { AddNetworkAdapterToListView( Context, FALSE, entry->AdapterId.InterfaceIndex, entry->AdapterId.InterfaceLuid, entry->AdapterId.InterfaceGuid, description ); PhDereferenceObject(description); } } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); }
struct json_object* json_object_from_file(wchar_t *filename) { NTSTATUS status; HANDLE fileHandle; IO_STATUS_BLOCK isb; struct json_object *obj = NULL; status = PhCreateFileWin32( &fileHandle, filename, FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (NT_SUCCESS(status)) { PSTR data; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; BYTE buffer[PAGE_SIZE]; allocatedLength = sizeof(buffer); data = (PSTR)PhAllocate(allocatedLength); dataLength = 0; memset(data, 0, allocatedLength); while (NT_SUCCESS(NtReadFile(fileHandle, NULL, NULL, NULL, &isb, buffer, PAGE_SIZE, NULL, NULL))) { returnLength = (ULONG)isb.Information; if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; data = (PSTR)PhReAllocate(data, allocatedLength); } memcpy(data + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; data = (PSTR)PhReAllocate(data, allocatedLength); } data[dataLength] = 0; obj = json_tokener_parse(data); PhFree(data); } return obj; }
NTSTATUS SaveDb( VOID ) { PH_AUTO_POOL autoPool; NTSTATUS status; HANDLE fileHandle; mxml_node_t *topNode; ULONG enumerationKey = 0; PDB_OBJECT *object; PhInitializeAutoPool(&autoPool); topNode = mxmlNewElement(MXML_NO_PARENT, "objects"); LockDb(); while (PhEnumHashtable(ObjectDb, (PVOID*)&object, &enumerationKey)) { CreateObjectElement( topNode, &UInt64ToBase10String((*object)->Tag)->sr, &(*object)->Name->sr, &UInt64ToBase10String((*object)->PriorityClass)->sr, &UInt64ToBase10String((*object)->IoPriorityPlusOne)->sr, &(*object)->Comment->sr, &UInt64ToBase10String((*object)->BackColor)->sr, &UInt64ToBase10String((*object)->Collapse)->sr, &UInt64ToBase10String((*object)->AffinityMask)->sr ); PhDrainAutoPool(&autoPool); } UnlockDb(); // Create the directory if it does not exist. { PPH_STRING fullPath; ULONG indexOfFileName; if (fullPath = PH_AUTO(PhGetFullPath(ObjectDbPath->Buffer, &indexOfFileName))) { if (indexOfFileName != -1) SHCreateDirectoryEx(NULL, PhaSubstring(fullPath, 0, indexOfFileName)->Buffer, NULL); } } PhDeleteAutoPool(&autoPool); status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { mxmlDelete(topNode); return status; } mxmlSaveFd(topNode, fileHandle, MXML_NO_CALLBACK); mxmlDelete(topNode); NtClose(fileHandle); return STATUS_SUCCESS; }
VOID PeInitializeSettings( VOID ) { static PH_STRINGREF settingsSuffix = PH_STRINGREF_INIT(L".peview.xml"); NTSTATUS status; PPH_STRING appFileName; PPH_STRING tempFileName; // There are three possible locations for the settings file: // 1. A file named peview.exe.peview.xml in the program directory. (This changes // based on the executable file name.) // 2. The default location. // 1. File in program directory appFileName = PhGetApplicationFileName(); tempFileName = PhConcatStringRef2(&appFileName->sr, &settingsSuffix); PhDereferenceObject(appFileName); if (RtlDoesFileExists_U(tempFileName->Buffer)) { PeSettingsFileName = tempFileName; } else { PhDereferenceObject(tempFileName); } // 2. Default location if (!PeSettingsFileName) { PeSettingsFileName = PhGetKnownLocation(CSIDL_APPDATA, L"\\Process Hacker\\peview.xml"); } if (PeSettingsFileName) { status = PhLoadSettings(PeSettingsFileName->Buffer); // If we didn't find the file, it will be created. Otherwise, // there was probably a parsing error and we don't want to // change anything. if (status == STATUS_FILE_CORRUPT_ERROR) { if (PhShowMessage2( NULL, TDCBF_YES_BUTTON | TDCBF_NO_BUTTON, TD_WARNING_ICON, L"PE View's settings file is corrupt. Do you want to reset it?", L"If you select No, the settings system will not function properly." ) == IDYES) { HANDLE fileHandle; IO_STATUS_BLOCK isb; CHAR data[] = "<settings></settings>"; // This used to delete the file. But it's better to keep the file there // and overwrite it with some valid XML, especially with case (2) above. if (NT_SUCCESS(PhCreateFileWin32( &fileHandle, PeSettingsFileName->Buffer, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OVERWRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { NtWriteFile(fileHandle, NULL, NULL, NULL, &isb, data, sizeof(data) - 1, NULL, NULL); NtClose(fileHandle); } } else { // Pretend we don't have a settings store so bad things don't happen. PhDereferenceObject(PeSettingsFileName); PeSettingsFileName = NULL; } } } // Apply basic global settings. PhMaxSizeUnit = PhGetIntegerSetting(L"MaxSizeUnit"); }
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; }
NTSTATUS LoadDb( VOID ) { NTSTATUS status; HANDLE fileHandle; LARGE_INTEGER fileSize; mxml_node_t *topNode; mxml_node_t *currentNode; status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) && fileSize.QuadPart == 0) { // A blank file is OK. There are no objects to load. NtClose(fileHandle); return status; } topNode = mxmlLoadFd(NULL, fileHandle, MXML_OPAQUE_CALLBACK); NtClose(fileHandle); if (!topNode) return STATUS_FILE_CORRUPT_ERROR; if (topNode->type != MXML_ELEMENT) { mxmlDelete(topNode); return STATUS_FILE_CORRUPT_ERROR; } LockDb(); for (currentNode = topNode->child; currentNode; currentNode = currentNode->next) { PDB_OBJECT object = NULL; PPH_STRING tag = NULL; PPH_STRING name = NULL; PPH_STRING priorityClass = NULL; PPH_STRING ioPriorityPlusOne = NULL; PPH_STRING comment = NULL; PPH_STRING backColor = NULL; PPH_STRING collapse = NULL; PPH_STRING affinityMask = NULL; if (currentNode->type == MXML_ELEMENT && currentNode->value.element.num_attrs >= 2) { for (INT i = 0; i < currentNode->value.element.num_attrs; i++) { if (_stricmp(currentNode->value.element.attrs[i].name, "tag") == 0) PhMoveReference(&tag, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "name") == 0) PhMoveReference(&name, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "priorityclass") == 0) PhMoveReference(&priorityClass, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "iopriorityplusone") == 0) PhMoveReference(&ioPriorityPlusOne, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "backcolor") == 0) PhMoveReference(&backColor, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "collapse") == 0) PhMoveReference(&collapse, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "affinity") == 0) PhMoveReference(&affinityMask, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); } } comment = GetOpaqueXmlNodeText(currentNode); if (tag && name && comment) { ULONG64 tagInteger; ULONG64 priorityClassInteger = 0; ULONG64 ioPriorityPlusOneInteger = 0; PhStringToInteger64(&tag->sr, 10, &tagInteger); if (priorityClass) PhStringToInteger64(&priorityClass->sr, 10, &priorityClassInteger); if (ioPriorityPlusOne) PhStringToInteger64(&ioPriorityPlusOne->sr, 10, &ioPriorityPlusOneInteger); object = CreateDbObject((ULONG)tagInteger, &name->sr, comment); object->PriorityClass = (ULONG)priorityClassInteger; object->IoPriorityPlusOne = (ULONG)ioPriorityPlusOneInteger; } // NOTE: These items are handled separately to maintain compatibility with previous versions of the database. if (object && backColor) { ULONG64 backColorInteger = ULONG_MAX; PhStringToInteger64(&backColor->sr, 10, &backColorInteger); object->BackColor = (COLORREF)backColorInteger; } if (object && collapse) { ULONG64 collapseInteger = 0; PhStringToInteger64(&collapse->sr, 10, &collapseInteger); object->Collapse = !!collapseInteger; } if (object && affinityMask) { ULONG64 affinityInteger = 0; PhStringToInteger64(&affinityMask->sr, 10, &affinityInteger); object->AffinityMask = (ULONG)affinityInteger; } PhClearReference(&tag); PhClearReference(&name); PhClearReference(&priorityClass); PhClearReference(&ioPriorityPlusOne); PhClearReference(&comment); PhClearReference(&backColor); PhClearReference(&collapse); PhClearReference(&affinityMask); } UnlockDb(); mxmlDelete(topNode); return STATUS_SUCCESS; }
VERIFY_RESULT PhpVerifyFileFromCatalog( __in PWSTR FileName, __out_opt PPH_STRING *SignerName ) { LONG status = TRUST_E_NOSIGNATURE; WINTRUST_DATA trustData = { 0 }; WINTRUST_CATALOG_INFO catalogInfo = { 0 }; GUID driverActionVerify = DRIVER_ACTION_VERIFY; HANDLE fileHandle; LARGE_INTEGER fileSize; PUCHAR fileHash = NULL; ULONG fileHashLength; PWSTR fileHashTag = NULL; HANDLE catAdminHandle = NULL; HANDLE catInfoHandle = NULL; ULONG i; if (!NT_SUCCESS(PhCreateFileWin32( &fileHandle, FileName, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) return VrNoSignature; // Don't try to hash files over 32 MB in size. if (!NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) || (fileSize.QuadPart > 32 * 1024 * 1024)) { NtClose(fileHandle); return VrNoSignature; } fileHashLength = 256; fileHash = PhAllocate(fileHashLength); if (!CryptCATAdminCalcHashFromFileHandle(fileHandle, &fileHashLength, fileHash, 0)) { PhFree(fileHash); fileHash = PhAllocate(fileHashLength); if (!CryptCATAdminCalcHashFromFileHandle(fileHandle, &fileHashLength, fileHash, 0)) { NtClose(fileHandle); PhFree(fileHash); return VrNoSignature; } } NtClose(fileHandle); if (!CryptCATAdminAcquireContext(&catAdminHandle, &driverActionVerify, 0)) { PhFree(fileHash); return VrNoSignature; } fileHashTag = PhAllocate((fileHashLength * 2 + 1) * sizeof(WCHAR)); for (i = 0; i < fileHashLength; i++) { fileHashTag[i * 2] = PhIntegerToCharUpper[fileHash[i] >> 4]; fileHashTag[i * 2 + 1] = PhIntegerToCharUpper[fileHash[i] & 0xf]; } fileHashTag[fileHashLength * 2] = 0; catInfoHandle = CryptCATAdminEnumCatalogFromHash( catAdminHandle, fileHash, fileHashLength, 0, NULL ); PhFree(fileHash); if (catInfoHandle) { CATALOG_INFO ci = { 0 }; if (CryptCATCatalogInfoFromContext(catInfoHandle, &ci, 0)) { catalogInfo.cbStruct = sizeof(catalogInfo); catalogInfo.pcwszCatalogFilePath = ci.wszCatalogFile; catalogInfo.pcwszMemberFilePath = FileName; catalogInfo.pcwszMemberTag = fileHashTag; trustData.cbStruct = sizeof(trustData); trustData.dwUIChoice = WTD_UI_NONE; trustData.fdwRevocationChecks = WTD_STATEACTION_VERIFY; trustData.dwUnionChoice = WTD_CHOICE_CATALOG; trustData.dwStateAction = WTD_STATEACTION_VERIFY; trustData.pCatalog = &catalogInfo; if (WindowsVersion >= WINDOWS_VISTA) trustData.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL; else trustData.dwProvFlags |= WTD_REVOCATION_CHECK_NONE; status = WinVerifyTrust_I(NULL, &driverActionVerify, &trustData); if (SignerName) { if (status != TRUST_E_NOSIGNATURE) *SignerName = PhpGetSignerNameFromStateData(trustData.hWVTStateData); else *SignerName = NULL; } // Close the state data. trustData.dwStateAction = WTD_STATEACTION_CLOSE; WinVerifyTrust_I(NULL, &driverActionVerify, &trustData); } CryptCATAdminReleaseCatalogContext(catAdminHandle, catInfoHandle, 0); } PhFree(fileHashTag); CryptCATAdminReleaseContext(catAdminHandle, 0); return PhpStatusToVerifyResult(status); }
NTSTATUS UpdateDownloadThread( _In_ PVOID Parameter ) { BOOLEAN downloadSuccess = FALSE; BOOLEAN hashSuccess = FALSE; BOOLEAN signatureSuccess = FALSE; HANDLE tempFileHandle = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING downloadHostPath = NULL; PPH_STRING downloadUrlPath = NULL; PUPDATER_HASH_CONTEXT hashContext = NULL; USHORT httpPort = 0; LARGE_INTEGER timeNow; LARGE_INTEGER timeStart; ULONG64 timeTicks = 0; ULONG64 timeBitsPerSecond = 0; PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)Parameter; SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Initializing download request..."); if (!PhHttpSocketParseUrl( context->SetupFileDownloadUrl, &downloadHostPath, &downloadUrlPath, &httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Create the local path string. context->SetupFilePath = UpdaterParseDownloadFileName(downloadUrlPath); if (PhIsNullOrEmptyString(context->SetupFilePath)) goto CleanupExit; // Create temporary output file. if (!NT_SUCCESS(PhCreateFileWin32( &tempFileHandle, PhGetString(context->SetupFilePath), FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Connecting..."); if (!PhHttpSocketCreate(&httpContext, NULL)) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, PhGetString(downloadHostPath), httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, PhGetString(downloadUrlPath), PH_HTTP_FLAG_REFRESH | (httpPort == PH_HTTP_DEFAULT_HTTPS_PORT ? PH_HTTP_FLAG_SECURE : 0) )) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Sending download request..."); if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Waiting for response..."); if (!PhHttpSocketEndRequest(httpContext)) { context->ErrorCode = GetLastError(); goto CleanupExit; } else { ULONG bytesDownloaded = 0; ULONG downloadedBytes = 0; ULONG contentLength = 0; PPH_STRING status; IO_STATUS_BLOCK isb; BYTE buffer[PAGE_SIZE]; status = PhFormatString(L"Downloading update %s...", PhGetStringOrEmpty(context->Version)); SendMessage(context->DialogHandle, TDM_SET_MARQUEE_PROGRESS_BAR, FALSE, 0); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)status->Buffer); PhDereferenceObject(status); if (!PhHttpSocketQueryHeaderUlong( httpContext, PH_HTTP_QUERY_CONTENT_LENGTH, &contentLength )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Initialize hash algorithm. if (!(hashContext = UpdaterInitializeHash())) goto CleanupExit; // Zero the buffer. memset(buffer, 0, PAGE_SIZE); // Start the clock. PhQuerySystemTime(&timeStart); // Download the data. while (PhHttpSocketReadData(httpContext, buffer, PAGE_SIZE, &bytesDownloaded)) { // If we get zero bytes, the file was uploaded or there was an error if (bytesDownloaded == 0) break; // If the dialog was closed, just cleanup and exit if (!UpdateDialogThreadHandle) goto CleanupExit; // Update the hash of bytes we downloaded. UpdaterUpdateHash(hashContext, buffer, bytesDownloaded); // Write the downloaded bytes to disk. if (!NT_SUCCESS(NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesDownloaded, NULL, NULL ))) { goto CleanupExit; } downloadedBytes += (DWORD)isb.Information; // Check the number of bytes written are the same we downloaded. if (bytesDownloaded != isb.Information) goto CleanupExit; // Query the current time PhQuerySystemTime(&timeNow); // Calculate the number of ticks timeTicks = (timeNow.QuadPart - timeStart.QuadPart) / PH_TICKS_PER_SEC; timeBitsPerSecond = downloadedBytes / __max(timeTicks, 1); // TODO: Update on timer callback. { FLOAT percent = ((FLOAT)downloadedBytes / contentLength * 100); PPH_STRING totalLength = PhFormatSize(contentLength, -1); PPH_STRING totalDownloaded = PhFormatSize(downloadedBytes, -1); PPH_STRING totalSpeed = PhFormatSize(timeBitsPerSecond, -1); PPH_STRING statusMessage = PhFormatString( L"Downloaded: %s of %s (%.0f%%)\r\nSpeed: %s/s", PhGetStringOrEmpty(totalDownloaded), PhGetStringOrEmpty(totalLength), percent, PhGetStringOrEmpty(totalSpeed) ); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_CONTENT, (LPARAM)statusMessage->Buffer); SendMessage(context->DialogHandle, TDM_SET_PROGRESS_BAR_POS, (WPARAM)percent, 0); PhDereferenceObject(statusMessage); PhDereferenceObject(totalSpeed); PhDereferenceObject(totalLength); PhDereferenceObject(totalDownloaded); } } if (UpdaterVerifyHash(hashContext, context->SetupFileHash)) { hashSuccess = TRUE; } if (UpdaterVerifySignature(hashContext, context->SetupFileSignature)) { signatureSuccess = TRUE; } if (hashSuccess && signatureSuccess) { downloadSuccess = TRUE; } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (hashContext) UpdaterDestroyHash(hashContext); if (tempFileHandle) NtClose(tempFileHandle); if (downloadHostPath) PhDereferenceObject(downloadHostPath); if (downloadUrlPath) PhDereferenceObject(downloadUrlPath); if (UpdateDialogThreadHandle) { if (downloadSuccess && hashSuccess && signatureSuccess) { ShowUpdateInstallDialog(context); } else if (downloadSuccess) { if (signatureSuccess) ShowUpdateFailedDialog(context, TRUE, FALSE); else if (hashSuccess) ShowUpdateFailedDialog(context, FALSE, TRUE); else ShowUpdateFailedDialog(context, FALSE, FALSE); } else { ShowUpdateFailedDialog(context, FALSE, FALSE); } } PhDereferenceObject(context); return STATUS_SUCCESS; }
NTSTATUS PhSaveSettings( _In_ PWSTR FileName ) { NTSTATUS status; HANDLE fileHandle; mxml_node_t *topNode; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_SETTING setting; topNode = mxmlNewElement(MXML_NO_PARENT, "settings"); PhAcquireQueuedLockShared(&PhSettingsLock); PhBeginEnumHashtable(PhSettingsHashtable, &enumContext); while (setting = PhNextEnumHashtable(&enumContext)) { PPH_STRING settingValue; settingValue = PhpSettingToString(setting->Type, setting); PhpCreateSettingElement(topNode, &setting->Name, &settingValue->sr); PhDereferenceObject(settingValue); } // Write the ignored settings. { ULONG i; for (i = 0; i < PhIgnoredSettings->Count; i++) { PPH_STRING settingValue; setting = PhIgnoredSettings->Items[i]; settingValue = setting->u.Pointer; PhpCreateSettingElement(topNode, &setting->Name, &settingValue->sr); } } PhReleaseQueuedLockShared(&PhSettingsLock); // Create the directory if it does not exist. { PPH_STRING fullPath; ULONG indexOfFileName; PPH_STRING directoryName; fullPath = PhGetFullPath(FileName, &indexOfFileName); if (fullPath) { if (indexOfFileName != -1) { directoryName = PhSubstring(fullPath, 0, indexOfFileName); //SHCreateDirectoryEx(NULL, directoryName->Buffer, NULL); PhDereferenceObject(directoryName); } PhDereferenceObject(fullPath); } } status = PhCreateFileWin32( &fileHandle, FileName, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { mxmlDelete(topNode); return status; } mxmlSaveFd(topNode, fileHandle, PhpSettingsSaveCallback); mxmlDelete(topNode); NtClose(fileHandle); return STATUS_SUCCESS; }
NTSTATUS PhVerifyFileEx( _In_ PPH_VERIFY_FILE_INFO Information, _Out_ VERIFY_RESULT *VerifyResult, _Out_opt_ PCERT_CONTEXT **Signatures, _Out_opt_ PULONG NumberOfSignatures ) { NTSTATUS status; HANDLE fileHandle; VERIFY_RESULT verifyResult; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; WINTRUST_FILE_INFO fileInfo = { 0 }; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { PhpVerifyInitialization(); PhEndInitOnce(&PhpVerifyInitOnce); } // Make sure we have successfully imported // the required functions. if ( !CryptCATAdminCalcHashFromFileHandle || !CryptCATAdminAcquireContext || !CryptCATAdminEnumCatalogFromHash || !CryptCATCatalogInfoFromContext || !CryptCATAdminReleaseCatalogContext || !CryptCATAdminReleaseContext || !WinVerifyTrust_I || !WTHelperProvDataFromStateData_I || !WTHelperGetProvSignerFromChain_I || !CertNameToStr_I || !CertDuplicateCertificateContext_I || !CertFreeCertificateContext_I ) return STATUS_NOT_SUPPORTED; if (!NT_SUCCESS(status = PhCreateFileWin32( &fileHandle, Information->FileName, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) return status; fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); fileInfo.pcwszFilePath = Information->FileName; fileInfo.hFile = fileHandle; verifyResult = PhpVerifyFile(Information, fileHandle, WTD_CHOICE_FILE, &fileInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures); if (verifyResult == VrNoSignature) { if (CryptCATAdminAcquireContext2 && CryptCATAdminCalcHashFromFileHandle2) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, BCRYPT_SHA256_ALGORITHM, &signatures, &numberOfSignatures); } if (verifyResult != VrTrusted) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, NULL, &signatures, &numberOfSignatures); } } *VerifyResult = verifyResult; if (Signatures) *Signatures = signatures; else PhFreeVerifySignatures(signatures, numberOfSignatures); if (NumberOfSignatures) *NumberOfSignatures = numberOfSignatures; NtClose(fileHandle); return STATUS_SUCCESS; }
VOID ExtractResourceToFile( _In_ PWSTR Resource, _In_ PWSTR FileName ) { HANDLE fileHandle = NULL; ULONG resourceLength; HRSRC resourceHandle = NULL; HGLOBAL resourceData; PVOID resourceBuffer; IO_STATUS_BLOCK isb; if (!(resourceHandle = FindResource(PhInstanceHandle, Resource, RT_RCDATA))) goto CleanupExit; resourceLength = SizeofResource(PhInstanceHandle, resourceHandle); if (!(resourceData = LoadResource(PhInstanceHandle, resourceHandle))) goto CleanupExit; if (!(resourceBuffer = LockResource(resourceData))) goto CleanupExit; if (!NT_SUCCESS(PhCreateFileWin32( &fileHandle, FileName, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { goto CleanupExit; } if (!NT_SUCCESS(NtWriteFile( fileHandle, NULL, NULL, NULL, &isb, resourceBuffer, resourceLength, NULL, NULL ))) { goto CleanupExit; } if (isb.Information != resourceLength) goto CleanupExit; CleanupExit: if (fileHandle) NtClose(fileHandle); if (resourceHandle) FreeResource(resourceHandle); }
static NTSTATUS DownloadUpdateThreadStart( __in PVOID Parameter ) { PPH_STRING downloadUrlPath = NULL; HANDLE tempFileHandle = NULL; HINTERNET hInitialize = NULL, hConnection = NULL, hRequest = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; HWND hwndDlg = (HWND)Parameter; Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), FALSE); SetDlgItemText(hwndDlg, IDC_STATUS, L"Initializing"); // Reset the progress state on Vista and above. if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0L); if (!ConnectionAvailable()) return status; __try { // Get temp dir. WCHAR tempPathString[MAX_PATH]; DWORD tempPathLength = GetTempPath(MAX_PATH, tempPathString); if (tempPathLength == 0 || tempPathLength > MAX_PATH) { LogEvent(hwndDlg, PhFormatString(L"CreateFile failed (%d)", GetLastError())); __leave; } // create the download path string. downloadUrlPath = PhFormatString( L"/projects/processhacker/files/processhacker2/processhacker-%u.%u-setup.exe/download?use_mirror=autoselect", /* ?use_mirror=waix" */ UpdateData.MajorVersion, UpdateData.MinorVersion ); // Append the tempath to our string: %TEMP%processhacker-%u.%u-setup.exe // Example: C:\\Users\\dmex\\AppData\\Temp\\processhacker-2.10-setup.exe SetupFilePath = PhFormatString( L"%sprocesshacker-%u.%u-setup.exe", tempPathString, UpdateData.MajorVersion, UpdateData.MinorVersion ); // Create output file status = PhCreateFileWin32( &tempFileHandle, SetupFilePath->Buffer, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { LogEvent(hwndDlg, PhFormatString(L"PhCreateFileWin32 failed (%s)", ((PPH_STRING)PHA_DEREFERENCE(PhGetNtMessage(status)))->Buffer)); __leave; } { // Create a user agent string. PPH_STRING phVersion = PhGetPhVersion(); PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer); // Initialize the wininet library. if (!(hInitialize = InternetOpen( userAgent->Buffer, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ))) { LogEvent(hwndDlg, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError())); PhDereferenceObject(userAgent); PhDereferenceObject(phVersion); __leave; } PhDereferenceObject(userAgent); PhDereferenceObject(phVersion); } // Connect to the server. if (!(hConnection = InternetConnect( hInitialize, L"sourceforge.net", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0))) { LogEvent(hwndDlg, PhFormatString(L"InternetConnect failed (%d)", GetLastError())); __leave; } // Open the HTTP request. if (!(hRequest = HttpOpenRequest( hConnection, NULL, downloadUrlPath->Buffer, NULL, NULL, NULL, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RESYNCHRONIZE, 0 ))) { LogEvent(hwndDlg, PhFormatString(L"HttpOpenRequest failed (%d)", GetLastError())); __leave; } SetDlgItemText(hwndDlg, IDC_STATUS, L"Connecting"); // Send the HTTP request. if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) { LogEvent(hwndDlg, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError())); // Enable the 'Retry' button. Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); SetDlgItemText(hwndDlg, IDC_DOWNLOAD, L"Retry"); // Reset the state and let user retry the download. PhUpdaterState = Download; } else { BYTE hashBuffer[20]; DWORD contentLengthSize = sizeof(DWORD); PH_HASH_CONTEXT hashContext; // Initialize hash algorithm. PhInitializeHash(&hashContext, Sha1HashAlgorithm); if (!HttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &contentLengthSize, 0)) { // No content length...impossible to calculate % complete... // we can read the data, BUT in this instance Sourceforge always returns the content length // so instead we'll exit here instead of downloading the file. LogEvent(hwndDlg, PhFormatString(L"HttpQueryInfo failed (%d)", GetLastError())); __leave; } else { BYTE buffer[PAGE_SIZE]; DWORD bytesRead = 0, startTick = 0; IO_STATUS_BLOCK isb; // Zero the buffer. ZeroMemory(buffer, PAGE_SIZE); // Reset the counters. bytesDownloaded = 0, timeTransferred = 0, LastUpdateTime = 0; IsUpdating = FALSE; // Start the clock. startTick = GetTickCount(); timeTransferred = startTick; // Download the data. while (InternetReadFile(hRequest, buffer, PAGE_SIZE, &bytesRead)) { // If we get zero bytes, the file was uploaded or there was an error. if (bytesRead == 0) break; // If window closed and thread handle was closed, just dispose and exit. // (This also skips error checking/prompts and updating the disposed UI) if (!DownloadThreadHandle) __leave; // Update the hash of bytes we downloaded. PhUpdateHash(&hashContext, buffer, bytesRead); // Write the downloaded bytes to disk. status = NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesRead, NULL, NULL ); if (!NT_SUCCESS(status)) { PPH_STRING message = PhGetNtMessage(status); LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer)); PhDereferenceObject(message); break; } // Check dwBytesRead are the same dwBytesWritten length returned by WriteFile. if (bytesRead != isb.Information) { PPH_STRING message = PhGetNtMessage(status); LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer)); PhDereferenceObject(message); break; } // Update our total bytes downloaded PhAcquireQueuedLockExclusive(&Lock); bytesDownloaded += (DWORD)isb.Information; PhReleaseQueuedLockExclusive(&Lock); AsyncUpdate(); } // Check if we downloaded the entire file. assert(bytesDownloaded == contentLength); // Compute our hash result. if (PhFinalHash(&hashContext, &hashBuffer, 20, NULL)) { // Allocate our hash string, hex the final hash result in our hashBuffer. PPH_STRING hexString = PhBufferToHexString(hashBuffer, 20); if (PhEqualString(hexString, UpdateData.Hash, TRUE)) { // If PH is not elevated, set the UAC shield for the install button as the setup requires elevation. if (!PhElevated) SendMessage(GetDlgItem(hwndDlg, IDC_DOWNLOAD), BCM_SETSHIELD, 0, TRUE); // Set the download result, don't include hash status since it succeeded. //SetDlgItemText(hwndDlg, IDC_STATUS, L"Download Complete"); // Set button text for next action Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Install"); // Enable the Install button Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); // Hash succeeded, set state as ready to install. PhUpdaterState = Install; } else { if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L); SetDlgItemText(hwndDlg, IDC_STATUS, L"Download complete, SHA1 Hash failed."); // Set button text for next action Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry"); // Enable the Install button Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); // Hash failed, reset state to downloading so user can redownload the file. PhUpdaterState = Download; } PhDereferenceObject(hexString); } else { //SetDlgItemText(hwndDlg, IDC_STATUS, L"PhFinalHash failed"); // Show fancy Red progressbar if hash failed on Vista and above. if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L); } } } status = STATUS_SUCCESS; } __finally { if (hInitialize) { InternetCloseHandle(hInitialize); hInitialize = NULL; } if (hConnection) { InternetCloseHandle(hConnection); hConnection = NULL; } if (hRequest) { InternetCloseHandle(hRequest); hRequest = NULL; } if (tempFileHandle) { NtClose(tempFileHandle); tempFileHandle = NULL; } if (downloadUrlPath) { PhDereferenceObject(downloadUrlPath); downloadUrlPath = NULL; } } return status; }
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)) { // Create the handle to the network device 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) { // Check the network adapter supports the OIDs we're going to be using. if (!NetworkAdapterQuerySupported(context->DeviceHandle)) { // Device is faulty. Close the handle so we can fallback to GetIfEntry. NtClose(context->DeviceHandle); context->DeviceHandle = NULL; } } } PhInitializeCircularBuffer_ULONG64(&context->InboundBuffer, PhGetIntegerSetting(L"SampleCount")); PhInitializeCircularBuffer_ULONG64(&context->OutboundBuffer, PhGetIntegerSetting(L"SampleCount")); } return TRUE; case SysInfoDestroy: { PhDeleteCircularBuffer_ULONG64(&context->InboundBuffer); PhDeleteCircularBuffer_ULONG64(&context->OutboundBuffer); if (context->AdapterName) PhDereferenceObject(context->AdapterName); if (context->DeviceHandle) NtClose(context->DeviceHandle); PhFree(context); } return TRUE; case SysInfoTick: { ULONG64 networkInOctets = 0; ULONG64 networkOutOctets = 0; ULONG64 networkRcvSpeed = 0; ULONG64 networkXmitSpeed = 0; //ULONG64 networkLinkSpeed = 0; if (context->DeviceHandle) { NDIS_STATISTICS_INFO interfaceStats; //NDIS_LINK_STATE interfaceState; if (NT_SUCCESS(NetworkAdapterQueryStatistics(context->DeviceHandle, &interfaceStats))) { if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV)) networkInOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_RCV); else networkInOctets = interfaceStats.ifHCInOctets; if (!(interfaceStats.SupportedStatistics & NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT)) networkOutOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_XMIT); else networkOutOctets = interfaceStats.ifHCOutOctets; networkRcvSpeed = networkInOctets - context->LastInboundValue; networkXmitSpeed = networkOutOctets - context->LastOutboundValue; } else { networkInOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_RCV); networkOutOctets = NetworkAdapterQueryValue(context->DeviceHandle, OID_GEN_BYTES_XMIT); networkRcvSpeed = networkInOctets - context->LastInboundValue; networkXmitSpeed = networkOutOctets - context->LastOutboundValue; } //if (NT_SUCCESS(NetworkAdapterQueryLinkState(context->DeviceHandle, &interfaceState))) //{ // networkLinkSpeed = interfaceState.XmitLinkSpeed; //} //else //{ // NetworkAdapterQueryLinkSpeed(context->DeviceHandle, &networkLinkSpeed); //} // 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 (GetIfEntry2_I) { MIB_IF_ROW2 interfaceRow; interfaceRow = QueryInterfaceRowVista(context->AdapterEntry); networkInOctets = interfaceRow.InOctets; networkOutOctets = interfaceRow.OutOctets; networkRcvSpeed = networkInOctets - context->LastInboundValue; networkXmitSpeed = networkOutOctets - context->LastOutboundValue; //networkLinkSpeed = interfaceRow.TransmitLinkSpeed; // 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->AdapterEntry); networkInOctets = interfaceRow.dwInOctets; networkOutOctets = interfaceRow.dwOutOctets; networkRcvSpeed = networkInOctets - context->LastInboundValue; networkXmitSpeed = networkOutOctets - context->LastOutboundValue; //networkLinkSpeed = interfaceRow.dwSpeed; // HACK: Pull the Adapter name from the current query. if (context->SysinfoSection->Name.Length == 0) { if (context->AdapterName = PhConvertMultiByteToUtf16(interfaceRow.bDescr)) { context->SysinfoSection->Name = context->AdapterName->sr; } } } if (!context->HaveFirstSample) { networkRcvSpeed = 0; networkXmitSpeed = 0; context->HaveFirstSample = TRUE; } PhAddItemCircularBuffer_ULONG64(&context->InboundBuffer, networkRcvSpeed); PhAddItemCircularBuffer_ULONG64(&context->OutboundBuffer, networkXmitSpeed); //context->LinkSpeed = networkLinkSpeed; context->InboundValue = networkRcvSpeed; context->OutboundValue = networkXmitSpeed; context->LastInboundValue = networkInOctets; context->LastOutboundValue = networkOutOctets; } 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"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite")); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, context->InboundBuffer.Count); if (!Section->GraphState.Valid) { FLOAT max = 0; for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { FLOAT data1; FLOAT data2; Section->GraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->InboundBuffer, i); Section->GraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->OutboundBuffer, i); if (max < data1 + data2) max = data1 + data2; } // Minimum scaling of 1 MB. //if (max < 1024 * 1024) // max = 1024 * 1024; // Scale the data. PhDivideSinglesBySingle( Section->GraphState.Data1, max, drawInfo->LineDataCount ); // Scale the data. PhDivideSinglesBySingle( Section->GraphState.Data2, max, 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 ); PhMoveReference(&Section->GraphState.TooltipText, PhFormatString( L"R: %s\nS: %s\n%s", PhaFormatSize(adapterInboundValue, -1)->Buffer, PhaFormatSize(adapterOutboundValue, -1)->Buffer, ((PPH_STRING)PhAutoDereferenceObject(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; }
NTSTATUS PhMapViewOfEntireFile( _In_opt_ PWSTR FileName, _In_opt_ HANDLE FileHandle, _In_ BOOLEAN ReadOnly, _Out_ PVOID *ViewBase, _Out_ PSIZE_T Size ) { NTSTATUS status; BOOLEAN openedFile = FALSE; LARGE_INTEGER size; HANDLE sectionHandle = NULL; SIZE_T viewSize; PVOID viewBase; if (!FileName && !FileHandle) return STATUS_INVALID_PARAMETER_MIX; // Open the file if we weren't supplied a file handle. if (!FileHandle) { status = PhCreateFileWin32( &FileHandle, FileName, ((FILE_EXECUTE | FILE_READ_ATTRIBUTES | FILE_READ_DATA) | (!ReadOnly ? (FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA) : 0)) | SYNCHRONIZE, 0, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; openedFile = TRUE; } // Get the file size and create the section. status = PhGetFileSize(FileHandle, &size); if (!NT_SUCCESS(status)) goto CleanupExit; status = NtCreateSection( §ionHandle, SECTION_ALL_ACCESS, NULL, &size, ReadOnly ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE, SEC_COMMIT, FileHandle ); if (!NT_SUCCESS(status)) goto CleanupExit; // Map the section. viewSize = (SIZE_T)size.QuadPart; viewBase = NULL; status = NtMapViewOfSection( sectionHandle, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, ReadOnly ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE ); if (!NT_SUCCESS(status)) goto CleanupExit; *ViewBase = viewBase; *Size = (SIZE_T)size.QuadPart; CleanupExit: if (sectionHandle) NtClose(sectionHandle); if (openedFile) NtClose(FileHandle); return status; }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // Handle load errors. // In certain startup modes we want to ignore all plugin load errors. if (LoadErrors && LoadErrors->Count != 0 && !PhStartupParameters.PhSvc) { PH_STRING_BUILDER sb; ULONG i; PPHP_PLUGIN_LOAD_ERROR loadError; PPH_STRING baseName; PhInitializeStringBuilder(&sb, 100); PhAppendStringBuilder2(&sb, L"Unable to load the following plugin(s):\n\n"); for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhAppendFormatStringBuilder(&sb, L"%s: %s\n", baseName->Buffer, PhGetStringOrDefault(loadError->ErrorMessage, L"An unknown error occurred.")); PhDereferenceObject(baseName); } PhAppendStringBuilder2(&sb, L"\nDo you want to disable the above plugin(s)?"); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, sb.String->Buffer ) == IDYES) { ULONG i; for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhSetPluginDisabled(&baseName->sr, TRUE); PhDereferenceObject(baseName); } } PhDeleteStringBuilder(&sb); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad, TRUE); }