From 1f907caf353b98959be4f6babdec1a667b3d6853 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 5 Jun 2017 11:43:40 +0800 Subject: [PATCH] windows: retry open_device() without r/w if it fails Modern Windows implementations don't allow opening HID devices in READ/WRITE mode if they are claimed by the system. Examples of such devices include keyboards and mice. However, these devices can be opened without READ/WRITE permissions, in order to allow sending and receiving feature reports. If open_device() fails, retry without requesting READ/WRITE permissions. This inverts the logic of the parameter to open_device(). It is a refactor of #44 by @pqu. Signed-off-by: Sean Cross --- windows/hid.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/windows/hid.c b/windows/hid.c index 86810d7e..33fbe48c 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -225,10 +225,10 @@ static int lookup_functions() } #endif -static HANDLE open_device(const char *path, BOOL enumerate) +static HANDLE open_device(const char *path, BOOL open_rw) { HANDLE handle; - DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ); + DWORD desired_access = (open_rw)? (GENERIC_WRITE | GENERIC_READ): 0; DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; handle = CreateFileA(path, @@ -370,7 +370,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); /* Open a handle to the device */ - write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); + write_handle = open_device(device_interface_detail_data->DevicePath, FALSE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { @@ -566,13 +566,23 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) dev = new_hid_device(); /* Open a handle to the device */ - dev->device_handle = open_device(path, FALSE); + dev->device_handle = open_device(path, TRUE); /* Check validity of write_handle. */ if (dev->device_handle == INVALID_HANDLE_VALUE) { - /* Unable to open the device. */ - register_error(dev, "CreateFile"); - goto err; + /* System devices, such as keyboards and mice, cannot be opened in + read-write mode, because the system takes exclusive control over + them. This is to prevent keyloggers. However, feature reports + can still be sent and received. Retry opening the device, but + without read/write access. */ + dev->device_handle = open_device(path, FALSE); + + /* Check the validity of the limited device_handle. */ + if (dev->device_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device, even without read-write mode. */ + register_error(dev, "CreateFile"); + goto err; + } } /* Set the Input Report buffer size to 64 reports. */