summaryrefslogtreecommitdiff
path: root/usbclerk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'usbclerk.cpp')
-rw-r--r--usbclerk.cpp81
1 files changed, 76 insertions, 5 deletions
diff --git a/usbclerk.cpp b/usbclerk.cpp
index 27435e3..5ef4160 100644
--- a/usbclerk.cpp
+++ b/usbclerk.cpp
@@ -1,4 +1,6 @@
#include <windows.h>
+#include <setupapi.h>
+#include <cfgmgr32.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
@@ -33,6 +35,9 @@ private:
bool execute();
bool dispatch_message(CHAR *buffer, DWORD bytes, USBClerkReply *reply);
bool install_winusb_driver(int vid, int pid);
+ bool remove_winusb_driver(int vid, int pid);
+ bool remove_dev(HDEVINFO devs, PSP_DEVINFO_DATA dev_info);
+ bool rescan();
static DWORD WINAPI control_handler(DWORD control, DWORD event_type,
LPVOID event_data, LPVOID context);
static VOID WINAPI main(DWORD argc, TCHAR * argv[]);
@@ -320,16 +325,21 @@ bool USBClerk::dispatch_message(CHAR *buffer, DWORD bytes, USBClerkReply *reply)
switch (hdr->type) {
case USB_CLERK_DRIVER_INSTALL:
vd_printf("Installing winusb driver for %04x:%04x", dev->vid, dev->pid);
- if (reply->status = install_winusb_driver(dev->vid, dev->pid)) {
- vd_printf("winusb driver install succeed");
- } else {
- vd_printf("winusb driver install failed");
- }
+ reply->status = install_winusb_driver(dev->vid, dev->pid);
+ break;
+ case USB_CLERK_DRIVER_REMOVE:
+ vd_printf("Removing winusb driver for %04x:%04x", dev->vid, dev->pid);
+ reply->status = remove_winusb_driver(dev->vid, dev->pid);
break;
default:
vd_printf("Unknown message received, type %u", hdr->type);
return false;
}
+ if (reply->status) {
+ vd_printf("Completed successfully");
+ } else {
+ vd_printf("Failed");
+ }
return true;
}
@@ -417,6 +427,67 @@ cleanup:
return installed;
}
+bool USBClerk::remove_winusb_driver(int vid, int pid)
+{
+ HDEVINFO devs;
+ DWORD dev_index;
+ SP_DEVINFO_DATA dev_info;
+ SP_DEVINFO_LIST_DETAIL_DATA dev_info_list_detail;
+ TCHAR dev_prefix[MAX_DEVICE_ID_LEN];
+ bool ret = false;
+
+ devs = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES, NULL, NULL, NULL);
+ if (devs == INVALID_HANDLE_VALUE) {
+ vd_printf("SetupDiGetClassDevsEx failed: %u\n", GetLastError());
+ return false;
+ }
+
+ dev_info_list_detail.cbSize = sizeof(dev_info_list_detail);
+ if (!SetupDiGetDeviceInfoListDetail(devs, &dev_info_list_detail)) {
+ vd_printf("SetupDiGetDeviceInfoListDetail failed: %u\n", GetLastError());
+ SetupDiDestroyDeviceInfoList(devs);
+ return false;
+ }
+
+ swprintf(dev_prefix, MAX_DEVICE_ID_LEN, L"USB\\VID_%04x&PID_%04x\\", vid, pid);
+ dev_info.cbSize = sizeof(dev_info);
+ for (dev_index = 0; SetupDiEnumDeviceInfo(devs, dev_index, &dev_info); dev_index++) {
+ TCHAR devID[MAX_DEVICE_ID_LEN];
+
+ if (CM_Get_Device_ID_Ex(dev_info.DevInst, devID, MAX_DEVICE_ID_LEN, 0,
+ dev_info_list_detail.RemoteMachineHandle) == CR_SUCCESS &&
+ wcsstr(devID, dev_prefix)) {
+ vd_printf("Removing %S\n", devID);
+ ret = remove_dev(devs, &dev_info);
+ break;
+ }
+ }
+ SetupDiDestroyDeviceInfoList(devs);
+ ret = ret && rescan();
+ return ret;
+}
+
+bool USBClerk::remove_dev(HDEVINFO devs, PSP_DEVINFO_DATA dev_info)
+{
+ SP_REMOVEDEVICE_PARAMS rmd_params;
+
+ rmd_params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ rmd_params.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+ rmd_params.Scope = DI_REMOVEDEVICE_GLOBAL;
+ rmd_params.HwProfile = 0;
+ return (SetupDiSetClassInstallParams(devs, dev_info,
+ &rmd_params.ClassInstallHeader, sizeof(rmd_params)) &&
+ SetupDiCallClassInstaller(DIF_REMOVE, devs, dev_info));
+}
+
+bool USBClerk::rescan()
+{
+ DEVINST dev_root;
+
+ return (CM_Locate_DevNode_Ex(&dev_root, NULL, CM_LOCATE_DEVNODE_NORMAL, NULL) == CR_SUCCESS &&
+ CM_Reenumerate_DevNode_Ex(dev_root, 0, NULL) == CR_SUCCESS);
+}
+
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
bool success = false;