#include #include #include #include #include #include #include "hook/iohook.h" #include "util/dprintf.h" #include "ri/ri.h" static HWND ri_hwnd; static WNDCLASSEX ri_wndclass; static HANDLE selected_ri_dev = (HANDLE)-1; static uintptr_t ri_thread; LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam); static unsigned int __stdcall ri_thread_proc(void *ctx); HRESULT ri_init(uint8_t dev_num) { wchar_t ri_dev_name[MAX_PATH] = L"\0"; wchar_t hid_prod_name[MAX_PATH] = L"\0"; UINT num_ri_devs = 0; UINT len_ri_dev_name = 0; DWORD err = 0; PRAWINPUTDEVICELIST ri_devs = NULL; if (GetRawInputDeviceList(NULL, &num_ri_devs, sizeof(RAWINPUTDEVICELIST)) != 0) { err = GetLastError(); dprintf("RawInput: GetRawInputDeviceList failed to get number of devices %08lX\n", err); return E_FAIL; } ri_devs = malloc(sizeof(RAWINPUTDEVICELIST) * num_ri_devs); GetRawInputDeviceList(ri_devs, &num_ri_devs, sizeof(RAWINPUTDEVICELIST)); if (num_ri_devs <= 0) { err = GetLastError(); dprintf("RawInput: GetRawInputDeviceList failed to get devices info %08lX\n", err); free(ri_devs); return E_FAIL; } dprintf("RawInput: Raw Input device list (%d devices):\n", num_ri_devs); for (int i = 0; i < num_ri_devs; i++) { len_ri_dev_name = 0; if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, NULL, &len_ri_dev_name) != 0) { dprintf("RawInput: GetRawInputDeviceInfoW #%d failed to get name size\n", i); break; } if (len_ri_dev_name <= 0) { dprintf("RawInput: GetRawInputDeviceInfoW #%d len_ri_dev_name <= 0\n", i); break; } if (len_ri_dev_name >= MAX_PATH) { dprintf("\tDev #%d - (name too long, %d characters)\n", i, len_ri_dev_name); continue; } if (GetRawInputDeviceInfoW(ri_devs[i].hDevice, RIDI_DEVICENAME, ri_dev_name, &len_ri_dev_name) <= 0) { dprintf("RawInput: GetRawInputDeviceInfoW #%d failed to get name\n", i); break; } HANDLE hiddev = CreateFileW(ri_dev_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hiddev == NULL) { dprintf("RawInput: CreateFileW failed on dev #%d for device %ls\n", i, ri_dev_name); continue; } if (!HidD_GetProductString(hiddev, hid_prod_name, MAX_PATH)) { //dprintf("RawInput: HidD_GetProductString failed on dev #%d for device %ls\n", i, ri_dev_name); continue; } dprintf("\tDev #%d - %ls\n", i, hid_prod_name); } selected_ri_dev = ri_devs[dev_num].hDevice; free(ri_devs); ri_wndclass.cbSize = sizeof(WNDCLASSEX); ri_wndclass.hInstance = GetModuleHandle(NULL); ri_wndclass.lpfnWndProc = ri_win_proc; ri_wndclass.lpszClassName = "Taitools Input"; RegisterClassEx(&ri_wndclass); ri_thread = _beginthreadex( NULL, 0, ri_thread_proc, NULL, 0, NULL); return S_OK; } void ri_exit() { if (ri_hwnd) { PostMessage(ri_hwnd, WM_CLOSE, 0, 0); } } static unsigned int __stdcall ri_thread_proc(void *ctx) { dprintf("RawInput: ri_thread_proc begin\n"); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); ri_hwnd = CreateWindowExA(0, ri_wndclass.lpszClassName, "Taitools Input", 0, 0, 0, 0, 0, NULL, NULL, ri_wndclass.hInstance, NULL); RAWINPUTDEVICE Rid[4]; Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC Rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE Rid[0].dwFlags = RIDEV_NOLEGACY; // adds mouse and also ignores legacy mouse messages Rid[0].hwndTarget = ri_hwnd; Rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC Rid[1].usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD Rid[1].dwFlags = RIDEV_NOLEGACY; // adds keyboard and also ignores legacy keyboard messages Rid[1].hwndTarget = ri_hwnd; Rid[2].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC Rid[2].usUsage = 0x05; // HID_USAGE_GENERIC_GAMEPAD Rid[2].dwFlags = 0; // adds game pad Rid[2].hwndTarget = ri_hwnd; Rid[3].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC Rid[3].usUsage = 0x04; // HID_USAGE_GENERIC_JOYSTICK Rid[3].dwFlags = 0; // adds joystick Rid[3].hwndTarget = ri_hwnd; if (!RegisterRawInputDevices(Rid, 4, sizeof(Rid[0]))) { dprintf("RawInput: Failed to register RI devices\n"); return E_FAIL; } MSG msg; while (GetMessage(&msg, ri_hwnd, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } DestroyWindow(ri_hwnd); ri_hwnd = NULL; UnregisterClass(ri_wndclass.lpszClassName, ri_wndclass.hInstance); dprintf("RawInput: ri_thread_proc end\n"); return S_OK; } LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam) { switch (msg) { case WM_INPUT: //dprintf("RawInput: Got input\n"); break; } return DefWindowProc(hWnd, msg, wparam, lParam); }