[Wine-patches] [eterhack 08/12] ntoskrnl.exe: Simplify IoSetDeviceInterfaceState.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Чт Май 21 17:53:44 MSD 2009


---
 dlls/ntoskrnl.exe/ntoskrnl.c |  126 +++++++++++++++++++-----------------------
 1 files changed, 57 insertions(+), 69 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index aa7a52d..b79ddba 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -103,6 +103,7 @@ struct InterfaceInstance
     struct list entry;
     WCHAR *link;
     UNICODE_STRING target;
+    GUID guid;
 };
 
 static struct list InterfaceChangeNotifications = LIST_INIT(InterfaceChangeNotifications);
@@ -293,6 +294,56 @@ static struct InterfaceInstance *get_registered_interface( WCHAR *name, USHORT l
     return NULL;
 }
 
+static void call_interface_change_callbacks( const GUID *interface_class,
+                                             UNICODE_STRING *link_name )
+{
+    struct list callbacks = LIST_INIT(callbacks);
+    struct InterfaceChangeNotification *notification;
+    struct callback *cb, *cb2;
+    DEVICE_INTERFACE_CHANGE_NOTIFICATION change_notification;
+    NTSTATUS callback_status;
+
+    EnterCriticalSection( &cs );
+    LIST_FOR_EACH_ENTRY( notification, &InterfaceChangeNotifications,
+            struct InterfaceChangeNotification, entry )
+    {
+        if (!memcmp( interface_class, &notification->interface_class,
+                sizeof(*interface_class) ))
+        {
+            cb = HeapAlloc( GetProcessHeap(), 0, sizeof(*cb) );
+            if (cb == NULL) break;
+            cb->routine = notification->callback;
+            cb->context = notification->context;
+            list_add_tail( &callbacks, &cb->entry );
+        }
+    }
+    LeaveCriticalSection( &cs );
+
+    change_notification.Version = 1;
+    change_notification.Size = sizeof(change_notification);
+    change_notification.Event = GUID_DEVICE_INTERFACE_ARRIVAL;
+    change_notification.InterfaceClassGuid = *interface_class;
+    change_notification.SymbolicLinkName = link_name;
+
+    LIST_FOR_EACH_ENTRY_SAFE( cb, cb2, &callbacks, struct callback, entry )
+    {
+        if (TRACE_ON(relay))
+            DPRINTF( "%04x:Call callback %p (notification=%p,context=%p)\n",
+                        GetCurrentThreadId(), cb->routine, &change_notification,
+                        cb->context );
+
+        callback_status = cb->routine( &change_notification, cb->context );
+
+        if (TRACE_ON(relay))
+            DPRINTF( "%04x:Ret  callback %p (notification=%p,context=%p) retval=%08x\n",
+                        GetCurrentThreadId(), cb->routine, &change_notification,
+                        cb->context, callback_status );
+
+        list_remove( &cb->entry );
+        HeapFree( GetProcessHeap(), 0, cb );
+    }
+}
+
 static HANDLE get_device_manager(void)
 {
     static HANDLE device_manager;
@@ -1477,6 +1528,7 @@ NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT PhysicalDeviceObject,
                 if (status == STATUS_SUCCESS)
                 {
                     RtlInitUnicodeString( &interf->target, target );
+                    interf->guid = *InterfaceClassGuid;
                     EnterCriticalSection( &cs );
                     if (!get_registered_interface( interf->link,
                             strlenW(interf->link) ))
@@ -1621,86 +1673,22 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( PUNICODE_STRING SymbolicLinkName,
 
     if (Enable)
     {
-        struct list callbacks = LIST_INIT(callbacks);
         struct InterfaceInstance *interf;
-        struct InterfaceChangeNotification *notification;
-        struct callback *cb, *cb2;
-        DEVICE_INTERFACE_CHANGE_NOTIFICATION change_notification;
-        NTSTATUS status, callback_status;
-        UNICODE_STRING guid_str;
-        WCHAR *ptr, *guid_strW;
-        USHORT len = 0;
+        NTSTATUS status;
         GUID guid;
 
-        /* get interface class GUID from SymbolicLinkName */
-        ptr = SymbolicLinkName->Buffer + SymbolicLinkName->Length / sizeof(WCHAR);
-        while (ptr-- > SymbolicLinkName->Buffer)
-        {
-            if (*ptr == '#') break;
-            ++len;
-        }
-        ++ptr;
-        if (len != 38) return STATUS_INVALID_PARAMETER;
-        guid_strW = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
-        if (guid_strW == NULL) return STATUS_NO_MEMORY;
-        memcpy( guid_strW, ptr, len * sizeof(WCHAR) );
-        guid_strW[len] = 0;
-        RtlInitUnicodeString( &guid_str, guid_strW );
-        status = RtlGUIDFromString( &guid_str, &guid );
-        HeapFree( GetProcessHeap(), 0, guid_strW );
-        if (status != STATUS_SUCCESS) return status;
-
-        /* create symbolic link if interface is registered */
         status = STATUS_OBJECT_NAME_NOT_FOUND;
         EnterCriticalSection( &cs );
         interf = get_registered_interface( SymbolicLinkName->Buffer,
                 SymbolicLinkName->Length / sizeof(WCHAR) );
         if (interf != NULL)
-            status = IoCreateSymbolicLink( SymbolicLinkName, &interf->target );
-        if (status != STATUS_SUCCESS)
-        {
-            LeaveCriticalSection( &cs );
-            return status;
-        }
-
-        /* call callback routines for registered interface change notifications */
-        LIST_FOR_EACH_ENTRY( notification, &InterfaceChangeNotifications,
-                struct InterfaceChangeNotification, entry )
         {
-            if (!memcmp( &guid, &notification->interface_class, sizeof(guid) ))
-            {
-                cb = HeapAlloc( GetProcessHeap(), 0, sizeof(*cb) );
-                if (cb == NULL) break;
-                cb->routine = notification->callback;
-                cb->context = notification->context;
-                list_add_tail( &callbacks, &cb->entry );
-            }
+            guid = interf->guid;
+            status = IoCreateSymbolicLink( SymbolicLinkName, &interf->target );
         }
         LeaveCriticalSection( &cs );
-
-        change_notification.Version = 1;
-        change_notification.Size = sizeof(change_notification);
-        change_notification.Event = GUID_DEVICE_INTERFACE_ARRIVAL;
-        change_notification.InterfaceClassGuid = guid;
-        change_notification.SymbolicLinkName = SymbolicLinkName;
-
-        LIST_FOR_EACH_ENTRY_SAFE( cb, cb2, &callbacks, struct callback, entry )
-        {
-            if (TRACE_ON(relay))
-                DPRINTF( "%04x:Call callback %p (notification=%p,context=%p)\n",
-                         GetCurrentThreadId(), cb->routine, &change_notification,
-                         cb->context );
-
-            callback_status = cb->routine( &change_notification, cb->context );
-
-            if (TRACE_ON(relay))
-                DPRINTF( "%04x:Ret  callback %p (notification=%p,context=%p) retval=%08x\n",
-                         GetCurrentThreadId(), cb->routine, &change_notification,
-                         cb->context, callback_status );
-
-            list_remove( &cb->entry );
-            HeapFree( GetProcessHeap(), 0, cb );
-        }
+        if (status != STATUS_SUCCESS) return status;
+        call_interface_change_callbacks( &guid, SymbolicLinkName );
         return STATUS_SUCCESS;
     }
     else
-- 
1.6.2.5



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