Add some information to the man page and README file.
[wine/multimedia.git] / scheduler / process.c
blobe05f010a6573bb7b8638a74c1d1867f422d5e037
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 BOOL32 inherit_handles, 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 if (inherit_handles)
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;
166 /* else will be done later on in PROCESS_Create */
168 return TRUE;
171 /***********************************************************************
172 * PROCESS_PDBList_Insert
173 * Insert this PDB into the global PDB list
176 static void PROCESS_PDBList_Insert (PDB32 *pdb)
178 TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
179 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
181 SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
182 * I.e., could more than one process be
183 * created at once ?
185 if (PROCESS_PDBList == NULL)
187 PROCESS_PDBList = pdb;
188 pdb->list_next = NULL;
189 pdb->list_prev = NULL;
191 else
193 PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList;
194 if (first->list_prev) last = first->list_prev;
196 PROCESS_PDBList = pdb;
197 pdb->list_next = first;
198 pdb->list_prev = last;
199 last->list_next = pdb;
200 first->list_prev = pdb;
202 PROCESS_PDBList_Size ++;
203 SYSTEM_UNLOCK ();
206 /***********************************************************************
207 * PROCESS_PDBList_Remove
208 * Remove this PDB from the global PDB list
211 static void PROCESS_PDBList_Remove (PDB32 *pdb)
213 PDB32 *next = pdb->list_next, *prev = pdb->list_prev;
215 TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
216 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
218 SYSTEM_LOCK ();
220 if (prev == next)
222 next->list_prev = NULL;
223 next->list_next = NULL;
225 else
227 if (next) next->list_prev = prev;
228 if (prev) prev->list_next = next;
231 if (pdb == PROCESS_PDBList)
233 PROCESS_PDBList = next ? next : prev;
235 PROCESS_PDBList_Size --;
237 SYSTEM_UNLOCK ();
240 /***********************************************************************
241 * PROCESS_PDBList_Getsize
242 * Return the number of items in the global PDB list
245 int PROCESS_PDBList_Getsize ()
247 return PROCESS_PDBList_Size;
250 /***********************************************************************
251 * PROCESS_PDBList_Getfirst
252 * Return the head of the PDB list
255 PDB32* PROCESS_PDBList_Getfirst ()
257 return PROCESS_PDBList;
260 /***********************************************************************
261 * PROCESS_PDBList_Getnext
262 * Return the "next" pdb as referenced from the argument.
263 * If at the end of the list, return NULL.
266 PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb)
268 return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
271 /***********************************************************************
272 * PROCESS_FreePDB
274 * Free a PDB and all associated storage.
276 static void PROCESS_FreePDB( PDB32 *pdb )
279 * FIXME:
280 * If this routine is called because PROCESS_CreatePDB fails, the
281 * following call to PROCESS_PDBList_Remove will probably screw
282 * up.
284 PROCESS_PDBList_Remove (pdb);
285 pdb->header.type = K32OBJ_UNKNOWN;
286 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
287 ENV_FreeEnvironment( pdb );
288 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
289 DeleteCriticalSection( &pdb->crit_section );
290 HeapFree( SystemHeap, 0, pdb );
294 /***********************************************************************
295 * PROCESS_CreatePDB
297 * Allocate and fill a PDB structure.
298 * Runs in the context of the parent process.
300 static PDB32 *PROCESS_CreatePDB( PDB32 *parent, BOOL32 inherit )
302 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
304 if (!pdb) return NULL;
305 pdb->header.type = K32OBJ_PROCESS;
306 pdb->header.refcount = 1;
307 pdb->exit_code = 0x103; /* STILL_ACTIVE */
308 pdb->threads = 1;
309 pdb->running_threads = 1;
310 pdb->ring0_threads = 1;
311 pdb->system_heap = SystemHeap;
312 pdb->parent = parent;
313 pdb->group = pdb;
314 pdb->priority = 8; /* Normal */
315 pdb->heap = pdb->system_heap; /* will be changed later on */
317 /* Create the handle table */
319 if (!HANDLE_CreateTable( pdb, inherit )) goto error;
321 PROCESS_PDBList_Insert (pdb);
322 return pdb;
324 error:
325 PROCESS_FreePDB( pdb );
326 return NULL;
330 /***********************************************************************
331 * PROCESS_FinishCreatePDB
333 * Second part of CreatePDB
335 static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
337 InitializeCriticalSection( &pdb->crit_section );
338 /* Allocate the event */
339 if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
340 return FALSE;
341 return TRUE;
345 /***********************************************************************
346 * PROCESS_Init
348 BOOL32 PROCESS_Init(void)
350 PDB32 *pdb;
351 THDB *thdb;
353 /* Initialize virtual memory management */
354 if (!VIRTUAL_Init()) return FALSE;
356 /* Create the system heaps */
357 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
359 /* Create the initial process and thread structures */
360 if (!(pdb = PROCESS_CreatePDB( NULL, FALSE ))) return FALSE;
361 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
362 thdb->unix_pid = getpid();
364 PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
366 /* Remember TEB selector of initial process for emergency use */
367 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
369 /* Create the environment DB of the first process */
370 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
372 /* Initialize the first thread */
373 if (CLIENT_InitThread()) return FALSE;
374 if (!PROCESS_FinishCreatePDB( pdb )) return FALSE;
376 /* Create the SEGPTR heap */
377 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
379 return TRUE;
383 /***********************************************************************
384 * PROCESS_Create
386 * Create a new process database and associated info.
388 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
389 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
390 BOOL32 inherit, STARTUPINFO32A *startup,
391 PROCESS_INFORMATION *info )
393 DWORD size, commit;
394 int server_thandle, server_phandle;
395 UINT32 cmdShow = 0;
396 THDB *thdb = NULL;
397 PDB32 *parent = PROCESS_Current();
398 PDB32 *pdb = PROCESS_CreatePDB( parent, inherit );
399 TDB *pTask;
401 if (!pdb) return NULL;
402 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
403 if (!PROCESS_FinishCreatePDB( pdb )) goto error;
405 /* Create the heap */
407 if (pModule->module32)
409 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
410 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
412 else
414 size = 0x10000;
415 commit = 0;
416 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
418 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
419 pdb->heap_list = pdb->heap;
421 /* Inherit the env DB from the parent */
423 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
425 /* Create the main thread */
427 if (pModule->module32)
428 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
429 else
430 size = 0;
431 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
432 NULL, NULL ))) goto error;
433 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
434 FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
435 goto error;
436 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
437 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
438 goto error;
439 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
440 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
442 #if 0
443 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
444 #else
445 /* All Win16 'threads' have the same unix_pid, no matter by which thread
446 they were created ! */
447 pTask = (TDB *)GlobalLock16( parent->task );
448 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
449 #endif
451 /* Duplicate the standard handles */
453 if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
455 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
456 info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
457 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
458 info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
459 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
460 info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
463 /* Create a Win16 task for this process */
465 if (startup->dwFlags & STARTF_USESHOWWINDOW)
466 cmdShow = startup->wShowWindow;
468 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
469 if (!pdb->task) goto error;
472 /* Map system DLLs into this process (from initial process) */
473 /* FIXME: this is a hack */
474 pdb->modref_list = PROCESS_Initial()->modref_list;
477 return pdb;
479 error:
480 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
481 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
482 if (thdb) K32OBJ_DecCount( &thdb->header );
483 PROCESS_FreePDB( pdb );
484 return NULL;
488 /***********************************************************************
489 * PROCESS_Destroy
491 static void PROCESS_Destroy( K32OBJ *ptr )
493 PDB32 *pdb = (PDB32 *)ptr;
494 assert( ptr->type == K32OBJ_PROCESS );
496 /* Free everything */
498 ptr->type = K32OBJ_UNKNOWN;
499 PROCESS_FreePDB( pdb );
503 /***********************************************************************
504 * ExitProcess (KERNEL32.100)
506 void WINAPI ExitProcess( DWORD status )
508 PDB32 *pdb = PROCESS_Current();
509 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
510 if ( pTask ) pTask->nEvents++;
512 if ( pTask && pTask->thdb != THREAD_Current() )
513 ExitThread( status );
515 SYSTEM_LOCK();
516 /* FIXME: should kill all running threads of this process */
517 pdb->exit_code = status;
518 if (pdb->console) FreeConsole();
519 SYSTEM_UNLOCK();
521 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
522 TASK_KillCurrentTask( status );
526 /******************************************************************************
527 * TerminateProcess (KERNEL32.684)
529 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
531 struct terminate_process_request req;
533 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
534 K32OBJ_PROCESS, PROCESS_TERMINATE );
535 req.exit_code = exit_code;
536 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
537 return !CLIENT_WaitReply( NULL, NULL, 0 );
540 /***********************************************************************
541 * GetCurrentProcess (KERNEL32.198)
543 HANDLE32 WINAPI GetCurrentProcess(void)
545 return CURRENT_PROCESS_PSEUDOHANDLE;
549 /*********************************************************************
550 * OpenProcess (KERNEL32.543)
552 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
554 int server_handle;
555 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
556 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
558 SetLastError( ERROR_INVALID_HANDLE );
559 return 0;
561 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
563 SetLastError( ERROR_INVALID_HANDLE );
564 return 0;
566 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
567 inherit, server_handle );
571 /***********************************************************************
572 * GetCurrentProcessId (KERNEL32.199)
574 DWORD WINAPI GetCurrentProcessId(void)
576 PDB32 *pdb = PROCESS_Current();
577 return PDB_TO_PROCESS_ID( pdb );
581 /***********************************************************************
582 * GetProcessHeap (KERNEL32.259)
584 HANDLE32 WINAPI GetProcessHeap(void)
586 PDB32 *pdb = PROCESS_Current();
587 return pdb->heap ? pdb->heap : SystemHeap;
591 /***********************************************************************
592 * GetThreadLocale (KERNEL32.295)
594 LCID WINAPI GetThreadLocale(void)
596 return PROCESS_Current()->locale;
600 /***********************************************************************
601 * SetPriorityClass (KERNEL32.503)
603 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
605 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
606 if (!pdb) return FALSE;
607 switch (priorityclass)
609 case NORMAL_PRIORITY_CLASS:
610 pdb->priority = 0x00000008;
611 break;
612 case IDLE_PRIORITY_CLASS:
613 pdb->priority = 0x00000004;
614 break;
615 case HIGH_PRIORITY_CLASS:
616 pdb->priority = 0x0000000d;
617 break;
618 case REALTIME_PRIORITY_CLASS:
619 pdb->priority = 0x00000018;
620 break;
621 default:
622 WARN(process,"Unknown priority class %ld\n",priorityclass);
623 break;
625 K32OBJ_DecCount( &pdb->header );
626 return TRUE;
630 /***********************************************************************
631 * GetPriorityClass (KERNEL32.250)
633 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
635 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
636 DWORD ret = 0;
637 if (pdb)
639 switch (pdb->priority)
641 case 0x00000008:
642 ret = NORMAL_PRIORITY_CLASS;
643 break;
644 case 0x00000004:
645 ret = IDLE_PRIORITY_CLASS;
646 break;
647 case 0x0000000d:
648 ret = HIGH_PRIORITY_CLASS;
649 break;
650 case 0x00000018:
651 ret = REALTIME_PRIORITY_CLASS;
652 break;
653 default:
654 WARN(process,"Unknown priority %ld\n",pdb->priority);
656 K32OBJ_DecCount( &pdb->header );
658 return ret;
662 /***********************************************************************
663 * GetStdHandle (KERNEL32.276)
665 * FIXME: These should be allocated when a console is created, or inherited
666 * from the parent.
668 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
670 HFILE32 hFile;
671 int fd;
672 PDB32 *pdb = PROCESS_Current();
674 switch(std_handle)
676 case STD_INPUT_HANDLE:
677 if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
678 fd = 0;
679 break;
680 case STD_OUTPUT_HANDLE:
681 if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
682 fd = 1;
683 break;
684 case STD_ERROR_HANDLE:
685 if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
686 fd = 2;
687 break;
688 default:
689 SetLastError( ERROR_INVALID_PARAMETER );
690 return INVALID_HANDLE_VALUE32;
692 hFile = FILE_DupUnixHandle( fd );
693 if (hFile != HFILE_ERROR32)
695 FILE_SetFileType( hFile, FILE_TYPE_CHAR );
696 switch(std_handle)
698 case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
699 case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
700 case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
703 return hFile;
707 /***********************************************************************
708 * SetStdHandle (KERNEL32.506)
710 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
712 PDB32 *pdb = PROCESS_Current();
713 /* FIXME: should we close the previous handle? */
714 switch(std_handle)
716 case STD_INPUT_HANDLE:
717 pdb->env_db->hStdin = handle;
718 return TRUE;
719 case STD_OUTPUT_HANDLE:
720 pdb->env_db->hStdout = handle;
721 return TRUE;
722 case STD_ERROR_HANDLE:
723 pdb->env_db->hStderr = handle;
724 return TRUE;
726 SetLastError( ERROR_INVALID_PARAMETER );
727 return FALSE;
730 /***********************************************************************
731 * GetProcessVersion (KERNEL32)
733 DWORD WINAPI GetProcessVersion( DWORD processid )
735 TDB *pTask;
736 PDB32 *pdb = PROCESS_IdToPDB( processid );
738 if (!pdb) return 0;
739 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
740 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
743 /***********************************************************************
744 * GetProcessFlags (KERNEL32)
746 DWORD WINAPI GetProcessFlags( DWORD processid )
748 PDB32 *pdb = PROCESS_IdToPDB( processid );
749 if (!pdb) return 0;
750 return pdb->flags;
753 /***********************************************************************
754 * SetProcessWorkingSetSize [KERNEL32.662]
755 * Sets the min/max working set sizes for a specified process.
757 * PARAMS
758 * hProcess [I] Handle to the process of interest
759 * minset [I] Specifies minimum working set size
760 * maxset [I] Specifies maximum working set size
762 * RETURNS STD
764 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
765 DWORD maxset)
767 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
768 if(( minset == -1) && (maxset == -1)) {
769 /* Trim the working set to zero */
770 /* Swap the process out of physical RAM */
772 return TRUE;
775 /***********************************************************************
776 * GetProcessWorkingSetSize (KERNEL32)
778 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
779 LPDWORD maxset)
781 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
782 /* 32 MB working set size */
783 if (minset) *minset = 32*1024*1024;
784 if (maxset) *maxset = 32*1024*1024;
785 return TRUE;
788 /***********************************************************************
789 * SetProcessShutdownParameters (KERNEL32)
791 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
792 * Now tracks changes made (but does not act on these changes)
793 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
794 * It really shouldn't be here, but I'll move it when it's been checked!
796 #define SHUTDOWN_NORETRY 1
797 static unsigned int shutdown_noretry = 0;
798 static unsigned int shutdown_priority = 0x280L;
799 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
801 if (flags & SHUTDOWN_NORETRY)
802 shutdown_noretry = 1;
803 else
804 shutdown_noretry = 0;
805 if (level > 0x100L && level < 0x3FFL)
806 shutdown_priority = level;
807 else
809 ERR(process,"invalid priority level 0x%08lx\n", level);
810 return FALSE;
812 return TRUE;
816 /***********************************************************************
817 * GetProcessShutdownParameters (KERNEL32)
820 BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
821 LPDWORD lpdwFlags )
823 (*lpdwLevel) = shutdown_priority;
824 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
825 return TRUE;
827 /***********************************************************************
828 * SetProcessPriorityBoost (KERNEL32)
830 BOOL32 WINAPI SetProcessPriorityBoost(HANDLE32 hprocess,BOOL32 disableboost)
832 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
833 /* Say we can do it. I doubt the program will notice that we don't. */
834 return TRUE;
837 /***********************************************************************
838 * ReadProcessMemory (KERNEL32)
839 * FIXME: check this, if we ever run win32 binaries in different addressspaces
840 * ... and add a sizecheck
842 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
843 LPVOID lpBuffer, DWORD nSize,
844 LPDWORD lpNumberOfBytesRead )
846 memcpy(lpBuffer,lpBaseAddress,nSize);
847 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
848 return TRUE;
851 /***********************************************************************
852 * WriteProcessMemory (KERNEL32)
853 * FIXME: check this, if we ever run win32 binaries in different addressspaces
854 * ... and add a sizecheck
856 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
857 LPVOID lpBuffer, DWORD nSize,
858 LPDWORD lpNumberOfBytesWritten )
860 memcpy(lpBaseAddress,lpBuffer,nSize);
861 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
862 return TRUE;
865 /***********************************************************************
866 * RegisterServiceProcess (KERNEL, KERNEL32)
868 * A service process calls this function to ensure that it continues to run
869 * even after a user logged off.
871 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
873 /* I don't think that Wine needs to do anything in that function */
874 return 1; /* success */
877 /***********************************************************************
878 * GetExitCodeProcess [KERNEL32.325]
880 * Gets termination status of specified process
882 * RETURNS
883 * Success: TRUE
884 * Failure: FALSE
886 BOOL32 WINAPI GetExitCodeProcess(
887 HANDLE32 hProcess, /* [I] handle to the process */
888 LPDWORD lpExitCode) /* [O] address to receive termination status */
890 struct get_process_info_reply info;
891 int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
892 K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
894 if (CLIENT_GetProcessInfo( handle, &info )) return FALSE;
895 if (lpExitCode) *lpExitCode = info.exit_code;
896 return TRUE;
899 /***********************************************************************
900 * GetProcessHeaps [KERNEL32.376]
902 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
903 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
905 if (nrofheaps) {
906 heaps[0] = GetProcessHeap();
907 /* ... probably SystemHeap too ? */
908 return 1;
910 /* number of available heaps */
911 return 1;
914 /***********************************************************************
915 * PROCESS_SuspendOtherThreads
918 void PROCESS_SuspendOtherThreads(void)
920 PDB32 *pdb;
921 THREAD_ENTRY *entry;
923 SYSTEM_LOCK();
925 pdb = PROCESS_Current();
926 entry = pdb->thread_list->next;
927 for (;;)
929 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
931 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
932 &entry->thread->header,
933 THREAD_ALL_ACCESS, FALSE, -1 );
934 SuspendThread(handle);
935 CloseHandle(handle);
937 if (entry == pdb->thread_list) break;
938 entry = entry->next;
941 SYSTEM_UNLOCK();
944 /***********************************************************************
945 * PROCESS_ResumeOtherThreads
948 void PROCESS_ResumeOtherThreads(void)
950 PDB32 *pdb;
951 THREAD_ENTRY *entry;
953 SYSTEM_LOCK();
955 pdb = PROCESS_Current();
956 entry = pdb->thread_list->next;
957 for (;;)
959 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
961 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
962 &entry->thread->header,
963 THREAD_ALL_ACCESS, FALSE, -1 );
964 ResumeThread(handle);
965 CloseHandle(handle);
967 if (entry == pdb->thread_list) break;
968 entry = entry->next;
971 SYSTEM_UNLOCK();