Release 990226.
[wine/gsoc-2012-control.git] / scheduler / process.c
blobef903bd5e3df4a2df1f1e2f8d9df0023bc9c147b
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 "debug.h"
27 static void PROCESS_Destroy( K32OBJ *obj );
29 const K32OBJ_OPS PROCESS_Ops =
31 PROCESS_Destroy /* destroy */
34 /* The initial process PDB */
35 static PDB initial_pdb;
37 static PDB *PROCESS_PDBList = NULL;
38 static DWORD PROCESS_PDBList_Size = 0;
40 /***********************************************************************
41 * PROCESS_Current
43 PDB *PROCESS_Current(void)
45 return THREAD_Current()->process;
48 /***********************************************************************
49 * PROCESS_Initial
51 * FIXME: This works only while running all processes in the same
52 * address space (or, at least, the initial process is mapped
53 * into all address spaces as is KERNEL32 in Windows 95)
56 PDB *PROCESS_Initial(void)
58 return &initial_pdb;
61 /***********************************************************************
62 * PROCESS_QueryInfo
64 * Retrieve information about a process
66 static BOOL PROCESS_QueryInfo( HANDLE handle,
67 struct get_process_info_reply *reply )
69 struct get_process_info_request req;
70 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
71 K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
72 CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
73 return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
76 /***********************************************************************
77 * PROCESS_IsCurrent
79 * Check if a handle is to the current process
81 BOOL PROCESS_IsCurrent( HANDLE handle )
83 struct get_process_info_reply reply;
84 return (PROCESS_QueryInfo( handle, &reply ) &&
85 (reply.pid == PROCESS_Current()->server_pid));
89 /***********************************************************************
90 * PROCESS_IdToPDB
92 * Convert a process id to a PDB, making sure it is valid.
94 PDB *PROCESS_IdToPDB( DWORD id )
96 PDB *pdb;
98 if (!id) return PROCESS_Current();
99 pdb = PROCESS_ID_TO_PDB( id );
100 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
102 SetLastError( ERROR_INVALID_PARAMETER );
103 return NULL;
105 return pdb;
110 /***********************************************************************
111 * PROCESS_BuildEnvDB
113 * Build the env DB for the initial process
115 static BOOL PROCESS_BuildEnvDB( PDB *pdb )
117 /* Allocate the env DB (FIXME: should not be on the system heap) */
119 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
120 return FALSE;
121 InitializeCriticalSection( &pdb->env_db->section );
123 /* Allocate startup info */
124 if (!(pdb->env_db->startup_info =
125 HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
126 return FALSE;
128 /* Allocate the standard handles */
130 pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
131 pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
132 pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
134 /* Build the command-line */
136 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
138 /* Build the environment strings */
140 return ENV_BuildEnvironment( pdb );
144 /***********************************************************************
145 * PROCESS_InheritEnvDB
147 static BOOL PROCESS_InheritEnvDB( PDB *pdb, LPCSTR cmd_line, LPCSTR env,
148 BOOL inherit_handles, STARTUPINFOA *startup )
150 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
151 return FALSE;
152 InitializeCriticalSection( &pdb->env_db->section );
154 /* Copy the parent environment */
156 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
158 /* Copy the command line */
160 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
161 return FALSE;
163 /* Remember startup info */
164 if (!(pdb->env_db->startup_info =
165 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
166 return FALSE;
167 *pdb->env_db->startup_info = *startup;
169 /* Inherit the standard handles */
170 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
172 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
173 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
174 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
176 else if (inherit_handles)
178 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
179 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
180 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
182 /* else will be done later on in PROCESS_Create */
184 return TRUE;
187 /***********************************************************************
188 * PROCESS_PDBList_Insert
189 * Insert this PDB into the global PDB list
192 static void PROCESS_PDBList_Insert (PDB *pdb)
194 TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
195 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
197 SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
198 * I.e., could more than one process be
199 * created at once ?
201 if (PROCESS_PDBList == NULL)
203 PROCESS_PDBList = pdb;
204 pdb->list_next = NULL;
205 pdb->list_prev = NULL;
207 else
209 PDB *first = PROCESS_PDBList, *last = PROCESS_PDBList;
210 if (first->list_prev) last = first->list_prev;
212 PROCESS_PDBList = pdb;
213 pdb->list_next = first;
214 pdb->list_prev = last;
215 last->list_next = pdb;
216 first->list_prev = pdb;
218 PROCESS_PDBList_Size ++;
219 SYSTEM_UNLOCK ();
222 /***********************************************************************
223 * PROCESS_PDBList_Remove
224 * Remove this PDB from the global PDB list
227 static void PROCESS_PDBList_Remove (PDB *pdb)
229 PDB *next = pdb->list_next, *prev = pdb->list_prev;
231 TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
232 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
234 SYSTEM_LOCK ();
236 if (prev == next)
238 next->list_prev = NULL;
239 next->list_next = NULL;
241 else
243 if (next) next->list_prev = prev;
244 if (prev) prev->list_next = next;
247 if (pdb == PROCESS_PDBList)
249 PROCESS_PDBList = next ? next : prev;
251 PROCESS_PDBList_Size --;
253 SYSTEM_UNLOCK ();
256 /***********************************************************************
257 * PROCESS_PDBList_Getsize
258 * Return the number of items in the global PDB list
261 int PROCESS_PDBList_Getsize ()
263 return PROCESS_PDBList_Size;
266 /***********************************************************************
267 * PROCESS_PDBList_Getfirst
268 * Return the head of the PDB list
271 PDB* PROCESS_PDBList_Getfirst ()
273 return PROCESS_PDBList;
276 /***********************************************************************
277 * PROCESS_PDBList_Getnext
278 * Return the "next" pdb as referenced from the argument.
279 * If at the end of the list, return NULL.
282 PDB* PROCESS_PDBList_Getnext (PDB *pdb)
284 return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
287 /***********************************************************************
288 * PROCESS_FreePDB
290 * Free a PDB and all associated storage.
292 static void PROCESS_FreePDB( PDB *pdb )
295 * FIXME:
296 * If this routine is called because PROCESS_CreatePDB fails, the
297 * following call to PROCESS_PDBList_Remove will probably screw
298 * up.
300 PROCESS_PDBList_Remove (pdb);
301 pdb->header.type = K32OBJ_UNKNOWN;
302 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
303 ENV_FreeEnvironment( pdb );
304 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
305 DeleteCriticalSection( &pdb->crit_section );
306 HeapFree( SystemHeap, 0, pdb );
310 /***********************************************************************
311 * PROCESS_CreatePDB
313 * Allocate and fill a PDB structure.
314 * Runs in the context of the parent process.
316 static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
318 PDB *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB) );
320 if (!pdb) return NULL;
321 pdb->header.type = K32OBJ_PROCESS;
322 pdb->header.refcount = 1;
323 pdb->exit_code = 0x103; /* STILL_ACTIVE */
324 pdb->threads = 1;
325 pdb->running_threads = 1;
326 pdb->ring0_threads = 1;
327 pdb->system_heap = SystemHeap;
328 pdb->parent = parent;
329 pdb->group = pdb;
330 pdb->priority = 8; /* Normal */
331 pdb->heap = pdb->system_heap; /* will be changed later on */
333 /* Create the handle table */
335 if (!HANDLE_CreateTable( pdb, inherit )) goto error;
337 PROCESS_PDBList_Insert (pdb);
338 return pdb;
340 error:
341 PROCESS_FreePDB( pdb );
342 return NULL;
346 /***********************************************************************
347 * PROCESS_FinishCreatePDB
349 * Second part of CreatePDB
351 static BOOL PROCESS_FinishCreatePDB( PDB *pdb )
353 InitializeCriticalSection( &pdb->crit_section );
354 /* Allocate the event */
355 if (!(pdb->load_done_evt = CreateEventA( NULL, TRUE, FALSE, NULL )))
356 return FALSE;
357 return TRUE;
361 /***********************************************************************
362 * PROCESS_Init
364 BOOL PROCESS_Init(void)
366 THDB *thdb;
368 /* Fill the initial process structure */
369 initial_pdb.header.type = K32OBJ_PROCESS;
370 initial_pdb.header.refcount = 1;
371 initial_pdb.exit_code = 0x103; /* STILL_ACTIVE */
372 initial_pdb.threads = 1;
373 initial_pdb.running_threads = 1;
374 initial_pdb.ring0_threads = 1;
375 initial_pdb.group = &initial_pdb;
376 initial_pdb.priority = 8; /* Normal */
378 /* Initialize virtual memory management */
379 if (!VIRTUAL_Init()) return FALSE;
381 /* Create the system heap */
382 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
383 initial_pdb.system_heap = initial_pdb.heap = SystemHeap;
385 /* Create the initial process and thread structures */
386 if (!HANDLE_CreateTable( &initial_pdb, FALSE )) return FALSE;
387 if (!(thdb = THREAD_CreateInitialThread( &initial_pdb ))) return FALSE;
389 /* Remember TEB selector of initial process for emergency use */
390 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
392 /* Create the environment DB of the first process */
393 PROCESS_PDBList_Insert( &initial_pdb );
394 if (!PROCESS_BuildEnvDB( &initial_pdb )) return FALSE;
396 /* Initialize the first thread */
397 if (CLIENT_InitThread()) return FALSE;
398 if (!PROCESS_FinishCreatePDB( &initial_pdb )) return FALSE;
400 /* Create the SEGPTR heap */
401 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
403 return TRUE;
407 /***********************************************************************
408 * PROCESS_Create
410 * Create a new process database and associated info.
412 PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
413 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
414 BOOL inherit, STARTUPINFOA *startup,
415 PROCESS_INFORMATION *info )
417 DWORD size, commit;
418 int server_thandle, server_phandle;
419 UINT cmdShow = 0;
420 THDB *thdb = NULL;
421 PDB *parent = PROCESS_Current();
422 PDB *pdb = PROCESS_CreatePDB( parent, inherit );
423 TDB *pTask;
425 if (!pdb) return NULL;
426 info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
427 if (!PROCESS_FinishCreatePDB( pdb )) goto error;
429 /* Create the heap */
431 if (pModule->module32)
433 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
434 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
436 else
438 size = 0x10000;
439 commit = 0;
440 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
442 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
443 pdb->heap_list = pdb->heap;
445 /* Inherit the env DB from the parent */
447 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
449 /* Create the main thread */
451 if (pModule->module32)
452 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
453 else
454 size = 0;
455 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
456 NULL, NULL ))) goto error;
457 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
458 FALSE, server_thandle )) == INVALID_HANDLE_VALUE)
459 goto error;
460 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
461 FALSE, server_phandle )) == INVALID_HANDLE_VALUE)
462 goto error;
463 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
464 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
466 /* Duplicate the standard handles */
468 if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
470 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
471 info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
472 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
473 info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
474 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
475 info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
478 /* Create a Win16 task for this process */
480 if (startup->dwFlags & STARTF_USESHOWWINDOW)
481 cmdShow = startup->wShowWindow;
483 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
484 if (!pdb->task) goto error;
487 /* Map system DLLs into this process (from initial process) */
488 /* FIXME: this is a hack */
489 pdb->modref_list = PROCESS_Initial()->modref_list;
492 return pdb;
494 error:
495 if (info->hThread != INVALID_HANDLE_VALUE) CloseHandle( info->hThread );
496 if (info->hProcess != INVALID_HANDLE_VALUE) CloseHandle( info->hProcess );
497 if (thdb) K32OBJ_DecCount( &thdb->header );
498 PROCESS_FreePDB( pdb );
499 return NULL;
503 /***********************************************************************
504 * PROCESS_Destroy
506 static void PROCESS_Destroy( K32OBJ *ptr )
508 PDB *pdb = (PDB *)ptr;
509 assert( ptr->type == K32OBJ_PROCESS );
511 /* Free everything */
513 ptr->type = K32OBJ_UNKNOWN;
514 PROCESS_FreePDB( pdb );
518 /***********************************************************************
519 * ExitProcess (KERNEL32.100)
521 void WINAPI ExitProcess( DWORD status )
523 PDB *pdb = PROCESS_Current();
524 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
525 if ( pTask ) pTask->nEvents++;
527 if ( pTask && pTask->thdb != THREAD_Current() )
528 ExitThread( status );
530 SYSTEM_LOCK();
531 /* FIXME: should kill all running threads of this process */
532 pdb->exit_code = status;
533 if (pdb->console) FreeConsole();
534 SYSTEM_UNLOCK();
536 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
537 TASK_KillCurrentTask( status );
541 /******************************************************************************
542 * TerminateProcess (KERNEL32.684)
544 BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
546 struct terminate_process_request req;
548 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
549 K32OBJ_PROCESS, PROCESS_TERMINATE );
550 req.exit_code = exit_code;
551 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
552 return !CLIENT_WaitReply( NULL, NULL, 0 );
555 /***********************************************************************
556 * GetCurrentProcess (KERNEL32.198)
558 HANDLE WINAPI GetCurrentProcess(void)
560 return CURRENT_PROCESS_PSEUDOHANDLE;
564 /*********************************************************************
565 * OpenProcess (KERNEL32.543)
567 HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
569 int server_handle;
570 PDB *pdb = PROCESS_ID_TO_PDB(id);
571 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
573 SetLastError( ERROR_INVALID_HANDLE );
574 return 0;
576 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
578 SetLastError( ERROR_INVALID_HANDLE );
579 return 0;
581 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
582 inherit, server_handle );
586 /***********************************************************************
587 * GetCurrentProcessId (KERNEL32.199)
589 DWORD WINAPI GetCurrentProcessId(void)
591 PDB *pdb = PROCESS_Current();
592 return PDB_TO_PROCESS_ID( pdb );
596 /***********************************************************************
597 * GetProcessHeap (KERNEL32.259)
599 HANDLE WINAPI GetProcessHeap(void)
601 PDB *pdb = PROCESS_Current();
602 return pdb->heap ? pdb->heap : SystemHeap;
606 /***********************************************************************
607 * GetThreadLocale (KERNEL32.295)
609 LCID WINAPI GetThreadLocale(void)
611 return PROCESS_Current()->locale;
615 /***********************************************************************
616 * SetPriorityClass (KERNEL32.503)
618 BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
620 struct set_process_info_request req;
621 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
622 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
623 if (req.handle == -1) return FALSE;
624 req.priority = priorityclass;
625 req.mask = SET_PROCESS_INFO_PRIORITY;
626 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
627 return !CLIENT_WaitReply( NULL, NULL, 0 );
631 /***********************************************************************
632 * GetPriorityClass (KERNEL32.250)
634 DWORD WINAPI GetPriorityClass(HANDLE hprocess)
636 struct get_process_info_reply reply;
637 if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
638 return reply.priority;
642 /***********************************************************************
643 * SetProcessAffinityMask (KERNEL32.662)
645 BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
647 struct set_process_info_request req;
648 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
649 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
650 if (req.handle == -1) return FALSE;
651 req.affinity = affmask;
652 req.mask = SET_PROCESS_INFO_AFFINITY;
653 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
654 return !CLIENT_WaitReply( NULL, NULL, 0 );
657 /**********************************************************************
658 * GetProcessAffinityMask (KERNEL32.373)
660 BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
661 LPDWORD lpProcessAffinityMask,
662 LPDWORD lpSystemAffinityMask )
664 struct get_process_info_reply reply;
665 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
666 if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
667 if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
668 return TRUE;
672 /***********************************************************************
673 * GetStdHandle (KERNEL32.276)
675 HANDLE WINAPI GetStdHandle( DWORD std_handle )
677 PDB *pdb = PROCESS_Current();
679 switch(std_handle)
681 case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
682 case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
683 case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
685 SetLastError( ERROR_INVALID_PARAMETER );
686 return INVALID_HANDLE_VALUE;
690 /***********************************************************************
691 * SetStdHandle (KERNEL32.506)
693 BOOL WINAPI SetStdHandle( DWORD std_handle, HANDLE handle )
695 PDB *pdb = PROCESS_Current();
696 /* FIXME: should we close the previous handle? */
697 switch(std_handle)
699 case STD_INPUT_HANDLE:
700 pdb->env_db->hStdin = handle;
701 return TRUE;
702 case STD_OUTPUT_HANDLE:
703 pdb->env_db->hStdout = handle;
704 return TRUE;
705 case STD_ERROR_HANDLE:
706 pdb->env_db->hStderr = handle;
707 return TRUE;
709 SetLastError( ERROR_INVALID_PARAMETER );
710 return FALSE;
713 /***********************************************************************
714 * GetProcessVersion (KERNEL32)
716 DWORD WINAPI GetProcessVersion( DWORD processid )
718 TDB *pTask;
719 PDB *pdb = PROCESS_IdToPDB( processid );
721 if (!pdb) return 0;
722 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
723 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
726 /***********************************************************************
727 * GetProcessFlags (KERNEL32)
729 DWORD WINAPI GetProcessFlags( DWORD processid )
731 PDB *pdb = PROCESS_IdToPDB( processid );
732 if (!pdb) return 0;
733 return pdb->flags;
736 /***********************************************************************
737 * SetProcessWorkingSetSize [KERNEL32.662]
738 * Sets the min/max working set sizes for a specified process.
740 * PARAMS
741 * hProcess [I] Handle to the process of interest
742 * minset [I] Specifies minimum working set size
743 * maxset [I] Specifies maximum working set size
745 * RETURNS STD
747 BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess,DWORD minset,
748 DWORD maxset)
750 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
751 if(( minset == -1) && (maxset == -1)) {
752 /* Trim the working set to zero */
753 /* Swap the process out of physical RAM */
755 return TRUE;
758 /***********************************************************************
759 * GetProcessWorkingSetSize (KERNEL32)
761 BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess,LPDWORD minset,
762 LPDWORD maxset)
764 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
765 /* 32 MB working set size */
766 if (minset) *minset = 32*1024*1024;
767 if (maxset) *maxset = 32*1024*1024;
768 return TRUE;
771 /***********************************************************************
772 * SetProcessShutdownParameters (KERNEL32)
774 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
775 * Now tracks changes made (but does not act on these changes)
776 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
777 * It really shouldn't be here, but I'll move it when it's been checked!
779 #define SHUTDOWN_NORETRY 1
780 static unsigned int shutdown_noretry = 0;
781 static unsigned int shutdown_priority = 0x280L;
782 BOOL WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
784 if (flags & SHUTDOWN_NORETRY)
785 shutdown_noretry = 1;
786 else
787 shutdown_noretry = 0;
788 if (level > 0x100L && level < 0x3FFL)
789 shutdown_priority = level;
790 else
792 ERR(process,"invalid priority level 0x%08lx\n", level);
793 return FALSE;
795 return TRUE;
799 /***********************************************************************
800 * GetProcessShutdownParameters (KERNEL32)
803 BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
804 LPDWORD lpdwFlags )
806 (*lpdwLevel) = shutdown_priority;
807 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
808 return TRUE;
810 /***********************************************************************
811 * SetProcessPriorityBoost (KERNEL32)
813 BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
815 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
816 /* Say we can do it. I doubt the program will notice that we don't. */
817 return TRUE;
820 /***********************************************************************
821 * ReadProcessMemory (KERNEL32)
822 * FIXME: check this, if we ever run win32 binaries in different addressspaces
823 * ... and add a sizecheck
825 BOOL WINAPI ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress,
826 LPVOID lpBuffer, DWORD nSize,
827 LPDWORD lpNumberOfBytesRead )
829 memcpy(lpBuffer,lpBaseAddress,nSize);
830 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
831 return TRUE;
834 /***********************************************************************
835 * WriteProcessMemory (KERNEL32)
836 * FIXME: check this, if we ever run win32 binaries in different addressspaces
837 * ... and add a sizecheck
839 BOOL WINAPI WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress,
840 LPVOID lpBuffer, DWORD nSize,
841 LPDWORD lpNumberOfBytesWritten )
843 memcpy(lpBaseAddress,lpBuffer,nSize);
844 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
845 return TRUE;
848 /***********************************************************************
849 * RegisterServiceProcess (KERNEL, KERNEL32)
851 * A service process calls this function to ensure that it continues to run
852 * even after a user logged off.
854 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
856 /* I don't think that Wine needs to do anything in that function */
857 return 1; /* success */
860 /***********************************************************************
861 * GetExitCodeProcess [KERNEL32.325]
863 * Gets termination status of specified process
865 * RETURNS
866 * Success: TRUE
867 * Failure: FALSE
869 BOOL WINAPI GetExitCodeProcess(
870 HANDLE hProcess, /* [I] handle to the process */
871 LPDWORD lpExitCode) /* [O] address to receive termination status */
873 struct get_process_info_reply reply;
874 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
875 if (lpExitCode) *lpExitCode = reply.exit_code;
876 return TRUE;
880 /***********************************************************************
881 * GetProcessHeaps [KERNEL32.376]
883 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE *heaps) {
884 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
886 if (nrofheaps) {
887 heaps[0] = GetProcessHeap();
888 /* ... probably SystemHeap too ? */
889 return 1;
891 /* number of available heaps */
892 return 1;
895 /***********************************************************************
896 * PROCESS_SuspendOtherThreads
899 void PROCESS_SuspendOtherThreads(void)
901 #if 0
902 PDB *pdb;
903 THREAD_ENTRY *entry;
905 SYSTEM_LOCK();
907 pdb = PROCESS_Current();
908 entry = pdb->thread_list->next;
909 for (;;)
911 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
913 HANDLE handle = HANDLE_Alloc( PROCESS_Current(),
914 &entry->thread->header,
915 THREAD_ALL_ACCESS, FALSE, -1 );
916 SuspendThread(handle);
917 CloseHandle(handle);
919 if (entry == pdb->thread_list) break;
920 entry = entry->next;
923 SYSTEM_UNLOCK();
924 #endif
927 /***********************************************************************
928 * PROCESS_ResumeOtherThreads
931 void PROCESS_ResumeOtherThreads(void)
933 #if 0
934 PDB *pdb;
935 THREAD_ENTRY *entry;
937 SYSTEM_LOCK();
939 pdb = PROCESS_Current();
940 entry = pdb->thread_list->next;
941 for (;;)
943 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
945 HANDLE handle = HANDLE_Alloc( PROCESS_Current(),
946 &entry->thread->header,
947 THREAD_ALL_ACCESS, FALSE, -1 );
948 ResumeThread(handle);
949 CloseHandle(handle);
951 if (entry == pdb->thread_list) break;
952 entry = entry->next;
955 SYSTEM_UNLOCK();
956 #endif