Beginning of mouse support in DirectInput (only "standard" mouse
[wine/hacks.git] / scheduler / process.c
blobc9fa851affd5eefc00ae49f413f6b7af1c30e949
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 BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id );
27 static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
28 static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id );
29 static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id );
30 static void PROCESS_Destroy( K32OBJ *obj );
32 const K32OBJ_OPS PROCESS_Ops =
34 PROCESS_Signaled, /* signaled */
35 PROCESS_Satisfied, /* satisfied */
36 PROCESS_AddWait, /* add_wait */
37 PROCESS_RemoveWait, /* remove_wait */
38 NULL, /* read */
39 NULL, /* write */
40 PROCESS_Destroy /* destroy */
44 /***********************************************************************
45 * PROCESS_Current
47 PDB32 *PROCESS_Current(void)
49 return THREAD_Current()->process;
53 /***********************************************************************
54 * PROCESS_GetPtr
56 * Get a process from a handle, incrementing the PDB refcount.
58 PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
60 return (PDB32 *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
61 K32OBJ_PROCESS, access, server_handle );
65 /***********************************************************************
66 * PROCESS_IdToPDB
68 * Convert a process id to a PDB, making sure it is valid.
70 PDB32 *PROCESS_IdToPDB( DWORD id )
72 PDB32 *pdb;
74 if (!id) return PROCESS_Current();
75 pdb = PROCESS_ID_TO_PDB( id );
76 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
78 SetLastError( ERROR_INVALID_PARAMETER );
79 return NULL;
81 return pdb;
86 /***********************************************************************
87 * PROCESS_BuildEnvDB
89 * Build the env DB for the initial process
91 static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
93 /* Allocate the env DB (FIXME: should not be on the system heap) */
95 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
96 return FALSE;
97 InitializeCriticalSection( &pdb->env_db->section );
99 /* Allocate the standard handles */
101 pdb->env_db->hStdin = FILE_DupUnixHandle( 0 );
102 pdb->env_db->hStdout = FILE_DupUnixHandle( 1 );
103 pdb->env_db->hStderr = FILE_DupUnixHandle( 2 );
104 FILE_SetFileType( pdb->env_db->hStdin, FILE_TYPE_CHAR );
105 FILE_SetFileType( pdb->env_db->hStdout, FILE_TYPE_CHAR );
106 FILE_SetFileType( pdb->env_db->hStderr, FILE_TYPE_CHAR );
108 /* Build the command-line */
110 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
112 /* Build the environment strings */
114 return ENV_BuildEnvironment( pdb );
118 /***********************************************************************
119 * PROCESS_InheritEnvDB
121 static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
122 STARTUPINFO32A *startup )
124 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
125 return FALSE;
126 InitializeCriticalSection( &pdb->env_db->section );
128 /* Copy the parent environment */
130 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
132 /* Copy the command line */
134 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
135 return FALSE;
137 /* Remember startup info */
138 if (!(pdb->env_db->startup_info =
139 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
140 return FALSE;
141 *pdb->env_db->startup_info = *startup;
143 /* Inherit the standard handles */
144 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
146 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
147 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
148 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
150 else
152 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
153 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
154 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
157 return TRUE;
161 /***********************************************************************
162 * PROCESS_FreePDB
164 * Free a PDB and all associated storage.
166 static void PROCESS_FreePDB( PDB32 *pdb )
168 pdb->header.type = K32OBJ_UNKNOWN;
169 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
170 ENV_FreeEnvironment( pdb );
171 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
172 if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
173 if (pdb->event) K32OBJ_DecCount( pdb->event );
174 DeleteCriticalSection( &pdb->crit_section );
175 HeapFree( SystemHeap, 0, pdb );
179 /***********************************************************************
180 * PROCESS_CreatePDB
182 * Allocate and fill a PDB structure.
183 * Runs in the context of the parent process.
185 static PDB32 *PROCESS_CreatePDB( PDB32 *parent )
187 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
189 if (!pdb) return NULL;
190 pdb->header.type = K32OBJ_PROCESS;
191 pdb->header.refcount = 1;
192 pdb->exit_code = 0x103; /* STILL_ACTIVE */
193 pdb->threads = 1;
194 pdb->running_threads = 1;
195 pdb->ring0_threads = 1;
196 pdb->system_heap = SystemHeap;
197 pdb->parent = parent;
198 pdb->group = pdb;
199 pdb->priority = 8; /* Normal */
200 pdb->heap = pdb->system_heap; /* will be changed later on */
202 InitializeCriticalSection( &pdb->crit_section );
204 /* Allocate the events */
206 if (!(pdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
207 if (!(pdb->load_done_evt = EVENT_Create( TRUE, FALSE ))) goto error;
209 /* Create the handle table */
211 if (!HANDLE_CreateTable( pdb, TRUE )) goto error;
213 return pdb;
215 error:
216 PROCESS_FreePDB( pdb );
217 return NULL;
221 /***********************************************************************
222 * PROCESS_Init
224 BOOL32 PROCESS_Init(void)
226 PDB32 *pdb;
227 THDB *thdb;
229 /* Initialize virtual memory management */
230 if (!VIRTUAL_Init()) return FALSE;
232 /* Create the system and SEGPTR heaps */
233 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
234 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
236 /* Create the initial process and thread structures */
237 if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
238 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
239 thdb->unix_pid = getpid();
241 /* Remember TEB selector of initial process for emergency use */
242 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
244 /* Create the environment DB of the first process */
245 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
247 /* Initialize the first thread */
248 if (CLIENT_InitThread()) return FALSE;
250 return TRUE;
254 /***********************************************************************
255 * PROCESS_Create
257 * Create a new process database and associated info.
259 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
260 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
261 STARTUPINFO32A *startup, PROCESS_INFORMATION *info )
263 DWORD size, commit;
264 int server_thandle, server_phandle;
265 UINT32 cmdShow = 0;
266 THDB *thdb = NULL;
267 PDB32 *parent = PROCESS_Current();
268 PDB32 *pdb = PROCESS_CreatePDB( parent );
269 TDB *pTask;
271 if (!pdb) return NULL;
272 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
274 /* Create the heap */
276 if (pModule->module32)
278 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
279 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
281 else
283 size = 0x10000;
284 commit = 0;
285 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
287 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
288 pdb->heap_list = pdb->heap;
290 /* Inherit the env DB from the parent */
292 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, startup )) goto error;
294 /* Create the main thread */
296 if (pModule->module32)
297 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
298 else
299 size = 0;
300 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
301 NULL, NULL ))) goto error;
302 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
303 FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
304 goto error;
305 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
306 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
307 goto error;
308 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
309 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
311 #if 0
312 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
313 #else
314 /* All Win16 'threads' have the same unix_pid, no matter by which thread
315 they were created ! */
316 pTask = (TDB *)GlobalLock16( parent->task );
317 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
318 #endif
320 /* Create a Win16 task for this process */
322 if (startup->dwFlags & STARTF_USESHOWWINDOW)
323 cmdShow = startup->wShowWindow;
325 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
326 if (!pdb->task) goto error;
328 return pdb;
330 error:
331 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
332 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
333 if (thdb) K32OBJ_DecCount( &thdb->header );
334 PROCESS_FreePDB( pdb );
335 return NULL;
339 /***********************************************************************
340 * PROCESS_Signaled
342 static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id )
344 PDB32 *pdb = (PDB32 *)obj;
345 assert( obj->type == K32OBJ_PROCESS );
346 return K32OBJ_OPS( pdb->event )->signaled( pdb->event, thread_id );
350 /***********************************************************************
351 * PROCESS_Satisfied
353 * Wait on this object has been satisfied.
355 static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
357 PDB32 *pdb = (PDB32 *)obj;
358 assert( obj->type == K32OBJ_PROCESS );
359 return K32OBJ_OPS( pdb->event )->satisfied( pdb->event, thread_id );
363 /***********************************************************************
364 * PROCESS_AddWait
366 * Add thread to object wait queue.
368 static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id )
370 PDB32 *pdb = (PDB32 *)obj;
371 assert( obj->type == K32OBJ_PROCESS );
372 return K32OBJ_OPS( pdb->event )->add_wait( pdb->event, thread_id );
376 /***********************************************************************
377 * PROCESS_RemoveWait
379 * Remove thread from object wait queue.
381 static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id )
383 PDB32 *pdb = (PDB32 *)obj;
384 assert( obj->type == K32OBJ_PROCESS );
385 return K32OBJ_OPS( pdb->event )->remove_wait( pdb->event, thread_id );
389 /***********************************************************************
390 * PROCESS_Destroy
392 static void PROCESS_Destroy( K32OBJ *ptr )
394 PDB32 *pdb = (PDB32 *)ptr;
395 assert( ptr->type == K32OBJ_PROCESS );
397 /* Free everything */
399 ptr->type = K32OBJ_UNKNOWN;
400 PROCESS_FreePDB( pdb );
404 /***********************************************************************
405 * ExitProcess (KERNEL32.100)
407 void WINAPI ExitProcess( DWORD status )
409 PDB32 *pdb = PROCESS_Current();
410 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
411 if ( pTask ) pTask->nEvents++;
413 if ( pTask && pTask->thdb != THREAD_Current() )
414 ExitThread( status );
416 SYSTEM_LOCK();
417 /* FIXME: should kill all running threads of this process */
418 pdb->exit_code = status;
419 EVENT_Set( pdb->event );
420 if (pdb->console) FreeConsole();
421 SYSTEM_UNLOCK();
423 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
424 TASK_KillCurrentTask( status );
428 /******************************************************************************
429 * TerminateProcess (KERNEL32.684)
431 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
433 int server_handle;
434 BOOL32 ret;
435 PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_TERMINATE, &server_handle );
436 if (!pdb) return FALSE;
437 ret = !CLIENT_TerminateProcess( server_handle, exit_code );
438 K32OBJ_DecCount( &pdb->header );
439 return ret;
442 /***********************************************************************
443 * GetCurrentProcess (KERNEL32.198)
445 HANDLE32 WINAPI GetCurrentProcess(void)
447 return CURRENT_PROCESS_PSEUDOHANDLE;
451 /*********************************************************************
452 * OpenProcess (KERNEL32.543)
454 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
456 int server_handle;
457 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
458 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
460 SetLastError( ERROR_INVALID_HANDLE );
461 return 0;
463 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
465 SetLastError( ERROR_INVALID_HANDLE );
466 return 0;
468 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
469 inherit, server_handle );
473 /***********************************************************************
474 * GetCurrentProcessId (KERNEL32.199)
476 DWORD WINAPI GetCurrentProcessId(void)
478 PDB32 *pdb = PROCESS_Current();
479 return PDB_TO_PROCESS_ID( pdb );
483 /***********************************************************************
484 * GetProcessHeap (KERNEL32.259)
486 HANDLE32 WINAPI GetProcessHeap(void)
488 PDB32 *pdb = PROCESS_Current();
489 return pdb->heap ? pdb->heap : SystemHeap;
493 /***********************************************************************
494 * GetThreadLocale (KERNEL32.295)
496 LCID WINAPI GetThreadLocale(void)
498 return PROCESS_Current()->locale;
502 /***********************************************************************
503 * SetPriorityClass (KERNEL32.503)
505 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
507 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
508 if (!pdb) return FALSE;
509 switch (priorityclass)
511 case NORMAL_PRIORITY_CLASS:
512 pdb->priority = 0x00000008;
513 break;
514 case IDLE_PRIORITY_CLASS:
515 pdb->priority = 0x00000004;
516 break;
517 case HIGH_PRIORITY_CLASS:
518 pdb->priority = 0x0000000d;
519 break;
520 case REALTIME_PRIORITY_CLASS:
521 pdb->priority = 0x00000018;
522 break;
523 default:
524 WARN(process,"Unknown priority class %ld\n",priorityclass);
525 break;
527 K32OBJ_DecCount( &pdb->header );
528 return TRUE;
532 /***********************************************************************
533 * GetPriorityClass (KERNEL32.250)
535 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
537 PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
538 DWORD ret = 0;
539 if (pdb)
541 switch (pdb->priority)
543 case 0x00000008:
544 ret = NORMAL_PRIORITY_CLASS;
545 break;
546 case 0x00000004:
547 ret = IDLE_PRIORITY_CLASS;
548 break;
549 case 0x0000000d:
550 ret = HIGH_PRIORITY_CLASS;
551 break;
552 case 0x00000018:
553 ret = REALTIME_PRIORITY_CLASS;
554 break;
555 default:
556 WARN(process,"Unknown priority %ld\n",pdb->priority);
558 K32OBJ_DecCount( &pdb->header );
560 return ret;
564 /***********************************************************************
565 * GetStdHandle (KERNEL32.276)
567 * FIXME: These should be allocated when a console is created, or inherited
568 * from the parent.
570 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
572 HFILE32 hFile;
573 int fd;
574 PDB32 *pdb = PROCESS_Current();
576 switch(std_handle)
578 case STD_INPUT_HANDLE:
579 if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
580 fd = 0;
581 break;
582 case STD_OUTPUT_HANDLE:
583 if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
584 fd = 1;
585 break;
586 case STD_ERROR_HANDLE:
587 if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
588 fd = 2;
589 break;
590 default:
591 SetLastError( ERROR_INVALID_PARAMETER );
592 return INVALID_HANDLE_VALUE32;
594 hFile = FILE_DupUnixHandle( fd );
595 if (hFile != HFILE_ERROR32)
597 FILE_SetFileType( hFile, FILE_TYPE_CHAR );
598 switch(std_handle)
600 case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
601 case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
602 case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
605 return hFile;
609 /***********************************************************************
610 * SetStdHandle (KERNEL32.506)
612 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
614 PDB32 *pdb = PROCESS_Current();
615 /* FIXME: should we close the previous handle? */
616 switch(std_handle)
618 case STD_INPUT_HANDLE:
619 pdb->env_db->hStdin = handle;
620 return TRUE;
621 case STD_OUTPUT_HANDLE:
622 pdb->env_db->hStdout = handle;
623 return TRUE;
624 case STD_ERROR_HANDLE:
625 pdb->env_db->hStderr = handle;
626 return TRUE;
628 SetLastError( ERROR_INVALID_PARAMETER );
629 return FALSE;
632 /***********************************************************************
633 * GetProcessVersion (KERNEL32)
635 DWORD WINAPI GetProcessVersion( DWORD processid )
637 TDB *pTask;
638 PDB32 *pdb = PROCESS_IdToPDB( processid );
640 if (!pdb) return 0;
641 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
642 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
645 /***********************************************************************
646 * GetProcessFlags (KERNEL32)
648 DWORD WINAPI GetProcessFlags( DWORD processid )
650 PDB32 *pdb = PROCESS_IdToPDB( processid );
651 if (!pdb) return 0;
652 return pdb->flags;
655 /***********************************************************************
656 * SetProcessWorkingSetSize [KERNEL32.662]
657 * Sets the min/max working set sizes for a specified process.
659 * PARAMS
660 * hProcess [I] Handle to the process of interest
661 * minset [I] Specifies minimum working set size
662 * maxset [I] Specifies maximum working set size
664 * RETURNS STD
666 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
667 DWORD maxset)
669 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
670 if(( minset == -1) && (maxset == -1)) {
671 /* Trim the working set to zero */
672 /* Swap the process out of physical RAM */
674 return TRUE;
677 /***********************************************************************
678 * GetProcessWorkingSetSize (KERNEL32)
680 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
681 LPDWORD maxset)
683 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
684 /* 32 MB working set size */
685 if (minset) *minset = 32*1024*1024;
686 if (maxset) *maxset = 32*1024*1024;
687 return TRUE;
690 /***********************************************************************
691 * SetProcessShutdownParameters (KERNEL32)
693 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
695 FIXME(process,"(%ld,0x%08lx): stub\n",level,flags);
696 return TRUE;
699 /***********************************************************************
700 * ReadProcessMemory (KERNEL32)
701 * FIXME: check this, if we ever run win32 binaries in different addressspaces
702 * ... and add a sizecheck
704 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
705 LPVOID lpBuffer, DWORD nSize,
706 LPDWORD lpNumberOfBytesRead )
708 memcpy(lpBuffer,lpBaseAddress,nSize);
709 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
710 return TRUE;
713 /***********************************************************************
714 * WriteProcessMemory (KERNEL32)
715 * FIXME: check this, if we ever run win32 binaries in different addressspaces
716 * ... and add a sizecheck
718 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
719 LPVOID lpBuffer, DWORD nSize,
720 LPDWORD lpNumberOfBytesWritten )
722 memcpy(lpBaseAddress,lpBuffer,nSize);
723 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
724 return TRUE;
727 /***********************************************************************
728 * ConvertToGlobalHandle (KERNEL32)
729 * FIXME: this is not correctly implemented...
731 HANDLE32 WINAPI ConvertToGlobalHandle(HANDLE32 h)
733 FIXME(process,"(%d): stub\n",h);
734 return h;
737 /***********************************************************************
738 * RegisterServiceProcess (KERNEL32)
740 * A service process calls this function to ensure that it continues to run
741 * even after a user logged off.
743 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
745 /* I don't think that Wine needs to do anything in that function */
746 return 1; /* success */
749 /***********************************************************************
750 * GetExitCodeProcess [KERNEL32.325]
752 * Gets termination status of specified process
754 * RETURNS
755 * Success: TRUE
756 * Failure: FALSE
758 * FIXME
759 * Should call SetLastError (but doesn't).
761 BOOL32 WINAPI GetExitCodeProcess(
762 HANDLE32 hProcess, /* [I] handle to the process */
763 LPDWORD lpExitCode) /* [O] address to receive termination status */
765 PDB32 *process;
766 int server_handle;
767 struct get_process_info_reply info;
769 if (!(process = PROCESS_GetPtr( hProcess, PROCESS_QUERY_INFORMATION,
770 &server_handle )))
771 return FALSE;
772 if (server_handle != -1)
774 CLIENT_GetProcessInfo( server_handle, &info );
775 if (lpExitCode) *lpExitCode = info.exit_code;
777 else if (lpExitCode) *lpExitCode = process->exit_code;
778 K32OBJ_DecCount( &process->header );
779 return TRUE;
782 /***********************************************************************
783 * GetProcessHeaps [KERNEL32.376]
785 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
786 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
788 if (nrofheaps) {
789 heaps[0] = GetProcessHeap();
790 /* ... probably SystemHeap too ? */
791 return 1;
793 /* number of available heaps */
794 return 1;
797 /***********************************************************************
798 * PROCESS_SuspendOtherThreads
801 void PROCESS_SuspendOtherThreads(void)
803 PDB32 *pdb;
804 THREAD_ENTRY *entry;
806 SYSTEM_LOCK();
808 pdb = PROCESS_Current();
809 entry = pdb->thread_list->next;
810 for (;;)
812 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
814 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
815 &entry->thread->header,
816 THREAD_ALL_ACCESS, FALSE, -1 );
817 SuspendThread(handle);
818 CloseHandle(handle);
820 if (entry == pdb->thread_list) break;
821 entry = entry->next;
824 SYSTEM_UNLOCK();
827 /***********************************************************************
828 * PROCESS_ResumeOtherThreads
831 void PROCESS_ResumeOtherThreads(void)
833 PDB32 *pdb;
834 THREAD_ENTRY *entry;
836 SYSTEM_LOCK();
838 pdb = PROCESS_Current();
839 entry = pdb->thread_list->next;
840 for (;;)
842 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
844 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
845 &entry->thread->header,
846 THREAD_ALL_ACCESS, FALSE, -1 );
847 ResumeThread(handle);
848 CloseHandle(handle);
850 if (entry == pdb->thread_list) break;
851 entry = entry->next;
854 SYSTEM_UNLOCK();