2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
10 #include <sys/types.h>
17 #define WANT_REQUEST_HANDLERS
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) ); \
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
, ... )
35 va_start( args
, err
);
36 fprintf( stderr
, "Protocol error:%p: ", current
);
37 vfprintf( stderr
, err
, 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
];
50 if ((req
< 0) || (req
>= REQ_NB_REQUESTS
))
52 fatal_protocol_error( "unknown request %d\n", req
);
56 if (len
< handler
->min_size
)
58 fatal_protocol_error( "req %d bad length %d < %d)\n", req
, len
, handler
->min_size
);
62 /* now call the handler */
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
);
74 /* handle a client timeout (unused for now) */
75 void call_timeout_handler( struct thread
*thread
)
78 if (debug_level
) trace_timeout();
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
;
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
;
106 if ((new_fd
= dup(fd
)) == -1)
109 err
= ERROR_TOO_MANY_OPEN_FILES
;
112 if (!(new_thread
= create_thread( new_fd
, req
->pid
, &reply
.thandle
,
116 err
= ERROR_OUTOFMEMORY
;
119 reply
.tid
= new_thread
;
120 reply
.pid
= new_thread
->process
;
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 );
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" );
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';
152 send_reply( current
, -1, 0 );
155 /* set the debug level */
156 DECL_HANDLER(set_debug
)
158 debug_level
= req
->level
;
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 );
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
);
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 */
263 if (len
!= req
->count
* sizeof(int))
264 fatal_protocol_error( "select: bad length %d for %d handles\n",
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 };
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
);
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
)
293 pulse_event( req
->handle
);
296 set_event( req
->handle
);
299 reset_event( req
->handle
);
302 fatal_protocol_error( "event_op: invalid operation %d\n", req
->op
);
304 send_reply( current
, -1, 0 );
308 DECL_HANDLER(create_mutex
)
310 struct create_mutex_reply reply
= { -1 };
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
);
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 };
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
);
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
);
369 reply
.handle
= open_event( req
->access
, req
->inherit
, name
);
372 reply
.handle
= open_mutex( req
->access
, req
->inherit
, name
);
375 reply
.handle
= open_semaphore( req
->access
, req
->inherit
, name
);
378 fatal_protocol_error( "open_named_obj: invalid type %d\n", req
->type
);
380 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );
384 DECL_HANDLER(create_file
)
386 struct create_file_reply reply
= { -1 };
390 if ((new_fd
= dup(fd
)) == -1)
392 SET_ERROR( ERROR_TOO_MANY_OPEN_FILES
);
395 if ((obj
= create_file( new_fd
)) != NULL
)
397 reply
.handle
= alloc_handle( current
->process
, obj
, req
->access
, req
->inherit
);
398 release_object( obj
);
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
) );