Introduce UsbDk API definitions and binding code. UsbDk API DLL is loaded dynamically and wrapped by a thin glue code layer. This approach was chosen in order to make spice-gtk functional without UsbDk installed. Next patches will introduce dynamic backend selection logic, i.e. spice-gtk will try to use UsbDk by default and fallback to the old WinUsb/usbclerk scheme in case UsbDk is not available. Signed-off-by: Kirill Moizik <kirillm@xxxxxxxxxx> Signed-off-by: Dmitry Fleytman <dmitry@xxxxxxxxxx> --- src/Makefile.am | 2 + src/usbdk_api.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/usbdk_api.h | 34 +++++++++++ 3 files changed, 223 insertions(+) create mode 100644 src/usbdk_api.c create mode 100644 src/usbdk_api.h diff --git a/src/Makefile.am b/src/Makefile.am index 37b89fe..f447ecb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -370,6 +370,8 @@ WIN_USB_FILES= \ win-usb-clerk.h \ win-usb-driver-install.h \ win-usb-driver-install.c \ + usbdk_api.h \ + usbdk_api.c \ $(NULL) if OS_WIN32 diff --git a/src/usbdk_api.c b/src/usbdk_api.c new file mode 100644 index 0000000..f5009e5 --- /dev/null +++ b/src/usbdk_api.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + + Authors: + Dmitry Fleytman <dmitry@xxxxxxxxxx> + Kirill Moizik <kirill@xxxxxxxxxx> +*/ +#include <config.h> + +#include <windows.h> +#include <glib-object.h> +#include "usbdk_api.h" +#include "channel-usbredir-priv.h" + +#define USB_DK_HIDE_RULE_MATCH_ALL ((ULONG64)(-1)) +typedef struct tag_USB_DK_HIDE_RULE +{ + ULONG64 Hide; + ULONG64 Class; + ULONG64 VID; + ULONG64 PID; + ULONG64 BCD; +} USB_DK_HIDE_RULE, *PUSB_DK_HIDE_RULE; + +typedef HANDLE(__cdecl *USBDK_CREATEHIDERHANDLE)(void); +typedef BOOL(__cdecl * USBDK_ADDHIDERULE)(HANDLE hider_handle, PUSB_DK_HIDE_RULE rule); +typedef BOOL(__cdecl *USBDK_CLEARHIDERULES)(HANDLE hider_handle); +typedef void(__cdecl *USBDK_CLOSEHIDERHANDLE)(HANDLE hider_handle); + +struct tag_usbdk_api_wrapper +{ + HMODULE module; + USBDK_CREATEHIDERHANDLE CreateHiderHandle; + USBDK_ADDHIDERULE AddRule; + USBDK_CLEARHIDERULES ClearRules; + USBDK_CLOSEHIDERHANDLE CloseHiderHandle; +}; + +BOOL usbdk_is_driver_installed(void) +{ + gboolean usbdk_installed = FALSE; + SC_HANDLE managerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + + if (managerHandle) { + SC_HANDLE serviceHandle = OpenService(managerHandle, TEXT("UsbDk"), GENERIC_READ); + + if (serviceHandle) { + SPICE_DEBUG("UsbDk driver is installed."); + usbdk_installed = TRUE; + CloseServiceHandle(serviceHandle); + } + CloseServiceHandle(managerHandle); + } + return usbdk_installed; +} + +void usbdk_api_unload(usbdk_api_wrapper *usbdk_api) +{ + if (usbdk_api != NULL) { + if (usbdk_api->module != NULL) { + SPICE_DEBUG("Unloading UsbDk API DLL"); + FreeLibrary(usbdk_api->module); + } + g_free(usbdk_api); + } +} + +usbdk_api_wrapper *usbdk_api_load(void) +{ + usbdk_api_wrapper *usbdk_api = g_new0(usbdk_api_wrapper, 1); + + SPICE_DEBUG("Loading UsbDk API DLL"); + usbdk_api->module = LoadLibraryA("UsbDkHelper"); + if (usbdk_api->module == NULL) { + g_warning("Failed to load UsbDkHelper.dll, error %lu", GetLastError()); + goto error_unload; + } + + usbdk_api->CreateHiderHandle = (USBDK_CREATEHIDERHANDLE) + GetProcAddress(usbdk_api->module, "UsbDk_CreateHiderHandle"); + if (usbdk_api->CreateHiderHandle == NULL) { + g_warning("Failed to find CreateHandle entry point"); + goto error_unload; + } + + usbdk_api->AddRule = (USBDK_ADDHIDERULE) + GetProcAddress(usbdk_api->module, "UsbDk_AddHideRule"); + if (usbdk_api->AddRule == NULL) { + g_warning("Failed to find AddRule entry point"); + goto error_unload; + } + + usbdk_api->ClearRules = (USBDK_CLEARHIDERULES) + GetProcAddress(usbdk_api->module, "UsbDk_ClearHideRules"); + if (usbdk_api->ClearRules == NULL) { + g_warning("Failed to find ClearRules entry point"); + goto error_unload; + } + + usbdk_api->CloseHiderHandle = (USBDK_CLOSEHIDERHANDLE) + GetProcAddress(usbdk_api->module, "UsbDk_CloseHiderHandle"); + if (usbdk_api->CloseHiderHandle == NULL) { + g_warning("Failed to find CloseHiderHandle entry point"); + goto error_unload; + } + return usbdk_api; + +error_unload: + usbdk_api_unload(usbdk_api); + return NULL; +} + +static uint64_t usbdk_usbredir_field_to_usbdk(int value) +{ + if (value >= 0) { + return value; + } + + g_warn_if_fail(value == -1); + + return USB_DK_HIDE_RULE_MATCH_ALL; +} + +static BOOL usbdk_add_hide_rule(usbdk_api_wrapper *usbdk_api, + HANDLE hider_handle, + PUSB_DK_HIDE_RULE rule) +{ + return usbdk_api->AddRule(hider_handle, rule); +} + +void usbdk_api_set_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle, + gchar *redirect_on_connect) +{ + struct usbredirfilter_rule *rules; + int r, count; + + r = usbredirfilter_string_to_rules(redirect_on_connect, ",", "|", + &rules, &count); + if (r) { + g_warning("auto-connect rules parsing failed with error %d", r); + return; + } + + for (int i = 0; i < count; i++) { + USB_DK_HIDE_RULE rule; + rule.Hide = usbdk_usbredir_field_to_usbdk(rules[i].allow); + rule.Class = usbdk_usbredir_field_to_usbdk(rules[i].device_class); + rule.VID = usbdk_usbredir_field_to_usbdk(rules[i].vendor_id); + rule.PID = usbdk_usbredir_field_to_usbdk(rules[i].product_id); + rule.BCD = usbdk_usbredir_field_to_usbdk(rules[i].device_version_bcd); + if (!usbdk_add_hide_rule(usbdk_api, hider_handle, &rule)) { + SPICE_DEBUG("UsbDk add hide rule API failed"); + } + } + + free(rules); +} + +HANDLE usbdk_create_hider_handle(usbdk_api_wrapper *usbdk_api) +{ + HANDLE handle = usbdk_api->CreateHiderHandle(); + return (handle == INVALID_HANDLE_VALUE) ? NULL : handle; +} + +BOOL usbdk_clear_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle) +{ + return usbdk_api->ClearRules(hider_handle); +} + +void usbdk_close_hider_handle(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle) +{ + return usbdk_api->CloseHiderHandle(hider_handle); +} diff --git a/src/usbdk_api.h b/src/usbdk_api.h new file mode 100644 index 0000000..8e5406c --- /dev/null +++ b/src/usbdk_api.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2014-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + + Authors: + Dmitry Fleytman <dmitry@xxxxxxxxxx> + Kirill Moizik <kirill@xxxxxxxxxx> +*/ +#ifndef USBDK_HEADER +#define USBDK_HEADER + +typedef struct tag_usbdk_api_wrapper usbdk_api_wrapper; + +usbdk_api_wrapper *usbdk_api_load(void); +void usbdk_api_unload(usbdk_api_wrapper *usbdk_api); +BOOL usbdk_is_driver_installed(void); +HANDLE usbdk_create_hider_handle(usbdk_api_wrapper *usbdk_api); +void usbdk_api_set_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle, gchar *redirect_on_connect); +BOOL usbdk_clear_hide_rules(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle); +void usbdk_close_hider_handle(usbdk_api_wrapper *usbdk_api, HANDLE hider_handle); +#endif -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel