Added a lost entry for last release.
[wine/multimedia.git] / scheduler / process.c
blob4ffcd1ff559a917eccb924a41184746dfa0280c5
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 "thread.h"
19 #include "winerror.h"
20 #include "pe_image.h"
21 #include "task.h"
22 #include "server.h"
23 #include "debug.h"
25 static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id );
26 static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
27 static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id );
28 static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id );
29 static void PROCESS_Destroy( K32OBJ *obj );
31 const K32OBJ_OPS PROCESS_Ops =
33 PROCESS_Signaled, /* signaled */
34 PROCESS_Satisfied, /* satisfied */
35 PROCESS_AddWait, /* add_wait */
36 PROCESS_RemoveWait, /* remove_wait */
37 NULL, /* read */
38 NULL, /* write */
39 PROCESS_Destroy /* destroy */
43 /***********************************************************************
44 * PROCESS_Current
46 PDB32 *PROCESS_Current(void)
48 return THREAD_Current()->process;
52 /***********************************************************************
53 * PROCESS_GetPtr
55 * Get a process from a handle, incrementing the PDB refcount.
57 PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
59 return (PDB32 *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
60 K32OBJ_PROCESS, access, server_handle );
64 /***********************************************************************
65 * PROCESS_IdToPDB
67 * Convert a process id to a PDB, making sure it is valid.
69 PDB32 *PROCESS_IdToPDB( DWORD id )
71 PDB32 *pdb;
73 if (!id) return PROCESS_Current();
74 pdb = PROCESS_ID_TO_PDB( id );
75 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
77 SetLastError( ERROR_INVALID_PARAMETER );
78 return NULL;
80 return pdb;
85 /***********************************************************************
86 * PROCESS_BuildEnvDB
88 * Build the env DB for the initial process
90 static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
92 /* Allocate the env DB (FIXME: should not be on the system heap) */
94 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
95 return FALSE;
96 InitializeCriticalSection( &pdb->env_db->section );
98 /* Allocate the standard handles */
100 pdb->env_db->hStdin = FILE_DupUnixHandle( 0 );
101 pdb->env_db->hStdout = FILE_DupUnixHandle( 1 );
102 pdb->env_db->hStderr = FILE_DupUnixHandle( 2 );
103 FILE_SetFileType( pdb->env_db->hStdin, FILE_TYPE_CHAR );
104 FILE_SetFileType( pdb->env_db->hStdout, FILE_TYPE_CHAR );
105 FILE_SetFileType( pdb->env_db->hStderr, FILE_TYPE_CHAR );
107 /* Build the command-line */
109 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
111 /* Build the environment strings */
113 return ENV_BuildEnvironment( pdb );
117 /***********************************************************************
118 * PROCESS_InheritEnvDB
120 static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
121 STARTUPINFO32A *startup )
123 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
124 return FALSE;
125 InitializeCriticalSection( &pdb->env_db->section );
127 /* Copy the parent environment */
129 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
131 /* Copy the command line */
133 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
134 return FALSE;
136 /* Remember startup info */
137 if (!(pdb->env_db->startup_info =
138 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
139 return FALSE;
140 *pdb->env_db->startup_info = *startup;
142 /* Inherit the standard handles */
143 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
145 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
146 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
147 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
149 else
151 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
152 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
153 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
156 return TRUE;
160 /***********************************************************************
161 * PROCESS_FreePDB
163 * Free a PDB and all associated storage.
165 static void PROCESS_FreePDB( PDB32 *pdb )
167 pdb->header.type = K32OBJ_UNKNOWN;
168 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
169 ENV_FreeEnvironment( pdb );
170 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
171 if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
172 if (pdb->event) K32OBJ_DecCount( pdb->event );
173 DeleteCriticalSection( &pdb->crit_section );
174 HeapFree( SystemHeap, 0, pdb );
178 /***********************************************************************
179 * PROCESS_CreatePDB
181 * Allocate and fill a PDB structure.
182 * Runs in the context of the parent process.
184 static PDB32 *PROCESS_CreatePDB( PDB32 *parent )
186 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
188 if (!pdb) return NULL;
189 pdb->header.type = K32OBJ_PROCESS;
190 pdb->header.refcount = 1;
191 pdb->exit_code = 0x103; /* STILL_ACTIVE */
192 pdb->threads = 1;
193 pdb->running_threads = 1;
194 pdb->ring0_threads = 1;
195 pdb->system_heap = SystemHeap;
196 pdb->parent = parent;
197 pdb->group = pdb;
198 pdb->priority = 8; /* Normal */
199 pdb->heap = pdb->system_heap; /* will be changed later on */
201 InitializeCriticalSection( &pdb->crit_section );
203 /* Allocate the events */
205 if (!(pdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
206 if (!(pdb->load_done_evt = EVENT_Create( TRUE, FALSE ))) goto error;
208 /* Create the handle table */
210 if (!HANDLE_CreateTable( pdb, TRUE )) goto error;
212 return pdb;
214 error:
215 PROCESS_FreePDB( pdb );
216 return NULL;
220 /***********************************************************************
221 * PROCESS_Init
223 BOOL32 PROCESS_Init(void)
225 PDB32 *pdb;
226 THDB *thdb;
228 /* Initialize virtual memory management */
229 if (!VIRTUAL_Init()) return FALSE;
231 /* Create the system and SEGPTR heaps */
232 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
233 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
235 /* Create the initial process and thread structures */
236 if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
237 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
238 thdb->unix_pid = getpid();
240 /* Create the environment DB of the first process */
241 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
243 /* Initialize the first thread */
244 if (CLIENT_InitThread()) return FALSE;
246 return TRUE;
250 /***********************************************************************
251 * PROCESS_Create
253 * Create a new process database and associated info.
255 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
256 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
257 STARTUPINFO32A *startup, PROCESS_INFORMATION *info )
259 DWORD size, commit;
260 int server_thandle, server_phandle;
261 UINT32 cmdShow = 0;
262 THDB *thdb = NULL;
263 PDB32 *parent = PROCESS_Current();
264 PDB32 *pdb = PROCESS_CreatePDB( parent );
265 TDB *pTask;
267 if (!pdb) return NULL;
268 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
270 /* Create the heap */
272 if (pModule->module32)
274 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
275 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
277 else
279 size = 0x10000;
280 commit = 0;
281 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
283 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
284 pdb->heap_list = pdb->heap;
286 /* Inherit the env DB from the parent */
288 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, startup )) goto error;
290 /* Create the main thread */
292 if (pModule->module32)
293 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
294 else
295 size = 0;
296 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
297 NULL, NULL ))) goto error;
298 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
299 FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
300 goto error;
301 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
302 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
303 goto error;
304 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
305 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
307 #if 0
308 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
309 #else
310 /* All Win16 'threads' have the same unix_pid, no matter by which thread
311 they were created ! */
312 pTask = (TDB *)GlobalLock16( parent->task );
313 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
314 #endif
316 /* Create a Win16 task for this process */
318 if (startup->dwFlags & STARTF_USESHOWWINDOW)
319 cmdShow = startup->wShowWindow;
321 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
322 if (!pdb->task) goto error;
324 return pdb;
326 error:
327 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
328 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
329 if (thdb) K32OBJ_DecCount( &thdb->header );
330 PROCESS_FreePDB( pdb );
331 return NULL;
335 /***********************************************************************
336 * PROCESS_Signaled
338 static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id )
340 PDB32 *pdb = (PDB32 *)obj;
341 assert( obj->type == K32OBJ_PROCESS );
342 return K32OBJ_OPS( pdb->event )->signaled( pdb->event, thread_id );
346 /***********************************************************************
347 * PROCESS_Satisfied
349 * Wait on this object has been satisfied.
351 static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
353 PDB32 *pdb = (PDB32 *)obj;
354 assert( obj->type == K32OBJ_PROCESS );
355 return K32OBJ_OPS( pdb->event )->satisfied( pdb->event, thread_id );
359 /***********************************************************************
360 * PROCESS_AddWait
362 * Add thread to object wait queue.
364 static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id )
366 PDB32 *pdb = (PDB32 *)obj;
367 assert( obj->type == K32OBJ_PROCESS );
368 return K32OBJ_OPS( pdb->event )->add_wait( pdb->event, thread_id );
372 /***********************************************************************
373 * PROCESS_RemoveWait
375 * Remove thread from object wait queue.
377 static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id )
379 PDB32 *pdb = (PDB32 *)obj;
380 assert( obj->type == K32OBJ_PROCESS );
381 return K32OBJ_OPS( pdb->event )->remove_wait( pdb->event, thread_id );
385 /***********************************************************************
386 * PROCESS_Destroy
388 static void PROCESS_Destroy( K32OBJ *ptr )
390 PDB32 *pdb = (PDB32 *)ptr;
391 assert( ptr->type == K32OBJ_PROCESS );
393 /* Free everything */
395 ptr->type = K32OBJ_UNKNOWN;
396 PROCESS_FreePDB( pdb );
400 /***********************************************************************
401 * ExitProcess (KERNEL32.100)
403 void WINAPI ExitProcess( DWORD status )
405 PDB32 *pdb = PROCESS_Current();
406 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
407 if ( pTask ) pTask->nEvents++;
409 if ( pTask && pTask->thdb != THREAD_Current() )
410 ExitThread( status );
412 SYSTEM_LOCK();
413 /* FIXME: should kill all running threads of this process */
414 pdb->exit_code = status;
415 EVENT_Set( pdb->event );
416 if (pdb->console) FreeConsole();
417 SYSTEM_UNLOCK();
419 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
420 TASK_KillCurrentTask( status );
424 /******************************************************************************
425 * TerminateProcess (KERNEL32.684)
427 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
429 int server_handle;
430 BOOL32 ret;
431 PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_TERMINATE, &server_handle );
432 if (!pdb) return FALSE;
433 ret = !CLIENT_TerminateProcess( server_handle, exit_code );
434 K32OBJ_DecCount( &pdb->header );
435 return ret;
438 /***********************************************************************
439 * GetCurrentProcess (KERNEL32.198)
441 HANDLE32 WINAPI GetCurrentProcess(void)
443 return CURRENT_PROCESS_PSEUDOHANDLE;
447 /*********************************************************************
448 * OpenProcess (KERNEL32.543)
450 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
452 int server_handle;
453 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
454 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
456 SetLastError( ERROR_INVALID_HANDLE );
457 return 0;
459 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
461 SetLastError( ERROR_INVALID_HANDLE );
462 return 0;
464 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
465 inherit, server_handle );
469 /***********************************************************************
470 * GetCurrentProcessId (KERNEL32.199)
472 DWORD WINAPI GetCurrentProcessId(void)
474 PDB32 *pdb = PROCESS_Current();
475 return PDB_TO_PROCESS_ID( pdb );
479 /***********************************************************************
480 * GetProcessHeap (KERNEL32.259)
482 HANDLE32 WINAPI GetProcessHeap(void)
484 PDB32 *pdb = PROCESS_Current();
485 return pdb->heap ? pdb->heap : SystemHeap;
489 /***********************************************************************
490 * GetThreadLocale (KERNEL32.295)
492 LCID WINAPI GetThreadLocale(void)
494 return PROCESS_Current()->locale;
498 /***********************************************************************
499 * SetPriorityClass (KERNEL32.503)
501 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
503 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
504 if (!pdb) return FALSE;
505 switch (priorityclass)
507 case NORMAL_PRIORITY_CLASS:
508 pdb->priority = 0x00000008;
509 break;
510 case IDLE_PRIORITY_CLASS:
511 pdb->priority = 0x00000004;
512 break;
513 case HIGH_PRIORITY_CLASS:
514 pdb->priority = 0x0000000d;
515 break;
516 case REALTIME_PRIORITY_CLASS:
517 pdb->priority = 0x00000018;
518 break;
519 default:
520 WARN(process,"Unknown priority class %ld\n",priorityclass);
521 break;
523 K32OBJ_DecCount( &pdb->header );
524 return TRUE;
528 /***********************************************************************
529 * GetPriorityClass (KERNEL32.250)
531 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
533 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
534 DWORD ret = 0;
535 if (pdb)
537 switch (pdb->priority)
539 case 0x00000008:
540 ret = NORMAL_PRIORITY_CLASS;
541 break;
542 case 0x00000004:
543 ret = IDLE_PRIORITY_CLASS;
544 break;
545 case 0x0000000d:
546 ret = HIGH_PRIORITY_CLASS;
547 break;
548 case 0x00000018:
549 ret = REALTIME_PRIORITY_CLASS;
550 break;
551 default:
552 WARN(process,"Unknown priority %ld\n",pdb->priority);
554 K32OBJ_DecCount( &pdb->header );
556 return ret;
560 /***********************************************************************
561 * GetStdHandle (KERNEL32.276)
563 * FIXME: These should be allocated when a console is created, or inherited
564 * from the parent.
566 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
568 HFILE32 hFile;
569 int fd;
570 PDB32 *pdb = PROCESS_Current();
572 switch(std_handle)
574 case STD_INPUT_HANDLE:
575 if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
576 fd = 0;
577 break;
578 case STD_OUTPUT_HANDLE:
579 if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
580 fd = 1;
581 break;
582 case STD_ERROR_HANDLE:
583 if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
584 fd = 2;
585 break;
586 default:
587 SetLastError( ERROR_INVALID_PARAMETER );
588 return INVALID_HANDLE_VALUE32;
590 hFile = FILE_DupUnixHandle( fd );
591 if (hFile != HFILE_ERROR32)
593 FILE_SetFileType( hFile, FILE_TYPE_CHAR );
594 switch(std_handle)
596 case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
597 case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
598 case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
601 return hFile;
605 /***********************************************************************
606 * SetStdHandle (KERNEL32.506)
608 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
610 PDB32 *pdb = PROCESS_Current();
611 /* FIXME: should we close the previous handle? */
612 switch(std_handle)
614 case STD_INPUT_HANDLE:
615 pdb->env_db->hStdin = handle;
616 return TRUE;
617 case STD_OUTPUT_HANDLE:
618 pdb->env_db->hStdout = handle;
619 return TRUE;
620 case STD_ERROR_HANDLE:
621 pdb->env_db->hStderr = handle;
622 return TRUE;
624 SetLastError( ERROR_INVALID_PARAMETER );
625 return FALSE;
628 /***********************************************************************
629 * GetProcessVersion (KERNEL32)
631 DWORD WINAPI GetProcessVersion( DWORD processid )
633 TDB *pTask;
634 PDB32 *pdb = PROCESS_IdToPDB( processid );
636 if (!pdb) return 0;
637 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
638 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
641 /***********************************************************************
642 * GetProcessFlags (KERNEL32)
644 DWORD WINAPI GetProcessFlags( DWORD processid )
646 PDB32 *pdb = PROCESS_IdToPDB( processid );
647 if (!pdb) return 0;
648 return pdb->flags;
651 /***********************************************************************
652 * SetProcessWorkingSetSize [KERNEL32.662]
653 * Sets the min/max working set sizes for a specified process.
655 * PARAMS
656 * hProcess [I] Handle to the process of interest
657 * minset [I] Specifies minimum working set size
658 * maxset [I] Specifies maximum working set size
660 * RETURNS STD
662 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
663 DWORD maxset)
665 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
666 if(( minset == -1) && (maxset == -1)) {
667 /* Trim the working set to zero */
668 /* Swap the process out of physical RAM */
670 return TRUE;
673 /***********************************************************************
674 * GetProcessWorkingSetSize (KERNEL32)
676 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
677 LPDWORD maxset)
679 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
680 /* 32 MB working set size */
681 if (minset) *minset = 32*1024*1024;
682 if (maxset) *maxset = 32*1024*1024;
683 return TRUE;
686 /***********************************************************************
687 * SetProcessShutdownParameters (KERNEL32)
689 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
691 FIXME(process,"(%ld,0x%08lx): stub\n",level,flags);
692 return TRUE;
695 /***********************************************************************
696 * ReadProcessMemory (KERNEL32)
697 * FIXME: check this, if we ever run win32 binaries in different addressspaces
698 * ... and add a sizecheck
700 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
701 LPVOID lpBuffer, DWORD nSize,
702 LPDWORD lpNumberOfBytesRead )
704 memcpy(lpBuffer,lpBaseAddress,nSize);
705 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
706 return TRUE;
709 /***********************************************************************
710 * WriteProcessMemory (KERNEL32)
711 * FIXME: check this, if we ever run win32 binaries in different addressspaces
712 * ... and add a sizecheck
714 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
715 LPVOID lpBuffer, DWORD nSize,
716 LPDWORD lpNumberOfBytesWritten )
718 memcpy(lpBaseAddress,lpBuffer,nSize);
719 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
720 return TRUE;
723 /***********************************************************************
724 * ConvertToGlobalHandle (KERNEL32)
725 * FIXME: this is not correctly implemented...
727 HANDLE32 WINAPI ConvertToGlobalHandle(HANDLE32 h)
729 FIXME(process,"(%d): stub\n",h);
730 return h;
733 /***********************************************************************
734 * RegisterServiceProcess (KERNEL32)
736 * A service process calls this function to ensure that it continues to run
737 * even after a user logged off.
739 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
741 /* I don't think that Wine needs to do anything in that function */
742 return 1; /* success */
745 /***********************************************************************
746 * GetExitCodeProcess [KERNEL32.325]
748 * Gets termination status of specified process
750 * RETURNS
751 * Success: TRUE
752 * Failure: FALSE
754 * FIXME
755 * Should call SetLastError (but doesn't).
757 BOOL32 WINAPI GetExitCodeProcess(
758 HANDLE32 hProcess, /* [I] handle to the process */
759 LPDWORD lpExitCode) /* [O] address to receive termination status */
761 PDB32 *process;
762 int server_handle;
763 struct get_process_info_reply info;
765 if (!(process = PROCESS_GetPtr( hProcess, PROCESS_QUERY_INFORMATION,
766 &server_handle )))
767 return FALSE;
768 if (server_handle != -1)
770 CLIENT_GetProcessInfo( server_handle, &info );
771 if (lpExitCode) *lpExitCode = info.exit_code;
773 else if (lpExitCode) *lpExitCode = process->exit_code;
774 K32OBJ_DecCount( &process->header );
775 return TRUE;
778 /***********************************************************************
779 * GetProcessHeaps [KERNEL32.376]
781 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
782 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
784 if (nrofheaps) {
785 heaps[0] = GetProcessHeap();
786 /* ... probably SystemHeap too ? */
787 return 1;
789 /* number of available heaps */
790 return 1;
793 /***********************************************************************
794 * PROCESS_SuspendOtherThreads
797 void PROCESS_SuspendOtherThreads(void)
799 PDB32 *pdb;
800 THREAD_ENTRY *entry;
802 SYSTEM_LOCK();
804 pdb = PROCESS_Current();
805 entry = pdb->thread_list->next;
806 for (;;)
808 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
810 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
811 &entry->thread->header,
812 THREAD_ALL_ACCESS, FALSE, -1 );
813 SuspendThread(handle);
814 CloseHandle(handle);
816 if (entry == pdb->thread_list) break;
817 entry = entry->next;
820 SYSTEM_UNLOCK();
823 /***********************************************************************
824 * PROCESS_ResumeOtherThreads
827 void PROCESS_ResumeOtherThreads(void)
829 PDB32 *pdb;
830 THREAD_ENTRY *entry;
832 SYSTEM_LOCK();
834 pdb = PROCESS_Current();
835 entry = pdb->thread_list->next;
836 for (;;)
838 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
840 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
841 &entry->thread->header,
842 THREAD_ALL_ACCESS, FALSE, -1 );
843 ResumeThread(handle);
844 CloseHandle(handle);
846 if (entry == pdb->thread_list) break;
847 entry = entry->next;
850 SYSTEM_UNLOCK();