Turn mega double switch into static table (reduces compile time).
[wine] / server / request.c
1 /*
2  * Server-side request handling
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/uio.h>
12 #include <unistd.h>
13
14 #include "winerror.h"
15 #include "winnt.h"
16 #include "winbase.h"
17 #define WANT_REQUEST_HANDLERS
18 #include "server.h"
19 #include "server/request.h"
20 #include "server/thread.h"
21
22 /* check that the string is NULL-terminated and that the len is correct */
23 #define CHECK_STRING(func,str,len) \
24   do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
25          fatal_protocol_error( "%s: invalid string '.*s'\n", (func), (len), (str) ); \
26      } while(0)
27  
28 struct thread *current = NULL;  /* thread handling the current request */
29
30 /* complain about a protocol error and terminate the client connection */
31 static void fatal_protocol_error( const char *err, ... )
32 {
33     va_list args;
34
35     va_start( args, err );
36     fprintf( stderr, "Protocol error:%p: ", current );
37     vfprintf( stderr, err, args );
38     va_end( args );
39     remove_client( current->client_fd, -2 );
40 }
41
42 /* call a request handler */
43 void call_req_handler( struct thread *thread, enum request req,
44                        void *data, int len, int fd )
45 {
46     const struct handler *handler = &req_handlers[req];
47     char *ptr;
48
49     current = thread;
50     if ((req < 0) || (req >= REQ_NB_REQUESTS))
51     {
52         fatal_protocol_error( "unknown request %d\n", req );
53         return;
54     }
55
56     if (len < handler->min_size)
57     {
58         fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
59         return;
60     }
61
62     /* now call the handler */
63     if (current)
64     {
65         CLEAR_ERROR();
66         if (debug_level) trace_request( req, data, len, fd );
67     }
68     len -= handler->min_size;
69     ptr = (char *)data + handler->min_size;
70     handler->handler( data, ptr, len, fd );
71     current = NULL;
72 }
73
74 /* handle a client timeout (unused for now) */
75 void call_timeout_handler( struct thread *thread )
76 {
77     current = thread;
78     if (debug_level) trace_timeout();
79     CLEAR_ERROR();
80     thread_timeout();
81     current = NULL;
82 }
83
84 /* a thread has been killed */
85 void call_kill_handler( struct thread *thread, int exit_code )
86 {
87     /* must be reentrant WRT call_req_handler */
88     struct thread *old_current = current;
89     current = thread;
90     if (current)
91     {
92         if (debug_level) trace_kill( exit_code );
93         thread_killed( current, exit_code );
94     }
95     current = (old_current != thread) ? old_current : NULL;
96 }
97
98
99 /* create a new thread */
100 DECL_HANDLER(new_thread)
101 {
102     struct new_thread_reply reply;
103     struct thread *new_thread;
104     int new_fd, err;
105
106     if ((new_fd = dup(fd)) == -1)
107     {
108         new_thread = NULL;
109         err = ERROR_TOO_MANY_OPEN_FILES;
110         goto done;
111     }
112     if (!(new_thread = create_thread( new_fd, req->pid, &reply.thandle,
113                                       &reply.phandle )))
114     {
115         close( new_fd );
116         err = ERROR_OUTOFMEMORY;
117         goto done;
118     }
119     reply.tid = new_thread;
120     reply.pid = new_thread->process;
121     err = ERROR_SUCCESS;
122
123  done:
124     if (!current)
125     {
126         /* first client doesn't have a current */
127         struct iovec vec = { &reply, sizeof(reply) };
128         send_reply_v( get_initial_client_fd(), err, -1, &vec, 1 );
129     }
130     else
131     {
132         SET_ERROR( err );
133         send_reply( current, -1, 1, &reply, sizeof(reply) );
134     }
135 }
136
137 /* create a new thread */
138 DECL_HANDLER(init_thread)
139 {
140     if (current->state != STARTING)
141     {
142         fatal_protocol_error( "init_thread: already running\n" );
143         return;
144     }
145     current->state    = RUNNING;
146     current->unix_pid = req->unix_pid;
147     if (!(current->name = mem_alloc( len + 1 ))) goto done;
148     memcpy( current->name, data, len );
149     current->name[len] = '\0';
150     CLEAR_ERROR();
151  done:
152     send_reply( current, -1, 0 );
153 }
154
155 /* terminate a process */
156 DECL_HANDLER(terminate_process)
157 {
158     struct process *process;
159
160     if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
161     {
162         kill_process( process, req->exit_code );
163         release_object( process );
164     }
165     if (current) send_reply( current, -1, 0 );
166 }
167
168 /* terminate a thread */
169 DECL_HANDLER(terminate_thread)
170 {
171     struct thread *thread;
172
173     if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
174     {
175         kill_thread( thread, req->exit_code );
176         release_object( thread );
177     }
178     if (current) send_reply( current, -1, 0 );
179 }
180
181 /* close a handle */
182 DECL_HANDLER(close_handle)
183 {
184     close_handle( current->process, req->handle );
185     send_reply( current, -1, 0 );
186 }
187
188 /* duplicate a handle */
189 DECL_HANDLER(dup_handle)
190 {
191     struct dup_handle_reply reply = { -1 };
192     struct process *src, *dst;
193
194     if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
195     {
196         if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
197         {
198             reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle,
199                                              req->access, req->inherit, req->options );
200             release_object( dst );
201         }
202         /* close the handle no matter what happened */
203         if (req->options & DUPLICATE_CLOSE_SOURCE)
204             close_handle( src, req->src_handle );
205         release_object( src );
206     }
207     send_reply( current, -1, 1, &reply, sizeof(reply) );
208 }
209
210 /* fetch information about a process */
211 DECL_HANDLER(get_process_info)
212 {
213     struct process *process;
214     struct get_process_info_reply reply = { 0, 0 };
215
216     if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
217     {
218         get_process_info( process, &reply );
219         release_object( process );
220     }
221     send_reply( current, -1, 1, &reply, sizeof(reply) );
222 }
223
224 /* fetch information about a thread */
225 DECL_HANDLER(get_thread_info)
226 {
227     struct thread *thread;
228     struct get_thread_info_reply reply = { 0, 0 };
229
230     if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
231     {
232         get_thread_info( thread, &reply );
233         release_object( thread );
234     }
235     send_reply( current, -1, 1, &reply, sizeof(reply) );
236 }
237
238 /* open a handle to a process */
239 DECL_HANDLER(open_process)
240 {
241     struct open_process_reply reply = { -1 };
242     struct process *process = get_process_from_id( req->pid );
243     if (process)
244     {
245         reply.handle = alloc_handle( current->process, process,
246                                      req->access, req->inherit );
247         release_object( process );
248     }
249     send_reply( current, -1, 1, &reply, sizeof(reply) );
250 }
251
252 /* select on a handle list */
253 DECL_HANDLER(select)
254 {
255     if (len != req->count * sizeof(int))
256         fatal_protocol_error( "select: bad length %d for %d handles\n",
257                               len, req->count );
258     sleep_on( current, req->count, (int *)data, req->flags, req->timeout );
259 }
260
261 /* create an event */
262 DECL_HANDLER(create_event)
263 {
264     struct create_event_reply reply = { -1 };
265     struct object *obj;
266     char *name = (char *)data;
267     if (!len) name = NULL;
268     else CHECK_STRING( "create_event", name, len );
269
270     obj = create_event( name, req->manual_reset, req->initial_state );
271     if (obj)
272     {
273         reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit );
274         release_object( obj );
275     }
276     send_reply( current, -1, 1, &reply, sizeof(reply) );
277 }
278
279 /* do an event operation */
280 DECL_HANDLER(event_op)
281 {
282     switch(req->op)
283     {
284     case PULSE_EVENT:
285         pulse_event( req->handle );
286         break;
287     case SET_EVENT:
288         set_event( req->handle );
289         break;
290     case RESET_EVENT:
291         reset_event( req->handle );
292         break;
293     default:
294         fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
295     }
296     send_reply( current, -1, 0 );
297 }
298
299 /* create a mutex */
300 DECL_HANDLER(create_mutex)
301 {
302     struct create_mutex_reply reply = { -1 };
303     struct object *obj;
304     char *name = (char *)data;
305     if (!len) name = NULL;
306     else CHECK_STRING( "create_mutex", name, len );
307
308     obj = create_mutex( name, req->owned );
309     if (obj)
310     {
311         reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit );
312         release_object( obj );
313     }
314     send_reply( current, -1, 1, &reply, sizeof(reply) );
315 }
316
317 /* release a mutex */
318 DECL_HANDLER(release_mutex)
319 {
320     if (release_mutex( req->handle )) CLEAR_ERROR();
321     send_reply( current, -1, 0 );
322 }
323
324 /* create a semaphore */
325 DECL_HANDLER(create_semaphore)
326 {
327     struct create_semaphore_reply reply = { -1 };
328     struct object *obj;
329     char *name = (char *)data;
330     if (!len) name = NULL;
331     else CHECK_STRING( "create_semaphore", name, len );
332
333     obj = create_semaphore( name, req->initial, req->max );
334     if (obj)
335     {
336         reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit );
337         release_object( obj );
338     }
339     send_reply( current, -1, 1, &reply, sizeof(reply) );
340 }
341
342 /* release a semaphore */
343 DECL_HANDLER(release_semaphore)
344 {
345     struct release_semaphore_reply reply;
346     if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR();
347     send_reply( current, -1, 1, &reply, sizeof(reply) );
348 }
349
350 /* open a handle to a named object (event, mutex, semaphore) */
351 DECL_HANDLER(open_named_obj)
352 {
353     struct open_named_obj_reply reply;
354     char *name = (char *)data;
355     if (!len) name = NULL;
356     else CHECK_STRING( "open_named_obj", name, len );
357
358     switch(req->type)
359     {
360     case OPEN_EVENT:
361         reply.handle = open_event( req->access, req->inherit, name );
362         break;
363     case OPEN_MUTEX:
364         reply.handle = open_mutex( req->access, req->inherit, name );
365         break;
366     case OPEN_SEMAPHORE:
367         reply.handle = open_semaphore( req->access, req->inherit, name );
368         break;
369     default:
370         fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
371     }
372     send_reply( current, -1, 1, &reply, sizeof(reply) );
373 }
374