1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/scheduler/process.c
Alexandre Julliard 0562539d18 Implemented file sharing checks in the server.
Added set file time server request.
Overall clean up of the file handling (DOS device handling is now
broken, should be redone).
1999-01-03 11:55:56 +00:00

944 lines
27 KiB
C

/*
* Win32 processes
*
* Copyright 1996, 1998 Alexandre Julliard
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "process.h"
#include "module.h"
#include "file.h"
#include "global.h"
#include "heap.h"
#include "task.h"
#include "ldt.h"
#include "syslevel.h"
#include "thread.h"
#include "winerror.h"
#include "pe_image.h"
#include "task.h"
#include "server.h"
#include "debug.h"
static void PROCESS_Destroy( K32OBJ *obj );
const K32OBJ_OPS PROCESS_Ops =
{
PROCESS_Destroy /* destroy */
};
static DWORD PROCESS_InitialProcessID = 0;
static PDB32 *PROCESS_PDBList = NULL;
static DWORD PROCESS_PDBList_Size = 0;
/***********************************************************************
* PROCESS_Current
*/
PDB32 *PROCESS_Current(void)
{
return THREAD_Current()->process;
}
/***********************************************************************
* PROCESS_Initial
*
* FIXME: This works only while running all processes in the same
* address space (or, at least, the initial process is mapped
* into all address spaces as is KERNEL32 in Windows 95)
*
*/
PDB32 *PROCESS_Initial(void)
{
return PROCESS_IdToPDB( PROCESS_InitialProcessID );
}
/***********************************************************************
* PROCESS_GetPtr
*
* Get a process from a handle, incrementing the PDB refcount.
*/
PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
{
return (PDB32 *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
K32OBJ_PROCESS, access, server_handle );
}
/***********************************************************************
* PROCESS_IdToPDB
*
* Convert a process id to a PDB, making sure it is valid.
*/
PDB32 *PROCESS_IdToPDB( DWORD id )
{
PDB32 *pdb;
if (!id) return PROCESS_Current();
pdb = PROCESS_ID_TO_PDB( id );
if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
{
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
return pdb;
}
/***********************************************************************
* PROCESS_BuildEnvDB
*
* Build the env DB for the initial process
*/
static BOOL32 PROCESS_BuildEnvDB( PDB32 *pdb )
{
/* Allocate the env DB (FIXME: should not be on the system heap) */
if (!(pdb->env_db = HeapAlloc(SystemHeap,HEAP_ZERO_MEMORY,sizeof(ENVDB))))
return FALSE;
InitializeCriticalSection( &pdb->env_db->section );
/* Allocate startup info */
if (!(pdb->env_db->startup_info =
HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
return FALSE;
/* Allocate the standard handles */
pdb->env_db->hStdin = FILE_DupUnixHandle( 0, GENERIC_READ );
pdb->env_db->hStdout = FILE_DupUnixHandle( 1, GENERIC_WRITE );
pdb->env_db->hStderr = FILE_DupUnixHandle( 2, GENERIC_WRITE );
/* Build the command-line */
pdb->env_db->cmd_line = HEAP_strdupA( SystemHeap, 0, "kernel32" );
/* Build the environment strings */
return ENV_BuildEnvironment( pdb );
}
/***********************************************************************
* PROCESS_InheritEnvDB
*/
static BOOL32 PROCESS_InheritEnvDB( PDB32 *pdb, LPCSTR cmd_line, LPCSTR env,
BOOL32 inherit_handles, STARTUPINFO32A *startup )
{
if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
return FALSE;
InitializeCriticalSection( &pdb->env_db->section );
/* Copy the parent environment */
if (!ENV_InheritEnvironment( pdb, env )) return FALSE;
/* Copy the command line */
if (!(pdb->env_db->cmd_line = HEAP_strdupA( pdb->heap, 0, cmd_line )))
return FALSE;
/* Remember startup info */
if (!(pdb->env_db->startup_info =
HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFO32A) )))
return FALSE;
*pdb->env_db->startup_info = *startup;
/* Inherit the standard handles */
if (pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)
{
pdb->env_db->hStdin = pdb->env_db->startup_info->hStdInput;
pdb->env_db->hStdout = pdb->env_db->startup_info->hStdOutput;
pdb->env_db->hStderr = pdb->env_db->startup_info->hStdError;
}
else if (inherit_handles)
{
pdb->env_db->hStdin = pdb->parent->env_db->hStdin;
pdb->env_db->hStdout = pdb->parent->env_db->hStdout;
pdb->env_db->hStderr = pdb->parent->env_db->hStderr;
}
/* else will be done later on in PROCESS_Create */
return TRUE;
}
/***********************************************************************
* PROCESS_PDBList_Insert
* Insert this PDB into the global PDB list
*/
static void PROCESS_PDBList_Insert (PDB32 *pdb)
{
TRACE (process, "Inserting PDB 0x%0lx, #%ld current\n",
PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
SYSTEM_LOCK (); /* FIXME: Do I need to worry about this ?
* I.e., could more than one process be
* created at once ?
*/
if (PROCESS_PDBList == NULL)
{
PROCESS_PDBList = pdb;
pdb->list_next = NULL;
pdb->list_prev = NULL;
}
else
{
PDB32 *first = PROCESS_PDBList, *last = PROCESS_PDBList;
if (first->list_prev) last = first->list_prev;
PROCESS_PDBList = pdb;
pdb->list_next = first;
pdb->list_prev = last;
last->list_next = pdb;
first->list_prev = pdb;
}
PROCESS_PDBList_Size ++;
SYSTEM_UNLOCK ();
}
/***********************************************************************
* PROCESS_PDBList_Remove
* Remove this PDB from the global PDB list
*/
static void PROCESS_PDBList_Remove (PDB32 *pdb)
{
PDB32 *next = pdb->list_next, *prev = pdb->list_prev;
TRACE (process, "Removing PDB 0x%0lx, #%ld current\n",
PDB_TO_PROCESS_ID (pdb), PROCESS_PDBList_Size);
SYSTEM_LOCK ();
if (prev == next)
{
next->list_prev = NULL;
next->list_next = NULL;
}
else
{
if (next) next->list_prev = prev;
if (prev) prev->list_next = next;
}
if (pdb == PROCESS_PDBList)
{
PROCESS_PDBList = next ? next : prev;
}
PROCESS_PDBList_Size --;
SYSTEM_UNLOCK ();
}
/***********************************************************************
* PROCESS_PDBList_Getsize
* Return the number of items in the global PDB list
*/
int PROCESS_PDBList_Getsize ()
{
return PROCESS_PDBList_Size;
}
/***********************************************************************
* PROCESS_PDBList_Getfirst
* Return the head of the PDB list
*/
PDB32* PROCESS_PDBList_Getfirst ()
{
return PROCESS_PDBList;
}
/***********************************************************************
* PROCESS_PDBList_Getnext
* Return the "next" pdb as referenced from the argument.
* If at the end of the list, return NULL.
*/
PDB32* PROCESS_PDBList_Getnext (PDB32 *pdb)
{
return (pdb->list_next != PROCESS_PDBList) ? pdb->list_next : NULL;
}
/***********************************************************************
* PROCESS_FreePDB
*
* Free a PDB and all associated storage.
*/
static void PROCESS_FreePDB( PDB32 *pdb )
{
/*
* FIXME:
* If this routine is called because PROCESS_CreatePDB fails, the
* following call to PROCESS_PDBList_Remove will probably screw
* up.
*/
PROCESS_PDBList_Remove (pdb);
pdb->header.type = K32OBJ_UNKNOWN;
if (pdb->handle_table) HANDLE_CloseAll( pdb, NULL );
ENV_FreeEnvironment( pdb );
if (pdb->heap && (pdb->heap != pdb->system_heap)) HeapDestroy( pdb->heap );
DeleteCriticalSection( &pdb->crit_section );
HeapFree( SystemHeap, 0, pdb );
}
/***********************************************************************
* PROCESS_CreatePDB
*
* Allocate and fill a PDB structure.
* Runs in the context of the parent process.
*/
static PDB32 *PROCESS_CreatePDB( PDB32 *parent, BOOL32 inherit )
{
PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
if (!pdb) return NULL;
pdb->header.type = K32OBJ_PROCESS;
pdb->header.refcount = 1;
pdb->exit_code = 0x103; /* STILL_ACTIVE */
pdb->threads = 1;
pdb->running_threads = 1;
pdb->ring0_threads = 1;
pdb->system_heap = SystemHeap;
pdb->parent = parent;
pdb->group = pdb;
pdb->priority = 8; /* Normal */
pdb->heap = pdb->system_heap; /* will be changed later on */
/* Create the handle table */
if (!HANDLE_CreateTable( pdb, inherit )) goto error;
PROCESS_PDBList_Insert (pdb);
return pdb;
error:
PROCESS_FreePDB( pdb );
return NULL;
}
/***********************************************************************
* PROCESS_FinishCreatePDB
*
* Second part of CreatePDB
*/
static BOOL32 PROCESS_FinishCreatePDB( PDB32 *pdb )
{
InitializeCriticalSection( &pdb->crit_section );
/* Allocate the event */
if (!(pdb->load_done_evt = CreateEvent32A( NULL, TRUE, FALSE, NULL )))
return FALSE;
return TRUE;
}
/***********************************************************************
* PROCESS_Init
*/
BOOL32 PROCESS_Init(void)
{
PDB32 *pdb;
THDB *thdb;
/* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE;
/* Create the system heaps */
if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
/* Create the initial process and thread structures */
if (!(pdb = PROCESS_CreatePDB( NULL, FALSE ))) return FALSE;
if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
thdb->unix_pid = getpid();
PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
/* Remember TEB selector of initial process for emergency use */
SYSLEVEL_EmergencyTeb = thdb->teb_sel;
/* Create the environment DB of the first process */
if (!PROCESS_BuildEnvDB( pdb )) return FALSE;
/* Initialize the first thread */
if (CLIENT_InitThread()) return FALSE;
if (!PROCESS_FinishCreatePDB( pdb )) return FALSE;
/* Create the SEGPTR heap */
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
return TRUE;
}
/***********************************************************************
* PROCESS_Create
*
* Create a new process database and associated info.
*/
PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
BOOL32 inherit, STARTUPINFO32A *startup,
PROCESS_INFORMATION *info )
{
DWORD size, commit;
int server_thandle, server_phandle;
UINT32 cmdShow = 0;
THDB *thdb = NULL;
PDB32 *parent = PROCESS_Current();
PDB32 *pdb = PROCESS_CreatePDB( parent, inherit );
TDB *pTask;
if (!pdb) return NULL;
info->hThread = info->hProcess = INVALID_HANDLE_VALUE32;
if (!PROCESS_FinishCreatePDB( pdb )) goto error;
/* Create the heap */
if (pModule->module32)
{
size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapReserve;
commit = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfHeapCommit;
}
else
{
size = 0x10000;
commit = 0;
pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
}
if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
pdb->heap_list = pdb->heap;
/* Inherit the env DB from the parent */
if (!PROCESS_InheritEnvDB( pdb, cmd_line, env, inherit, startup )) goto error;
/* Create the main thread */
if (pModule->module32)
size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
else
size = 0;
if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
NULL, NULL ))) goto error;
if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
FALSE, server_thandle )) == INVALID_HANDLE_VALUE32)
goto error;
if ((info->hProcess = HANDLE_Alloc( parent, &pdb->header, PROCESS_ALL_ACCESS,
FALSE, server_phandle )) == INVALID_HANDLE_VALUE32)
goto error;
info->dwProcessId = PDB_TO_PROCESS_ID(pdb);
info->dwThreadId = THDB_TO_THREAD_ID(thdb);
#if 0
thdb->unix_pid = getpid(); /* FIXME: wrong here ... */
#else
/* All Win16 'threads' have the same unix_pid, no matter by which thread
they were created ! */
pTask = (TDB *)GlobalLock16( parent->task );
thdb->unix_pid = pTask? pTask->thdb->unix_pid : THREAD_Current()->unix_pid;
#endif
/* Duplicate the standard handles */
if ((!(pdb->env_db->startup_info->dwFlags & STARTF_USESTDHANDLES)) && !inherit)
{
DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdin,
info->hProcess, &pdb->env_db->hStdin, 0, TRUE, DUPLICATE_SAME_ACCESS );
DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStdout,
info->hProcess, &pdb->env_db->hStdout, 0, TRUE, DUPLICATE_SAME_ACCESS );
DuplicateHandle( GetCurrentProcess(), pdb->parent->env_db->hStderr,
info->hProcess, &pdb->env_db->hStderr, 0, TRUE, DUPLICATE_SAME_ACCESS );
}
/* Create a Win16 task for this process */
if (startup->dwFlags & STARTF_USESHOWWINDOW)
cmdShow = startup->wShowWindow;
pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
if (!pdb->task) goto error;
/* Map system DLLs into this process (from initial process) */
/* FIXME: this is a hack */
pdb->modref_list = PROCESS_Initial()->modref_list;
return pdb;
error:
if (info->hThread != INVALID_HANDLE_VALUE32) CloseHandle( info->hThread );
if (info->hProcess != INVALID_HANDLE_VALUE32) CloseHandle( info->hProcess );
if (thdb) K32OBJ_DecCount( &thdb->header );
PROCESS_FreePDB( pdb );
return NULL;
}
/***********************************************************************
* PROCESS_Destroy
*/
static void PROCESS_Destroy( K32OBJ *ptr )
{
PDB32 *pdb = (PDB32 *)ptr;
assert( ptr->type == K32OBJ_PROCESS );
/* Free everything */
ptr->type = K32OBJ_UNKNOWN;
PROCESS_FreePDB( pdb );
}
/***********************************************************************
* ExitProcess (KERNEL32.100)
*/
void WINAPI ExitProcess( DWORD status )
{
PDB32 *pdb = PROCESS_Current();
TDB *pTask = (TDB *)GlobalLock16( pdb->task );
if ( pTask ) pTask->nEvents++;
if ( pTask && pTask->thdb != THREAD_Current() )
ExitThread( status );
SYSTEM_LOCK();
/* FIXME: should kill all running threads of this process */
pdb->exit_code = status;
if (pdb->console) FreeConsole();
SYSTEM_UNLOCK();
__RESTORE_ES; /* Necessary for Pietrek's showseh example program */
TASK_KillCurrentTask( status );
}
/******************************************************************************
* TerminateProcess (KERNEL32.684)
*/
BOOL32 WINAPI TerminateProcess( HANDLE32 handle, DWORD exit_code )
{
struct terminate_process_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_PROCESS, PROCESS_TERMINATE );
req.exit_code = exit_code;
CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
/***********************************************************************
* GetCurrentProcess (KERNEL32.198)
*/
HANDLE32 WINAPI GetCurrentProcess(void)
{
return CURRENT_PROCESS_PSEUDOHANDLE;
}
/*********************************************************************
* OpenProcess (KERNEL32.543)
*/
HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id )
{
int server_handle;
PDB32 *pdb = PROCESS_ID_TO_PDB(id);
if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
{
SetLastError( ERROR_INVALID_HANDLE );
return 0;
}
if ((server_handle = CLIENT_OpenProcess( pdb->server_pid, access, inherit )) == -1)
{
SetLastError( ERROR_INVALID_HANDLE );
return 0;
}
return HANDLE_Alloc( PROCESS_Current(), &pdb->header, access,
inherit, server_handle );
}
/***********************************************************************
* GetCurrentProcessId (KERNEL32.199)
*/
DWORD WINAPI GetCurrentProcessId(void)
{
PDB32 *pdb = PROCESS_Current();
return PDB_TO_PROCESS_ID( pdb );
}
/***********************************************************************
* GetProcessHeap (KERNEL32.259)
*/
HANDLE32 WINAPI GetProcessHeap(void)
{
PDB32 *pdb = PROCESS_Current();
return pdb->heap ? pdb->heap : SystemHeap;
}
/***********************************************************************
* GetThreadLocale (KERNEL32.295)
*/
LCID WINAPI GetThreadLocale(void)
{
return PROCESS_Current()->locale;
}
/***********************************************************************
* SetPriorityClass (KERNEL32.503)
*/
BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
{
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
if (!pdb) return FALSE;
switch (priorityclass)
{
case NORMAL_PRIORITY_CLASS:
pdb->priority = 0x00000008;
break;
case IDLE_PRIORITY_CLASS:
pdb->priority = 0x00000004;
break;
case HIGH_PRIORITY_CLASS:
pdb->priority = 0x0000000d;
break;
case REALTIME_PRIORITY_CLASS:
pdb->priority = 0x00000018;
break;
default:
WARN(process,"Unknown priority class %ld\n",priorityclass);
break;
}
K32OBJ_DecCount( &pdb->header );
return TRUE;
}
/***********************************************************************
* GetPriorityClass (KERNEL32.250)
*/
DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
{
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
DWORD ret = 0;
if (pdb)
{
switch (pdb->priority)
{
case 0x00000008:
ret = NORMAL_PRIORITY_CLASS;
break;
case 0x00000004:
ret = IDLE_PRIORITY_CLASS;
break;
case 0x0000000d:
ret = HIGH_PRIORITY_CLASS;
break;
case 0x00000018:
ret = REALTIME_PRIORITY_CLASS;
break;
default:
WARN(process,"Unknown priority %ld\n",pdb->priority);
}
K32OBJ_DecCount( &pdb->header );
}
return ret;
}
/***********************************************************************
* GetStdHandle (KERNEL32.276)
*/
HANDLE32 WINAPI GetStdHandle( DWORD std_handle )
{
PDB32 *pdb = PROCESS_Current();
switch(std_handle)
{
case STD_INPUT_HANDLE: return pdb->env_db->hStdin;
case STD_OUTPUT_HANDLE: return pdb->env_db->hStdout;
case STD_ERROR_HANDLE: return pdb->env_db->hStderr;
}
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE32;
}
/***********************************************************************
* SetStdHandle (KERNEL32.506)
*/
BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
{
PDB32 *pdb = PROCESS_Current();
/* FIXME: should we close the previous handle? */
switch(std_handle)
{
case STD_INPUT_HANDLE:
pdb->env_db->hStdin = handle;
return TRUE;
case STD_OUTPUT_HANDLE:
pdb->env_db->hStdout = handle;
return TRUE;
case STD_ERROR_HANDLE:
pdb->env_db->hStderr = handle;
return TRUE;
}
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
/***********************************************************************
* GetProcessVersion (KERNEL32)
*/
DWORD WINAPI GetProcessVersion( DWORD processid )
{
TDB *pTask;
PDB32 *pdb = PROCESS_IdToPDB( processid );
if (!pdb) return 0;
if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
}
/***********************************************************************
* GetProcessFlags (KERNEL32)
*/
DWORD WINAPI GetProcessFlags( DWORD processid )
{
PDB32 *pdb = PROCESS_IdToPDB( processid );
if (!pdb) return 0;
return pdb->flags;
}
/***********************************************************************
* SetProcessWorkingSetSize [KERNEL32.662]
* Sets the min/max working set sizes for a specified process.
*
* PARAMS
* hProcess [I] Handle to the process of interest
* minset [I] Specifies minimum working set size
* maxset [I] Specifies maximum working set size
*
* RETURNS STD
*/
BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32 hProcess,DWORD minset,
DWORD maxset)
{
FIXME(process,"(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
if(( minset == -1) && (maxset == -1)) {
/* Trim the working set to zero */
/* Swap the process out of physical RAM */
}
return TRUE;
}
/***********************************************************************
* GetProcessWorkingSetSize (KERNEL32)
*/
BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32 hProcess,LPDWORD minset,
LPDWORD maxset)
{
FIXME(process,"(0x%08x,%p,%p): stub\n",hProcess,minset,maxset);
/* 32 MB working set size */
if (minset) *minset = 32*1024*1024;
if (maxset) *maxset = 32*1024*1024;
return TRUE;
}
/***********************************************************************
* SetProcessShutdownParameters (KERNEL32)
*
* CHANGED - James Sutherland (JamesSutherland@gmx.de)
* Now tracks changes made (but does not act on these changes)
* NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
* It really shouldn't be here, but I'll move it when it's been checked!
*/
#define SHUTDOWN_NORETRY 1
static unsigned int shutdown_noretry = 0;
static unsigned int shutdown_priority = 0x280L;
BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
{
if (flags & SHUTDOWN_NORETRY)
shutdown_noretry = 1;
else
shutdown_noretry = 0;
if (level > 0x100L && level < 0x3FFL)
shutdown_priority = level;
else
{
ERR(process,"invalid priority level 0x%08lx\n", level);
return FALSE;
}
return TRUE;
}
/***********************************************************************
* GetProcessShutdownParameters (KERNEL32)
*
*/
BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
LPDWORD lpdwFlags )
{
(*lpdwLevel) = shutdown_priority;
(*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
return TRUE;
}
/***********************************************************************
* SetProcessPriorityBoost (KERNEL32)
*/
BOOL32 WINAPI SetProcessPriorityBoost(HANDLE32 hprocess,BOOL32 disableboost)
{
FIXME(process,"(%d,%d): stub\n",hprocess,disableboost);
/* Say we can do it. I doubt the program will notice that we don't. */
return TRUE;
}
/***********************************************************************
* ReadProcessMemory (KERNEL32)
* FIXME: check this, if we ever run win32 binaries in different addressspaces
* ... and add a sizecheck
*/
BOOL32 WINAPI ReadProcessMemory( HANDLE32 hProcess, LPCVOID lpBaseAddress,
LPVOID lpBuffer, DWORD nSize,
LPDWORD lpNumberOfBytesRead )
{
memcpy(lpBuffer,lpBaseAddress,nSize);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
return TRUE;
}
/***********************************************************************
* WriteProcessMemory (KERNEL32)
* FIXME: check this, if we ever run win32 binaries in different addressspaces
* ... and add a sizecheck
*/
BOOL32 WINAPI WriteProcessMemory(HANDLE32 hProcess, LPVOID lpBaseAddress,
LPVOID lpBuffer, DWORD nSize,
LPDWORD lpNumberOfBytesWritten )
{
memcpy(lpBaseAddress,lpBuffer,nSize);
if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
return TRUE;
}
/***********************************************************************
* RegisterServiceProcess (KERNEL, KERNEL32)
*
* A service process calls this function to ensure that it continues to run
* even after a user logged off.
*/
DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
{
/* I don't think that Wine needs to do anything in that function */
return 1; /* success */
}
/***********************************************************************
* GetExitCodeProcess [KERNEL32.325]
*
* Gets termination status of specified process
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL32 WINAPI GetExitCodeProcess(
HANDLE32 hProcess, /* [I] handle to the process */
LPDWORD lpExitCode) /* [O] address to receive termination status */
{
struct get_process_info_reply reply;
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &handle, sizeof(handle) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
if (lpExitCode) *lpExitCode = reply.exit_code;
return TRUE;
}
/***********************************************************************
* GetProcessHeaps [KERNEL32.376]
*/
DWORD WINAPI GetProcessHeaps(DWORD nrofheaps,HANDLE32 *heaps) {
FIXME(win32,"(%ld,%p), incomplete implementation.\n",nrofheaps,heaps);
if (nrofheaps) {
heaps[0] = GetProcessHeap();
/* ... probably SystemHeap too ? */
return 1;
}
/* number of available heaps */
return 1;
}
/***********************************************************************
* PROCESS_SuspendOtherThreads
*/
void PROCESS_SuspendOtherThreads(void)
{
PDB32 *pdb;
THREAD_ENTRY *entry;
SYSTEM_LOCK();
pdb = PROCESS_Current();
entry = pdb->thread_list->next;
for (;;)
{
if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
{
HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
&entry->thread->header,
THREAD_ALL_ACCESS, FALSE, -1 );
SuspendThread(handle);
CloseHandle(handle);
}
if (entry == pdb->thread_list) break;
entry = entry->next;
}
SYSTEM_UNLOCK();
}
/***********************************************************************
* PROCESS_ResumeOtherThreads
*/
void PROCESS_ResumeOtherThreads(void)
{
PDB32 *pdb;
THREAD_ENTRY *entry;
SYSTEM_LOCK();
pdb = PROCESS_Current();
entry = pdb->thread_list->next;
for (;;)
{
if (entry->thread != THREAD_Current() && !THREAD_IsWin16(entry->thread))
{
HANDLE32 handle = HANDLE_Alloc( PROCESS_Current(),
&entry->thread->header,
THREAD_ALL_ACCESS, FALSE, -1 );
ResumeThread(handle);
CloseHandle(handle);
}
if (entry == pdb->thread_list) break;
entry = entry->next;
}
SYSTEM_UNLOCK();
}