summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-02-15 19:24:27 +0000
committerPete Batard <pbatard@gmail.com>2010-02-15 19:24:27 +0000
commitadf2a8e3082be13d4324a8b277a99333dc90301d (patch)
treefdfabe0c82ba393888ebaaef6abe4fa0bfe7964a
parent0d6afe88a6ff5b85aaa21468a951b349a81a7bb0 (diff)
downloadlibusb-a156.tar.gz
added inf generation and installation (WIP)a156
-rw-r--r--examples/lsusb.c9
-rw-r--r--examples/lsusb_2008.vcproj4
-rw-r--r--libusb/os/driver_install.c167
-rw-r--r--libusb/os/driver_install.h5
4 files changed, 161 insertions, 24 deletions
diff --git a/examples/lsusb.c b/examples/lsusb.c
index 6b815d4..61d278a 100644
--- a/examples/lsusb.c
+++ b/examples/lsusb.c
@@ -55,12 +55,13 @@ main(void)
drv_info = list_driverless();
for (; drv_info != NULL; drv_info = drv_info->next) {
- printf("%s\n", drv_info->desc);
- printf(" %s\n", drv_info->vid);
- printf(" %s\n", drv_info->pid);
- printf(" %s\n", drv_info->mi);
+ if (create_inf(drv_info, "C:\\test") == 0) {
+ install_device("C:\\test\\libusb_device.inf");
+ }
}
+// return 0;
+
r = libusb_init(NULL);
if (r < 0)
return r;
diff --git a/examples/lsusb_2008.vcproj b/examples/lsusb_2008.vcproj
index 8316fe9..f0d13a0 100644
--- a/examples/lsusb_2008.vcproj
+++ b/examples/lsusb_2008.vcproj
@@ -219,7 +219,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="setupapi.lib pthreadVC2.lib"
+ AdditionalDependencies="setupapi.lib pthreadVC2.lib difxapi.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\msvc"
GenerateDebugInformation="true"
@@ -299,7 +299,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib"
+ AdditionalDependencies="setupapi.lib pthreadVC2_x64.lib difxapi.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\msvc"
GenerateDebugInformation="true"
diff --git a/libusb/os/driver_install.c b/libusb/os/driver_install.c
index 3c80901..81dd1f1 100644
--- a/libusb/os/driver_install.c
+++ b/libusb/os/driver_install.c
@@ -5,18 +5,80 @@
#endif
#include <windows.h>
#include <setupapi.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <process.h>
+#include <io.h>
#include <stdio.h>
#include <inttypes.h>
#include <objbase.h> // for GUID ops. requires libole32.a
+#include <api/difxapi.h>
#include "libusbi.h"
#include "windows_usb.h"
#include "driver_install.h"
+const char inf[] = "DeviceClassGUID = \"{78a1c341-4539-11d3-b88d-00c04fad5171}\"\n" \
+ "Date = \"01/08/2010\"\n\n" \
+ "ProviderName = \"libusb 1.0\"\n" \
+ "WinUSB_SvcDesc = \"WinUSB Driver Service\"\n" \
+ "DiskName = \"libusb (WinUSB) Device Install Disk\"\n" \
+ "ClassName = \"libusb (WinUSB) devices\"\n\n" \
+ "[Version]\n" \
+ "DriverVer = %Date%\n" \
+ "Signature = \"$Windows NT$\"\n" \
+ "Class = %ClassName%\n" \
+ "ClassGuid = %DeviceClassGUID%\n" \
+ "Provider = %ProviderName%\n" \
+ "CatalogFile = libusb_device.cat\n\n" \
+ "[ClassInstall32]\n" \
+ "Addreg = WinUSBDeviceClassReg\n\n" \
+ "[WinUSBDeviceClassReg]\n" \
+ "HKR,,,0,%ClassName%\n" \
+ "HKR,,Icon,,-20\n\n" \
+ "[Manufacturer]\n" \
+ "%ProviderName% = libusbDevice_WinUSB,NTx86,NTamd64\n\n" \
+ "[libusbDevice_WinUSB.NTx86]\n" \
+ "%DeviceName% = USB_Install, USB\\%DeviceID%\n\n" \
+ "[libusbDevice_WinUSB.NTamd64]\n" \
+ "%DeviceName% = USB_Install, USB\\%DeviceID%\n\n" \
+ "[USB_Install]\n" \
+ "Include=winusb.inf\n" \
+ "Needs=WINUSB.NT\n\n" \
+ "[USB_Install.Services]\n" \
+ "Include=winusb.inf\n" \
+ "AddService=WinUSB,0x00000002,WinUSB_ServiceInstall\n\n" \
+ "[WinUSB_ServiceInstall]\n" \
+ "DisplayName = %WinUSB_SvcDesc%\n" \
+ "ServiceType = 1\n" \
+ "StartType = 3\n" \
+ "ErrorControl = 1\n" \
+ "ServiceBinary = %12%\\WinUSB.sys\n\n" \
+ "[USB_Install.Wdf]\n" \
+ "KmdfService=WINUSB, WinUsb_Install\n\n" \
+ "[WinUSB_Install]\n" \
+ "KmdfLibraryVersion=1.9\n\n" \
+ "[USB_Install.HW]\n" \
+ "AddReg=Dev_AddReg\n\n" \
+ "[Dev_AddReg]\n" \
+ "HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%\n\n" \
+ "[USB_Install.CoInstallers]\n" \
+ "AddReg=CoInstallers_AddReg\n" \
+ "CopyFiles=CoInstallers_CopyFiles\n\n" \
+ "[CoInstallers_AddReg]\n" \
+ "HKR,,CoInstallers32,0x00010000,\"WdfCoInstaller01009.dll,WdfCoInstaller\",\"WinUSBCoInstaller2.dll\"\n\n" \
+ "[CoInstallers_CopyFiles]\n" \
+ "WinUSBCoInstaller2.dll\n" \
+ "WdfCoInstaller01009.dll\n\n" \
+ "[DestinationDirs]\n" \
+ "CoInstallers_CopyFiles=11\n\n" \
+ "[SourceDisksNames]\n" \
+ "1 = %DiskName%,,,\\x86\n" \
+ "2 = %DiskName%,,,\\amd64\n\n" \
+ "[SourceDisksFiles.x86]\n" \
+ "WinUSBCoInstaller2.dll=1\n" \
+ "WdfCoInstaller01009.dll=1\n\n" \
+ "[SourceDisksFiles.amd64]\n" \
+ "WinUSBCoInstaller2.dll=2\n" \
+ "WdfCoInstaller01009.dll=2\n";
+
char* guid_to_string(const GUID guid)
{
static char guid_string[MAX_GUID_STRING_LENGTH];
@@ -41,7 +103,6 @@ void free_di(struct driver_info *start)
struct driver_info* list_driverless(void)
{
unsigned i, j;
- struct libusb_context *ctx = NULL;
DWORD size, reg_type, install_state;
CONFIGRET r;
HDEVINFO dev_info;
@@ -49,11 +110,12 @@ struct driver_info* list_driverless(void)
SP_DEVICE_INTERFACE_DETAIL_DATA *dev_interface_details = NULL;
char *sanitized_short = NULL;
char *prefix[3] = {"VID_", "PID_", "MI_"};
-// char *designation[3] = {"VendorID", "ProductID", "InterfaceID"};
char *token;
char path[MAX_PATH_LENGTH];
char desc[MAX_DESC_LENGTH];
+ char driver[MAX_DESC_LENGTH];
struct driver_info *ret = NULL, *cur = NULL, *drv_info;
+ bool driverless;
// List all connected USB devices
dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
@@ -64,6 +126,7 @@ struct driver_info* list_driverless(void)
// Find the ones that are driverless
for (i = 0; ; i++)
{
+ driverless = false;
safe_free(sanitized_short);
dev_info_data.cbSize = sizeof(dev_info_data);
@@ -71,37 +134,48 @@ struct driver_info* list_driverless(void)
break;
}
+ // SPDRP_DRIVER seems to do a better job at detecting driverless devices than
+ // SPDRP_INSTALL_STATE
+ if ( SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_DRIVER,
+ &reg_type, (BYTE*)driver, MAX_KEY_LENGTH, &size)) {
+ // Driverless devices should return an error
+ continue;
+ }
+// usbi_dbg("driver: %s", driver);
+/*
if ( (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
&reg_type, (BYTE*)&install_state, 4, &size))
&& (size != 4) ) {
- usbi_warn(ctx, "could not detect installation state of driver for %d: %s",
+ usbi_warn(NULL, "could not detect installation state of driver for %d: %s",
i, windows_error_str(0));
continue;
}
- if (install_state != InstallStateFailedInstall) {
+ usbi_dbg("install state: %d", install_state);
+ if ( (install_state != InstallStateFailedInstall)
+ && (SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_DRIVER,
+ &reg_type, (BYTE*)driver, MAX_KEY_LENGTH, &size) != ERROR_INVALID_DATA) ) {
continue;
}
-
+*/
if ( (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, SPDRP_DEVICEDESC,
&reg_type, (BYTE*)desc, MAX_KEY_LENGTH, &size)) ) {
- usbi_warn(ctx, "could not read device description for %d: %s",
+ usbi_warn(NULL, "could not read device description for %d: %s",
i, windows_error_str(0));
continue;
}
r = CM_Get_Device_ID(dev_info_data.DevInst, path, MAX_PATH_LENGTH, 0);
if (r != CR_SUCCESS) {
- usbi_err(ctx, "could not retrieve simple path for device %d: CR error %d",
+ usbi_err(NULL, "could not retrieve simple path for device %d: CR error %d",
i, r);
continue;
}
sanitized_short = sanitize_path(path);
if (sanitized_short == NULL) {
- usbi_err(ctx, "could not sanitize path for device %d", i);
+ usbi_err(NULL, "could not sanitize path for device %d", i);
continue;
}
usbi_dbg("Driverless USB device (%d): %s", i, sanitized_short);
-// usbi_dbg(" DeviceName = \"%s\"", desc);
drv_info = calloc(1, sizeof(struct driver_info));
if (drv_info == NULL) {
@@ -132,16 +206,75 @@ struct driver_info* list_driverless(void)
safe_strcpy(drv_info->mi, sizeof(drv_info->mi), token);
break;
default:
- usbi_err(ctx, "unexpected case");
+ usbi_err(NULL, "unexpected case");
break;
}
}
}
token = strtok (NULL, "#&");
}
- CoCreateGuid(&drv_info->dev_guid);
-
-// usbi_dbg(" DeviceGUID = \"%s\"", guid_to_string(drv_info->dev_guid));
}
return ret;
+}
+
+// Create an inf and extract coinstallers in the directory pointed by path
+int create_inf(struct driver_info* drv_info, char* path)
+{
+ char filename[MAX_PATH_LENGTH];
+ FILE* fd;
+ GUID guid;
+
+ // TODO? create a reusable temp dir if path is NULL?
+ if ((path == NULL) || (drv_info == NULL))
+ return -1;
+
+ // Try to create directory if it doesn't exist
+ if ( (_access(path, 02) != 0) && (CreateDirectory(path, 0) == 0) ) {
+ usbi_err(NULL, "could not access directory: %s", path);
+ return -1;
+ }
+
+ safe_strcpy(filename, MAX_PATH_LENGTH, path);
+ safe_strcat(filename, MAX_PATH_LENGTH, "\\libusb_device.inf");
+
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ usbi_err(NULL, "failed to create file: %s", filename);
+ return -1;
+ }
+
+ fprintf(fd, "[Strings]\n");
+ fprintf(fd, "DeviceName = \"%s\"\n", drv_info->desc);
+ fprintf(fd, "DeviceID = \"%s&%s", drv_info->vid, drv_info->pid);
+ if (drv_info->mi[0] != 0) {
+ fprintf(fd, "&%s\"\n", drv_info->mi);
+ } else {
+ fprintf(fd, "\"\n");
+ }
+ CoCreateGuid(&guid);
+ fprintf(fd, "DeviceGUID = \"%s\"\n", guid_to_string(guid));
+ fwrite(inf, sizeof(inf), 1, fd);
+ return 0;
+
+ // TODO: extract coinstaller files from resource
+ // TODO: create cat file for XP?
+}
+
+int install_device(char* path)
+{
+ DWORD r;
+
+ r = DriverPackagePreinstall(path, DRIVER_PACKAGE_LEGACY_MODE|DRIVER_PACKAGE_REPAIR);
+ // Will fail if inf not signed, unless DRIVER_PACKAGE_LEGACY_MODE is specified.
+ // Will fail if no cat file has been created
+ // r = 87 ERROR_INVALID_PARAMETER on path == NULL
+ // r = 2 ERROR_FILE_NOT_FOUND if no inf in path
+ // r = 5 ERROR_ACCESS_DENIED if needs admin elevation
+ // r = 0xE0000003 ERROR_GENERAL_SYNTAX the syntax of the inf is invalid
+ // r = 0xE0000304 ERROR_INVALID_CATALOG_DATA => no cat
+ // r = 0xE0000247 if user decided not to install on warnings
+ // r = 0x800B0100 ERROR_WRONG_INF_STYLE => missing cat entry in inf
+
+ usbi_dbg("ret = %X", r);
+ return 0;
} \ No newline at end of file
diff --git a/libusb/os/driver_install.h b/libusb/os/driver_install.h
index f1703b3..81688b3 100644
--- a/libusb/os/driver_install.h
+++ b/libusb/os/driver_install.h
@@ -9,9 +9,12 @@ struct driver_info {
char vid[9];
char pid[9];
char mi[6];
- GUID dev_guid;
};
struct driver_info *list_driverless(void);
char* guid_to_string(const GUID guid);
+int create_inf(struct driver_info* drv_info, char* path);
+int install_device(char* path);
+
+