Added support for VT_I8/VT_UI8 marshalling.
[wine] / server / event.c
1 /*
2  * Server-side event management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "windef.h"
29 #include "winternl.h"
30
31 #include "handle.h"
32 #include "thread.h"
33 #include "request.h"
34
35 struct event
36 {
37     struct object  obj;             /* object header */
38     int            manual_reset;    /* is it a manual reset event? */
39     int            signaled;        /* event has been signaled */
40 };
41
42 static void event_dump( struct object *obj, int verbose );
43 static int event_signaled( struct object *obj, struct thread *thread );
44 static int event_satisfied( struct object *obj, struct thread *thread );
45 static int event_signal( struct object *obj, unsigned int access);
46
47 static const struct object_ops event_ops =
48 {
49     sizeof(struct event),      /* size */
50     event_dump,                /* dump */
51     add_queue,                 /* add_queue */
52     remove_queue,              /* remove_queue */
53     event_signaled,            /* signaled */
54     event_satisfied,           /* satisfied */
55     event_signal,              /* signal */
56     no_get_fd,                 /* get_fd */
57     no_close_handle,           /* close_handle */
58     no_destroy                 /* destroy */
59 };
60
61
62 struct event *create_event( const WCHAR *name, size_t len, unsigned int attr,
63                             int manual_reset, int initial_state )
64 {
65     struct event *event;
66
67     if ((event = create_named_object( sync_namespace, &event_ops, name, len, attr )))
68     {
69         if (get_error() != STATUS_OBJECT_NAME_COLLISION)
70         {
71             /* initialize it if it didn't already exist */
72             event->manual_reset = manual_reset;
73             event->signaled     = initial_state;
74         }
75     }
76     return event;
77 }
78
79 struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access )
80 {
81     return (struct event *)get_handle_obj( process, handle, access, &event_ops );
82 }
83
84 void pulse_event( struct event *event )
85 {
86     event->signaled = 1;
87     /* wake up all waiters if manual reset, a single one otherwise */
88     wake_up( &event->obj, !event->manual_reset );
89     event->signaled = 0;
90 }
91
92 void set_event( struct event *event )
93 {
94     event->signaled = 1;
95     /* wake up all waiters if manual reset, a single one otherwise */
96     wake_up( &event->obj, !event->manual_reset );
97 }
98
99 void reset_event( struct event *event )
100 {
101     event->signaled = 0;
102 }
103
104 static void event_dump( struct object *obj, int verbose )
105 {
106     struct event *event = (struct event *)obj;
107     assert( obj->ops == &event_ops );
108     fprintf( stderr, "Event manual=%d signaled=%d ",
109              event->manual_reset, event->signaled );
110     dump_object_name( &event->obj );
111     fputc( '\n', stderr );
112 }
113
114 static int event_signaled( struct object *obj, struct thread *thread )
115 {
116     struct event *event = (struct event *)obj;
117     assert( obj->ops == &event_ops );
118     return event->signaled;
119 }
120
121 static int event_satisfied( struct object *obj, struct thread *thread )
122 {
123     struct event *event = (struct event *)obj;
124     assert( obj->ops == &event_ops );
125     /* Reset if it's an auto-reset event */
126     if (!event->manual_reset) event->signaled = 0;
127     return 0;  /* Not abandoned */
128 }
129
130 static int event_signal( struct object *obj, unsigned int access )
131 {
132     struct event *event = (struct event *)obj;
133     assert( obj->ops == &event_ops );
134
135     if (!(access & EVENT_MODIFY_STATE))
136     {
137         set_error( STATUS_ACCESS_DENIED );
138         return 0;
139     }
140     set_event( event );
141     return 1;
142 }
143
144 /* create an event */
145 DECL_HANDLER(create_event)
146 {
147     struct event *event;
148
149     reply->handle = 0;
150     if ((event = create_event( get_req_data(), get_req_data_size(), req->attributes,
151                                req->manual_reset, req->initial_state )))
152     {
153         reply->handle = alloc_handle( current->process, event, req->access,
154                                       req->attributes & OBJ_INHERIT );
155         release_object( event );
156     }
157 }
158
159 /* open a handle to an event */
160 DECL_HANDLER(open_event)
161 {
162     reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
163                                  &event_ops, req->access, req->attributes );
164 }
165
166 /* do an event operation */
167 DECL_HANDLER(event_op)
168 {
169     struct event *event;
170
171     if (!(event = get_event_obj( current->process, req->handle, EVENT_MODIFY_STATE ))) return;
172     switch(req->op)
173     {
174     case PULSE_EVENT:
175         pulse_event( event );
176         break;
177     case SET_EVENT:
178         set_event( event );
179         break;
180     case RESET_EVENT:
181         reset_event( event );
182         break;
183     default:
184         fatal_protocol_error( current, "event_op: invalid operation %d\n", req->op );
185     }
186     release_object( event );
187 }