[Wine-patches] [eterhack 12/24] ntoskrnl.exe: Partially implement Io*PlugPlayNotification.
Alexander Morozov
=?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Ср Мар 4 12:25:21 MSK 2009
---
dlls/ntoskrnl.exe/ntoskrnl.c | 129 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 18fc88d..097a696 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -25,6 +25,7 @@
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
+#define INITGUID
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -39,6 +40,7 @@
#include "cfgmgr32.h"
#include "excpt.h"
#include "ddk/ntddk.h"
+#include "ddk/wdmguid.h"
#include "wine/unicode.h"
#include "wine/server.h"
#include "wine/list.h"
@@ -105,6 +107,23 @@ struct InterfaceInstance
UNICODE_STRING target;
};
+static struct list InterfaceChangeNotifications = LIST_INIT(InterfaceChangeNotifications);
+
+struct InterfaceChangeNotification
+{
+ struct list entry;
+ GUID interface_class;
+ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback;
+ void *context;
+};
+
+struct callback
+{
+ struct list entry;
+ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE routine;
+ void *context;
+};
+
#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \
METHOD_BUFFERED, FILE_ANY_ACCESS)
@@ -1459,9 +1478,37 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( PUNICODE_STRING SymbolicLinkName,
if (Enable)
{
+ struct list callbacks = LIST_INIT(callbacks);
struct InterfaceInstance *interf;
- NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
-
+ 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;
+ 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 );
LIST_FOR_EACH_ENTRY( interf, &Interfaces, struct InterfaceInstance, entry )
{
@@ -1472,8 +1519,51 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( PUNICODE_STRING SymbolicLinkName,
break;
}
}
+ 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 );
+ }
+ }
LeaveCriticalSection( &cs );
- return status;
+
+ 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 );
+ }
+ return STATUS_SUCCESS;
}
else
{
@@ -1642,10 +1732,30 @@ NTSTATUS WINAPI IoRegisterPlugPlayNotification( IO_NOTIFICATION_EVENT_CATEGORY
CallbackRoutine, PVOID Context,
PVOID *NotificationEntry )
{
- FIXME( "stub: %u %u %p %p %p %p %p\n", EventCategory, EventCategoryFlags,
+ TRACE( "%u %u %p %p %p %p %p\n", EventCategory, EventCategoryFlags,
EventCategoryData, DriverObject, CallbackRoutine, Context,
NotificationEntry );
- return STATUS_SUCCESS;
+
+ if (EventCategory == EventCategoryDeviceInterfaceChange)
+ {
+ struct InterfaceChangeNotification *notification =
+ HeapAlloc( GetProcessHeap(), 0, sizeof(*notification) );
+
+ if (notification == NULL) return STATUS_NO_MEMORY;
+ notification->interface_class = *(GUID *)EventCategoryData;
+ notification->callback = CallbackRoutine;
+ notification->context = Context;
+ EnterCriticalSection( &cs );
+ list_add_tail( &InterfaceChangeNotifications, ¬ification->entry );
+ LeaveCriticalSection( &cs );
+ *NotificationEntry = notification;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ FIXME( "event category %u is not supported\n", EventCategory );
+ return STATUS_NOT_IMPLEMENTED;
+ }
}
@@ -1654,7 +1764,14 @@ NTSTATUS WINAPI IoRegisterPlugPlayNotification( IO_NOTIFICATION_EVENT_CATEGORY
*/
NTSTATUS WINAPI IoUnregisterPlugPlayNotification( PVOID NotificationEntry )
{
- FIXME( "stub: %p\n", NotificationEntry );
+ struct InterfaceChangeNotification *notification = NotificationEntry;
+
+ TRACE( "%p\n", NotificationEntry );
+
+ EnterCriticalSection( &cs );
+ list_remove( ¬ification->entry );
+ LeaveCriticalSection( &cs );
+ HeapFree( GetProcessHeap(), 0, notification );
return STATUS_SUCCESS;
}
--
1.6.1.3.GIT
Подробная информация о списке рассылки Wine-patches