2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
12 #include <sys/types.h>
20 #define WANT_REQUEST_HANDLERS
22 #include "server/request.h"
23 #include "server/process.h"
24 #include "server/thread.h"
26 /* check that the string is NULL-terminated and that the len is correct */
27 #define CHECK_STRING(func,str,len) \
28 do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
29 fatal_protocol_error( "%s: invalid string '%.*s'\n", (func), (len), (str) ); \
32 struct thread
*current
= NULL
; /* thread handling the current request */
34 /* complain about a protocol error and terminate the client connection */
35 static void fatal_protocol_error( const char *err
, ... )
39 va_start( args
, err
);
40 fprintf( stderr
, "Protocol error:%p: ", current
);
41 vfprintf( stderr
, err
, args
);
43 remove_client( current
->client_fd
, -2 );
46 /* call a request handler */
47 void call_req_handler( struct thread
*thread
, enum request req
,
48 void *data
, int len
, int fd
)
50 const struct handler
*handler
= &req_handlers
[req
];
54 if ((req
< 0) || (req
>= REQ_NB_REQUESTS
))
56 fatal_protocol_error( "unknown request %d\n", req
);
60 if (len
< handler
->min_size
)
62 fatal_protocol_error( "req %d bad length %d < %d)\n", req
, len
, handler
->min_size
);
66 /* now call the handler */
70 if (debug_level
) trace_request( req
, data
, len
, fd
);
72 len
-= handler
->min_size
;
73 ptr
= (char *)data
+ handler
->min_size
;
74 handler
->handler( data
, ptr
, len
, fd
);
78 /* handle a client timeout (unused for now) */
79 void call_timeout_handler( struct thread
*thread
)
82 if (debug_level
) trace_timeout();
88 /* a thread has been killed */
89 void call_kill_handler( struct thread
*thread
, int exit_code
)
91 /* must be reentrant WRT call_req_handler */
92 struct thread
*old_current
= current
;
96 if (debug_level
) trace_kill( exit_code
);
97 thread_killed( current
, exit_code
);
99 current
= (old_current
!= thread
) ? old_current
: NULL
;
103 /* create a new thread */
104 DECL_HANDLER(new_thread
)
106 struct new_thread_reply reply
;
107 struct thread
*new_thread
;
110 if ((new_fd
= dup(fd
)) == -1)
113 err
= ERROR_TOO_MANY_OPEN_FILES
;
116 if (!(new_thread
= create_thread( new_fd
, req
->pid
, &reply
.thandle
,
120 err
= ERROR_OUTOFMEMORY
;
123 reply
.tid
= new_thread
;
124 reply
.pid
= new_thread
->process
;
130 /* first client doesn't have a current */
131 struct iovec vec
= { &reply
, sizeof(reply
) };
132 send_reply_v( get_initial_client_fd(), err
, -1, &vec
, 1 );
137 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
141 /* create a new thread */
142 DECL_HANDLER(init_thread
)
144 if (current
->state
!= STARTING
)
146 fatal_protocol_error( "init_thread: already running\n" );
149 current
->state
= RUNNING
;
150 current
->unix_pid
= req
->unix_pid
;
151 if (!(current
->name
= mem_alloc( len
+ 1 ))) goto done
;
152 memcpy( current
->name
, data
, len
);
153 current
->name
[len
] = '\0';
156 send_reply( current
, -1, 0 );
159 /* set the debug level */
160 DECL_HANDLER(set_debug
)
162 debug_level
= req
->level
;
163 /* Make sure last_req is initialized */
164 current
->last_req
= REQ_SET_DEBUG
;
166 send_reply( current
, -1, 0 );
169 /* terminate a process */
170 DECL_HANDLER(terminate_process
)
172 struct process
*process
;
174 if ((process
= get_process_from_handle( req
->handle
, PROCESS_TERMINATE
)))
176 kill_process( process
, req
->exit_code
);
177 release_object( process
);
179 if (current
) send_reply( current
, -1, 0 );
182 /* terminate a thread */
183 DECL_HANDLER(terminate_thread
)
185 struct thread
*thread
;
187 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_TERMINATE
)))
189 kill_thread( thread
, req
->exit_code
);
190 release_object( thread
);
192 if (current
) send_reply( current
, -1, 0 );
196 DECL_HANDLER(close_handle
)
198 close_handle( current
->process
, req
->handle
);
199 send_reply( current
, -1, 0 );
202 /* get information about a handle */
203 DECL_HANDLER(get_handle_info
)
205 struct get_handle_info_reply reply
;
206 reply
.flags
= set_handle_info( current
->process
, req
->handle
, 0, 0 );
207 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
210 /* set a handle information */
211 DECL_HANDLER(set_handle_info
)
213 set_handle_info( current
->process
, req
->handle
, req
->mask
, req
->flags
);
214 send_reply( current
, -1, 0 );
217 /* duplicate a handle */
218 DECL_HANDLER(dup_handle
)
220 struct dup_handle_reply reply
= { -1 };
221 struct process
*src
, *dst
;
223 if ((src
= get_process_from_handle( req
->src_process
, PROCESS_DUP_HANDLE
)))
225 if (req
->options
& DUP_HANDLE_MAKE_GLOBAL
)
227 reply
.handle
= duplicate_handle( src
, req
->src_handle
, NULL
,
228 req
->access
, req
->inherit
, req
->options
);
230 else if ((dst
= get_process_from_handle( req
->dst_process
, PROCESS_DUP_HANDLE
)))
232 reply
.handle
= duplicate_handle( src
, req
->src_handle
, dst
,
233 req
->access
, req
->inherit
, req
->options
);
234 release_object( dst
);
236 /* close the handle no matter what happened */
237 if (req
->options
& DUP_HANDLE_CLOSE_SOURCE
)
238 close_handle( src
, req
->src_handle
);
239 release_object( src
);
241 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
244 /* fetch information about a process */
245 DECL_HANDLER(get_process_info
)
247 struct process
*process
;
248 struct get_process_info_reply reply
= { 0, 0, 0 };
250 if ((process
= get_process_from_handle( req
->handle
, PROCESS_QUERY_INFORMATION
)))
252 get_process_info( process
, &reply
);
253 release_object( process
);
255 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
258 /* set information about a process */
259 DECL_HANDLER(set_process_info
)
261 struct process
*process
;
263 if ((process
= get_process_from_handle( req
->handle
, PROCESS_SET_INFORMATION
)))
265 set_process_info( process
, req
);
266 release_object( process
);
268 send_reply( current
, -1, 0 );
271 /* fetch information about a thread */
272 DECL_HANDLER(get_thread_info
)
274 struct thread
*thread
;
275 struct get_thread_info_reply reply
= { 0, 0 };
277 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_QUERY_INFORMATION
)))
279 get_thread_info( thread
, &reply
);
280 release_object( thread
);
282 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
285 /* set information about a thread */
286 DECL_HANDLER(set_thread_info
)
288 struct thread
*thread
;
290 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_INFORMATION
)))
292 set_thread_info( thread
, req
);
293 release_object( thread
);
295 send_reply( current
, -1, 0 );
298 /* suspend a thread */
299 DECL_HANDLER(suspend_thread
)
301 struct thread
*thread
;
302 struct suspend_thread_reply reply
= { -1 };
303 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
305 reply
.count
= suspend_thread( thread
);
306 release_object( thread
);
308 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
312 /* resume a thread */
313 DECL_HANDLER(resume_thread
)
315 struct thread
*thread
;
316 struct resume_thread_reply reply
= { -1 };
317 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SUSPEND_RESUME
)))
319 reply
.count
= resume_thread( thread
);
320 release_object( thread
);
322 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
326 /* queue an APC for a thread */
327 DECL_HANDLER(queue_apc
)
329 struct thread
*thread
;
330 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_CONTEXT
)))
332 thread_queue_apc( thread
, req
->func
, req
->param
);
333 release_object( thread
);
335 send_reply( current
, -1, 0 );
338 /* open a handle to a process */
339 DECL_HANDLER(open_process
)
341 struct open_process_reply reply
= { -1 };
342 struct process
*process
= get_process_from_id( req
->pid
);
345 reply
.handle
= alloc_handle( current
->process
, process
,
346 req
->access
, req
->inherit
);
347 release_object( process
);
349 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
352 /* select on a handle list */
355 if (len
!= req
->count
* sizeof(int))
356 fatal_protocol_error( "select: bad length %d for %d handles\n",
358 sleep_on( current
, req
->count
, (int *)data
, req
->flags
, req
->timeout
);
361 /* create an event */
362 DECL_HANDLER(create_event
)
364 struct create_event_reply reply
= { -1 };
366 char *name
= (char *)data
;
367 if (!len
) name
= NULL
;
368 else CHECK_STRING( "create_event", name
, len
);
370 obj
= create_event( name
, req
->manual_reset
, req
->initial_state
);
373 reply
.handle
= alloc_handle( current
->process
, obj
, EVENT_ALL_ACCESS
, req
->inherit
);
374 release_object( obj
);
376 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
379 /* do an event operation */
380 DECL_HANDLER(event_op
)
385 pulse_event( req
->handle
);
388 set_event( req
->handle
);
391 reset_event( req
->handle
);
394 fatal_protocol_error( "event_op: invalid operation %d\n", req
->op
);
396 send_reply( current
, -1, 0 );
400 DECL_HANDLER(create_mutex
)
402 struct create_mutex_reply reply
= { -1 };
404 char *name
= (char *)data
;
405 if (!len
) name
= NULL
;
406 else CHECK_STRING( "create_mutex", name
, len
);
408 obj
= create_mutex( name
, req
->owned
);
411 reply
.handle
= alloc_handle( current
->process
, obj
, MUTEX_ALL_ACCESS
, req
->inherit
);
412 release_object( obj
);
414 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
417 /* release a mutex */
418 DECL_HANDLER(release_mutex
)
420 if (release_mutex( req
->handle
)) CLEAR_ERROR();
421 send_reply( current
, -1, 0 );
424 /* create a semaphore */
425 DECL_HANDLER(create_semaphore
)
427 struct create_semaphore_reply reply
= { -1 };
429 char *name
= (char *)data
;
430 if (!len
) name
= NULL
;
431 else CHECK_STRING( "create_semaphore", name
, len
);
433 obj
= create_semaphore( name
, req
->initial
, req
->max
);
436 reply
.handle
= alloc_handle( current
->process
, obj
, SEMAPHORE_ALL_ACCESS
, req
->inherit
);
437 release_object( obj
);
439 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
442 /* release a semaphore */
443 DECL_HANDLER(release_semaphore
)
445 struct release_semaphore_reply reply
;
446 if (release_semaphore( req
->handle
, req
->count
, &reply
.prev_count
)) CLEAR_ERROR();
447 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
450 /* open a handle to a named object (event, mutex, semaphore) */
451 DECL_HANDLER(open_named_obj
)
453 struct open_named_obj_reply reply
;
454 char *name
= (char *)data
;
455 if (!len
) name
= NULL
;
456 else CHECK_STRING( "open_named_obj", name
, len
);
461 reply
.handle
= open_event( req
->access
, req
->inherit
, name
);
464 reply
.handle
= open_mutex( req
->access
, req
->inherit
, name
);
467 reply
.handle
= open_semaphore( req
->access
, req
->inherit
, name
);
470 reply
.handle
= open_mapping( req
->access
, req
->inherit
, name
);
473 fatal_protocol_error( "open_named_obj: invalid type %d\n", req
->type
);
475 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
479 DECL_HANDLER(create_file
)
481 struct create_file_reply reply
= { -1 };
483 char *name
= (char *)data
;
484 if (!len
) name
= NULL
;
485 else CHECK_STRING( "create_file", name
, len
);
487 if ((obj
= create_file( fd
, name
, req
->access
,
488 req
->sharing
, req
->create
, req
->attrs
)) != NULL
)
490 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
491 release_object( obj
);
493 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
496 /* get a Unix fd to read from a file */
497 DECL_HANDLER(get_read_fd
)
502 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_READ
, NULL
)))
504 read_fd
= obj
->ops
->get_read_fd( obj
);
505 release_object( obj
);
508 send_reply( current
, read_fd
, 0 );
511 /* get a Unix fd to write to a file */
512 DECL_HANDLER(get_write_fd
)
517 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
519 write_fd
= obj
->ops
->get_write_fd( obj
);
520 release_object( obj
);
523 send_reply( current
, write_fd
, 0 );
526 /* set a file current position */
527 DECL_HANDLER(set_file_pointer
)
529 struct set_file_pointer_reply reply
= { req
->low
, req
->high
};
530 set_file_pointer( req
->handle
, &reply
.low
, &reply
.high
, req
->whence
);
531 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
534 /* truncate (or extend) a file */
535 DECL_HANDLER(truncate_file
)
537 truncate_file( req
->handle
);
538 send_reply( current
, -1, 0 );
541 /* flush a file buffers */
542 DECL_HANDLER(flush_file
)
546 if ((obj
= get_handle_obj( current
->process
, req
->handle
, GENERIC_WRITE
, NULL
)))
548 obj
->ops
->flush( obj
);
549 release_object( obj
);
551 send_reply( current
, -1, 0 );
554 /* set a file access and modification times */
555 DECL_HANDLER(set_file_time
)
557 set_file_time( req
->handle
, req
->access_time
, req
->write_time
);
558 send_reply( current
, -1, 0 );
561 /* get a file information */
562 DECL_HANDLER(get_file_info
)
565 struct get_file_info_reply reply
;
567 if ((obj
= get_handle_obj( current
->process
, req
->handle
, 0, NULL
)))
569 obj
->ops
->get_file_info( obj
, &reply
);
570 release_object( obj
);
572 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
575 /* lock a region of a file */
576 DECL_HANDLER(lock_file
)
580 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
582 file_lock( file
, req
->offset_high
, req
->offset_low
,
583 req
->count_high
, req
->count_low
);
584 release_object( file
);
586 send_reply( current
, -1, 0 );
590 /* unlock a region of a file */
591 DECL_HANDLER(unlock_file
)
595 if ((file
= get_file_obj( current
->process
, req
->handle
, 0 )))
597 file_unlock( file
, req
->offset_high
, req
->offset_low
,
598 req
->count_high
, req
->count_low
);
599 release_object( file
);
601 send_reply( current
, -1, 0 );
605 /* create an anonymous pipe */
606 DECL_HANDLER(create_pipe
)
608 struct create_pipe_reply reply
= { -1, -1 };
609 struct object
*obj
[2];
610 if (create_pipe( obj
))
612 reply
.handle_read
= alloc_handle( current
->process
, obj
[0],
613 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_READ
,
615 if (reply
.handle_read
!= -1)
617 reply
.handle_write
= alloc_handle( current
->process
, obj
[1],
618 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_WRITE
,
620 if (reply
.handle_write
== -1)
621 close_handle( current
->process
, reply
.handle_read
);
623 release_object( obj
[0] );
624 release_object( obj
[1] );
626 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
629 /* allocate a console for the current process */
630 DECL_HANDLER(alloc_console
)
632 alloc_console( current
->process
);
633 send_reply( current
, -1, 0 );
636 /* free the console of the current process */
637 DECL_HANDLER(free_console
)
639 free_console( current
->process
);
640 send_reply( current
, -1, 0 );
643 /* open a handle to the process console */
644 DECL_HANDLER(open_console
)
647 struct open_console_reply reply
= { -1 };
648 if ((obj
= get_console( current
->process
, req
->output
)))
650 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
651 release_object( obj
);
653 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
656 /* set info about a console (output only) */
657 DECL_HANDLER(set_console_info
)
659 char *name
= (char *)data
;
660 if (!len
) name
= NULL
;
661 else CHECK_STRING( "set_console_info", name
, len
);
662 set_console_info( req
->handle
, req
, name
);
663 send_reply( current
, -1, 0 );
666 /* get info about a console (output only) */
667 DECL_HANDLER(get_console_info
)
669 struct get_console_info_reply reply
;
671 get_console_info( req
->handle
, &reply
, &title
);
672 send_reply( current
, -1, 2, &reply
, sizeof(reply
),
673 title
, title
? strlen(title
)+1 : 0 );
676 /* set a console fd */
677 DECL_HANDLER(set_console_fd
)
679 set_console_fd( req
->handle
, fd
, req
->pid
);
680 send_reply( current
, -1, 0 );
683 /* get a console mode (input or output) */
684 DECL_HANDLER(get_console_mode
)
686 struct get_console_mode_reply reply
;
687 get_console_mode( req
->handle
, &reply
.mode
);
688 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
691 /* set a console mode (input or output) */
692 DECL_HANDLER(set_console_mode
)
694 set_console_mode( req
->handle
, req
->mode
);
695 send_reply( current
, -1, 0 );
698 /* add input records to a console input queue */
699 DECL_HANDLER(write_console_input
)
701 struct write_console_input_reply reply
;
702 INPUT_RECORD
*records
= (INPUT_RECORD
*)data
;
704 if (len
!= req
->count
* sizeof(INPUT_RECORD
))
705 fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
707 reply
.written
= write_console_input( req
->handle
, req
->count
, records
);
708 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
711 /* fetch input records from a console input queue */
712 DECL_HANDLER(read_console_input
)
714 read_console_input( req
->handle
, req
->count
, req
->flush
);
717 /* create a change notification */
718 DECL_HANDLER(create_change_notification
)
721 struct create_change_notification_reply reply
= { -1 };
723 if ((obj
= create_change_notification( req
->subtree
, req
->filter
)))
725 reply
.handle
= alloc_handle( current
->process
, obj
,
726 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
, 0 );
727 release_object( obj
);
729 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
732 /* create a file mapping */
733 DECL_HANDLER(create_mapping
)
736 struct create_mapping_reply reply
= { -1 };
737 char *name
= (char *)data
;
738 if (!len
) name
= NULL
;
739 else CHECK_STRING( "create_mapping", name
, len
);
741 if ((obj
= create_mapping( req
->size_high
, req
->size_low
,
742 req
->protect
, req
->handle
, name
)))
744 int access
= FILE_MAP_ALL_ACCESS
;
745 if (!(req
->protect
& VPROT_WRITE
)) access
&= ~FILE_MAP_WRITE
;
746 reply
.handle
= alloc_handle( current
->process
, obj
, access
, req
->inherit
);
747 release_object( obj
);
749 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
752 /* get a mapping information */
753 DECL_HANDLER(get_mapping_info
)
755 struct get_mapping_info_reply reply
;
756 int map_fd
= get_mapping_info( req
->handle
, &reply
);
757 send_reply( current
, map_fd
, 1, &reply
, sizeof(reply
) );
760 /* create a device */
761 DECL_HANDLER(create_device
)
764 struct create_device_reply reply
= { -1 };
766 if ((obj
= create_device( req
->id
)))
768 reply
.handle
= alloc_handle( current
->process
, obj
,
769 req
->access
, req
->inherit
);
770 release_object( obj
);
772 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
775 /* create a snapshot */
776 DECL_HANDLER(create_snapshot
)
779 struct create_snapshot_reply reply
= { -1 };
781 if ((obj
= create_snapshot( req
->flags
)))
783 reply
.handle
= alloc_handle( current
->process
, obj
, 0, req
->inherit
);
784 release_object( obj
);
786 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
789 /* get the next process from a snapshot */
790 DECL_HANDLER(next_process
)
792 struct next_process_reply reply
;
793 snapshot_next_process( req
->handle
, req
->reset
, &reply
);
794 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );