Removed dst_handle in duplicate_handle request.
[wine/multimedia.git] / server / request.c
blob7e5b682e7392193f7d58f90d86857896abe3cf75
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 #include "wincon.h"
19 #define WANT_REQUEST_HANDLERS
20 #include "server.h"
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) ); \
29 } while(0)
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, ... )
36 va_list args;
38 va_start( args, err );
39 fprintf( stderr, "Protocol error:%p: ", current );
40 vfprintf( stderr, err, args );
41 va_end( 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];
50 char *ptr;
52 current = thread;
53 if ((req < 0) || (req >= REQ_NB_REQUESTS))
55 fatal_protocol_error( "unknown request %d\n", req );
56 return;
59 if (len < handler->min_size)
61 fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
62 return;
65 /* now call the handler */
66 if (current)
68 CLEAR_ERROR();
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 );
74 current = NULL;
77 /* handle a client timeout (unused for now) */
78 void call_timeout_handler( struct thread *thread )
80 current = thread;
81 if (debug_level) trace_timeout();
82 CLEAR_ERROR();
83 thread_timeout();
84 current = NULL;
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;
92 current = thread;
93 if (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;
107 int new_fd, err;
109 if ((new_fd = dup(fd)) == -1)
111 new_thread = NULL;
112 err = ERROR_TOO_MANY_OPEN_FILES;
113 goto done;
115 if (!(new_thread = create_thread( new_fd, req->pid, &reply.thandle,
116 &reply.phandle )))
118 close( new_fd );
119 err = ERROR_OUTOFMEMORY;
120 goto done;
122 reply.tid = new_thread;
123 reply.pid = new_thread->process;
124 err = ERROR_SUCCESS;
126 done:
127 if (!current)
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 );
133 else
135 SET_ERROR( err );
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" );
146 return;
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';
153 CLEAR_ERROR();
154 done:
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;
164 CLEAR_ERROR();
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 );
194 /* close a handle */
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 );
342 if (process)
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 */
352 DECL_HANDLER(select)
354 if (len != req->count * sizeof(int))
355 fatal_protocol_error( "select: bad length %d for %d handles\n",
356 len, req->count );
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 };
364 struct object *obj;
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 );
370 if (obj)
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)
381 switch(req->op)
383 case PULSE_EVENT:
384 pulse_event( req->handle );
385 break;
386 case SET_EVENT:
387 set_event( req->handle );
388 break;
389 case RESET_EVENT:
390 reset_event( req->handle );
391 break;
392 default:
393 fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
395 send_reply( current, -1, 0 );
398 /* create a mutex */
399 DECL_HANDLER(create_mutex)
401 struct create_mutex_reply reply = { -1 };
402 struct object *obj;
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 );
408 if (obj)
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 };
427 struct object *obj;
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 );
433 if (obj)
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 );
457 switch(req->type)
459 case OPEN_EVENT:
460 reply.handle = open_event( req->access, req->inherit, name );
461 break;
462 case OPEN_MUTEX:
463 reply.handle = open_mutex( req->access, req->inherit, name );
464 break;
465 case OPEN_SEMAPHORE:
466 reply.handle = open_semaphore( req->access, req->inherit, name );
467 break;
468 case OPEN_MAPPING:
469 reply.handle = open_mapping( req->access, req->inherit, name );
470 break;
471 default:
472 fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
474 send_reply( current, -1, 1, &reply, sizeof(reply) );
477 /* create a file */
478 DECL_HANDLER(create_file)
480 struct create_file_reply reply = { -1 };
481 struct object *obj;
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)
498 struct object *obj;
499 int 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 );
506 else read_fd = -1;
507 send_reply( current, read_fd, 0 );
510 /* get a Unix fd to write to a file */
511 DECL_HANDLER(get_write_fd)
513 struct object *obj;
514 int 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 );
521 else write_fd = -1;
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)
543 struct object *obj;
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)
563 struct object *obj;
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)
577 struct file *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)
592 struct file *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,
613 req->inherit );
614 if (reply.handle_read != -1)
616 reply.handle_write = alloc_handle( current->process, obj[1],
617 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
618 req->inherit );
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)
645 struct object *obj;
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;
669 const char *title;
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",
705 len, req->count );
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)
719 struct object *obj;
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)
734 struct object *obj;
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)
762 struct object *obj;
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)
777 struct object *obj;
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) );