[Spice-devel] [PATCH v7 03/10] win-usbredir: Introduce UsbDk wrapper
Jonathon Jongsma
jjongsma at redhat.com
Wed Feb 17 20:45:02 UTC 2016
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
On Thu, 2016-02-11 at 18:04 +0200, Dmitry Fleytman wrote:
> 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 at daynix.com>
> Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
> ---
> 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 at daynix.com>
> + Kirill Moizik <kirill at daynix.com>
> +*/
> +#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 at daynix.com>
> + Kirill Moizik <kirill at daynix.com>
> +*/
> +#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
More information about the Spice-devel
mailing list