mirror of
https://gitea.tendokyu.moe/TeamTofuShop/taitools.git
synced 2026-09-25 07:37:54 +03:00
463 lines
13 KiB
C
463 lines
13 KiB
C
#include <windows.h>
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
#include "hook/table.h"
|
|
#include "hook/iohook.h"
|
|
#include "hook/procaddr.h"
|
|
|
|
#include "board/guid.h"
|
|
#include "hooklib/setupapi.h"
|
|
#include "hooklib/winusb.h"
|
|
|
|
#include "util/dprintf.h"
|
|
|
|
static bool winusb_initted;
|
|
static CRITICAL_SECTION winusb_lock;
|
|
static struct winusb_dev *winusb_classes;
|
|
static size_t winusb_nclasses;
|
|
|
|
static void winusb_hook_init();
|
|
static HRESULT winusb_handle_irp(struct irp *irp);
|
|
|
|
BOOL my_WinUsb_QueryPipe(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR AlternateInterfaceNumber,
|
|
UCHAR PipeIndex,
|
|
PWINUSB_PIPE_INFORMATION PipeInformation
|
|
);
|
|
|
|
BOOL my_WinUsb_QueryInterfaceSettings(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR AlternateInterfaceNumber,
|
|
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
|
|
);
|
|
|
|
BOOL my_WinUsb_GetDescriptor(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR DescriptorType,
|
|
UCHAR Index,
|
|
USHORT LanguageID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred
|
|
);
|
|
|
|
BOOL my_WinUsb_WritePipe(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
);
|
|
|
|
BOOL my_WinUsb_QueryDeviceInformation(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
ULONG InformationType,
|
|
PULONG BufferLength,
|
|
PVOID Buffer
|
|
);
|
|
|
|
BOOL my_WinUsb_ReadPipe(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
);
|
|
|
|
BOOL my_WinUsb_Initialize(
|
|
HANDLE DeviceHandle,
|
|
PWINUSB_INTERFACE_HANDLE InterfaceHandle
|
|
);
|
|
|
|
BOOL my_WinUsb_Free(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
|
);
|
|
|
|
BOOL (*next_WinUsb_QueryPipe)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR AlternateInterfaceNumber,
|
|
UCHAR PipeIndex,
|
|
PWINUSB_PIPE_INFORMATION PipeInformation
|
|
);
|
|
|
|
BOOL (*next_WinUsb_QueryInterfaceSettings)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR AlternateInterfaceNumber,
|
|
PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
|
|
);
|
|
|
|
BOOL (*next_WinUsb_GetDescriptor)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR DescriptorType,
|
|
UCHAR Index,
|
|
USHORT LanguageID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred
|
|
);
|
|
|
|
BOOL (*next_WinUsb_WritePipe)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
);
|
|
|
|
BOOL (*next_WinUsb_QueryDeviceInformation)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
ULONG InformationType,
|
|
PULONG BufferLength,
|
|
PVOID Buffer
|
|
);
|
|
|
|
BOOL (*next_WinUsb_ReadPipe)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
);
|
|
|
|
BOOL (*next_WinUsb_Initialize)(
|
|
HANDLE DeviceHandle,
|
|
PWINUSB_INTERFACE_HANDLE InterfaceHandle
|
|
);
|
|
|
|
BOOL (*next_WinUsb_Free)(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle
|
|
);
|
|
|
|
static const struct hook_symbol winusb_syms[] = {
|
|
{
|
|
.name = "WinUsb_QueryPipe",
|
|
.patch = my_WinUsb_QueryPipe,
|
|
.link = (void *) &next_WinUsb_QueryPipe,
|
|
}, {
|
|
.name = "WinUsb_QueryInterfaceSettings",
|
|
.patch = my_WinUsb_QueryInterfaceSettings,
|
|
.link = (void *) &next_WinUsb_QueryInterfaceSettings,
|
|
}, {
|
|
.name = "WinUsb_GetDescriptor",
|
|
.patch = my_WinUsb_GetDescriptor,
|
|
.link = (void *) &next_WinUsb_GetDescriptor,
|
|
}, {
|
|
.name = "WinUsb_WritePipe",
|
|
.patch = my_WinUsb_WritePipe,
|
|
.link = (void *) &next_WinUsb_WritePipe,
|
|
}, {
|
|
.name = "WinUsb_QueryDeviceInformation",
|
|
.patch = my_WinUsb_QueryDeviceInformation,
|
|
.link = (void *) &next_WinUsb_QueryDeviceInformation,
|
|
}, {
|
|
.name = "WinUsb_ReadPipe",
|
|
.patch = my_WinUsb_ReadPipe,
|
|
.link = (void *) &next_WinUsb_ReadPipe,
|
|
}, {
|
|
.name = "WinUsb_Initialize",
|
|
.patch = my_WinUsb_Initialize,
|
|
.link = (void *) &next_WinUsb_Initialize,
|
|
}, {
|
|
.name = "WinUsb_Free",
|
|
.patch = my_WinUsb_Free,
|
|
.link = (void *) &next_WinUsb_Free,
|
|
}
|
|
};
|
|
|
|
HRESULT winusb_add_phantom_dev(const struct winusb_dev *dev)
|
|
{
|
|
//struct winusb_dev *class_;
|
|
struct winusb_dev *new_array;
|
|
HRESULT hr;
|
|
|
|
assert(dev != NULL);
|
|
|
|
winusb_hook_init();
|
|
|
|
EnterCriticalSection(&winusb_lock);
|
|
|
|
new_array = realloc(
|
|
winusb_classes,
|
|
(winusb_nclasses + 1) * sizeof(struct winusb_dev));
|
|
|
|
if (new_array == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto end;
|
|
}
|
|
|
|
winusb_classes = new_array;
|
|
|
|
memcpy_s(&winusb_classes[winusb_nclasses++], sizeof(struct winusb_dev), dev, sizeof(*dev));
|
|
hr = S_OK;
|
|
|
|
setupapi_add_phantom_dev(&usbio_guid, dev->path);
|
|
iohook_push_handler(winusb_handle_irp);
|
|
|
|
dprintf("WinUSB: Init\n");
|
|
|
|
end:
|
|
LeaveCriticalSection(&winusb_lock);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static void winusb_hook_init()
|
|
{
|
|
if (winusb_initted) {
|
|
return;
|
|
}
|
|
|
|
winusb_hook_insert_hooks(NULL);
|
|
|
|
InitializeCriticalSection(&winusb_lock);
|
|
winusb_initted = true;
|
|
}
|
|
|
|
void winusb_hook_insert_hooks(HMODULE target)
|
|
{
|
|
hook_table_apply(
|
|
target,
|
|
"WINUSB.dll",
|
|
winusb_syms,
|
|
_countof(winusb_syms));
|
|
|
|
proc_addr_table_push(
|
|
target,
|
|
"WINUSB.dll",
|
|
winusb_syms,
|
|
_countof(winusb_syms));
|
|
}
|
|
|
|
static HRESULT winusb_handle_irp(struct irp *irp)
|
|
{
|
|
bool found = false;
|
|
if (irp->op != IRP_OP_OPEN && irp->op != IRP_OP_CLOSE) {
|
|
return iohook_invoke_next(irp);
|
|
}
|
|
|
|
if (irp->open_filename == NULL || irp->open_filename[0] == L'\0') {
|
|
return iohook_invoke_next(irp);
|
|
}
|
|
|
|
for (int i = 0; i < winusb_nclasses; i++) {
|
|
if (!wcscmp(irp->open_filename, winusb_classes[i].path)) {
|
|
dprintf("WinUSB: Open/close %ls\n", winusb_classes[i].path);
|
|
irp->fd = winusb_classes[i].fd;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
return iohook_invoke_next(irp);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// FIXME
|
|
int get_winusb_fake_dev_idx(WINUSB_INTERFACE_HANDLE InterfaceHandle)
|
|
{
|
|
for (int i = 0; i < winusb_nclasses; i++) {
|
|
if (winusb_classes[i].fd == InterfaceHandle) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
BOOL my_WinUsb_QueryPipe(WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR AlternateInterfaceNumber, UCHAR PipeIndex, PWINUSB_PIPE_INFORMATION PipeInformation)
|
|
{
|
|
dprintf("WinUSB: my_WinUsb_QueryPipe\n");
|
|
UCHAR this_pipeid = 0;
|
|
|
|
int idx = 0;
|
|
/*int idx = get_winusb_fake_dev_idx(InterfaceHandle);
|
|
if (idx == -1) {
|
|
return next_WinUsb_QueryPipe(InterfaceHandle, AlternateInterfaceNumber, PipeIndex, PipeInformation);
|
|
}*/
|
|
|
|
switch (PipeIndex) {
|
|
case 0: this_pipeid = 0x02; break;
|
|
case 1: this_pipeid = 0x81; break;
|
|
}
|
|
|
|
if (!this_pipeid) {
|
|
return false;
|
|
}
|
|
|
|
PipeInformation->PipeType = UsbdPipeTypeBulk;
|
|
PipeInformation->PipeId = this_pipeid;
|
|
PipeInformation->Interval = 0x00; // never checked?
|
|
PipeInformation->MaximumPacketSize = 0x40; // never checked?
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_QueryInterfaceSettings(WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR AlternateInterfaceNumber, PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor)
|
|
{
|
|
dprintf("WinUSB: my_WinUsb_QueryInterfaceSettings\n");
|
|
int idx = 0;
|
|
/*int idx = get_winusb_fake_dev_idx(InterfaceHandle);
|
|
if (idx == -1) {
|
|
return next_WinUsb_QueryInterfaceSettings(InterfaceHandle, AlternateInterfaceNumber, UsbAltInterfaceDescriptor);
|
|
}*/
|
|
|
|
UsbAltInterfaceDescriptor->bLength = 9;
|
|
UsbAltInterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE;
|
|
UsbAltInterfaceDescriptor->bInterfaceNumber = 0;
|
|
UsbAltInterfaceDescriptor->bAlternateSetting = 0;
|
|
UsbAltInterfaceDescriptor->bNumEndpoints = 2; // nothing else is checked
|
|
UsbAltInterfaceDescriptor->bInterfaceClass = 255;
|
|
UsbAltInterfaceDescriptor->bInterfaceSubClass = 0;
|
|
UsbAltInterfaceDescriptor->bInterfaceProtocol = 0;
|
|
UsbAltInterfaceDescriptor->iInterface = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_GetDescriptor(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR DescriptorType,
|
|
UCHAR Index,
|
|
USHORT LanguageID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred
|
|
)
|
|
{
|
|
int idx = 0;
|
|
/*int idx = get_winusb_fake_dev_idx(InterfaceHandle);
|
|
if (idx == -1) {
|
|
return next_WinUsb_GetDescriptor(
|
|
InterfaceHandle,
|
|
DescriptorType,
|
|
Index,
|
|
LanguageID,
|
|
Buffer,
|
|
BufferLength,
|
|
LengthTransferred
|
|
);
|
|
}*/
|
|
|
|
dprintf("WinUSB: my_WinUsb_GetDescriptor %d\n", idx);
|
|
|
|
if (BufferLength < winusb_classes[idx].descriptor.bLength) {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return false;
|
|
}
|
|
|
|
// Surly this won't explode
|
|
memcpy_s(Buffer, BufferLength, &winusb_classes[idx].descriptor, winusb_classes[(uintptr_t)InterfaceHandle].descriptor.bLength);
|
|
|
|
*LengthTransferred = winusb_classes[idx].descriptor.bLength;
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_WritePipe(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
)
|
|
{
|
|
int idx = 0;
|
|
/*int idx = get_winusb_fake_dev_idx(InterfaceHandle);
|
|
if (idx == -1) {
|
|
return next_WinUsb_WritePipe(
|
|
InterfaceHandle,
|
|
PipeID,
|
|
Buffer,
|
|
BufferLength,
|
|
LengthTransferred,
|
|
Overlapped
|
|
);
|
|
}*/
|
|
#if 0
|
|
dprintf("WritePipe %d\t", (int)BufferLength);
|
|
for (int i = 0; i < BufferLength; i++) {
|
|
dprintf("%02X ", (uint8_t)Buffer[i]);
|
|
}
|
|
dprintf("\n");
|
|
#endif
|
|
winusb_classes[idx].write_pipe(NULL, Buffer, BufferLength, (uint32_t *)LengthTransferred);
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_QueryDeviceInformation(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
ULONG InformationType,
|
|
PULONG BufferLength,
|
|
PVOID Buffer
|
|
)
|
|
{
|
|
//dprintf("WinUSB: my_WinUsb_QueryDeviceInformation\n");
|
|
memset(Buffer, 0x03, 1);
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_ReadPipe(
|
|
WINUSB_INTERFACE_HANDLE InterfaceHandle,
|
|
UCHAR PipeID,
|
|
PUCHAR Buffer,
|
|
ULONG BufferLength,
|
|
PULONG LengthTransferred,
|
|
LPOVERLAPPED Overlapped
|
|
)
|
|
{
|
|
int idx = 0;
|
|
/*int idx = get_winusb_fake_dev_idx(InterfaceHandle);
|
|
if (idx == -1) {
|
|
return next_WinUsb_WritePipe(
|
|
InterfaceHandle,
|
|
PipeID,
|
|
Buffer,
|
|
BufferLength,
|
|
LengthTransferred,
|
|
Overlapped
|
|
);
|
|
}*/
|
|
#if 0
|
|
dprintf("ReadPipe %d\n", (int)BufferLength);
|
|
#endif
|
|
winusb_classes[idx].read_pipe(NULL, Buffer, BufferLength, (uint32_t *)LengthTransferred);
|
|
return true;
|
|
}
|
|
|
|
BOOL my_WinUsb_Initialize(HANDLE DeviceHandle, PWINUSB_INTERFACE_HANDLE InterfaceHandle)
|
|
{
|
|
dprintf("WinUSB: my_WinUsb_Initialize\n");
|
|
for (int i = 0; i < winusb_nclasses; i++) {
|
|
if (winusb_classes[i].fd == DeviceHandle) {
|
|
dprintf("WinUSB: Init %ls\n", winusb_classes[i].path);
|
|
InterfaceHandle = winusb_classes[i].fd;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return next_WinUsb_Initialize(DeviceHandle, InterfaceHandle);
|
|
}
|
|
|
|
BOOL my_WinUsb_Free(WINUSB_INTERFACE_HANDLE InterfaceHandle)
|
|
{
|
|
if (get_winusb_fake_dev_idx(InterfaceHandle) == -1) {
|
|
return next_WinUsb_Free(InterfaceHandle);
|
|
}
|
|
|
|
InterfaceHandle = NULL;
|
|
return true;
|
|
|
|
}
|