[2/2] winedevice: special-case usbd.sys loading

Damjan Jovanovic damjan.jov at gmail.com
Mon Nov 15 14:03:56 CST 2010


Changelog:
* winedevice: special-case usbd.sys loading

Damjan Jovanovic
-------------- next part --------------
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index 2ce8c15..c92bc11 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -46,6 +46,8 @@ static HKEY driver_hkey;
 static HANDLE stop_event;
 static DRIVER_OBJECT driver_obj;
 static DRIVER_EXTENSION driver_extension;
+static DRIVER_OBJECT usbd_driver;
+static DRIVER_EXTENSION usbd_extension;
 
 /* find the LDR_MODULE corresponding to the driver module */
 static LDR_MODULE *find_ldr_module( HMODULE module )
@@ -130,7 +132,7 @@ error:
 }
 
 /* call the driver init entry point */
-static NTSTATUS init_driver( HMODULE module, UNICODE_STRING *keyname )
+static NTSTATUS init_driver( DRIVER_OBJECT *driver_obj, DRIVER_EXTENSION *driver_extension, HMODULE module, UNICODE_STRING *keyname )
 {
     unsigned int i;
     NTSTATUS status;
@@ -138,34 +140,55 @@ static NTSTATUS init_driver( HMODULE module, UNICODE_STRING *keyname )
 
     if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
 
-    driver_obj.Size            = sizeof(driver_obj);
-    driver_obj.DriverSection   = find_ldr_module( module );
-    driver_obj.DriverInit      = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
-    driver_obj.DriverExtension = &driver_extension;
+    driver_obj->Size            = sizeof(*driver_obj);
+    driver_obj->DriverSection   = find_ldr_module( module );
+    driver_obj->DriverInit      = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
+    driver_obj->DriverExtension = driver_extension;
 
-    driver_extension.DriverObject   = &driver_obj;
-    driver_extension.ServiceKeyName = *keyname;
+    driver_extension->DriverObject   = driver_obj;
+    driver_extension->ServiceKeyName = *keyname;
 
     if (WINE_TRACE_ON(relay))
         WINE_DPRINTF( "%04x:Call driver init %p (obj=%p,str=%s)\n", GetCurrentThreadId(),
-                      driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer) );
+                      driver_obj->DriverInit, driver_obj, wine_dbgstr_w(keyname->Buffer) );
 
-    status = driver_obj.DriverInit( &driver_obj, keyname );
+    status = driver_obj->DriverInit( driver_obj, keyname );
 
     if (WINE_TRACE_ON(relay))
         WINE_DPRINTF( "%04x:Ret  driver init %p (obj=%p,str=%s) retval=%08x\n", GetCurrentThreadId(),
-                      driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer), status );
+                      driver_obj->DriverInit, driver_obj, wine_dbgstr_w(keyname->Buffer), status );
 
-    WINE_TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), &driver_obj );
-    WINE_TRACE( "- DriverInit = %p\n", driver_obj.DriverInit );
-    WINE_TRACE( "- DriverStartIo = %p\n", driver_obj.DriverStartIo );
-    WINE_TRACE( "- DriverUnload = %p\n", driver_obj.DriverUnload );
+    WINE_TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), driver_obj );
+    WINE_TRACE( "- DriverInit = %p\n", driver_obj->DriverInit );
+    WINE_TRACE( "- DriverStartIo = %p\n", driver_obj->DriverStartIo );
+    WINE_TRACE( "- DriverUnload = %p\n", driver_obj->DriverUnload );
     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-        WINE_TRACE( "- MajorFunction[%d] = %p\n", i, driver_obj.MajorFunction[i] );
+        WINE_TRACE( "- MajorFunction[%d] = %p\n", i, driver_obj->MajorFunction[i] );
 
     return status;
 }
 
+static void load_additional_drivers(void)
+{
+    /* Tests on Windows show DriverEntry() is not called
+     * on SYS files loaded via DLL imports, but we must
+     * initialize USBD.SYS somehow...
+     */
+    HMODULE usbd = GetModuleHandleA( "USBD.SYS" );
+    if (usbd)
+    {
+        void (WINAPI *__wine_usbd_init)(DRIVER_OBJECT*,DRIVER_OBJECT*);
+        UNICODE_STRING str;
+        static const WCHAR emptyW[] = {0};
+
+        RtlInitUnicodeString( &str, emptyW );
+        init_driver( &usbd_driver, &usbd_extension, usbd, &str );
+        __wine_usbd_init = (void*) GetProcAddress( usbd, "__wine_usbd_init" );
+        if (__wine_usbd_init)
+            __wine_usbd_init( &usbd_driver, &driver_obj );
+    }
+}
+
 /* load the .sys module for a device driver */
 static BOOL load_driver(void)
 {
@@ -183,6 +206,7 @@ static BOOL load_driver(void)
     HMODULE module;
     LPWSTR path = NULL, str;
     DWORD type, size;
+    NTSTATUS status;
 
     str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(driver_name)*sizeof(WCHAR) );
     lstrcpyW( str, servicesW );
@@ -234,8 +258,10 @@ static BOOL load_driver(void)
     HeapFree( GetProcessHeap(), 0, path );
     if (!module) return FALSE;
 
-    init_driver( module, &keypath );
-    return TRUE;
+    status = init_driver( &driver_obj, &driver_extension, module, &keypath );
+    if (status == STATUS_SUCCESS)
+        load_additional_drivers();
+    return status == STATUS_SUCCESS;
 }
 
 static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )


More information about the wine-patches mailing list