2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
11 #include <sys/types.h>
19 #define WANT_REQUEST_HANDLERS
21 #include "server/request.h"
22 #include "server/process.h"
23 #include "server/thread.h"
25 /* check that the string is NULL-terminated and that the len is correct */
26 #define CHECK_STRING(func,str,len) \
27 do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
28 fatal_protocol_error( "%s: invalid string '%.*s'\n", (func), (len), (str) ); \
31 struct thread
*current
= NULL
; /* thread handling the current request */
33 /* complain about a protocol error and terminate the client connection */
34 static void fatal_protocol_error( const char *err
, ... )
38 va_start( args
, err
);
39 fprintf( stderr
, "Protocol error:%p: ", current
);
40 vfprintf( stderr
, err
, args
);
42 remove_client( current
->client_fd
, -2 );
45 /* call a request handler */
46 void call_req_handler( struct thread
*thread
, enum request req
,
47 void *data
, int len
, int fd
)
49 const struct handler
*handler
= &req_handlers
[req
];
53 if ((req
< 0) || (req
>= REQ_NB_REQUESTS
))
55 fatal_protocol_error( "unknown request %d\n", req
);
59 if (len
< handler
->min_size
)
61 fatal_protocol_error( "req %d bad length %d < %d)\n", req
, len
, handler
->min_size
);
65 /* now call the handler */
69 if (debug_level
) trace_request( req
, data
, len
, fd
);
71 len
-= handler
->min_size
;
72 ptr
= (char *)data
+ handler
->min_size
;
73 handler
->handler( data
, ptr
, len
, fd
);
77 /* handle a client timeout (unused for now) */
78 void call_timeout_handler( struct thread
*thread
)
81 if (debug_level
) trace_timeout();
87 /* a thread has been killed */
88 void call_kill_handler( struct thread
*thread
, int exit_code
)
90 /* must be reentrant WRT call_req_handler */
91 struct thread
*old_current
= current
;
95 if (debug_level
) trace_kill( exit_code
);
96 thread_killed( current
, exit_code
);
98 current
= (old_current
!= thread
) ? old_current
: NULL
;
102 /* create a new thread */
103 DECL_HANDLER(new_thread
)
105 struct new_thread_reply reply
;
106 struct thread
*new_thread
;
109 if ((new_fd
= dup(fd
)) == -1)
112 err
= ERROR_TOO_MANY_OPEN_FILES
;
115 if (!(new_thread
= create_thread( new_fd
, req
->pid
, &reply
.thandle
,
119 err
= ERROR_OUTOFMEMORY
;
122 reply
.tid
= new_thread
;
123 reply
.pid
= new_thread
->process
;
129 /* first client doesn't have a current */
130 struct iovec vec
= { &reply
, sizeof(reply
) };
131 send_reply_v( get_initial_client_fd(), err
, -1, &vec
, 1 );
136 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
140 /* create a new thread */
141 DECL_HANDLER(init_thread
)
143 if (current
->state
!= STARTING
)
145 fatal_protocol_error( "init_thread: already running\n" );
148 current
->state
= RUNNING
;
149 current
->unix_pid
= req
->unix_pid
;
150 if (!(current
->name
= mem_alloc( len
+ 1 ))) goto done
;
151 memcpy( current
->name
, data
, len
);
152 current
->name
[len
] = '\0';
155 send_reply( current
, -1, 0 );
158 /* set the debug level */
159 DECL_HANDLER(set_debug
)
161 debug_level
= req
->level
;
162 /* Make sure last_req is initialized */
163 current
->last_req
= REQ_SET_DEBUG
;
165 send_reply( current
, -1, 0 );
168 /* terminate a process */
169 DECL_HANDLER(terminate_process
)
171 struct process
*process
;
173 if ((process
= get_process_from_handle( req
->handle
, PROCESS_TERMINATE
)))
175 kill_process( process
, req
->exit_code
);
176 release_object( process
);
178 if (current
) send_reply( current
, -1, 0 );
181 /* terminate a thread */
182 DECL_HANDLER(terminate_thread
)
184 struct thread
*thread
;
186 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_TERMINATE
)))
188 kill_thread( thread
, req
->exit_code
);
189 release_object( thread
);
191 if (current
) send_reply( current
, -1, 0 );
195 DECL_HANDLER(close_handle
)
197 close_handle( current
->process
, req
->handle
);
198 send_reply( current
, -1, 0 );
201 /* get information about a handle */
202 DECL_HANDLER(get_handle_info
)
204 struct get_handle_info_reply reply
;
205 reply
.flags
= set_handle_info( current
->process
, req
->handle
, 0, 0 );
206 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
209 /* set a handle information */
210 DECL_HANDLER(set_handle_info
)
212 set_handle_info( current
->process
, req
->handle
, req
->mask
, req
->flags
);
213 send_reply( current
, -1, 0 );
216 /* duplicate a handle */
217 DECL_HANDLER(dup_handle
)
219 struct dup_handle_reply reply
= { -1 };
220 struct process
*src
, *dst
;
222 if ((src
= get_process_from_handle( req
->src_process
, PROCESS_DUP_HANDLE
)))
224 if (req
->options
& DUP_HANDLE_MAKE_GLOBAL
)
226 reply
.handle
= duplicate_handle( src
, req
->src_handle
, NULL
,
227 req
->access
, req
->inherit
, req
->options
);
229 else if ((dst
= get_process_from_handle( req
->dst_process
, PROCESS_DUP_HANDLE
)))
231 reply
.handle
= duplicate_handle( src
, req
->src_handle
, dst
,
232 req
->access
, req
->inherit
, req
->options
);
233 release_object( dst
);
235 /* close the handle no matter what happened */
236 if (req
->options
& DUP_HANDLE_CLOSE_SOURCE
)
237 close_handle( src
, req
->src_handle
);
238 release_object( src
);
240 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
243 /* fetch information about a process */
244 DECL_HANDLER(get_process_info
)
246 struct process
*process
;
247 struct get_process_info_reply reply
= { 0, 0, 0 };
249 if ((process
= get_process_from_handle( req
->handle
, PROCESS_QUERY_INFORMATION
)))
251 get_process_info( process
, &reply
);
252 release_object( process
);
254 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
257 /* set information about a process */
258 DECL_HANDLER(set_process_info
)
260 struct process
*process
;
262 if ((process
= get_process_from_handle( req
->handle
, PROCESS_SET_INFORMATION
)))
264 set_process_info( process
, req
);
265 release_object( process
);
267 send_reply( current
, -1, 0 );
270 /* fetch information about a thread */
271 DECL_HANDLER(get_thread_info
)
273 struct thread
*thread
;
274 struct get_thread_info_reply reply
= { 0, 0 };
276 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_QUERY_INFORMATION
)))
278 get_thread_info( thread
, &reply
);
279 release_object( thread
);
281 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
284 /* set information about a thread */
285 DECL_HANDLER(set_thread_info
)
287 struct thread
*thread
;
289 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_INFORMATION
)))
291 set_thread_info( thread
, req
);
292 release_object( thread
);
294 send_reply( current
, -1, 0 );
297 /* suspend a thread */
298 DECL_HANDLER(suspend_thread
)
300 struct thread
*thread
;
301 struct suspend_thread_reply reply
= { -1 };
302 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
304 reply
.count
= suspend_thread( thread
);
305 release_object( thread
);
307 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
311 /* resume a thread */
312 DECL_HANDLER(resume_thread
)
314 struct thread
*thread
;
315 struct resume_thread_reply reply
= { -1 };
316 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
318 reply
.count
= resume_thread( thread
);
319 release_object( thread
);
321 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
325 /* queue an APC for a thread */
326 DECL_HANDLER(queue_apc
)
328 struct thread
*thread
;
329 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_CONTEXT
)))
331 thread_queue_apc( thread
, req
->func
, req
->param
);
332 release_object( thread
);
334 send_reply( current
, -1, 0 );
337 /* open a handle to a process */
338 DECL_HANDLER(open_process
)
340 struct open_process_reply reply
= { -1 };
341 struct process
*process
= get_process_from_id( req
->pid
);
344 reply
.handle
= alloc_handle( current
->process
, process
,
345 req
->access
, req
->inherit
);
346 release_object( process
);
348 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
351 /* select on a handle list */
354 if (len
!= req
->count
* sizeof(int))
355 fatal_protocol_error( "select: bad length %d for %d handles\n",
357 sleep_on( current
, req
->count
, (int *)data
, req
->flags
, req
->timeout
);
360 /* create an event */
361 DECL_HANDLER(create_event
)
363 struct create_event_reply reply
= { -1 };
365 char *name
= (char *)data
;
366 if (!len
) name
= NULL
;
367 else CHECK_STRING( "create_event", name
, len
);
369 obj
= create_event( name
, req
->manual_reset
, req
->initial_state
);
372 reply
.handle
= alloc_handle( current
->process
, obj
, EVENT_ALL_ACCESS
, req
->inherit
);
373 release_object( obj
);
375 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
378 /* do an event operation */
379 DECL_HANDLER(event_op
)
384 pulse_event( req
->handle
);
387 set_event( req
->handle
);
390 reset_event( req
->handle
);
393 fatal_protocol_error( "event_op: invalid operation %d\n", req
->op
);
395 send_reply( current
, -1, 0 );
399 DECL_HANDLER(create_mutex
)
401 struct create_mutex_reply reply
= { -1 };
403 char *name
= (char *)data
;
404 if (!len
) name
= NULL
;
405 else CHECK_STRING( "create_mutex", name
, len
);
407 obj
= create_mutex( name
, req
->owned
);
410 reply
.handle
= alloc_handle( current
->process
, obj
, MUTEX_ALL_ACCESS
, req
->inherit
);
411 release_object( obj
);
413 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
416 /* release a mutex */
417 DECL_HANDLER(release_mutex
)
419 if (release_mutex( req
->handle
)) CLEAR_ERROR();
420 send_reply( current
, -1, 0 );
423 /* create a semaphore */
424 DECL_HANDLER(create_semaphore
)
426 struct create_semaphore_reply reply
= { -1 };
428 char *name
= (char *)data
;
429 if (!len
) name
= NULL
;
430 else CHECK_STRING( "create_semaphore", name
, len
);
432 obj
= create_semaphore( name
, req
->initial
, req
->max
);
435 reply
.handle
= alloc_handle( current
->process
, obj
, SEMAPHORE_ALL_ACCESS
, req
->inherit
);
436 release_object( obj
);
438 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
441 /* release a semaphore */
442 DECL_HANDLER(release_semaphore
)
444 struct release_semaphore_reply reply
;
445 if (release_semaphore( req
->handle
, req
->count
, &reply
.prev_count
)) CLEAR_ERROR();
446 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
449 /* open a handle to a named object (event, mutex, semaphore) */
450 DECL_HANDLER(open_named_obj
)
452 struct open_named_obj_reply reply
;
453 char *name
= (char *)data
;
454 if (!len
) name
= NULL
;
455 else CHECK_STRING( "open_named_obj", name
, len
);
460 reply
.handle
= open_event( req
->access
, req
->inherit
, name
);
463 reply
.handle
= open_mutex( req
->access
, req
->inherit
, name
);
466 reply
.handle
= open_semaphore( req
->access
, req
->inherit
, name
);
469 reply
.handle
= open_mapping( req
->access
, req
->inherit
, name
);
472 fatal_protocol_error( "open_named_obj: invalid type %d\n", req
->type
);
474 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
478 DECL_HANDLER(create_file
)
480 struct create_file_reply reply
= { -1 };
482 char *name
= (char *)data
;
483 if (!len
) name
= NULL
;
484 else CHECK_STRING( "create_file", name
, len
);
486 if ((obj
= create_file( fd
, name
, req
->access
,
487 req
->sharing
, req
->create
, req
->attrs
)) != NULL
)
489 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
490 release_object( obj
);
492 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
495 /* get a Unix fd to read from a file */
496 DECL_HANDLER(get_read_fd
)
501 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_READ
, NULL
)))
503 read_fd
= obj
->ops
->get_read_fd( obj
);
504 release_object( obj
);
507 send_reply( current
, read_fd
, 0 );
510 /* get a Unix fd to write to a file */
511 DECL_HANDLER(get_write_fd
)
516 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
518 write_fd
= obj
->ops
->get_write_fd( obj
);
519 release_object( obj
);
522 send_reply( current
, write_fd
, 0 );
525 /* set a file current position */
526 DECL_HANDLER(set_file_pointer
)
528 struct set_file_pointer_reply reply
= { req
->low
, req
->high
};
529 set_file_pointer( req
->handle
, &reply
.low
, &reply
.high
, req
->whence
);
530 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
533 /* truncate (or extend) a file */
534 DECL_HANDLER(truncate_file
)
536 truncate_file( req
->handle
);
537 send_reply( current
, -1, 0 );
540 /* flush a file buffers */
541 DECL_HANDLER(flush_file
)
545 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
547 obj
->ops
->flush( obj
);
548 release_object( obj
);
550 send_reply( current
, -1, 0 );
553 /* set a file access and modification times */
554 DECL_HANDLER(set_file_time
)
556 set_file_time( req
->handle
, req
->access_time
, req
->write_time
);
557 send_reply( current
, -1, 0 );
560 /* get a file information */
561 DECL_HANDLER(get_file_info
)
564 struct get_file_info_reply reply
;
566 if ((obj
= get_handle_obj( current
->process
, req
->handle
, 0, NULL
)))
568 obj
->ops
->get_file_info( obj
, &reply
);
569 release_object( obj
);
571 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
574 /* lock a region of a file */
575 DECL_HANDLER(lock_file
)
579 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
581 file_lock( file
, req
->offset_high
, req
->offset_low
,
582 req
->count_high
, req
->count_low
);
583 release_object( file
);
585 send_reply( current
, -1, 0 );
589 /* unlock a region of a file */
590 DECL_HANDLER(unlock_file
)
594 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
596 file_unlock( file
, req
->offset_high
, req
->offset_low
,
597 req
->count_high
, req
->count_low
);
598 release_object( file
);
600 send_reply( current
, -1, 0 );
604 /* create an anonymous pipe */
605 DECL_HANDLER(create_pipe
)
607 struct create_pipe_reply reply
= { -1, -1 };
608 struct object
*obj
[2];
609 if (create_pipe( obj
))
611 reply
.handle_read
= alloc_handle( current
->process
, obj
[0],
612 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_READ
,
614 if (reply
.handle_read
!= -1)
616 reply
.handle_write
= alloc_handle( current
->process
, obj
[1],
617 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_WRITE
,
619 if (reply
.handle_write
== -1)
620 close_handle( current
->process
, reply
.handle_read
);
622 release_object( obj
[0] );
623 release_object( obj
[1] );
625 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
628 /* allocate a console for the current process */
629 DECL_HANDLER(alloc_console
)
631 alloc_console( current
->process
);
632 send_reply( current
, -1, 0 );
635 /* free the console of the current process */
636 DECL_HANDLER(free_console
)
638 free_console( current
->process
);
639 send_reply( current
, -1, 0 );
642 /* open a handle to the process console */
643 DECL_HANDLER(open_console
)
646 struct open_console_reply reply
= { -1 };
647 if ((obj
= get_console( current
->process
, req
->output
)))
649 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
650 release_object( obj
);
652 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
655 /* set info about a console (output only) */
656 DECL_HANDLER(set_console_info
)
658 char *name
= (char *)data
;
659 if (!len
) name
= NULL
;
660 else CHECK_STRING( "set_console_info", name
, len
);
661 set_console_info( req
->handle
, req
, name
);
662 send_reply( current
, -1, 0 );
665 /* get info about a console (output only) */
666 DECL_HANDLER(get_console_info
)
668 struct get_console_info_reply reply
;
670 get_console_info( req
->handle
, &reply
, &title
);
671 send_reply( current
, -1, 2, &reply
, sizeof(reply
),
672 title
, title
? strlen(title
)+1 : 0 );
675 /* set a console fd */
676 DECL_HANDLER(set_console_fd
)
678 set_console_fd( req
->handle
, fd
, req
->pid
);
679 send_reply( current
, -1, 0 );
682 /* get a console mode (input or output) */
683 DECL_HANDLER(get_console_mode
)
685 struct get_console_mode_reply reply
;
686 get_console_mode( req
->handle
, &reply
.mode
);
687 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
690 /* set a console mode (input or output) */
691 DECL_HANDLER(set_console_mode
)
693 set_console_mode( req
->handle
, req
->mode
);
694 send_reply( current
, -1, 0 );
697 /* add input records to a console input queue */
698 DECL_HANDLER(write_console_input
)
700 struct write_console_input_reply reply
;
701 INPUT_RECORD
*records
= (INPUT_RECORD
*)data
;
703 if (len
!= req
->count
* sizeof(INPUT_RECORD
))
704 fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
706 reply
.written
= write_console_input( req
->handle
, req
->count
, records
);
707 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
710 /* fetch input records from a console input queue */
711 DECL_HANDLER(read_console_input
)
713 read_console_input( req
->handle
, req
->count
, req
->flush
);
716 /* create a change notification */
717 DECL_HANDLER(create_change_notification
)
720 struct create_change_notification_reply reply
= { -1 };
722 if ((obj
= create_change_notification( req
->subtree
, req
->filter
)))
724 reply
.handle
= alloc_handle( current
->process
, obj
,
725 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
, 0 );
726 release_object( obj
);
728 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
731 /* create a file mapping */
732 DECL_HANDLER(create_mapping
)
735 struct create_mapping_reply reply
= { -1 };
736 char *name
= (char *)data
;
737 if (!len
) name
= NULL
;
738 else CHECK_STRING( "create_mapping", name
, len
);
740 if ((obj
= create_mapping( req
->size_high
, req
->size_low
,
741 req
->protect
, req
->handle
, name
)))
743 int access
= FILE_MAP_ALL_ACCESS
;
744 if (!(req
->protect
& VPROT_WRITE
)) access
&= ~FILE_MAP_WRITE
;
745 reply
.handle
= alloc_handle( current
->process
, obj
, access
, req
->inherit
);
746 release_object( obj
);
748 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
751 /* get a mapping information */
752 DECL_HANDLER(get_mapping_info
)
754 struct get_mapping_info_reply reply
;
755 int map_fd
= get_mapping_info( req
->handle
, &reply
);
756 send_reply( current
, map_fd
, 1, &reply
, sizeof(reply
) );
759 /* create a device */
760 DECL_HANDLER(create_device
)
763 struct create_device_reply reply
= { -1 };
765 if ((obj
= create_device( req
->id
)))
767 reply
.handle
= alloc_handle( current
->process
, obj
,
768 req
->access
, req
->inherit
);
769 release_object( obj
);
771 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
774 /* create a snapshot */
775 DECL_HANDLER(create_snapshot
)
778 struct create_snapshot_reply reply
= { -1 };
780 if ((obj
= create_snapshot( req
->flags
)))
782 reply
.handle
= alloc_handle( current
->process
, obj
, 0, req
->inherit
);
783 release_object( obj
);
785 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
788 /* get the next process from a snapshot */
789 DECL_HANDLER(next_process
)
791 struct next_process_reply reply
;
792 snapshot_next_process( req
->handle
, req
->reset
, &reply
);
793 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );