Fix ambiguous else warning.
[wine/dcerpc.git] / scheduler / process.c
blob94a44b701fa3f0f56c412b152c70fca00215b037
1 /*
2 * Win32 processes
4 * Copyright 1996, 1998 Alexandre Julliard
5 */
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"
29 /* The initial process PDB */
30 static PDB initial_pdb;
32 static PDB *PROCESS_First = &initial_pdb;
34 /***********************************************************************
35 * PROCESS_Current
37 PDB *PROCESS_Current(void)
39 return THREAD_Current()->process;
42 /***********************************************************************
43 * PROCESS_Initial
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)
50 PDB *PROCESS_Initial(void)
52 return &initial_pdb;
55 /***********************************************************************
56 * PROCESS_QueryInfo
58 * Retrieve information about a process
60 static BOOL PROCESS_QueryInfo( HANDLE handle,
61 struct get_process_info_reply *reply )
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 );
69 /***********************************************************************
70 * PROCESS_IsCurrent
72 * Check if a handle is to the current process
74 BOOL PROCESS_IsCurrent( HANDLE handle )
76 struct get_process_info_reply reply;
77 return (PROCESS_QueryInfo( handle, &reply ) &&
78 (reply.pid == PROCESS_Current()->server_pid));
82 /***********************************************************************
83 * PROCESS_IdToPDB
85 * Convert a process id to a PDB, making sure it is valid.
87 PDB *PROCESS_IdToPDB( DWORD id )
89 PDB *pdb;
91 if (!id) return PROCESS_Current();
92 pdb = PROCESS_First;
93 while (pdb)
95 if ((DWORD)pdb->server_pid == id) return pdb;
96 pdb = pdb->next;
98 SetLastError( ERROR_INVALID_PARAMETER );
99 return NULL;
103 /***********************************************************************
104 * PROCESS_CallUserSignalProc
106 * FIXME: Some of the signals aren't sent correctly!
108 * The exact meaning of the USER signals is undocumented, but this
109 * should cover the basic idea:
111 * USIG_DLL_UNLOAD_WIN16
112 * This is sent when a 16-bit module is unloaded.
114 * USIG_DLL_UNLOAD_WIN32
115 * This is sent when a 32-bit module is unloaded.
117 * USIG_DLL_UNLOAD_ORPHANS
118 * This is sent after the last Win3.1 module is unloaded,
119 * to allow removal of orphaned menus.
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.
127 * USIG_THREAD_INIT
128 * This is called from the context of a new thread, as soon as it
129 * has started to run.
131 * USIG_THREAD_EXIT
132 * This is called, still in its context, just before a thread is
133 * about to terminate.
135 * USIG_PROCESS_CREATE
136 * This is called, in the parent process context, after a new process
137 * has been created.
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).
144 * USIG_PROCESS_LOADED
145 * This is called after the executable file has been loaded into the
146 * new process context.
148 * USIG_PROCESS_RUNNING
149 * This is called immediately before the main entry point is called.
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).
156 * USIG_PROCESS_DESTROY
157 * This is called after a process has terminated.
160 * The meaning of the dwFlags bits is as follows:
162 * USIG_FLAGS_WIN32
163 * Current process is 32-bit.
165 * USIG_FLAGS_GUI
166 * Current process is a (Win32) GUI process.
168 * USIG_FLAGS_FEEDBACK
169 * Current process needs 'feedback' (determined from the STARTUPINFO
170 * flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
172 * USIG_FLAGS_FAULT
173 * The signal is being sent due to a fault.
175 void PROCESS_CallUserSignalProc( UINT uCode, DWORD dwThreadOrProcessId, HMODULE hModule )
177 PDB *pdb = PROCESS_Current();
178 STARTUPINFOA *startup = pdb->env_db? pdb->env_db->startup_info : NULL;
179 DWORD dwFlags = 0;
181 /* Determine dwFlags */
183 if ( !(pdb->flags & PDB32_WIN16_PROC) )
184 dwFlags |= USIG_FLAGS_WIN32;
186 if ( !(pdb->flags & PDB32_CONSOLE_PROC) )
187 dwFlags |= USIG_FLAGS_GUI;
189 if ( dwFlags & USIG_FLAGS_GUI )
191 /* Feedback defaults to ON */
192 if ( !(startup && (startup->dwFlags & STARTF_FORCEOFFFEEDBACK)) )
193 dwFlags |= USIG_FLAGS_FEEDBACK;
195 else
197 /* Feedback defaults to OFF */
198 if ( startup && (startup->dwFlags & STARTF_FORCEONFEEDBACK) )
199 dwFlags |= USIG_FLAGS_FEEDBACK;
202 /* Get thread or process ID */
204 if ( dwThreadOrProcessId == 0 )
206 if ( uCode == USIG_THREAD_INIT || uCode == USIG_THREAD_EXIT )
207 dwThreadOrProcessId = GetCurrentThreadId();
208 else
209 dwThreadOrProcessId = GetCurrentProcessId();
212 /* Convert module handle to 16-bit */
214 if ( HIWORD( hModule ) )
215 hModule = MapHModuleLS( hModule );
217 /* Call USER signal proc */
219 if ( Callout.UserSignalProc )
220 Callout.UserSignalProc( uCode, dwThreadOrProcessId, dwFlags, hModule );
224 /***********************************************************************
225 * PROCESS_BuildEnvDB
227 * Build the env DB for the initial process
229 static BOOL PROCESS_BuildEnvDB( PDB *pdb )
231 /* Allocate the env DB (FIXME: should not be on the system heap) */
233 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
234 return FALSE;
235 InitializeCriticalSection( &pdb->env_db->section );
237 /* Allocate startup info */
238 if (!(pdb->env_db->startup_info =
239 HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
240 return FALSE;
242 /* Allocate the standard handles */
244 pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
245 pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
246 pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
248 /* Build the command-line */
250 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
252 /* Build the environment strings */
254 return ENV_BuildEnvironment( pdb );
258 /***********************************************************************
259 * PROCESS_InheritEnvDB
261 static BOOL PROCESS_InheritEnvDB( PDB *pdb, LPCSTR cmd_line, LPCSTR env,
262 BOOL inherit_handles, STARTUPINFOA *startup )
264 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
265 return FALSE;
266 InitializeCriticalSection( &pdb->env_db->section );
268 /* Copy the parent environment */
270 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
272 /* Copy the command line */
274 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
275 return FALSE;
277 /* Remember startup info */
278 if (!(pdb->env_db->startup_info =
279 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
280 return FALSE;
281 *pdb->env_db->startup_info = *startup;
283 /* Inherit the standard handles */
284 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
286 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
287 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
288 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
290 else if (inherit_handles)
292 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
293 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
294 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
296 /* else will be done later on in PROCESS_Create */
298 return TRUE;
302 /***********************************************************************
303 * PROCESS_CreateEnvDB
305 * Create the env DB for a newly started process.
307 static BOOL PROCESS_CreateEnvDB(void)
309 struct init_process_request req;
310 struct init_process_reply reply;
311 STARTUPINFOA *startup;
312 ENVDB *env_db;
313 PDB *pdb = PROCESS_Current();
315 /* Retrieve startup info from the server */
317 req.dummy = 0;
318 CLIENT_SendRequest( REQ_INIT_PROCESS, -1, 1, &req, sizeof(req) );
319 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
321 /* Allocate the env DB */
323 if (!(env_db = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB) )))
324 return FALSE;
325 pdb->env_db = env_db;
326 InitializeCriticalSection( &env_db->section );
328 /* Allocate and fill the startup info */
329 if (!(startup = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
330 return FALSE;
331 pdb->env_db->startup_info = startup;
332 startup->dwFlags = reply.start_flags;
333 pdb->env_db->hStdin = startup->hStdInput = reply.hstdin;
334 pdb->env_db->hStdout = startup->hStdOutput = reply.hstdout;
335 pdb->env_db->hStderr = startup->hStdError = reply.hstderr;
337 #if 0 /* FIXME */
338 /* Copy the parent environment */
340 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
342 /* Copy the command line */
344 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
345 return FALSE;
346 #endif
347 return TRUE;
351 /***********************************************************************
352 * PROCESS_FreePDB
354 * Free a PDB and all associated storage.
356 void PROCESS_FreePDB( PDB *pdb )
358 PDB **pptr = &PROCESS_First;
360 ENV_FreeEnvironment( pdb );
361 while (*pptr && (*pptr != pdb)) pptr = &(*pptr)->next;
362 if (*pptr) *pptr = pdb->next;
363 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
364 HeapFree( SystemHeap, 0, pdb );
368 /***********************************************************************
369 * PROCESS_CreatePDB
371 * Allocate and fill a PDB structure.
372 * Runs in the context of the parent process.
374 static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
376 PDB *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB) );
378 if (!pdb) return NULL;
379 pdb->exit_code = 0x103; /* STILL_ACTIVE */
380 pdb->threads = 1;
381 pdb->running_threads = 1;
382 pdb->ring0_threads = 1;
383 pdb->system_heap = SystemHeap;
384 pdb->parent = parent;
385 pdb->group = pdb;
386 pdb->priority = 8; /* Normal */
387 pdb->heap = pdb->system_heap; /* will be changed later on */
388 pdb->next = PROCESS_First;
389 PROCESS_First = pdb;
390 return pdb;
394 /***********************************************************************
395 * PROCESS_Init
397 BOOL PROCESS_Init(void)
399 THDB *thdb;
400 int server_fd;
402 /* Start the server */
403 server_fd = CLIENT_InitServer();
405 /* Fill the initial process structure */
406 initial_pdb.exit_code = 0x103; /* STILL_ACTIVE */
407 initial_pdb.threads = 1;
408 initial_pdb.running_threads = 1;
409 initial_pdb.ring0_threads = 1;
410 initial_pdb.group = &initial_pdb;
411 initial_pdb.priority = 8; /* Normal */
412 initial_pdb.flags = PDB32_WIN16_PROC;
414 /* Initialize virtual memory management */
415 if (!VIRTUAL_Init()) return FALSE;
417 /* Create the initial thread structure and socket pair */
418 if (!(thdb = THREAD_CreateInitialThread( &initial_pdb, server_fd ))) return FALSE;
420 /* Remember TEB selector of initial process for emergency use */
421 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
423 /* Create the system heap */
424 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
425 initial_pdb.system_heap = initial_pdb.heap = SystemHeap;
427 /* Create the environment DB of the first process */
428 if (!PROCESS_BuildEnvDB( &initial_pdb )) return FALSE;
430 /* Create the SEGPTR heap */
431 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
433 /* Initialize the first process critical section */
434 InitializeCriticalSection( &initial_pdb.crit_section );
436 return TRUE;
440 /***********************************************************************
441 * PROCESS_Start
443 * Startup routine of a new process. Called in the context of the new process.
445 void PROCESS_Start(void)
447 DWORD size, commit;
448 UINT cmdShow = 0;
449 LPTHREAD_START_ROUTINE entry;
450 THDB *thdb = THREAD_Current();
451 PDB *pdb = thdb->process;
452 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
453 NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
454 OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
456 PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0, 0 ); /* for initial thread */
458 #if 0
459 /* Initialize the critical section */
461 InitializeCriticalSection( &pdb->crit_section );
463 /* Create the heap */
465 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
466 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
467 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
468 pdb->heap_list = pdb->heap;
470 /* Create the environment db */
472 if (!PROCESS_CreateEnvDB()) goto error;
474 if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
475 cmdShow = pdb->env_db->startup_info->wShowWindow;
476 if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
478 #endif
480 PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0, 0 );
482 /* Map system DLLs into this process (from initial process) */
483 /* FIXME: this is a hack */
484 pdb->modref_list = PROCESS_Initial()->modref_list;
486 /* Create 32-bit MODREF */
487 if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
489 PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 ); /* FIXME: correct location? */
491 /* Initialize thread-local storage */
493 PE_InitTls();
495 if ( pdb->flags & PDB32_CONSOLE_PROC )
496 AllocConsole();
498 /* Now call the entry point */
500 MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)1 );
502 PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
504 entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
505 OptionalHeader.AddressOfEntryPoint);
506 TRACE(relay, "(entryproc=%p)\n", entry );
507 ExitProcess( entry(NULL) );
509 error:
510 ExitProcess(1);
514 /***********************************************************************
515 * PROCESS_Create
517 * Create a new process database and associated info.
519 PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
520 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
521 LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
522 BOOL inherit, STARTUPINFOA *startup,
523 PROCESS_INFORMATION *info )
525 DWORD size, commit;
526 int server_thandle;
527 struct new_process_request req;
528 struct new_process_reply reply;
529 UINT cmdShow = 0;
530 THDB *thdb = NULL;
531 PDB *parent = PROCESS_Current();
532 PDB *pdb = PROCESS_CreatePDB( parent, inherit );
534 if (!pdb) return NULL;
535 info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
537 /* Create the process on the server side */
539 req.inherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
540 req.inherit_all = inherit;
541 req.start_flags = startup->dwFlags;
542 if (startup->dwFlags & STARTF_USESTDHANDLES)
544 req.hstdin = startup->hStdInput;
545 req.hstdout = startup->hStdOutput;
546 req.hstderr = startup->hStdError;
548 else
550 req.hstdin = GetStdHandle( STD_INPUT_HANDLE );
551 req.hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
552 req.hstderr = GetStdHandle( STD_ERROR_HANDLE );
554 CLIENT_SendRequest( REQ_NEW_PROCESS, -1, 2,
555 &req, sizeof(req), cmd_line, strlen(cmd_line) + 1 );
556 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
557 pdb->server_pid = reply.pid;
558 info->hProcess = reply.handle;
559 info->dwProcessId = (DWORD)pdb->server_pid;
561 /* Initialize the critical section */
563 InitializeCriticalSection( &pdb->crit_section );
565 /* Setup process flags */
567 if ( !pModule->module32 )
568 pdb->flags |= PDB32_WIN16_PROC;
570 else if ( PE_HEADER(pModule->module32)->OptionalHeader.Subsystem
571 == IMAGE_SUBSYSTEM_WINDOWS_CUI )
572 pdb->flags |= PDB32_CONSOLE_PROC;
574 /* Create the heap */
576 if (pModule->module32)
578 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
579 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
581 else
583 size = 0x10000;
584 commit = 0;
586 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
587 pdb->heap_list = pdb->heap;
589 /* Inherit the env DB from the parent */
591 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
593 /* Call USER signal proc */
595 PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, info->dwProcessId, 0 );
597 /* Create the main thread */
599 if (pModule->module32)
600 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
601 else
602 size = 0;
603 if (!(thdb = THREAD_Create( pdb, 0L, size, hInstance == 0, tsa, &server_thandle )))
604 goto error;
605 info->hThread = server_thandle;
606 info->dwThreadId = (DWORD)thdb->server_tid;
607 thdb->startup = PROCESS_Start;
609 /* Duplicate the standard handles */
611 if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
613 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
614 info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
615 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
616 info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
617 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
618 info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
621 /* Create a Win16 task for this process */
623 if (startup->dwFlags & STARTF_USESHOWWINDOW)
624 cmdShow = startup->wShowWindow;
626 if ( !TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow) )
627 goto error;
630 /* Map system DLLs into this process (from initial process) */
631 /* FIXME: this is a hack */
632 pdb->modref_list = PROCESS_Initial()->modref_list;
635 /* Start the task */
637 TASK_StartTask( pdb->task );
639 return pdb;
641 error:
642 if (info->hThread != INVALID_HANDLE_VALUE) CloseHandle( info->hThread );
643 if (info->hProcess != INVALID_HANDLE_VALUE) CloseHandle( info->hProcess );
644 PROCESS_FreePDB( pdb );
645 return NULL;
649 /***********************************************************************
650 * ExitProcess (KERNEL32.100)
652 void WINAPI ExitProcess( DWORD status )
654 MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, (LPVOID)1 );
656 if ( THREAD_IsWin16( THREAD_Current() ) )
657 TASK_KillCurrentTask( status );
659 TASK_KillTask( 0 );
660 TerminateProcess( GetCurrentProcess(), status );
664 /******************************************************************************
665 * TerminateProcess (KERNEL32.684)
667 BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
669 struct terminate_process_request req;
670 req.handle = handle;
671 req.exit_code = exit_code;
672 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
673 return !CLIENT_WaitReply( NULL, NULL, 0 );
677 /***********************************************************************
678 * GetProcessDword (KERNEL32.18) (KERNEL.485)
679 * 'Of course you cannot directly access Windows internal structures'
681 DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
683 PDB *process = PROCESS_IdToPDB( dwProcessID );
684 TDB *pTask;
685 DWORD x, y;
687 TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
688 if ( !process ) return 0;
690 switch ( offset )
692 case GPD_APP_COMPAT_FLAGS:
693 pTask = (TDB *)GlobalLock16( process->task );
694 return pTask? pTask->compat_flags : 0;
696 case GPD_LOAD_DONE_EVENT:
697 return process->load_done_evt;
699 case GPD_HINSTANCE16:
700 pTask = (TDB *)GlobalLock16( process->task );
701 return pTask? pTask->hInstance : 0;
703 case GPD_WINDOWS_VERSION:
704 pTask = (TDB *)GlobalLock16( process->task );
705 return pTask? pTask->version : 0;
707 case GPD_THDB:
708 if ( process != PROCESS_Current() ) return 0;
709 return (DWORD)THREAD_Current();
711 case GPD_PDB:
712 return (DWORD)process;
714 case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
715 return process->env_db->startup_info->hStdOutput;
717 case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
718 return process->env_db->startup_info->hStdInput;
720 case GPD_STARTF_SHOWWINDOW:
721 return process->env_db->startup_info->wShowWindow;
723 case GPD_STARTF_SIZE:
724 x = process->env_db->startup_info->dwXSize;
725 if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
726 y = process->env_db->startup_info->dwYSize;
727 if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
728 return MAKELONG( x, y );
730 case GPD_STARTF_POSITION:
731 x = process->env_db->startup_info->dwX;
732 if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
733 y = process->env_db->startup_info->dwY;
734 if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
735 return MAKELONG( x, y );
737 case GPD_STARTF_FLAGS:
738 return process->env_db->startup_info->dwFlags;
740 case GPD_PARENT:
741 return (DWORD)process->parent->server_pid;
743 case GPD_FLAGS:
744 return process->flags;
746 case GPD_USERDATA:
747 return process->process_dword;
749 default:
750 ERR( win32, "Unknown offset %d\n", offset );
751 return 0;
755 /***********************************************************************
756 * SetProcessDword (KERNEL.484)
757 * 'Of course you cannot directly access Windows internal structures'
759 void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
761 PDB *process = PROCESS_IdToPDB( dwProcessID );
763 TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
764 if ( !process ) return;
766 switch ( offset )
768 case GPD_APP_COMPAT_FLAGS:
769 case GPD_LOAD_DONE_EVENT:
770 case GPD_HINSTANCE16:
771 case GPD_WINDOWS_VERSION:
772 case GPD_THDB:
773 case GPD_PDB:
774 case GPD_STARTF_SHELLDATA:
775 case GPD_STARTF_HOTKEY:
776 case GPD_STARTF_SHOWWINDOW:
777 case GPD_STARTF_SIZE:
778 case GPD_STARTF_POSITION:
779 case GPD_STARTF_FLAGS:
780 case GPD_PARENT:
781 case GPD_FLAGS:
782 ERR( win32, "Not allowed to modify offset %d\n", offset );
783 break;
785 case GPD_USERDATA:
786 process->process_dword = value;
787 break;
789 default:
790 ERR( win32, "Unknown offset %d\n", offset );
791 break;
796 /***********************************************************************
797 * GetCurrentProcess (KERNEL32.198)
799 HANDLE WINAPI GetCurrentProcess(void)
801 return CURRENT_PROCESS_PSEUDOHANDLE;
805 /*********************************************************************
806 * OpenProcess (KERNEL32.543)
808 HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
810 struct open_process_request req;
811 struct open_process_reply reply;
813 req.pid = (void *)id;
814 req.access = access;
815 req.inherit = inherit;
816 CLIENT_SendRequest( REQ_OPEN_PROCESS, -1, 1, &req, sizeof(req) );
817 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0;
818 return reply.handle;
822 /***********************************************************************
823 * GetCurrentProcessId (KERNEL32.199)
825 DWORD WINAPI GetCurrentProcessId(void)
827 return (DWORD)PROCESS_Current()->server_pid;
831 /***********************************************************************
832 * GetProcessHeap (KERNEL32.259)
834 HANDLE WINAPI GetProcessHeap(void)
836 PDB *pdb = PROCESS_Current();
837 return pdb->heap ? pdb->heap : SystemHeap;
841 /***********************************************************************
842 * GetThreadLocale (KERNEL32.295)
844 LCID WINAPI GetThreadLocale(void)
846 return PROCESS_Current()->locale;
850 /***********************************************************************
851 * SetPriorityClass (KERNEL32.503)
853 BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
855 struct set_process_info_request req;
856 req.handle = hprocess;
857 req.priority = priorityclass;
858 req.mask = SET_PROCESS_INFO_PRIORITY;
859 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
860 return !CLIENT_WaitReply( NULL, NULL, 0 );
864 /***********************************************************************
865 * GetPriorityClass (KERNEL32.250)
867 DWORD WINAPI GetPriorityClass(HANDLE hprocess)
869 struct get_process_info_reply reply;
870 if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
871 return reply.priority;
875 /***********************************************************************
876 * SetProcessAffinityMask (KERNEL32.662)
878 BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
880 struct set_process_info_request req;
881 req.handle = hProcess;
882 req.affinity = affmask;
883 req.mask = SET_PROCESS_INFO_AFFINITY;
884 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
885 return !CLIENT_WaitReply( NULL, NULL, 0 );
888 /**********************************************************************
889 * GetProcessAffinityMask (KERNEL32.373)
891 BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
892 LPDWORD lpProcessAffinityMask,
893 LPDWORD lpSystemAffinityMask )
895 struct get_process_info_reply reply;
896 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
897 if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
898 if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
899 return TRUE;
903 /***********************************************************************
904 * GetStdHandle (KERNEL32.276)
906 HANDLE WINAPI GetStdHandle( DWORD std_handle )
908 PDB *pdb = PROCESS_Current();
910 switch(std_handle)
912 case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
913 case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
914 case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
916 SetLastError( ERROR_INVALID_PARAMETER );
917 return INVALID_HANDLE_VALUE;
921 /***********************************************************************
922 * SetStdHandle (KERNEL32.506)
924 BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
926 PDB *pdb = PROCESS_Current();
927 /* FIXME: should we close the previous handle? */
928 switch(std_handle)
930 case STD_INPUT_HANDLE:
931 pdb->env_db->hStdin = handle;
932 return TRUE;
933 case STD_OUTPUT_HANDLE:
934 pdb->env_db->hStdout = handle;
935 return TRUE;
936 case STD_ERROR_HANDLE:
937 pdb->env_db->hStderr = handle;
938 return TRUE;
940 SetLastError( ERROR_INVALID_PARAMETER );
941 return FALSE;
944 /***********************************************************************
945 * GetProcessVersion (KERNEL32)
947 DWORD WINAPI GetProcessVersion( DWORD processid )
949 TDB *pTask;
950 PDB *pdb = PROCESS_IdToPDB( processid );
952 if (!pdb) return 0;
953 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
954 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
957 /***********************************************************************
958 * GetProcessFlags (KERNEL32)
960 DWORD WINAPI GetProcessFlags( DWORD processid )
962 PDB *pdb = PROCESS_IdToPDB( processid );
963 if (!pdb) return 0;
964 return pdb->flags;
967 /***********************************************************************
968 * SetProcessWorkingSetSize [KERNEL32.662]
969 * Sets the min/max working set sizes for a specified process.
971 * PARAMS
972 * hProcess [I] Handle to the process of interest
973 * minset [I] Specifies minimum working set size
974 * maxset [I] Specifies maximum working set size
976 * RETURNS STD
978 BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess,DWORD minset,
979 DWORD maxset)
981 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
982 if(( minset == -1) && (maxset == -1)) {
983 /* Trim the working set to zero */
984 /* Swap the process out of physical RAM */
986 return TRUE;
989 /***********************************************************************
990 * GetProcessWorkingSetSize (KERNEL32)
992 BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess,LPDWORD minset,
993 LPDWORD maxset)
995 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
996 /* 32 MB working set size */
997 if (minset) *minset = 32*1024*1024;
998 if (maxset) *maxset = 32*1024*1024;
999 return TRUE;
1002 /***********************************************************************
1003 * SetProcessShutdownParameters (KERNEL32)
1005 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
1006 * Now tracks changes made (but does not act on these changes)
1007 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
1008 * It really shouldn't be here, but I'll move it when it's been checked!
1010 #define SHUTDOWN_NORETRY 1
1011 static unsigned int shutdown_noretry = 0;
1012 static unsigned int shutdown_priority = 0x280L;
1013 BOOL WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
1015 if (flags & SHUTDOWN_NORETRY)
1016 shutdown_noretry = 1;
1017 else
1018 shutdown_noretry = 0;
1019 if (level > 0x100L && level < 0x3FFL)
1020 shutdown_priority = level;
1021 else
1023 ERR(process,"invalid priority level 0x%08lx\n", level);
1024 return FALSE;
1026 return TRUE;
1030 /***********************************************************************
1031 * GetProcessShutdownParameters (KERNEL32)
1034 BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
1035 LPDWORD lpdwFlags )
1037 (*lpdwLevel) = shutdown_priority;
1038 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
1039 return TRUE;
1041 /***********************************************************************
1042 * SetProcessPriorityBoost (KERNEL32)
1044 BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
1046 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
1047 /* Say we can do it. I doubt the program will notice that we don't. */
1048 return TRUE;
1051 /***********************************************************************
1052 * ReadProcessMemory (KERNEL32)
1053 * FIXME: check this, if we ever run win32 binaries in different addressspaces
1054 * ... and add a sizecheck
1056 BOOL WINAPI ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress,
1057 LPVOID lpBuffer, DWORD nSize,
1058 LPDWORD lpNumberOfBytesRead )
1060 memcpy(lpBuffer,lpBaseAddress,nSize);
1061 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
1062 return TRUE;
1065 /***********************************************************************
1066 * WriteProcessMemory (KERNEL32)
1067 * FIXME: check this, if we ever run win32 binaries in different addressspaces
1068 * ... and add a sizecheck
1070 BOOL WINAPI WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress,
1071 LPVOID lpBuffer, DWORD nSize,
1072 LPDWORD lpNumberOfBytesWritten )
1074 memcpy(lpBaseAddress,lpBuffer,nSize);
1075 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
1076 return TRUE;
1079 /***********************************************************************
1080 * RegisterServiceProcess (KERNEL, KERNEL32)
1082 * A service process calls this function to ensure that it continues to run
1083 * even after a user logged off.
1085 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
1087 /* I don't think that Wine needs to do anything in that function */
1088 return 1; /* success */
1091 /***********************************************************************
1092 * GetExitCodeProcess [KERNEL32.325]
1094 * Gets termination status of specified process
1096 * RETURNS
1097 * Success: TRUE
1098 * Failure: FALSE
1100 BOOL WINAPI GetExitCodeProcess(
1101 HANDLE hProcess, /* [I] handle to the process */
1102 LPDWORD lpExitCode) /* [O] address to receive termination status */
1104 struct get_process_info_reply reply;
1105 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
1106 if (lpExitCode) *lpExitCode = reply.exit_code;
1107 return TRUE;
1111 /***********************************************************************
1112 * GetProcessHeaps [KERNEL32.376]
1114 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE *heaps) {
1115 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
1117 if (nrofheaps) {
1118 heaps[0] = GetProcessHeap();
1119 /* ... probably SystemHeap too ? */
1120 return 1;
1122 /* number of available heaps */
1123 return 1;