Changed how list of loadable MCI drivers is obtained.
[wine] / server / process.c
1 /*
2  * Server-side process management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <limits.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/time.h>
13 #include <unistd.h>
14
15 #include "winerror.h"
16 #include "winbase.h"
17 #include "winnt.h"
18
19 #include "server.h"
20 #include "server/process.h"
21 #include "server/thread.h"
22
23 /* reserved handle access rights */
24 #define RESERVED_SHIFT         25
25 #define RESERVED_INHERIT       (HANDLE_FLAG_INHERIT << RESERVED_SHIFT)
26 #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT)
27 #define RESERVED_ALL           (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT)
28
29 /* global handle macros */
30 #define HANDLE_OBFUSCATOR         0x544a4def
31 #define HANDLE_IS_GLOBAL(h)       (((h) ^ HANDLE_OBFUSCATOR) < 0x10000)
32 #define HANDLE_LOCAL_TO_GLOBAL(h) ((h) ^ HANDLE_OBFUSCATOR)
33 #define HANDLE_GLOBAL_TO_LOCAL(h) ((h) ^ HANDLE_OBFUSCATOR)
34
35 struct handle_entry
36 {
37     struct object *ptr;
38     unsigned int   access;
39 };
40
41 /* process structure; not much for now... */
42
43 struct process
44 {
45     struct object        obj;             /* object header */
46     struct process      *next;            /* system-wide process list */
47     struct process      *prev;
48     struct thread       *thread_list;     /* head of the thread list */
49     struct handle_entry *entries;         /* handle entry table */
50     int                  handle_count;    /* nb of allocated handle entries */
51     int                  handle_last;     /* last used handle entry */
52     int                  exit_code;       /* process exit code */
53     int                  running_threads; /* number of threads running in this process */
54     struct timeval       start_time;      /* absolute time at process start */
55     struct timeval       end_time;        /* absolute time at process end */
56     int                  priority;        /* priority class */
57     int                  affinity;        /* process affinity mask */
58     struct object       *console_in;      /* console input */
59     struct object       *console_out;     /* console output */
60 };
61
62 static struct process *first_process;
63 static struct process *initial_process;
64 static int running_processes;
65
66 #define MIN_HANDLE_ENTRIES  32
67
68 /* process operations */
69
70 static void process_dump( struct object *obj, int verbose );
71 static int process_signaled( struct object *obj, struct thread *thread );
72 static void process_destroy( struct object *obj );
73 static void free_handles( struct process *process );
74 static int copy_handle_table( struct process *process, struct process *parent );
75
76 static const struct object_ops process_ops =
77 {
78     process_dump,
79     add_queue,
80     remove_queue,
81     process_signaled,
82     no_satisfied,
83     no_read_fd,
84     no_write_fd,
85     no_flush,
86     no_get_file_info,
87     process_destroy
88 };
89
90 /* create a new process */
91 struct process *create_process(void)
92 {
93     struct process *process, *parent;
94
95     if (!(process = mem_alloc( sizeof(*process) ))) return NULL;
96
97     parent = current ? current->process : NULL;
98     if (!copy_handle_table( process, parent ))
99     {
100         free( process );
101         return NULL;
102     }
103     init_object( &process->obj, &process_ops, NULL );
104     process->next            = first_process;
105     process->prev            = NULL;
106     process->thread_list     = NULL;
107     process->exit_code       = 0x103;  /* STILL_ACTIVE */
108     process->running_threads = 0;
109     process->priority        = NORMAL_PRIORITY_CLASS;
110     process->affinity        = 1;
111     process->console_in      = NULL;
112     process->console_out     = NULL;
113     if (parent)
114     {
115         if (parent->console_in) process->console_in = grab_object( parent->console_in );
116         if (parent->console_out) process->console_out = grab_object( parent->console_out );
117     }
118
119     if (first_process) first_process->prev = process;
120     first_process = process;
121     if (!initial_process)
122     {
123         initial_process = process;
124         grab_object( initial_process ); /* so that we never free it */
125     }
126
127     gettimeofday( &process->start_time, NULL );
128     /* alloc a handle for the process itself */
129     alloc_handle( process, process, PROCESS_ALL_ACCESS, 0 );
130     return process;
131 }
132
133 /* destroy a process when its refcount is 0 */
134 static void process_destroy( struct object *obj )
135 {
136     struct process *process = (struct process *)obj;
137     assert( obj->ops == &process_ops );
138     assert( process != initial_process );
139
140     /* we can't have a thread remaining */
141     assert( !process->thread_list );
142     if (process->next) process->next->prev = process->prev;
143     if (process->prev) process->prev->next = process->next;
144     else first_process = process->next;
145     free_console( process );
146     free_handles( process );
147     if (debug_level) memset( process, 0xbb, sizeof(process) );  /* catch errors */
148     free( process );
149 }
150
151 /* dump a process on stdout for debugging purposes */
152 static void process_dump( struct object *obj, int verbose )
153 {
154     struct process *process = (struct process *)obj;
155     assert( obj->ops == &process_ops );
156
157     printf( "Process next=%p prev=%p\n", process->next, process->prev );
158 }
159
160 static int process_signaled( struct object *obj, struct thread *thread )
161 {
162     struct process *process = (struct process *)obj;
163     return !process->running_threads;
164 }
165
166 /* get a process from an id (and increment the refcount) */
167 struct process *get_process_from_id( void *id )
168 {
169     struct process *p = first_process;
170     while (p && (p != id)) p = p->next;
171     if (p) grab_object( p );
172     else SET_ERROR( ERROR_INVALID_PARAMETER );
173     return p;
174 }
175
176 /* get a process from a handle (and increment the refcount) */
177 struct process *get_process_from_handle( int handle, unsigned int access )
178 {
179     return (struct process *)get_handle_obj( current->process, handle,
180                                              access, &process_ops );
181 }
182
183 /* a process has been killed (i.e. its last thread died) */
184 static void process_killed( struct process *process, int exit_code )
185 {
186     assert( !process->thread_list );
187     process->exit_code = exit_code;
188     gettimeofday( &process->end_time, NULL );
189     wake_up( &process->obj, 0 );
190     free_handles( process );
191 }
192
193 /* free the process handle entries */
194 static void free_handles( struct process *process )
195 {
196     struct handle_entry *entry;
197     int handle;
198
199     if (!(entry = process->entries)) return;
200     for (handle = 0; handle <= process->handle_last; handle++, entry++)
201     {
202         struct object *obj = entry->ptr;
203         entry->ptr = NULL;
204         if (obj) release_object( obj );
205     }
206     free( process->entries );
207     process->handle_count = 0;
208     process->handle_last  = -1;
209     process->entries = NULL;
210 }
211
212 /* add a thread to a process running threads list */
213 void add_process_thread( struct process *process, struct thread *thread )
214 {
215     thread->proc_next = process->thread_list;
216     thread->proc_prev = NULL;
217     if (thread->proc_next) thread->proc_next->proc_prev = thread;
218     process->thread_list = thread;
219     if (!process->running_threads++) running_processes++;
220     grab_object( thread );
221 }
222
223 /* remove a thread from a process running threads list */
224 void remove_process_thread( struct process *process, struct thread *thread )
225 {
226     assert( process->running_threads > 0 );
227     assert( process->thread_list );
228
229     if (thread->proc_next) thread->proc_next->proc_prev = thread->proc_prev;
230     if (thread->proc_prev) thread->proc_prev->proc_next = thread->proc_next;
231     else process->thread_list = thread->proc_next;
232
233     if (!--process->running_threads)
234     {
235         /* we have removed the last running thread, exit the process */
236         running_processes--;
237         process_killed( process, thread->exit_code );
238     }
239     release_object( thread );
240 }
241
242 /* grow a handle table */
243 /* return 1 if OK, 0 on error */
244 static int grow_handle_table( struct process *process )
245 {
246     struct handle_entry *new_entries;
247     int count = process->handle_count;
248
249     if (count >= INT_MAX / 2) return 0;
250     count *= 2;
251     if (!(new_entries = realloc( process->entries, count * sizeof(struct handle_entry) )))
252     {
253         SET_ERROR( ERROR_OUTOFMEMORY );
254         return 0;
255     }
256     process->handle_count = count;
257     process->entries      = new_entries;
258     return 1;
259 }
260
261 /* allocate a handle for an object, incrementing its refcount */
262 /* return the handle, or -1 on error */
263 int alloc_handle( struct process *process, void *obj, unsigned int access,
264                   int inherit )
265 {
266     struct handle_entry *entry;
267     int handle;
268
269     assert( !(access & RESERVED_ALL) );
270     if (inherit) access |= RESERVED_INHERIT;
271
272     /* find the first free entry */
273
274     if (!(entry = process->entries)) return -1;
275     for (handle = 0; handle <= process->handle_last; handle++, entry++)
276         if (!entry->ptr) goto found;
277
278     if (handle >= process->handle_count)
279     {
280         if (!grow_handle_table( process )) return -1;
281         entry = process->entries + handle;  /* the table may have moved */
282     }
283     process->handle_last = handle;
284
285  found:
286     entry->ptr    = grab_object( obj );
287     entry->access = access;
288     return handle + 1;  /* avoid handle 0 */
289 }
290
291 /* return an handle entry, or NULL if the handle is invalid */
292 static struct handle_entry *get_handle( struct process *process, int handle )
293 {
294     struct handle_entry *entry;
295
296     if (HANDLE_IS_GLOBAL(handle))
297     {
298         handle = HANDLE_GLOBAL_TO_LOCAL(handle);
299         process = initial_process;
300     }
301     handle--;  /* handles start at 1 */
302     if ((handle < 0) || (handle > process->handle_last)) goto error;
303     entry = process->entries + handle;
304     if (!entry->ptr) goto error;
305     return entry;
306
307  error:
308     SET_ERROR( ERROR_INVALID_HANDLE );
309     return NULL;
310 }
311
312 /* attempt to shrink a table */
313 /* return 1 if OK, 0 on error */
314 static int shrink_handle_table( struct process *process )
315 {
316     struct handle_entry *new_entries;
317     struct handle_entry *entry = process->entries + process->handle_last;
318     int count = process->handle_count;
319
320     while (process->handle_last >= 0)
321     {
322         if (entry->ptr) break;
323         process->handle_last--;
324         entry--;
325     }
326     if (process->handle_last >= count / 4) return 1;  /* no need to shrink */
327     if (count < MIN_HANDLE_ENTRIES * 2) return 1;  /* too small to shrink */
328     count /= 2;
329     if (!(new_entries = realloc( process->entries,
330                                  count * sizeof(struct handle_entry) )))
331         return 0;
332     process->handle_count = count;
333     process->entries      = new_entries;
334     return 1;
335 }
336
337 /* copy the handle table of the parent process */
338 /* return 1 if OK, 0 on error */
339 static int copy_handle_table( struct process *process, struct process *parent )
340 {
341     struct handle_entry *ptr;
342     int i, count, last;
343
344     if (!parent)  /* first process */
345     {
346         count = MIN_HANDLE_ENTRIES;
347         last  = -1;
348     }
349     else
350     {
351         assert( parent->entries );
352         count = parent->handle_count;
353         last  = parent->handle_last;
354     }
355
356     if (!(ptr = mem_alloc( count * sizeof(struct handle_entry)))) return 0;
357     process->entries      = ptr;
358     process->handle_count = count;
359     process->handle_last  = last;
360
361     if (last >= 0)
362     {
363         memcpy( ptr, parent->entries, (last + 1) * sizeof(struct handle_entry) );
364         for (i = 0; i <= last; i++, ptr++)
365         {
366             if (!ptr->ptr) continue;
367             if (ptr->access & RESERVED_INHERIT) grab_object( ptr->ptr );
368             else ptr->ptr = NULL; /* don't inherit this entry */
369         }
370     }
371     /* attempt to shrink the table */
372     shrink_handle_table( process );
373     return 1;
374 }
375
376 /* close a handle and decrement the refcount of the associated object */
377 /* return 1 if OK, 0 on error */
378 int close_handle( struct process *process, int handle )
379 {
380     struct handle_entry *entry;
381     struct object *obj;
382
383     if (HANDLE_IS_GLOBAL(handle))
384     {
385         handle = HANDLE_GLOBAL_TO_LOCAL(handle);
386         process = initial_process;
387     }
388     if (!(entry = get_handle( process, handle ))) return 0;
389     if (entry->access & RESERVED_CLOSE_PROTECT) return 0;  /* FIXME: error code */
390     obj = entry->ptr;
391     entry->ptr = NULL;
392     if (handle-1 == process->handle_last) shrink_handle_table( process );
393     release_object( obj );
394     return 1;
395 }
396
397 /* retrieve the object corresponding to a handle, incrementing its refcount */
398 struct object *get_handle_obj( struct process *process, int handle,
399                                unsigned int access, const struct object_ops *ops )
400 {
401     struct handle_entry *entry;
402     struct object *obj;
403
404     switch( handle )
405     {
406     case 0xfffffffe:  /* current thread pseudo-handle */
407         obj = &current->obj;
408         break;
409     case 0x7fffffff:  /* current process pseudo-handle */
410         obj = (struct object *)current->process;
411         break;
412     default:
413         if (!(entry = get_handle( process, handle ))) return NULL;
414         if ((entry->access & access) != access)
415         {
416             SET_ERROR( ERROR_ACCESS_DENIED );
417             return NULL;
418         }
419         obj = entry->ptr;
420         break;
421     }
422     if (ops && (obj->ops != ops))
423     {
424         SET_ERROR( ERROR_INVALID_HANDLE );  /* not the right type */
425         return NULL;
426     }
427     return grab_object( obj );
428 }
429
430 /* get/set the handle reserved flags */
431 /* return the new flags (or -1 on error) */
432 int set_handle_info( struct process *process, int handle, int mask, int flags )
433 {
434     struct handle_entry *entry;
435
436     if (!(entry = get_handle( process, handle ))) return -1;
437     mask  = (mask << RESERVED_SHIFT) & RESERVED_ALL;
438     flags = (flags << RESERVED_SHIFT) & mask;
439     entry->access = (entry->access & ~mask) | flags;
440     return (entry->access & RESERVED_ALL) >> RESERVED_SHIFT;
441 }
442
443 /* duplicate a handle */
444 int duplicate_handle( struct process *src, int src_handle, struct process *dst,
445                       unsigned int access, int inherit, int options )
446 {
447     int res;
448     struct handle_entry *entry = get_handle( src, src_handle );
449     if (!entry) return -1;
450
451     if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access;
452     if (options & DUP_HANDLE_MAKE_GLOBAL) dst = initial_process;
453     access &= ~RESERVED_ALL;
454     res = alloc_handle( dst, entry->ptr, access, inherit );
455     if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res);
456     return res;
457 }
458
459 /* open a new handle to an existing object */
460 int open_object( const char *name, const struct object_ops *ops,
461                  unsigned int access, int inherit )
462 {
463     struct object *obj = find_object( name );
464     if (!obj) 
465     {
466         SET_ERROR( ERROR_FILE_NOT_FOUND );
467         return -1;
468     }
469     if (ops && obj->ops != ops)
470     {
471         release_object( obj );
472         SET_ERROR( ERROR_INVALID_HANDLE );  /* FIXME: not the right type */ 
473         return -1;
474     }
475     return alloc_handle( current->process, obj, access, inherit );
476 }
477
478 /* dump a handle table on stdout */
479 void dump_handles( struct process *process )
480 {
481     struct handle_entry *entry;
482     int i;
483
484     if (!process->entries) return;
485     entry = process->entries;
486     for (i = 0; i <= process->handle_last; i++, entry++)
487     {
488         if (!entry->ptr) continue;
489         printf( "%5d: %p %08x ", i + 1, entry->ptr, entry->access );
490         entry->ptr->ops->dump( entry->ptr, 0 );
491     }
492 }
493
494 /* kill a process on the spot */
495 void kill_process( struct process *process, int exit_code )
496 {
497     while (process->thread_list)
498         kill_thread( process->thread_list, exit_code );
499 }
500
501 /* get all information about a process */
502 void get_process_info( struct process *process,
503                        struct get_process_info_reply *reply )
504 {
505     reply->pid              = process;
506     reply->exit_code        = process->exit_code;
507     reply->priority         = process->priority;
508     reply->process_affinity = process->affinity;
509     reply->system_affinity  = 1;
510 }
511
512 /* set all information about a process */
513 void set_process_info( struct process *process,
514                        struct set_process_info_request *req )
515 {
516     if (req->mask & SET_PROCESS_INFO_PRIORITY)
517         process->priority = req->priority;
518     if (req->mask & SET_PROCESS_INFO_AFFINITY)
519     {
520         if (req->affinity != 1) SET_ERROR( ERROR_INVALID_PARAMETER );
521         else process->affinity = req->affinity;
522     }
523 }
524
525 /* allocate a console for this process */
526 int alloc_console( struct process *process )
527 {
528     struct object *obj[2];
529     if (process->console_in || process->console_out)
530     {
531         SET_ERROR( ERROR_ACCESS_DENIED );
532         return 0;
533     }
534     if (!create_console( -1, obj )) return 0;
535     process->console_in  = obj[0];
536     process->console_out = obj[1];
537     return 1;
538 }
539
540 /* free the console for this process */
541 int free_console( struct process *process )
542 {
543     if (process->console_in) release_object( process->console_in );
544     if (process->console_out) release_object( process->console_out );
545     process->console_in = process->console_out = NULL;
546     return 1;
547 }
548
549 /* get the process console */
550 struct object *get_console( struct process *process, int output )
551 {
552     struct object *obj;
553     if (!(obj = output ? process->console_out : process->console_in))
554         return NULL;
555     return grab_object( obj );
556 }
557
558 /* take a snapshot of currently running processes */
559 struct process_snapshot *process_snap( int *count )
560 {
561     struct process_snapshot *snapshot, *ptr;
562     struct process *process;
563     if (!running_processes) return NULL;
564     if (!(snapshot = mem_alloc( sizeof(*snapshot) * running_processes )))
565         return NULL;
566     ptr = snapshot;
567     for (process = first_process; process; process = process->next)
568     {
569         if (!process->running_threads) continue;
570         ptr->process  = process;
571         ptr->threads  = process->running_threads;
572         ptr->priority = process->priority;
573         grab_object( process );
574         ptr++;
575     }
576     *count = running_processes;
577     return snapshot;
578 }