NTDLL: implement NtSignalAndWaitForSingleObject (resend)

Mike McCormack mike at codeweavers.com
Thu Apr 21 06:38:50 CDT 2005


This improves on my previous patch by adding a new method to the 
standard set of object operations.  The new method needs to know the 
access rights that the handle had, because different objects require 
different access rights for the "Signal" part of the operation.

To fetch the handle's access rights, I've created a 
get_handle_obj_access that returns a handle's access rights as well as 
the object it references.

Mike


ChangeLog:
* implement NtSignalAndWaitForSingleObject

-------------- next part --------------
Index: dlls/ntdll/sync.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/sync.c,v
retrieving revision 1.45
diff -u -p -r1.45 sync.c
--- dlls/ntdll/sync.c	18 Apr 2005 15:38:44 -0000	1.45
+++ dlls/ntdll/sync.c	21 Apr 2005 11:33:19 -0000
@@ -827,6 +827,35 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEA
 NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWaitObject,
                                                 BOOLEAN bAlertable, PLARGE_INTEGER Timeout )
 {
-    FIXME("%p %p %d %p\n", hSignalObject, hWaitObject, bAlertable, Timeout);
-    return STATUS_SUCCESS;
+    int cookie, flags = SELECT_INTERRUPTIBLE;
+    NTSTATUS ret;
+
+    TRACE("%p %p %d %p\n", hSignalObject, hWaitObject, bAlertable, Timeout);
+
+    if (Timeout) flags |= SELECT_TIMEOUT;
+    if (bAlertable) flags |= SELECT_ALERTABLE;
+    for (;;)
+    {
+        SERVER_START_REQ( signal_and_wait )
+        {
+            req->hsignal = hSignalObject;
+            req->hwait   = hWaitObject;
+            req->flags   = flags;
+            req->cookie  = &cookie;
+            NTDLL_get_server_timeout( &req->timeout, Timeout );
+            ret = wine_server_call( req );
+        }
+        SERVER_END_REQ;
+        if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
+        if (ret != STATUS_USER_APC) break;
+        call_apcs( (flags & SELECT_ALERTABLE) != 0 );
+        if (flags & SELECT_ALERTABLE) break;
+    }
+
+    /* A test on Windows 2000 shows that Windows always yields during
+       a wait, but a wait that is hit by an event gets a priority
+       boost as well.  This seems to model that behavior the closest.  */
+    if (ret == WAIT_TIMEOUT) NtYieldExecution();
+
+    return ret;
 }
Index: server/atom.c
===================================================================
RCS file: /home/wine/wine/server/atom.c,v
retrieving revision 1.17
diff -u -p -r1.17 atom.c
--- server/atom.c	19 Feb 2003 00:33:33 -0000	1.17
+++ server/atom.c	21 Apr 2005 11:33:19 -0000
@@ -72,6 +72,7 @@ static const struct object_ops atom_tabl
     NULL,                         /* signaled */
     NULL,                         /* satified */
     no_get_fd,                    /* get_fd */
+    NULL,                         /* signal */
     atom_table_destroy            /* destroy */
 };
 
Index: server/change.c
===================================================================
RCS file: /home/wine/wine/server/change.c,v
retrieving revision 1.21
diff -u -p -r1.21 change.c
--- server/change.c	1 Mar 2004 21:32:02 -0000	1.21
+++ server/change.c	21 Apr 2005 11:33:19 -0000
@@ -72,6 +72,7 @@ static const struct object_ops change_op
     change_signaled,          /* signaled */
     no_satisfied,             /* satisfied */
     no_get_fd,                /* get_fd */
+    NULL,                     /* signal */
     change_destroy            /* destroy */
 };
 
Index: server/console.c
===================================================================
RCS file: /home/wine/wine/server/console.c,v
retrieving revision 1.55
diff -u -p -r1.55 console.c
--- server/console.c	1 Mar 2005 10:56:18 -0000	1.55
+++ server/console.c	21 Apr 2005 11:33:19 -0000
@@ -47,6 +47,7 @@ static const struct object_ops console_i
     NULL,                             /* signaled */
     no_satisfied,                     /* satisfied */
     no_get_fd,                        /* get_fd */
+    NULL,                             /* signal */
     console_input_destroy             /* destroy */
 };
 
@@ -71,6 +72,7 @@ static const struct object_ops console_i
     console_input_events_signaled,    /* signaled */
     no_satisfied,                     /* satisfied */
     no_get_fd,                        /* get_fd */
+    NULL,                             /* signal */
     console_input_events_destroy      /* destroy */
 };
 
@@ -106,6 +108,7 @@ static const struct object_ops screen_bu
     NULL,                             /* signaled */
     NULL,                             /* satisfied */
     no_get_fd,                        /* get_fd */
+    NULL,                             /* signal */
     screen_buffer_destroy             /* destroy */
 };
 
Index: server/debugger.c
===================================================================
RCS file: /home/wine/wine/server/debugger.c,v
retrieving revision 1.55
diff -u -p -r1.55 debugger.c
--- server/debugger.c	2 Mar 2005 10:20:09 -0000	1.55
+++ server/debugger.c	21 Apr 2005 11:33:20 -0000
@@ -73,6 +73,7 @@ static const struct object_ops debug_eve
     debug_event_signaled,          /* signaled */
     no_satisfied,                  /* satisfied */
     no_get_fd,                     /* get_fd */
+    NULL,                          /* signal */
     debug_event_destroy            /* destroy */
 };
 
@@ -89,6 +90,7 @@ static const struct object_ops debug_ctx
     debug_ctx_signaled,            /* signaled */
     no_satisfied,                  /* satisfied */
     no_get_fd,                     /* get_fd */
+    NULL,                          /* signal */
     debug_ctx_destroy              /* destroy */
 };
 
Index: server/event.c
===================================================================
RCS file: /home/wine/wine/server/event.c,v
retrieving revision 1.29
diff -u -p -r1.29 event.c
--- server/event.c	2 Dec 2004 18:05:37 -0000	1.29
+++ server/event.c	21 Apr 2005 11:33:20 -0000
@@ -41,6 +41,7 @@ struct event
 static void event_dump( struct object *obj, int verbose );
 static int event_signaled( struct object *obj, struct thread *thread );
 static int event_satisfied( struct object *obj, struct thread *thread );
+static int event_signal( struct object *obj, unsigned int access);
 
 static const struct object_ops event_ops =
 {
@@ -51,6 +52,7 @@ static const struct object_ops event_ops
     event_signaled,            /* signaled */
     event_satisfied,           /* satisfied */
     no_get_fd,                 /* get_fd */
+    event_signal,              /* signal */
     no_destroy                 /* destroy */
 };
 
@@ -121,6 +123,20 @@ static int event_satisfied( struct objec
     /* Reset if it's an auto-reset event */
     if (!event->manual_reset) event->signaled = 0;
     return 0;  /* Not abandoned */
+}
+
+static int event_signal( struct object *obj, unsigned int access )
+{
+    struct event *event = (struct event *)obj;
+    assert( obj->ops == &event_ops );
+
+    if (!(access & EVENT_MODIFY_STATE))
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        return -1;
+    }
+    set_event( event );
+    return 0;
 }
 
 /* create an event */
Index: server/fd.c
===================================================================
RCS file: /home/wine/wine/server/fd.c,v
retrieving revision 1.36
diff -u -p -r1.36 fd.c
--- server/fd.c	29 Mar 2005 11:40:11 -0000	1.36
+++ server/fd.c	21 Apr 2005 11:33:20 -0000
@@ -160,6 +160,7 @@ static const struct object_ops fd_ops =
     NULL,                     /* signaled */
     NULL,                     /* satisfied */
     no_get_fd,                /* get_fd */
+    NULL,                     /* signal */
     fd_destroy                /* destroy */
 };
 
@@ -189,6 +190,7 @@ static const struct object_ops inode_ops
     NULL,                     /* signaled */
     NULL,                     /* satisfied */
     no_get_fd,                /* get_fd */
+    NULL,                     /* signal */
     inode_destroy             /* destroy */
 };
 
@@ -219,6 +221,7 @@ static const struct object_ops file_lock
     file_lock_signaled,         /* signaled */
     no_satisfied,               /* satisfied */
     no_get_fd,                  /* get_fd */
+    NULL,                       /* signal */
     no_destroy                  /* destroy */
 };
 
Index: server/file.c
===================================================================
RCS file: /home/wine/wine/server/file.c,v
retrieving revision 1.93
diff -u -p -r1.93 file.c
--- server/file.c	19 Apr 2005 11:59:13 -0000	1.93
+++ server/file.c	21 Apr 2005 11:33:20 -0000
@@ -84,6 +84,7 @@ static const struct object_ops file_ops 
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     file_get_fd,                  /* get_fd */
+    NULL,                         /* signal */
     file_destroy                  /* destroy */
 };
 
Index: server/handle.c
===================================================================
RCS file: /home/wine/wine/server/handle.c,v
retrieving revision 1.29
diff -u -p -r1.29 handle.c
--- server/handle.c	16 Sep 2003 01:07:21 -0000	1.29
+++ server/handle.c	21 Apr 2005 11:33:20 -0000
@@ -107,6 +107,7 @@ static const struct object_ops handle_ta
     NULL,                            /* signaled */
     NULL,                            /* satisfied */
     no_get_fd,                       /* get_fd */
+    NULL,                            /* signal */
     handle_table_destroy             /* destroy */
 };
 
@@ -360,13 +361,16 @@ static inline struct object *get_magic_h
     }
 }
 
-/* retrieve the object corresponding to a handle, incrementing its refcount */
-struct object *get_handle_obj( struct process *process, obj_handle_t handle,
-                               unsigned int access, const struct object_ops *ops )
+/* retrieve the object corresponding to a handle and the handle's access rights */
+struct object *get_handle_obj_access( struct process *process, obj_handle_t handle,
+                               unsigned int *paccess, const struct object_ops *ops )
 {
     struct handle_entry *entry;
     struct object *obj;
+    int access = 0;
 
+    if (paccess)
+        access = *paccess;
     if (!(obj = get_magic_handle( handle )))
     {
         if (!(entry = get_handle( process, handle ))) return NULL;
@@ -376,6 +380,8 @@ struct object *get_handle_obj( struct pr
             return NULL;
         }
         obj = entry->ptr;
+        if (paccess)
+            *paccess = entry->access;
     }
     if (ops && (obj->ops != ops))
     {
@@ -383,6 +389,13 @@ struct object *get_handle_obj( struct pr
         return NULL;
     }
     return grab_object( obj );
+}
+
+/* retrieve the object corresponding to a handle, incrementing its refcount */
+struct object *get_handle_obj( struct process *process, obj_handle_t handle,
+                               unsigned int access, const struct object_ops *ops )
+{
+    return get_handle_obj_access( process, handle, &access, ops );
 }
 
 /* retrieve the cached fd for a given handle */
Index: server/handle.h
===================================================================
RCS file: /home/wine/wine/server/handle.h,v
retrieving revision 1.13
diff -u -p -r1.13 handle.h
--- server/handle.h	16 Sep 2003 01:07:21 -0000	1.13
+++ server/handle.h	21 Apr 2005 11:33:20 -0000
@@ -38,6 +38,8 @@ extern obj_handle_t alloc_handle( struct
 extern int close_handle( struct process *process, obj_handle_t handle, int *fd );
 extern struct object *get_handle_obj( struct process *process, obj_handle_t handle,
                                       unsigned int access, const struct object_ops *ops );
+extern struct object *get_handle_obj_access( struct process *process, obj_handle_t handle,
+                                    unsigned int *paccess, const struct object_ops *ops );
 extern int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned int access );
 extern int set_handle_info( struct process *process, obj_handle_t handle, int mask, int flags, int *fd );
 extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
Index: server/hook.c
===================================================================
RCS file: /home/wine/wine/server/hook.c,v
retrieving revision 1.12
diff -u -p -r1.12 hook.c
--- server/hook.c	3 Feb 2005 16:40:20 -0000	1.12
+++ server/hook.c	21 Apr 2005 11:33:20 -0000
@@ -78,6 +78,7 @@ static const struct object_ops hook_tabl
     NULL,                         /* signaled */
     NULL,                         /* satisfied */
     no_get_fd,                    /* get_fd */
+    NULL,                         /* signal */
     hook_table_destroy            /* destroy */
 };
 
Index: server/mailslot.c
===================================================================
RCS file: /home/wine/wine/server/mailslot.c,v
retrieving revision 1.2
diff -u -p -r1.2 mailslot.c
--- server/mailslot.c	11 Apr 2005 16:11:32 -0000	1.2
+++ server/mailslot.c	21 Apr 2005 11:33:20 -0000
@@ -73,6 +73,7 @@ static const struct object_ops mailslot_
     default_fd_signaled,       /* signaled */
     no_satisfied,              /* satisfied */
     mailslot_get_fd,           /* get_fd */
+    NULL,                      /* signal */
     mailslot_destroy           /* destroy */
 };
 
@@ -114,6 +115,7 @@ static const struct object_ops mail_writ
     NULL,                       /* signaled */
     NULL,                       /* satisfied */
     mail_writer_get_fd,         /* get_fd */
+    NULL,                       /* signal */
     mail_writer_destroy         /* destroy */
 };
 
Index: server/mapping.c
===================================================================
RCS file: /home/wine/wine/server/mapping.c,v
retrieving revision 1.49
diff -u -p -r1.49 mapping.c
--- server/mapping.c	19 Apr 2005 11:59:13 -0000	1.49
+++ server/mapping.c	21 Apr 2005 11:33:20 -0000
@@ -63,6 +63,7 @@ static const struct object_ops mapping_o
     NULL,                        /* signaled */
     NULL,                        /* satisfied */
     mapping_get_fd,              /* get_fd */
+    NULL,                        /* signal */
     mapping_destroy              /* destroy */
 };
 
Index: server/mutex.c
===================================================================
RCS file: /home/wine/wine/server/mutex.c,v
retrieving revision 1.27
diff -u -p -r1.27 mutex.c
--- server/mutex.c	25 Feb 2005 16:58:43 -0000	1.27
+++ server/mutex.c	21 Apr 2005 11:33:20 -0000
@@ -44,6 +44,7 @@ static void mutex_dump( struct object *o
 static int mutex_signaled( struct object *obj, struct thread *thread );
 static int mutex_satisfied( struct object *obj, struct thread *thread );
 static void mutex_destroy( struct object *obj );
+static int mutex_signal( struct object *obj, unsigned int access );
 
 static const struct object_ops mutex_ops =
 {
@@ -54,6 +55,7 @@ static const struct object_ops mutex_ops
     mutex_signaled,            /* signaled */
     mutex_satisfied,           /* satisfied */
     no_get_fd,                 /* get_fd */
+    mutex_signal,              /* signal */
     mutex_destroy              /* destroy */
 };
 
@@ -141,6 +143,17 @@ static void mutex_destroy( struct object
     if (!mutex->count) return;
     mutex->count = 0;
     do_release( mutex );
+}
+
+static int mutex_signal( struct object *obj, unsigned int access )
+{
+    if (!(access & SYNCHRONIZE))
+    {
+        set_error(STATUS_ACCESS_DENIED);
+        return -1;
+    }
+    mutex_satisfied( obj, current );
+    return 0;
 }
 
 /* create a mutex */
Index: server/named_pipe.c
===================================================================
RCS file: /home/wine/wine/server/named_pipe.c,v
retrieving revision 1.36
diff -u -p -r1.36 named_pipe.c
--- server/named_pipe.c	18 Apr 2005 14:57:04 -0000	1.36
+++ server/named_pipe.c	21 Apr 2005 11:33:20 -0000
@@ -107,6 +107,7 @@ static const struct object_ops named_pip
     NULL,                         /* signaled */
     NULL,                         /* satisfied */
     no_get_fd,                    /* get_fd */
+    NULL,                         /* signal */
     named_pipe_destroy            /* destroy */
 };
 
@@ -129,6 +130,7 @@ static const struct object_ops pipe_serv
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     pipe_server_get_fd,           /* get_fd */
+    NULL,                         /* signal */
     pipe_server_destroy           /* destroy */
 };
 
@@ -157,6 +159,7 @@ static const struct object_ops pipe_clie
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     pipe_client_get_fd,           /* get_fd */
+    NULL,                         /* signal */
     pipe_client_destroy           /* destroy */
 };
 
Index: server/object.h
===================================================================
RCS file: /home/wine/wine/server/object.h,v
retrieving revision 1.57
diff -u -p -r1.57 object.h
--- server/object.h	1 Mar 2005 11:49:58 -0000	1.57
+++ server/object.h	21 Apr 2005 11:33:20 -0000
@@ -61,6 +61,8 @@ struct object_ops
     int  (*satisfied)(struct object *,struct thread *);
     /* return an fd object that can be used to read/write from the object */
     struct fd *(*get_fd)(struct object *);
+    /* signal an object */
+    int (*signal)(struct object *, unsigned int);
     /* destroy on refcount == 0 */
     void (*destroy)(struct object *);
 };
Index: server/process.c
===================================================================
RCS file: /home/wine/wine/server/process.c,v
retrieving revision 1.124
diff -u -p -r1.124 process.c
--- server/process.c	4 Mar 2005 12:38:37 -0000	1.124
+++ server/process.c	21 Apr 2005 11:33:20 -0000
@@ -70,6 +70,7 @@ static const struct object_ops process_o
     process_signaled,            /* signaled */
     no_satisfied,                /* satisfied */
     no_get_fd,                   /* get_fd */
+    NULL,                        /* signal */
     process_destroy              /* destroy */
 };
 
@@ -116,6 +117,7 @@ static const struct object_ops startup_i
     startup_info_signaled,         /* signaled */
     no_satisfied,                  /* satisfied */
     no_get_fd,                     /* get_fd */
+    NULL,                          /* signal */
     startup_info_destroy           /* destroy */
 };
 
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.130
diff -u -p -r1.130 protocol.def
--- server/protocol.def	20 Apr 2005 13:03:59 -0000	1.130
+++ server/protocol.def	21 Apr 2005 11:33:20 -0000
@@ -489,6 +489,15 @@ enum apc_type { APC_NONE, APC_USER, APC_
 #define SELECT_TIMEOUT       8
 
 
+ at REQ(signal_and_wait)
+    obj_handle_t   hsignal;      /* handle to signal */
+    obj_handle_t   hwait;        /* handle to wait on */
+    int            flags;        /* wait flags (see above) */
+    void*          cookie;       /* magic cookie to return to client */
+    abs_time_t     timeout;      /* absolute timeout */
+ at END
+
+
 /* Create an event */
 @REQ(create_event)
     unsigned int access;        /* wanted access rights */
Index: server/queue.c
===================================================================
RCS file: /home/wine/wine/server/queue.c,v
retrieving revision 1.58
diff -u -p -r1.58 queue.c
--- server/queue.c	20 Apr 2005 13:03:59 -0000	1.58
+++ server/queue.c	21 Apr 2005 11:33:21 -0000
@@ -147,6 +147,7 @@ static const struct object_ops msg_queue
     msg_queue_signaled,        /* signaled */
     msg_queue_satisfied,       /* satisfied */
     no_get_fd,                 /* get_fd */
+    NULL,                      /* signal */
     msg_queue_destroy          /* destroy */
 };
 
@@ -160,6 +161,7 @@ static const struct object_ops thread_in
     NULL,                         /* signaled */
     NULL,                         /* satisfied */
     no_get_fd,                    /* get_fd */
+    NULL,                         /* signal */
     thread_input_destroy          /* destroy */
 };
 
Index: server/registry.c
===================================================================
RCS file: /home/wine/wine/server/registry.c,v
retrieving revision 1.66
diff -u -p -r1.66 registry.c
--- server/registry.c	20 Apr 2005 12:57:53 -0000	1.66
+++ server/registry.c	21 Apr 2005 11:33:21 -0000
@@ -139,6 +139,7 @@ static const struct object_ops key_ops =
     NULL,                    /* signaled */
     NULL,                    /* satisfied */
     no_get_fd,               /* get_fd */
+    NULL,                    /* signal */
     key_destroy              /* destroy */
 };
 
Index: server/request.c
===================================================================
RCS file: /home/wine/wine/server/request.c,v
retrieving revision 1.86
diff -u -p -r1.86 request.c
--- server/request.c	4 Mar 2005 12:38:37 -0000	1.86
+++ server/request.c	21 Apr 2005 11:33:21 -0000
@@ -94,6 +94,7 @@ static const struct object_ops master_so
     NULL,                          /* signaled */
     NULL,                          /* satisfied */
     no_get_fd,                     /* get_fd */
+    NULL,                          /* signal */
     master_socket_destroy          /* destroy */
 };
 
Index: server/request.h
===================================================================
RCS file: /home/wine/wine/server/request.h,v
retrieving revision 1.110
diff -u -p -r1.110 request.h
--- server/request.h	30 Mar 2005 19:02:15 -0000	1.110
+++ server/request.h	21 Apr 2005 11:33:21 -0000
@@ -130,6 +130,7 @@ DECL_HANDLER(dup_handle);
 DECL_HANDLER(open_process);
 DECL_HANDLER(open_thread);
 DECL_HANDLER(select);
+DECL_HANDLER(signal_and_wait);
 DECL_HANDLER(create_event);
 DECL_HANDLER(event_op);
 DECL_HANDLER(open_event);
@@ -324,6 +325,7 @@ static const req_handler req_handlers[RE
     (req_handler)req_open_process,
     (req_handler)req_open_thread,
     (req_handler)req_select,
+    (req_handler)req_signal_and_wait,
     (req_handler)req_create_event,
     (req_handler)req_event_op,
     (req_handler)req_open_event,
Index: server/semaphore.c
===================================================================
RCS file: /home/wine/wine/server/semaphore.c,v
retrieving revision 1.27
diff -u -p -r1.27 semaphore.c
--- server/semaphore.c	2 Dec 2004 18:05:37 -0000	1.27
+++ server/semaphore.c	21 Apr 2005 11:33:21 -0000
@@ -41,6 +41,7 @@ struct semaphore
 static void semaphore_dump( struct object *obj, int verbose );
 static int semaphore_signaled( struct object *obj, struct thread *thread );
 static int semaphore_satisfied( struct object *obj, struct thread *thread );
+static int semaphore_signal( struct object *obj, unsigned int access );
 
 static const struct object_ops semaphore_ops =
 {
@@ -51,6 +52,7 @@ static const struct object_ops semaphore
     semaphore_signaled,            /* signaled */
     semaphore_satisfied,           /* satisfied */
     no_get_fd,                     /* get_fd */
+    semaphore_signal,              /* signal */
     no_destroy                     /* destroy */
 };
 
@@ -77,32 +79,27 @@ static struct semaphore *create_semaphor
     return sem;
 }
 
-static unsigned int release_semaphore( obj_handle_t handle, unsigned int count )
+static int release_semaphore( struct semaphore *sem, unsigned int count,
+                              unsigned int *prev )
 {
-    struct semaphore *sem;
-    unsigned int prev = 0;
-
-    if ((sem = (struct semaphore *)get_handle_obj( current->process, handle,
-                                                   SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
+    if (prev)
+        *prev = sem->count;
+    if (sem->count + count < sem->count || sem->count + count > sem->max)
     {
-        prev = sem->count;
-        if (sem->count + count < sem->count || sem->count + count > sem->max)
-        {
-            set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
-        }
-        else if (sem->count)
-        {
-            /* there cannot be any thread to wake up if the count is != 0 */
-            sem->count += count;
-        }
-        else
-        {
-            sem->count = count;
-            wake_up( &sem->obj, count );
-        }
-        release_object( sem );
+        set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
+        return -1;
+    }
+    else if (sem->count)
+    {
+        /* there cannot be any thread to wake up if the count is != 0 */
+        sem->count += count;
+    }
+    else
+    {
+        sem->count = count;
+        wake_up( &sem->obj, count );
     }
-    return prev;
+    return 0;
 }
 
 static void semaphore_dump( struct object *obj, int verbose )
@@ -130,6 +127,19 @@ static int semaphore_satisfied( struct o
     return 0;  /* not abandoned */
 }
 
+static int semaphore_signal( struct object *obj, unsigned int access )
+{
+    struct semaphore *sem = (struct semaphore *)obj;
+    assert( obj->ops == &semaphore_ops );
+
+    if (!(access&SEMAPHORE_MODIFY_STATE))
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        return -1;
+    }
+    return release_semaphore( sem, 1, NULL );
+}
+
 /* create a semaphore */
 DECL_HANDLER(create_semaphore)
 {
@@ -154,5 +164,12 @@ DECL_HANDLER(open_semaphore)
 /* release a semaphore */
 DECL_HANDLER(release_semaphore)
 {
-    reply->prev_count = release_semaphore( req->handle, req->count );
+    struct semaphore *sem;
+
+    if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle,
+                                                   SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
+    {
+        release_semaphore( req->handle, req->count, &reply->prev_count );
+        release_object( sem );
+    }
 }
Index: server/serial.c
===================================================================
RCS file: /home/wine/wine/server/serial.c,v
retrieving revision 1.39
diff -u -p -r1.39 serial.c
--- server/serial.c	29 Mar 2005 11:40:11 -0000	1.39
+++ server/serial.c	21 Apr 2005 11:33:21 -0000
@@ -102,6 +102,7 @@ static const struct object_ops serial_op
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
     serial_get_fd,                /* get_fd */
+    NULL,                         /* signal */
     serial_destroy                /* destroy */
 };
 
Index: server/signal.c
===================================================================
RCS file: /home/wine/wine/server/signal.c,v
retrieving revision 1.9
diff -u -p -r1.9 signal.c
--- server/signal.c	4 Mar 2005 12:38:37 -0000	1.9
+++ server/signal.c	21 Apr 2005 11:33:21 -0000
@@ -63,6 +63,7 @@ static const struct object_ops handler_o
     NULL,                     /* signaled */
     NULL,                     /* satisfied */
     no_get_fd,                /* get_fd */
+    NULL,                     /* signal */
     handler_destroy           /* destroy */
 };
 
Index: server/snapshot.c
===================================================================
RCS file: /home/wine/wine/server/snapshot.c,v
retrieving revision 1.22
diff -u -p -r1.22 snapshot.c
--- server/snapshot.c	16 Sep 2003 01:07:21 -0000	1.22
+++ server/snapshot.c	21 Apr 2005 11:33:21 -0000
@@ -62,6 +62,7 @@ static const struct object_ops snapshot_
     NULL,                         /* signaled */
     NULL,                         /* satisfied */
     no_get_fd,                    /* get_fd */
+    NULL,                         /* signal */
     snapshot_destroy              /* destroy */
 };
 
Index: server/sock.c
===================================================================
RCS file: /home/wine/wine/server/sock.c,v
retrieving revision 1.53
diff -u -p -r1.53 sock.c
--- server/sock.c	29 Mar 2005 11:40:10 -0000	1.53
+++ server/sock.c	21 Apr 2005 11:33:21 -0000
@@ -108,6 +108,7 @@ static const struct object_ops sock_ops 
     sock_signaled,                /* signaled */
     no_satisfied,                 /* satisfied */
     sock_get_fd,                  /* get_fd */
+    NULL,                         /* signal */
     sock_destroy                  /* destroy */
 };
 
Index: server/thread.c
===================================================================
RCS file: /home/wine/wine/server/thread.c,v
retrieving revision 1.110
diff -u -p -r1.110 thread.c
--- server/thread.c	4 Mar 2005 12:38:36 -0000	1.110
+++ server/thread.c	21 Apr 2005 11:33:21 -0000
@@ -93,6 +93,7 @@ static const struct object_ops thread_op
     thread_signaled,            /* signaled */
     no_satisfied,               /* satisfied */
     no_get_fd,                  /* get_fd */
+    NULL,                       /* signal */
     destroy_thread              /* destroy */
 };
 
@@ -577,6 +578,65 @@ void wake_up( struct object *obj, int ma
     }
 }
 
+/* 
+ * signal_object
+ *
+ * Try signaling an event flag, a semaphore or a mutex.
+ */
+static int signal_object( obj_handle_t handle )
+{
+    struct object *obj;
+    int access = 0, r = -1;
+
+    obj = get_handle_obj_access( current->process, handle, &access, NULL );
+    if (obj)
+    {
+        if (obj->ops->signal)
+            r = obj->ops->signal( obj, access );
+        else
+            set_error( STATUS_INVALID_HANDLE );
+        release_object( obj );
+    }
+    return r;
+}
+
+static void signal_and_wait( obj_handle_t hsignal, struct object *wait,
+                             int flags, const abs_time_t *timeout )
+{
+    int r;
+
+    if (!wait_on( 1, &wait, flags, timeout ))
+        return;
+
+    /* signal the object */
+    if (signal_object( hsignal ) == -1)
+    {
+        end_wait( current );
+        return;
+    }
+
+    /* check if we woke ourselves up */
+    if (!current->wait)
+        return;
+
+    r = check_wait( current );
+    if (r != -1)
+    {
+        end_wait( current );
+        set_error( r );
+        return;
+    }
+
+    /* check if we need to wait */
+    if (!(flags & SELECT_TIMEOUT))
+        return;
+
+    current->wait->user = add_timeout_user( &current->wait->timeout,
+                                            thread_timeout, current->wait );
+    if (!current->wait->user)
+        end_wait( current );
+}
+
 /* queue an async procedure call */
 int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
                       enum apc_type type, int system, void *arg1, void *arg2, void *arg3 )
@@ -954,6 +1014,18 @@ DECL_HANDLER(select)
 {
     int count = get_req_data_size() / sizeof(int);
     select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout );
+}
+
+DECL_HANDLER(signal_and_wait)
+{   
+    struct object *wait;
+
+    wait = get_handle_obj( current->process, req->hwait, SYNCHRONIZE, NULL );
+    if (wait)
+    {
+        signal_and_wait( req->hsignal, wait, req->flags, &req->timeout );
+        release_object( wait );
+    }
 }
 
 /* queue an APC for a thread */
Index: server/timer.c
===================================================================
RCS file: /home/wine/wine/server/timer.c,v
retrieving revision 1.25
diff -u -p -r1.25 timer.c
--- server/timer.c	13 Dec 2004 21:10:59 -0000	1.25
+++ server/timer.c	21 Apr 2005 11:33:21 -0000
@@ -60,6 +60,7 @@ static const struct object_ops timer_ops
     timer_signaled,            /* signaled */
     timer_satisfied,           /* satisfied */
     no_get_fd,                 /* get_fd */
+    NULL,                      /* signal */
     timer_destroy              /* destroy */
 };
 
Index: server/token.c
===================================================================
RCS file: /home/wine/wine/server/token.c,v
retrieving revision 1.2
diff -u -p -r1.2 token.c
--- server/token.c	11 Feb 2005 11:52:06 -0000	1.2
+++ server/token.c	21 Apr 2005 11:33:21 -0000
@@ -58,6 +58,7 @@ static const struct object_ops token_ops
     NULL,                      /* signaled */
     NULL,                      /* satified */
     no_get_fd,                 /* get_fd */
+    NULL,                      /* signal */
     token_destroy              /* destroy */
 };
 


More information about the wine-patches mailing list