[Wine-patches] [16/23] ntoskrnl.exe: Improve IoRegisterDeviceInterface implementation.

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


For eterhack branch
----------- следующая часть -----------
From 547b82db834dc3b8cb78860f96a810c62676c5c7 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 15 Jan 2009 12:36:42 +0300
Subject: [PATCH] ntoskrnl.exe: Improve IoRegisterDeviceInterface implementation.

---
 dlls/ntoskrnl.exe/ntoskrnl.c |  200 +++++++++++++++++++++---------------------
 1 files changed, 101 insertions(+), 99 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 094f0f3..6ac20cd 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -219,6 +219,44 @@ end:
     return (*service_name != NULL);
 }
 
+static NTSTATUS get_device_id( DEVICE_OBJECT *pdo, BUS_QUERY_ID_TYPE id_type,
+                               WCHAR **id )
+{
+    NTSTATUS status;
+    IO_STACK_LOCATION *irpsp;
+    IRP *irp;
+
+    *id = NULL;
+    irp = IoAllocateIrp( pdo->StackSize, FALSE );
+    if (irp == NULL) return STATUS_NO_MEMORY;
+    irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+    irpsp->MajorFunction = IRP_MJ_PNP;
+    irpsp->MinorFunction = IRP_MN_QUERY_ID;
+    irpsp->Parameters.QueryId.IdType = id_type;
+    status = __regs_IofCallDriver( pdo, irp );
+    if (status == STATUS_SUCCESS)
+        *id = (WCHAR *)irp->IoStatus.Information;
+    IoFreeIrp( irp );
+    return status;
+}
+
+static BOOL compare_ids( WCHAR *hardware_id, WCHAR *instance_id,
+                         WCHAR *device_instance_id )
+{
+    WCHAR *ptr, *ptr2;
+
+    ptr = strrchrW( device_instance_id, '\\' );
+    if (ptr == NULL) return FALSE;
+    if (strncmpiW( hardware_id, device_instance_id, ptr - device_instance_id ))
+        return FALSE;
+    ++ptr;
+    ptr2 = strrchrW( ptr, '&' );
+    ptr2 = ptr2 ? (ptr2 + 1) : ptr;
+    if (strcmpiW( instance_id, ptr2 ))
+        return FALSE;
+    return TRUE;
+}
+
 static HANDLE get_device_manager(void)
 {
     static HANDLE device_manager;
@@ -1118,127 +1156,91 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
                                            PUNICODE_STRING ReferenceString,
                                            PUNICODE_STRING SymbolicLinkName )
 {
-    /* Now this function is implemented only for USB devices */
+    /* Now this function is implemented only for "USB" enumerator */
     static const WCHAR usb[] = {'U','S','B',0};
-    static const WCHAR link_name[] = {'\\','\?','\?','\\','U','S','B','#',
-            'V','i','d','_','%','0','4','x','&','P','i','d','_','%','0','4','x',
-            '#','%','s','#','%','s',0};
-    static const WCHAR device_name[] = {'U','S','B','\\','V','i','d','_',
-            '%','0','4','x','&','P','i','d','_','%','0','4','x',0};
-    PWSTR buf, hardware_id;
-    UNICODE_STRING guid_str;
-    WCHAR instance_id[MAX_DEVICE_ID_LEN];
-    char *inst_ptr;
+    WCHAR *hardware_id = NULL, *instance_id = NULL, *id = NULL;
     HDEVINFO set;
-    SP_DEVINFO_DATA devInfo = { 0 };
+    SP_DEVINFO_DATA devInfo;
+    SP_DEVICE_INTERFACE_DATA interfaceData;
     DWORD i = 0;
-    int found = 0;
-    NTSTATUS status = STATUS_UNSUCCESSFUL;
-    struct PdoExtension *dx;
-    USHORT vid, pid;
+    NTSTATUS status;
+    struct PdoExtension *dx = PhysicalDeviceObject->DeviceExtension;
+    struct InterfaceInstance *interf;
 
     TRACE( "%p %s %s %p\n", PhysicalDeviceObject,
            debugstr_guid(InterfaceClassGuid), debugstr_us(ReferenceString),
            SymbolicLinkName );
 
-    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;
-
-    buf = RtlAllocateHeap( GetProcessHeap(), 0, (strlenW( link_name )
-            + strlenW( instance_id ) + 34 /* 37 - 4  + 1 */ ) * sizeof(WCHAR) );
-    if (NULL == buf)
-        return STATUS_NO_MEMORY;
-    if (STATUS_SUCCESS != RtlStringFromGUID( InterfaceClassGuid, &guid_str ))
-    {
-        RtlFreeHeap( GetProcessHeap(), 0, buf );
-        /* RtlStringFromGUID returns STATUS_NO_MEMORY if unsuccessful */
-        return STATUS_NO_MEMORY;
-    }
-    /* guid_str.Buffer contains null-terminated string */
-    sprintfW( buf, link_name, vid, pid, instance_id, guid_str.Buffer );
-    RtlFreeUnicodeString( &guid_str );
-
-    hardware_id = RtlAllocateHeap( GetProcessHeap(), 0,
-            (strlenW( device_name ) + 1) * sizeof(WCHAR) );
-    if (NULL == hardware_id)
+    status = get_device_id( PhysicalDeviceObject, BusQueryInstanceID, &instance_id );
+    if (status != STATUS_SUCCESS) goto end;
+    status = get_device_id( PhysicalDeviceObject, BusQueryDeviceID, &hardware_id );
+    if (status != STATUS_SUCCESS) goto end;
+    id = RtlAllocateHeap( GetProcessHeap(), 0, MAX_DEVICE_ID_LEN );
+    if (id == NULL)
     {
-        RtlFreeHeap( GetProcessHeap(), 0, buf );
-        return STATUS_NO_MEMORY;
+        status = STATUS_NO_MEMORY;
+        goto end;
     }
-    sprintfW( hardware_id, device_name, vid, pid, instance_id );
 
+    status = STATUS_UNSUCCESSFUL;
     set = SetupDiGetClassDevsW( NULL, usb, NULL, DIGCF_ALLCLASSES );
-    if (INVALID_HANDLE_VALUE == set)
-    {
-        RtlFreeHeap( GetProcessHeap(), 0, buf );
-        return STATUS_UNSUCCESSFUL;
-    }
+    if (INVALID_HANDLE_VALUE == set) goto end;
     devInfo.cbSize = sizeof(devInfo);
-    while (!found && SetupDiEnumDeviceInfo( set, i++, &devInfo ))
-    {
-        PWSTR id;
-        DWORD size;
-
-        SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_HARDWAREID,
-                NULL, NULL, 0, &size );
-        id = RtlAllocateHeap( GetProcessHeap(), 0, size );
-        if (NULL == id)
+    while (SetupDiEnumDeviceInfo( set, i++, &devInfo ))
+        if (SetupDiGetDeviceInstanceIdW( set, &devInfo, id, MAX_DEVICE_ID_LEN, NULL )
+            && compare_ids( hardware_id, instance_id, id ))
         {
-            status = STATUS_NO_MEMORY;
-            break;
-        }
-        if (SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_HARDWAREID,
-                NULL, (PBYTE)id, size, NULL ))
-            while (*id)
+            SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
+            DWORD size;
+
+            interfaceData.cbSize = sizeof(interfaceData);
+            if (SetupDiCreateDeviceInterfaceW( set, &devInfo,
+                    InterfaceClassGuid, NULL, 0, &interfaceData ))
             {
-                if (!strcmpiW( id, hardware_id ))
+                SetupDiGetDeviceInterfaceDetailW( set, &interfaceData, NULL, 0,
+                        &size, NULL );
+                detail = RtlAllocateHeap( GetProcessHeap(), 0, size );
+                if (detail == NULL) break;
+                detail->cbSize = sizeof(*detail);
+                if (!SetupDiGetDeviceInterfaceDetailW( set, &interfaceData,
+                        detail, size, NULL, NULL ))
                 {
-                    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 ))
-                    {
-                        EnterCriticalSection( &cs );
-                        list_add_tail( &Interfaces, &interf->entry );
-                        LeaveCriticalSection( &cs );
-                        status = STATUS_SUCCESS;
-                    }
-                    else
-                    {
-                        RtlFreeHeap( GetProcessHeap(), 0, interf->link );
-                        RtlFreeHeap( GetProcessHeap(), 0, interf );
-                    }
+                    RtlFreeHeap( GetProcessHeap(), 0, detail );
+                    break;
+                }
+                interf = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*interf) );
+                if (interf == NULL)
+                {
+                    RtlFreeHeap( GetProcessHeap(), 0, detail );
+                    break;
+                }
+                interf->link = RtlAllocateHeap( GetProcessHeap(), 0,
+                        (strlenW(detail->DevicePath) + 1) * sizeof(WCHAR) );
+                if (interf->link == NULL)
+                {
+                    RtlFreeHeap( GetProcessHeap(), 0, detail );
+                    RtlFreeHeap( GetProcessHeap(), 0, interf );
                     break;
                 }
-                id += strlenW( id ) + 1;
+                strcpyW( interf->link, detail->DevicePath );
+                RtlFreeHeap( GetProcessHeap(), 0, detail );
+                interf->link[1] = '?';
+                interf->target = &dx->instance->pdo_name;
+                EnterCriticalSection( &cs );
+                list_add_tail( &Interfaces, &interf->entry );
+                LeaveCriticalSection( &cs );
+                status = STATUS_SUCCESS;
             }
-        RtlFreeHeap( GetProcessHeap(), 0, id );
-    }
-    RtlFreeHeap( GetProcessHeap(), 0, hardware_id );
+            break;
+        }
     SetupDiDestroyDeviceInfoList( set );
 
     if (STATUS_SUCCESS == status)
-        RtlInitUnicodeString( SymbolicLinkName, buf );
-    else
-        RtlFreeHeap( GetProcessHeap(), 0, buf );
-
+        RtlCreateUnicodeString( SymbolicLinkName, interf->link );
+end:
+    if (id) RtlFreeHeap( GetProcessHeap(), 0, id );
+    if (hardware_id) ExFreePool( hardware_id );
+    if (instance_id) ExFreePool( instance_id );
     return status;
 }
 
-- 
1.6.0.2.GIT



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