Re-implemented using a real semaphore.
[wine/multimedia.git] / scheduler / process.c
blob6ddc950d54c3c6fa1a051a931ac826ac0db2cf3c
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 "file.h"
14 #include "global.h"
15 #include "heap.h"
16 #include "task.h"
17 #include "ldt.h"
18 #include "syslevel.h"
19 #include "thread.h"
20 #include "winerror.h"
21 #include "pe_image.h"
22 #include "task.h"
23 #include "server.h"
24 #include "debug.h"
26 static void PROCESS_Destroy( K32OBJ *obj );
28 const K32OBJ_OPS PROCESS_Ops =
30 PROCESS_Destroy /* destroy */
33 static DWORD PROCESS_InitialProcessID = 0;
34 static PDB32 *PROCESS_PDBList = NULL;
35 static DWORD PROCESS_PDBList_Size = 0;
37 /***********************************************************************
38 * PROCESS_Current
40 PDB32 *PROCESS_Current(void)
42 return THREAD_Current()->process;
45 /***********************************************************************
46 * PROCESS_Initial
48 * FIXME: This works only while running all processes in the same
49 * address space (or, at least, the initial process is mapped
50 * into all address spaces as is KERNEL32 in Windows 95)
53 PDB32 *PROCESS_Initial(void)
55 return PROCESS_IdToPDB( PROCESS_InitialProcessID );
58 /***********************************************************************
59 * PROCESS_GetPtr
61 * Get a process from a handle, incrementing the PDB refcount.
63 PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
65 return (PDB32 *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
66 K32OBJ_PROCESS, access, server_handle );
70 /***********************************************************************
71 * PROCESS_IdToPDB
73 * Convert a process id to a PDB, making sure it is valid.
75 PDB32 *PROCESS_IdToPDB( DWORD id )
77 PDB32 *pdb;
79 if (!id) return PROCESS_Current();
80 pdb = PROCESS_ID_TO_PDB( id );
81 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
83 SetLastError( ERROR_INVALID_PARAMETER );
84 return NULL;
86 return pdb;
91 /***********************************************************************
92 * PROCESS_BuildEnvDB
94 * Build the env DB for the initial process
96 static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
98 /* Allocate the env DB (FIXME: should not be on the system heap) */
100 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
101 return FALSE;
102 InitializeCriticalSection( &pdb->env_db->section );
104 /* Allocate startup info */
105 if (!(pdb->env_db->startup_info =
106 HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
107 return FALSE;
109 /* Allocate the standard handles */
111 pdb->env_db->hStdin = FILE_DupUnixHandle( 0 );
112 pdb->env_db->hStdout = FILE_DupUnixHandle( 1 );
113 pdb->env_db->hStderr = FILE_DupUnixHandle( 2 );
114 FILE_SetFileType( pdb->env_db->hStdin, FILE_TYPE_CHAR );
115 FILE_SetFileType( pdb->env_db->hStdout, FILE_TYPE_CHAR );
116 FILE_SetFileType( pdb->env_db->hStderr, FILE_TYPE_CHAR );
118 /* Build the command-line */
120 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
122 /* Build the environment strings */
124 return ENV_BuildEnvironment( pdb );
128 /***********************************************************************
129 * PROCESS_InheritEnvDB
131 static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
132 STARTUPINFO32A *startup )
134 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
135 return FALSE;
136 InitializeCriticalSection( &pdb->env_db->section );
138 /* Copy the parent environment */
140 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
142 /* Copy the command line */
144 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
145 return FALSE;
147 /* Remember startup info */
148 if (!(pdb->env_db->startup_info =
149 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
150 return FALSE;
151 *pdb->env_db->startup_info = *startup;
153 /* Inherit the standard handles */
154 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
156 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
157 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
158 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
160 else
162 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
163 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
164 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
167 return TRUE;
170 /***********************************************************************
171 * PROCESS_PDBList_Insert
172 * Insert this PDB into the global PDB list
175 static void PROCESS_PDBList_Insert (PDB32 *pdb)
177 TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
178 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
180 SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
181 * I.e., could more than one process be
182 * created at once ?
184 if (PROCESS_PDBList == NULL)
186 PROCESS_PDBList = pdb;
187 pdb->list_next = NULL;
188 pdb->list_prev = NULL;
190 else
192 PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList;
193 if (first->list_prev) last = first->list_prev;
195 PROCESS_PDBList = pdb;
196 pdb->list_next = first;
197 pdb->list_prev = last;
198 last->list_next = pdb;
199 first->list_prev = pdb;
201 PROCESS_PDBList_Size ++;
202 SYSTEM_UNLOCK ();
205 /***********************************************************************
206 * PROCESS_PDBList_Remove
207 * Remove this PDB from the global PDB list
210 static void PROCESS_PDBList_Remove (PDB32 *pdb)
212 PDB32 *next = pdb->list_next, *prev = pdb->list_prev;
214 TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
215 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
217 SYSTEM_LOCK ();
219 if (prev == next)
221 next->list_prev = NULL;
222 next->list_next = NULL;
224 else
226 if (next) next->list_prev = prev;
227 if (prev) prev->list_next = next;
230 if (pdb == PROCESS_PDBList)
232 PROCESS_PDBList = next ? next : prev;
234 PROCESS_PDBList_Size --;
236 SYSTEM_UNLOCK ();
239 /***********************************************************************
240 * PROCESS_PDBList_Getsize
241 * Return the number of items in the global PDB list
244 int PROCESS_PDBList_Getsize ()
246 return PROCESS_PDBList_Size;
249 /***********************************************************************
250 * PROCESS_PDBList_Getfirst
251 * Return the head of the PDB list
254 PDB32* PROCESS_PDBList_Getfirst ()
256 return PROCESS_PDBList;
259 /***********************************************************************
260 * PROCESS_PDBList_Getnext
261 * Return the "next" pdb as referenced from the argument.
262 * If at the end of the list, return NULL.
265 PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb)
267 return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
270 /***********************************************************************
271 * PROCESS_FreePDB
273 * Free a PDB and all associated storage.
275 static void PROCESS_FreePDB( PDB32 *pdb )
278 * FIXME:
279 * If this routine is called because PROCESS_CreatePDB fails, the
280 * following call to PROCESS_PDBList_Remove will probably screw
281 * up.
283 PROCESS_PDBList_Remove (pdb);
284 pdb->header.type = K32OBJ_UNKNOWN;
285 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
286 ENV_FreeEnvironment( pdb );
287 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
288 DeleteCriticalSection( &pdb->crit_section );
289 HeapFree( SystemHeap, 0, pdb );
293 /***********************************************************************
294 * PROCESS_CreatePDB
296 * Allocate and fill a PDB structure.
297 * Runs in the context of the parent process.
299 static PDB32 *PROCESS_CreatePDB( PDB32 *parent )
301 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
303 if (!pdb) return NULL;
304 pdb->header.type = K32OBJ_PROCESS;
305 pdb->header.refcount = 1;
306 pdb->exit_code = 0x103; /* STILL_ACTIVE */
307 pdb->threads = 1;
308 pdb->running_threads = 1;
309 pdb->ring0_threads = 1;
310 pdb->system_heap = SystemHeap;
311 pdb->parent = parent;
312 pdb->group = pdb;
313 pdb->priority = 8; /* Normal */
314 pdb->heap = pdb->system_heap; /* will be changed later on */
316 /* Create the handle table */
318 if (!HANDLE_CreateTable( pdb, TRUE )) goto error;
320 PROCESS_PDBList_Insert (pdb);
321 return pdb;
323 error:
324 PROCESS_FreePDB( pdb );
325 return NULL;
329 /***********************************************************************
330 * PROCESS_FinishCreatePDB
332 * Second part of CreatePDB
334 static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
336 InitializeCriticalSection( &pdb->crit_section );
337 /* Allocate the event */
338 if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
339 return FALSE;
340 return TRUE;
344 /***********************************************************************
345 * PROCESS_Init
347 BOOL32 PROCESS_Init(void)
349 PDB32 *pdb;
350 THDB *thdb;
352 /* Initialize virtual memory management */
353 if (!VIRTUAL_Init()) return FALSE;
355 /* Create the system heaps */
356 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
358 /* Create the initial process and thread structures */
359 if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
360 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
361 thdb->unix_pid = getpid();
363 PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
365 /* Remember TEB selector of initial process for emergency use */
366 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
368 /* Create the environment DB of the first process */
369 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
371 /* Initialize the first thread */
372 if (CLIENT_InitThread()) return FALSE;
373 if (!PROCESS_FinishCreatePDB( pdb )) return FALSE;
375 /* Create the SEGPTR heap */
376 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
378 return TRUE;
382 /***********************************************************************
383 * PROCESS_Create
385 * Create a new process database and associated info.
387 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
388 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
389 STARTUPINFO32A *startup, PROCESS_INFORMATION *info )
391 DWORD size, commit;
392 int server_thandle, server_phandle;
393 UINT32 cmdShow = 0;
394 THDB *thdb = NULL;
395 PDB32 *parent = PROCESS_Current();
396 PDB32 *pdb = PROCESS_CreatePDB( parent );
397 TDB *pTask;
399 if (!pdb) return NULL;
400 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
401 if (!PROCESS_FinishCreatePDB( pdb )) goto error;
403 /* Create the heap */
405 if (pModule->module32)
407 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
408 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
410 else
412 size = 0x10000;
413 commit = 0;
414 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
416 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
417 pdb->heap_list = pdb->heap;
419 /* Inherit the env DB from the parent */
421 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, startup )) goto error;
423 /* Create the main thread */
425 if (pModule->module32)
426 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
427 else
428 size = 0;
429 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
430 NULL, NULL ))) goto error;
431 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
432 FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
433 goto error;
434 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
435 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
436 goto error;
437 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
438 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
440 #if 0
441 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
442 #else
443 /* All Win16 'threads' have the same unix_pid, no matter by which thread
444 they were created ! */
445 pTask = (TDB *)GlobalLock16( parent->task );
446 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
447 #endif
449 /* Create a Win16 task for this process */
451 if (startup->dwFlags & STARTF_USESHOWWINDOW)
452 cmdShow = startup->wShowWindow;
454 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
455 if (!pdb->task) goto error;
458 /* Map system DLLs into this process (from initial process) */
459 /* FIXME: this is a hack */
460 pdb->modref_list = PROCESS_Initial()->modref_list;
463 return pdb;
465 error:
466 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
467 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
468 if (thdb) K32OBJ_DecCount( &thdb->header );
469 PROCESS_FreePDB( pdb );
470 return NULL;
474 /***********************************************************************
475 * PROCESS_Destroy
477 static void PROCESS_Destroy( K32OBJ *ptr )
479 PDB32 *pdb = (PDB32 *)ptr;
480 assert( ptr->type == K32OBJ_PROCESS );
482 /* Free everything */
484 ptr->type = K32OBJ_UNKNOWN;
485 PROCESS_FreePDB( pdb );
489 /***********************************************************************
490 * ExitProcess (KERNEL32.100)
492 void WINAPI ExitProcess( DWORD status )
494 PDB32 *pdb = PROCESS_Current();
495 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
496 if ( pTask ) pTask->nEvents++;
498 if ( pTask && pTask->thdb != THREAD_Current() )
499 ExitThread( status );
501 SYSTEM_LOCK();
502 /* FIXME: should kill all running threads of this process */
503 pdb->exit_code = status;
504 if (pdb->console) FreeConsole();
505 SYSTEM_UNLOCK();
507 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
508 TASK_KillCurrentTask( status );
512 /******************************************************************************
513 * TerminateProcess (KERNEL32.684)
515 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
517 struct terminate_process_request req;
519 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
520 K32OBJ_PROCESS, PROCESS_TERMINATE );
521 req.exit_code = exit_code;
522 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
523 return !CLIENT_WaitReply( NULL, NULL, 0 );
526 /***********************************************************************
527 * GetCurrentProcess (KERNEL32.198)
529 HANDLE32 WINAPI GetCurrentProcess(void)
531 return CURRENT_PROCESS_PSEUDOHANDLE;
535 /*********************************************************************
536 * OpenProcess (KERNEL32.543)
538 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
540 int server_handle;
541 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
542 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
544 SetLastError( ERROR_INVALID_HANDLE );
545 return 0;
547 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
549 SetLastError( ERROR_INVALID_HANDLE );
550 return 0;
552 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
553 inherit, server_handle );
557 /***********************************************************************
558 * GetCurrentProcessId (KERNEL32.199)
560 DWORD WINAPI GetCurrentProcessId(void)
562 PDB32 *pdb = PROCESS_Current();
563 return PDB_TO_PROCESS_ID( pdb );
567 /***********************************************************************
568 * GetProcessHeap (KERNEL32.259)
570 HANDLE32 WINAPI GetProcessHeap(void)
572 PDB32 *pdb = PROCESS_Current();
573 return pdb->heap ? pdb->heap : SystemHeap;
577 /***********************************************************************
578 * GetThreadLocale (KERNEL32.295)
580 LCID WINAPI GetThreadLocale(void)
582 return PROCESS_Current()->locale;
586 /***********************************************************************
587 * SetPriorityClass (KERNEL32.503)
589 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
591 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
592 if (!pdb) return FALSE;
593 switch (priorityclass)
595 case NORMAL_PRIORITY_CLASS:
596 pdb->priority = 0x00000008;
597 break;
598 case IDLE_PRIORITY_CLASS:
599 pdb->priority = 0x00000004;
600 break;
601 case HIGH_PRIORITY_CLASS:
602 pdb->priority = 0x0000000d;
603 break;
604 case REALTIME_PRIORITY_CLASS:
605 pdb->priority = 0x00000018;
606 break;
607 default:
608 WARN(process,"Unknown priority class %ld\n",priorityclass);
609 break;
611 K32OBJ_DecCount( &pdb->header );
612 return TRUE;
616 /***********************************************************************
617 * GetPriorityClass (KERNEL32.250)
619 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
621 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
622 DWORD ret = 0;
623 if (pdb)
625 switch (pdb->priority)
627 case 0x00000008:
628 ret = NORMAL_PRIORITY_CLASS;
629 break;
630 case 0x00000004:
631 ret = IDLE_PRIORITY_CLASS;
632 break;
633 case 0x0000000d:
634 ret = HIGH_PRIORITY_CLASS;
635 break;
636 case 0x00000018:
637 ret = REALTIME_PRIORITY_CLASS;
638 break;
639 default:
640 WARN(process,"Unknown priority %ld\n",pdb->priority);
642 K32OBJ_DecCount( &pdb->header );
644 return ret;
648 /***********************************************************************
649 * GetStdHandle (KERNEL32.276)
651 * FIXME: These should be allocated when a console is created, or inherited
652 * from the parent.
654 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
656 HFILE32 hFile;
657 int fd;
658 PDB32 *pdb = PROCESS_Current();
660 switch(std_handle)
662 case STD_INPUT_HANDLE:
663 if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
664 fd = 0;
665 break;
666 case STD_OUTPUT_HANDLE:
667 if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
668 fd = 1;
669 break;
670 case STD_ERROR_HANDLE:
671 if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
672 fd = 2;
673 break;
674 default:
675 SetLastError( ERROR_INVALID_PARAMETER );
676 return INVALID_HANDLE_VALUE32;
678 hFile = FILE_DupUnixHandle( fd );
679 if (hFile != HFILE_ERROR32)
681 FILE_SetFileType( hFile, FILE_TYPE_CHAR );
682 switch(std_handle)
684 case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
685 case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
686 case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
689 return hFile;
693 /***********************************************************************
694 * SetStdHandle (KERNEL32.506)
696 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
698 PDB32 *pdb = PROCESS_Current();
699 /* FIXME: should we close the previous handle? */
700 switch(std_handle)
702 case STD_INPUT_HANDLE:
703 pdb->env_db->hStdin = handle;
704 return TRUE;
705 case STD_OUTPUT_HANDLE:
706 pdb->env_db->hStdout = handle;
707 return TRUE;
708 case STD_ERROR_HANDLE:
709 pdb->env_db->hStderr = handle;
710 return TRUE;
712 SetLastError( ERROR_INVALID_PARAMETER );
713 return FALSE;
716 /***********************************************************************
717 * GetProcessVersion (KERNEL32)
719 DWORD WINAPI GetProcessVersion( DWORD processid )
721 TDB *pTask;
722 PDB32 *pdb = PROCESS_IdToPDB( processid );
724 if (!pdb) return 0;
725 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
726 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
729 /***********************************************************************
730 * GetProcessFlags (KERNEL32)
732 DWORD WINAPI GetProcessFlags( DWORD processid )
734 PDB32 *pdb = PROCESS_IdToPDB( processid );
735 if (!pdb) return 0;
736 return pdb->flags;
739 /***********************************************************************
740 * SetProcessWorkingSetSize [KERNEL32.662]
741 * Sets the min/max working set sizes for a specified process.
743 * PARAMS
744 * hProcess [I] Handle to the process of interest
745 * minset [I] Specifies minimum working set size
746 * maxset [I] Specifies maximum working set size
748 * RETURNS STD
750 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
751 DWORD maxset)
753 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
754 if(( minset == -1) && (maxset == -1)) {
755 /* Trim the working set to zero */
756 /* Swap the process out of physical RAM */
758 return TRUE;
761 /***********************************************************************
762 * GetProcessWorkingSetSize (KERNEL32)
764 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
765 LPDWORD maxset)
767 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
768 /* 32 MB working set size */
769 if (minset) *minset = 32*1024*1024;
770 if (maxset) *maxset = 32*1024*1024;
771 return TRUE;
774 /***********************************************************************
775 * SetProcessShutdownParameters (KERNEL32)
777 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
778 * Now tracks changes made (but does not act on these changes)
779 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
780 * It really shouldn't be here, but I'll move it when it's been checked!
782 #define SHUTDOWN_NORETRY 1
783 static unsigned int shutdown_noretry = 0;
784 static unsigned int shutdown_priority = 0x280L;
785 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
787 if (flags & SHUTDOWN_NORETRY)
788 shutdown_noretry = 1;
789 else
790 shutdown_noretry = 0;
791 if (level > 0x100L && level < 0x3FFL)
792 shutdown_priority = level;
793 else
795 ERR(process,"invalid priority level 0x%08lx\n", level);
796 return FALSE;
798 return TRUE;
802 /***********************************************************************
803 * GetProcessShutdownParameters (KERNEL32)
806 BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
807 LPDWORD lpdwFlags )
809 (*lpdwLevel) = shutdown_priority;
810 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
811 return TRUE;
813 /***********************************************************************
814 * SetProcessPriorityBoost (KERNEL32)
816 BOOL32 WINAPI SetProcessPriorityBoost(HANDLE32 hprocess,BOOL32 disableboost)
818 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
819 /* Say we can do it. I doubt the program will notice that we don't. */
820 return TRUE;
823 /***********************************************************************
824 * ReadProcessMemory (KERNEL32)
825 * FIXME: check this, if we ever run win32 binaries in different addressspaces
826 * ... and add a sizecheck
828 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
829 LPVOID lpBuffer, DWORD nSize,
830 LPDWORD lpNumberOfBytesRead )
832 memcpy(lpBuffer,lpBaseAddress,nSize);
833 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
834 return TRUE;
837 /***********************************************************************
838 * WriteProcessMemory (KERNEL32)
839 * FIXME: check this, if we ever run win32 binaries in different addressspaces
840 * ... and add a sizecheck
842 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
843 LPVOID lpBuffer, DWORD nSize,
844 LPDWORD lpNumberOfBytesWritten )
846 memcpy(lpBaseAddress,lpBuffer,nSize);
847 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
848 return TRUE;
851 /***********************************************************************
852 * RegisterServiceProcess (KERNEL, KERNEL32)
854 * A service process calls this function to ensure that it continues to run
855 * even after a user logged off.
857 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
859 /* I don't think that Wine needs to do anything in that function */
860 return 1; /* success */
863 /***********************************************************************
864 * GetExitCodeProcess [KERNEL32.325]
866 * Gets termination status of specified process
868 * RETURNS
869 * Success: TRUE
870 * Failure: FALSE
872 BOOL32 WINAPI GetExitCodeProcess(
873 HANDLE32 hProcess, /* [I] handle to the process */
874 LPDWORD lpExitCode) /* [O] address to receive termination status */
876 struct get_process_info_reply info;
877 int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
878 K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
880 if (CLIENT_GetProcessInfo( handle, &info )) return FALSE;
881 if (lpExitCode) *lpExitCode = info.exit_code;
882 return TRUE;
885 /***********************************************************************
886 * GetProcessHeaps [KERNEL32.376]
888 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
889 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
891 if (nrofheaps) {
892 heaps[0] = GetProcessHeap();
893 /* ... probably SystemHeap too ? */
894 return 1;
896 /* number of available heaps */
897 return 1;
900 /***********************************************************************
901 * PROCESS_SuspendOtherThreads
904 void PROCESS_SuspendOtherThreads(void)
906 PDB32 *pdb;
907 THREAD_ENTRY *entry;
909 SYSTEM_LOCK();
911 pdb = PROCESS_Current();
912 entry = pdb->thread_list->next;
913 for (;;)
915 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
917 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
918 &entry->thread->header,
919 THREAD_ALL_ACCESS, FALSE, -1 );
920 SuspendThread(handle);
921 CloseHandle(handle);
923 if (entry == pdb->thread_list) break;
924 entry = entry->next;
927 SYSTEM_UNLOCK();
930 /***********************************************************************
931 * PROCESS_ResumeOtherThreads
934 void PROCESS_ResumeOtherThreads(void)
936 PDB32 *pdb;
937 THREAD_ENTRY *entry;
939 SYSTEM_LOCK();
941 pdb = PROCESS_Current();
942 entry = pdb->thread_list->next;
943 for (;;)
945 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
947 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
948 &entry->thread->header,
949 THREAD_ALL_ACCESS, FALSE, -1 );
950 ResumeThread(handle);
951 CloseHandle(handle);
953 if (entry == pdb->thread_list) break;
954 entry = entry->next;
957 SYSTEM_UNLOCK();