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 /* debugger support operations */
319 DECL_HANDLER(debugger
)
323 case DEBUGGER_FREEZE_ALL
:
324 suspend_all_threads();
327 case DEBUGGER_UNFREEZE_ALL
:
328 resume_all_threads();
332 send_reply( current
, -1, 0 );
335 /* suspend a thread */
336 DECL_HANDLER(suspend_thread
)
338 struct thread
*thread
;
339 struct suspend_thread_reply reply
= { -1 };
340 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
342 reply
.count
= suspend_thread( thread
);
343 release_object( thread
);
345 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
349 /* resume a thread */
350 DECL_HANDLER(resume_thread
)
352 struct thread
*thread
;
353 struct resume_thread_reply reply
= { -1 };
354 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
356 reply
.count
= resume_thread( thread
);
357 release_object( thread
);
359 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
363 /* queue an APC for a thread */
364 DECL_HANDLER(queue_apc
)
366 struct thread
*thread
;
367 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_CONTEXT
)))
369 thread_queue_apc( thread
, req
->func
, req
->param
);
370 release_object( thread
);
372 send_reply( current
, -1, 0 );
375 /* open a handle to a process */
376 DECL_HANDLER(open_process
)
378 struct open_process_reply reply
= { -1 };
379 struct process
*process
= get_process_from_id( req
->pid
);
382 reply
.handle
= alloc_handle( current
->process
, process
,
383 req
->access
, req
->inherit
);
384 release_object( process
);
386 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
389 /* select on a handle list */
392 if (len
!= req
->count
* sizeof(int))
393 fatal_protocol_error( "select: bad length %d for %d handles\n",
395 sleep_on( current
, req
->count
, (int *)data
, req
->flags
, req
->timeout
);
398 /* create an event */
399 DECL_HANDLER(create_event
)
401 struct create_event_reply reply
= { -1 };
403 char *name
= (char *)data
;
404 if (!len
) name
= NULL
;
405 else CHECK_STRING( "create_event", name
, len
);
407 obj
= create_event( name
, req
->manual_reset
, req
->initial_state
);
410 reply
.handle
= alloc_handle( current
->process
, obj
, EVENT_ALL_ACCESS
, req
->inherit
);
411 release_object( obj
);
413 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
416 /* do an event operation */
417 DECL_HANDLER(event_op
)
422 pulse_event( req
->handle
);
425 set_event( req
->handle
);
428 reset_event( req
->handle
);
431 fatal_protocol_error( "event_op: invalid operation %d\n", req
->op
);
433 send_reply( current
, -1, 0 );
437 DECL_HANDLER(create_mutex
)
439 struct create_mutex_reply reply
= { -1 };
441 char *name
= (char *)data
;
442 if (!len
) name
= NULL
;
443 else CHECK_STRING( "create_mutex", name
, len
);
445 obj
= create_mutex( name
, req
->owned
);
448 reply
.handle
= alloc_handle( current
->process
, obj
, MUTEX_ALL_ACCESS
, req
->inherit
);
449 release_object( obj
);
451 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
454 /* release a mutex */
455 DECL_HANDLER(release_mutex
)
457 if (release_mutex( req
->handle
)) CLEAR_ERROR();
458 send_reply( current
, -1, 0 );
461 /* create a semaphore */
462 DECL_HANDLER(create_semaphore
)
464 struct create_semaphore_reply reply
= { -1 };
466 char *name
= (char *)data
;
467 if (!len
) name
= NULL
;
468 else CHECK_STRING( "create_semaphore", name
, len
);
470 obj
= create_semaphore( name
, req
->initial
, req
->max
);
473 reply
.handle
= alloc_handle( current
->process
, obj
, SEMAPHORE_ALL_ACCESS
, req
->inherit
);
474 release_object( obj
);
476 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
479 /* release a semaphore */
480 DECL_HANDLER(release_semaphore
)
482 struct release_semaphore_reply reply
;
483 if (release_semaphore( req
->handle
, req
->count
, &reply
.prev_count
)) CLEAR_ERROR();
484 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
487 /* open a handle to a named object (event, mutex, semaphore) */
488 DECL_HANDLER(open_named_obj
)
490 struct open_named_obj_reply reply
;
491 char *name
= (char *)data
;
492 if (!len
) name
= NULL
;
493 else CHECK_STRING( "open_named_obj", name
, len
);
498 reply
.handle
= open_event( req
->access
, req
->inherit
, name
);
501 reply
.handle
= open_mutex( req
->access
, req
->inherit
, name
);
504 reply
.handle
= open_semaphore( req
->access
, req
->inherit
, name
);
507 reply
.handle
= open_mapping( req
->access
, req
->inherit
, name
);
510 fatal_protocol_error( "open_named_obj: invalid type %d\n", req
->type
);
512 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
516 DECL_HANDLER(create_file
)
518 struct create_file_reply reply
= { -1 };
520 char *name
= (char *)data
;
521 if (!len
) name
= NULL
;
522 else CHECK_STRING( "create_file", name
, len
);
524 if ((obj
= create_file( fd
, name
, req
->access
,
525 req
->sharing
, req
->create
, req
->attrs
)) != NULL
)
527 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
528 release_object( obj
);
530 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
533 /* get a Unix fd to read from a file */
534 DECL_HANDLER(get_read_fd
)
539 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_READ
, NULL
)))
541 read_fd
= obj
->ops
->get_read_fd( obj
);
542 release_object( obj
);
545 send_reply( current
, read_fd
, 0 );
548 /* get a Unix fd to write to a file */
549 DECL_HANDLER(get_write_fd
)
554 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
556 write_fd
= obj
->ops
->get_write_fd( obj
);
557 release_object( obj
);
560 send_reply( current
, write_fd
, 0 );
563 /* set a file current position */
564 DECL_HANDLER(set_file_pointer
)
566 struct set_file_pointer_reply reply
;
567 reply
.low
= req
->low
;
568 reply
.high
= req
->high
;
569 set_file_pointer( req
->handle
, &reply
.low
, &reply
.high
, req
->whence
);
570 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
573 /* truncate (or extend) a file */
574 DECL_HANDLER(truncate_file
)
576 truncate_file( req
->handle
);
577 send_reply( current
, -1, 0 );
580 /* flush a file buffers */
581 DECL_HANDLER(flush_file
)
585 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
587 obj
->ops
->flush( obj
);
588 release_object( obj
);
590 send_reply( current
, -1, 0 );
593 /* set a file access and modification times */
594 DECL_HANDLER(set_file_time
)
596 set_file_time( req
->handle
, req
->access_time
, req
->write_time
);
597 send_reply( current
, -1, 0 );
600 /* get a file information */
601 DECL_HANDLER(get_file_info
)
604 struct get_file_info_reply reply
;
606 if ((obj
= get_handle_obj( current
->process
, req
->handle
, 0, NULL
)))
608 obj
->ops
->get_file_info( obj
, &reply
);
609 release_object( obj
);
611 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
614 /* lock a region of a file */
615 DECL_HANDLER(lock_file
)
619 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
621 file_lock( file
, req
->offset_high
, req
->offset_low
,
622 req
->count_high
, req
->count_low
);
623 release_object( file
);
625 send_reply( current
, -1, 0 );
629 /* unlock a region of a file */
630 DECL_HANDLER(unlock_file
)
634 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
636 file_unlock( file
, req
->offset_high
, req
->offset_low
,
637 req
->count_high
, req
->count_low
);
638 release_object( file
);
640 send_reply( current
, -1, 0 );
644 /* create an anonymous pipe */
645 DECL_HANDLER(create_pipe
)
647 struct create_pipe_reply reply
= { -1, -1 };
648 struct object
*obj
[2];
649 if (create_pipe( obj
))
651 reply
.handle_read
= alloc_handle( current
->process
, obj
[0],
652 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_READ
,
654 if (reply
.handle_read
!= -1)
656 reply
.handle_write
= alloc_handle( current
->process
, obj
[1],
657 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_WRITE
,
659 if (reply
.handle_write
== -1)
660 close_handle( current
->process
, reply
.handle_read
);
662 release_object( obj
[0] );
663 release_object( obj
[1] );
665 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
668 /* allocate a console for the current process */
669 DECL_HANDLER(alloc_console
)
671 alloc_console( current
->process
);
672 send_reply( current
, -1, 0 );
675 /* free the console of the current process */
676 DECL_HANDLER(free_console
)
678 free_console( current
->process
);
679 send_reply( current
, -1, 0 );
682 /* open a handle to the process console */
683 DECL_HANDLER(open_console
)
686 struct open_console_reply reply
= { -1 };
687 if ((obj
= get_console( current
->process
, req
->output
)))
689 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
690 release_object( obj
);
692 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
695 /* set info about a console (output only) */
696 DECL_HANDLER(set_console_info
)
698 char *name
= (char *)data
;
699 if (!len
) name
= NULL
;
700 else CHECK_STRING( "set_console_info", name
, len
);
701 set_console_info( req
->handle
, req
, name
);
702 send_reply( current
, -1, 0 );
705 /* get info about a console (output only) */
706 DECL_HANDLER(get_console_info
)
708 struct get_console_info_reply reply
;
710 get_console_info( req
->handle
, &reply
, &title
);
711 send_reply( current
, -1, 2, &reply
, sizeof(reply
),
712 title
, title
? strlen(title
)+1 : 0 );
715 /* set a console fd */
716 DECL_HANDLER(set_console_fd
)
718 set_console_fd( req
->handle
, fd
, req
->pid
);
719 send_reply( current
, -1, 0 );
722 /* get a console mode (input or output) */
723 DECL_HANDLER(get_console_mode
)
725 struct get_console_mode_reply reply
;
726 get_console_mode( req
->handle
, &reply
.mode
);
727 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
730 /* set a console mode (input or output) */
731 DECL_HANDLER(set_console_mode
)
733 set_console_mode( req
->handle
, req
->mode
);
734 send_reply( current
, -1, 0 );
737 /* add input records to a console input queue */
738 DECL_HANDLER(write_console_input
)
740 struct write_console_input_reply reply
;
741 INPUT_RECORD
*records
= (INPUT_RECORD
*)data
;
743 if (len
!= req
->count
* sizeof(INPUT_RECORD
))
744 fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
746 reply
.written
= write_console_input( req
->handle
, req
->count
, records
);
747 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
750 /* fetch input records from a console input queue */
751 DECL_HANDLER(read_console_input
)
753 read_console_input( req
->handle
, req
->count
, req
->flush
);
756 /* create a change notification */
757 DECL_HANDLER(create_change_notification
)
760 struct create_change_notification_reply reply
= { -1 };
762 if ((obj
= create_change_notification( req
->subtree
, req
->filter
)))
764 reply
.handle
= alloc_handle( current
->process
, obj
,
765 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
, 0 );
766 release_object( obj
);
768 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
771 /* create a file mapping */
772 DECL_HANDLER(create_mapping
)
775 struct create_mapping_reply reply
= { -1 };
776 char *name
= (char *)data
;
777 if (!len
) name
= NULL
;
778 else CHECK_STRING( "create_mapping", name
, len
);
780 if ((obj
= create_mapping( req
->size_high
, req
->size_low
,
781 req
->protect
, req
->handle
, name
)))
783 int access
= FILE_MAP_ALL_ACCESS
;
784 if (!(req
->protect
& VPROT_WRITE
)) access
&= ~FILE_MAP_WRITE
;
785 reply
.handle
= alloc_handle( current
->process
, obj
, access
, req
->inherit
);
786 release_object( obj
);
788 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
791 /* get a mapping information */
792 DECL_HANDLER(get_mapping_info
)
794 struct get_mapping_info_reply reply
;
795 int map_fd
= get_mapping_info( req
->handle
, &reply
);
796 send_reply( current
, map_fd
, 1, &reply
, sizeof(reply
) );
799 /* create a device */
800 DECL_HANDLER(create_device
)
803 struct create_device_reply reply
= { -1 };
805 if ((obj
= create_device( req
->id
)))
807 reply
.handle
= alloc_handle( current
->process
, obj
,
808 req
->access
, req
->inherit
);
809 release_object( obj
);
811 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
814 /* create a snapshot */
815 DECL_HANDLER(create_snapshot
)
818 struct create_snapshot_reply reply
= { -1 };
820 if ((obj
= create_snapshot( req
->flags
)))
822 reply
.handle
= alloc_handle( current
->process
, obj
, 0, req
->inherit
);
823 release_object( obj
);
825 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
828 /* get the next process from a snapshot */
829 DECL_HANDLER(next_process
)
831 struct next_process_reply reply
;
832 snapshot_next_process( req
->handle
, req
->reset
, &reply
);
833 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );