server: Use the security descriptor passed in when creating events.
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 21a9814..b2b3069 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -61,6 +61,74 @@
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
 
+static NTSTATUS create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd,
+                                 data_size_t *server_sd_len)
+{
+    unsigned int len;
+    PSID owner, group;
+    ACL *dacl, *sacl;
+    BOOLEAN owner_present, group_present, dacl_present, sacl_present;
+    BOOLEAN defaulted;
+    NTSTATUS status;
+    unsigned char *ptr;
+
+    if (!nt_sd)
+    {
+        *server_sd = NULL;
+        *server_sd_len = 0;
+        return STATUS_SUCCESS;
+    }
+
+    len = sizeof(struct security_descriptor);
+
+    status = RtlGetOwnerSecurityDescriptor(nt_sd, &owner, &owner_present);
+    if (status != STATUS_SUCCESS) return status;
+    status = RtlGetGroupSecurityDescriptor(nt_sd, &group, &group_present);
+    if (status != STATUS_SUCCESS) return status;
+    status = RtlGetSaclSecurityDescriptor(nt_sd, &sacl_present, &sacl, &defaulted);
+    if (status != STATUS_SUCCESS) return status;
+    status = RtlGetDaclSecurityDescriptor(nt_sd, &dacl_present, &dacl, &defaulted);
+    if (status != STATUS_SUCCESS) return status;
+
+    if (owner_present)
+        len += RtlLengthSid(owner);
+    if (group_present)
+        len += RtlLengthSid(group);
+    if (sacl_present && sacl)
+        len += sacl->AclSize;
+    if (dacl_present && dacl)
+        len += dacl->AclSize;
+
+    /* fix alignment for the Unicode name that follows the structure */
+    len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
+    *server_sd = RtlAllocateHeap(GetProcessHeap(), 0, len);
+    if (!*server_sd) return STATUS_NO_MEMORY;
+
+    (*server_sd)->control = ((SECURITY_DESCRIPTOR *)nt_sd)->Control & ~SE_SELF_RELATIVE;
+    (*server_sd)->owner_len = owner_present ? RtlLengthSid(owner) : 0;
+    (*server_sd)->group_len = group_present ? RtlLengthSid(group) : 0;
+    (*server_sd)->sacl_len = (sacl_present && sacl) ? sacl->AclSize : 0;
+    (*server_sd)->dacl_len = (dacl_present && dacl) ? dacl->AclSize : 0;
+
+    ptr = (unsigned char *)(*server_sd + 1);
+    memcpy(ptr, owner, (*server_sd)->owner_len);
+    ptr += (*server_sd)->owner_len;
+    memcpy(ptr, group, (*server_sd)->group_len);
+    ptr += (*server_sd)->group_len;
+    memcpy(ptr, sacl, (*server_sd)->sacl_len);
+    ptr += (*server_sd)->sacl_len;
+    memcpy(ptr, dacl, (*server_sd)->dacl_len);
+
+    *server_sd_len = len;
+
+    return STATUS_SUCCESS;
+}
+
+static void free_struct_sd(struct security_descriptor *server_sd)
+{
+    RtlFreeHeap(GetProcessHeap(), 0, server_sd);
+}
+
 /*
  *	Semaphores
  */
@@ -172,21 +240,35 @@
 {
     DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
     NTSTATUS ret;
+    struct security_descriptor *sd = NULL;
+    struct object_attributes objattr;
 
     if (len >= MAX_PATH * sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
 
+    objattr.rootdir = attr ? attr->RootDirectory : 0;
+    objattr.sd_len = 0;
+    if (attr)
+    {
+        ret = create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
+        if (ret != STATUS_SUCCESS) return ret;
+    }
+
     SERVER_START_REQ( create_event )
     {
         req->access = DesiredAccess;
         req->attributes = (attr) ? attr->Attributes : 0;
-        req->rootdir = attr ? attr->RootDirectory : 0;
         req->manual_reset = ManualReset;
         req->initial_state = InitialState;
+        wine_server_add_data( req, &objattr, sizeof(objattr) );
+        if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_len );
         if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
         ret = wine_server_call( req );
         *EventHandle = reply->handle;
     }
     SERVER_END_REQ;
+
+    free_struct_sd( sd );
+
     return ret;
 }
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 116216b..312d822 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -217,6 +217,14 @@
 
 };
 
+struct object_attributes
+{
+    obj_handle_t rootdir;
+    data_size_t sd_len;
+
+
+};
+
 struct token_groups
 {
     unsigned int count;
@@ -860,10 +868,9 @@
     struct request_header __header;
     unsigned int access;
     unsigned int attributes;
-    obj_handle_t rootdir;
     int          manual_reset;
     int          initial_state;
-    /* VARARG(name,unicode_str); */
+    /* VARARG(objattr,object_attributes); */
 };
 struct create_event_reply
 {
@@ -4873,6 +4880,6 @@
     struct set_completion_info_reply set_completion_info_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 317
+#define SERVER_PROTOCOL_VERSION 318
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/console.c b/server/console.c
index 61c4924..5f00588 100644
--- a/server/console.c
+++ b/server/console.c
@@ -289,7 +289,7 @@
     console_input->input_cp      = 0;
     console_input->output_cp     = 0;
     console_input->win           = 0;
-    console_input->event         = create_event( NULL, NULL, 0, 1, 0 );
+    console_input->event         = create_event( NULL, NULL, 0, 1, 0, NULL );
 
     if (!console_input->history || !console_input->evt)
     {
diff --git a/server/event.c b/server/event.c
index 5d49845..f866211 100644
--- a/server/event.c
+++ b/server/event.c
@@ -34,6 +34,7 @@
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
+#include "security.h"
 
 struct event
 {
@@ -69,7 +70,8 @@
 
 
 struct event *create_event( struct directory *root, const struct unicode_str *name,
-                            unsigned int attr, int manual_reset, int initial_state )
+                            unsigned int attr, int manual_reset, int initial_state,
+                            const struct security_descriptor *sd )
 {
     struct event *event;
 
@@ -80,6 +82,10 @@
             /* initialize it if it didn't already exist */
             event->manual_reset = manual_reset;
             event->signaled     = initial_state;
+            if (sd) default_set_sd( &event->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                     GROUP_SECURITY_INFORMATION|
+                                                     DACL_SECURITY_INFORMATION|
+                                                     SACL_SECURITY_INFORMATION );
         }
     }
     return event;
@@ -165,13 +171,24 @@
     struct event *event;
     struct unicode_str name;
     struct directory *root = NULL;
+    const struct object_attributes *objattr = get_req_data();
+    const struct security_descriptor *sd;
 
     reply->handle = 0;
-    get_req_unicode_str( &name );
-    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+
+    if (!objattr_is_valid( objattr, get_req_data_size() ))
         return;
 
-    if ((event = create_event( root, &name, req->attributes, req->manual_reset, req->initial_state )))
+    sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
+
+    /* get unicode string */
+    name.len = ((get_req_data_size() - sizeof(*objattr) - objattr->sd_len) / sizeof(WCHAR)) * sizeof(WCHAR);
+    name.str = (const WCHAR *)get_req_data() + (sizeof(*objattr) + objattr->sd_len) / sizeof(WCHAR);
+
+    if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 )))
+        return;
+
+    if ((event = create_event( root, &name, req->attributes, req->manual_reset, req->initial_state, sd )))
     {
         reply->handle = alloc_handle( current->process, event, req->access, req->attributes );
         release_object( event );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 51da895..d277cdc 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -539,7 +539,7 @@
     {
         /* this kind of sux -
            there's no unix way to be alerted when a pipe becomes empty */
-        server->event = create_event( NULL, NULL, 0, 0, 0 );
+        server->event = create_event( NULL, NULL, 0, 0, 0, NULL );
         if (!server->event) return;
         server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
         *event = server->event;
@@ -569,7 +569,7 @@
 static obj_handle_t alloc_wait_event( struct process *process )
 {
     obj_handle_t handle = 0;
-    struct event *event = create_event( NULL, NULL, 0, 1, 0 );
+    struct event *event = create_event( NULL, NULL, 0, 1, 0, NULL );
 
     if (event)
     {
diff --git a/server/object.h b/server/object.h
index cb5822a..d1af7f2 100644
--- a/server/object.h
+++ b/server/object.h
@@ -148,7 +148,8 @@
 struct event;
 
 extern struct event *create_event( struct directory *root, const struct unicode_str *name,
-                                   unsigned int attr, int manual_reset, int initial_state );
+                                   unsigned int attr, int manual_reset, int initial_state,
+                                   const struct security_descriptor *sd );
 extern struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern void pulse_event( struct event *event );
 extern void set_event( struct event *event );
diff --git a/server/process.c b/server/process.c
index 8ca20d8..7031e14 100644
--- a/server/process.c
+++ b/server/process.c
@@ -991,7 +991,7 @@
     generate_startup_debug_events( process, req->entry );
     set_process_startup_state( process, STARTUP_DONE );
 
-    if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0 );
+    if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL );
     if (current->suspend + process->suspend > 0) stop_thread( current );
     if (process->debugger) set_process_debug_flag( process, 1 );
 }
@@ -1170,7 +1170,7 @@
 
     if (!user_process_event)
     {
-        if (!(user_process_event = create_event( NULL, NULL, 0, 1, 0 ))) return;
+        if (!(user_process_event = create_event( NULL, NULL, 0, 1, 0, NULL ))) return;
         make_object_static( (struct object *)user_process_event );
     }
 
diff --git a/server/protocol.def b/server/protocol.def
index a00ccb9..41f71ca 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -227,17 +227,25 @@
     data_size_t  group_len;
     data_size_t  sacl_len;
     data_size_t  dacl_len;
-    /* VARARGS(owner,SID); */
-    /* VARARGS(group,SID); */
-    /* VARARGS(sacl,ACL); */
-    /* VARARGS(dacl,ACL); */
+    /* VARARG(owner,SID); */
+    /* VARARG(group,SID); */
+    /* VARARG(sacl,ACL); */
+    /* VARARG(dacl,ACL); */
+};
+
+struct object_attributes
+{
+    obj_handle_t rootdir; /* root directory */
+    data_size_t sd_len;   /* length of security_descriptor data. may be 0 */
+    /* VARARG(sd,security_descriptor); */
+    /* VARARG(name,unicode_str); */
 };
 
 struct token_groups
 {
     unsigned int count;
     /* unsigned int attributes[count]; */
-    /* VARARGS(sids,SID); */
+    /* VARARG(sids,SID); */
 };
 
 enum apc_type
@@ -743,10 +751,9 @@
 @REQ(create_event)
     unsigned int access;        /* wanted access rights */
     unsigned int attributes;    /* object attributes */
-    obj_handle_t rootdir;       /* root directory */
     int          manual_reset;  /* manual reset event */
     int          initial_state; /* initial state of the event */
-    VARARG(name,unicode_str);   /* object name */
+    VARARG(objattr,object_attributes); /* object attributes */
 @REPLY
     obj_handle_t handle;        /* handle to the event */
 @END
diff --git a/server/security.h b/server/security.h
index 5df5887..50fba52 100644
--- a/server/security.h
+++ b/server/security.h
@@ -127,3 +127,7 @@
     else
         return NULL;
 }
+
+/* determines whether an object_attributes struct is valid in a buffer
+ * and calls set_error appropriately */
+extern int objattr_is_valid( const struct object_attributes *objattr, data_size_t size );
diff --git a/server/token.c b/server/token.c
index 38877fe..b6ba50d 100644
--- a/server/token.c
+++ b/server/token.c
@@ -305,6 +305,29 @@
     return TRUE;
 }
 
+/* determines whether an object_attributes struct is valid in a buffer
+ * and calls set_error appropriately */
+int objattr_is_valid( const struct object_attributes *objattr, data_size_t size )
+{
+    if ((size < sizeof(*objattr)) || (size - sizeof(*objattr) < objattr->sd_len))
+    {
+        set_error( STATUS_ACCESS_VIOLATION );
+        return FALSE;
+    }
+
+    if (objattr->sd_len)
+    {
+        const struct security_descriptor *sd = (const struct security_descriptor *)(objattr + 1);
+        if (!sd_is_valid( sd, objattr->sd_len ))
+        {
+            set_error( STATUS_INVALID_SECURITY_DESCR );
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
 /* maps from generic rights to specific rights as given by a mapping */
 static inline void map_generic_mask(unsigned int *mask, const GENERIC_MAPPING *mapping)
 {
diff --git a/server/trace.c b/server/trace.c
index e0a2e96..4abdb55 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -782,6 +782,26 @@
     fputc( '}', stderr );
 }
 
+static void dump_varargs_object_attributes( data_size_t size )
+{
+    const struct object_attributes *objattr = cur_data;
+    fputc( '{', stderr );
+    if (size >= sizeof(struct object_attributes))
+    {
+        const WCHAR *str;
+        fprintf( stderr, "rootdir=%p,sd=", objattr->rootdir );
+        if (objattr->sd_len > size - sizeof(*objattr)) return;
+        dump_inline_security_descriptor( (const struct security_descriptor *)(objattr + 1), objattr->sd_len );
+        str = (const WCHAR *)cur_data + (sizeof(*objattr) + objattr->sd_len) / sizeof(WCHAR);
+        fprintf( stderr, ",name=L\"" );
+        dump_strW( str, (size - sizeof(*objattr) - objattr->sd_len) / sizeof(WCHAR),
+                   stderr, "\"\"" );
+        fputc( '\"', stderr );
+        remove_data( size );
+    }
+    fputc( '}', stderr );
+}
+
 typedef void (*dump_func)( const void *req );
 
 /* Everything below this line is generated automatically by tools/make_requests */
@@ -1136,11 +1156,10 @@
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " attributes=%08x,", req->attributes );
-    fprintf( stderr, " rootdir=%p,", req->rootdir );
     fprintf( stderr, " manual_reset=%d,", req->manual_reset );
     fprintf( stderr, " initial_state=%d,", req->initial_state );
-    fprintf( stderr, " name=" );
-    dump_varargs_unicode_str( cur_size );
+    fprintf( stderr, " objattr=" );
+    dump_varargs_object_attributes( cur_size );
 }
 
 static void dump_create_event_reply( const struct create_event_reply *req )