120 lines
5.4 KiB
C
120 lines
5.4 KiB
C
#include "setupapi_.h"
|
|
|
|
FAKE_DEVICE* fake_devices = NULL;
|
|
|
|
BOOL add_fake_device(const GUID* guid, const WCHAR* path) {
|
|
FAKE_DEVICE* new_device = (FAKE_DEVICE*)malloc(sizeof *new_device);
|
|
if (!new_device) return FALSE;
|
|
new_device->guid = guid;
|
|
new_device->path = path;
|
|
new_device->handle = NULL;
|
|
new_device->next = NULL;
|
|
FAKE_DEVICE** tail = &fake_devices;
|
|
while (*tail) tail = &((*tail)->next);
|
|
*tail = new_device;
|
|
return TRUE;
|
|
}
|
|
|
|
HDEVINFO WINAPI FakeSetupDiGetClassDevsA(const GUID* ClassGuid, PCWSTR Enumerator, HWND hwndParent, DWORD Flags) {
|
|
log_misc(plfSetupAPI, "SetupDiGetClassDevsA(%p, %s, %d, %d)", ClassGuid, Enumerator, hwndParent, Flags);
|
|
HDEVINFO res = TrueSetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
|
|
|
|
if (res != INVALID_HANDLE_VALUE && ClassGuid != NULL) {
|
|
FAKE_DEVICE* device = fake_devices;
|
|
while (device != NULL) {
|
|
if (memcmp(device->guid, ClassGuid, sizeof(*ClassGuid)) == 0) {
|
|
log_misc(plfSetupAPI, "injecting %ls into class devs list", device->path);
|
|
device->handle = res;
|
|
}
|
|
device = device->next;
|
|
}
|
|
} else {
|
|
log_warning(plfSetupAPI, "upstream SetupDiGetClassDevsA failed: %d", GetLastError());
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
BOOL WINAPI FakeSetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData,
|
|
const GUID* InterfaceClassGuid, DWORD MemberIndex,
|
|
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) {
|
|
log_misc(plfSetupAPI, "SetupDiEnumDeviceInterfaces");
|
|
FAKE_DEVICE* device = fake_devices;
|
|
if (DeviceInterfaceData) {
|
|
while (device != NULL) {
|
|
if (device->handle == DeviceInfoSet) {
|
|
log_misc(plfSetupAPI, "hooking fake device: %ls", device->path);
|
|
memcpy(&DeviceInterfaceData->InterfaceClassGuid, device->guid, sizeof *device->guid);
|
|
DeviceInterfaceData->Flags = SPINT_ACTIVE;
|
|
DeviceInterfaceData->Reserved = (ULONG_PTR)device->path;
|
|
SetLastError(ERROR_SUCCESS);
|
|
return TRUE;
|
|
}
|
|
device = device->next;
|
|
}
|
|
}
|
|
|
|
// Fallback
|
|
log_misc(plfSetupAPI, "device info fallthrough");
|
|
return TrueSetupDiEnumDeviceInterfaces(DeviceInfoSet, DeviceInfoData, InterfaceClassGuid, MemberIndex,
|
|
DeviceInterfaceData);
|
|
}
|
|
|
|
BOOL WINAPI FakeSetupDiGetDeviceInterfaceDetailA(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
|
|
PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
|
|
DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize,
|
|
PSP_DEVINFO_DATA DeviceInfoData) {
|
|
log_misc(plfSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
|
|
FAKE_DEVICE* device = fake_devices;
|
|
while (device != NULL) {
|
|
if (device->handle == DeviceInfoSet && (ULONG_PTR)device->path == DeviceInterfaceData->Reserved) {
|
|
log_misc(plfSetupAPI, "Intercepted SetupDiGetDeviceInterfaceDetailA");
|
|
|
|
const WCHAR* res = (WCHAR*)DeviceInterfaceData->Reserved;
|
|
int new_len = (wcslen(res) + 1) * (sizeof *res);
|
|
char* new_res = (char*)malloc(new_len);
|
|
size_t convertedChars = 0;
|
|
wcstombs_s(&convertedChars, new_res, new_len, res, _TRUNCATE);
|
|
|
|
size_t len = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + convertedChars;
|
|
if (RequiredSize) *RequiredSize = len;
|
|
if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize < len) {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
if (!DeviceInterfaceDetailData || sizeof *DeviceInterfaceDetailData != DeviceInterfaceDetailData->cbSize) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
memcpy(DeviceInterfaceDetailData->DevicePath, new_res, len);
|
|
free(new_res);
|
|
SetLastError(ERROR_SUCCESS);
|
|
return TRUE;
|
|
}
|
|
device = device->next;
|
|
}
|
|
|
|
log_misc(plfSetupAPI, "TrueSetupDiGetDeviceInterfaceDetailA fallthrough");
|
|
return TrueSetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, DeviceInterfaceData, DeviceInterfaceDetailData,
|
|
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
|
}
|
|
|
|
BOOL WINAPI FakeSetupDiDestroyDeviceInfoList(HDEVINFO DevicesInfoSet) {
|
|
FAKE_DEVICE* device = fake_devices;
|
|
while (device != NULL) {
|
|
if (device->handle == DevicesInfoSet) device->handle = NULL;
|
|
device = device->next;
|
|
}
|
|
return TrueSetupDiDestroyDeviceInfoList(DevicesInfoSet);
|
|
}
|
|
|
|
void hook_setupapi() {
|
|
hook("Setupapi.DLL", "SetupDiGetClassDevsA", FakeSetupDiGetClassDevsA, (void**)&TrueSetupDiGetClassDevsA);
|
|
hook("Setupapi.DLL", "SetupDiEnumDeviceInterfaces", FakeSetupDiEnumDeviceInterfaces,
|
|
(void**)&TrueSetupDiEnumDeviceInterfaces);
|
|
hook("Setupapi.DLL", "SetupDiGetDeviceInterfaceDetailA", FakeSetupDiGetDeviceInterfaceDetailA,
|
|
(void**)&TrueSetupDiGetDeviceInterfaceDetailA);
|
|
hook("Setupapi.DLL", "SetupDiDestroyDeviceInfoList", FakeSetupDiDestroyDeviceInfoList,
|
|
(void**)&TrueSetupDiDestroyDeviceInfoList);
|
|
}
|