2 * Server-side event management
4 * Copyright (C) 1998 Alexandre Julliard
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <sys/types.h>
30 #define WIN32_NO_STATUS
39 static const WCHAR event_name
[] = {'E','v','e','n','t'};
41 struct type_descr event_type
=
43 { event_name
, sizeof(event_name
) }, /* name */
44 EVENT_ALL_ACCESS
, /* valid_access */
46 STANDARD_RIGHTS_READ
| EVENT_QUERY_STATE
,
47 STANDARD_RIGHTS_WRITE
| EVENT_MODIFY_STATE
,
48 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
55 struct object obj
; /* object header */
56 struct list kernel_object
; /* list of kernel object pointers */
57 int manual_reset
; /* is it a manual reset event? */
58 int signaled
; /* event has been signaled */
61 static void event_dump( struct object
*obj
, int verbose
);
62 static int event_signaled( struct object
*obj
, struct wait_queue_entry
*entry
);
63 static void event_satisfied( struct object
*obj
, struct wait_queue_entry
*entry
);
64 static int event_signal( struct object
*obj
, unsigned int access
);
65 static struct list
*event_get_kernel_obj_list( struct object
*obj
);
67 static const struct object_ops event_ops
=
69 sizeof(struct event
), /* size */
70 &event_type
, /* type */
71 event_dump
, /* dump */
72 add_queue
, /* add_queue */
73 remove_queue
, /* remove_queue */
74 event_signaled
, /* signaled */
75 event_satisfied
, /* satisfied */
76 event_signal
, /* signal */
77 no_get_fd
, /* get_fd */
78 default_map_access
, /* map_access */
79 default_get_sd
, /* get_sd */
80 default_set_sd
, /* set_sd */
81 default_get_full_name
, /* get_full_name */
82 no_lookup_name
, /* lookup_name */
83 directory_link_name
, /* link_name */
84 default_unlink_name
, /* unlink_name */
85 no_open_file
, /* open_file */
86 event_get_kernel_obj_list
, /* get_kernel_obj_list */
87 no_close_handle
, /* close_handle */
88 no_destroy
/* destroy */
92 static const WCHAR keyed_event_name
[] = {'K','e','y','e','d','E','v','e','n','t'};
94 struct type_descr keyed_event_type
=
96 { keyed_event_name
, sizeof(keyed_event_name
) }, /* name */
97 KEYEDEVENT_ALL_ACCESS
| SYNCHRONIZE
, /* valid_access */
99 STANDARD_RIGHTS_READ
| KEYEDEVENT_WAIT
,
100 STANDARD_RIGHTS_WRITE
| KEYEDEVENT_WAKE
,
101 STANDARD_RIGHTS_EXECUTE
,
102 KEYEDEVENT_ALL_ACCESS
108 struct object obj
; /* object header */
111 static void keyed_event_dump( struct object
*obj
, int verbose
);
112 static int keyed_event_signaled( struct object
*obj
, struct wait_queue_entry
*entry
);
114 static const struct object_ops keyed_event_ops
=
116 sizeof(struct keyed_event
), /* size */
117 &keyed_event_type
, /* type */
118 keyed_event_dump
, /* dump */
119 add_queue
, /* add_queue */
120 remove_queue
, /* remove_queue */
121 keyed_event_signaled
, /* signaled */
122 no_satisfied
, /* satisfied */
123 no_signal
, /* signal */
124 no_get_fd
, /* get_fd */
125 default_map_access
, /* map_access */
126 default_get_sd
, /* get_sd */
127 default_set_sd
, /* set_sd */
128 default_get_full_name
, /* get_full_name */
129 no_lookup_name
, /* lookup_name */
130 directory_link_name
, /* link_name */
131 default_unlink_name
, /* unlink_name */
132 no_open_file
, /* open_file */
133 no_kernel_obj_list
, /* get_kernel_obj_list */
134 no_close_handle
, /* close_handle */
135 no_destroy
/* destroy */
139 struct event
*create_event( struct object
*root
, const struct unicode_str
*name
,
140 unsigned int attr
, int manual_reset
, int initial_state
,
141 const struct security_descriptor
*sd
)
145 if ((event
= create_named_object( root
, &event_ops
, name
, attr
, sd
)))
147 if (get_error() != STATUS_OBJECT_NAME_EXISTS
)
149 /* initialize it if it didn't already exist */
150 list_init( &event
->kernel_object
);
151 event
->manual_reset
= manual_reset
;
152 event
->signaled
= initial_state
;
158 struct event
*get_event_obj( struct process
*process
, obj_handle_t handle
, unsigned int access
)
160 return (struct event
*)get_handle_obj( process
, handle
, access
, &event_ops
);
163 static void pulse_event( struct event
*event
)
166 /* wake up all waiters if manual reset, a single one otherwise */
167 wake_up( &event
->obj
, !event
->manual_reset
);
171 void set_event( struct event
*event
)
174 /* wake up all waiters if manual reset, a single one otherwise */
175 wake_up( &event
->obj
, !event
->manual_reset
);
178 void reset_event( struct event
*event
)
183 static void event_dump( struct object
*obj
, int verbose
)
185 struct event
*event
= (struct event
*)obj
;
186 assert( obj
->ops
== &event_ops
);
187 fprintf( stderr
, "Event manual=%d signaled=%d\n",
188 event
->manual_reset
, event
->signaled
);
191 static int event_signaled( struct object
*obj
, struct wait_queue_entry
*entry
)
193 struct event
*event
= (struct event
*)obj
;
194 assert( obj
->ops
== &event_ops
);
195 return event
->signaled
;
198 static void event_satisfied( struct object
*obj
, struct wait_queue_entry
*entry
)
200 struct event
*event
= (struct event
*)obj
;
201 assert( obj
->ops
== &event_ops
);
202 /* Reset if it's an auto-reset event */
203 if (!event
->manual_reset
) event
->signaled
= 0;
206 static int event_signal( struct object
*obj
, unsigned int access
)
208 struct event
*event
= (struct event
*)obj
;
209 assert( obj
->ops
== &event_ops
);
211 if (!(access
& EVENT_MODIFY_STATE
))
213 set_error( STATUS_ACCESS_DENIED
);
220 static struct list
*event_get_kernel_obj_list( struct object
*obj
)
222 struct event
*event
= (struct event
*)obj
;
223 return &event
->kernel_object
;
226 struct keyed_event
*create_keyed_event( struct object
*root
, const struct unicode_str
*name
,
227 unsigned int attr
, const struct security_descriptor
*sd
)
229 struct keyed_event
*event
;
231 if ((event
= create_named_object( root
, &keyed_event_ops
, name
, attr
, sd
)))
233 if (get_error() != STATUS_OBJECT_NAME_EXISTS
)
235 /* initialize it if it didn't already exist */
241 struct keyed_event
*get_keyed_event_obj( struct process
*process
, obj_handle_t handle
, unsigned int access
)
243 return (struct keyed_event
*)get_handle_obj( process
, handle
, access
, &keyed_event_ops
);
246 static void keyed_event_dump( struct object
*obj
, int verbose
)
248 fputs( "Keyed event\n", stderr
);
251 static enum select_op
matching_op( enum select_op op
)
253 return op
^ (SELECT_KEYED_EVENT_WAIT
^ SELECT_KEYED_EVENT_RELEASE
);
256 static int keyed_event_signaled( struct object
*obj
, struct wait_queue_entry
*entry
)
258 struct wait_queue_entry
*ptr
;
259 struct process
*process
;
260 enum select_op select_op
;
262 assert( obj
->ops
== &keyed_event_ops
);
264 process
= get_wait_queue_thread( entry
)->process
;
265 select_op
= get_wait_queue_select_op( entry
);
266 if (select_op
!= SELECT_KEYED_EVENT_WAIT
&& select_op
!= SELECT_KEYED_EVENT_RELEASE
) return 1;
268 LIST_FOR_EACH_ENTRY( ptr
, &obj
->wait_queue
, struct wait_queue_entry
, entry
)
270 if (ptr
== entry
) continue;
271 if (get_wait_queue_thread( ptr
)->process
!= process
) continue;
272 if (get_wait_queue_select_op( ptr
) != matching_op( select_op
)) continue;
273 if (get_wait_queue_key( ptr
) != get_wait_queue_key( entry
)) continue;
274 if (wake_thread_queue_entry( ptr
)) return 1;
279 /* create an event */
280 DECL_HANDLER(create_event
)
283 struct unicode_str name
;
285 const struct security_descriptor
*sd
;
286 const struct object_attributes
*objattr
= get_req_object_attributes( &sd
, &name
, &root
);
288 if (!objattr
) return;
290 if ((event
= create_event( root
, &name
, objattr
->attributes
,
291 req
->manual_reset
, req
->initial_state
, sd
)))
293 if (get_error() == STATUS_OBJECT_NAME_EXISTS
)
294 reply
->handle
= alloc_handle( current
->process
, event
, req
->access
, objattr
->attributes
);
296 reply
->handle
= alloc_handle_no_access_check( current
->process
, event
,
297 req
->access
, objattr
->attributes
);
298 release_object( event
);
301 if (root
) release_object( root
);
304 /* open a handle to an event */
305 DECL_HANDLER(open_event
)
307 struct unicode_str name
= get_req_unicode_str();
309 reply
->handle
= open_object( current
->process
, req
->rootdir
, req
->access
,
310 &event_ops
, &name
, req
->attributes
);
313 /* do an event operation */
314 DECL_HANDLER(event_op
)
318 if (!(event
= get_event_obj( current
->process
, req
->handle
, EVENT_MODIFY_STATE
))) return;
319 reply
->state
= event
->signaled
;
323 pulse_event( event
);
329 reset_event( event
);
332 set_error( STATUS_INVALID_PARAMETER
);
335 release_object( event
);
338 /* return details about the event */
339 DECL_HANDLER(query_event
)
343 if (!(event
= get_event_obj( current
->process
, req
->handle
, EVENT_QUERY_STATE
))) return;
345 reply
->manual_reset
= event
->manual_reset
;
346 reply
->state
= event
->signaled
;
348 release_object( event
);
351 /* create a keyed event */
352 DECL_HANDLER(create_keyed_event
)
354 struct keyed_event
*event
;
355 struct unicode_str name
;
357 const struct security_descriptor
*sd
;
358 const struct object_attributes
*objattr
= get_req_object_attributes( &sd
, &name
, &root
);
360 if (!objattr
) return;
362 if ((event
= create_keyed_event( root
, &name
, objattr
->attributes
, sd
)))
364 if (get_error() == STATUS_OBJECT_NAME_EXISTS
)
365 reply
->handle
= alloc_handle( current
->process
, event
, req
->access
, objattr
->attributes
);
367 reply
->handle
= alloc_handle_no_access_check( current
->process
, event
,
368 req
->access
, objattr
->attributes
);
369 release_object( event
);
371 if (root
) release_object( root
);
374 /* open a handle to a keyed event */
375 DECL_HANDLER(open_keyed_event
)
377 struct unicode_str name
= get_req_unicode_str();
379 reply
->handle
= open_object( current
->process
, req
->rootdir
, req
->access
,
380 &keyed_event_ops
, &name
, req
->attributes
);