[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