2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
13 #include <sys/types.h>
21 #define WANT_REQUEST_HANDLERS
23 #include "server/request.h"
24 #include "server/process.h"
25 #include "server/thread.h"
27 /* check that the string is NULL-terminated and that the len is correct */
28 #define CHECK_STRING(func,str,len) \
29 do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
30 fatal_protocol_error( "%s: invalid string '%.*s'\n", (func), (len), (str) ); \
33 struct thread *current = NULL; /* thread handling the current request */
35 /* complain about a protocol error and terminate the client connection */
36 static void fatal_protocol_error( const char *err, ... )
40 va_start( args, err );
41 fprintf( stderr, "Protocol error:%p: ", current );
42 vfprintf( stderr, err, args );
44 remove_client( current->client_fd, -2 );
47 /* call a request handler */
48 void call_req_handler( struct thread *thread, enum request req,
49 void *data, int len, int fd )
51 const struct handler *handler = &req_handlers[req];
55 if ((req < 0) || (req >= REQ_NB_REQUESTS))
57 fatal_protocol_error( "unknown request %d\n", req );
61 if (len < handler->min_size)
63 fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
67 /* now call the handler */
71 if (debug_level) trace_request( req, data, len, fd );
73 len -= handler->min_size;
74 ptr = (char *)data + handler->min_size;
75 handler->handler( data, ptr, len, fd );
79 /* handle a client timeout (unused for now) */
80 void call_timeout_handler( struct thread *thread )
83 if (debug_level) trace_timeout();
89 /* a thread has been killed */
90 void call_kill_handler( struct thread *thread, int exit_code )
92 /* must be reentrant WRT call_req_handler */
93 struct thread *old_current = current;
97 if (debug_level) trace_kill( exit_code );
98 thread_killed( current, exit_code );
100 current = (old_current != thread) ? old_current : NULL;
104 /* create a new process */
105 DECL_HANDLER(new_process)
107 struct new_process_reply reply;
108 struct process *process;
110 if ((process = create_process( req )))
113 reply.handle = alloc_handle( current->process, process,
114 PROCESS_ALL_ACCESS, req->inherit );
115 release_object( process );
122 send_reply( current, -1, 1, &reply, sizeof(reply) );
125 /* create a new thread */
126 DECL_HANDLER(new_thread)
128 struct new_thread_reply reply;
131 if ((new_fd = dup(fd)) != -1)
133 reply.tid = create_thread( new_fd, req->pid, req->suspend,
134 req->inherit, &reply.handle );
135 if (!reply.tid) close( new_fd );
138 SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
140 send_reply( current, -1, 1, &reply, sizeof(reply) );
143 /* initialize a new process */
144 DECL_HANDLER(init_process)
146 struct init_process_reply reply;
147 if (current->state != RUNNING)
149 fatal_protocol_error( "init_process: init_thread not called yet\n" );
152 if (!get_process_init_info( current->process, &reply ))
154 fatal_protocol_error( "init_process: called twice\n" );
157 send_reply( current, -1, 1, &reply, sizeof(reply) );
160 /* initialize a new thread */
161 DECL_HANDLER(init_thread)
163 struct init_thread_reply reply;
165 if (current->state != STARTING)
167 fatal_protocol_error( "init_thread: already running\n" );
170 current->state = RUNNING;
171 current->unix_pid = req->unix_pid;
172 if (current->suspend > 0)
173 kill( current->unix_pid, SIGSTOP );
174 reply.pid = current->process;
176 send_reply( current, -1, 1, &reply, sizeof(reply) );
179 /* set the debug level */
180 DECL_HANDLER(set_debug)
182 debug_level = req->level;
183 /* Make sure last_req is initialized */
184 current->last_req = REQ_SET_DEBUG;
186 send_reply( current, -1, 0 );
189 /* terminate a process */
190 DECL_HANDLER(terminate_process)
192 struct process *process;
194 if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
196 kill_process( process, req->exit_code );
197 release_object( process );
199 if (current) send_reply( current, -1, 0 );
202 /* terminate a thread */
203 DECL_HANDLER(terminate_thread)
205 struct thread *thread;
207 if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
209 kill_thread( thread, req->exit_code );
210 release_object( thread );
212 if (current) send_reply( current, -1, 0 );
216 DECL_HANDLER(close_handle)
218 close_handle( current->process, req->handle );
219 send_reply( current, -1, 0 );
222 /* get information about a handle */
223 DECL_HANDLER(get_handle_info)
225 struct get_handle_info_reply reply;
226 reply.flags = set_handle_info( current->process, req->handle, 0, 0 );
227 send_reply( current, -1, 1, &reply, sizeof(reply) );
230 /* set a handle information */
231 DECL_HANDLER(set_handle_info)
233 set_handle_info( current->process, req->handle, req->mask, req->flags );
234 send_reply( current, -1, 0 );
237 /* duplicate a handle */
238 DECL_HANDLER(dup_handle)
240 struct dup_handle_reply reply = { -1 };
241 struct process *src, *dst;
243 if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
245 if (req->options & DUP_HANDLE_MAKE_GLOBAL)
247 reply.handle = duplicate_handle( src, req->src_handle, NULL,
248 req->access, req->inherit, req->options );
250 else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
252 reply.handle = duplicate_handle( src, req->src_handle, dst,
253 req->access, req->inherit, req->options );
254 release_object( dst );
256 /* close the handle no matter what happened */
257 if (req->options & DUP_HANDLE_CLOSE_SOURCE)
258 close_handle( src, req->src_handle );
259 release_object( src );
261 send_reply( current, -1, 1, &reply, sizeof(reply) );
264 /* fetch information about a process */
265 DECL_HANDLER(get_process_info)
267 struct process *process;
268 struct get_process_info_reply reply = { 0, 0, 0 };
270 if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
272 get_process_info( process, &reply );
273 release_object( process );
275 send_reply( current, -1, 1, &reply, sizeof(reply) );
278 /* set information about a process */
279 DECL_HANDLER(set_process_info)
281 struct process *process;
283 if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
285 set_process_info( process, req );
286 release_object( process );
288 send_reply( current, -1, 0 );
291 /* fetch information about a thread */
292 DECL_HANDLER(get_thread_info)
294 struct thread *thread;
295 struct get_thread_info_reply reply = { 0, 0 };
297 if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
299 get_thread_info( thread, &reply );
300 release_object( thread );
302 send_reply( current, -1, 1, &reply, sizeof(reply) );
305 /* set information about a thread */
306 DECL_HANDLER(set_thread_info)
308 struct thread *thread;
310 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
312 set_thread_info( thread, req );
313 release_object( thread );
315 send_reply( current, -1, 0 );
318 /* suspend a thread */
319 DECL_HANDLER(suspend_thread)
321 struct thread *thread;
322 struct suspend_thread_reply reply = { -1 };
323 if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
325 reply.count = suspend_thread( thread );
326 release_object( thread );
328 send_reply( current, -1, 1, &reply, sizeof(reply) );
332 /* resume a thread */
333 DECL_HANDLER(resume_thread)
335 struct thread *thread;
336 struct resume_thread_reply reply = { -1 };
337 if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
339 reply.count = resume_thread( thread );
340 release_object( thread );
342 send_reply( current, -1, 1, &reply, sizeof(reply) );
346 /* queue an APC for a thread */
347 DECL_HANDLER(queue_apc)
349 struct thread *thread;
350 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
352 thread_queue_apc( thread, req->func, req->param );
353 release_object( thread );
355 send_reply( current, -1, 0 );
358 /* open a handle to a process */
359 DECL_HANDLER(open_process)
361 struct open_process_reply reply = { -1 };
362 struct process *process = get_process_from_id( req->pid );
365 reply.handle = alloc_handle( current->process, process,
366 req->access, req->inherit );
367 release_object( process );
369 send_reply( current, -1, 1, &reply, sizeof(reply) );
372 /* select on a handle list */
375 if (len != req->count * sizeof(int))
376 fatal_protocol_error( "select: bad length %d for %d handles\n",
378 sleep_on( current, req->count, (int *)data, req->flags, req->timeout );
381 /* create an event */
382 DECL_HANDLER(create_event)
384 struct create_event_reply reply = { -1 };
386 char *name = (char *)data;
387 if (!len) name = NULL;
388 else CHECK_STRING( "create_event", name, len );
390 obj = create_event( name, req->manual_reset, req->initial_state );
393 reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit );
394 release_object( obj );
396 send_reply( current, -1, 1, &reply, sizeof(reply) );
399 /* do an event operation */
400 DECL_HANDLER(event_op)
405 pulse_event( req->handle );
408 set_event( req->handle );
411 reset_event( req->handle );
414 fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
416 send_reply( current, -1, 0 );
420 DECL_HANDLER(create_mutex)
422 struct create_mutex_reply reply = { -1 };
424 char *name = (char *)data;
425 if (!len) name = NULL;
426 else CHECK_STRING( "create_mutex", name, len );
428 obj = create_mutex( name, req->owned );
431 reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit );
432 release_object( obj );
434 send_reply( current, -1, 1, &reply, sizeof(reply) );
437 /* release a mutex */
438 DECL_HANDLER(release_mutex)
440 if (release_mutex( req->handle )) CLEAR_ERROR();
441 send_reply( current, -1, 0 );
444 /* create a semaphore */
445 DECL_HANDLER(create_semaphore)
447 struct create_semaphore_reply reply = { -1 };
449 char *name = (char *)data;
450 if (!len) name = NULL;
451 else CHECK_STRING( "create_semaphore", name, len );
453 obj = create_semaphore( name, req->initial, req->max );
456 reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit );
457 release_object( obj );
459 send_reply( current, -1, 1, &reply, sizeof(reply) );
462 /* release a semaphore */
463 DECL_HANDLER(release_semaphore)
465 struct release_semaphore_reply reply;
466 if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR();
467 send_reply( current, -1, 1, &reply, sizeof(reply) );
470 /* open a handle to a named object (event, mutex, semaphore) */
471 DECL_HANDLER(open_named_obj)
473 struct open_named_obj_reply reply;
474 char *name = (char *)data;
475 if (!len) name = NULL;
476 else CHECK_STRING( "open_named_obj", name, len );
481 reply.handle = open_event( req->access, req->inherit, name );
484 reply.handle = open_mutex( req->access, req->inherit, name );
487 reply.handle = open_semaphore( req->access, req->inherit, name );
490 reply.handle = open_mapping( req->access, req->inherit, name );
493 fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
495 send_reply( current, -1, 1, &reply, sizeof(reply) );
499 DECL_HANDLER(create_file)
501 struct create_file_reply reply = { -1 };
503 char *name = (char *)data;
504 if (!len) name = NULL;
505 else CHECK_STRING( "create_file", name, len );
507 if ((obj = create_file( fd, name, req->access,
508 req->sharing, req->create, req->attrs )) != NULL)
510 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
511 release_object( obj );
513 send_reply( current, -1, 1, &reply, sizeof(reply) );
516 /* get a Unix fd to read from a file */
517 DECL_HANDLER(get_read_fd)
522 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
524 read_fd = obj->ops->get_read_fd( obj );
525 release_object( obj );
528 send_reply( current, read_fd, 0 );
531 /* get a Unix fd to write to a file */
532 DECL_HANDLER(get_write_fd)
537 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
539 write_fd = obj->ops->get_write_fd( obj );
540 release_object( obj );
543 send_reply( current, write_fd, 0 );
546 /* set a file current position */
547 DECL_HANDLER(set_file_pointer)
549 struct set_file_pointer_reply reply = { req->low, req->high };
550 set_file_pointer( req->handle, &reply.low, &reply.high, req->whence );
551 send_reply( current, -1, 1, &reply, sizeof(reply) );
554 /* truncate (or extend) a file */
555 DECL_HANDLER(truncate_file)
557 truncate_file( req->handle );
558 send_reply( current, -1, 0 );
561 /* flush a file buffers */
562 DECL_HANDLER(flush_file)
566 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
568 obj->ops->flush( obj );
569 release_object( obj );
571 send_reply( current, -1, 0 );
574 /* set a file access and modification times */
575 DECL_HANDLER(set_file_time)
577 set_file_time( req->handle, req->access_time, req->write_time );
578 send_reply( current, -1, 0 );
581 /* get a file information */
582 DECL_HANDLER(get_file_info)
585 struct get_file_info_reply reply;
587 if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
589 obj->ops->get_file_info( obj, &reply );
590 release_object( obj );
592 send_reply( current, -1, 1, &reply, sizeof(reply) );
595 /* lock a region of a file */
596 DECL_HANDLER(lock_file)
600 if ((file = get_file_obj( current->process, req->handle, 0 )))
602 file_lock( file, req->offset_high, req->offset_low,
603 req->count_high, req->count_low );
604 release_object( file );
606 send_reply( current, -1, 0 );
610 /* unlock a region of a file */
611 DECL_HANDLER(unlock_file)
615 if ((file = get_file_obj( current->process, req->handle, 0 )))
617 file_unlock( file, req->offset_high, req->offset_low,
618 req->count_high, req->count_low );
619 release_object( file );
621 send_reply( current, -1, 0 );
625 /* create an anonymous pipe */
626 DECL_HANDLER(create_pipe)
628 struct create_pipe_reply reply = { -1, -1 };
629 struct object *obj[2];
630 if (create_pipe( obj ))
632 reply.handle_read = alloc_handle( current->process, obj[0],
633 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
635 if (reply.handle_read != -1)
637 reply.handle_write = alloc_handle( current->process, obj[1],
638 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
640 if (reply.handle_write == -1)
641 close_handle( current->process, reply.handle_read );
643 release_object( obj[0] );
644 release_object( obj[1] );
646 send_reply( current, -1, 1, &reply, sizeof(reply) );
649 /* allocate a console for the current process */
650 DECL_HANDLER(alloc_console)
652 alloc_console( current->process );
653 send_reply( current, -1, 0 );
656 /* free the console of the current process */
657 DECL_HANDLER(free_console)
659 free_console( current->process );
660 send_reply( current, -1, 0 );
663 /* open a handle to the process console */
664 DECL_HANDLER(open_console)
667 struct open_console_reply reply = { -1 };
668 if ((obj = get_console( current->process, req->output )))
670 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
671 release_object( obj );
673 send_reply( current, -1, 1, &reply, sizeof(reply) );
676 /* set info about a console (output only) */
677 DECL_HANDLER(set_console_info)
679 char *name = (char *)data;
680 if (!len) name = NULL;
681 else CHECK_STRING( "set_console_info", name, len );
682 set_console_info( req->handle, req, name );
683 send_reply( current, -1, 0 );
686 /* get info about a console (output only) */
687 DECL_HANDLER(get_console_info)
689 struct get_console_info_reply reply;
691 get_console_info( req->handle, &reply, &title );
692 send_reply( current, -1, 2, &reply, sizeof(reply),
693 title, title ? strlen(title)+1 : 0 );
696 /* set a console fd */
697 DECL_HANDLER(set_console_fd)
699 set_console_fd( req->handle, fd, req->pid );
700 send_reply( current, -1, 0 );
703 /* get a console mode (input or output) */
704 DECL_HANDLER(get_console_mode)
706 struct get_console_mode_reply reply;
707 get_console_mode( req->handle, &reply.mode );
708 send_reply( current, -1, 1, &reply, sizeof(reply) );
711 /* set a console mode (input or output) */
712 DECL_HANDLER(set_console_mode)
714 set_console_mode( req->handle, req->mode );
715 send_reply( current, -1, 0 );
718 /* add input records to a console input queue */
719 DECL_HANDLER(write_console_input)
721 struct write_console_input_reply reply;
722 INPUT_RECORD *records = (INPUT_RECORD *)data;
724 if (len != req->count * sizeof(INPUT_RECORD))
725 fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
727 reply.written = write_console_input( req->handle, req->count, records );
728 send_reply( current, -1, 1, &reply, sizeof(reply) );
731 /* fetch input records from a console input queue */
732 DECL_HANDLER(read_console_input)
734 read_console_input( req->handle, req->count, req->flush );
737 /* create a change notification */
738 DECL_HANDLER(create_change_notification)
741 struct create_change_notification_reply reply = { -1 };
743 if ((obj = create_change_notification( req->subtree, req->filter )))
745 reply.handle = alloc_handle( current->process, obj,
746 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
747 release_object( obj );
749 send_reply( current, -1, 1, &reply, sizeof(reply) );
752 /* create a file mapping */
753 DECL_HANDLER(create_mapping)
756 struct create_mapping_reply reply = { -1 };
757 char *name = (char *)data;
758 if (!len) name = NULL;
759 else CHECK_STRING( "create_mapping", name, len );
761 if ((obj = create_mapping( req->size_high, req->size_low,
762 req->protect, req->handle, name )))
764 int access = FILE_MAP_ALL_ACCESS;
765 if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
766 reply.handle = alloc_handle( current->process, obj, access, req->inherit );
767 release_object( obj );
769 send_reply( current, -1, 1, &reply, sizeof(reply) );
772 /* get a mapping information */
773 DECL_HANDLER(get_mapping_info)
775 struct get_mapping_info_reply reply;
776 int map_fd = get_mapping_info( req->handle, &reply );
777 send_reply( current, map_fd, 1, &reply, sizeof(reply) );
780 /* create a device */
781 DECL_HANDLER(create_device)
784 struct create_device_reply reply = { -1 };
786 if ((obj = create_device( req->id )))
788 reply.handle = alloc_handle( current->process, obj,
789 req->access, req->inherit );
790 release_object( obj );
792 send_reply( current, -1, 1, &reply, sizeof(reply) );
795 /* create a snapshot */
796 DECL_HANDLER(create_snapshot)
799 struct create_snapshot_reply reply = { -1 };
801 if ((obj = create_snapshot( req->flags )))
803 reply.handle = alloc_handle( current->process, obj, 0, req->inherit );
804 release_object( obj );
806 send_reply( current, -1, 1, &reply, sizeof(reply) );
809 /* get the next process from a snapshot */
810 DECL_HANDLER(next_process)
812 struct next_process_reply reply;
813 snapshot_next_process( req->handle, req->reset, &reply );
814 send_reply( current, -1, 1, &reply, sizeof(reply) );