[Wine-patches] [eterhack] eterbug #6247

Alexander Morozov amorozov на etersoft.ru
Вт Апр 26 16:48:01 MSD 2011


----------- следующая часть -----------
From c4d327524cf5931a4da1b6a2a0599e0c9f7415b7 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Tue, 19 Apr 2011 20:35:11 +0400
Subject: [eterhack 1/7] Add int 0x2e support (eterbug #6247).

---
 dlls/kernel32/Makefile.in      |    1 +
 dlls/kernel32/instr.c          |  131 ++++++++++++++++++++++++++++++++++++++++
 dlls/kernel32/kernel_main.c    |    2 +
 dlls/kernel32/kernel_private.h |    2 +
 tools/winebuild/spec32.c       |   89 +++++++++++++++++++++++++++
 5 files changed, 225 insertions(+), 0 deletions(-)
 create mode 100644 dlls/kernel32/instr.c

diff --git a/dlls/kernel32/Makefile.in b/dlls/kernel32/Makefile.in
index 6c60623..4309a04 100644
--- a/dlls/kernel32/Makefile.in
+++ b/dlls/kernel32/Makefile.in
@@ -21,6 +21,7 @@ C_SRCS = \
 	file.c \
 	format_msg.c \
 	heap.c \
+	instr.c \
 	kernel_main.c \
 	lcformat.c \
 	locale.c \
diff --git a/dlls/kernel32/instr.c b/dlls/kernel32/instr.c
new file mode 100644
index 0000000..329db88
--- /dev/null
+++ b/dlls/kernel32/instr.c
@@ -0,0 +1,131 @@
+/*
+ * Emulation of privileged instructions
+ *
+ * Copyright 1995 Alexandre Julliard
+ * Copyright 2005 Ivan Leo Puoti
+ * Copyright 2005 Laurent Pinchart
+ * Copyright 2011 Alexander Morozov
+ *
+ * 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"
+
+#ifdef __i386__
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "excpt.h"
+#include "wine/debug.h"
+#include "wine/exception.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(int);
+
+static void *INSTR_get_ntdll_func( DWORD n )
+{
+    static const WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0};
+
+    HANDLE ntdll = GetModuleHandleW( ntdllW );
+    IMAGE_EXPORT_DIRECTORY *exports;
+    DWORD *func_addr, *func_name, size, k;
+    void *fptr;
+
+    exports = RtlImageDirectoryEntryToData( ntdll, TRUE,
+            IMAGE_DIRECTORY_ENTRY_EXPORT, &size );
+    func_addr = (DWORD *)((char *)ntdll + exports->AddressOfFunctions);
+    func_name = (DWORD *)((char *)ntdll + exports->AddressOfNames);
+    for (k = 0; k < exports->NumberOfFunctions; ++k)
+    {
+        if (func_addr[k] + (DWORD)ntdll > (DWORD)exports &&
+            func_addr[k] + (DWORD)ntdll < (DWORD)exports + size)
+            continue;  /* function is forwarded */
+        if (strncmp( (char *)((DWORD)ntdll + func_name[k]), "Nt", 2 ))
+            continue;  /* skip functions with names which do not begin from Nt */
+        fptr = (void *)((DWORD)ntdll + func_addr[k]);
+        if (*(DWORD *)((char *)fptr + 1) == n)
+        {
+            TRACE( "%d -> %p\n", n, fptr );
+            return fptr;
+        }
+    }
+    return NULL;
+}
+
+extern int CDECL INSTR_syscall( void *func, DWORD params );
+__ASM_GLOBAL_FUNC( INSTR_syscall,
+                   "pushl %ebp\n\t"
+                   "movl %esp,%ebp\n\t"
+                   "movl 12(%ebp),%esi\n\t"
+                   "subl $80,%esp\n\t"
+                   "movl %esp,%edi\n\t"
+                   "movl $20,%ecx\n\t"
+                   "rep movsl\n\t"
+                   "call *8(%ebp)\n\t"
+                   "movl %ebp,%esp\n\t"
+                   "popl %ebp\n\t"
+                   "ret" )
+
+
+/***********************************************************************
+ *           emulate_instruction
+ *
+ * Emulate a privileged instruction.
+ * Returns exception continuation status.
+ */
+static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
+{
+    BYTE *instr;
+
+    instr = (BYTE *)context->Eip;
+    if (!instr) return ExceptionContinueSearch;
+
+    if (*(WORD *)instr == 0x2ecd)  /* int 0x2e */
+    {
+        void *ptr = INSTR_get_ntdll_func( context->Eax );
+
+        if (!ptr) return ExceptionContinueSearch;
+        context->Eax = INSTR_syscall( ptr, context->Edx );
+        context->Eip += 2;
+        return ExceptionContinueExecution;
+    }
+    return ExceptionContinueSearch;  /* Unable to emulate it */
+}
+
+
+/***********************************************************************
+ *           INSTR_vectored_handler
+ *
+ * Vectored exception handler used to emulate protected instructions
+ * from 32-bit code.
+ */
+LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs )
+{
+    EXCEPTION_RECORD *record = ptrs->ExceptionRecord;
+    CONTEXT *context = ptrs->ContextRecord;
+
+    if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
+        record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION)
+    {
+        if (emulate_instruction( record, context ) == ExceptionContinueExecution)
+            return EXCEPTION_CONTINUE_EXECUTION;
+    }
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+#endif  /* __i386__ */
diff --git a/dlls/kernel32/kernel_main.c b/dlls/kernel32/kernel_main.c
index fc0bc90..5976557 100644
--- a/dlls/kernel32/kernel_main.c
+++ b/dlls/kernel32/kernel_main.c
@@ -114,6 +114,8 @@ static BOOL process_attach( HMODULE module )
          * ole implementation works right we need the shared heap*/
         /* create the shared heap for broken win95 native dlls */
         HeapCreate( HEAP_SHARED, 0, 0 );
+        /* setup emulation of protected instructions from 32-bit code */
+        RtlAddVectoredExceptionHandler( TRUE, INSTR_vectored_handler );
 #endif
     }
     else LoadLibraryA( "krnl386.exe16" );
diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h
index f180e7d..288bc38 100644
--- a/dlls/kernel32/kernel_private.h
+++ b/dlls/kernel32/kernel_private.h
@@ -62,6 +62,8 @@ extern void FILE_SetDosError(void);
 extern WCHAR *FILE_name_AtoW( LPCSTR name, BOOL alloc );
 extern DWORD FILE_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen );
 
+extern LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs );
+
 /* return values for MODULE_GetBinaryType */
 enum binary_type
 {
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index e16260a..efafa26 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -46,6 +46,8 @@
 #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
 #define IMAGE_ROM_OPTIONAL_HDR_MAGIC  0x107
 
+static int *ntdll_ep;
+
 /* check if entry point needs a relay thunk */
 static inline int needs_relay( const ORDDEF *odp )
 {
@@ -81,6 +83,86 @@ int has_relays( DLLSPEC *spec )
     return 0;
 }
 
+static int needs_ntdll_ep( const DLLSPEC *spec, const ORDDEF *odp )
+{
+    if (target_cpu != CPU_x86 || strcmp(spec->file_name, "ntdll.dll"))
+        return 0;
+    if (!odp)
+        return 1;
+    else
+        return (odp->type == TYPE_STDCALL || odp->type == TYPE_STUB) &&
+                !(odp->flags & (FLAG_FORWARD | FLAG_EXT_LINK | FLAG_REGISTER)) &&
+                (!strncmp(odp->name, "Nt", 2) || !strncmp(odp->name, "Zw", 2));
+}
+
+static void generate_ntdll_call_nums( const DLLSPEC *spec )
+{
+    int nt, nt_end, zw, zw_end, r, i = 0;
+
+    if (!needs_ntdll_ep( spec, NULL )) return;
+    ntdll_ep = xmalloc( spec->limit * sizeof(int) );
+
+    for (nt = spec->base; nt <= spec->limit; nt++)
+        if (!strncmp(spec->ordinals[nt]->name, "Nt", 2))
+            break;
+    for (nt_end = nt; nt_end <= spec->limit; nt_end++)
+        if (strncmp(spec->ordinals[nt_end]->name, "Nt", 2))
+            break;
+    for (zw = nt_end; zw <= spec->limit; zw++)
+        if (!strncmp(spec->ordinals[zw]->name, "Zw", 2))
+            break;
+    for (zw_end = zw; zw_end <= spec->limit; zw_end++)
+        if (strncmp(spec->ordinals[zw_end]->name, "Zw", 2))
+            break;
+
+    while (nt < nt_end && zw < zw_end)
+    {
+        r = strcmp(spec->ordinals[nt]->name + 2, spec->ordinals[zw]->name + 2);
+        if (!r)
+        {
+            ntdll_ep[nt++] = i;
+            ntdll_ep[zw++] = i++;
+        }
+        else if (r < 0)
+            ntdll_ep[nt++] = i++;
+        else
+            ntdll_ep[zw++] = i++;
+    }
+}
+
+static const char *get_ntdll_ep_name( int i )
+{
+    static char buffer[256];
+    sprintf( buffer, ".L__wine_spec_ntdll_entry_point_%d", i );
+    return buffer;
+}
+
+static void output_ntdll_entry_points( const DLLSPEC *spec )
+{
+    int i;
+
+    if (!needs_ntdll_ep( spec, NULL )) return;
+
+    output( "\t.text\n" );
+    output( "__wine_spec_ntdll_entry_points:\n" );
+
+    for (i = spec->base; i <= spec->limit; i++)
+    {
+        ORDDEF *odp = spec->ordinals[i];
+
+        if (!needs_ntdll_ep( spec, odp )) continue;
+
+        output( "\t.align %d\n", get_alignment(4) );
+        output( "%s:\n", asm_name(get_ntdll_ep_name(i)) );
+        output( "\tmovl $%d,%%eax\n", ntdll_ep[i] );
+
+        if (odp->type == TYPE_STUB)
+            output( "\tjmp %s\n", asm_name(get_stub_name( odp, spec )) );
+        else
+            output( "\tjmp %s\n", asm_name(odp->link_name) );
+    }
+}
+
 /*******************************************************************
  *         output_relay_debug
  *
@@ -156,6 +238,8 @@ static void output_relay_debug( DLLSPEC *spec )
         switch (target_cpu)
         {
         case CPU_x86:
+            if (needs_ntdll_ep( spec, odp ))
+                output( "\tmovl $%d,%%eax\n", ntdll_ep[i] );
             if (odp->type == TYPE_THISCALL)  /* add the this pointer */
             {
                 output( "\tpopl %%eax\n" );
@@ -266,6 +350,8 @@ void output_exports( DLLSPEC *spec )
     {
         ORDDEF *odp = spec->ordinals[i];
         if (!odp) output( "\t%s 0\n", get_asm_ptr_keyword() );
+        else if (needs_ntdll_ep( spec, odp ))
+            output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(get_ntdll_ep_name(i)) );
         else switch(odp->type)
         {
         case TYPE_EXTERN:
@@ -363,7 +449,10 @@ void output_exports( DLLSPEC *spec )
     output( "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
     output( "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
 
+    generate_ntdll_call_nums( spec );
     output_relay_debug( spec );
+    output_ntdll_entry_points( spec );
+    free( ntdll_ep );
 }
 
 
-- 
1.7.4.4

----------- следующая часть -----------
From d5754cab4cbecb72f7dd6347239d0f42b8d7eef2 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 21 Apr 2011 21:55:09 +0400
Subject: [eterhack 2/7] mountmgr.sys: Create HCD* devices (eterbug #6247).

---
 dlls/mountmgr.sys/usbhub.c |   74 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/dlls/mountmgr.sys/usbhub.c b/dlls/mountmgr.sys/usbhub.c
index ef9e174..ab33fe5 100644
--- a/dlls/mountmgr.sys/usbhub.c
+++ b/dlls/mountmgr.sys/usbhub.c
@@ -65,6 +65,7 @@ extern BOOL CDECL __wine_start_service( const WCHAR *name );
 static const WCHAR usbW[] = {'U','S','B',0};
 
 static struct list RootDevices = LIST_INIT(RootDevices);
+static struct list HostControllers = LIST_INIT(HostControllers);
 static struct list Devices = LIST_INIT(Devices);
 
 struct RootDevInstance
@@ -73,6 +74,13 @@ struct RootDevInstance
     DEVICE_OBJECT *pdo;
 };
 
+struct HCDInstance
+{
+    struct list entry;
+    DEVICE_OBJECT *dev;
+    WCHAR *root_hub_name;
+};
+
 struct DeviceInstance
 {
     struct list entry;
@@ -1278,7 +1286,8 @@ static DEVICE_OBJECT *create_pdo( struct DeviceInstance *inst,
     return usbdev;
 }
 
-static void register_root_hub_device( DEVICE_OBJECT *dev, unsigned int instance_id )
+static BOOL register_root_hub_device( DEVICE_OBJECT *dev,
+        unsigned int instance_id, UNICODE_STRING *link )
 {
     static const WCHAR root_hub_idW[] = {'U','S','B',
                                          '\\','R','O','O','T','_','H','U','B',
@@ -1289,12 +1298,11 @@ static void register_root_hub_device( DEVICE_OBJECT *dev, unsigned int instance_
     WCHAR *devnameW;
     ULONG size;
     BOOL ret;
-    UNICODE_STRING link;
-    NTSTATUS status;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
 
     size = sizeof(root_hub_idW) + 16 * sizeof(WCHAR);
     devnameW = HeapAlloc( GetProcessHeap(), 0, size );
-    if (devnameW == NULL) return;
+    if (devnameW == NULL) return FALSE;
     snprintfW( devnameW, size / sizeof(WCHAR), root_hub_idW, instance_id );
 
     set = SetupDiGetClassDevsW( NULL, usbW, 0, DIGCF_ALLCLASSES );
@@ -1310,16 +1318,57 @@ static void register_root_hub_device( DEVICE_OBJECT *dev, unsigned int instance_
     else if (ERROR_DEVINST_ALREADY_EXISTS != GetLastError()) goto done;
 
     status = IoRegisterDeviceInterface( dev, &GUID_DEVINTERFACE_USB_HUB,
-            NULL, &link );
+            NULL, link );
     if (status == STATUS_SUCCESS)
-    {
-        IoSetDeviceInterfaceState( &link, TRUE );
-        RtlFreeUnicodeString( &link );
-    }
+        IoSetDeviceInterfaceState( link, TRUE );
 done:
     if (set != INVALID_HANDLE_VALUE)
         SetupDiDestroyDeviceInfoList( set );
     HeapFree( GetProcessHeap(), 0, devnameW );
+    return (status == STATUS_SUCCESS) ? TRUE : FALSE;
+}
+
+static void create_hcd_device( unsigned int instance_id, DRIVER_OBJECT *hubdrv,
+        UNICODE_STRING *link )
+{
+    static const WCHAR usbfdoW[] = {'\\','D','e','v','i','c','e',
+                                    '\\','U','S','B','F','D','O','-','%','u',0};
+    static const WCHAR usbhcdW[] = {'\\','D','o','s','D','e','v','i','c','e','s',
+                                    '\\','H','C','D','%','u',0};
+
+    WCHAR *fdo_buf = RtlAllocateHeap( GetProcessHeap(), 0, 30 * sizeof(WCHAR) );
+    WCHAR *hcd_buf = RtlAllocateHeap( GetProcessHeap(), 0, 30 * sizeof(WCHAR) );
+    UNICODE_STRING fdo_name, hcd_name;
+    struct HCDInstance *instance = NULL;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+
+    if (fdo_buf == NULL || hcd_buf == NULL) goto done;
+    instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
+    if (instance == NULL) goto done;
+    instance->root_hub_name = HeapAlloc( GetProcessHeap(), 0,
+            link->Length + sizeof(WCHAR) );
+    if (instance->root_hub_name == NULL) goto done;
+    memcpy( instance->root_hub_name, link->Buffer, link->Length );
+    instance->root_hub_name[link->Length / sizeof(WCHAR)] = 0;
+
+    snprintfW( fdo_buf, 30, usbfdoW, instance_id );
+    RtlInitUnicodeString( &fdo_name, fdo_buf );
+    snprintfW( hcd_buf, 30, usbhcdW, instance_id );
+    RtlInitUnicodeString( &hcd_name, hcd_buf );
+
+    status = IoCreateDevice( hubdrv, 0, &fdo_name, 0, 0, FALSE, &instance->dev );
+    if (status != STATUS_SUCCESS) goto done;
+    IoCreateSymbolicLink( &hcd_name, &fdo_name );
+    instance->dev->Flags &= ~DO_DEVICE_INITIALIZING;
+    list_add_tail( &HostControllers, &instance->entry );
+done:
+    if (status != STATUS_SUCCESS && instance != NULL)
+    {
+        HeapFree( GetProcessHeap(), 0, instance->root_hub_name );
+        HeapFree( GetProcessHeap(), 0, instance );
+    }
+    RtlFreeUnicodeString( &fdo_name );
+    RtlFreeUnicodeString( &hcd_name );
 }
 
 static void create_root_hub_device( USHORT vid, USHORT pid, void *dev,
@@ -1327,6 +1376,7 @@ static void create_root_hub_device( USHORT vid, USHORT pid, void *dev,
 {
     static unsigned int instance_id;
     struct DeviceInstance *instance = NULL;
+    UNICODE_STRING link;
 
     instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
     if (instance == NULL) return;
@@ -1341,7 +1391,11 @@ static void create_root_hub_device( USHORT vid, USHORT pid, void *dev,
     instance->pdo = create_pdo( instance, hubdrv, DO_POWER_PAGABLE );
     if (instance->pdo == NULL) goto fail;
     list_add_tail( &Devices, &instance->entry );
-    register_root_hub_device( instance->pdo, instance_id );
+    if (register_root_hub_device( instance->pdo, instance_id, &link ))
+    {
+        create_hcd_device( instance_id, hubdrv, &link );
+        RtlFreeUnicodeString( &link );
+    }
     ++instance_id;
     return;
 fail:
-- 
1.7.4.4

----------- следующая часть -----------
From fa0332408a880d366cdd209bb946ddd1d2f865a5 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 21 Apr 2011 19:30:44 +0400
Subject: [eterhack 3/7] include: Add IOCTL_USB_GET_ROOT_HUB_NAME declaration
 (eterbug #6247).

---
 include/ddk/usbioctl.h |    2 ++
 include/ddk/usbiodef.h |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/include/ddk/usbioctl.h b/include/ddk/usbioctl.h
index fd80b11..89fc9a6 100644
--- a/include/ddk/usbioctl.h
+++ b/include/ddk/usbioctl.h
@@ -26,6 +26,8 @@
 #define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION    CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
+#define IOCTL_USB_GET_ROOT_HUB_NAME CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
 /* Wine extensions */
 #ifdef WINE_USBHUB_EXTENSIONS
 
diff --git a/include/ddk/usbiodef.h b/include/ddk/usbiodef.h
index 7d26f48..05da9ae 100644
--- a/include/ddk/usbiodef.h
+++ b/include/ddk/usbiodef.h
@@ -25,6 +25,8 @@
 #define USB_GET_NODE_CONNECTION_INFORMATION    259
 #define USB_GET_NODE_CONNECTION_DRIVERKEY_NAME 264
 
+#define HCD_GET_ROOT_HUB_NAME    258
+
 #ifdef WINE_USBHUB_EXTENSIONS
 #define USB_GET_DEVICE_INFO                 280
 #endif
-- 
1.7.4.4

----------- следующая часть -----------
From 164e6ce41cb0fe47d8537e4ffe09a48a65d0a5c6 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 22 Apr 2011 20:10:58 +0400
Subject: [eterhack 4/7] mountmgr.sys: Use separate functions for various
 IOCTLs (eterbug #6247).

---
 dlls/mountmgr.sys/usbhub.c |  457 ++++++++++++++++++++++----------------------
 1 files changed, 230 insertions(+), 227 deletions(-)

diff --git a/dlls/mountmgr.sys/usbhub.c b/dlls/mountmgr.sys/usbhub.c
index ab33fe5..ac9770d 100644
--- a/dlls/mountmgr.sys/usbhub.c
+++ b/dlls/mountmgr.sys/usbhub.c
@@ -63,6 +63,9 @@ extern BOOL CDECL __wine_start_service( const WCHAR *name );
 #define NUMBER_OF_PORTS 8
 
 static const WCHAR usbW[] = {'U','S','B',0};
+static const WCHAR device_idW[] = {'U','S','B','\\',
+                                   'V','i','d','_','%','0','4','x','&',
+                                   'P','i','d','_','%','0','4','x','\\',0};
 
 static struct list RootDevices = LIST_INIT(RootDevices);
 static struct list HostControllers = LIST_INIT(HostControllers);
@@ -134,268 +137,268 @@ static void add_data( unsigned char **dst, ULONG *dst_size, const void *src, ULO
     *dst_size -= copy;
 }
 
-static NTSTATUS WINAPI usbhub_ioctl( DEVICE_OBJECT *device, IRP *irp )
+#ifdef HAVE_LIBUSB_H
+
+struct DeviceInstance *get_device_by_index( libusb_device *device,
+        ULONG connection_index, ULONG *addr )
 {
-    static const WCHAR device_idW[] = {'U','S','B','\\',
-                                       'V','i','d','_','%','0','4','x','&',
-                                       'P','i','d','_','%','0','4','x','\\',0};
-    static const WCHAR root_hub_idW[] = {'U','S','B','\\',
-                                         'R','O','O','T','_','H','U','B','\\',0};
+    struct DeviceInstance *instance;
+    uint8_t bus_number = libusb_get_bus_number( device );
+    ULONG index = 0;
 
-    IO_STACK_LOCATION *irpsp;
-    NTSTATUS status = STATUS_UNSUCCESSFUL;
-    struct DeviceInstance *inst;
-    ULONG_PTR info = 0;
+    LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+        if (instance->dev && instance->dev != device &&
+            libusb_get_bus_number( instance->dev ) == bus_number &&
+            ++index == connection_index)
+        {
+            if (addr)
+                *addr = libusb_get_device_address( instance->dev );
+            return instance;
+        }
+    return NULL;
+}
 
-    TRACE( "%p, %p\n", device, irp );
+#else  /* HAVE_LIBUSB_H */
 
-    EnterCriticalSection( &usbhub_cs );
-    if (!device_exists( device )) goto done;
-    inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
-    if (inst->service) goto done;
-    irpsp = IoGetCurrentIrpStackLocation( irp );
+struct DeviceInstance *get_device_by_index( struct usb_device *device,
+        ULONG connection_index, ULONG *addr )
+{
+    struct DeviceInstance *instance;
+    struct usb_device *dev;
+    ULONG index = 0;
 
-    switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
-    {
-    case IOCTL_USB_GET_NODE_INFORMATION:
-    {
-        USB_NODE_INFORMATION *node_info = irp->AssociatedIrp.SystemBuffer;
+    for (dev = device->next; dev; dev = dev->next)
+        if (++index == connection_index)
+            LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+                if (instance->dev == dev)
+                {
+                    if (addr)
+                        *addr = dev->devnum;
+                    return instance;
+                }
+    return NULL;
+}
+
+#endif  /* HAVE_LIBUSB_H */
+
+static NTSTATUS get_node_info( void *buff, ULONG size, ULONG_PTR *outsize )
+{
+    USB_NODE_INFORMATION *node_info = buff;
+
+    if (size < sizeof(*node_info))
+        return STATUS_BUFFER_TOO_SMALL;
+    RtlZeroMemory( node_info, sizeof(*node_info) );
+    node_info->u.HubInformation.HubDescriptor.bDescriptorLength = 9;
+    node_info->u.HubInformation.HubDescriptor.bDescriptorType = 41;
+    node_info->u.HubInformation.HubDescriptor.bNumberOfPorts = NUMBER_OF_PORTS;
+    *outsize = sizeof(*node_info);
+    return STATUS_SUCCESS;
+}
 
-        if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*node_info))
-        {
-            status = STATUS_BUFFER_TOO_SMALL;
-            break;
-        }
-        RtlZeroMemory( node_info, sizeof(*node_info) );
-        node_info->u.HubInformation.HubDescriptor.bDescriptorLength = 9;
-        node_info->u.HubInformation.HubDescriptor.bDescriptorType = 41;
-        node_info->u.HubInformation.HubDescriptor.bNumberOfPorts = NUMBER_OF_PORTS;
-        status = STATUS_SUCCESS;
-        info = sizeof(*node_info);
-        break;
-    }
-    case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
-    {
-        USB_NODE_CONNECTION_INFORMATION *conn_info = irp->AssociatedIrp.SystemBuffer;
-        ULONG index = 0;
 #ifdef HAVE_LIBUSB_H
-        struct DeviceInstance *instance;
-        uint8_t bus_number = libusb_get_bus_number( inst->dev );
-#else
-        struct usb_device *dev;
-#endif
 
-        if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*conn_info))
+static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
+        ULONG size, ULONG_PTR *outsize )
+{
+    USB_NODE_CONNECTION_INFORMATION *conn_info = buff;
+    ULONG index = 0;
+    struct DeviceInstance *instance;
+    uint8_t bus_number = libusb_get_bus_number( inst->dev );
+
+    if (size < sizeof(*conn_info))
+        return STATUS_BUFFER_TOO_SMALL;
+    if (!conn_info->ConnectionIndex ||
+        conn_info->ConnectionIndex > NUMBER_OF_PORTS)
+        return STATUS_INVALID_PARAMETER;
+    RtlZeroMemory( (ULONG *)conn_info + 1, sizeof(*conn_info) - sizeof(ULONG) );
+    LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+    {
+        if (instance->dev && instance->dev != inst->dev &&
+            libusb_get_bus_number( instance->dev ) == bus_number &&
+            ++index == conn_info->ConnectionIndex)
         {
-            status = STATUS_BUFFER_TOO_SMALL;
+            struct libusb_device_descriptor desc;
+
+            if (libusb_get_device_descriptor( instance->dev, &desc ))
+                break;
+            memcpy( &conn_info->DeviceDescriptor, &desc,
+                    sizeof(USB_DEVICE_DESCRIPTOR) );
+            conn_info->ConnectionStatus = 1;
             break;
         }
-        if (!conn_info->ConnectionIndex || conn_info->ConnectionIndex > NUMBER_OF_PORTS)
+    }
+    *outsize = sizeof(*conn_info);
+    return STATUS_SUCCESS;
+}
+
+#else  /* HAVE_LIBUSB_H */
+
+static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
+        ULONG size, ULONG_PTR *outsize )
+{
+    USB_NODE_CONNECTION_INFORMATION *conn_info = buff;
+    ULONG index = 0;
+    struct usb_device *dev;
+
+    if (size < sizeof(*conn_info))
+        return STATUS_BUFFER_TOO_SMALL;
+    if (!conn_info->ConnectionIndex ||
+        conn_info->ConnectionIndex > NUMBER_OF_PORTS)
+        return STATUS_INVALID_PARAMETER;
+    RtlZeroMemory( (ULONG *)conn_info + 1, sizeof(*conn_info) - sizeof(ULONG) );
+    for (dev = inst->dev->next; dev; dev = dev->next)
+        if (++index == conn_info->ConnectionIndex)
         {
-            status = STATUS_INVALID_PARAMETER;
+            memcpy( &conn_info->DeviceDescriptor, &dev->descriptor,
+                    sizeof(USB_DEVICE_DESCRIPTOR) );
+            conn_info->ConnectionStatus = 1;
             break;
         }
-        RtlZeroMemory( (ULONG *)conn_info + 1, sizeof(*conn_info) - sizeof(ULONG) );
-#ifdef HAVE_LIBUSB_H
-        LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
-        {
-            if (instance->dev && instance->dev != inst->dev &&
-                libusb_get_bus_number( instance->dev ) == bus_number &&
-                ++index == conn_info->ConnectionIndex)
-            {
-                struct libusb_device_descriptor desc;
+    *outsize = sizeof(*conn_info);
+    return STATUS_SUCCESS;
+}
 
-                if (libusb_get_device_descriptor( instance->dev, &desc ))
-                    break;
-                memcpy( &conn_info->DeviceDescriptor, &desc,
-                        sizeof(USB_DEVICE_DESCRIPTOR) );
-                conn_info->ConnectionStatus = 1;
-                break;
-            }
-        }
-#else
-        for (dev = inst->dev->next; dev; dev = dev->next)
-            if (++index == conn_info->ConnectionIndex)
-            {
-                memcpy( &conn_info->DeviceDescriptor, &dev->descriptor,
-                        sizeof(USB_DEVICE_DESCRIPTOR) );
-                conn_info->ConnectionStatus = 1;
-                break;
-            }
-#endif
-        status = STATUS_SUCCESS;
-        info = sizeof(*conn_info);
-        break;
+#endif  /* HAVE_LIBUSB_H */
+
+static NTSTATUS get_node_conn_driverkey_name( struct DeviceInstance *inst,
+        void *buff, ULONG size, ULONG_PTR *outsize )
+{
+    USB_NODE_CONNECTION_DRIVERKEY_NAME *driver_key_name = buff;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    WCHAR *dev_instance_idW, *bufW;
+    struct DeviceInstance *instance;
+    HDEVINFO set;
+    SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
+    ULONG len, index = 0;
+
+    if (size < sizeof(*driver_key_name))
+        return STATUS_BUFFER_TOO_SMALL;
+    instance = get_device_by_index( inst->dev,
+            driver_key_name->ConnectionIndex, NULL );
+    if (instance == NULL)
+        return STATUS_INVALID_PARAMETER;
+    bufW = HeapAlloc( GetProcessHeap(), 0,
+            2 * MAX_DEVICE_ID_LEN * sizeof(WCHAR) );
+    if (bufW == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    dev_instance_idW = bufW + MAX_DEVICE_ID_LEN;
+    snprintfW( dev_instance_idW, MAX_DEVICE_ID_LEN, device_idW, instance->vid,
+            instance->pid );
+    len = strlenW(dev_instance_idW);
+    RtlMultiByteToUnicodeN( dev_instance_idW + len,
+            (MAX_DEVICE_ID_LEN - len) * sizeof(WCHAR), NULL,
+            instance->instance_id, strlen(instance->instance_id) + 1 );
+    set = SetupDiGetClassDevsW( NULL, usbW, 0, DIGCF_ALLCLASSES );
+    if (set == INVALID_HANDLE_VALUE)
+    {
+        HeapFree( GetProcessHeap(), 0, bufW );
+        return STATUS_UNSUCCESSFUL;
     }
-    case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
+    while (SetupDiEnumDeviceInfo( set, index++, &devInfo ))
     {
-        USB_NODE_CONNECTION_DRIVERKEY_NAME *driver_key_name =
-                irp->AssociatedIrp.SystemBuffer;
-        WCHAR *dev_instance_idW, *bufW;
-        struct DeviceInstance *instance;
-        HDEVINFO set;
-        SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
-        ULONG len, index = 0, found = 0;
-#ifdef HAVE_LIBUSB_H
-        uint8_t bus_number = libusb_get_bus_number( inst->dev );
-#else
-        struct usb_device *dev;
-#endif
-
-        if (irpsp->Parameters.DeviceIoControl.OutputBufferLength <
-                sizeof(*driver_key_name))
-        {
-            status = STATUS_BUFFER_TOO_SMALL;
+        if (!SetupDiGetDeviceInstanceIdW( set, &devInfo, bufW,
+                MAX_DEVICE_ID_LEN, NULL ))
             break;
-        }
-#ifdef HAVE_LIBUSB_H
-        LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+        if (!strcmpiW( dev_instance_idW, bufW ))
         {
-            if (instance->dev && instance->dev != inst->dev &&
-                libusb_get_bus_number( instance->dev ) == bus_number &&
-                ++index == driver_key_name->ConnectionIndex)
+            SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_DRIVER,
+                    NULL, NULL, 0, &len );
+            driver_key_name->ActualLength = 2 * sizeof(ULONG) + len;
+            if (size < driver_key_name->ActualLength)
             {
-                found = 1;
-                break;
+                status = STATUS_SUCCESS;
+                *outsize = sizeof(*driver_key_name);
             }
-        }
-#else
-        for (dev = inst->dev->next; dev; dev = dev->next)
-            if (++index == driver_key_name->ConnectionIndex)
+            else if (SetupDiGetDeviceRegistryPropertyW( set, &devInfo,
+                    SPDRP_DRIVER, NULL, (BYTE *)driver_key_name->DriverKeyName,
+                    len, NULL ))
             {
-                LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
-                {
-                    if (instance->dev == dev)
-                    {
-                        found = 1;
-                        break;
-                    }
-                }
-                break;
+                status = STATUS_SUCCESS;
+                *outsize = driver_key_name->ActualLength;
             }
-#endif
-        if (!found)
-        {
-            status = STATUS_INVALID_PARAMETER;
-            break;
-        }
-        bufW = HeapAlloc( GetProcessHeap(), 0,
-                2 * MAX_DEVICE_ID_LEN * sizeof(WCHAR) );
-        if (bufW == NULL)
-        {
-            status = STATUS_INSUFFICIENT_RESOURCES;
             break;
         }
-        dev_instance_idW = bufW + MAX_DEVICE_ID_LEN;
-        snprintfW( dev_instance_idW, MAX_DEVICE_ID_LEN, device_idW,
+    }
+    SetupDiDestroyDeviceInfoList( set );
+    HeapFree( GetProcessHeap(), 0, bufW );
+    return status;
+}
+
+static NTSTATUS get_device_info( struct DeviceInstance *inst, void *buff,
+        ULONG size, ULONG_PTR *outsize )
+{
+    static const WCHAR root_hub_idW[] = {'U','S','B','\\',
+                                         'R','O','O','T','_','H','U','B',0};
+
+    struct usb_device_info *dev_info = buff;
+    struct DeviceInstance *instance;
+    ULONG len;
+
+    if (size < sizeof(*dev_info))
+        return STATUS_BUFFER_TOO_SMALL;
+    if (!dev_info->connection_index ||
+        dev_info->connection_index > NUMBER_OF_PORTS)
+        return STATUS_INVALID_PARAMETER;
+    RtlZeroMemory( (ULONG *)dev_info + 1, sizeof(*dev_info) - sizeof(ULONG) );
+    memcpy( dev_info->root_hub_id, root_hub_idW, sizeof(root_hub_idW) );
+    len = strlenW(root_hub_idW);
+    RtlMultiByteToUnicodeN( dev_info->root_hub_id + len,
+            (MAX_DEVICE_ID_LEN - len) * sizeof(WCHAR), NULL, inst->instance_id,
+            strlen(inst->instance_id) + 1 );
+    instance = get_device_by_index( inst->dev, dev_info->connection_index,
+            &dev_info->device_address );
+    if (dev_info->device_address)
+    {
+        snprintfW( dev_info->device_id, MAX_DEVICE_ID_LEN, device_idW,
                 instance->vid, instance->pid );
-        len = strlenW(dev_instance_idW);
-        RtlMultiByteToUnicodeN( dev_instance_idW + len,
+        len = strlenW(dev_info->device_id);
+        RtlMultiByteToUnicodeN( dev_info->device_id + len,
                 (MAX_DEVICE_ID_LEN - len) * sizeof(WCHAR), NULL,
                 instance->instance_id, strlen(instance->instance_id) + 1 );
-        set = SetupDiGetClassDevsW( NULL, usbW, 0, DIGCF_ALLCLASSES );
-        if (set == INVALID_HANDLE_VALUE)
-        {
-            HeapFree( GetProcessHeap(), 0, bufW );
-            break;
-        }
-        index = 0;
-        while (SetupDiEnumDeviceInfo( set, index++, &devInfo ))
-        {
-            if (!SetupDiGetDeviceInstanceIdW( set, &devInfo, bufW,
-                    MAX_DEVICE_ID_LEN, NULL ))
-                break;
-            if (!strcmpiW( dev_instance_idW, bufW ))
-            {
-                SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_DRIVER,
-                        NULL, NULL, 0, &len );
-                driver_key_name->ActualLength = 2 * sizeof(ULONG) + len;
-                if (irpsp->Parameters.DeviceIoControl.OutputBufferLength <
-                        driver_key_name->ActualLength)
-                {
-                    status = STATUS_SUCCESS;
-                    info = sizeof(*driver_key_name);
-                }
-                else if (SetupDiGetDeviceRegistryPropertyW( set, &devInfo,
-                        SPDRP_DRIVER, NULL, (BYTE *)driver_key_name->DriverKeyName,
-                        len, NULL ))
-                {
-                    status = STATUS_SUCCESS;
-                    info = driver_key_name->ActualLength;
-                }
-                break;
-            }
-        }
-        SetupDiDestroyDeviceInfoList( set );
-        HeapFree( GetProcessHeap(), 0, bufW );
-        break;
     }
-    case IOCTL_USB_GET_DEVICE_INFO:
+    *outsize = sizeof(*dev_info);
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS WINAPI usbhub_ioctl( DEVICE_OBJECT *device, IRP *irp )
+{
+    IO_STACK_LOCATION *irpsp;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
+    struct DeviceInstance *inst;
+    ULONG_PTR info = 0;
+
+    TRACE( "%p, %p\n", device, irp );
+
+    EnterCriticalSection( &usbhub_cs );
+    irpsp = IoGetCurrentIrpStackLocation( irp );
+    if (device_exists( device ))
     {
-        struct usb_device_info *dev_info = irp->AssociatedIrp.SystemBuffer;
-        struct DeviceInstance *instance;
-        ULONG len, index = 0;
-#ifdef HAVE_LIBUSB_H
-        uint8_t bus_number = libusb_get_bus_number( inst->dev );
-#else
-        struct usb_device *dev;
-#endif
+        inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
+        if (inst->service) goto done;
 
-        if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*dev_info))
+        switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
         {
-            status = STATUS_BUFFER_TOO_SMALL;
+        case IOCTL_USB_GET_NODE_INFORMATION:
+            status = get_node_info( irp->AssociatedIrp.SystemBuffer,
+                    irpsp->Parameters.DeviceIoControl.OutputBufferLength, &info );
             break;
-        }
-        if (!dev_info->connection_index || dev_info->connection_index > NUMBER_OF_PORTS)
-        {
-            status = STATUS_INVALID_PARAMETER;
+        case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
+            status = get_node_conn_info( inst, irp->AssociatedIrp.SystemBuffer,
+                    irpsp->Parameters.DeviceIoControl.OutputBufferLength, &info );
             break;
+        case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
+            status = get_node_conn_driverkey_name( inst,
+                    irp->AssociatedIrp.SystemBuffer,
+                    irpsp->Parameters.DeviceIoControl.OutputBufferLength, &info );
+            break;
+        case IOCTL_USB_GET_DEVICE_INFO:
+            status = get_device_info( inst, irp->AssociatedIrp.SystemBuffer,
+                    irpsp->Parameters.DeviceIoControl.OutputBufferLength, &info );
+            break;
+        default:
+            FIXME( "IOCTL %08x is not implemented\n",
+                    irpsp->Parameters.DeviceIoControl.IoControlCode );
         }
-        RtlZeroMemory( (ULONG *)dev_info + 1, sizeof(*dev_info) - sizeof(ULONG) );
-        memcpy( dev_info->root_hub_id, root_hub_idW, sizeof(root_hub_idW) );
-        len = strlenW(root_hub_idW);
-        RtlMultiByteToUnicodeN( dev_info->root_hub_id + len,
-                (MAX_DEVICE_ID_LEN - len) * sizeof(WCHAR), NULL,
-                inst->instance_id, strlen(inst->instance_id) + 1 );
-#ifdef HAVE_LIBUSB_H
-        LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
-        {
-            if (instance->dev && instance->dev != inst->dev &&
-                libusb_get_bus_number( instance->dev ) == bus_number &&
-                ++index == dev_info->connection_index)
-            {
-                dev_info->device_address = libusb_get_device_address( instance->dev );
-                break;
-            }
-        }
-#else
-        for (dev = inst->dev->next; dev; dev = dev->next)
-            if (++index == dev_info->connection_index)
-            {
-                dev_info->device_address = dev->devnum;
-                LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
-                {
-                    if (instance->dev == dev) break;
-                }
-                break;
-            }
-#endif
-        if (dev_info->device_address)
-        {
-            snprintfW( dev_info->device_id, MAX_DEVICE_ID_LEN, device_idW,
-                    instance->vid, instance->pid );
-            len = strlenW(dev_info->device_id);
-            RtlMultiByteToUnicodeN( dev_info->device_id + len,
-                    (MAX_DEVICE_ID_LEN - len) * sizeof(WCHAR), NULL,
-                    instance->instance_id, strlen(instance->instance_id) + 1 );
-        }
-        status = STATUS_SUCCESS;
-        info = sizeof(*dev_info);
-        break;
-    }
-    default:
-        FIXME( "IOCTL %08x is not implemented\n",
-                irpsp->Parameters.DeviceIoControl.IoControlCode );
     }
 
 done:
-- 
1.7.4.4

----------- следующая часть -----------
From 3b9dda85ead2e581d73f196b069051ced93826b6 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 22 Apr 2011 20:15:26 +0400
Subject: [eterhack 5/7] mountmgr.sys: Add support for
 IOCTL_USB_GET_ROOT_HUB_NAME (eterbug #6247).

---
 dlls/mountmgr.sys/usbhub.c |   45 ++++++++++++++++++++++++++++++++++++++++++++
 include/ddk/usbioctl.h     |    5 ++++
 2 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/dlls/mountmgr.sys/usbhub.c b/dlls/mountmgr.sys/usbhub.c
index ac9770d..6eea21a 100644
--- a/dlls/mountmgr.sys/usbhub.c
+++ b/dlls/mountmgr.sys/usbhub.c
@@ -127,6 +127,16 @@ static BOOL device_exists( DEVICE_OBJECT *device )
     return FALSE;
 }
 
+static struct HCDInstance *get_hcd_instance( DEVICE_OBJECT *device )
+{
+    struct HCDInstance *instance;
+
+    LIST_FOR_EACH_ENTRY( instance, &HostControllers, struct HCDInstance, entry )
+        if (instance->dev == device)
+            return instance;
+    return NULL;
+}
+
 static void add_data( unsigned char **dst, ULONG *dst_size, const void *src, ULONG src_size )
 {
     int copy;
@@ -181,6 +191,27 @@ struct DeviceInstance *get_device_by_index( struct usb_device *device,
 
 #endif  /* HAVE_LIBUSB_H */
 
+static NTSTATUS get_root_hub_name( struct HCDInstance *instance, void *buff,
+        ULONG size, ULONG_PTR *outsize )
+{
+    USB_HCD_DRIVERKEY_NAME *name = buff;
+    ULONG name_size;
+
+    if (size < sizeof(*name))
+        return STATUS_BUFFER_TOO_SMALL;
+    RtlZeroMemory( buff, size );
+    name_size = (strlenW(instance->root_hub_name) - 4 + 1) * sizeof(WCHAR);
+    name->ActualLength = sizeof(*name) - sizeof(WCHAR) + name_size;
+    if (size >= name->ActualLength)
+    {
+        memcpy( name->DriverKeyName, instance->root_hub_name + 4, name_size );
+        *outsize = name->ActualLength;
+    }
+    else
+        *outsize = sizeof(*name);
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS get_node_info( void *buff, ULONG size, ULONG_PTR *outsize )
 {
     USB_NODE_INFORMATION *node_info = buff;
@@ -365,6 +396,7 @@ static NTSTATUS WINAPI usbhub_ioctl( DEVICE_OBJECT *device, IRP *irp )
     IO_STACK_LOCATION *irpsp;
     NTSTATUS status = STATUS_UNSUCCESSFUL;
     struct DeviceInstance *inst;
+    struct HCDInstance *hcd_inst;
     ULONG_PTR info = 0;
 
     TRACE( "%p, %p\n", device, irp );
@@ -400,6 +432,19 @@ static NTSTATUS WINAPI usbhub_ioctl( DEVICE_OBJECT *device, IRP *irp )
                     irpsp->Parameters.DeviceIoControl.IoControlCode );
         }
     }
+    else if ((hcd_inst = get_hcd_instance( device )))
+    {
+        switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
+        {
+        case IOCTL_USB_GET_ROOT_HUB_NAME:
+            status = get_root_hub_name( hcd_inst, irp->AssociatedIrp.SystemBuffer,
+                    irpsp->Parameters.DeviceIoControl.OutputBufferLength, &info );
+            break;
+        default:
+            FIXME( "IOCTL %08x is not implemented for HCD\n",
+                    irpsp->Parameters.DeviceIoControl.IoControlCode );
+        }
+    }
 
 done:
     LeaveCriticalSection( &usbhub_cs );
diff --git a/include/ddk/usbioctl.h b/include/ddk/usbioctl.h
index 89fc9a6..6e1dcb5 100644
--- a/include/ddk/usbioctl.h
+++ b/include/ddk/usbioctl.h
@@ -102,6 +102,11 @@ typedef struct _USB_NODE_CONNECTION_DRIVERKEY_NAME {
     WCHAR DriverKeyName[1];
 } USB_NODE_CONNECTION_DRIVERKEY_NAME, *PUSB_NODE_CONNECTION_DRIVERKEY_NAME;
 
+typedef struct _USB_HCD_DRIVERKEY_NAME {
+    ULONG ActualLength;
+    WCHAR DriverKeyName[1];
+} USB_HCD_DRIVERKEY_NAME, *PUSB_HCD_DRIVERKEY_NAME;
+
 #include <poppack.h>
 
 #endif  /* __USBIOCTL_H__ */
-- 
1.7.4.4

----------- следующая часть -----------
From 32ca3612de146186ce529d636c2e298b61a3d3f9 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Mon, 25 Apr 2011 20:32:55 +0400
Subject: [eterhack 6/7] mountmgr.sys: Add CurrentConfigurationValue field
 support (eterbug #6247).

---
 dlls/mountmgr.sys/usbhub.c |   43 +++++++++++++++++++++++++++++++++++++------
 1 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/dlls/mountmgr.sys/usbhub.c b/dlls/mountmgr.sys/usbhub.c
index 6eea21a..ee31eee 100644
--- a/dlls/mountmgr.sys/usbhub.c
+++ b/dlls/mountmgr.sys/usbhub.c
@@ -235,6 +235,7 @@ static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
     ULONG index = 0;
     struct DeviceInstance *instance;
     uint8_t bus_number = libusb_get_bus_number( inst->dev );
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
 
     if (size < sizeof(*conn_info))
         return STATUS_BUFFER_TOO_SMALL;
@@ -249,17 +250,31 @@ static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
             ++index == conn_info->ConnectionIndex)
         {
             struct libusb_device_descriptor desc;
+            libusb_device_handle *husb;
+            int config, ret;
 
             if (libusb_get_device_descriptor( instance->dev, &desc ))
                 break;
             memcpy( &conn_info->DeviceDescriptor, &desc,
                     sizeof(USB_DEVICE_DESCRIPTOR) );
-            conn_info->ConnectionStatus = 1;
+            ret = libusb_open( instance->dev, &husb );
+            if (!ret)
+            {
+                ret = libusb_get_configuration( husb, &config );
+                if (!ret)
+                    conn_info->CurrentConfigurationValue = config;
+                libusb_close( husb );
+            }
+            if (!ret)
+            {
+                conn_info->ConnectionStatus = 1;
+                *outsize = sizeof(*conn_info);
+                status = STATUS_SUCCESS;
+            }
             break;
         }
     }
-    *outsize = sizeof(*conn_info);
-    return STATUS_SUCCESS;
+    return status;
 }
 
 #else  /* HAVE_LIBUSB_H */
@@ -270,6 +285,7 @@ static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
     USB_NODE_CONNECTION_INFORMATION *conn_info = buff;
     ULONG index = 0;
     struct usb_device *dev;
+    NTSTATUS status = STATUS_UNSUCCESSFUL;
 
     if (size < sizeof(*conn_info))
         return STATUS_BUFFER_TOO_SMALL;
@@ -280,13 +296,28 @@ static NTSTATUS get_node_conn_info( struct DeviceInstance *inst, void *buff,
     for (dev = inst->dev->next; dev; dev = dev->next)
         if (++index == conn_info->ConnectionIndex)
         {
+            usb_dev_handle *husb;
+            int ret = -1;
+
             memcpy( &conn_info->DeviceDescriptor, &dev->descriptor,
                     sizeof(USB_DEVICE_DESCRIPTOR) );
-            conn_info->ConnectionStatus = 1;
+            husb = usb_open( inst->dev );
+            if (husb)
+            {
+                ret = usb_control_msg( husb, 1 << 7, USB_REQ_GET_CONFIGURATION,
+                        0, 0, (char *)&conn_info->CurrentConfigurationValue,
+                        sizeof(UCHAR), 0 );
+                usb_close( husb );
+            }
+            if (ret >= 0)
+            {
+                conn_info->ConnectionStatus = 1;
+                *outsize = sizeof(*conn_info);
+                status = STATUS_SUCCESS;
+            }
             break;
         }
-    *outsize = sizeof(*conn_info);
-    return STATUS_SUCCESS;
+    return status;
 }
 
 #endif  /* HAVE_LIBUSB_H */
-- 
1.7.4.4

----------- следующая часть -----------
From 5f69535e3aff671ca41fa5ddaf98ad50b6280709 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Mon, 25 Apr 2011 20:54:08 +0400
Subject: [eterhack 7/7] mountmgr.sys: Do not use ERR for USB devices errors.

---
 dlls/mountmgr.sys/usbhub.c |   20 ++++++--------------
 1 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/dlls/mountmgr.sys/usbhub.c b/dlls/mountmgr.sys/usbhub.c
index ee31eee..287f89c 100644
--- a/dlls/mountmgr.sys/usbhub.c
+++ b/dlls/mountmgr.sys/usbhub.c
@@ -527,7 +527,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                     ret = libusb_set_configuration( husb, (conf_desc != NULL) ?
                             conf_desc->bConfigurationValue : -1 );
                     if (ret < 0)
-                        ERR( "libusb_set_configuration: %d\n", ret );
+                        ;
                     else if (conf_desc == NULL)
                         status = STATUS_SUCCESS;
                     else if (!libusb_get_active_config_descriptor( inst->dev, &conf ))
@@ -799,9 +799,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                         ret = libusb_control_transfer( husb, req_type,
                                 request->Request, request->Value, request->Index,
                                 buf, size, 0 );
-                        if (ret < 0)
-                            ERR( "libusb_control_transfer: %d\n", ret );
-                        else
+                        if (ret >= 0)
                         {
                             if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
                             {
@@ -877,7 +875,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                     ret = usb_set_configuration( husb, (conf_desc != NULL) ?
                             conf_desc->bConfigurationValue : -1 );
                     if (ret < 0)
-                        ERR( "%s\n", usb_strerror() );
+                        ;
                     else if (conf_desc == NULL)
                         status = STATUS_SUCCESS;
                     else
@@ -1072,9 +1070,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                         {
                             ret = usb_get_string( husb, request->Index,
                                     request->LanguageId, (void *)buf, size );
-                            if (ret < 0)
-                                ERR( "%s\n", usb_strerror() );
-                            else
+                            if (ret >= 0)
                                 status = STATUS_SUCCESS;
                             usb_close( husb );
                         }
@@ -1104,9 +1100,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                 {
                     ret = usb_control_msg( husb, 1 << 7, USB_REQ_GET_STATUS, 0,
                             request->Index, buf, sizeof(USHORT), 0 );
-                    if (ret < 0)
-                        ERR( "%s\n", usb_strerror() );
-                    else
+                    if (ret >= 0)
                         status = STATUS_SUCCESS;
                     usb_close( husb );
                 }
@@ -1158,9 +1152,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                             req_type |= (1 << 7);
                         ret = usb_control_msg( husb, req_type, request->Request,
                                 request->Value, request->Index, buf, size, 0 );
-                        if (ret < 0)
-                            ERR( "%s\n", usb_strerror() );
-                        else
+                        if (ret >= 0)
                         {
                             if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
                             {
-- 
1.7.4.4



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