[Wine-patches] [PATCH 2/5] ntoskrnl.exe: Implement some functions working with event objects.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пт Мар 13 15:29:58 MSK 2009


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

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index bc838e9..f99d86d 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -122,6 +122,16 @@ struct callback
     void *context;
 };
 
+static struct list Handles = LIST_INIT(Handles);
+
+struct HandleInstance
+{
+    struct list entry;
+    void *object;
+    HANDLE handle;
+    ULONG refs;
+};
+
 #define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \
         METHOD_BUFFERED, FILE_ANY_ACCESS)
 
@@ -2138,7 +2148,7 @@ void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type,
 void WINAPI KeClearEvent( PRKEVENT Event )
 {
     TRACE( "%p\n", Event );
-    Event->Header.SignalState = 0;
+    InterlockedExchange( &Event->Header.SignalState, 0 );
 }
 
 
@@ -2147,13 +2157,8 @@ void WINAPI KeClearEvent( PRKEVENT Event )
  */
 LONG WINAPI KeResetEvent( PRKEVENT Event )
 {
-    LONG ret;
-
     TRACE( "%p\n", Event );
-
-    ret = Event->Header.SignalState;
-    Event->Header.SignalState = 0;
-    return ret;
+    return InterlockedExchange( &Event->Header.SignalState, 0 );
 }
 
 
@@ -2163,12 +2168,22 @@ LONG WINAPI KeResetEvent( PRKEVENT Event )
 LONG WINAPI KeSetEvent( PRKEVENT Event, KPRIORITY Increment,
                         BOOLEAN Wait )
 {
+    struct HandleInstance *inst;
     LONG ret;
 
     TRACE("%p %d %d\n", Event, Increment, Wait);
 
-    ret = Event->Header.SignalState;
-    Event->Header.SignalState = 1;
+    ret = InterlockedExchange( &Event->Header.SignalState, 1 );
+    EnterCriticalSection( &cs );
+    LIST_FOR_EACH_ENTRY( inst, &Handles, struct HandleInstance, entry )
+    {
+        if (inst->object == Event)
+        {
+            NtSetEvent( inst->handle, NULL );
+            break;
+        }
+    }
+    LeaveCriticalSection( &cs );
     return ret;
 }
 
@@ -2337,8 +2352,84 @@ NTSTATUS WINAPI KeWaitForSingleObject( PVOID Object, KWAIT_REASON WaitReason,
                                        KPROCESSOR_MODE WaitMode, BOOLEAN Alertable,
                                        PLARGE_INTEGER Timeout )
 {
+    DISPATCHER_HEADER *header = Object;
+    NTSTATUS status = STATUS_SUCCESS;
+
     TRACE("%p %u %d %d %p\n", Object, WaitReason, WaitMode, Alertable, Timeout);
-    return STATUS_SUCCESS;
+
+    switch (header->Type)
+    {
+    case NotificationEvent:
+    case SynchronizationEvent:
+    {
+        struct HandleInstance *inst;
+        HANDLE event_handle = NULL;
+
+        if (InterlockedCompareExchange( &header->SignalState, 0, header->Type ))
+        {
+            status = STATUS_SUCCESS;
+            break;
+        }
+
+        EnterCriticalSection( &cs );
+        LIST_FOR_EACH_ENTRY( inst, &Handles, struct HandleInstance, entry )
+        {
+            if (inst->object == Object)
+            {
+                event_handle = inst->handle;
+                ++inst->refs;
+                break;
+            }
+        }
+        while (event_handle == NULL)
+        {
+            OBJECT_ATTRIBUTES attr;
+
+            RtlZeroMemory( &attr, sizeof(attr) );
+            attr.Length = sizeof(attr);
+            status = NtCreateEvent( &event_handle, EVENT_ALL_ACCESS, &attr,
+                    !header->Type, FALSE );
+            if (status != STATUS_SUCCESS)
+                break;
+            inst = HeapAlloc( GetProcessHeap(), 0, sizeof(*inst) );
+            if (inst == NULL)
+            {
+                NtClose( event_handle );
+                status = STATUS_NO_MEMORY;
+                break;
+            }
+            inst->object = Object;
+            inst->handle = event_handle;
+            inst->refs = 1;
+            list_add_head( &Handles, &inst->entry );
+        }
+        LeaveCriticalSection( &cs );
+        if (status != STATUS_SUCCESS)
+            break;
+
+        status = NtWaitForSingleObject( event_handle, Alertable, Timeout );
+
+        EnterCriticalSection( &cs );
+        LIST_FOR_EACH_ENTRY( inst, &Handles, struct HandleInstance, entry )
+        {
+            if (inst->object == Object)
+            {
+                if (!--inst->refs)
+                {
+                    list_remove( &inst->entry );
+                    NtClose( inst->handle );
+                    HeapFree( GetProcessHeap(), 0, inst );
+                }
+                break;
+            }
+        }
+        LeaveCriticalSection( &cs );
+        break;
+    }
+    default:
+        WARN( "synchronization object %u is not supported\n", header->Type );
+    }
+    return status;
 }
 
 
-- 
1.6.1.3.GIT



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