winex11: Add helper function get_xrender_format_from_color_shifts.
[wine] / server / semaphore.c
index 589704a..0e26125 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
 #include <stdlib.h>
 #include <stdarg.h>
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windef.h"
 #include "winternl.h"
 
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
+#include "security.h"
 
 struct semaphore
 {
@@ -41,28 +44,36 @@ struct semaphore
 };
 
 static void semaphore_dump( struct object *obj, int verbose );
+static struct object_type *semaphore_get_type( struct object *obj );
 static int semaphore_signaled( struct object *obj, struct thread *thread );
 static int semaphore_satisfied( struct object *obj, struct thread *thread );
+static unsigned int semaphore_map_access( struct object *obj, unsigned int access );
 static int semaphore_signal( struct object *obj, unsigned int access );
 
 static const struct object_ops semaphore_ops =
 {
     sizeof(struct semaphore),      /* size */
     semaphore_dump,                /* dump */
+    semaphore_get_type,            /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     semaphore_signaled,            /* signaled */
     semaphore_satisfied,           /* satisfied */
     semaphore_signal,              /* signal */
     no_get_fd,                     /* get_fd */
+    semaphore_map_access,          /* map_access */
+    default_get_sd,                /* get_sd */
+    default_set_sd,                /* set_sd */
     no_lookup_name,                /* lookup_name */
+    no_open_file,                  /* open_file */
     no_close_handle,               /* close_handle */
     no_destroy                     /* destroy */
 };
 
 
-static struct semaphore *create_semaphore( const struct unicode_str *name, unsigned int attr,
-                                           unsigned int initial, unsigned int max )
+static struct semaphore *create_semaphore( struct directory *root, const struct unicode_str *name,
+                                           unsigned int attr, unsigned int initial, unsigned int max,
+                                           const struct security_descriptor *sd )
 {
     struct semaphore *sem;
 
@@ -71,13 +82,17 @@ static struct semaphore *create_semaphore( const struct unicode_str *name, unsig
         set_error( STATUS_INVALID_PARAMETER );
         return NULL;
     }
-    if ((sem = create_named_object( sync_namespace, &semaphore_ops, name, attr )))
+    if ((sem = create_named_object_dir( root, name, attr, &semaphore_ops )))
     {
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
             /* initialize it if it didn't already exist */
             sem->count = initial;
             sem->max   = max;
+            if (sd) default_set_sd( &sem->obj, sd, OWNER_SECURITY_INFORMATION|
+                                                   GROUP_SECURITY_INFORMATION|
+                                                   DACL_SECURITY_INFORMATION|
+                                                   SACL_SECURITY_INFORMATION );
         }
     }
     return sem;
@@ -114,6 +129,13 @@ static void semaphore_dump( struct object *obj, int verbose )
     fputc( '\n', stderr );
 }
 
+static struct object_type *semaphore_get_type( struct object *obj )
+{
+    static const WCHAR name[] = {'S','e','m','a','p','h','o','r','e'};
+    static const struct unicode_str str = { name, sizeof(name) };
+    return get_object_type( &str );
+}
+
 static int semaphore_signaled( struct object *obj, struct thread *thread )
 {
     struct semaphore *sem = (struct semaphore *)obj;
@@ -130,6 +152,15 @@ static int semaphore_satisfied( struct object *obj, struct thread *thread )
     return 0;  /* not abandoned */
 }
 
+static unsigned int semaphore_map_access( struct object *obj, unsigned int access )
+{
+    if (access & GENERIC_READ)    access |= STANDARD_RIGHTS_READ | SYNCHRONIZE;
+    if (access & GENERIC_WRITE)   access |= STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE;
+    if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
+    if (access & GENERIC_ALL)     access |= STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS;
+    return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
+}
+
 static int semaphore_signal( struct object *obj, unsigned int access )
 {
     struct semaphore *sem = (struct semaphore *)obj;
@@ -148,24 +179,51 @@ DECL_HANDLER(create_semaphore)
 {
     struct semaphore *sem;
     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 ((sem = create_semaphore( &name, req->attributes, req->initial, req->max )))
+
+    if (!objattr_is_valid( objattr, get_req_data_size() ))
+        return;
+
+    sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
+    objattr_get_name( objattr, &name );
+
+    if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 )))
+        return;
+
+    if ((sem = create_semaphore( root, &name, req->attributes, req->initial, req->max, sd )))
     {
-        reply->handle = alloc_handle( current->process, sem, req->access,
-                                      req->attributes & OBJ_INHERIT );
+        if (get_error() == STATUS_OBJECT_NAME_EXISTS)
+            reply->handle = alloc_handle( current->process, sem, req->access, req->attributes );
+        else
+            reply->handle = alloc_handle_no_access_check( current->process, sem, req->access, req->attributes );
         release_object( sem );
     }
+
+    if (root) release_object( root );
 }
 
 /* open a handle to a semaphore */
 DECL_HANDLER(open_semaphore)
 {
     struct unicode_str name;
+    struct directory *root = NULL;
+    struct semaphore *sem;
 
     get_req_unicode_str( &name );
-    reply->handle = open_object( sync_namespace, &name, &semaphore_ops, req->access, req->attributes );
+    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+        return;
+
+    if ((sem = open_object_dir( root, &name, req->attributes, &semaphore_ops )))
+    {
+        reply->handle = alloc_handle( current->process, &sem->obj, req->access, req->attributes );
+        release_object( sem );
+    }
+
+    if (root) release_object( root );
 }
 
 /* release a semaphore */