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 (*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 ExEventObjectType;
|
||||||
extern POBJECT_TYPE ExSemaphoreObjectType;
|
extern POBJECT_TYPE ExSemaphoreObjectType;
|
||||||
extern POBJECT_TYPE IoDeviceObjectType;
|
extern POBJECT_TYPE IoDeviceObjectType;
|
||||||
|
|
|
@ -76,6 +76,13 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
||||||
EnterCriticalSection( &sync_cs );
|
EnterCriticalSection( &sync_cs );
|
||||||
for (i = 0; i < count; i++)
|
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);
|
++*((ULONG_PTR *)&objs[i]->WaitListHead.Flink);
|
||||||
if (!objs[i]->WaitListHead.Blink)
|
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))
|
if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
|
||||||
{
|
{
|
||||||
switch (objs[i]->Type)
|
switch (objs[i]->Type)
|
||||||
|
@ -186,10 +195,24 @@ void WINAPI KeInitializeEvent( PRKEVENT event, EVENT_TYPE type, BOOLEAN state )
|
||||||
event->Header.WaitListHead.Flink = NULL;
|
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 const WCHAR event_type_name[] = {'E','v','e','n','t',0};
|
||||||
|
|
||||||
static struct _OBJECT_TYPE event_type = {
|
static struct _OBJECT_TYPE event_type = {
|
||||||
event_type_name,
|
event_type_name,
|
||||||
|
create_event_object
|
||||||
};
|
};
|
||||||
|
|
||||||
POBJECT_TYPE ExEventObjectType = &event_type;
|
POBJECT_TYPE ExEventObjectType = &event_type;
|
||||||
|
@ -200,15 +223,23 @@ POBJECT_TYPE ExEventObjectType = &event_type;
|
||||||
LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
|
LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
LONG ret;
|
ULONG ret = 0;
|
||||||
|
|
||||||
TRACE("event %p, increment %d, wait %u.\n", event, increment, wait);
|
TRACE("event %p, increment %d, wait %u.\n", event, increment, wait);
|
||||||
|
|
||||||
|
if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
EnterCriticalSection( &sync_cs );
|
EnterCriticalSection( &sync_cs );
|
||||||
ret = InterlockedExchange( &event->Header.SignalState, TRUE );
|
ret = InterlockedExchange( &event->Header.SignalState, TRUE );
|
||||||
if ((handle = event->Header.WaitListHead.Blink))
|
if ((handle = event->Header.WaitListHead.Blink))
|
||||||
SetEvent( handle );
|
SetEvent( handle );
|
||||||
LeaveCriticalSection( &sync_cs );
|
LeaveCriticalSection( &sync_cs );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("unsupported on kernel objects\n");
|
||||||
|
event->Header.SignalState = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -219,15 +250,23 @@ LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
|
||||||
LONG WINAPI KeResetEvent( PRKEVENT event )
|
LONG WINAPI KeResetEvent( PRKEVENT event )
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
LONG ret;
|
ULONG ret = 0;
|
||||||
|
|
||||||
TRACE("event %p.\n", event);
|
TRACE("event %p.\n", event);
|
||||||
|
|
||||||
|
if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
EnterCriticalSection( &sync_cs );
|
EnterCriticalSection( &sync_cs );
|
||||||
ret = InterlockedExchange( &event->Header.SignalState, FALSE );
|
ret = InterlockedExchange( &event->Header.SignalState, FALSE );
|
||||||
if ((handle = event->Header.WaitListHead.Blink))
|
if ((handle = event->Header.WaitListHead.Blink))
|
||||||
ResetEvent( handle );
|
ResetEvent( handle );
|
||||||
LeaveCriticalSection( &sync_cs );
|
LeaveCriticalSection( &sync_cs );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("unsupported on kernel objects\n");
|
||||||
|
event->Header.SignalState = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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);
|
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)
|
static void run_thread(PKSTART_ROUTINE proc, void *arg)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES attr = {0};
|
OBJECT_ATTRIBUTES attr = {0};
|
||||||
|
@ -341,11 +349,13 @@ static void WINAPI mutex_thread(void *arg)
|
||||||
static void test_sync(void)
|
static void test_sync(void)
|
||||||
{
|
{
|
||||||
KSEMAPHORE semaphore, semaphore2;
|
KSEMAPHORE semaphore, semaphore2;
|
||||||
KEVENT manual_event, auto_event;
|
KEVENT manual_event, auto_event, *event;
|
||||||
KTIMER timer;
|
KTIMER timer;
|
||||||
LARGE_INTEGER timeout;
|
LARGE_INTEGER timeout;
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
void *objs[2];
|
void *objs[2];
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
|
HANDLE handle;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
|
KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
|
||||||
|
@ -440,6 +450,33 @@ static void test_sync(void)
|
||||||
ret = wait_multiple(2, objs, WaitAny, 0);
|
ret = wait_multiple(2, objs, WaitAny, 0);
|
||||||
ok(ret == 1, "got %#x\n", ret);
|
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 */
|
/* test semaphores */
|
||||||
KeInitializeSemaphore(&semaphore, 0, 5);
|
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);
|
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj2, NULL);
|
||||||
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
||||||
todo_wine
|
|
||||||
ok(obj1 == obj2, "obj1 != obj2\n");
|
ok(obj1 == obj2, "obj1 != obj2\n");
|
||||||
|
|
||||||
ObDereferenceObject(obj2);
|
ObDereferenceObject(obj2);
|
||||||
|
|
||||||
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj2, NULL);
|
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj2, NULL);
|
||||||
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
|
||||||
todo_wine
|
|
||||||
ok(obj1 == obj2, "obj1 != obj2\n");
|
ok(obj1 == obj2, "obj1 != obj2\n");
|
||||||
|
|
||||||
ObDereferenceObject(obj2);
|
ObDereferenceObject(obj2);
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
struct event
|
struct event
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
|
struct list kernel_object; /* list of kernel object pointers */
|
||||||
int manual_reset; /* is it a manual reset event? */
|
int manual_reset; /* is it a manual reset event? */
|
||||||
int signaled; /* event has been signaled */
|
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 void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
|
||||||
static unsigned int event_map_access( struct object *obj, unsigned int access );
|
static unsigned int event_map_access( struct object *obj, unsigned int access );
|
||||||
static int event_signal( 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 =
|
static const struct object_ops event_ops =
|
||||||
{
|
{
|
||||||
|
@ -68,7 +70,7 @@ static const struct object_ops event_ops =
|
||||||
directory_link_name, /* link_name */
|
directory_link_name, /* link_name */
|
||||||
default_unlink_name, /* unlink_name */
|
default_unlink_name, /* unlink_name */
|
||||||
no_open_file, /* open_file */
|
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_close_handle, /* close_handle */
|
||||||
no_destroy /* destroy */
|
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)
|
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
|
||||||
{
|
{
|
||||||
/* initialize it if it didn't already exist */
|
/* initialize it if it didn't already exist */
|
||||||
|
list_init( &event->kernel_object );
|
||||||
event->manual_reset = manual_reset;
|
event->manual_reset = manual_reset;
|
||||||
event->signaled = initial_state;
|
event->signaled = initial_state;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +207,12 @@ static int event_signal( struct object *obj, unsigned int access )
|
||||||
return 1;
|
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,
|
struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
|
||||||
unsigned int attr, const struct security_descriptor *sd )
|
unsigned int attr, const struct security_descriptor *sd )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue