Added beginnings of server-side file handling.
[wine/multimedia.git] / server / request.c
blob4c14c48c47b2bb6c0cd389a6c26c76078f743421
1 /*
2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/uio.h>
12 #include <unistd.h>
14 #include "winerror.h"
15 #include "winnt.h"
16 #include "winbase.h"
17 #define WANT_REQUEST_HANDLERS
18 #include "server.h"
19 #include "server/request.h"
20 #include "server/thread.h"
22 /* check that the string is NULL-terminated and that the len is correct */
23 #define CHECK_STRING(func,str,len) \
24 do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \
25 fatal_protocol_error( "%s: invalid string '.*s'\n", (func), (len), (str) ); \
26 } while(0)
28 struct thread *current = NULL; /* thread handling the current request */
30 /* complain about a protocol error and terminate the client connection */
31 static void fatal_protocol_error( const char *err, ... )
33 va_list args;
35 va_start( args, err );
36 fprintf( stderr, "Protocol error:%p: ", current );
37 vfprintf( stderr, err, args );
38 va_end( args );
39 remove_client( current->client_fd, -2 );
42 /* call a request handler */
43 void call_req_handler( struct thread *thread, enum request req,
44 void *data, int len, int fd )
46 const struct handler *handler = &req_handlers[req];
47 char *ptr;
49 current = thread;
50 if ((req < 0) || (req >= REQ_NB_REQUESTS))
52 fatal_protocol_error( "unknown request %d\n", req );
53 return;
56 if (len < handler->min_size)
58 fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size );
59 return;
62 /* now call the handler */
63 if (current)
65 CLEAR_ERROR();
66 if (debug_level) trace_request( req, data, len, fd );
68 len -= handler->min_size;
69 ptr = (char *)data + handler->min_size;
70 handler->handler( data, ptr, len, fd );
71 current = NULL;
74 /* handle a client timeout (unused for now) */
75 void call_timeout_handler( struct thread *thread )
77 current = thread;
78 if (debug_level) trace_timeout();
79 CLEAR_ERROR();
80 thread_timeout();
81 current = NULL;
84 /* a thread has been killed */
85 void call_kill_handler( struct thread *thread, int exit_code )
87 /* must be reentrant WRT call_req_handler */
88 struct thread *old_current = current;
89 current = thread;
90 if (current)
92 if (debug_level) trace_kill( exit_code );
93 thread_killed( current, exit_code );
95 current = (old_current != thread) ? old_current : NULL;
99 /* create a new thread */
100 DECL_HANDLER(new_thread)
102 struct new_thread_reply reply;
103 struct thread *new_thread;
104 int new_fd, err;
106 if ((new_fd = dup(fd)) == -1)
108 new_thread = NULL;
109 err = ERROR_TOO_MANY_OPEN_FILES;
110 goto done;
112 if (!(new_thread = create_thread( new_fd, req->pid, &reply.thandle,
113 &reply.phandle )))
115 close( new_fd );
116 err = ERROR_OUTOFMEMORY;
117 goto done;
119 reply.tid = new_thread;
120 reply.pid = new_thread->process;
121 err = ERROR_SUCCESS;
123 done:
124 if (!current)
126 /* first client doesn't have a current */
127 struct iovec vec = { &reply, sizeof(reply) };
128 send_reply_v( get_initial_client_fd(), err, -1, &vec, 1 );
130 else
132 SET_ERROR( err );
133 send_reply( current, -1, 1, &reply, sizeof(reply) );
137 /* create a new thread */
138 DECL_HANDLER(init_thread)
140 if (current->state != STARTING)
142 fatal_protocol_error( "init_thread: already running\n" );
143 return;
145 current->state = RUNNING;
146 current->unix_pid = req->unix_pid;
147 if (!(current->name = mem_alloc( len + 1 ))) goto done;
148 memcpy( current->name, data, len );
149 current->name[len] = '\0';
150 CLEAR_ERROR();
151 done:
152 send_reply( current, -1, 0 );
155 /* set the debug level */
156 DECL_HANDLER(set_debug)
158 debug_level = req->level;
159 CLEAR_ERROR();
160 send_reply( current, -1, 0 );
163 /* terminate a process */
164 DECL_HANDLER(terminate_process)
166 struct process *process;
168 if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
170 kill_process( process, req->exit_code );
171 release_object( process );
173 if (current) send_reply( current, -1, 0 );
176 /* terminate a thread */
177 DECL_HANDLER(terminate_thread)
179 struct thread *thread;
181 if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
183 kill_thread( thread, req->exit_code );
184 release_object( thread );
186 if (current) send_reply( current, -1, 0 );
189 /* close a handle */
190 DECL_HANDLER(close_handle)
192 close_handle( current->process, req->handle );
193 send_reply( current, -1, 0 );
196 /* duplicate a handle */
197 DECL_HANDLER(dup_handle)
199 struct dup_handle_reply reply = { -1 };
200 struct process *src, *dst;
202 if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
204 if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
206 reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle,
207 req->access, req->inherit, req->options );
208 release_object( dst );
210 /* close the handle no matter what happened */
211 if (req->options & DUPLICATE_CLOSE_SOURCE)
212 close_handle( src, req->src_handle );
213 release_object( src );
215 send_reply( current, -1, 1, &reply, sizeof(reply) );
218 /* fetch information about a process */
219 DECL_HANDLER(get_process_info)
221 struct process *process;
222 struct get_process_info_reply reply = { 0, 0 };
224 if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
226 get_process_info( process, &reply );
227 release_object( process );
229 send_reply( current, -1, 1, &reply, sizeof(reply) );
232 /* fetch information about a thread */
233 DECL_HANDLER(get_thread_info)
235 struct thread *thread;
236 struct get_thread_info_reply reply = { 0, 0 };
238 if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
240 get_thread_info( thread, &reply );
241 release_object( thread );
243 send_reply( current, -1, 1, &reply, sizeof(reply) );
246 /* open a handle to a process */
247 DECL_HANDLER(open_process)
249 struct open_process_reply reply = { -1 };
250 struct process *process = get_process_from_id( req->pid );
251 if (process)
253 reply.handle = alloc_handle( current->process, process,
254 req->access, req->inherit );
255 release_object( process );
257 send_reply( current, -1, 1, &reply, sizeof(reply) );
260 /* select on a handle list */
261 DECL_HANDLER(select)
263 if (len != req->count * sizeof(int))
264 fatal_protocol_error( "select: bad length %d for %d handles\n",
265 len, req->count );
266 sleep_on( current, req->count, (int *)data, req->flags, req->timeout );
269 /* create an event */
270 DECL_HANDLER(create_event)
272 struct create_event_reply reply = { -1 };
273 struct object *obj;
274 char *name = (char *)data;
275 if (!len) name = NULL;
276 else CHECK_STRING( "create_event", name, len );
278 obj = create_event( name, req->manual_reset, req->initial_state );
279 if (obj)
281 reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit );
282 release_object( obj );
284 send_reply( current, -1, 1, &reply, sizeof(reply) );
287 /* do an event operation */
288 DECL_HANDLER(event_op)
290 switch(req->op)
292 case PULSE_EVENT:
293 pulse_event( req->handle );
294 break;
295 case SET_EVENT:
296 set_event( req->handle );
297 break;
298 case RESET_EVENT:
299 reset_event( req->handle );
300 break;
301 default:
302 fatal_protocol_error( "event_op: invalid operation %d\n", req->op );
304 send_reply( current, -1, 0 );
307 /* create a mutex */
308 DECL_HANDLER(create_mutex)
310 struct create_mutex_reply reply = { -1 };
311 struct object *obj;
312 char *name = (char *)data;
313 if (!len) name = NULL;
314 else CHECK_STRING( "create_mutex", name, len );
316 obj = create_mutex( name, req->owned );
317 if (obj)
319 reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit );
320 release_object( obj );
322 send_reply( current, -1, 1, &reply, sizeof(reply) );
325 /* release a mutex */
326 DECL_HANDLER(release_mutex)
328 if (release_mutex( req->handle )) CLEAR_ERROR();
329 send_reply( current, -1, 0 );
332 /* create a semaphore */
333 DECL_HANDLER(create_semaphore)
335 struct create_semaphore_reply reply = { -1 };
336 struct object *obj;
337 char *name = (char *)data;
338 if (!len) name = NULL;
339 else CHECK_STRING( "create_semaphore", name, len );
341 obj = create_semaphore( name, req->initial, req->max );
342 if (obj)
344 reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit );
345 release_object( obj );
347 send_reply( current, -1, 1, &reply, sizeof(reply) );
350 /* release a semaphore */
351 DECL_HANDLER(release_semaphore)
353 struct release_semaphore_reply reply;
354 if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR();
355 send_reply( current, -1, 1, &reply, sizeof(reply) );
358 /* open a handle to a named object (event, mutex, semaphore) */
359 DECL_HANDLER(open_named_obj)
361 struct open_named_obj_reply reply;
362 char *name = (char *)data;
363 if (!len) name = NULL;
364 else CHECK_STRING( "open_named_obj", name, len );
366 switch(req->type)
368 case OPEN_EVENT:
369 reply.handle = open_event( req->access, req->inherit, name );
370 break;
371 case OPEN_MUTEX:
372 reply.handle = open_mutex( req->access, req->inherit, name );
373 break;
374 case OPEN_SEMAPHORE:
375 reply.handle = open_semaphore( req->access, req->inherit, name );
376 break;
377 default:
378 fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
380 send_reply( current, -1, 1, &reply, sizeof(reply) );
383 /* create a file */
384 DECL_HANDLER(create_file)
386 struct create_file_reply reply = { -1 };
387 struct object *obj;
388 int new_fd;
390 if ((new_fd = dup(fd)) == -1)
392 SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
393 goto done;
395 if ((obj = create_file( new_fd )) != NULL)
397 reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
398 release_object( obj );
400 done:
401 send_reply( current, -1, 1, &reply, sizeof(reply) );
404 /* get a Unix handle to a file */
405 DECL_HANDLER(get_unix_handle)
407 int handle = file_get_unix_handle( req->handle, req->access );
408 send_reply( current, handle, 0 );
411 /* get a file information */
412 DECL_HANDLER(get_file_info)
414 struct get_file_info_reply reply;
415 get_file_info( req->handle, &reply );
416 send_reply( current, -1, 1, &reply, sizeof(reply) );