ntoskrnl.exe: Support creating event objects from server handle.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a5c2f043e6
commit
0decadd62a
|
@ -27,6 +27,8 @@ struct _OBJECT_TYPE {
|
|||
void (*release)(void*); /* called when the last reference is released */
|
||||
};
|
||||
|
||||
void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern POBJECT_TYPE ExEventObjectType;
|
||||
extern POBJECT_TYPE ExSemaphoreObjectType;
|
||||
extern POBJECT_TYPE IoDeviceObjectType;
|
||||
|
|
|
@ -76,6 +76,13 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
|||
EnterCriticalSection( &sync_cs );
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FIXME("unsupported on kernel objects\n");
|
||||
handles[i] = INVALID_HANDLE_VALUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
++*((ULONG_PTR *)&objs[i]->WaitListHead.Flink);
|
||||
if (!objs[i]->WaitListHead.Blink)
|
||||
{
|
||||
|
@ -127,6 +134,8 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
|||
}
|
||||
}
|
||||
|
||||
if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
|
||||
{
|
||||
switch (objs[i]->Type)
|
||||
|
@ -186,10 +195,24 @@ void WINAPI KeInitializeEvent( PRKEVENT event, EVENT_TYPE type, BOOLEAN state )
|
|||
event->Header.WaitListHead.Flink = NULL;
|
||||
}
|
||||
|
||||
static void *create_event_object( HANDLE handle )
|
||||
{
|
||||
EVENT_BASIC_INFORMATION info;
|
||||
KEVENT *event;
|
||||
|
||||
if (!(event = alloc_kernel_object( ExEventObjectType, handle, sizeof(*event), 0 ))) return NULL;
|
||||
|
||||
if (!NtQueryEvent( handle, EventBasicInformation, &info, sizeof(info), NULL ))
|
||||
KeInitializeEvent( event, info.EventType, info.EventState );
|
||||
event->Header.WaitListHead.Blink = INVALID_HANDLE_VALUE; /* mark as kernel object */
|
||||
return event;
|
||||
}
|
||||
|
||||
static const WCHAR event_type_name[] = {'E','v','e','n','t',0};
|
||||
|
||||
static struct _OBJECT_TYPE event_type = {
|
||||
event_type_name,
|
||||
create_event_object
|
||||
};
|
||||
|
||||
POBJECT_TYPE ExEventObjectType = &event_type;
|
||||
|
@ -200,15 +223,23 @@ POBJECT_TYPE ExEventObjectType = &event_type;
|
|||
LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
|
||||
{
|
||||
HANDLE handle;
|
||||
LONG ret;
|
||||
ULONG ret = 0;
|
||||
|
||||
TRACE("event %p, increment %d, wait %u.\n", event, increment, wait);
|
||||
|
||||
EnterCriticalSection( &sync_cs );
|
||||
ret = InterlockedExchange( &event->Header.SignalState, TRUE );
|
||||
if ((handle = event->Header.WaitListHead.Blink))
|
||||
SetEvent( handle );
|
||||
LeaveCriticalSection( &sync_cs );
|
||||
if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
EnterCriticalSection( &sync_cs );
|
||||
ret = InterlockedExchange( &event->Header.SignalState, TRUE );
|
||||
if ((handle = event->Header.WaitListHead.Blink))
|
||||
SetEvent( handle );
|
||||
LeaveCriticalSection( &sync_cs );
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("unsupported on kernel objects\n");
|
||||
event->Header.SignalState = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -219,15 +250,23 @@ LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
|
|||
LONG WINAPI KeResetEvent( PRKEVENT event )
|
||||
{
|
||||
HANDLE handle;
|
||||
LONG ret;
|
||||
ULONG ret = 0;
|
||||
|
||||
TRACE("event %p.\n", event);
|
||||
|
||||
EnterCriticalSection( &sync_cs );
|
||||
ret = InterlockedExchange( &event->Header.SignalState, FALSE );
|
||||
if ((handle = event->Header.WaitListHead.Blink))
|
||||
ResetEvent( handle );
|
||||
LeaveCriticalSection( &sync_cs );
|
||||
if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
EnterCriticalSection( &sync_cs );
|
||||
ret = InterlockedExchange( &event->Header.SignalState, FALSE );
|
||||
if ((handle = event->Header.WaitListHead.Blink))
|
||||
ResetEvent( handle );
|
||||
LeaveCriticalSection( &sync_cs );
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("unsupported on kernel objects\n");
|
||||
event->Header.SignalState = FALSE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -308,6 +308,14 @@ static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, UL
|
|||
return KeWaitForMultipleObjects(count, objs, wait_type, Executive, KernelMode, FALSE, &integer, NULL);
|
||||
}
|
||||
|
||||
static NTSTATUS wait_single_handle(HANDLE handle, ULONGLONG timeout)
|
||||
{
|
||||
LARGE_INTEGER integer;
|
||||
|
||||
integer.QuadPart = timeout;
|
||||
return ZwWaitForSingleObject(handle, FALSE, &integer);
|
||||
}
|
||||
|
||||
static void run_thread(PKSTART_ROUTINE proc, void *arg)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr = {0};
|
||||
|
@ -341,11 +349,13 @@ static void WINAPI mutex_thread(void *arg)
|
|||
static void test_sync(void)
|
||||
{
|
||||
KSEMAPHORE semaphore, semaphore2;
|
||||
KEVENT manual_event, auto_event;
|
||||
KEVENT manual_event, auto_event, *event;
|
||||
KTIMER timer;
|
||||
LARGE_INTEGER timeout;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
void *objs[2];
|
||||
NTSTATUS ret;
|
||||
HANDLE handle;
|
||||
int i;
|
||||
|
||||
KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
|
||||
|
@ -440,6 +450,33 @@ static void test_sync(void)
|
|||
ret = wait_multiple(2, objs, WaitAny, 0);
|
||||
ok(ret == 1, "got %#x\n", ret);
|
||||
|
||||
InitializeObjectAttributes(&attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
ret = ZwCreateEvent(&handle, SYNCHRONIZE, &attr, NotificationEvent, TRUE);
|
||||
ok(!ret, "ZwCreateEvent failed: %#x\n", ret);
|
||||
|
||||
ret = ObReferenceObjectByHandle(handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, (void **)&event, NULL);
|
||||
ok(!ret, "ObReferenceObjectByHandle failed: %#x\n", ret);
|
||||
|
||||
ret = wait_single(event, 0);
|
||||
todo_wine
|
||||
ok(ret == 0, "got %#x\n", ret);
|
||||
KeResetEvent(event);
|
||||
ret = wait_single(event, 0);
|
||||
ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||||
ret = wait_single_handle(handle, 0);
|
||||
todo_wine
|
||||
ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||||
|
||||
KeSetEvent(event, 0, FALSE);
|
||||
ret = wait_single(event, 0);
|
||||
todo_wine
|
||||
ok(ret == 0, "got %#x\n", ret);
|
||||
ret = wait_single_handle(handle, 0);
|
||||
ok(!ret, "got %#x\n", ret);
|
||||
|
||||
ZwClose(handle);
|
||||
ObDereferenceObject(event);
|
||||
|
||||
/* test semaphores */
|
||||
KeInitializeSemaphore(&semaphore, 0, 5);
|
||||
|
||||
|
@ -731,14 +768,12 @@ static void test_ob_reference(const WCHAR *test_path)
|
|||
|
||||
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj2, NULL);
|
||||
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
||||
todo_wine
|
||||
ok(obj1 == obj2, "obj1 != obj2\n");
|
||||
|
||||
ObDereferenceObject(obj2);
|
||||
|
||||
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj2, NULL);
|
||||
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
||||
todo_wine
|
||||
ok(obj1 == obj2, "obj1 != obj2\n");
|
||||
|
||||
ObDereferenceObject(obj2);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
struct event
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
struct list kernel_object; /* list of kernel object pointers */
|
||||
int manual_reset; /* is it a manual reset event? */
|
||||
int signaled; /* event has been signaled */
|
||||
};
|
||||
|
@ -49,6 +50,7 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
|
|||
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
|
||||
static unsigned int event_map_access( struct object *obj, unsigned int access );
|
||||
static int event_signal( struct object *obj, unsigned int access);
|
||||
static struct list *event_get_kernel_obj_list( struct object *obj );
|
||||
|
||||
static const struct object_ops event_ops =
|
||||
{
|
||||
|
@ -68,7 +70,7 @@ static const struct object_ops event_ops =
|
|||
directory_link_name, /* link_name */
|
||||
default_unlink_name, /* unlink_name */
|
||||
no_open_file, /* open_file */
|
||||
no_kernel_obj_list, /* get_kernel_obj_list */
|
||||
event_get_kernel_obj_list, /* get_kernel_obj_list */
|
||||
no_close_handle, /* close_handle */
|
||||
no_destroy /* destroy */
|
||||
};
|
||||
|
@ -119,6 +121,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
|
|||
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
|
||||
{
|
||||
/* initialize it if it didn't already exist */
|
||||
list_init( &event->kernel_object );
|
||||
event->manual_reset = manual_reset;
|
||||
event->signaled = initial_state;
|
||||
}
|
||||
|
@ -204,6 +207,12 @@ static int event_signal( struct object *obj, unsigned int access )
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct list *event_get_kernel_obj_list( struct object *obj )
|
||||
{
|
||||
struct event *event = (struct event *)obj;
|
||||
return &event->kernel_object;
|
||||
}
|
||||
|
||||
struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue