[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, ¬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
--
1.6.2.5
Подробная информация о списке рассылки Wine-patches