[Wine-patches] [6/23] Combine wineusb and wineusbhub into usbhub.sys, do not use wineserver to call AddDevice.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пн Янв 19 18:23:22 MSK 2009


For eterhack branch
----------- следующая часть -----------
From 5b8eef145dc43d841e05d64f0f61102bb8dbb41e Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Mon, 12 Jan 2009 14:25:13 +0300
Subject: [PATCH] Combine wineusb and wineusbhub into usbhub.sys, do not use wineserver to call AddDevice.

---
 dlls/ntoskrnl.exe/Makefile.in       |    2 +-
 dlls/ntoskrnl.exe/ntoskrnl.c        |  212 +++++++++------
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec |    3 +
 dlls/usbhub.sys/Makefile.in         |   16 +
 dlls/usbhub.sys/usbhub.c            |  528 +++++++++++++++++++++++++++++++++++
 dlls/usbhub.sys/usbhub.sys.spec     |    1 +
 dlls/wineusbhub/Makefile.in         |   15 -
 dlls/wineusbhub/wineusbhub.c        |  319 ---------------------
 dlls/wineusbhub/wineusbhub.spec     |   11 -
 programs/winedevice/Makefile.in     |    2 +-
 programs/winedevice/device.c        |   97 +------
 programs/wineusb/Makefile.in        |   15 -
 programs/wineusb/main.c             |  329 ----------------------
 tools/wine.inf.in                   |   13 +-
 14 files changed, 692 insertions(+), 871 deletions(-)
 create mode 100644 dlls/usbhub.sys/Makefile.in
 create mode 100644 dlls/usbhub.sys/usbhub.c
 create mode 100644 dlls/usbhub.sys/usbhub.sys.spec
 delete mode 100644 dlls/wineusbhub/Makefile.in
 delete mode 100644 dlls/wineusbhub/wineusbhub.c
 delete mode 100644 dlls/wineusbhub/wineusbhub.spec
 delete mode 100644 programs/wineusb/Makefile.in
 delete mode 100644 programs/wineusb/main.c

diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in
index 164e86e..1cd60dc 100644
--- a/dlls/ntoskrnl.exe/Makefile.in
+++ b/dlls/ntoskrnl.exe/Makefile.in
@@ -4,7 +4,7 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = ntoskrnl.exe
 IMPORTLIB = ntoskrnl.exe
-IMPORTS   = kernel32 ntdll wineusbhub setupapi
+IMPORTS   = kernel32 ntdll setupapi
 
 C_SRCS = \
 	ntoskrnl.c
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 6a0e00d..ee75766 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -47,11 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
 
 
-extern UNICODE_STRING * CDECL __wine_usbhub_get_pdo_name();
-extern char * CDECL __wine_usbhub_get_instance_id();
-extern USHORT CDECL __wine_usbhub_get_vid();
-extern USHORT CDECL __wine_usbhub_get_pid();
-
 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
 
 typedef struct _KSERVICE_TABLE_DESCRIPTOR
@@ -67,6 +62,22 @@ KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
 typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
 
+struct DeviceInstance
+{
+    struct list entry;
+    USHORT vid;
+    USHORT pid;
+    char *instance_id;
+    WCHAR *service;
+    UNICODE_STRING pdo_name;
+    struct usb_device *dev;
+};
+
+struct PdoExtension
+{
+    struct DeviceInstance *instance;
+};
+
 static struct list Irps = LIST_INIT(Irps);
 
 struct IrpInstance
@@ -94,6 +105,24 @@ struct DriverObjExtension
     void *id_addr;
 };
 
+static struct list Drivers = LIST_INIT(Drivers);
+
+struct DriverInstance
+{
+    struct list entry;
+    DRIVER_OBJECT *driver;
+    const WCHAR *service;
+};
+
+static struct list Interfaces = LIST_INIT(Interfaces);
+
+struct InterfaceInstance
+{
+    struct list entry;
+    WCHAR *link;
+    UNICODE_STRING *target;
+};
+
 #ifdef __i386__
 #define mem_mask 0xffff
 #define mem_size 0x10000
@@ -359,6 +388,57 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
 
 
 /***********************************************************************
+ *           __wine_add_driver_object   (Not a Windows API)
+ */
+BOOL CDECL __wine_add_driver_object( DRIVER_OBJECT *driver, const WCHAR *service )
+{
+    struct DriverInstance *drv;
+
+    drv = HeapAlloc( GetProcessHeap(), 0, sizeof(*drv) );
+    if (drv == NULL) return FALSE;
+    drv->driver = driver;
+    drv->service = service;
+    list_add_tail( &Drivers, &drv->entry );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           __wine_del_driver_object   (Not a Windows API)
+ */
+void CDECL __wine_del_driver_object( const DRIVER_OBJECT *driver )
+{
+    struct DriverInstance *drv;
+
+    LIST_FOR_EACH_ENTRY( drv, &Drivers, struct DriverInstance, entry )
+    {
+        if (drv->driver == driver)
+        {
+            list_remove( &drv->entry );
+            HeapFree( GetProcessHeap(), 0, drv );
+            return;
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           __wine_get_driver_object   (Not a Windows API)
+ */
+DRIVER_OBJECT * CDECL __wine_get_driver_object( const WCHAR *service )
+{
+    struct DriverInstance *drv;
+
+    LIST_FOR_EACH_ENTRY( drv, &Drivers, struct DriverInstance, entry )
+    {
+        if (!strcmpW( drv->service, service ))
+            return drv->driver;
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
  *           ExAcquireFastMutexUnsafe  (NTOSKRNL.EXE.@)
  */
 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
@@ -872,12 +952,17 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
     DWORD i = 0;
     int found = 0;
     NTSTATUS status = STATUS_UNSUCCESSFUL;
+    struct PdoExtension *dx;
+    USHORT vid, pid;
 
     TRACE( "%p %s %s %p\n", PhysicalDeviceObject,
            debugstr_guid(InterfaceClassGuid), debugstr_us(ReferenceString),
            SymbolicLinkName );
 
-    inst_ptr = __wine_usbhub_get_instance_id();
+    dx = PhysicalDeviceObject->DeviceExtension;
+    vid = dx->instance->vid;
+    pid = dx->instance->pid;
+    inst_ptr = dx->instance->instance_id;
     RtlMultiByteToUnicodeN( instance_id, MAX_DEVICE_ID_LEN, NULL,
             inst_ptr, strlen( inst_ptr ) );
     instance_id[strlen( inst_ptr )] = 0;
@@ -893,8 +978,7 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
         return STATUS_NO_MEMORY;
     }
     /* guid_str.Buffer contains null-terminated string */
-    sprintfW( buf, link_name, __wine_usbhub_get_vid(),
-            __wine_usbhub_get_pid(), instance_id, guid_str.Buffer );
+    sprintfW( buf, link_name, vid, pid, instance_id, guid_str.Buffer );
     RtlFreeUnicodeString( &guid_str );
 
     hardware_id = RtlAllocateHeap( GetProcessHeap(), 0,
@@ -904,8 +988,7 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
         RtlFreeHeap( GetProcessHeap(), 0, buf );
         return STATUS_NO_MEMORY;
     }
-    sprintfW( hardware_id, device_name, __wine_usbhub_get_vid(),
-            __wine_usbhub_get_pid(), instance_id );
+    sprintfW( hardware_id, device_name, vid, pid, instance_id );
 
     set = SetupDiGetClassDevsW( NULL, usb, NULL, DIGCF_ALLCLASSES );
     if (INVALID_HANDLE_VALUE == set)
@@ -933,10 +1016,31 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
             {
                 if (!strcmpiW( id, hardware_id ))
                 {
+                    struct InterfaceInstance *interf;
+
                     found = 1;
+                    interf = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*interf) );
+                    if (NULL == interf) break;
+                    interf->link = RtlAllocateHeap( GetProcessHeap(), 0,
+                            (strlenW(buf) + 1) * sizeof(WCHAR) );
+                    if (NULL == interf->link)
+                    {
+                        RtlFreeHeap( GetProcessHeap(), 0, interf );
+                        break;
+                    }
+                    strcpyW( interf->link, buf );
+                    interf->target = &dx->instance->pdo_name;
                     if (SetupDiCreateDeviceInterfaceW( set, &devInfo,
                             InterfaceClassGuid, NULL, 0, NULL ))
+                    {
+                        list_add_tail( &Interfaces, &interf->entry );
                         status = STATUS_SUCCESS;
+                    }
+                    else
+                    {
+                        RtlFreeHeap( GetProcessHeap(), 0, interf->link );
+                        RtlFreeHeap( GetProcessHeap(), 0, interf );
+                    }
                     break;
                 }
                 id += strlenW( id ) + 1;
@@ -990,89 +1094,25 @@ NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
 NTSTATUS WINAPI IoSetDeviceInterfaceState( PUNICODE_STRING SymbolicLinkName,
                                            BOOLEAN Enable )
 {
-    NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
-
     TRACE( "%s %d\n", debugstr_us(SymbolicLinkName), Enable );
 
     if (Enable)
     {
-        HDEVINFO set;
-        UNICODE_STRING link_name;
-        DWORD i, k = 0;
-        SP_DEVICE_INTERFACE_DATA ifaceData;
-        SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
-        SIZE_T size;
-        GUID guid;
-        WCHAR buf[39];
-        UNICODE_STRING guid_str;
-        BOOL copy = FALSE;
-
-        for (i = 0; i < (SymbolicLinkName->Length / sizeof(WCHAR)) && k < 38; ++i)
+        struct InterfaceInstance *interf;
+
+        LIST_FOR_EACH_ENTRY( interf, &Interfaces, struct InterfaceInstance, entry )
         {
-            if (SymbolicLinkName->Buffer[i] == '{')
-                copy = TRUE;
-            if (copy)
-                buf[k++] = SymbolicLinkName->Buffer[i];
+            if (!strncmpW( SymbolicLinkName->Buffer, interf->link,
+                SymbolicLinkName->Length ))
+                return IoCreateSymbolicLink( SymbolicLinkName, interf->target );
         }
-        if (k != 38)
-            return STATUS_INVALID_PARAMETER;
-        buf[38] = 0;
-        RtlInitUnicodeString( &guid_str, buf );
-        if (STATUS_SUCCESS != RtlGUIDFromString( &guid_str, &guid ))
-            return STATUS_INVALID_PARAMETER;
-
-        set = SetupDiGetClassDevsW( &guid, NULL, NULL, DIGCF_DEVICEINTERFACE );
-        if (INVALID_HANDLE_VALUE == set)
-            return STATUS_UNSUCCESSFUL;
-        ifaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-        size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + SymbolicLinkName->Length;
-        detail = HeapAlloc( GetProcessHeap(), 0, size );
-        if (NULL != detail)
-        {
-            i = 0;
-            detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
-            while (SetupDiEnumDeviceInterfaces( set, NULL, &guid, i++, &ifaceData ))
-            {
-                if (SetupDiGetDeviceInterfaceDetailW( set, &ifaceData, detail,
-                        size, NULL, NULL))
-                    if (!strncmpiW( SymbolicLinkName->Buffer + 3,
-                            detail->DevicePath + 3,
-                            SymbolicLinkName->Length / sizeof(WCHAR) - 3 ))
-                    {
-                        static const WCHAR DosDevices[] =
-                                {'\\','D','o','s','D','e','v','i','c','e','s',0};
-                        PWSTR ptr;
-
-                        ptr = HeapAlloc( GetProcessHeap(), 0,
-                                (strlenW( detail->DevicePath ) - 3
-                                + strlenW( DosDevices ) + 1) * sizeof(WCHAR) );
-                        if (NULL != ptr)
-                        {
-                            strcpyW( ptr, DosDevices );
-                            strcatW( ptr, detail->DevicePath + 3 );
-                            RtlInitUnicodeString( &link_name, ptr );
-                            status = IoCreateSymbolicLink( &link_name,
-                                    __wine_usbhub_get_pdo_name() );
-                            HeapFree( GetProcessHeap(), 0, ptr );
-                        }
-                        else
-                            status = STATUS_NO_MEMORY;
-                        break;
-                    }
-            }
-            HeapFree( GetProcessHeap(), 0, detail );
-        }
-        else
-            status = STATUS_NO_MEMORY;
-        SetupDiDestroyDeviceInfoList( set );
+        return STATUS_OBJECT_NAME_NOT_FOUND;
     }
     else
     {
         FIXME( "Disabling interface is not supported\n" );
-        status = STATUS_NOT_IMPLEMENTED;
+        return STATUS_NOT_IMPLEMENTED;
     }
-
-    return status;
 }
 
 
@@ -1854,6 +1894,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
     LARGE_INTEGER count;
     static PVOID vectored_handler_added;
     struct DriverObjExtension *ext, *ext2;
+    struct InterfaceInstance *intf, *intf2;
 
     switch(reason)
     {
@@ -1871,6 +1912,13 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
             ExFreePool( ext->ptr );
             ExFreePool( ext );
         }
+        LIST_FOR_EACH_ENTRY_SAFE( intf, intf2, &Interfaces,
+                struct InterfaceInstance, entry )
+        {
+            list_remove( &intf->entry );
+            RtlFreeHeap( GetProcessHeap(), 0, intf->link );
+            RtlFreeHeap( GetProcessHeap(), 0, intf );
+        }
     }
     return TRUE;
 }
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 9a30b0e..68ab9e2 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1490,3 +1490,6 @@
 
 @ cdecl wine_ntoskrnl_main_loop(long)
 @ cdecl wine_complete_request(ptr long)
+@ cdecl __wine_add_driver_object(ptr wstr)
+@ cdecl __wine_del_driver_object(ptr)
+@ cdecl __wine_get_driver_object(wstr)
diff --git a/dlls/usbhub.sys/Makefile.in b/dlls/usbhub.sys/Makefile.in
new file mode 100644
index 0000000..ffefdda
--- /dev/null
+++ b/dlls/usbhub.sys/Makefile.in
@@ -0,0 +1,16 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = usbhub.sys
+IMPORTLIB = usbhub.sys
+IMPORTS   = ntoskrnl.exe kernel32 advapi32 setupapi ntdll
+EXTRADLLFLAGS = -Wb,--subsystem,native
+EXTRALIBS = @USBLIBS@
+
+C_SRCS = \
+	usbhub.c
+
+ на MAKE_DLL_RULES@
+
+ на DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c
new file mode 100644
index 0000000..7f80b40
--- /dev/null
+++ b/dlls/usbhub.sys/usbhub.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright 2008 Alexander Morozov for Etersoft
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#ifdef HAVE_USB_H
+#include <usb.h>
+#endif
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "winreg.h"
+#include "winsvc.h"
+#include "winuser.h"
+#include "setupapi.h"
+#include "cfgmgr32.h"
+#include "ddk/ntddk.h"
+#include "ddk/usb.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(usbhub);
+WINE_DECLARE_DEBUG_CHANNEL(relay);
+
+extern void CDECL wine_complete_request( IRP *irp, UCHAR priority_boost );
+extern DRIVER_OBJECT * CDECL __wine_get_driver_object( const WCHAR *service );
+
+static unsigned int last_pdo_num;
+
+static struct list Devices = LIST_INIT(Devices);
+
+struct DeviceInstance
+{
+    struct list entry;
+    USHORT vid;
+    USHORT pid;
+    char *instance_id;
+    WCHAR *service;
+    UNICODE_STRING pdo_name;
+    struct usb_device *dev;
+};
+
+struct PdoExtension
+{
+    struct DeviceInstance *instance;
+};
+
+#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
+static void add_data( char **dst, int *dst_size, void *src, int src_size )
+{
+    int copy;
+
+    copy = (src_size >= *dst_size) ? *dst_size : src_size;
+    memcpy( *dst, src, copy );
+    *dst += copy;
+    *dst_size -= copy;
+}
+
+NTSTATUS WINAPI __wine_usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
+{
+    IO_STACK_LOCATION *irpsp;
+    URB *urb;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    struct DeviceInstance *inst;
+
+    TRACE( "%p, %p\n", device, irp );
+
+    inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
+    irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
+    urb = irpsp->Parameters.Others.Argument1;
+
+    switch (urb->u.UrbHeader.Function)
+    {
+    case URB_FUNCTION_SELECT_CONFIGURATION:
+        {
+            USB_CONFIGURATION_DESCRIPTOR *conf_desc =
+                    urb->u.UrbSelectConfiguration.ConfigurationDescriptor;
+            usb_dev_handle *husb;
+
+            TRACE( "URB_FUNCTION_SELECT_CONFIGURATION\n" );
+
+            husb = usb_open( inst->dev );
+            if (husb)
+            {
+                int ret;
+
+                ret = usb_set_configuration( husb, conf_desc->bConfigurationValue );
+                if (ret < 0)
+                    ERR( "%s\n", usb_strerror() );
+                else
+                    status = STATUS_SUCCESS;
+                usb_close( husb );
+            }
+        }
+        break;
+    case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+        {
+            struct _URB_CONTROL_DESCRIPTOR_REQUEST *request =
+                    &urb->u.UrbControlDescriptorRequest;
+
+            TRACE( "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n" );
+
+            switch (request->DescriptorType)
+            {
+            case USB_DEVICE_DESCRIPTOR_TYPE:
+                TRACE( "USB_DEVICE_DESCRIPTOR_TYPE\n" );
+                if (request->TransferBuffer == NULL)
+                    break;
+                if (sizeof(USB_DEVICE_DESCRIPTOR) <= request->TransferBufferLength)
+                {
+                    memcpy( request->TransferBuffer, &inst->dev->descriptor,
+                            sizeof(USB_DEVICE_DESCRIPTOR) );
+                    status = STATUS_SUCCESS;
+                }
+                break;
+            case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+                TRACE( "USB_CONFIGURATION_DESCRIPTOR_TYPE\n" );
+                {
+                    unsigned int i, k;
+                    char *buf = request->TransferBuffer;
+                    struct usb_config_descriptor *conf = &inst->dev->config[0];
+                    struct usb_interface_descriptor *intf;
+                    struct usb_endpoint_descriptor *endp;
+                    int size = request->TransferBufferLength;
+
+                    /* FIXME: case of num_altsetting > 1 */
+
+                    if (buf == NULL)
+                        break;
+                    add_data( &buf, &size, conf,
+                            sizeof(USB_CONFIGURATION_DESCRIPTOR) );
+                    if (size > 0 && conf->extra)
+                        add_data( &buf, &size, conf->extra, conf->extralen );
+                    for (i = 0; i < conf->bNumInterfaces; ++i)
+                    {
+                        intf = &conf->interface[i].altsetting[0];
+                        if (size > 0)
+                            add_data( &buf, &size, intf,
+                                    sizeof(USB_INTERFACE_DESCRIPTOR) );
+                        if (size > 0 && intf->extra)
+                            add_data( &buf, &size, intf->extra, intf->extralen );
+                        for (k = 0; k < intf->bNumEndpoints; ++k)
+                        {
+                            endp = &intf->endpoint[k];
+                            if (size > 0)
+                                add_data( &buf, &size, endp,
+                                        sizeof(USB_ENDPOINT_DESCRIPTOR) );
+                            if (size > 0 && endp->extra)
+                                add_data( &buf, &size, endp->extra, endp->extralen );
+                        }
+                    }
+                    status = STATUS_SUCCESS;
+                }
+                break;
+            default:
+                FIXME( "unsupported descriptor type %x\n", request->DescriptorType );
+            }
+        }
+        break;
+    case URB_FUNCTION_VENDOR_DEVICE:
+    case URB_FUNCTION_VENDOR_INTERFACE:
+    case URB_FUNCTION_VENDOR_ENDPOINT:
+        {
+            usb_dev_handle *husb;
+            struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *request =
+                    &urb->u.UrbControlVendorClassRequest;
+
+            TRACE( "URB_FUNCTION_VENDOR_*\n" );
+
+            husb = usb_open( inst->dev );
+            if (husb)
+            {
+                UCHAR req_type = request->RequestTypeReservedBits | (2 << 5);
+                char *buf;
+                int ret;
+
+                if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_INTERFACE)
+                    req_type |= 1;
+                else if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_ENDPOINT)
+                    req_type |= 2;
+                buf = HeapAlloc( GetProcessHeap(), 0, request->TransferBufferLength );
+                if (buf != NULL)
+                {
+                    memcpy( buf, request->TransferBuffer, request->TransferBufferLength );
+                    if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+                        req_type |= (1 << 7);
+                    ret = usb_control_msg( husb, req_type, request->Request, request->Value,
+                            request->Index, buf, request->TransferBufferLength, 1000 );
+                    if (ret < 0)
+                        ERR( "%s\n", usb_strerror() );
+                    else
+                    {
+                        if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+                        {
+                            request->TransferBufferLength =
+                                    (ret <= request->TransferBufferLength) ?
+                                    ret : request->TransferBufferLength;
+                            memcpy( request->TransferBuffer, buf,
+                                    request->TransferBufferLength );
+                        }
+                        status = STATUS_SUCCESS;
+                    }
+                    HeapFree( GetProcessHeap(), 0, buf );
+                }
+                usb_close( husb );
+            }
+        }
+        break;
+    default:
+        FIXME( "unsupported URB function %x\n", urb->u.UrbHeader.Function );
+    }
+
+    urb->u.UrbHeader.Status = status;
+    if (irp->UserIosb != NULL)
+    {
+        irp->UserIosb->u.Status = status;
+        irp->UserIosb->Information = 0;
+    }
+    irp->IoStatus.u.Status = status;
+    irp->IoStatus.Information = 0;
+    wine_complete_request( irp, IO_NO_INCREMENT );
+
+    return status;
+}
+
+NTSTATUS WINAPI __wine_usbhub_dispatch_pnp( DEVICE_OBJECT *device, IRP *irp )
+{
+    TRACE( "%p, %p\n", device, irp );
+
+    irp->IoStatus.u.Status = STATUS_SUCCESS;
+    irp->IoStatus.Information = 0;
+    wine_complete_request( irp, IO_NO_INCREMENT );
+
+    return STATUS_SUCCESS;
+}
+
+static BOOL start_service( WCHAR *name )
+{
+    SC_HANDLE scm, service;
+    BOOL ret;
+
+    scm = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
+    if (scm == NULL)
+        return FALSE;
+
+    service = OpenServiceW( scm, name, SERVICE_ALL_ACCESS );
+    if (service == NULL)
+    {
+        CloseServiceHandle( scm );
+        return FALSE;
+    }
+
+    ret = StartServiceW( service, 0, NULL );
+    if (!ret && ERROR_SERVICE_ALREADY_RUNNING == GetLastError())
+        ret = TRUE;
+
+    CloseServiceHandle( service );
+    CloseServiceHandle( scm );
+
+    return ret;
+}
+
+static DEVICE_OBJECT *create_pdo( struct DeviceInstance *inst, DRIVER_OBJECT *hubdrv )
+{
+    static const WCHAR usbpdoW[] = {'\\','D','e','v','i','c','e','\\',
+                                    'U','S','B','P','D','O','-','%','u',0};
+
+    DEVICE_OBJECT *usbdev;
+    WCHAR *buf;
+
+    buf = HeapAlloc( GetProcessHeap(), 0, 30 * sizeof(WCHAR) );
+    if (buf == NULL) return NULL;
+    snprintfW( buf, 30, usbpdoW, last_pdo_num++ );
+    RtlInitUnicodeString( &inst->pdo_name, buf );
+
+    if (IoCreateDevice( hubdrv, sizeof(struct PdoExtension), &inst->pdo_name,
+        0, 0, FALSE, &usbdev ) != STATUS_SUCCESS)
+    {
+        HeapFree( GetProcessHeap(), 0, buf );
+        return NULL;
+    }
+    ((struct PdoExtension *)usbdev->DeviceExtension)->instance = inst;
+    usbdev->Flags |= DO_BUS_ENUMERATED_DEVICE | DO_POWER_PAGABLE;
+    usbdev->Flags &= ~DO_DEVICE_INITIALIZING;
+    return usbdev;
+}
+
+static NTSTATUS add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *dev )
+{
+    NTSTATUS status;
+    NTSTATUS (WINAPI *AddDevice)( PDRIVER_OBJECT, PDEVICE_OBJECT ) =
+            driver->DriverExtension->AddDevice;
+
+    if (TRACE_ON(relay))
+        DPRINTF( "%04x:Call AddDevice %p (%p,%p)\n",
+                 GetCurrentThreadId(), AddDevice, driver, dev );
+
+    status = AddDevice( driver, dev );
+
+    if (TRACE_ON(relay))
+        DPRINTF( "%04x:Ret  AddDevice %p (%p,%p) retval=%08x\n",
+                 GetCurrentThreadId(), AddDevice, driver, dev, status );
+
+    return status;
+}
+
+static void start_device( DRIVER_OBJECT *driver )
+{
+    PDRIVER_DISPATCH dispatch = driver->MajorFunction[IRP_MJ_PNP];
+    DEVICE_OBJECT *device = driver->DeviceObject;
+    IO_STACK_LOCATION *irpsp;
+    PIRP irp;
+    NTSTATUS status;
+
+    if (dispatch == NULL) return;
+    irp = IoAllocateIrp( device->StackSize, FALSE );
+    if (irp == NULL) return;
+
+    --irp->CurrentLocation;
+    irpsp = --irp->Tail.Overlay.s.u.CurrentStackLocation;
+    irp->RequestorMode = KernelMode;
+    irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
+    irpsp->MajorFunction = IRP_MJ_PNP;
+    irpsp->MinorFunction = IRP_MN_START_DEVICE;
+    irpsp->DeviceObject = device;
+    device->CurrentIrp = irp;
+
+    if (TRACE_ON(relay))
+        DPRINTF( "%04x:Call driver dispatch %p (device=%p,irp=%p)\n",
+                 GetCurrentThreadId(), dispatch, device, irp );
+
+    status = dispatch( device, irp );
+
+    if (TRACE_ON(relay))
+        DPRINTF( "%04x:Ret  driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
+                 GetCurrentThreadId(), dispatch, device, irp, status );
+
+    IoFreeIrp( irp );
+}
+
+static BOOL enum_reg_usb_devices(void)
+{
+    static const WCHAR usb[] = {'U','S','B',0};
+
+    SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
+    char *instance_id = NULL;
+    struct DeviceInstance *instance, *instance2;
+    HDEVINFO set;
+    DWORD size, i = 0;
+    USHORT vid, pid;
+    char *str, *buf;
+    BOOL ret;
+
+    set = SetupDiGetClassDevsW( NULL, usb, 0, DIGCF_ALLCLASSES );
+    if (set == INVALID_HANDLE_VALUE) return FALSE;
+
+    while (SetupDiEnumDeviceInfo( set, i++, &devInfo ))
+    {
+        /* get VID and PID */
+        SetupDiGetDeviceRegistryPropertyA( set, &devInfo, SPDRP_HARDWAREID,
+                NULL, NULL, 0, &size );
+        buf = HeapAlloc( GetProcessHeap(), 0, size );
+        if (buf == NULL) goto fail;
+        ret = SetupDiGetDeviceRegistryPropertyA( set, &devInfo, SPDRP_HARDWAREID,
+                NULL, (BYTE *)buf, size, NULL );
+        if (!ret) goto fail;
+        str = strstr( buf, "Vid_" );
+        if (str != NULL)
+        {
+            str += 4;
+            vid = strtol( str, NULL, 16 );
+            str = strstr( str, "Pid_" );
+        }
+        if (str == NULL)
+        {
+            ERR( "bad hardware ID\n" );
+            HeapFree( GetProcessHeap(), 0, buf );
+            continue;
+        }
+        str += 4;
+        pid = strtol( str, NULL, 16 );
+        HeapFree( GetProcessHeap(), 0, buf );
+
+        /* get instance ID */
+        buf = HeapAlloc( GetProcessHeap(), 0, MAX_DEVICE_ID_LEN );
+        if (buf == NULL) goto fail;
+        ret = SetupDiGetDeviceInstanceIdA( set, &devInfo, buf,
+                MAX_DEVICE_ID_LEN, NULL );
+        if (!ret) goto fail;
+        str = strrchr( buf, '\\' );
+        if (str != NULL) ++str;
+        if (str == NULL || *str == 0)
+        {
+            ERR( "bad instance ID\n" );
+            HeapFree( GetProcessHeap(), 0, buf );
+            continue;
+        }
+        instance_id = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
+        if (instance_id == NULL) goto fail;
+        strcpy( instance_id, str );
+        HeapFree( GetProcessHeap(), 0, buf );
+
+        /* get service name */
+        SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_SERVICE,
+                NULL, NULL, 0, &size );
+        buf = HeapAlloc( GetProcessHeap(), 0, size );
+        if (buf == NULL) goto fail;
+        ret = SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_SERVICE,
+                NULL, (BYTE *)buf, size, NULL );
+        if (!ret) goto fail;
+
+        /* add DeviceInstance structure to Devices list */
+        instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
+        if (instance == NULL) goto fail;
+        instance->vid = vid;
+        instance->pid = pid;
+        instance->instance_id = instance_id;
+        instance->service = (WCHAR *)buf;
+        instance->dev = NULL;
+        list_add_tail( &Devices, &instance->entry );
+        instance_id = NULL;
+    }
+
+    SetupDiDestroyDeviceInfoList( set );
+    return TRUE;
+fail:
+    if (buf) HeapFree( GetProcessHeap(), 0, buf );
+    if (instance_id) HeapFree( GetProcessHeap(), 0, instance_id );
+    SetupDiDestroyDeviceInfoList( set );
+    LIST_FOR_EACH_ENTRY_SAFE( instance, instance2, &Devices,
+            struct DeviceInstance, entry )
+    {
+        HeapFree( GetProcessHeap(), 0, instance->instance_id );
+        HeapFree( GetProcessHeap(), 0, instance->service );
+        list_remove( &instance->entry );
+    }
+    return FALSE;
+}
+
+static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
+{
+    struct DeviceInstance *instance;
+    struct usb_device *dev;
+    struct usb_bus *bus;
+    DEVICE_OBJECT *pdo;
+    DRIVER_OBJECT *driver;
+    DRIVER_OBJECT *hubdrv = usbhubdrv;
+    NTSTATUS status;
+
+    if (!enum_reg_usb_devices())
+    {
+        ERR( "failed to enumerate USB devices\n" );
+        return 1;
+    }
+
+    usb_init();
+    usb_find_busses();
+    usb_find_devices();
+
+    for (bus = usb_busses; bus; bus = bus->next)
+        for (dev = bus->devices; dev; dev = dev->next)
+            LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+            {
+                if (instance->dev == NULL &&
+                    dev->descriptor.idVendor == instance->vid &&
+                    dev->descriptor.idProduct == instance->pid)
+                {
+                    if (start_service( instance->service ))
+                    {
+                        pdo = create_pdo( instance, hubdrv );
+                        if (pdo == NULL) break;
+                        instance->dev = dev;
+                        while (!(driver = __wine_get_driver_object(
+                                instance->service )))
+                            Sleep( 100 );
+                        status = add_device( driver, pdo );
+                        if (status != STATUS_SUCCESS) break;
+                        start_device( driver );
+                    }
+                    break;
+                }
+            }
+
+    return 0;
+}
+#endif
+
+NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
+{
+#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
+    HANDLE thread;
+
+    driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __wine_usbhub_internal_ioctl;
+    driver->MajorFunction[IRP_MJ_PNP] = __wine_usbhub_dispatch_pnp;
+
+    thread = CreateThread( NULL, 0, enum_usb_devices, driver, 0, NULL );
+    if (!thread) return STATUS_UNSUCCESSFUL;
+    CloseHandle( thread );
+#else
+    TRACE( "USB support not compiled in\n" );
+#endif
+    return STATUS_SUCCESS;
+}
diff --git a/dlls/usbhub.sys/usbhub.sys.spec b/dlls/usbhub.sys/usbhub.sys.spec
new file mode 100644
index 0000000..76421d7
--- /dev/null
+++ b/dlls/usbhub.sys/usbhub.sys.spec
@@ -0,0 +1 @@
+# nothing to export
diff --git a/dlls/wineusbhub/Makefile.in b/dlls/wineusbhub/Makefile.in
deleted file mode 100644
index 4954a5d..0000000
--- a/dlls/wineusbhub/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR    = @srcdir@
-VPATH     = @srcdir@
-MODULE    = wineusbhub.dll
-IMPORTLIB = wineusbhub
-IMPORTS   = ntoskrnl.exe kernel32
-EXTRALIBS = @USBLIBS@
-
-C_SRCS = \
-	wineusbhub.c
-
- на MAKE_DLL_RULES@
-
- на DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/dlls/wineusbhub/wineusbhub.c b/dlls/wineusbhub/wineusbhub.c
deleted file mode 100644
index 8023a91..0000000
--- a/dlls/wineusbhub/wineusbhub.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-
-#ifdef HAVE_USB_H
-#include <usb.h>
-#endif
-
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "winternl.h"
-#include "cfgmgr32.h"
-#include "ddk/ntddk.h"
-#include "ddk/usb.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(wineusbhub);
-
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-extern void CDECL wine_complete_request( IRP *irp, UCHAR priority_boost );
-
-DRIVER_OBJECT hubdrv;
-DEVICE_OBJECT *usbdev = NULL;      /* USB PDO */
-static struct usb_device *dev;
-WCHAR bufW[20];
-UNICODE_STRING pdo_name = {0, 0, NULL};
-char instance_id[MAX_DEVICE_ID_LEN] = {0};
-
-static void add_data( char **dst, int *dst_size, void *src, int src_size )
-{
-    int copy;
-
-    copy = (src_size >= *dst_size) ? *dst_size : src_size;
-    memcpy( *dst, src, copy );
-    *dst += copy;
-    *dst_size -= copy;
-}
-
-NTSTATUS WINAPI __wine_usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
-{
-    IO_STACK_LOCATION *irpsp;
-    URB *urb;
-    NTSTATUS status = STATUS_UNSUCCESSFUL;
-
-    TRACE( "%p, %p\n", device, irp );
-
-    irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
-    urb = irpsp->Parameters.Others.Argument1;
-
-    switch (urb->u.UrbHeader.Function)
-    {
-    case URB_FUNCTION_SELECT_CONFIGURATION:
-        {
-            USB_CONFIGURATION_DESCRIPTOR *conf_desc =
-                    urb->u.UrbSelectConfiguration.ConfigurationDescriptor;
-            usb_dev_handle *husb;
-
-            TRACE( "URB_FUNCTION_SELECT_CONFIGURATION\n" );
-
-            husb = usb_open( dev );
-            if (husb)
-            {
-                int ret;
-
-                ret = usb_set_configuration( husb, conf_desc->bConfigurationValue );
-                if (ret < 0)
-                    ERR( "%s\n", usb_strerror() );
-                else
-                    status = STATUS_SUCCESS;
-                usb_close( husb );
-            }
-        }
-        break;
-    case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
-        {
-            struct _URB_CONTROL_DESCRIPTOR_REQUEST *request =
-                    &urb->u.UrbControlDescriptorRequest;
-
-            TRACE( "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n" );
-
-            switch (request->DescriptorType)
-            {
-            case USB_DEVICE_DESCRIPTOR_TYPE:
-                TRACE( "USB_DEVICE_DESCRIPTOR_TYPE\n" );
-                if (request->TransferBuffer == NULL)
-                    break;
-                if (sizeof(USB_DEVICE_DESCRIPTOR) <= request->TransferBufferLength)
-                {
-                    memcpy( request->TransferBuffer, &dev->descriptor,
-                            sizeof(USB_DEVICE_DESCRIPTOR) );
-                    status = STATUS_SUCCESS;
-                }
-                break;
-            case USB_CONFIGURATION_DESCRIPTOR_TYPE:
-                TRACE( "USB_CONFIGURATION_DESCRIPTOR_TYPE\n" );
-                {
-                    unsigned int i, k;
-                    char *buf = request->TransferBuffer;
-                    struct usb_config_descriptor *conf = &dev->config[0];
-                    struct usb_interface_descriptor *intf;
-                    struct usb_endpoint_descriptor *endp;
-                    int size = request->TransferBufferLength;
-
-                    /* FIXME: case of num_altsetting > 1 */
-
-                    if (buf == NULL)
-                        break;
-                    add_data( &buf, &size, conf,
-                            sizeof(USB_CONFIGURATION_DESCRIPTOR) );
-                    if (size > 0 && conf->extra)
-                        add_data( &buf, &size, conf->extra, conf->extralen );
-                    for (i = 0; i < conf->bNumInterfaces; ++i)
-                    {
-                        intf = &conf->interface[i].altsetting[0];
-                        if (size > 0)
-                            add_data( &buf, &size, intf,
-                                    sizeof(USB_INTERFACE_DESCRIPTOR) );
-                        if (size > 0 && intf->extra)
-                            add_data( &buf, &size, intf->extra, intf->extralen );
-                        for (k = 0; k < intf->bNumEndpoints; ++k)
-                        {
-                            endp = &intf->endpoint[k];
-                            if (size > 0)
-                                add_data( &buf, &size, endp,
-                                        sizeof(USB_ENDPOINT_DESCRIPTOR) );
-                            if (size > 0 && endp->extra)
-                                add_data( &buf, &size, endp->extra, endp->extralen );
-                        }
-                    }
-                    status = STATUS_SUCCESS;
-                }
-                break;
-            default:
-                FIXME( "unsupported descriptor type %x\n", request->DescriptorType );
-            }
-        }
-        break;
-    case URB_FUNCTION_VENDOR_DEVICE:
-    case URB_FUNCTION_VENDOR_INTERFACE:
-    case URB_FUNCTION_VENDOR_ENDPOINT:
-        {
-            usb_dev_handle *husb;
-            struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *request =
-                    &urb->u.UrbControlVendorClassRequest;
-
-            TRACE( "URB_FUNCTION_VENDOR_*\n" );
-
-            husb = usb_open( dev );
-            if (husb)
-            {
-                UCHAR req_type = request->RequestTypeReservedBits | (2 << 5);
-                char *buf;
-                int ret;
-
-                if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_INTERFACE)
-                    req_type |= 1;
-                else if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_ENDPOINT)
-                    req_type |= 2;
-                buf = HeapAlloc( GetProcessHeap(), 0, request->TransferBufferLength );
-                if (buf != NULL)
-                {
-                    memcpy( buf, request->TransferBuffer, request->TransferBufferLength );
-                    if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
-                        req_type |= (1 << 7);
-                    ret = usb_control_msg( husb, req_type, request->Request, request->Value,
-                            request->Index, buf, request->TransferBufferLength, 1000 );
-                    if (ret < 0)
-                        ERR( "%s\n", usb_strerror() );
-                    else
-                    {
-                        if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
-                        {
-                            request->TransferBufferLength =
-                                    (ret <= request->TransferBufferLength) ?
-                                    ret : request->TransferBufferLength;
-                            memcpy( request->TransferBuffer, buf,
-                                    request->TransferBufferLength );
-                        }
-                        status = STATUS_SUCCESS;
-                    }
-                    HeapFree( GetProcessHeap(), 0, buf );
-                }
-                usb_close( husb );
-            }
-        }
-        break;
-    default:
-        FIXME( "unsupported URB function %x\n", urb->u.UrbHeader.Function );
-    }
-
-    urb->u.UrbHeader.Status = status;
-    if (irp->UserIosb != NULL)
-    {
-        irp->UserIosb->u.Status = status;
-        irp->UserIosb->Information = 0;
-    }
-    irp->IoStatus.u.Status = status;
-    irp->IoStatus.Information = 0;
-    wine_complete_request( irp, IO_NO_INCREMENT );
-
-    return status;
-}
-
-NTSTATUS WINAPI __wine_usbhub_dispatch_pnp( DEVICE_OBJECT *device, IRP *irp )
-{
-    TRACE( "%p, %p\n", device, irp );
-
-    irp->IoStatus.u.Status = STATUS_SUCCESS;
-    irp->IoStatus.Information = 0;
-    wine_complete_request( irp, IO_NO_INCREMENT );
-
-    return STATUS_SUCCESS;
-}
-#endif
-
-DEVICE_OBJECT * CDECL __wine_usbhub_get_pdo( UCHAR *pdo_info )
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    static const WCHAR usbpdoW[] = {'\\','D','e','v','i','c','e','\\',
-                                    'U','S','B','P','D','O','-','%','u',0};
-    struct usb_bus *bus;
-
-    TRACE( "%u, %s, %s, %s\n", pdo_info[0], debugstr_a((char *)pdo_info + 1),
-            debugstr_a((char *)pdo_info + 2 + PATH_MAX),
-            debugstr_a((char *)pdo_info + 3 + 2 * PATH_MAX) );
-
-    for (bus = usb_busses; bus; bus = bus->next)
-        for (dev = bus->devices; dev; dev = dev->next)
-            if (!strcmp( bus->dirname, (char *)(pdo_info + 1) ) &&
-                    !strcmp( dev->filename, (char *)(pdo_info + 2 + PATH_MAX) ))
-            {
-                hubdrv.MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __wine_usbhub_internal_ioctl;
-                hubdrv.MajorFunction[IRP_MJ_PNP] = __wine_usbhub_dispatch_pnp;
-
-                strcpy( instance_id, (char *)pdo_info + 3 + 2 * PATH_MAX );
-                snprintfW( bufW, sizeof(bufW), usbpdoW, pdo_info[0] );
-                RtlInitUnicodeString( &pdo_name, bufW );
-
-                if (STATUS_SUCCESS == IoCreateDevice( &hubdrv, 0, &pdo_name, 0, 0, FALSE, &usbdev ))
-                {
-                    usbdev->Flags |= DO_BUS_ENUMERATED_DEVICE | DO_POWER_PAGABLE;
-                    return usbdev;
-                }
-            }
-#endif
-    return NULL;
-}
-
-UNICODE_STRING * CDECL __wine_usbhub_get_pdo_name()
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    if (pdo_name.Length)
-        return &pdo_name;
-#endif
-    return NULL;
-}
-
-char * CDECL __wine_usbhub_get_instance_id()
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    if (*instance_id)
-        return instance_id;
-#endif
-    return NULL;
-}
-
-USHORT CDECL __wine_usbhub_get_vid()
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    if (usbdev != NULL)
-        return dev->descriptor.idVendor;
-#endif
-    return 0;
-}
-
-USHORT CDECL __wine_usbhub_get_pid()
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    if (usbdev != NULL)
-        return dev->descriptor.idProduct;
-#endif
-    return 0;
-}
-
-BOOL WINAPI DllMain( HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv )
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    if (fdwReason == DLL_PROCESS_ATTACH)
-    {
-        usb_init();
-        usb_find_busses();
-        usb_find_devices();
-    }
-#endif
-    return TRUE;
-}
diff --git a/dlls/wineusbhub/wineusbhub.spec b/dlls/wineusbhub/wineusbhub.spec
deleted file mode 100644
index f277e0e..0000000
--- a/dlls/wineusbhub/wineusbhub.spec
+++ /dev/null
@@ -1,11 +0,0 @@
-##################
-# Wine extensions
-#
-# All functions must be prefixed with '__wine_' (for internal functions)
-# or 'wine_' (for user-visible functions) to avoid namespace conflicts.
-
-@ cdecl __wine_usbhub_get_pdo(ptr)
-@ cdecl __wine_usbhub_get_pdo_name()
-@ cdecl __wine_usbhub_get_instance_id()
-@ cdecl __wine_usbhub_get_vid()
-@ cdecl __wine_usbhub_get_pid()
diff --git a/programs/winedevice/Makefile.in b/programs/winedevice/Makefile.in
index 8b8b8dd..c644b7a 100644
--- a/programs/winedevice/Makefile.in
+++ b/programs/winedevice/Makefile.in
@@ -5,7 +5,7 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = winedevice.exe
 APPMODE   = -mwindows -municode
-IMPORTS   = advapi32 ntoskrnl.exe kernel32 ntdll wineusbhub
+IMPORTS   = advapi32 ntoskrnl.exe kernel32 ntdll
 
 C_SRCS = \
 	device.c
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index adf61a4..2d83d24 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -22,10 +22,6 @@
 #include "wine/port.h"
 
 #include <stdarg.h>
-#include <limits.h>
-
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -33,19 +29,17 @@
 #include "winbase.h"
 #include "winternl.h"
 #include "winreg.h"
-#include "winnls.h"
 #include "winsvc.h"
-#include "cfgmgr32.h"
 #include "ddk/ntddk.h"
 #include "wine/unicode.h"
-#include "wine/server.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(winedevice);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
 
-extern DEVICE_OBJECT * CDECL __wine_usbhub_get_pdo( UCHAR *pdo_info );
 extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event );
+extern BOOL CDECL __wine_add_driver_object( DRIVER_OBJECT *driver, const WCHAR *service );
+extern void CDECL __wine_del_driver_object( const DRIVER_OBJECT *driver );
 extern HANDLE CDECL __wine_make_process_system(void);
 
 #define EVENT_NAME_LEN (30 * sizeof(WCHAR))
@@ -475,95 +469,16 @@ static DWORD CALLBACK driver_thread( HANDLE pipe )
             &drv_name, &event_name );
     if (module)
     {
-        UNICODE_STRING drvname;
-        NTSTATUS ret = STATUS_SUCCESS;
-        IRP *irp;
-        IO_STACK_LOCATION *irpsp;
-        PDRIVER_DISPATCH dispatch;
         HANDLE loop_event;
 
         loop_event = CreateEventW( NULL, TRUE, FALSE, event_name );
-        RtlInitUnicodeString( &drvname, drv_name );
-
-        if (driver_extension.AddDevice)
-        {
-            NTSTATUS (WINAPI *AddDevice)( PDRIVER_OBJECT, PDEVICE_OBJECT ) =
-                    driver_extension.AddDevice;
-            PDEVICE_OBJECT pdev_obj = NULL;
-            UCHAR pdo_info[2 * PATH_MAX + 3 + MAX_DEVICE_ID_LEN];
-            data_size_t reply_size = 0;
-            HANDLE events[2] = {loop_event, NULL};
-            DWORD wait_ret;
-
-            while (!reply_size)
-            {
-                SERVER_START_REQ( get_add_device_request )
-                {
-                    req->event = events[1];
-                    wine_server_add_data( req, drvname.Buffer, drvname.Length );
-                    wine_server_set_reply( req, pdo_info, sizeof(pdo_info) );
-                    ret = wine_server_call( req );
-                    events[1] = reply->event;
-                    if (STATUS_SUCCESS == ret)
-                        reply_size = wine_server_reply_size( reply );
-                }
-                SERVER_END_REQ;
-
-                if (STATUS_PENDING == ret)
-                {
-                    wait_ret = WaitForMultipleObjects( 2, events, FALSE, INFINITE );
-                    if (wait_ret == WAIT_OBJECT_0)
-                        goto stop;
-                }
-            }
-
-            pdev_obj = __wine_usbhub_get_pdo( pdo_info );
-            if (pdev_obj)
-            {
-                WINE_TRACE( "calling AddDevice( %p, %p )\n", &driver_obj, pdev_obj );
-                ret = AddDevice( &driver_obj, pdev_obj );
-                if (STATUS_SUCCESS != ret)
-                    WINE_ERR( "AddDevice failed: %x\n", ret );
-            }
-            else
-            {
-                ret = STATUS_UNSUCCESSFUL;
-                WINE_ERR( "wineusbhub error\n" );
-            }
-        }
-
-        if (driver_obj.MajorFunction[IRP_MJ_PNP])
+        if (__wine_add_driver_object( &driver_obj, drv_name ))
         {
-            irp = IoAllocateIrp( driver_obj.DeviceObject->StackSize, FALSE );
-            if (irp != NULL)
-            {
-                --irp->CurrentLocation;
-                irpsp = --irp->Tail.Overlay.s.u.CurrentStackLocation;
-
-                irp->RequestorMode = KernelMode;
-                irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
-
-                irpsp->MajorFunction = IRP_MJ_PNP;
-                irpsp->MinorFunction = IRP_MN_START_DEVICE;
-                irpsp->DeviceObject = driver_obj.DeviceObject;
-
-                driver_obj.DeviceObject->CurrentIrp = irp;
-
-                dispatch = driver_obj.MajorFunction[IRP_MJ_PNP];
-                ret = dispatch( driver_obj.DeviceObject, irp );
-                if (STATUS_SUCCESS != ret)
-                    WINE_ERR( "MajorFunction[IRP_MJ_PNP] failed: %x\n", ret );
-
-                IoFreeIrp( irp );
-            }
-            else
-                ret = STATUS_UNSUCCESSFUL;
+            wine_ntoskrnl_main_loop( loop_event );
+            __wine_del_driver_object( &driver_obj );
         }
-
-        wine_ntoskrnl_main_loop( loop_event );
-        /* Stop service if wine_ntoskrnl_main_loop exits */
+        /* stop service if wine_ntoskrnl_main_loop exits */
         SetEvent( loop_event );
-stop:
         CloseHandle( loop_event );
         unload_driver( module, &driver_obj );
         HeapFree( GetProcessHeap(), 0, drv_name );
diff --git a/programs/wineusb/Makefile.in b/programs/wineusb/Makefile.in
deleted file mode 100644
index d2d0fdf..0000000
--- a/programs/wineusb/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR    = @srcdir@
-VPATH     = @srcdir@
-MODULE    = wineusb.exe
-APPMODE   = -mwindows -municode
-IMPORTS   = advapi32 ntoskrnl.exe kernel32 ntdll setupapi
-EXTRALIBS = @USBLIBS@
-
-C_SRCS = \
-	main.c
-
- на MAKE_PROG_RULES@
-
- на DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/programs/wineusb/main.c b/programs/wineusb/main.c
deleted file mode 100644
index 18eae1d..0000000
--- a/programs/wineusb/main.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Service process to call USB driver`s AddDevice routine
- *
- * Based on winedevice
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-
-#ifdef HAVE_USB_H
-#include <usb.h>
-#endif
-
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "winternl.h"
-#include "winreg.h"
-#include "winnls.h"
-#include "winsvc.h"
-#include "winuser.h"
-#include "setupapi.h"
-#include "cfgmgr32.h"
-#include "ddk/wdm.h"
-#include "ddk/usb.h"
-#include "wine/unicode.h"
-#include "wine/server.h"
-#include "wine/debug.h"
-#include "wine/list.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(wineusb);
-
-static WCHAR service_nameW[] = {'w','i','n','e','u','s','b',0};
-static SERVICE_STATUS_HANDLE service_handle;
-
-/* List of devices for which AddDevice was called */
-static struct list Devices = LIST_INIT(Devices);
-
-struct DeviceInstance
-{
-    struct list entry;
-    struct usb_device *dev;
-};
-
-static BOOL start_service( PWSTR name )
-{
-    SC_HANDLE scm, service;
-    BOOL ret;
-
-    scm = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
-    if (scm == NULL)
-        return FALSE;
-
-    service = OpenServiceW( scm, name, SERVICE_ALL_ACCESS );
-    if (service == NULL)
-    {
-        CloseServiceHandle( scm );
-        return FALSE;
-    }
-
-    ret = StartServiceW( service, 0, NULL );
-    if (!ret && ERROR_SERVICE_ALREADY_RUNNING == GetLastError())
-        ret = TRUE;
-
-    CloseServiceHandle( service );
-    CloseServiceHandle( scm );
-
-    return ret;
-}
-
-static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
-{
-    SERVICE_STATUS status;
-
-    status.dwServiceType             = SERVICE_WIN32;
-    status.dwControlsAccepted        = SERVICE_ACCEPT_STOP;
-    status.dwWin32ExitCode           = 0;
-    status.dwServiceSpecificExitCode = 0;
-    status.dwCheckPoint              = 0;
-    status.dwWaitHint                = 0;
-
-    switch(ctrl)
-    {
-    case SERVICE_CONTROL_STOP:
-    case SERVICE_CONTROL_SHUTDOWN:
-        WINE_TRACE( "shutting down\n" );
-        status.dwCurrentState     = SERVICE_STOP_PENDING;
-        status.dwControlsAccepted = 0;
-        SetServiceStatus( service_handle, &status );
-        return NO_ERROR;
-    default:
-        status.dwCurrentState = SERVICE_RUNNING;
-        SetServiceStatus( service_handle, &status );
-        return NO_ERROR;
-    }
-}
-
-static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
-{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    HDEVINFO set;
-    static const WCHAR usb[] = {'U','S','B',0};
-#endif
-    SERVICE_STATUS status;
-
-    WINE_TRACE( "starting service\n" );
-
-    service_handle = RegisterServiceCtrlHandlerExW( service_nameW, service_handler, NULL );
-    if (!service_handle)
-        return;
-
-    status.dwServiceType             = SERVICE_WIN32;
-    status.dwCurrentState            = SERVICE_RUNNING;
-    status.dwControlsAccepted        = 0;
-    status.dwWin32ExitCode           = 0;
-    status.dwServiceSpecificExitCode = 0;
-    status.dwCheckPoint              = 0;
-    status.dwWaitHint                = 10000;
-    SetServiceStatus( service_handle, &status );
-
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-    set = SetupDiGetClassDevsW( NULL, usb, 0, DIGCF_ALLCLASSES );
-    if (set != INVALID_HANDLE_VALUE)
-    {
-        struct DeviceInstance *instance, *instance2;
-        UNICODE_STRING drvname;
-        UCHAR pdo_info[2 * PATH_MAX + 3 + MAX_DEVICE_ID_LEN] = {0};
-        char instance_id[MAX_DEVICE_ID_LEN];
-        struct usb_device *dev;
-        struct usb_bus *bus;
-        SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
-        DWORD size = 0, i = 0;
-        USHORT vid, pid;
-        char *str;
-        BYTE *buf;
-        BOOL ret;
-
-        usb_init();
-        usb_find_busses();
-        usb_find_devices();
-
-        while (SetupDiEnumDeviceInfo( set, i++, &devInfo ))
-        {
-            SetupDiGetDeviceRegistryPropertyA( set, &devInfo, SPDRP_HARDWAREID,
-                    NULL, NULL, 0, &size );
-            buf = HeapAlloc( GetProcessHeap(), 0, size );
-            if (buf == NULL)
-            {
-                WINE_ERR( "insufficient memory\n" );
-                continue;
-            }
-            ret = SetupDiGetDeviceRegistryPropertyA( set, &devInfo, SPDRP_HARDWAREID,
-                    NULL, buf, size, NULL );
-            if (!ret)
-            {
-                WINE_ERR( "SetupDiGetDeviceRegistryPropertyA failed\n" );
-                HeapFree( GetProcessHeap(), 0, buf );
-                continue;
-            }
-            str = strstr( (char *)buf, "Vid_" );
-            if (str != NULL)
-            {
-                str += 4;
-                vid = strtol( str, NULL, 16 );
-                str = strstr( str, "Pid_" );
-            }
-            if (str == NULL)
-            {
-                WINE_ERR( "bad hardware ID\n" );
-                HeapFree( GetProcessHeap(), 0, buf );
-                continue;
-            }
-            str += 4;
-            pid = strtol( str, NULL, 16 );
-            HeapFree( GetProcessHeap(), 0, buf );
-
-            SetupDiGetDeviceInstanceIdA( set, &devInfo, NULL, 0, &size );
-            buf = HeapAlloc( GetProcessHeap(), 0, size );
-            if (buf == NULL)
-            {
-                WINE_ERR( "insufficient memory\n" );
-                continue;
-            }
-            ret = SetupDiGetDeviceInstanceIdA( set, &devInfo, (PSTR)buf, size, NULL );
-            if (!ret)
-            {
-                WINE_ERR( "SetupDiGetDeviceInstanceIdA failed\n" );
-                HeapFree( GetProcessHeap(), 0, buf );
-                continue;
-            }
-            str = strrchr( (char *)buf, '\\' );
-            if (str != NULL)
-                ++str;
-            if (str == NULL || *str == 0 || strlen( str ) >= MAX_DEVICE_ID_LEN)
-            {
-                WINE_ERR( "bad instance ID\n" );
-                HeapFree( GetProcessHeap(), 0, buf );
-                continue;
-            }
-            strcpy( instance_id, str );
-            HeapFree( GetProcessHeap(), 0, buf );
-
-            for (bus = usb_busses; bus && ret; bus = bus->next)
-                for (dev = bus->devices; dev && ret; dev = dev->next)
-                    if (dev->descriptor.idVendor == vid &&
-                            dev->descriptor.idProduct == pid)
-                    {
-                        int found = 0;
-
-                        LIST_FOR_EACH_ENTRY( instance, &Devices,
-                                struct DeviceInstance, entry )
-                        {
-                            if (instance->dev == dev)
-                            {
-                                found = 1;
-                                break;
-                            }
-                        }
-                        if (found)
-                            continue;
-
-                        instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
-                        if (instance == NULL)
-                        {
-                            WINE_ERR( "insufficient memory\n" );
-                            ret = FALSE;
-                            break;
-                        }
-
-                        SetupDiGetDeviceRegistryPropertyW( set, &devInfo,
-                                SPDRP_SERVICE, NULL, NULL, 0, &size );
-                        buf = HeapAlloc( GetProcessHeap(), 0, size );
-                        if (buf == NULL)
-                        {
-                            WINE_ERR( "insufficient memory\n" );
-                            ret = FALSE;
-                            break;
-                        }
-                        ret = SetupDiGetDeviceRegistryPropertyW( set, &devInfo,
-                                SPDRP_SERVICE, NULL, buf, size, NULL );
-                        if (!ret)
-                        {
-                            WINE_ERR( "SetupDiGetDeviceRegistryPropertyW failed\n" );
-                            HeapFree( GetProcessHeap(), 0, buf );
-                            break;
-                        }
-
-                        if (!start_service( (PWSTR)buf ))
-                        {
-                            HeapFree( GetProcessHeap(), 0, buf );
-                            HeapFree( GetProcessHeap(), 0, instance );
-                            ret = FALSE;
-                            break;
-                        }
-
-                        RtlInitUnicodeString( &drvname, (PWSTR)buf );
-                        str = (char *)pdo_info + 1;
-                        strcpy( str, bus->dirname );
-                        str += 1 + PATH_MAX;
-                        strcpy( str, dev->filename );
-                        str += 1 + PATH_MAX;
-                        strcpy( str, instance_id );
-
-                        SERVER_START_REQ( call_add_device )
-                        {
-                            req->drvname_len = drvname.Length;
-                            wine_server_add_data( req, drvname.Buffer, drvname.Length );
-                            wine_server_add_data( req, pdo_info, sizeof(pdo_info) );
-                            wine_server_call( req );
-                        }
-                        SERVER_END_REQ;
-
-                        instance->dev = dev;
-                        list_add_tail( &Devices, &instance->entry );
-
-                        ++pdo_info[0];
-                        HeapFree( GetProcessHeap(), 0, buf );
-                        ret = FALSE;
-                        break;
-                    }
-        }
-        SetupDiDestroyDeviceInfoList( set );
-
-        LIST_FOR_EACH_ENTRY_SAFE( instance, instance2, &Devices,
-                struct DeviceInstance, entry )
-        {
-            list_remove( &instance->entry );
-            HeapFree( GetProcessHeap(), 0, instance );
-        }
-    }
-    else
-        WINE_ERR( "SetupDiGetClassDevsW failed\n" );
-#endif
-
-    status.dwCurrentState     = SERVICE_STOPPED;
-    status.dwControlsAccepted = 0;
-    SetServiceStatus( service_handle, &status );
-    WINE_TRACE( "service stopped\n" );
-}
-
-int wmain( int argc, WCHAR *argv[] )
-{
-    SERVICE_TABLE_ENTRYW service_table[2];
-
-    service_table[0].lpServiceName = service_nameW;
-    service_table[0].lpServiceProc = ServiceMain;
-    service_table[1].lpServiceName = NULL;
-    service_table[1].lpServiceProc = NULL;
-
-    StartServiceCtrlDispatcherW( service_table );
-    return 0;
-}
diff --git a/tools/wine.inf.in b/tools/wine.inf.in
index 2857403..f08ecf8 100644
--- a/tools/wine.inf.in
+++ b/tools/wine.inf.in
@@ -80,12 +80,12 @@ AddReg=\
 [DefaultInstall.Services]
 AddService=MountMgr,0x800,MountMgrService
 AddService=Spooler,0,SpoolerService
-AddService=Wineusb,0,WineusbService
+AddService=Usbhub,0,UsbhubService
 
 [DefaultInstall.NT.Services]
 AddService=MountMgr,0x800,MountMgrService
 AddService=Spooler,0,SpoolerService
-AddService=Wineusb,0,WineusbService
+AddService=Usbhub,0,UsbhubService
 
 [Strings]
 MciExtStr="Software\Microsoft\Windows NT\CurrentVersion\MCI Extensions"
@@ -2324,6 +2324,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
 11,,ws2_32.dll
 11,,wsock32.dll
 12,,mountmgr.sys
+12,,usbhub.sys
 16422,Internet Explorer,iexplore.exe
 
 [SystemIni]
@@ -2719,11 +2720,9 @@ StartType=4
 ErrorControl=1
 LoadOrderGroup="SpoolerGroup"
 
-[WineusbService]
-Description="WineUSB"
-DisplayName="WineUSB"
-ServiceBinary="%11%\wineusb.exe"
-ServiceType=0x10
+[UsbhubService]
+ServiceBinary="%12%\usbhub.sys"
+ServiceType=1
 StartType=2
 ErrorControl=1
 
-- 
1.6.0.2.GIT



Подробная информация о списке рассылки Wine-patches