Allow user APCs with NULL 'func' (just wake up the thread).
[wine] / scheduler / process.c
1 /*
2  * Win32 processes
3  *
4  * Copyright 1996, 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include "process.h"
12 #include "module.h"
13 #include "neexe.h"
14 #include "file.h"
15 #include "global.h"
16 #include "heap.h"
17 #include "task.h"
18 #include "ldt.h"
19 #include "syslevel.h"
20 #include "thread.h"
21 #include "winerror.h"
22 #include "pe_image.h"
23 #include "task.h"
24 #include "server.h"
25 #include "callback.h"
26 #include "debug.h"
27
28
29 /* The initial process PDB */
30 static PDB initial_pdb;
31
32 static PDB *PROCESS_First = &initial_pdb;
33
34 /***********************************************************************
35  *           PROCESS_Current
36  */
37 PDB *PROCESS_Current(void)
38 {
39     return THREAD_Current()->process;
40 }
41
42 /***********************************************************************
43  *           PROCESS_Initial
44  *
45  * FIXME: This works only while running all processes in the same
46  *        address space (or, at least, the initial process is mapped
47  *        into all address spaces as is KERNEL32 in Windows 95)
48  *
49  */
50 PDB *PROCESS_Initial(void)
51 {
52     return &initial_pdb;
53 }
54
55 /***********************************************************************
56  *           PROCESS_QueryInfo
57  *
58  * Retrieve information about a process
59  */
60 static BOOL PROCESS_QueryInfo( HANDLE handle,
61                                  struct get_process_info_reply *reply )
62 {
63     struct get_process_info_request req;
64     req.handle = handle;
65     CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
66     return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
67 }
68
69 /***********************************************************************
70  *           PROCESS_IsCurrent
71  *
72  * Check if a handle is to the current process
73  */
74 BOOL PROCESS_IsCurrent( HANDLE handle )
75 {
76     struct get_process_info_reply reply;
77     return (PROCESS_QueryInfo( handle, &reply ) &&
78             (reply.pid == PROCESS_Current()->server_pid));
79 }
80
81
82 /***********************************************************************
83  *           PROCESS_IdToPDB
84  *
85  * Convert a process id to a PDB, making sure it is valid.
86  */
87 PDB *PROCESS_IdToPDB( DWORD id )
88 {
89     PDB *pdb;
90
91     if (!id) return PROCESS_Current();
92     pdb = PROCESS_First;
93     while (pdb)
94     {
95         if ((DWORD)pdb->server_pid == id) return pdb;
96         pdb = pdb->next;
97     }
98     SetLastError( ERROR_INVALID_PARAMETER );
99     return NULL;
100 }
101
102
103 /***********************************************************************
104  *           PROCESS_CallUserSignalProc
105  *
106  * FIXME:  Some of the signals aren't sent correctly!
107  *
108  * The exact meaning of the USER signals is undocumented, but this 
109  * should cover the basic idea:
110  *
111  * USIG_DLL_UNLOAD_WIN16
112  *     This is sent when a 16-bit module is unloaded.
113  *
114  * USIG_DLL_UNLOAD_WIN32
115  *     This is sent when a 32-bit module is unloaded.
116  *
117  * USIG_DLL_UNLOAD_ORPHANS
118  *     This is sent after the last Win3.1 module is unloaded,
119  *     to allow removal of orphaned menus.
120  *
121  * USIG_FAULT_DIALOG_PUSH
122  * USIG_FAULT_DIALOG_POP
123  *     These are called to allow USER to prepare for displaying a
124  *     fault dialog, even though the fault might have happened while
125  *     inside a USER critical section.
126  *
127  * USIG_THREAD_INIT
128  *     This is called from the context of a new thread, as soon as it
129  *     has started to run.
130  *
131  * USIG_THREAD_EXIT
132  *     This is called, still in its context, just before a thread is
133  *     about to terminate.
134  *
135  * USIG_PROCESS_CREATE
136  *     This is called, in the parent process context, after a new process
137  *     has been created.
138  *
139  * USIG_PROCESS_INIT
140  *     This is called in the new process context, just after the main thread
141  *     has started execution (after the main thread's USIG_THREAD_INIT has
142  *     been sent).
143  *
144  * USIG_PROCESS_LOADED
145  *     This is called after the executable file has been loaded into the
146  *     new process context.
147  *
148  * USIG_PROCESS_RUNNING
149  *     This is called immediately before the main entry point is called.
150  *
151  * USIG_PROCESS_EXIT
152  *     This is called in the context of a process that is about to
153  *     terminate (but before the last thread's USIG_THREAD_EXIT has
154  *     been sent).
155  *
156  * USIG_PROCESS_DESTROY
157  *     This is called after a process has terminated.
158  *
159  *
160  * The meaning of the dwFlags bits is as follows:
161  *
162  * USIG_FLAGS_WIN32
163  *     Current process is 32-bit.
164  *
165  * USIG_FLAGS_GUI
166  *     Current process is a (Win32) GUI process.
167  *
168  * USIG_FLAGS_FEEDBACK 
169  *     Current process needs 'feedback' (determined from the STARTUPINFO
170  *     flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
171  *
172  * USIG_FLAGS_FAULT
173  *     The signal is being sent due to a fault.
174  */
175 void PROCESS_CallUserSignalProc( UINT uCode, DWORD dwThreadOrProcessId, HMODULE hModule )
176 {
177     PDB *pdb = PROCESS_Current();
178     STARTUPINFOA *startup = pdb->env_db? pdb->env_db->startup_info : NULL;
179     DWORD dwFlags = 0;
180
181     /* Determine dwFlags */
182
183     if ( !(pdb->flags & PDB32_WIN16_PROC) )
184         dwFlags |= USIG_FLAGS_WIN32;
185
186     if ( !(pdb->flags & PDB32_CONSOLE_PROC) )
187         dwFlags |= USIG_FLAGS_GUI;
188
189     if ( dwFlags & USIG_FLAGS_GUI )
190     {
191         /* Feedback defaults to ON */
192         if ( !(startup && (startup->dwFlags & STARTF_FORCEOFFFEEDBACK)) )
193             dwFlags |= USIG_FLAGS_FEEDBACK;
194     }
195     else
196     {
197         /* Feedback defaults to OFF */
198         if ( startup && (startup->dwFlags & STARTF_FORCEONFEEDBACK) )
199             dwFlags |= USIG_FLAGS_FEEDBACK;
200     }
201
202     /* Get thread or process ID */
203
204     if ( dwThreadOrProcessId == 0 )
205         if ( uCode == USIG_THREAD_INIT || uCode == USIG_THREAD_EXIT )
206             dwThreadOrProcessId = GetCurrentThreadId();
207         else
208             dwThreadOrProcessId = GetCurrentProcessId();
209
210     /* Convert module handle to 16-bit */
211
212     if ( HIWORD( hModule ) )
213         hModule = MapHModuleLS( hModule );
214
215     /* Call USER signal proc */
216
217     if ( Callout.UserSignalProc )
218         Callout.UserSignalProc( uCode, dwThreadOrProcessId, dwFlags, hModule );
219 }
220
221
222 /***********************************************************************
223  *           PROCESS_BuildEnvDB
224  *
225  * Build the env DB for the initial process
226  */
227 static BOOL PROCESS_BuildEnvDB( PDB *pdb )
228 {
229     /* Allocate the env DB (FIXME: should not be on the system heap) */
230
231     if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
232         return FALSE;
233     InitializeCriticalSection( &pdb->env_db->section );
234
235     /* Allocate startup info */
236     if (!(pdb->env_db->startup_info = 
237           HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
238         return FALSE;
239
240     /* Allocate the standard handles */
241
242     pdb->env_db->hStdin  = FILE_DupUnixHandle( 0, GENERIC_READ );
243     pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
244     pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
245
246     /* Build the command-line */
247
248     pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
249
250     /* Build the environment strings */
251
252     return ENV_BuildEnvironment( pdb );
253 }
254
255
256 /***********************************************************************
257  *           PROCESS_InheritEnvDB
258  */
259 static BOOL PROCESS_InheritEnvDB( PDB *pdb, LPCSTR cmd_line, LPCSTR env,
260                                     BOOL inherit_handles, STARTUPINFOA *startup )
261 {
262     if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
263         return FALSE;
264     InitializeCriticalSection( &pdb->env_db->section );
265
266     /* Copy the parent environment */
267
268     if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
269
270     /* Copy the command line */
271
272     if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
273         return FALSE;
274
275     /* Remember startup info */
276     if (!(pdb->env_db->startup_info = 
277           HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
278         return FALSE;
279     *pdb->env_db->startup_info = *startup;
280
281     /* Inherit the standard handles */
282     if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
283     {
284         pdb->env_db->hStdin  = pdb->env_db->startup_info->hStdInput;
285         pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
286         pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
287     }
288     else if (inherit_handles)
289     {
290         pdb->env_db->hStdin  = pdb->parent->env_db->hStdin;
291         pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
292         pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
293     }
294     /* else will be done later on in PROCESS_Create */
295
296     return TRUE;
297 }
298
299
300 /***********************************************************************
301  *           PROCESS_CreateEnvDB
302  *
303  * Create the env DB for a newly started process.
304  */
305 static BOOL PROCESS_CreateEnvDB(void)
306 {
307     struct init_process_request req;
308     struct init_process_reply reply;
309     STARTUPINFOA *startup;
310     ENVDB *env_db;
311     PDB *pdb = PROCESS_Current();
312
313     /* Retrieve startup info from the server */
314
315     req.dummy = 0;
316     CLIENT_SendRequest( REQ_INIT_PROCESS, -1, 1, &req, sizeof(req) );
317     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
318
319     /* Allocate the env DB */
320
321     if (!(env_db = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB) )))
322         return FALSE;
323     pdb->env_db = env_db;
324     InitializeCriticalSection( &env_db->section );
325
326     /* Allocate and fill the startup info */
327     if (!(startup = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
328         return FALSE;
329     pdb->env_db->startup_info = startup;
330     startup->dwFlags = reply.start_flags;
331     pdb->env_db->hStdin  = startup->hStdInput  = reply.hstdin;
332     pdb->env_db->hStdout = startup->hStdOutput = reply.hstdout;
333     pdb->env_db->hStderr = startup->hStdError  = reply.hstderr;
334
335 #if 0  /* FIXME */
336     /* Copy the parent environment */
337
338     if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
339
340     /* Copy the command line */
341
342     if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
343         return FALSE;
344 #endif
345     return TRUE;
346 }
347
348
349 /***********************************************************************
350  *           PROCESS_FreePDB
351  *
352  * Free a PDB and all associated storage.
353  */
354 void PROCESS_FreePDB( PDB *pdb )
355 {
356     PDB **pptr = &PROCESS_First;
357
358     ENV_FreeEnvironment( pdb );
359     while (*pptr && (*pptr != pdb)) pptr = &(*pptr)->next;
360     if (*pptr) *pptr = pdb->next;
361     if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
362     HeapFree( SystemHeap, 0, pdb );
363 }
364
365
366 /***********************************************************************
367  *           PROCESS_CreatePDB
368  *
369  * Allocate and fill a PDB structure.
370  * Runs in the context of the parent process.
371  */
372 static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
373 {
374     PDB *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB) );
375
376     if (!pdb) return NULL;
377     pdb->exit_code       = 0x103; /* STILL_ACTIVE */
378     pdb->threads         = 1;
379     pdb->running_threads = 1;
380     pdb->ring0_threads   = 1;
381     pdb->system_heap     = SystemHeap;
382     pdb->parent          = parent;
383     pdb->group           = pdb;
384     pdb->priority        = 8;  /* Normal */
385     pdb->heap            = pdb->system_heap;  /* will be changed later on */
386     pdb->next            = PROCESS_First;
387     PROCESS_First = pdb;
388     return pdb;
389 }
390
391
392 /***********************************************************************
393  *           PROCESS_Init
394  */
395 BOOL PROCESS_Init(void)
396 {
397     THDB *thdb;
398     int server_fd;
399
400     /* Start the server */
401     server_fd = CLIENT_InitServer();
402
403     /* Fill the initial process structure */
404     initial_pdb.exit_code       = 0x103; /* STILL_ACTIVE */
405     initial_pdb.threads         = 1;
406     initial_pdb.running_threads = 1;
407     initial_pdb.ring0_threads   = 1;
408     initial_pdb.group           = &initial_pdb;
409     initial_pdb.priority        = 8;  /* Normal */
410     initial_pdb.flags           = PDB32_WIN16_PROC;
411
412     /* Initialize virtual memory management */
413     if (!VIRTUAL_Init()) return FALSE;
414
415     /* Create the initial thread structure and socket pair */
416     if (!(thdb = THREAD_CreateInitialThread( &initial_pdb, server_fd ))) return FALSE;
417
418     /* Remember TEB selector of initial process for emergency use */
419     SYSLEVEL_EmergencyTeb = thdb->teb_sel;
420
421     /* Create the system heap */
422     if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
423     initial_pdb.system_heap = initial_pdb.heap = SystemHeap;
424
425     /* Create the environment DB of the first process */
426     if (!PROCESS_BuildEnvDB( &initial_pdb )) return FALSE;
427
428     /* Create the SEGPTR heap */
429     if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
430
431     /* Initialize the first process critical section */
432     InitializeCriticalSection( &initial_pdb.crit_section );
433
434     return TRUE;
435 }
436
437
438 /***********************************************************************
439  *           PROCESS_Start
440  *
441  * Startup routine of a new process. Called in the context of the new process.
442  */
443 void PROCESS_Start(void)
444 {
445     DWORD size, commit;
446     UINT cmdShow = 0;
447     LPTHREAD_START_ROUTINE entry;
448     THDB *thdb = THREAD_Current();
449     PDB *pdb = thdb->process;
450     TDB *pTask = (TDB *)GlobalLock16( pdb->task );
451     NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
452     OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
453
454     PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0, 0 );  /* for initial thread */
455
456 #if 0
457     /* Initialize the critical section */
458
459     InitializeCriticalSection( &pdb->crit_section );
460
461     /* Create the heap */
462
463     size  = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
464     commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
465     if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
466     pdb->heap_list = pdb->heap;
467
468     /* Create the environment db */
469
470     if (!PROCESS_CreateEnvDB()) goto error;
471
472     if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
473         cmdShow = pdb->env_db->startup_info->wShowWindow;
474     if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
475
476 #endif
477
478     PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0, 0 );
479
480     /* Map system DLLs into this process (from initial process) */
481     /* FIXME: this is a hack */
482     pdb->modref_list = PROCESS_Initial()->modref_list;
483
484     /* Create 32-bit MODREF */
485     if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
486
487     PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 );   /* FIXME: correct location? */
488
489     /* Initialize thread-local storage */
490
491     PE_InitTls();
492
493     if ( pdb->flags & PDB32_CONSOLE_PROC )
494         AllocConsole();
495
496     /* Now call the entry point */
497
498     MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)1 );
499
500     PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
501
502     entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
503                                             OptionalHeader.AddressOfEntryPoint);
504     TRACE(relay, "(entryproc=%p)\n", entry );
505     ExitProcess( entry(NULL) );
506
507  error:
508     ExitProcess(1);
509 }
510
511
512 /***********************************************************************
513  *           PROCESS_Create
514  *
515  * Create a new process database and associated info.
516  */
517 PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
518                      HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
519                      LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
520                      BOOL inherit, STARTUPINFOA *startup,
521                      PROCESS_INFORMATION *info )
522 {
523     DWORD size, commit;
524     int server_thandle;
525     struct new_process_request req;
526     struct new_process_reply reply;
527     UINT cmdShow = 0;
528     THDB *thdb = NULL;
529     PDB *parent = PROCESS_Current();
530     PDB *pdb = PROCESS_CreatePDB( parent, inherit );
531
532     if (!pdb) return NULL;
533     info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
534
535     /* Create the process on the server side */
536
537     req.inherit     = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
538     req.inherit_all = inherit;
539     req.start_flags = startup->dwFlags;
540     if (startup->dwFlags & STARTF_USESTDHANDLES)
541     {
542         req.hstdin  = startup->hStdInput;
543         req.hstdout = startup->hStdOutput;
544         req.hstderr = startup->hStdError;
545     }
546     else
547     {
548         req.hstdin  = GetStdHandle( STD_INPUT_HANDLE );
549         req.hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
550         req.hstderr = GetStdHandle( STD_ERROR_HANDLE );
551     }
552     CLIENT_SendRequest( REQ_NEW_PROCESS, -1, 2,
553                         &req, sizeof(req), cmd_line, strlen(cmd_line) + 1 );
554     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
555     pdb->server_pid   = reply.pid;
556     info->hProcess    = reply.handle;
557     info->dwProcessId = (DWORD)pdb->server_pid;
558
559     /* Initialize the critical section */
560
561     InitializeCriticalSection( &pdb->crit_section );
562
563     /* Setup process flags */
564
565     if ( !pModule->module32 )
566         pdb->flags |= PDB32_WIN16_PROC;
567
568     else if ( PE_HEADER(pModule->module32)->OptionalHeader.Subsystem
569               == IMAGE_SUBSYSTEM_WINDOWS_CUI )
570         pdb->flags |= PDB32_CONSOLE_PROC;
571
572     /* Create the heap */
573
574     if (pModule->module32)
575     {
576         size  = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
577         commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
578     }
579     else
580     {
581         size = 0x10000;
582         commit = 0;
583     }
584     if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
585     pdb->heap_list = pdb->heap;
586
587     /* Inherit the env DB from the parent */
588
589     if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
590
591     /* Call USER signal proc */
592
593     PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, info->dwProcessId, 0 );
594
595     /* Create the main thread */
596
597     if (pModule->module32)
598         size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
599     else
600         size = 0;
601     if (!(thdb = THREAD_Create( pdb, 0L, size, hInstance == 0, tsa, &server_thandle ))) 
602         goto error;
603     info->hThread     = server_thandle;
604     info->dwThreadId  = (DWORD)thdb->server_tid;
605     thdb->startup     = PROCESS_Start;
606
607     /* Duplicate the standard handles */
608
609     if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
610     {
611         DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
612                          info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
613         DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
614                          info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
615         DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
616                          info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
617     }
618
619     /* Create a Win16 task for this process */
620
621     if (startup->dwFlags & STARTF_USESHOWWINDOW)
622         cmdShow = startup->wShowWindow;
623
624     if ( !TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow) )
625         goto error;
626
627
628     /* Map system DLLs into this process (from initial process) */
629     /* FIXME: this is a hack */
630     pdb->modref_list = PROCESS_Initial()->modref_list;
631     
632
633     /* Start the task */
634
635     TASK_StartTask( pdb->task );
636
637     return pdb;
638
639 error:
640     if (info->hThread != INVALID_HANDLE_VALUE) CloseHandle( info->hThread );
641     if (info->hProcess != INVALID_HANDLE_VALUE) CloseHandle( info->hProcess );
642     PROCESS_FreePDB( pdb );
643     return NULL;
644 }
645
646
647 /***********************************************************************
648  *           ExitProcess   (KERNEL32.100)
649  */
650 void WINAPI ExitProcess( DWORD status )
651 {
652     MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, (LPVOID)1 );
653
654     if ( THREAD_IsWin16( THREAD_Current() ) )
655         TASK_KillCurrentTask( status );
656
657     TASK_KillTask( 0 );
658     TerminateProcess( GetCurrentProcess(), status );
659 }
660
661
662 /******************************************************************************
663  *           TerminateProcess   (KERNEL32.684)
664  */
665 BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
666 {
667     struct terminate_process_request req;
668     req.handle    = handle;
669     req.exit_code = exit_code;
670     CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
671     return !CLIENT_WaitReply( NULL, NULL, 0 );
672 }
673
674
675 /***********************************************************************
676  *           GetProcessDword    (KERNEL32.18) (KERNEL.485)
677  * 'Of course you cannot directly access Windows internal structures'
678  */
679 DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
680 {
681     PDB *process = PROCESS_IdToPDB( dwProcessID );
682     TDB *pTask;
683     DWORD x, y;
684
685     TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
686     if ( !process ) return 0;
687
688     switch ( offset ) 
689     {
690     case GPD_APP_COMPAT_FLAGS:
691         pTask = (TDB *)GlobalLock16( process->task );
692         return pTask? pTask->compat_flags : 0;
693
694     case GPD_LOAD_DONE_EVENT:
695         return process->load_done_evt;
696
697     case GPD_HINSTANCE16:
698         pTask = (TDB *)GlobalLock16( process->task );
699         return pTask? pTask->hInstance : 0;
700
701     case GPD_WINDOWS_VERSION:
702         pTask = (TDB *)GlobalLock16( process->task );
703         return pTask? pTask->version : 0;
704
705     case GPD_THDB:
706         if ( process != PROCESS_Current() ) return 0;
707         return (DWORD)THREAD_Current();
708
709     case GPD_PDB:
710         return (DWORD)process;
711
712     case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
713         return process->env_db->startup_info->hStdOutput;
714
715     case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
716         return process->env_db->startup_info->hStdInput;
717
718     case GPD_STARTF_SHOWWINDOW:
719         return process->env_db->startup_info->wShowWindow;
720
721     case GPD_STARTF_SIZE:
722         x = process->env_db->startup_info->dwXSize;
723         if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
724         y = process->env_db->startup_info->dwYSize;
725         if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
726         return MAKELONG( x, y );
727
728     case GPD_STARTF_POSITION:
729         x = process->env_db->startup_info->dwX;
730         if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
731         y = process->env_db->startup_info->dwY;
732         if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
733         return MAKELONG( x, y );
734
735     case GPD_STARTF_FLAGS:
736         return process->env_db->startup_info->dwFlags;
737
738     case GPD_PARENT:
739         return (DWORD)process->parent->server_pid;
740
741     case GPD_FLAGS:
742         return process->flags;
743
744     case GPD_USERDATA:
745         return process->process_dword;
746
747     default:
748         ERR( win32, "Unknown offset %d\n", offset );
749         return 0;
750     }
751 }
752
753 /***********************************************************************
754  *           SetProcessDword    (KERNEL.484)
755  * 'Of course you cannot directly access Windows internal structures'
756  */
757 void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
758 {
759     PDB *process = PROCESS_IdToPDB( dwProcessID );
760
761     TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
762     if ( !process ) return;
763
764     switch ( offset ) 
765     {
766     case GPD_APP_COMPAT_FLAGS:
767     case GPD_LOAD_DONE_EVENT:
768     case GPD_HINSTANCE16:
769     case GPD_WINDOWS_VERSION:
770     case GPD_THDB:
771     case GPD_PDB:
772     case GPD_STARTF_SHELLDATA:
773     case GPD_STARTF_HOTKEY:
774     case GPD_STARTF_SHOWWINDOW:
775     case GPD_STARTF_SIZE:
776     case GPD_STARTF_POSITION:
777     case GPD_STARTF_FLAGS:
778     case GPD_PARENT:
779     case GPD_FLAGS:
780         ERR( win32, "Not allowed to modify offset %d\n", offset );
781         break;
782
783     case GPD_USERDATA:
784         process->process_dword = value; 
785         break;
786
787     default:
788         ERR( win32, "Unknown offset %d\n", offset );
789         break;
790     }
791 }
792
793
794 /***********************************************************************
795  *           GetCurrentProcess   (KERNEL32.198)
796  */
797 HANDLE WINAPI GetCurrentProcess(void)
798 {
799     return CURRENT_PROCESS_PSEUDOHANDLE;
800 }
801
802
803 /*********************************************************************
804  *           OpenProcess   (KERNEL32.543)
805  */
806 HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
807 {
808     struct open_process_request req;
809     struct open_process_reply reply;
810
811     req.pid     = (void *)id;
812     req.access  = access;
813     req.inherit = inherit;
814     CLIENT_SendRequest( REQ_OPEN_PROCESS, -1, 1, &req, sizeof(req) );
815     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0;
816     return reply.handle;
817 }                             
818
819
820 /***********************************************************************
821  *           GetCurrentProcessId   (KERNEL32.199)
822  */
823 DWORD WINAPI GetCurrentProcessId(void)
824 {
825     return (DWORD)PROCESS_Current()->server_pid;
826 }
827
828
829 /***********************************************************************
830  *           GetProcessHeap    (KERNEL32.259)
831  */
832 HANDLE WINAPI GetProcessHeap(void)
833 {
834     PDB *pdb = PROCESS_Current();
835     return pdb->heap ? pdb->heap : SystemHeap;
836 }
837
838
839 /***********************************************************************
840  *           GetThreadLocale    (KERNEL32.295)
841  */
842 LCID WINAPI GetThreadLocale(void)
843 {
844     return PROCESS_Current()->locale;
845 }
846
847
848 /***********************************************************************
849  *           SetPriorityClass   (KERNEL32.503)
850  */
851 BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
852 {
853     struct set_process_info_request req;
854     req.handle   = hprocess;
855     req.priority = priorityclass;
856     req.mask     = SET_PROCESS_INFO_PRIORITY;
857     CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
858     return !CLIENT_WaitReply( NULL, NULL, 0 );
859 }
860
861
862 /***********************************************************************
863  *           GetPriorityClass   (KERNEL32.250)
864  */
865 DWORD WINAPI GetPriorityClass(HANDLE hprocess)
866 {
867     struct get_process_info_reply reply;
868     if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
869     return reply.priority;
870 }
871
872
873 /***********************************************************************
874  *          SetProcessAffinityMask   (KERNEL32.662)
875  */
876 BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
877 {
878     struct set_process_info_request req;
879     req.handle   = hProcess;
880     req.affinity = affmask;
881     req.mask     = SET_PROCESS_INFO_AFFINITY;
882     CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
883     return !CLIENT_WaitReply( NULL, NULL, 0 );
884 }
885
886 /**********************************************************************
887  *          GetProcessAffinityMask    (KERNEL32.373)
888  */
889 BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
890                                       LPDWORD lpProcessAffinityMask,
891                                       LPDWORD lpSystemAffinityMask )
892 {
893     struct get_process_info_reply reply;
894     if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
895     if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
896     if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
897     return TRUE;
898 }
899
900
901 /***********************************************************************
902  *           GetStdHandle    (KERNEL32.276)
903  */
904 HANDLE WINAPI GetStdHandle( DWORD std_handle )
905 {
906     PDB *pdb = PROCESS_Current();
907
908     switch(std_handle)
909     {
910     case STD_INPUT_HANDLE:  return pdb->env_db->hStdin;
911     case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
912     case STD_ERROR_HANDLE:  return pdb->env_db->hStderr;
913     }
914     SetLastError( ERROR_INVALID_PARAMETER );
915     return INVALID_HANDLE_VALUE;
916 }
917
918
919 /***********************************************************************
920  *           SetStdHandle    (KERNEL32.506)
921  */
922 BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
923 {
924     PDB *pdb = PROCESS_Current();
925     /* FIXME: should we close the previous handle? */
926     switch(std_handle)
927     {
928     case STD_INPUT_HANDLE:
929         pdb->env_db->hStdin = handle;
930         return TRUE;
931     case STD_OUTPUT_HANDLE:
932         pdb->env_db->hStdout = handle;
933         return TRUE;
934     case STD_ERROR_HANDLE:
935         pdb->env_db->hStderr = handle;
936         return TRUE;
937     }
938     SetLastError( ERROR_INVALID_PARAMETER );
939     return FALSE;
940 }
941
942 /***********************************************************************
943  *           GetProcessVersion    (KERNEL32)
944  */
945 DWORD WINAPI GetProcessVersion( DWORD processid )
946 {
947     TDB *pTask;
948     PDB *pdb = PROCESS_IdToPDB( processid );
949
950     if (!pdb) return 0;
951     if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
952     return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
953 }
954
955 /***********************************************************************
956  *           GetProcessFlags    (KERNEL32)
957  */
958 DWORD WINAPI GetProcessFlags( DWORD processid )
959 {
960     PDB *pdb = PROCESS_IdToPDB( processid );
961     if (!pdb) return 0;
962     return pdb->flags;
963 }
964
965 /***********************************************************************
966  *              SetProcessWorkingSetSize        [KERNEL32.662]
967  * Sets the min/max working set sizes for a specified process.
968  *
969  * PARAMS
970  *    hProcess [I] Handle to the process of interest
971  *    minset   [I] Specifies minimum working set size
972  *    maxset   [I] Specifies maximum working set size
973  *
974  * RETURNS  STD
975  */
976 BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess,DWORD minset,
977                                        DWORD maxset)
978 {
979     FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
980     if(( minset == -1) && (maxset == -1)) {
981         /* Trim the working set to zero */
982         /* Swap the process out of physical RAM */
983     }
984     return TRUE;
985 }
986
987 /***********************************************************************
988  *           GetProcessWorkingSetSize    (KERNEL32)
989  */
990 BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess,LPDWORD minset,
991                                        LPDWORD maxset)
992 {
993         FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
994         /* 32 MB working set size */
995         if (minset) *minset = 32*1024*1024;
996         if (maxset) *maxset = 32*1024*1024;
997         return TRUE;
998 }
999
1000 /***********************************************************************
1001  *           SetProcessShutdownParameters    (KERNEL32)
1002  *
1003  * CHANGED - James Sutherland (JamesSutherland@gmx.de)
1004  * Now tracks changes made (but does not act on these changes)
1005  * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
1006  * It really shouldn't be here, but I'll move it when it's been checked!
1007  */
1008 #define SHUTDOWN_NORETRY 1
1009 static unsigned int shutdown_noretry = 0;
1010 static unsigned int shutdown_priority = 0x280L;
1011 BOOL WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
1012 {
1013     if (flags & SHUTDOWN_NORETRY)
1014       shutdown_noretry = 1;
1015     else
1016       shutdown_noretry = 0;
1017     if (level > 0x100L && level < 0x3FFL)
1018       shutdown_priority = level;
1019     else
1020       {
1021         ERR(process,"invalid priority level 0x%08lx\n", level);
1022         return FALSE;
1023       }
1024     return TRUE;
1025 }
1026
1027
1028 /***********************************************************************
1029  * GetProcessShutdownParameters                 (KERNEL32)
1030  *
1031  */
1032 BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
1033                                             LPDWORD lpdwFlags )
1034 {
1035   (*lpdwLevel) = shutdown_priority;
1036   (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
1037   return TRUE;
1038 }
1039 /***********************************************************************
1040  *           SetProcessPriorityBoost    (KERNEL32)
1041  */
1042 BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
1043 {
1044     FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
1045     /* Say we can do it. I doubt the program will notice that we don't. */
1046     return TRUE;
1047 }
1048
1049 /***********************************************************************
1050  *           ReadProcessMemory                  (KERNEL32)
1051  * FIXME: check this, if we ever run win32 binaries in different addressspaces
1052  *        ... and add a sizecheck
1053  */
1054 BOOL WINAPI ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress,
1055                                  LPVOID lpBuffer, DWORD nSize,
1056                                  LPDWORD lpNumberOfBytesRead )
1057 {
1058         memcpy(lpBuffer,lpBaseAddress,nSize);
1059         if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
1060         return TRUE;
1061 }
1062
1063 /***********************************************************************
1064  *           WriteProcessMemory                 (KERNEL32)
1065  * FIXME: check this, if we ever run win32 binaries in different addressspaces
1066  *        ... and add a sizecheck
1067  */
1068 BOOL WINAPI WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress,
1069                                  LPVOID lpBuffer, DWORD nSize,
1070                                  LPDWORD lpNumberOfBytesWritten )
1071 {
1072         memcpy(lpBaseAddress,lpBuffer,nSize);
1073         if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
1074         return TRUE;
1075 }
1076
1077 /***********************************************************************
1078  *           RegisterServiceProcess             (KERNEL, KERNEL32)
1079  *
1080  * A service process calls this function to ensure that it continues to run
1081  * even after a user logged off.
1082  */
1083 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
1084 {
1085         /* I don't think that Wine needs to do anything in that function */
1086         return 1; /* success */
1087 }
1088
1089 /***********************************************************************
1090  * GetExitCodeProcess [KERNEL32.325]
1091  *
1092  * Gets termination status of specified process
1093  * 
1094  * RETURNS
1095  *   Success: TRUE
1096  *   Failure: FALSE
1097  */
1098 BOOL WINAPI GetExitCodeProcess(
1099     HANDLE hProcess,  /* [I] handle to the process */
1100     LPDWORD lpExitCode) /* [O] address to receive termination status */
1101 {
1102     struct get_process_info_reply reply;
1103     if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
1104     if (lpExitCode) *lpExitCode = reply.exit_code;
1105     return TRUE;
1106 }
1107
1108
1109 /***********************************************************************
1110  * GetProcessHeaps [KERNEL32.376]
1111  */
1112 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE *heaps) {
1113         FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
1114
1115         if (nrofheaps) {
1116                 heaps[0] = GetProcessHeap();
1117                 /* ... probably SystemHeap too ? */
1118                 return 1;
1119         }
1120         /* number of available heaps */
1121         return 1;
1122 }
1123
1124 /***********************************************************************
1125  * PROCESS_SuspendOtherThreads
1126  */
1127
1128 void PROCESS_SuspendOtherThreads(void)
1129 {
1130 #if 0
1131     PDB *pdb;
1132     THREAD_ENTRY *entry;
1133
1134     SYSTEM_LOCK();
1135
1136     pdb = PROCESS_Current();
1137     entry = pdb->thread_list->next;
1138     for (;;)
1139     {
1140          if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
1141          {
1142              HANDLE handle = HANDLE_Alloc( PROCESS_Current(), 
1143                                              &entry->thread->header,
1144                                              THREAD_ALL_ACCESS, FALSE, -1 );
1145              SuspendThread(handle);
1146              CloseHandle(handle);
1147          }
1148          if (entry == pdb->thread_list) break;
1149          entry = entry->next;
1150     }
1151
1152     SYSTEM_UNLOCK();
1153 #endif
1154 }
1155
1156 /***********************************************************************
1157  * PROCESS_ResumeOtherThreads
1158  */
1159
1160 void PROCESS_ResumeOtherThreads(void)
1161 {
1162 #if 0
1163     PDB *pdb;
1164     THREAD_ENTRY *entry;
1165
1166     SYSTEM_LOCK();
1167
1168     pdb = PROCESS_Current();
1169     entry = pdb->thread_list->next;
1170     for (;;)
1171     {
1172          if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
1173          {
1174              HANDLE handle = HANDLE_Alloc( PROCESS_Current(), 
1175                                              &entry->thread->header,
1176                                              THREAD_ALL_ACCESS, FALSE, -1 );
1177              ResumeThread(handle);
1178              CloseHandle(handle);
1179          }
1180          if (entry == pdb->thread_list) break;
1181          entry = entry->next;
1182     }
1183
1184     SYSTEM_UNLOCK();
1185 #endif
1186 }
1187