From 0f63bfc10bf4fcb5be118dc94107b920f534a97e Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Thu, 21 May 2009 17:53:44 +0400 Subject: [PATCH] ntoskrnl.exe: Simplify IoSetDeviceInterfaceState. --- dlls/ntoskrnl.exe/ntoskrnl.c | 126 ++++++++++++++++------------------- 1 file changed, 57 insertions(+), 69 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index aa7a52d784..b79ddba838 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, ¬ification->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, ¬ification->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 -- 2.33.8