4 * Copyright 1996, 1998 Alexandre Julliard
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 /***********************************************************************
40 PDB32
*PROCESS_Current(void)
42 return THREAD_Current()->process
;
45 /***********************************************************************
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 /***********************************************************************
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 /***********************************************************************
73 * Convert a process id to a PDB, making sure it is valid.
75 PDB32
*PROCESS_IdToPDB( DWORD id
)
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
);
91 /***********************************************************************
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
))))
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
) )))
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
))))
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
)))
147 /* Remember startup info */
148 if (!(pdb
->env_db
->startup_info
=
149 HeapAlloc( pdb
->heap
, HEAP_ZERO_MEMORY
, sizeof(STARTUPINFO32A
) )))
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 */
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
185 if (PROCESS_PDBList
== NULL
)
187 PROCESS_PDBList
= pdb
;
188 pdb
->list_next
= NULL
;
189 pdb
->list_prev
= NULL
;
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
++;
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
);
222 next
->list_prev
= NULL
;
223 next
->list_next
= NULL
;
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
--;
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 /***********************************************************************
274 * Free a PDB and all associated storage.
276 static void PROCESS_FreePDB( PDB32
*pdb
)
280 * If this routine is called because PROCESS_CreatePDB fails, the
281 * following call to PROCESS_PDBList_Remove will probably screw
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 /***********************************************************************
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 */
309 pdb
->running_threads
= 1;
310 pdb
->ring0_threads
= 1;
311 pdb
->system_heap
= SystemHeap
;
312 pdb
->parent
= parent
;
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
);
325 PROCESS_FreePDB( pdb
);
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
)))
345 /***********************************************************************
348 BOOL32
PROCESS_Init(void)
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
;
383 /***********************************************************************
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
)
394 int server_thandle
, server_phandle
;
397 PDB32
*parent
= PROCESS_Current();
398 PDB32
*pdb
= PROCESS_CreatePDB( parent
, inherit
);
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
;
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
;
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
)
436 if ((info
->hProcess
= HANDLE_Alloc( parent
, &pdb
->header
, PROCESS_ALL_ACCESS
,
437 FALSE
, server_phandle
)) == INVALID_HANDLE_VALUE32
)
439 info
->dwProcessId
= PDB_TO_PROCESS_ID(pdb
);
440 info
->dwThreadId
= THDB_TO_THREAD_ID(thdb
);
443 thdb
->unix_pid
= getpid(); /* FIXME: wrong here ... */
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
;
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
;
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
);
488 /***********************************************************************
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
);
516 /* FIXME: should kill all running threads of this process */
517 pdb
->exit_code
= status
;
518 if (pdb
->console
) FreeConsole();
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
)
555 PDB32
*pdb
= PROCESS_ID_TO_PDB(id
);
556 if (!K32OBJ_IsValid( &pdb
->header
, K32OBJ_PROCESS
))
558 SetLastError( ERROR_INVALID_HANDLE
);
561 if ((server_handle
= CLIENT_OpenProcess( pdb
->server_pid
, access
, inherit
)) == -1)
563 SetLastError( ERROR_INVALID_HANDLE
);
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;
612 case IDLE_PRIORITY_CLASS
:
613 pdb
->priority
= 0x00000004;
615 case HIGH_PRIORITY_CLASS
:
616 pdb
->priority
= 0x0000000d;
618 case REALTIME_PRIORITY_CLASS
:
619 pdb
->priority
= 0x00000018;
622 WARN(process
,"Unknown priority class %ld\n",priorityclass
);
625 K32OBJ_DecCount( &pdb
->header
);
630 /***********************************************************************
631 * GetPriorityClass (KERNEL32.250)
633 DWORD WINAPI
GetPriorityClass(HANDLE32 hprocess
)
635 PDB32
*pdb
= PROCESS_GetPtr( hprocess
, PROCESS_QUERY_INFORMATION
, NULL
);
639 switch (pdb
->priority
)
642 ret
= NORMAL_PRIORITY_CLASS
;
645 ret
= IDLE_PRIORITY_CLASS
;
648 ret
= HIGH_PRIORITY_CLASS
;
651 ret
= REALTIME_PRIORITY_CLASS
;
654 WARN(process
,"Unknown priority %ld\n",pdb
->priority
);
656 K32OBJ_DecCount( &pdb
->header
);
662 /***********************************************************************
663 * GetStdHandle (KERNEL32.276)
665 * FIXME: These should be allocated when a console is created, or inherited
668 HANDLE32 WINAPI
GetStdHandle( DWORD std_handle
)
672 PDB32
*pdb
= PROCESS_Current();
676 case STD_INPUT_HANDLE
:
677 if (pdb
->env_db
->hStdin
) return pdb
->env_db
->hStdin
;
680 case STD_OUTPUT_HANDLE
:
681 if (pdb
->env_db
->hStdout
) return pdb
->env_db
->hStdout
;
684 case STD_ERROR_HANDLE
:
685 if (pdb
->env_db
->hStderr
) return pdb
->env_db
->hStderr
;
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
);
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;
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? */
716 case STD_INPUT_HANDLE
:
717 pdb
->env_db
->hStdin
= handle
;
719 case STD_OUTPUT_HANDLE
:
720 pdb
->env_db
->hStdout
= handle
;
722 case STD_ERROR_HANDLE
:
723 pdb
->env_db
->hStderr
= handle
;
726 SetLastError( ERROR_INVALID_PARAMETER
);
730 /***********************************************************************
731 * GetProcessVersion (KERNEL32)
733 DWORD WINAPI
GetProcessVersion( DWORD processid
)
736 PDB32
*pdb
= PROCESS_IdToPDB( processid
);
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
);
753 /***********************************************************************
754 * SetProcessWorkingSetSize [KERNEL32.662]
755 * Sets the min/max working set sizes for a specified process.
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
764 BOOL32 WINAPI
SetProcessWorkingSetSize(HANDLE32 hProcess
,DWORD minset
,
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 */
775 /***********************************************************************
776 * GetProcessWorkingSetSize (KERNEL32)
778 BOOL32 WINAPI
GetProcessWorkingSetSize(HANDLE32 hProcess
,LPDWORD minset
,
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;
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;
804 shutdown_noretry
= 0;
805 if (level
> 0x100L
&& level
< 0x3FFL
)
806 shutdown_priority
= level
;
809 ERR(process
,"invalid priority level 0x%08lx\n", level
);
816 /***********************************************************************
817 * GetProcessShutdownParameters (KERNEL32)
820 BOOL32 WINAPI
GetProcessShutdownParameters( LPDWORD lpdwLevel
,
823 (*lpdwLevel
) = shutdown_priority
;
824 (*lpdwFlags
) = (shutdown_noretry
* SHUTDOWN_NORETRY
);
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. */
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
;
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
;
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
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
;
899 /***********************************************************************
900 * GetProcessHeaps [KERNEL32.376]
902 DWORD WINAPI
GetProcessHeaps(DWORD nrofheaps
,HANDLE32
*heaps
) {
903 FIXME(win32
,"(%ld,%p), incomplete implementation.\n",nrofheaps
,heaps
);
906 heaps
[0] = GetProcessHeap();
907 /* ... probably SystemHeap too ? */
910 /* number of available heaps */
914 /***********************************************************************
915 * PROCESS_SuspendOtherThreads
918 void PROCESS_SuspendOtherThreads(void)
925 pdb
= PROCESS_Current();
926 entry
= pdb
->thread_list
->next
;
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
);
937 if (entry
== pdb
->thread_list
) break;
944 /***********************************************************************
945 * PROCESS_ResumeOtherThreads
948 void PROCESS_ResumeOtherThreads(void)
955 pdb
= PROCESS_Current();
956 entry
= pdb
->thread_list
->next
;
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
);
967 if (entry
== pdb
->thread_list
) break;