4 * Copyright 1996, 1998 Alexandre Julliard
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 /***********************************************************************
43 PDB
*PROCESS_Current(void)
45 return THREAD_Current()->process
;
48 /***********************************************************************
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)
61 /***********************************************************************
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 /***********************************************************************
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 /***********************************************************************
92 * Convert a process id to a PDB, making sure it is valid.
94 PDB
*PROCESS_IdToPDB( DWORD id
)
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
);
110 /***********************************************************************
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
))))
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
) )))
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
))))
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
)))
163 /* Remember startup info */
164 if (!(pdb
->env_db
->startup_info
=
165 HeapAlloc( pdb
->heap
, HEAP_ZERO_MEMORY
, sizeof(STARTUPINFOA
) )))
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 */
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
201 if (PROCESS_PDBList
== NULL
)
203 PROCESS_PDBList
= pdb
;
204 pdb
->list_next
= NULL
;
205 pdb
->list_prev
= NULL
;
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
++;
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
);
238 next
->list_prev
= NULL
;
239 next
->list_next
= NULL
;
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
--;
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 /***********************************************************************
290 * Free a PDB and all associated storage.
292 static void PROCESS_FreePDB( PDB
*pdb
)
296 * If this routine is called because PROCESS_CreatePDB fails, the
297 * following call to PROCESS_PDBList_Remove will probably screw
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 /***********************************************************************
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 */
325 pdb
->running_threads
= 1;
326 pdb
->ring0_threads
= 1;
327 pdb
->system_heap
= SystemHeap
;
328 pdb
->parent
= parent
;
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
);
341 PROCESS_FreePDB( pdb
);
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
)))
361 /***********************************************************************
364 BOOL
PROCESS_Init(void)
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
;
407 /***********************************************************************
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
)
418 int server_thandle
, server_phandle
;
421 PDB
*parent
= PROCESS_Current();
422 PDB
*pdb
= PROCESS_CreatePDB( parent
, inherit
);
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
;
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
;
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
)
460 if ((info
->hProcess
= HANDLE_Alloc( parent
, &pdb
->header
, PROCESS_ALL_ACCESS
,
461 FALSE
, server_phandle
)) == INVALID_HANDLE_VALUE
)
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
;
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
);
503 /***********************************************************************
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
);
531 /* FIXME: should kill all running threads of this process */
532 pdb
->exit_code
= status
;
533 if (pdb
->console
) FreeConsole();
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
)
570 PDB
*pdb
= PROCESS_ID_TO_PDB(id
);
571 if (!K32OBJ_IsValid( &pdb
->header
, K32OBJ_PROCESS
))
573 SetLastError( ERROR_INVALID_HANDLE
);
576 if ((server_handle
= CLIENT_OpenProcess( pdb
->server_pid
, access
, inherit
)) == -1)
578 SetLastError( ERROR_INVALID_HANDLE
);
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
;
672 /***********************************************************************
673 * GetStdHandle (KERNEL32.276)
675 HANDLE WINAPI
GetStdHandle( DWORD std_handle
)
677 PDB
*pdb
= PROCESS_Current();
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? */
699 case STD_INPUT_HANDLE
:
700 pdb
->env_db
->hStdin
= handle
;
702 case STD_OUTPUT_HANDLE
:
703 pdb
->env_db
->hStdout
= handle
;
705 case STD_ERROR_HANDLE
:
706 pdb
->env_db
->hStderr
= handle
;
709 SetLastError( ERROR_INVALID_PARAMETER
);
713 /***********************************************************************
714 * GetProcessVersion (KERNEL32)
716 DWORD WINAPI
GetProcessVersion( DWORD processid
)
719 PDB
*pdb
= PROCESS_IdToPDB( processid
);
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
);
736 /***********************************************************************
737 * SetProcessWorkingSetSize [KERNEL32.662]
738 * Sets the min/max working set sizes for a specified process.
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
747 BOOL WINAPI
SetProcessWorkingSetSize(HANDLE hProcess
,DWORD minset
,
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 */
758 /***********************************************************************
759 * GetProcessWorkingSetSize (KERNEL32)
761 BOOL WINAPI
GetProcessWorkingSetSize(HANDLE hProcess
,LPDWORD minset
,
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;
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;
787 shutdown_noretry
= 0;
788 if (level
> 0x100L
&& level
< 0x3FFL
)
789 shutdown_priority
= level
;
792 ERR(process
,"invalid priority level 0x%08lx\n", level
);
799 /***********************************************************************
800 * GetProcessShutdownParameters (KERNEL32)
803 BOOL WINAPI
GetProcessShutdownParameters( LPDWORD lpdwLevel
,
806 (*lpdwLevel
) = shutdown_priority
;
807 (*lpdwFlags
) = (shutdown_noretry
* SHUTDOWN_NORETRY
);
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. */
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
;
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
;
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
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
;
880 /***********************************************************************
881 * GetProcessHeaps [KERNEL32.376]
883 DWORD WINAPI
GetProcessHeaps(DWORD nrofheaps
,HANDLE
*heaps
) {
884 FIXME(win32
,"(%ld,%p), incomplete implementation.\n",nrofheaps
,heaps
);
887 heaps
[0] = GetProcessHeap();
888 /* ... probably SystemHeap too ? */
891 /* number of available heaps */
895 /***********************************************************************
896 * PROCESS_SuspendOtherThreads
899 void PROCESS_SuspendOtherThreads(void)
907 pdb
= PROCESS_Current();
908 entry
= pdb
->thread_list
->next
;
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
);
919 if (entry
== pdb
->thread_list
) break;
927 /***********************************************************************
928 * PROCESS_ResumeOtherThreads
931 void PROCESS_ResumeOtherThreads(void)
939 pdb
= PROCESS_Current();
940 entry
= pdb
->thread_list
->next
;
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
);
951 if (entry
== pdb
->thread_list
) break;