Fixed typos.
[wine/wine64.git] / scheduler / process.c
blob41736ddecd9a773f5bd0dbf580feead6876a10fb
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 );
69 /***********************************************************************
70 * PROCESS_QueryInfo
72 * Retrieve information about a process
74 static BOOL32 PROCESS_QueryInfo( HANDLE32 handle,
75 struct get_process_info_reply *reply )
77 struct get_process_info_request req;
78 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
79 K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
80 CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
81 return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
84 /***********************************************************************
85 * PROCESS_IsCurrent
87 * Check if a handle is to the current process
89 BOOL32 PROCESS_IsCurrent( HANDLE32 handle )
91 struct get_process_info_reply reply;
92 return (PROCESS_QueryInfo( handle, &reply ) &&
93 (reply.pid == PROCESS_Current()->server_pid));
97 /***********************************************************************
98 * PROCESS_IdToPDB
100 * Convert a process id to a PDB, making sure it is valid.
102 PDB32 *PROCESS_IdToPDB( DWORD id )
104 PDB32 *pdb;
106 if (!id) return PROCESS_Current();
107 pdb = PROCESS_ID_TO_PDB( id );
108 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
110 SetLastError( ERROR_INVALID_PARAMETER );
111 return NULL;
113 return pdb;
118 /***********************************************************************
119 * PROCESS_BuildEnvDB
121 * Build the env DB for the initial process
123 static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
125 /* Allocate the env DB (FIXME: should not be on the system heap) */
127 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
128 return FALSE;
129 InitializeCriticalSection( &pdb->env_db->section );
131 /* Allocate startup info */
132 if (!(pdb->env_db->startup_info =
133 HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
134 return FALSE;
136 /* Allocate the standard handles */
138 pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
139 pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
140 pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
142 /* Build the command-line */
144 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
146 /* Build the environment strings */
148 return ENV_BuildEnvironment( pdb );
152 /***********************************************************************
153 * PROCESS_InheritEnvDB
155 static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
156 BOOL32 inherit_handles, STARTUPINFO32A *startup )
158 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
159 return FALSE;
160 InitializeCriticalSection( &pdb->env_db->section );
162 /* Copy the parent environment */
164 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
166 /* Copy the command line */
168 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
169 return FALSE;
171 /* Remember startup info */
172 if (!(pdb->env_db->startup_info =
173 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
174 return FALSE;
175 *pdb->env_db->startup_info = *startup;
177 /* Inherit the standard handles */
178 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
180 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
181 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
182 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
184 else if (inherit_handles)
186 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
187 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
188 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
190 /* else will be done later on in PROCESS_Create */
192 return TRUE;
195 /***********************************************************************
196 * PROCESS_PDBList_Insert
197 * Insert this PDB into the global PDB list
200 static void PROCESS_PDBList_Insert (PDB32 *pdb)
202 TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
203 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
205 SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
206 * I.e., could more than one process be
207 * created at once ?
209 if (PROCESS_PDBList == NULL)
211 PROCESS_PDBList = pdb;
212 pdb->list_next = NULL;
213 pdb->list_prev = NULL;
215 else
217 PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList;
218 if (first->list_prev) last = first->list_prev;
220 PROCESS_PDBList = pdb;
221 pdb->list_next = first;
222 pdb->list_prev = last;
223 last->list_next = pdb;
224 first->list_prev = pdb;
226 PROCESS_PDBList_Size ++;
227 SYSTEM_UNLOCK ();
230 /***********************************************************************
231 * PROCESS_PDBList_Remove
232 * Remove this PDB from the global PDB list
235 static void PROCESS_PDBList_Remove (PDB32 *pdb)
237 PDB32 *next = pdb->list_next, *prev = pdb->list_prev;
239 TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
240 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
242 SYSTEM_LOCK ();
244 if (prev == next)
246 next->list_prev = NULL;
247 next->list_next = NULL;
249 else
251 if (next) next->list_prev = prev;
252 if (prev) prev->list_next = next;
255 if (pdb == PROCESS_PDBList)
257 PROCESS_PDBList = next ? next : prev;
259 PROCESS_PDBList_Size --;
261 SYSTEM_UNLOCK ();
264 /***********************************************************************
265 * PROCESS_PDBList_Getsize
266 * Return the number of items in the global PDB list
269 int PROCESS_PDBList_Getsize ()
271 return PROCESS_PDBList_Size;
274 /***********************************************************************
275 * PROCESS_PDBList_Getfirst
276 * Return the head of the PDB list
279 PDB32* PROCESS_PDBList_Getfirst ()
281 return PROCESS_PDBList;
284 /***********************************************************************
285 * PROCESS_PDBList_Getnext
286 * Return the "next" pdb as referenced from the argument.
287 * If at the end of the list, return NULL.
290 PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb)
292 return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
295 /***********************************************************************
296 * PROCESS_FreePDB
298 * Free a PDB and all associated storage.
300 static void PROCESS_FreePDB( PDB32 *pdb )
303 * FIXME:
304 * If this routine is called because PROCESS_CreatePDB fails, the
305 * following call to PROCESS_PDBList_Remove will probably screw
306 * up.
308 PROCESS_PDBList_Remove (pdb);
309 pdb->header.type = K32OBJ_UNKNOWN;
310 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
311 ENV_FreeEnvironment( pdb );
312 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
313 DeleteCriticalSection( &pdb->crit_section );
314 HeapFree( SystemHeap, 0, pdb );
318 /***********************************************************************
319 * PROCESS_CreatePDB
321 * Allocate and fill a PDB structure.
322 * Runs in the context of the parent process.
324 static PDB32 *PROCESS_CreatePDB( PDB32 *parent, BOOL32 inherit )
326 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
328 if (!pdb) return NULL;
329 pdb->header.type = K32OBJ_PROCESS;
330 pdb->header.refcount = 1;
331 pdb->exit_code = 0x103; /* STILL_ACTIVE */
332 pdb->threads = 1;
333 pdb->running_threads = 1;
334 pdb->ring0_threads = 1;
335 pdb->system_heap = SystemHeap;
336 pdb->parent = parent;
337 pdb->group = pdb;
338 pdb->priority = 8; /* Normal */
339 pdb->heap = pdb->system_heap; /* will be changed later on */
341 /* Create the handle table */
343 if (!HANDLE_CreateTable( pdb, inherit )) goto error;
345 PROCESS_PDBList_Insert (pdb);
346 return pdb;
348 error:
349 PROCESS_FreePDB( pdb );
350 return NULL;
354 /***********************************************************************
355 * PROCESS_FinishCreatePDB
357 * Second part of CreatePDB
359 static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
361 InitializeCriticalSection( &pdb->crit_section );
362 /* Allocate the event */
363 if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
364 return FALSE;
365 return TRUE;
369 /***********************************************************************
370 * PROCESS_Init
372 BOOL32 PROCESS_Init(void)
374 PDB32 *pdb;
375 THDB *thdb;
377 /* Initialize virtual memory management */
378 if (!VIRTUAL_Init()) return FALSE;
380 /* Create the system heaps */
381 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
383 /* Create the initial process and thread structures */
384 if (!(pdb = PROCESS_CreatePDB( NULL, FALSE ))) return FALSE;
385 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
386 thdb->unix_pid = getpid();
388 PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
390 /* Remember TEB selector of initial process for emergency use */
391 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
393 /* Create the environment DB of the first process */
394 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
396 /* Initialize the first thread */
397 if (CLIENT_InitThread()) return FALSE;
398 if (!PROCESS_FinishCreatePDB( 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 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
413 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
414 BOOL32 inherit, STARTUPINFO32A *startup,
415 PROCESS_INFORMATION *info )
417 DWORD size, commit;
418 int server_thandle, server_phandle;
419 UINT32 cmdShow = 0;
420 THDB *thdb = NULL;
421 PDB32 *parent = PROCESS_Current();
422 PDB32 *pdb = PROCESS_CreatePDB( parent, inherit );
423 TDB *pTask;
425 if (!pdb) return NULL;
426 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
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_VALUE32)
459 goto error;
460 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
461 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
462 goto error;
463 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
464 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
466 #if 0
467 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
468 #else
469 /* All Win16 'threads' have the same unix_pid, no matter by which thread
470 they were created ! */
471 pTask = (TDB *)GlobalLock16( parent->task );
472 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
473 #endif
475 /* Duplicate the standard handles */
477 if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
479 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
480 info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
481 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
482 info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
483 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
484 info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
487 /* Create a Win16 task for this process */
489 if (startup->dwFlags & STARTF_USESHOWWINDOW)
490 cmdShow = startup->wShowWindow;
492 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
493 if (!pdb->task) goto error;
496 /* Map system DLLs into this process (from initial process) */
497 /* FIXME: this is a hack */
498 pdb->modref_list = PROCESS_Initial()->modref_list;
501 return pdb;
503 error:
504 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
505 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
506 if (thdb) K32OBJ_DecCount( &thdb->header );
507 PROCESS_FreePDB( pdb );
508 return NULL;
512 /***********************************************************************
513 * PROCESS_Destroy
515 static void PROCESS_Destroy( K32OBJ *ptr )
517 PDB32 *pdb = (PDB32 *)ptr;
518 assert( ptr->type == K32OBJ_PROCESS );
520 /* Free everything */
522 ptr->type = K32OBJ_UNKNOWN;
523 PROCESS_FreePDB( pdb );
527 /***********************************************************************
528 * ExitProcess (KERNEL32.100)
530 void WINAPI ExitProcess( DWORD status )
532 PDB32 *pdb = PROCESS_Current();
533 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
534 if ( pTask ) pTask->nEvents++;
536 if ( pTask && pTask->thdb != THREAD_Current() )
537 ExitThread( status );
539 SYSTEM_LOCK();
540 /* FIXME: should kill all running threads of this process */
541 pdb->exit_code = status;
542 if (pdb->console) FreeConsole();
543 SYSTEM_UNLOCK();
545 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
546 TASK_KillCurrentTask( status );
550 /******************************************************************************
551 * TerminateProcess (KERNEL32.684)
553 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
555 struct terminate_process_request req;
557 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
558 K32OBJ_PROCESS, PROCESS_TERMINATE );
559 req.exit_code = exit_code;
560 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
561 return !CLIENT_WaitReply( NULL, NULL, 0 );
564 /***********************************************************************
565 * GetCurrentProcess (KERNEL32.198)
567 HANDLE32 WINAPI GetCurrentProcess(void)
569 return CURRENT_PROCESS_PSEUDOHANDLE;
573 /*********************************************************************
574 * OpenProcess (KERNEL32.543)
576 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
578 int server_handle;
579 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
580 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
582 SetLastError( ERROR_INVALID_HANDLE );
583 return 0;
585 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
587 SetLastError( ERROR_INVALID_HANDLE );
588 return 0;
590 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
591 inherit, server_handle );
595 /***********************************************************************
596 * GetCurrentProcessId (KERNEL32.199)
598 DWORD WINAPI GetCurrentProcessId(void)
600 PDB32 *pdb = PROCESS_Current();
601 return PDB_TO_PROCESS_ID( pdb );
605 /***********************************************************************
606 * GetProcessHeap (KERNEL32.259)
608 HANDLE32 WINAPI GetProcessHeap(void)
610 PDB32 *pdb = PROCESS_Current();
611 return pdb->heap ? pdb->heap : SystemHeap;
615 /***********************************************************************
616 * GetThreadLocale (KERNEL32.295)
618 LCID WINAPI GetThreadLocale(void)
620 return PROCESS_Current()->locale;
624 /***********************************************************************
625 * SetPriorityClass (KERNEL32.503)
627 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
629 struct set_process_info_request req;
630 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
631 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
632 if (req.handle == -1) return FALSE;
633 req.priority = priorityclass;
634 req.mask = SET_PROCESS_INFO_PRIORITY;
635 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
636 return !CLIENT_WaitReply( NULL, NULL, 0 );
640 /***********************************************************************
641 * GetPriorityClass (KERNEL32.250)
643 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
645 struct get_process_info_reply reply;
646 if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
647 return reply.priority;
651 /***********************************************************************
652 * SetProcessAffinityMask (KERNEL32.662)
654 BOOL32 WINAPI SetProcessAffinityMask( HANDLE32 hProcess, DWORD affmask )
656 struct set_process_info_request req;
657 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
658 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
659 if (req.handle == -1) return FALSE;
660 req.affinity = affmask;
661 req.mask = SET_PROCESS_INFO_AFFINITY;
662 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
663 return !CLIENT_WaitReply( NULL, NULL, 0 );
666 /**********************************************************************
667 * GetProcessAffinityMask (KERNEL32.373)
669 BOOL32 WINAPI GetProcessAffinityMask( HANDLE32 hProcess,
670 LPDWORD lpProcessAffinityMask,
671 LPDWORD lpSystemAffinityMask )
673 struct get_process_info_reply reply;
674 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
675 if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
676 if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
677 return TRUE;
681 /***********************************************************************
682 * GetStdHandle (KERNEL32.276)
684 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
686 PDB32 *pdb = PROCESS_Current();
688 switch(std_handle)
690 case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
691 case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
692 case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
694 SetLastError( ERROR_INVALID_PARAMETER );
695 return INVALID_HANDLE_VALUE32;
699 /***********************************************************************
700 * SetStdHandle (KERNEL32.506)
702 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
704 PDB32 *pdb = PROCESS_Current();
705 /* FIXME: should we close the previous handle? */
706 switch(std_handle)
708 case STD_INPUT_HANDLE:
709 pdb->env_db->hStdin = handle;
710 return TRUE;
711 case STD_OUTPUT_HANDLE:
712 pdb->env_db->hStdout = handle;
713 return TRUE;
714 case STD_ERROR_HANDLE:
715 pdb->env_db->hStderr = handle;
716 return TRUE;
718 SetLastError( ERROR_INVALID_PARAMETER );
719 return FALSE;
722 /***********************************************************************
723 * GetProcessVersion (KERNEL32)
725 DWORD WINAPI GetProcessVersion( DWORD processid )
727 TDB *pTask;
728 PDB32 *pdb = PROCESS_IdToPDB( processid );
730 if (!pdb) return 0;
731 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
732 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
735 /***********************************************************************
736 * GetProcessFlags (KERNEL32)
738 DWORD WINAPI GetProcessFlags( DWORD processid )
740 PDB32 *pdb = PROCESS_IdToPDB( processid );
741 if (!pdb) return 0;
742 return pdb->flags;
745 /***********************************************************************
746 * SetProcessWorkingSetSize [KERNEL32.662]
747 * Sets the min/max working set sizes for a specified process.
749 * PARAMS
750 * hProcess [I] Handle to the process of interest
751 * minset [I] Specifies minimum working set size
752 * maxset [I] Specifies maximum working set size
754 * RETURNS STD
756 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
757 DWORD maxset)
759 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
760 if(( minset == -1) && (maxset == -1)) {
761 /* Trim the working set to zero */
762 /* Swap the process out of physical RAM */
764 return TRUE;
767 /***********************************************************************
768 * GetProcessWorkingSetSize (KERNEL32)
770 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
771 LPDWORD maxset)
773 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
774 /* 32 MB working set size */
775 if (minset) *minset = 32*1024*1024;
776 if (maxset) *maxset = 32*1024*1024;
777 return TRUE;
780 /***********************************************************************
781 * SetProcessShutdownParameters (KERNEL32)
783 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
784 * Now tracks changes made (but does not act on these changes)
785 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
786 * It really shouldn't be here, but I'll move it when it's been checked!
788 #define SHUTDOWN_NORETRY 1
789 static unsigned int shutdown_noretry = 0;
790 static unsigned int shutdown_priority = 0x280L;
791 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
793 if (flags & SHUTDOWN_NORETRY)
794 shutdown_noretry = 1;
795 else
796 shutdown_noretry = 0;
797 if (level > 0x100L && level < 0x3FFL)
798 shutdown_priority = level;
799 else
801 ERR(process,"invalid priority level 0x%08lx\n", level);
802 return FALSE;
804 return TRUE;
808 /***********************************************************************
809 * GetProcessShutdownParameters (KERNEL32)
812 BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
813 LPDWORD lpdwFlags )
815 (*lpdwLevel) = shutdown_priority;
816 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
817 return TRUE;
819 /***********************************************************************
820 * SetProcessPriorityBoost (KERNEL32)
822 BOOL32 WINAPI SetProcessPriorityBoost(HANDLE32 hprocess,BOOL32 disableboost)
824 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
825 /* Say we can do it. I doubt the program will notice that we don't. */
826 return TRUE;
829 /***********************************************************************
830 * ReadProcessMemory (KERNEL32)
831 * FIXME: check this, if we ever run win32 binaries in different addressspaces
832 * ... and add a sizecheck
834 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
835 LPVOID lpBuffer, DWORD nSize,
836 LPDWORD lpNumberOfBytesRead )
838 memcpy(lpBuffer,lpBaseAddress,nSize);
839 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
840 return TRUE;
843 /***********************************************************************
844 * WriteProcessMemory (KERNEL32)
845 * FIXME: check this, if we ever run win32 binaries in different addressspaces
846 * ... and add a sizecheck
848 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
849 LPVOID lpBuffer, DWORD nSize,
850 LPDWORD lpNumberOfBytesWritten )
852 memcpy(lpBaseAddress,lpBuffer,nSize);
853 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
854 return TRUE;
857 /***********************************************************************
858 * RegisterServiceProcess (KERNEL, KERNEL32)
860 * A service process calls this function to ensure that it continues to run
861 * even after a user logged off.
863 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
865 /* I don't think that Wine needs to do anything in that function */
866 return 1; /* success */
869 /***********************************************************************
870 * GetExitCodeProcess [KERNEL32.325]
872 * Gets termination status of specified process
874 * RETURNS
875 * Success: TRUE
876 * Failure: FALSE
878 BOOL32 WINAPI GetExitCodeProcess(
879 HANDLE32 hProcess, /* [I] handle to the process */
880 LPDWORD lpExitCode) /* [O] address to receive termination status */
882 struct get_process_info_reply reply;
883 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
884 if (lpExitCode) *lpExitCode = reply.exit_code;
885 return TRUE;
889 /***********************************************************************
890 * GetProcessHeaps [KERNEL32.376]
892 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
893 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
895 if (nrofheaps) {
896 heaps[0] = GetProcessHeap();
897 /* ... probably SystemHeap too ? */
898 return 1;
900 /* number of available heaps */
901 return 1;
904 /***********************************************************************
905 * PROCESS_SuspendOtherThreads
908 void PROCESS_SuspendOtherThreads(void)
910 PDB32 *pdb;
911 THREAD_ENTRY *entry;
913 SYSTEM_LOCK();
915 pdb = PROCESS_Current();
916 entry = pdb->thread_list->next;
917 for (;;)
919 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
921 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
922 &entry->thread->header,
923 THREAD_ALL_ACCESS, FALSE, -1 );
924 SuspendThread(handle);
925 CloseHandle(handle);
927 if (entry == pdb->thread_list) break;
928 entry = entry->next;
931 SYSTEM_UNLOCK();
934 /***********************************************************************
935 * PROCESS_ResumeOtherThreads
938 void PROCESS_ResumeOtherThreads(void)
940 PDB32 *pdb;
941 THREAD_ENTRY *entry;
943 SYSTEM_LOCK();
945 pdb = PROCESS_Current();
946 entry = pdb->thread_list->next;
947 for (;;)
949 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
951 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
952 &entry->thread->header,
953 THREAD_ALL_ACCESS, FALSE, -1 );
954 ResumeThread(handle);
955 CloseHandle(handle);
957 if (entry == pdb->thread_list) break;
958 entry = entry->next;
961 SYSTEM_UNLOCK();