Added server-side file mapping object support.
[wine] / server / request.c
1 /*
2  * Server-side request handling
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #include <unistd.h>
14
15 #include "winerror.h"
16 #include "winnt.h"
17 #include "winbase.h"
18 #define WANT_REQUEST_HANDLERS
19 #include "server.h"
20 #include "server/request.h"
21 #include "server/thread.h"
22
23 /* check that the string is NULL-terminated and that the len is correct */
24 #define CHECK_STRING(func,str,len) \
25   do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
26          fatal_protocol_error( "%s: invalid string '.*s'\n", (func), (len), (str) ); \
27      } while(0)
28  
29 struct thread *current = NULL;  /* thread handling the current request */
30
31 /* complain about a protocol error and terminate the client connection */
32 static void fatal_protocol_error( const char *err, ... )
33 {
34     va_list args;
35
36     va_start( args, err );
37     fprintf( stderr, "Protocol error:%p: ", current );
38     vfprintf( stderr, err, args );
39     va_end( args );
40     remove_client( current->client_fd, -2 );
41 }
42
43 /* call a request handler */
44 void call_req_handler( struct thread *thread, enum request req,
45                        void *data, int len, int fd )
46 {
47     const struct handler *handler = &req_handlers[req];
48     char *ptr;
49
50     current = thread;
51     if ((req < 0) || (req >= REQ_NB_REQUESTS))
52     {
53         fatal_protocol_error( "unknown request %d\n", req );
54         return;
55     }
56
57     if (len < handler->min_size)
58     {
59         fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
60         return;
61     }
62
63     /* now call the handler */
64     if (current)
65     {
66         CLEAR_ERROR();
67         if (debug_level) trace_request( req, data, len, fd );
68     }
69     len -= handler->min_size;
70     ptr = (char *)data + handler->min_size;
71     handler->handler( data, ptr, len, fd );
72     current = NULL;
73 }
74
75 /* handle a client timeout (unused for now) */
76 void call_timeout_handler( struct thread *thread )
77 {
78     current = thread;
79     if (debug_level) trace_timeout();
80     CLEAR_ERROR();
81     thread_timeout();
82     current = NULL;
83 }
84
85 /* a thread has been killed */
86 void call_kill_handler( struct thread *thread, int exit_code )
87 {
88     /* must be reentrant WRT call_req_handler */
89     struct thread *old_current = current;
90     current = thread;
91     if (current)
92     {
93         if (debug_level) trace_kill( exit_code );
94         thread_killed( current, exit_code );
95     }
96     current = (old_current != thread) ? old_current : NULL;
97 }
98
99
100 /* create a new thread */
101 DECL_HANDLER(new_thread)
102 {
103     struct new_thread_reply reply;
104     struct thread *new_thread;
105     int new_fd, err;
106
107     if ((new_fd = dup(fd)) == -1)
108     {
109         new_thread = NULL;
110         err = ERROR_TOO_MANY_OPEN_FILES;
111         goto done;
112     }
113     if (!(new_thread = create_thread( new_fd, req->pid, &reply.thandle,
114                                       &reply.phandle )))
115     {
116         close( new_fd );
117         err = ERROR_OUTOFMEMORY;
118         goto done;
119     }
120     reply.tid = new_thread;
121     reply.pid = new_thread->process;
122     err = ERROR_SUCCESS;
123
124  done:
125     if (!current)
126     {
127         /* first client doesn't have a current */
128         struct iovec vec = { &reply, sizeof(reply) };
129         send_reply_v( get_initial_client_fd(), err, -1, &vec, 1 );
130     }
131     else
132     {
133         SET_ERROR( err );
134         send_reply( current, -1, 1, &reply, sizeof(reply) );
135     }
136 }
137
138 /* create a new thread */
139 DECL_HANDLER(init_thread)
140 {
141     if (current->state != STARTING)
142     {
143         fatal_protocol_error( "init_thread: already running\n" );
144         return;
145     }
146     current->state    = RUNNING;
147     current->unix_pid = req->unix_pid;
148     if (!(current->name = mem_alloc( len + 1 ))) goto done;
149     memcpy( current->name, data, len );
150     current->name[len] = '\0';
151     CLEAR_ERROR();
152  done:
153     send_reply( current, -1, 0 );
154 }
155
156 /* set the debug level */
157 DECL_HANDLER(set_debug)
158 {
159     debug_level = req->level;
160     /* Make sure last_req is initialized */
161     current->last_req = REQ_SET_DEBUG;
162     CLEAR_ERROR();
163     send_reply( current, -1, 0 );
164 }
165
166 /* terminate a process */
167 DECL_HANDLER(terminate_process)
168 {
169     struct process *process;
170
171     if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
172     {
173         kill_process( process, req->exit_code );
174         release_object( process );
175     }
176     if (current) send_reply( current, -1, 0 );
177 }
178
179 /* terminate a thread */
180 DECL_HANDLER(terminate_thread)
181 {
182     struct thread *thread;
183
184     if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
185     {
186         kill_thread( thread, req->exit_code );
187         release_object( thread );
188     }
189     if (current) send_reply( current, -1, 0 );
190 }
191
192 /* close a handle */
193 DECL_HANDLER(close_handle)
194 {
195     close_handle( current->process, req->handle );
196     send_reply( current, -1, 0 );
197 }
198
199 /* duplicate a handle */
200 DECL_HANDLER(dup_handle)
201 {
202     struct dup_handle_reply reply = { -1 };
203     struct process *src, *dst;
204
205     if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
206     {
207         if (req->options & DUP_HANDLE_MAKE_GLOBAL)
208         {
209             reply.handle = duplicate_handle( src, req->src_handle, NULL, -1,
210                                              req->access, req->inherit, req->options );
211         }
212         else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
213         {
214             reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle,
215                                              req->access, req->inherit, req->options );
216             release_object( dst );
217         }
218         /* close the handle no matter what happened */
219         if (req->options & DUP_HANDLE_CLOSE_SOURCE)
220             close_handle( src, req->src_handle );
221         release_object( src );
222     }
223     send_reply( current, -1, 1, &reply, sizeof(reply) );
224 }
225
226 /* fetch information about a process */
227 DECL_HANDLER(get_process_info)
228 {
229     struct process *process;
230     struct get_process_info_reply reply = { 0, 0 };
231
232     if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
233     {
234         get_process_info( process, &reply );
235         release_object( process );
236     }
237     send_reply( current, -1, 1, &reply, sizeof(reply) );
238 }
239
240 /* fetch information about a thread */
241 DECL_HANDLER(get_thread_info)
242 {
243     struct thread *thread;
244     struct get_thread_info_reply reply = { 0, 0 };
245
246     if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
247     {
248         get_thread_info( thread, &reply );
249         release_object( thread );
250     }
251     send_reply( current, -1, 1, &reply, sizeof(reply) );
252 }
253
254 /* open a handle to a process */
255 DECL_HANDLER(open_process)
256 {
257     struct open_process_reply reply = { -1 };
258     struct process *process = get_process_from_id( req->pid );
259     if (process)
260     {
261         reply.handle = alloc_handle( current->process, process,
262                                      req->access, req->inherit );
263         release_object( process );
264     }
265     send_reply( current, -1, 1, &reply, sizeof(reply) );
266 }
267
268 /* select on a handle list */
269 DECL_HANDLER(select)
270 {
271     if (len != req->count * sizeof(int))
272         fatal_protocol_error( "select: bad length %d for %d handles\n",
273                               len, req->count );
274     sleep_on( current, req->count, (int *)data, req->flags, req->timeout );
275 }
276
277 /* create an event */
278 DECL_HANDLER(create_event)
279 {
280     struct create_event_reply reply = { -1 };
281     struct object *obj;
282     char *name = (char *)data;
283     if (!len) name = NULL;
284     else CHECK_STRING( "create_event", name, len );
285
286     obj = create_event( name, req->manual_reset, req->initial_state );
287     if (obj)
288     {
289         reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit );
290         release_object( obj );
291     }
292     send_reply( current, -1, 1, &reply, sizeof(reply) );
293 }
294
295 /* do an event operation */
296 DECL_HANDLER(event_op)
297 {
298     switch(req->op)
299     {
300     case PULSE_EVENT:
301         pulse_event( req->handle );
302         break;
303     case SET_EVENT:
304         set_event( req->handle );
305         break;
306     case RESET_EVENT:
307         reset_event( req->handle );
308         break;
309     default:
310         fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
311     }
312     send_reply( current, -1, 0 );
313 }
314
315 /* create a mutex */
316 DECL_HANDLER(create_mutex)
317 {
318     struct create_mutex_reply reply = { -1 };
319     struct object *obj;
320     char *name = (char *)data;
321     if (!len) name = NULL;
322     else CHECK_STRING( "create_mutex", name, len );
323
324     obj = create_mutex( name, req->owned );
325     if (obj)
326     {
327         reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit );
328         release_object( obj );
329     }
330     send_reply( current, -1, 1, &reply, sizeof(reply) );
331 }
332
333 /* release a mutex */
334 DECL_HANDLER(release_mutex)
335 {
336     if (release_mutex( req->handle )) CLEAR_ERROR();
337     send_reply( current, -1, 0 );
338 }
339
340 /* create a semaphore */
341 DECL_HANDLER(create_semaphore)
342 {
343     struct create_semaphore_reply reply = { -1 };
344     struct object *obj;
345     char *name = (char *)data;
346     if (!len) name = NULL;
347     else CHECK_STRING( "create_semaphore", name, len );
348
349     obj = create_semaphore( name, req->initial, req->max );
350     if (obj)
351     {
352         reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit );
353         release_object( obj );
354     }
355     send_reply( current, -1, 1, &reply, sizeof(reply) );
356 }
357
358 /* release a semaphore */
359 DECL_HANDLER(release_semaphore)
360 {
361     struct release_semaphore_reply reply;
362     if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR();
363     send_reply( current, -1, 1, &reply, sizeof(reply) );
364 }
365
366 /* open a handle to a named object (event, mutex, semaphore) */
367 DECL_HANDLER(open_named_obj)
368 {
369     struct open_named_obj_reply reply;
370     char *name = (char *)data;
371     if (!len) name = NULL;
372     else CHECK_STRING( "open_named_obj", name, len );
373
374     switch(req->type)
375     {
376     case OPEN_EVENT:
377         reply.handle = open_event( req->access, req->inherit, name );
378         break;
379     case OPEN_MUTEX:
380         reply.handle = open_mutex( req->access, req->inherit, name );
381         break;
382     case OPEN_SEMAPHORE:
383         reply.handle = open_semaphore( req->access, req->inherit, name );
384         break;
385     case OPEN_MAPPING:
386         reply.handle = open_mapping( req->access, req->inherit, name );
387         break;
388     default:
389         fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
390     }
391     send_reply( current, -1, 1, &reply, sizeof(reply) );
392 }
393
394 /* create a file */
395 DECL_HANDLER(create_file)
396 {
397     struct create_file_reply reply = { -1 };
398     struct object *obj;
399     int new_fd;
400
401     if ((new_fd = dup(fd)) == -1)
402     {
403         SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
404         goto done;
405     }
406     if ((obj = create_file( new_fd )) != NULL)
407     {
408         reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
409         release_object( obj );
410     }
411  done:
412     send_reply( current, -1, 1, &reply, sizeof(reply) );
413 }
414
415 /* get a Unix fd to read from a file */
416 DECL_HANDLER(get_read_fd)
417 {
418     struct object *obj;
419     int read_fd;
420
421     if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
422     {
423         read_fd = obj->ops->get_read_fd( obj );
424         release_object( obj );
425     }
426     else read_fd = -1;
427     send_reply( current, read_fd, 0 );
428 }
429
430 /* get a Unix fd to write to a file */
431 DECL_HANDLER(get_write_fd)
432 {
433     struct object *obj;
434     int write_fd;
435
436     if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
437     {
438         write_fd = obj->ops->get_write_fd( obj );
439         release_object( obj );
440     }
441     else write_fd = -1;
442     send_reply( current, write_fd, 0 );
443 }
444
445 /* set a file current position */
446 DECL_HANDLER(set_file_pointer)
447 {
448     struct set_file_pointer_reply reply = { req->low, req->high };
449     set_file_pointer( req->handle, &reply.low, &reply.high, req->whence );
450     send_reply( current, -1, 1, &reply, sizeof(reply) );
451 }
452
453 /* truncate (or extend) a file */
454 DECL_HANDLER(truncate_file)
455 {
456     truncate_file( req->handle );
457     send_reply( current, -1, 0 );
458 }
459
460 /* flush a file buffers */
461 DECL_HANDLER(flush_file)
462 {
463     struct object *obj;
464
465     if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
466     {
467         obj->ops->flush( obj );
468         release_object( obj );
469     }
470     send_reply( current, -1, 0 );
471 }
472
473 /* get a file information */
474 DECL_HANDLER(get_file_info)
475 {
476     struct get_file_info_reply reply;
477     get_file_info( req->handle, &reply );
478     send_reply( current, -1, 1, &reply, sizeof(reply) );
479 }
480
481 /* create an anonymous pipe */
482 DECL_HANDLER(create_pipe)
483 {
484     struct create_pipe_reply reply = { -1, -1 };
485     struct object *obj[2];
486     if (create_pipe( obj ))
487     {
488         reply.handle_read = alloc_handle( current->process, obj[0],
489                                           STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
490                                           req->inherit );
491         if (reply.handle_read != -1)
492         {
493             reply.handle_write = alloc_handle( current->process, obj[1],
494                                                STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
495                                                req->inherit );
496             if (reply.handle_write == -1)
497                 close_handle( current->process, reply.handle_read );
498         }
499         release_object( obj[0] );
500         release_object( obj[1] );
501     }
502     send_reply( current, -1, 1, &reply, sizeof(reply) );
503 }
504
505 /* create a console */
506 DECL_HANDLER(create_console)
507 {
508     struct create_console_reply reply = { -1, -1 };
509     struct object *obj[2];
510     if (create_console( fd, obj ))
511     {
512         reply.handle_read = alloc_handle( current->process, obj[0],
513                                           STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
514                                           req->inherit );
515         if (reply.handle_read != -1)
516         {
517             reply.handle_write = alloc_handle( current->process, obj[1],
518                                                STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
519                                                req->inherit );
520             if (reply.handle_write == -1)
521                 close_handle( current->process, reply.handle_read );
522         }
523         release_object( obj[0] );
524         release_object( obj[1] );
525     }
526     send_reply( current, -1, 1, &reply, sizeof(reply) );
527 }
528
529 /* set a console fd */
530 DECL_HANDLER(set_console_fd)
531 {
532     set_console_fd( req->handle, fd );
533     send_reply( current, -1, 0 );
534 }
535
536 /* create a change notification */
537 DECL_HANDLER(create_change_notification)
538 {
539     struct object *obj;
540     struct create_change_notification_reply reply = { -1 };
541
542     if ((obj = create_change_notification( req->subtree, req->filter )))
543     {
544         reply.handle = alloc_handle( current->process, obj,
545                                      STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
546         release_object( obj );
547     }
548     send_reply( current, -1, 1, &reply, sizeof(reply) );
549 }
550
551 /* create a file mapping */
552 DECL_HANDLER(create_mapping)
553 {
554     struct object *obj;
555     struct create_mapping_reply reply = { -1 };
556     char *name = (char *)data;
557     if (!len) name = NULL;
558     else CHECK_STRING( "create_mapping", name, len );
559
560     if ((obj = create_mapping( req->size_high, req->size_low,
561                                req->protect, req->handle, name )))
562     {
563         int access = FILE_MAP_ALL_ACCESS;
564         if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
565         reply.handle = alloc_handle( current->process, obj, access, 0 );
566         release_object( obj );
567     }
568     send_reply( current, -1, 1, &reply, sizeof(reply) );
569 }
570
571 /* get a mapping information */
572 DECL_HANDLER(get_mapping_info)
573 {
574     struct get_mapping_info_reply reply;
575     int map_fd = get_mapping_info( req->handle, &reply );
576     send_reply( current, map_fd, 1, &reply, sizeof(reply) );
577 }