Allow passing task handles to GetThreadQueue() and SetFastQueue().
[wine/wine-kai.git] / server / request.c
blobbfdcae51e493287ac61a114dd329d39572e8410d
1 /*
2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
5 */
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>
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"
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)
29 struct thread *current = NULL; /* thread handling the current request */
31 /* complain about a protocol error and terminate the client connection */
32 static void fatal_protocol_error( const char *err, ... )
34 va_list args;
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 );
43 /* call a request handler */
44 void call_req_handler( struct thread *thread, enum request req,
45 void *data, int len, int fd )
47 const struct handler *handler = &req_handlers[req];
48 char *ptr;
50 current = thread;
51 if ((req < 0) || (req >= REQ_NB_REQUESTS))
53 fatal_protocol_error( "unknown request %d\n", req );
54 return;
57 if (len < handler->min_size)
59 fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
60 return;
63 /* now call the handler */
64 if (current)
66 CLEAR_ERROR();
67 if (debug_level) trace_request( req, data, len, fd );
69 len -= handler->min_size;
70 ptr = (char *)data + handler->min_size;
71 handler->handler( data, ptr, len, fd );
72 current = NULL;
75 /* handle a client timeout (unused for now) */
76 void call_timeout_handler( struct thread *thread )
78 current = thread;
79 if (debug_level) trace_timeout();
80 CLEAR_ERROR();
81 thread_timeout();
82 current = NULL;
85 /* a thread has been killed */
86 void call_kill_handler( struct thread *thread, int exit_code )
88 /* must be reentrant WRT call_req_handler */
89 struct thread *old_current = current;
90 current = thread;
91 if (current)
93 if (debug_level) trace_kill( exit_code );
94 thread_killed( current, exit_code );
96 current = (old_current != thread) ? old_current : NULL;
100 /* create a new thread */
101 DECL_HANDLER(new_thread)
103 struct new_thread_reply reply;
104 struct thread *new_thread;
105 int new_fd, err;
107 if ((new_fd = dup(fd)) == -1)
109 new_thread = NULL;
110 err = ERROR_TOO_MANY_OPEN_FILES;
111 goto done;
113 if (!(new_thread = create_thread( new_fd, req->pid, &reply.thandle,
114 &reply.phandle )))
116 close( new_fd );
117 err = ERROR_OUTOFMEMORY;
118 goto done;
120 reply.tid = new_thread;
121 reply.pid = new_thread->process;
122 err = ERROR_SUCCESS;
124 done:
125 if (!current)
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 );
131 else
133 SET_ERROR( err );
134 send_reply( current, -1, 1, &reply, sizeof(reply) );
138 /* create a new thread */
139 DECL_HANDLER(init_thread)
141 if (current->state != STARTING)
143 fatal_protocol_error( "init_thread: already running\n" );
144 return;
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 );
156 /* set the debug level */
157 DECL_HANDLER(set_debug)
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 );
166 /* terminate a process */
167 DECL_HANDLER(terminate_process)
169 struct process *process;
171 if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
173 kill_process( process, req->exit_code );
174 release_object( process );
176 if (current) send_reply( current, -1, 0 );
179 /* terminate a thread */
180 DECL_HANDLER(terminate_thread)
182 struct thread *thread;
184 if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
186 kill_thread( thread, req->exit_code );
187 release_object( thread );
189 if (current) send_reply( current, -1, 0 );
192 /* close a handle */
193 DECL_HANDLER(close_handle)
195 close_handle( current->process, req->handle );
196 send_reply( current, -1, 0 );
199 /* duplicate a handle */
200 DECL_HANDLER(dup_handle)
202 struct dup_handle_reply reply = { -1 };
203 struct process *src, *dst;
205 if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
207 if (req->options & DUP_HANDLE_MAKE_GLOBAL)
209 reply.handle = duplicate_handle( src, req->src_handle, NULL, -1,
210 req->access, req->inherit, req->options );
212 else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
214 reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle,
215 req->access, req->inherit, req->options );
216 release_object( dst );
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 );
223 send_reply( current, -1, 1, &reply, sizeof(reply) );
226 /* fetch information about a process */
227 DECL_HANDLER(get_process_info)
229 struct process *process;
230 struct get_process_info_reply reply = { 0, 0, 0 };
232 if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
234 get_process_info( process, &reply );
235 release_object( process );
237 send_reply( current, -1, 1, &reply, sizeof(reply) );
240 /* set information about a process */
241 DECL_HANDLER(set_process_info)
243 struct process *process;
245 if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
247 set_process_info( process, req );
248 release_object( process );
250 send_reply( current, -1, 0 );
253 /* fetch information about a thread */
254 DECL_HANDLER(get_thread_info)
256 struct thread *thread;
257 struct get_thread_info_reply reply = { 0, 0 };
259 if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
261 get_thread_info( thread, &reply );
262 release_object( thread );
264 send_reply( current, -1, 1, &reply, sizeof(reply) );
267 /* set information about a thread */
268 DECL_HANDLER(set_thread_info)
270 struct thread *thread;
272 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
274 set_thread_info( thread, req );
275 release_object( thread );
277 send_reply( current, -1, 0 );
280 /* suspend a thread */
281 DECL_HANDLER(suspend_thread)
283 struct thread *thread;
284 struct suspend_thread_reply reply = { -1 };
285 if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
287 reply.count = suspend_thread( thread );
288 release_object( thread );
290 send_reply( current, -1, 1, &reply, sizeof(reply) );
294 /* resume a thread */
295 DECL_HANDLER(resume_thread)
297 struct thread *thread;
298 struct resume_thread_reply reply = { -1 };
299 if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
301 reply.count = resume_thread( thread );
302 release_object( thread );
304 send_reply( current, -1, 1, &reply, sizeof(reply) );
308 /* queue an APC for a thread */
309 DECL_HANDLER(queue_apc)
311 struct thread *thread;
312 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
314 thread_queue_apc( thread, req->func, req->param );
315 release_object( thread );
317 send_reply( current, -1, 0 );
320 /* open a handle to a process */
321 DECL_HANDLER(open_process)
323 struct open_process_reply reply = { -1 };
324 struct process *process = get_process_from_id( req->pid );
325 if (process)
327 reply.handle = alloc_handle( current->process, process,
328 req->access, req->inherit );
329 release_object( process );
331 send_reply( current, -1, 1, &reply, sizeof(reply) );
334 /* select on a handle list */
335 DECL_HANDLER(select)
337 if (len != req->count * sizeof(int))
338 fatal_protocol_error( "select: bad length %d for %d handles\n",
339 len, req->count );
340 sleep_on( current, req->count, (int *)data, req->flags, req->timeout );
343 /* create an event */
344 DECL_HANDLER(create_event)
346 struct create_event_reply reply = { -1 };
347 struct object *obj;
348 char *name = (char *)data;
349 if (!len) name = NULL;
350 else CHECK_STRING( "create_event", name, len );
352 obj = create_event( name, req->manual_reset, req->initial_state );
353 if (obj)
355 reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit );
356 release_object( obj );
358 send_reply( current, -1, 1, &reply, sizeof(reply) );
361 /* do an event operation */
362 DECL_HANDLER(event_op)
364 switch(req->op)
366 case PULSE_EVENT:
367 pulse_event( req->handle );
368 break;
369 case SET_EVENT:
370 set_event( req->handle );
371 break;
372 case RESET_EVENT:
373 reset_event( req->handle );
374 break;
375 default:
376 fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
378 send_reply( current, -1, 0 );
381 /* create a mutex */
382 DECL_HANDLER(create_mutex)
384 struct create_mutex_reply reply = { -1 };
385 struct object *obj;
386 char *name = (char *)data;
387 if (!len) name = NULL;
388 else CHECK_STRING( "create_mutex", name, len );
390 obj = create_mutex( name, req->owned );
391 if (obj)
393 reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit );
394 release_object( obj );
396 send_reply( current, -1, 1, &reply, sizeof(reply) );
399 /* release a mutex */
400 DECL_HANDLER(release_mutex)
402 if (release_mutex( req->handle )) CLEAR_ERROR();
403 send_reply( current, -1, 0 );
406 /* create a semaphore */
407 DECL_HANDLER(create_semaphore)
409 struct create_semaphore_reply reply = { -1 };
410 struct object *obj;
411 char *name = (char *)data;
412 if (!len) name = NULL;
413 else CHECK_STRING( "create_semaphore", name, len );
415 obj = create_semaphore( name, req->initial, req->max );
416 if (obj)
418 reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit );
419 release_object( obj );
421 send_reply( current, -1, 1, &reply, sizeof(reply) );
424 /* release a semaphore */
425 DECL_HANDLER(release_semaphore)
427 struct release_semaphore_reply reply;
428 if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR();
429 send_reply( current, -1, 1, &reply, sizeof(reply) );
432 /* open a handle to a named object (event, mutex, semaphore) */
433 DECL_HANDLER(open_named_obj)
435 struct open_named_obj_reply reply;
436 char *name = (char *)data;
437 if (!len) name = NULL;
438 else CHECK_STRING( "open_named_obj", name, len );
440 switch(req->type)
442 case OPEN_EVENT:
443 reply.handle = open_event( req->access, req->inherit, name );
444 break;
445 case OPEN_MUTEX:
446 reply.handle = open_mutex( req->access, req->inherit, name );
447 break;
448 case OPEN_SEMAPHORE:
449 reply.handle = open_semaphore( req->access, req->inherit, name );
450 break;
451 case OPEN_MAPPING:
452 reply.handle = open_mapping( req->access, req->inherit, name );
453 break;
454 default:
455 fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
457 send_reply( current, -1, 1, &reply, sizeof(reply) );
460 /* create a file */
461 DECL_HANDLER(create_file)
463 struct create_file_reply reply = { -1 };
464 struct object *obj;
465 char *name = (char *)data;
466 if (!len) name = NULL;
467 else CHECK_STRING( "create_file", name, len );
469 if ((obj = create_file( fd, name, req->access,
470 req->sharing, req->create, req->attrs )) != NULL)
472 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
473 release_object( obj );
475 send_reply( current, -1, 1, &reply, sizeof(reply) );
478 /* get a Unix fd to read from a file */
479 DECL_HANDLER(get_read_fd)
481 struct object *obj;
482 int read_fd;
484 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL )))
486 read_fd = obj->ops->get_read_fd( obj );
487 release_object( obj );
489 else read_fd = -1;
490 send_reply( current, read_fd, 0 );
493 /* get a Unix fd to write to a file */
494 DECL_HANDLER(get_write_fd)
496 struct object *obj;
497 int write_fd;
499 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
501 write_fd = obj->ops->get_write_fd( obj );
502 release_object( obj );
504 else write_fd = -1;
505 send_reply( current, write_fd, 0 );
508 /* set a file current position */
509 DECL_HANDLER(set_file_pointer)
511 struct set_file_pointer_reply reply = { req->low, req->high };
512 set_file_pointer( req->handle, &reply.low, &reply.high, req->whence );
513 send_reply( current, -1, 1, &reply, sizeof(reply) );
516 /* truncate (or extend) a file */
517 DECL_HANDLER(truncate_file)
519 truncate_file( req->handle );
520 send_reply( current, -1, 0 );
523 /* flush a file buffers */
524 DECL_HANDLER(flush_file)
526 struct object *obj;
528 if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL )))
530 obj->ops->flush( obj );
531 release_object( obj );
533 send_reply( current, -1, 0 );
536 /* set a file access and modification times */
537 DECL_HANDLER(set_file_time)
539 set_file_time( req->handle, req->access_time, req->write_time );
540 send_reply( current, -1, 0 );
543 /* get a file information */
544 DECL_HANDLER(get_file_info)
546 struct object *obj;
547 struct get_file_info_reply reply;
549 if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
551 obj->ops->get_file_info( obj, &reply );
552 release_object( obj );
554 send_reply( current, -1, 1, &reply, sizeof(reply) );
557 /* lock a region of a file */
558 DECL_HANDLER(lock_file)
560 struct file *file;
562 if ((file = get_file_obj( current->process, req->handle, 0 )))
564 file_lock( file, req->offset_high, req->offset_low,
565 req->count_high, req->count_low );
566 release_object( file );
568 send_reply( current, -1, 0 );
572 /* unlock a region of a file */
573 DECL_HANDLER(unlock_file)
575 struct file *file;
577 if ((file = get_file_obj( current->process, req->handle, 0 )))
579 file_unlock( file, req->offset_high, req->offset_low,
580 req->count_high, req->count_low );
581 release_object( file );
583 send_reply( current, -1, 0 );
587 /* create an anonymous pipe */
588 DECL_HANDLER(create_pipe)
590 struct create_pipe_reply reply = { -1, -1 };
591 struct object *obj[2];
592 if (create_pipe( obj ))
594 reply.handle_read = alloc_handle( current->process, obj[0],
595 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
596 req->inherit );
597 if (reply.handle_read != -1)
599 reply.handle_write = alloc_handle( current->process, obj[1],
600 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
601 req->inherit );
602 if (reply.handle_write == -1)
603 close_handle( current->process, reply.handle_read );
605 release_object( obj[0] );
606 release_object( obj[1] );
608 send_reply( current, -1, 1, &reply, sizeof(reply) );
611 /* allocate a console for the current process */
612 DECL_HANDLER(alloc_console)
614 alloc_console( current->process );
615 send_reply( current, -1, 0 );
618 /* free the console of the current process */
619 DECL_HANDLER(free_console)
621 free_console( current->process );
622 send_reply( current, -1, 0 );
625 /* open a handle to the process console */
626 DECL_HANDLER(open_console)
628 struct object *obj;
629 struct open_console_reply reply = { -1 };
630 if ((obj = get_console( current->process, req->output )))
632 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
633 release_object( obj );
635 send_reply( current, -1, 1, &reply, sizeof(reply) );
638 /* set info about a console (output only) */
639 DECL_HANDLER(set_console_info)
641 char *name = (char *)data;
642 if (!len) name = NULL;
643 else CHECK_STRING( "set_console_info", name, len );
644 set_console_info( req->handle, req, name );
645 send_reply( current, -1, 0 );
648 /* get info about a console (output only) */
649 DECL_HANDLER(get_console_info)
651 struct get_console_info_reply reply;
652 const char *title;
653 get_console_info( req->handle, &reply, &title );
654 send_reply( current, -1, 2, &reply, sizeof(reply),
655 title, title ? strlen(title)+1 : 0 );
658 /* set a console fd */
659 DECL_HANDLER(set_console_fd)
661 set_console_fd( req->handle, fd, req->pid );
662 send_reply( current, -1, 0 );
665 /* get a console mode (input or output) */
666 DECL_HANDLER(get_console_mode)
668 struct get_console_mode_reply reply;
669 get_console_mode( req->handle, &reply.mode );
670 send_reply( current, -1, 1, &reply, sizeof(reply) );
673 /* set a console mode (input or output) */
674 DECL_HANDLER(set_console_mode)
676 set_console_mode( req->handle, req->mode );
677 send_reply( current, -1, 0 );
680 /* create a change notification */
681 DECL_HANDLER(create_change_notification)
683 struct object *obj;
684 struct create_change_notification_reply reply = { -1 };
686 if ((obj = create_change_notification( req->subtree, req->filter )))
688 reply.handle = alloc_handle( current->process, obj,
689 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
690 release_object( obj );
692 send_reply( current, -1, 1, &reply, sizeof(reply) );
695 /* create a file mapping */
696 DECL_HANDLER(create_mapping)
698 struct object *obj;
699 struct create_mapping_reply reply = { -1 };
700 char *name = (char *)data;
701 if (!len) name = NULL;
702 else CHECK_STRING( "create_mapping", name, len );
704 if ((obj = create_mapping( req->size_high, req->size_low,
705 req->protect, req->handle, name )))
707 int access = FILE_MAP_ALL_ACCESS;
708 if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
709 reply.handle = alloc_handle( current->process, obj, access, 0 );
710 release_object( obj );
712 send_reply( current, -1, 1, &reply, sizeof(reply) );
715 /* get a mapping information */
716 DECL_HANDLER(get_mapping_info)
718 struct get_mapping_info_reply reply;
719 int map_fd = get_mapping_info( req->handle, &reply );
720 send_reply( current, map_fd, 1, &reply, sizeof(reply) );
723 /* create a device */
724 DECL_HANDLER(create_device)
726 struct object *obj;
727 struct create_device_reply reply = { -1 };
729 if ((obj = create_device( req->id )))
731 reply.handle = alloc_handle( current->process, obj,
732 req->access, req->inherit );
733 release_object( obj );
735 send_reply( current, -1, 1, &reply, sizeof(reply) );