4 * Copyright 1996, 1998 Alexandre Julliard
27 static void PROCESS_Destroy( K32OBJ *obj );
29 const K32OBJ_OPS PROCESS_Ops =
31 PROCESS_Destroy /* destroy */
34 static DWORD PROCESS_InitialProcessID = 0;
35 static PDB32 *PROCESS_PDBList = NULL;
36 static DWORD PROCESS_PDBList_Size = 0;
38 /***********************************************************************
41 PDB32 *PROCESS_Current(void)
43 return THREAD_Current()->process;
46 /***********************************************************************
49 * FIXME: This works only while running all processes in the same
50 * address space (or, at least, the initial process is mapped
51 * into all address spaces as is KERNEL32 in Windows 95)
54 PDB32 *PROCESS_Initial(void)
56 return PROCESS_IdToPDB( PROCESS_InitialProcessID );
59 /***********************************************************************
62 * Retrieve information about a process
64 static BOOL32 PROCESS_QueryInfo( HANDLE32 handle,
65 struct get_process_info_reply *reply )
67 struct get_process_info_request req;
68 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
69 K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
70 CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
71 return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
74 /***********************************************************************
77 * Check if a handle is to the current process
79 BOOL32 PROCESS_IsCurrent( HANDLE32 handle )
81 struct get_process_info_reply reply;
82 return (PROCESS_QueryInfo( handle, &reply ) &&
83 (reply.pid == PROCESS_Current()->server_pid));
87 /***********************************************************************
90 * Convert a process id to a PDB, making sure it is valid.
92 PDB32 *PROCESS_IdToPDB( DWORD id )
96 if (!id) return PROCESS_Current();
97 pdb = PROCESS_ID_TO_PDB( id );
98 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
100 SetLastError( ERROR_INVALID_PARAMETER );
108 /***********************************************************************
111 * Build the env DB for the initial process
113 static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
115 /* Allocate the env DB (FIXME: should not be on the system heap) */
117 if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
119 InitializeCriticalSection( &pdb->env_db->section );
121 /* Allocate startup info */
122 if (!(pdb->env_db->startup_info =
123 HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
126 /* Allocate the standard handles */
128 pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
129 pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
130 pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
132 /* Build the command-line */
134 pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
136 /* Build the environment strings */
138 return ENV_BuildEnvironment( pdb );
142 /***********************************************************************
143 * PROCESS_InheritEnvDB
145 static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
146 BOOL32 inherit_handles, STARTUPINFO32A *startup )
148 if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
150 InitializeCriticalSection( &pdb->env_db->section );
152 /* Copy the parent environment */
154 if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
156 /* Copy the command line */
158 if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
161 /* Remember startup info */
162 if (!(pdb->env_db->startup_info =
163 HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
165 *pdb->env_db->startup_info = *startup;
167 /* Inherit the standard handles */
168 if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
170 pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
171 pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
172 pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
174 else if (inherit_handles)
176 pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
177 pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
178 pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
180 /* else will be done later on in PROCESS_Create */
185 /***********************************************************************
186 * PROCESS_PDBList_Insert
187 * Insert this PDB into the global PDB list
190 static void PROCESS_PDBList_Insert (PDB32 *pdb)
192 TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
193 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
195 SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
196 * I.e., could more than one process be
199 if (PROCESS_PDBList == NULL)
201 PROCESS_PDBList = pdb;
202 pdb->list_next = NULL;
203 pdb->list_prev = NULL;
207 PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList;
208 if (first->list_prev) last = first->list_prev;
210 PROCESS_PDBList = pdb;
211 pdb->list_next = first;
212 pdb->list_prev = last;
213 last->list_next = pdb;
214 first->list_prev = pdb;
216 PROCESS_PDBList_Size ++;
220 /***********************************************************************
221 * PROCESS_PDBList_Remove
222 * Remove this PDB from the global PDB list
225 static void PROCESS_PDBList_Remove (PDB32 *pdb)
227 PDB32 *next = pdb->list_next, *prev = pdb->list_prev;
229 TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
230 PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
236 next->list_prev = NULL;
237 next->list_next = NULL;
241 if (next) next->list_prev = prev;
242 if (prev) prev->list_next = next;
245 if (pdb == PROCESS_PDBList)
247 PROCESS_PDBList = next ? next : prev;
249 PROCESS_PDBList_Size --;
254 /***********************************************************************
255 * PROCESS_PDBList_Getsize
256 * Return the number of items in the global PDB list
259 int PROCESS_PDBList_Getsize ()
261 return PROCESS_PDBList_Size;
264 /***********************************************************************
265 * PROCESS_PDBList_Getfirst
266 * Return the head of the PDB list
269 PDB32* PROCESS_PDBList_Getfirst ()
271 return PROCESS_PDBList;
274 /***********************************************************************
275 * PROCESS_PDBList_Getnext
276 * Return the "next" pdb as referenced from the argument.
277 * If at the end of the list, return NULL.
280 PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb)
282 return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
285 /***********************************************************************
288 * Free a PDB and all associated storage.
290 static void PROCESS_FreePDB( PDB32 *pdb )
294 * If this routine is called because PROCESS_CreatePDB fails, the
295 * following call to PROCESS_PDBList_Remove will probably screw
298 PROCESS_PDBList_Remove (pdb);
299 pdb->header.type = K32OBJ_UNKNOWN;
300 if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
301 ENV_FreeEnvironment( pdb );
302 if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
303 DeleteCriticalSection( &pdb->crit_section );
304 HeapFree( SystemHeap, 0, pdb );
308 /***********************************************************************
311 * Allocate and fill a PDB structure.
312 * Runs in the context of the parent process.
314 static PDB32 *PROCESS_CreatePDB( PDB32 *parent, BOOL32 inherit )
316 PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
318 if (!pdb) return NULL;
319 pdb->header.type = K32OBJ_PROCESS;
320 pdb->header.refcount = 1;
321 pdb->exit_code = 0x103; /* STILL_ACTIVE */
323 pdb->running_threads = 1;
324 pdb->ring0_threads = 1;
325 pdb->system_heap = SystemHeap;
326 pdb->parent = parent;
328 pdb->priority = 8; /* Normal */
329 pdb->heap = pdb->system_heap; /* will be changed later on */
331 /* Create the handle table */
333 if (!HANDLE_CreateTable( pdb, inherit )) goto error;
335 PROCESS_PDBList_Insert (pdb);
339 PROCESS_FreePDB( pdb );
344 /***********************************************************************
345 * PROCESS_FinishCreatePDB
347 * Second part of CreatePDB
349 static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
351 InitializeCriticalSection( &pdb->crit_section );
352 /* Allocate the event */
353 if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
359 /***********************************************************************
362 BOOL32 PROCESS_Init(void)
367 /* Initialize virtual memory management */
368 if (!VIRTUAL_Init()) return FALSE;
370 /* Create the system heaps */
371 if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
373 /* Create the initial process and thread structures */
374 if (!(pdb = PROCESS_CreatePDB( NULL, FALSE ))) return FALSE;
375 if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
376 thdb->unix_pid = getpid();
378 PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
380 /* Remember TEB selector of initial process for emergency use */
381 SYSLEVEL_EmergencyTeb = thdb->teb_sel;
383 /* Create the environment DB of the first process */
384 if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
386 /* Initialize the first thread */
387 if (CLIENT_InitThread()) return FALSE;
388 if (!PROCESS_FinishCreatePDB( pdb )) return FALSE;
390 /* Create the SEGPTR heap */
391 if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
397 /***********************************************************************
400 * Create a new process database and associated info.
402 PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
403 HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
404 BOOL32 inherit, STARTUPINFO32A *startup,
405 PROCESS_INFORMATION *info )
408 int server_thandle, server_phandle;
411 PDB32 *parent = PROCESS_Current();
412 PDB32 *pdb = PROCESS_CreatePDB( parent, inherit );
415 if (!pdb) return NULL;
416 info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
417 if (!PROCESS_FinishCreatePDB( pdb )) goto error;
419 /* Create the heap */
421 if (pModule->module32)
423 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
424 commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
430 pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
432 if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
433 pdb->heap_list = pdb->heap;
435 /* Inherit the env DB from the parent */
437 if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
439 /* Create the main thread */
441 if (pModule->module32)
442 size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
445 if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
446 NULL, NULL ))) goto error;
447 if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
448 FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
450 if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
451 FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
453 info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
454 info->dwThreadId = THDB_TO_THREAD_ID(thdb);
457 thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
459 /* All Win16 'threads' have the same unix_pid, no matter by which thread
460 they were created ! */
461 pTask = (TDB *)GlobalLock16( parent->task );
462 thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
465 /* Duplicate the standard handles */
467 if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
469 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
470 info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
471 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
472 info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
473 DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
474 info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
477 /* Create a Win16 task for this process */
479 if (startup->dwFlags & STARTF_USESHOWWINDOW)
480 cmdShow = startup->wShowWindow;
482 pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
483 if (!pdb->task) goto error;
486 /* Map system DLLs into this process (from initial process) */
487 /* FIXME: this is a hack */
488 pdb->modref_list = PROCESS_Initial()->modref_list;
494 if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
495 if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
496 if (thdb) K32OBJ_DecCount( &thdb->header );
497 PROCESS_FreePDB( pdb );
502 /***********************************************************************
505 static void PROCESS_Destroy( K32OBJ *ptr )
507 PDB32 *pdb = (PDB32 *)ptr;
508 assert( ptr->type == K32OBJ_PROCESS );
510 /* Free everything */
512 ptr->type = K32OBJ_UNKNOWN;
513 PROCESS_FreePDB( pdb );
517 /***********************************************************************
518 * ExitProcess (KERNEL32.100)
520 void WINAPI ExitProcess( DWORD status )
522 PDB32 *pdb = PROCESS_Current();
523 TDB *pTask = (TDB *)GlobalLock16( pdb->task );
524 if ( pTask ) pTask->nEvents++;
526 if ( pTask && pTask->thdb != THREAD_Current() )
527 ExitThread( status );
530 /* FIXME: should kill all running threads of this process */
531 pdb->exit_code = status;
532 if (pdb->console) FreeConsole();
535 __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
536 TASK_KillCurrentTask( status );
540 /******************************************************************************
541 * TerminateProcess (KERNEL32.684)
543 BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
545 struct terminate_process_request req;
547 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
548 K32OBJ_PROCESS, PROCESS_TERMINATE );
549 req.exit_code = exit_code;
550 CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
551 return !CLIENT_WaitReply( NULL, NULL, 0 );
554 /***********************************************************************
555 * GetCurrentProcess (KERNEL32.198)
557 HANDLE32 WINAPI GetCurrentProcess(void)
559 return CURRENT_PROCESS_PSEUDOHANDLE;
563 /*********************************************************************
564 * OpenProcess (KERNEL32.543)
566 HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
569 PDB32 *pdb = PROCESS_ID_TO_PDB(id);
570 if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
572 SetLastError( ERROR_INVALID_HANDLE );
575 if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
577 SetLastError( ERROR_INVALID_HANDLE );
580 return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
581 inherit, server_handle );
585 /***********************************************************************
586 * GetCurrentProcessId (KERNEL32.199)
588 DWORD WINAPI GetCurrentProcessId(void)
590 PDB32 *pdb = PROCESS_Current();
591 return PDB_TO_PROCESS_ID( pdb );
595 /***********************************************************************
596 * GetProcessHeap (KERNEL32.259)
598 HANDLE32 WINAPI GetProcessHeap(void)
600 PDB32 *pdb = PROCESS_Current();
601 return pdb->heap ? pdb->heap : SystemHeap;
605 /***********************************************************************
606 * GetThreadLocale (KERNEL32.295)
608 LCID WINAPI GetThreadLocale(void)
610 return PROCESS_Current()->locale;
614 /***********************************************************************
615 * SetPriorityClass (KERNEL32.503)
617 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
619 struct set_process_info_request req;
620 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
621 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
622 if (req.handle == -1) return FALSE;
623 req.priority = priorityclass;
624 req.mask = SET_PROCESS_INFO_PRIORITY;
625 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
626 return !CLIENT_WaitReply( NULL, NULL, 0 );
630 /***********************************************************************
631 * GetPriorityClass (KERNEL32.250)
633 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
635 struct get_process_info_reply reply;
636 if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
637 return reply.priority;
641 /***********************************************************************
642 * SetProcessAffinityMask (KERNEL32.662)
644 BOOL32 WINAPI SetProcessAffinityMask( HANDLE32 hProcess, DWORD affmask )
646 struct set_process_info_request req;
647 req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
648 K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
649 if (req.handle == -1) return FALSE;
650 req.affinity = affmask;
651 req.mask = SET_PROCESS_INFO_AFFINITY;
652 CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
653 return !CLIENT_WaitReply( NULL, NULL, 0 );
656 /**********************************************************************
657 * GetProcessAffinityMask (KERNEL32.373)
659 BOOL32 WINAPI GetProcessAffinityMask( HANDLE32 hProcess,
660 LPDWORD lpProcessAffinityMask,
661 LPDWORD lpSystemAffinityMask )
663 struct get_process_info_reply reply;
664 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
665 if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
666 if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
671 /***********************************************************************
672 * GetStdHandle (KERNEL32.276)
674 HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
676 PDB32 *pdb = PROCESS_Current();
680 case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
681 case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
682 case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
684 SetLastError( ERROR_INVALID_PARAMETER );
685 return INVALID_HANDLE_VALUE32;
689 /***********************************************************************
690 * SetStdHandle (KERNEL32.506)
692 BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
694 PDB32 *pdb = PROCESS_Current();
695 /* FIXME: should we close the previous handle? */
698 case STD_INPUT_HANDLE:
699 pdb->env_db->hStdin = handle;
701 case STD_OUTPUT_HANDLE:
702 pdb->env_db->hStdout = handle;
704 case STD_ERROR_HANDLE:
705 pdb->env_db->hStderr = handle;
708 SetLastError( ERROR_INVALID_PARAMETER );
712 /***********************************************************************
713 * GetProcessVersion (KERNEL32)
715 DWORD WINAPI GetProcessVersion( DWORD processid )
718 PDB32 *pdb = PROCESS_IdToPDB( processid );
721 if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
722 return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
725 /***********************************************************************
726 * GetProcessFlags (KERNEL32)
728 DWORD WINAPI GetProcessFlags( DWORD processid )
730 PDB32 *pdb = PROCESS_IdToPDB( processid );
735 /***********************************************************************
736 * SetProcessWorkingSetSize [KERNEL32.662]
737 * Sets the min/max working set sizes for a specified process.
740 * hProcess [I] Handle to the process of interest
741 * minset [I] Specifies minimum working set size
742 * maxset [I] Specifies maximum working set size
746 BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
749 FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
750 if(( minset == -1) && (maxset == -1)) {
751 /* Trim the working set to zero */
752 /* Swap the process out of physical RAM */
757 /***********************************************************************
758 * GetProcessWorkingSetSize (KERNEL32)
760 BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
763 FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
764 /* 32 MB working set size */
765 if (minset) *minset = 32*1024*1024;
766 if (maxset) *maxset = 32*1024*1024;
770 /***********************************************************************
771 * SetProcessShutdownParameters (KERNEL32)
773 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
774 * Now tracks changes made (but does not act on these changes)
775 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
776 * It really shouldn't be here, but I'll move it when it's been checked!
778 #define SHUTDOWN_NORETRY 1
779 static unsigned int shutdown_noretry = 0;
780 static unsigned int shutdown_priority = 0x280L;
781 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
783 if (flags & SHUTDOWN_NORETRY)
784 shutdown_noretry = 1;
786 shutdown_noretry = 0;
787 if (level > 0x100L && level < 0x3FFL)
788 shutdown_priority = level;
791 ERR(process,"invalid priority level 0x%08lx\n", level);
798 /***********************************************************************
799 * GetProcessShutdownParameters (KERNEL32)
802 BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
805 (*lpdwLevel) = shutdown_priority;
806 (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
809 /***********************************************************************
810 * SetProcessPriorityBoost (KERNEL32)
812 BOOL32 WINAPI SetProcessPriorityBoost(HANDLE32 hprocess,BOOL32 disableboost)
814 FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
815 /* Say we can do it. I doubt the program will notice that we don't. */
819 /***********************************************************************
820 * ReadProcessMemory (KERNEL32)
821 * FIXME: check this, if we ever run win32 binaries in different addressspaces
822 * ... and add a sizecheck
824 BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
825 LPVOID lpBuffer, DWORD nSize,
826 LPDWORD lpNumberOfBytesRead )
828 memcpy(lpBuffer,lpBaseAddress,nSize);
829 if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
833 /***********************************************************************
834 * WriteProcessMemory (KERNEL32)
835 * FIXME: check this, if we ever run win32 binaries in different addressspaces
836 * ... and add a sizecheck
838 BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
839 LPVOID lpBuffer, DWORD nSize,
840 LPDWORD lpNumberOfBytesWritten )
842 memcpy(lpBaseAddress,lpBuffer,nSize);
843 if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
847 /***********************************************************************
848 * RegisterServiceProcess (KERNEL, KERNEL32)
850 * A service process calls this function to ensure that it continues to run
851 * even after a user logged off.
853 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
855 /* I don't think that Wine needs to do anything in that function */
856 return 1; /* success */
859 /***********************************************************************
860 * GetExitCodeProcess [KERNEL32.325]
862 * Gets termination status of specified process
868 BOOL32 WINAPI GetExitCodeProcess(
869 HANDLE32 hProcess, /* [I] handle to the process */
870 LPDWORD lpExitCode) /* [O] address to receive termination status */
872 struct get_process_info_reply reply;
873 if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
874 if (lpExitCode) *lpExitCode = reply.exit_code;
879 /***********************************************************************
880 * GetProcessHeaps [KERNEL32.376]
882 DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
883 FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
886 heaps[0] = GetProcessHeap();
887 /* ... probably SystemHeap too ? */
890 /* number of available heaps */
894 /***********************************************************************
895 * PROCESS_SuspendOtherThreads
898 void PROCESS_SuspendOtherThreads(void)
905 pdb = PROCESS_Current();
906 entry = pdb->thread_list->next;
909 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
911 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
912 &entry->thread->header,
913 THREAD_ALL_ACCESS, FALSE, -1 );
914 SuspendThread(handle);
917 if (entry == pdb->thread_list) break;
924 /***********************************************************************
925 * PROCESS_ResumeOtherThreads
928 void PROCESS_ResumeOtherThreads(void)
935 pdb = PROCESS_Current();
936 entry = pdb->thread_list->next;
939 if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
941 HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
942 &entry->thread->header,
943 THREAD_ALL_ACCESS, FALSE, -1 );
944 ResumeThread(handle);
947 if (entry == pdb->thread_list) break;