[Spice-devel] [PATCH 6/6] usbclerk: add device filter support
Arnon Gilboa
agilboa at redhat.com
Mon Jul 23 02:23:08 PDT 2012
read from HKLM\Software\USBClerk\filter_rules
same format as in client
---
usbclerk.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
usbclerk.vcproj | 40 +++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+), 0 deletions(-)
diff --git a/usbclerk.cpp b/usbclerk.cpp
index 09f1e66..2913998 100644
--- a/usbclerk.cpp
+++ b/usbclerk.cpp
@@ -5,6 +5,7 @@
#include <string.h>
#include <tchar.h>
#include "usbclerk.h"
+#include "usbredirfilter.h"
#include "libwdi.h"
#include "vdlog.h"
@@ -22,6 +23,8 @@
#define USB_DRIVER_INSTALL_RETRIES 10
#define USB_DRIVER_INSTALL_INTERVAL 2000
#define MAX_DEVICE_PROP_LEN 256
+#define MAX_DEVICE_HCID_LEN 1024
+#define MAX_DEVICE_FILTER_LEN 1024
class USBClerk {
public:
@@ -40,6 +43,7 @@ private:
bool remove_dev(HDEVINFO devs, PSP_DEVINFO_DATA dev_info);
bool rescan();
bool get_dev_info(HDEVINFO devs, int vid, int pid, SP_DEVINFO_DATA *dev_info);
+ bool dev_filter_check(int vid, int pid);
static DWORD WINAPI control_handler(DWORD control, DWORD event_type,
LPVOID event_data, LPVOID context);
static VOID WINAPI main(DWORD argc, TCHAR * argv[]);
@@ -48,6 +52,8 @@ private:
static USBClerk* _singleton;
SERVICE_STATUS _status;
SERVICE_STATUS_HANDLE _status_handle;
+ struct usbredirfilter_rule *filter_rules;
+ int filter_count;
char _wdi_path[MAX_PATH];
HANDLE _pipe;
bool _running;
@@ -265,8 +271,11 @@ bool USBClerk::execute()
SECURITY_DESCRIPTOR* sec_desr;
USBClerkReply reply = {{USB_CLERK_MAGIC, USB_CLERK_VERSION,
USB_CLERK_REPLY, sizeof(USBClerkReply)}};
+ CHAR filter_str[MAX_DEVICE_FILTER_LEN];
CHAR buffer[USB_CLERK_PIPE_BUF_SIZE];
DWORD bytes;
+ HKEY hkey;
+ LONG ret;
#if 0
/* Hack for wdi logging */
@@ -288,6 +297,20 @@ bool USBClerk::execute()
vd_printf("CreatePipe() failed: %u", GetLastError());
return false;
}
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\USBClerk", 0, KEY_READ, &hkey);
+ if (ret == ERROR_SUCCESS) {
+ DWORD size = sizeof(filter_str);
+ ret = RegQueryValueExA(hkey, "filter_rules", NULL, NULL, (LPBYTE)filter_str, &size);
+ if (ret == ERROR_SUCCESS) {
+ ret = usbredirfilter_string_to_rules(filter_str, ",", "|",
+ &filter_rules, &filter_count);
+ if (ret != 0) {
+ vd_printf("Failed parsing filter rules: %s %d", filter_str, ret);
+ }
+ }
+ RegCloseKey(hkey);
+ }
+ vd_printf("filter_count: %d", filter_count);
while (_running) {
if (!ConnectNamedPipe(_pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED) {
vd_printf("ConnectNamedPipe() failed: %u", GetLastError());
@@ -308,6 +331,7 @@ bool USBClerk::execute()
disconnect:
DisconnectNamedPipe(_pipe);
}
+ free(filter_rules);
CloseHandle(_pipe);
return true;
}
@@ -326,6 +350,10 @@ bool USBClerk::dispatch_message(CHAR *buffer, DWORD bytes, USBClerkReply *reply)
return false;
}
dev = (USBClerkDriverOp *)buffer;
+ if (!dev_filter_check(dev->vid, dev->pid)) {
+ reply->status = FALSE;
+ return true;
+ }
switch (hdr->type) {
case USB_CLERK_DRIVER_INSTALL:
vd_printf("Installing winusb driver for %04x:%04x", dev->vid, dev->pid);
@@ -504,6 +532,47 @@ bool USBClerk::get_dev_info(HDEVINFO devs, int vid, int pid, SP_DEVINFO_DATA *de
return false;
}
+bool USBClerk::dev_filter_check(int vid, int pid)
+{
+ HDEVINFO devs;
+ SP_DEVINFO_DATA dev_info;
+ TCHAR compat_ids[MAX_DEVICE_HCID_LEN];
+ uint8_t dev_cls, dev_subcls, dev_proto;
+ bool ret = false;
+
+ if (!filter_rules) {
+ return true;
+ }
+ devs = SetupDiGetClassDevs(NULL, L"USB", NULL, DIGCF_ALLCLASSES);
+ if (devs == INVALID_HANDLE_VALUE) {
+ vd_printf("SetupDiGetClassDevsEx failed: %u", GetLastError());
+ return false;
+ }
+ if (!get_dev_info(devs, vid, pid, &dev_info)) {
+ vd_printf("Cannot find device info %04x:%04x", vid, pid);
+ goto cleanup;
+ }
+ if (!SetupDiGetDeviceRegistryProperty(devs, &dev_info, SPDRP_COMPATIBLEIDS, NULL,
+ (PBYTE)compat_ids, sizeof(compat_ids), NULL)) {
+ vd_printf("Cannot get compatible id %04x:%04x", vid, pid);
+ goto cleanup;
+ }
+ if (swscanf_s(compat_ids, L"USB\\Class_%02hx&SubClass_%02hx&Prot_%02hx",
+ &dev_cls, &dev_subcls, &dev_proto) != 3) {
+ vd_printf("Cannot parse compatible id %S", compat_ids);
+ goto cleanup;
+ }
+ if (usbredirfilter_check(filter_rules, filter_count, dev_cls, dev_subcls, dev_proto,
+ NULL, NULL, NULL, 0, vid, pid, 0, 0) == 0) {
+ ret = true;
+ } else {
+ vd_printf("Device filter failed %04x:%04x", vid, pid);
+ }
+cleanup:
+ SetupDiDestroyDeviceInfoList(devs);
+ return ret;
+}
+
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
bool success = false;
diff --git a/usbclerk.vcproj b/usbclerk.vcproj
index b692737..dc59ad5 100644
--- a/usbclerk.vcproj
+++ b/usbclerk.vcproj
@@ -347,6 +347,10 @@
>
</File>
<File
+ RelativePath=".\usbredirfilter.h"
+ >
+ </File>
+ <File
RelativePath=".\vdlog.h"
>
</File>
@@ -371,6 +375,42 @@
>
</File>
<File
+ RelativePath=".\usbredirfilter.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath=".\vdlog.cpp"
>
</File>
--
1.7.4.1
More information about the Spice-devel
mailing list