Moved some of the process functions to dlls/kernel.
Removed kernel dependencies from sysdeps.c and moved it to dlls/ntdll.
This commit is contained in:
parent
b379334271
commit
4cb212063b
|
@ -35,6 +35,7 @@ C_SRCS = \
|
|||
lcformat.c \
|
||||
local16.c \
|
||||
locale.c \
|
||||
process.c \
|
||||
resource.c \
|
||||
resource16.c \
|
||||
stress.c \
|
||||
|
|
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
* Win32 processes
|
||||
*
|
||||
* Copyright 1996, 1998 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include "wine/winbase16.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(process);
|
||||
|
||||
/* Process flags */
|
||||
#define PDB32_DEBUGGED 0x0001 /* Process is being debugged */
|
||||
#define PDB32_WIN16_PROC 0x0008 /* Win16 process */
|
||||
#define PDB32_DOS_PROC 0x0010 /* Dos process */
|
||||
#define PDB32_CONSOLE_PROC 0x0020 /* Console process */
|
||||
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
|
||||
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
|
||||
|
||||
|
||||
static DWORD shutdown_flags = 0;
|
||||
static DWORD shutdown_priority = 0x280;
|
||||
static DWORD process_dword;
|
||||
static BOOL oem_file_apis;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessFlags (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetProcessFlags( DWORD processid )
|
||||
{
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
DWORD flags = 0;
|
||||
|
||||
if (processid && processid != GetCurrentProcessId()) return 0;
|
||||
|
||||
if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
|
||||
{
|
||||
if (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||
flags |= PDB32_CONSOLE_PROC;
|
||||
}
|
||||
if (!AreFileApisANSI()) flags |= PDB32_FILE_APIS_OEM;
|
||||
if (IsDebuggerPresent()) flags |= PDB32_DEBUGGED;
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessDword (KERNEL.485)
|
||||
* GetProcessDword (KERNEL32.18)
|
||||
* 'Of course you cannot directly access Windows internal structures'
|
||||
*/
|
||||
DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
|
||||
{
|
||||
DWORD x, y;
|
||||
STARTUPINFOW siw;
|
||||
|
||||
TRACE("(%ld, %d)\n", dwProcessID, offset );
|
||||
|
||||
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
case GPD_APP_COMPAT_FLAGS:
|
||||
return GetAppCompatFlags16(0);
|
||||
case GPD_LOAD_DONE_EVENT:
|
||||
return 0;
|
||||
case GPD_HINSTANCE16:
|
||||
return GetTaskDS16();
|
||||
case GPD_WINDOWS_VERSION:
|
||||
return GetExeVersion16();
|
||||
case GPD_THDB:
|
||||
return (DWORD)NtCurrentTeb() - 0x10 /* FIXME */;
|
||||
case GPD_PDB:
|
||||
return (DWORD)NtCurrentTeb()->Peb;
|
||||
case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
|
||||
GetStartupInfoW(&siw);
|
||||
return (DWORD)siw.hStdOutput;
|
||||
case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
|
||||
GetStartupInfoW(&siw);
|
||||
return (DWORD)siw.hStdInput;
|
||||
case GPD_STARTF_SHOWWINDOW:
|
||||
GetStartupInfoW(&siw);
|
||||
return siw.wShowWindow;
|
||||
case GPD_STARTF_SIZE:
|
||||
GetStartupInfoW(&siw);
|
||||
x = siw.dwXSize;
|
||||
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
||||
y = siw.dwYSize;
|
||||
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
||||
return MAKELONG( x, y );
|
||||
case GPD_STARTF_POSITION:
|
||||
GetStartupInfoW(&siw);
|
||||
x = siw.dwX;
|
||||
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
||||
y = siw.dwY;
|
||||
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
||||
return MAKELONG( x, y );
|
||||
case GPD_STARTF_FLAGS:
|
||||
GetStartupInfoW(&siw);
|
||||
return siw.dwFlags;
|
||||
case GPD_PARENT:
|
||||
return 0;
|
||||
case GPD_FLAGS:
|
||||
return GetProcessFlags(0);
|
||||
case GPD_USERDATA:
|
||||
return process_dword;
|
||||
default:
|
||||
ERR("Unknown offset %d\n", offset );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessDword (KERNEL.484)
|
||||
* 'Of course you cannot directly access Windows internal structures'
|
||||
*/
|
||||
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
|
||||
{
|
||||
TRACE("(%ld, %d)\n", dwProcessID, offset );
|
||||
|
||||
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
case GPD_APP_COMPAT_FLAGS:
|
||||
case GPD_LOAD_DONE_EVENT:
|
||||
case GPD_HINSTANCE16:
|
||||
case GPD_WINDOWS_VERSION:
|
||||
case GPD_THDB:
|
||||
case GPD_PDB:
|
||||
case GPD_STARTF_SHELLDATA:
|
||||
case GPD_STARTF_HOTKEY:
|
||||
case GPD_STARTF_SHOWWINDOW:
|
||||
case GPD_STARTF_SIZE:
|
||||
case GPD_STARTF_POSITION:
|
||||
case GPD_STARTF_FLAGS:
|
||||
case GPD_PARENT:
|
||||
case GPD_FLAGS:
|
||||
ERR("Not allowed to modify offset %d\n", offset );
|
||||
break;
|
||||
case GPD_USERDATA:
|
||||
process_dword = value;
|
||||
break;
|
||||
default:
|
||||
ERR("Unknown offset %d\n", offset );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ExitProcess (KERNEL.466)
|
||||
*/
|
||||
void WINAPI ExitProcess16( WORD status )
|
||||
{
|
||||
DWORD count;
|
||||
ReleaseThunkLock( &count );
|
||||
ExitProcess( status );
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* OpenProcess (KERNEL32.@)
|
||||
*/
|
||||
HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
|
||||
{
|
||||
HANDLE ret = 0;
|
||||
SERVER_START_REQ( open_process )
|
||||
{
|
||||
req->pid = id;
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* MapProcessHandle (KERNEL.483)
|
||||
*/
|
||||
DWORD WINAPI MapProcessHandle( HANDLE handle )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->pid;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetPriorityClass (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( set_process_info )
|
||||
{
|
||||
req->handle = hprocess;
|
||||
req->priority = priorityclass;
|
||||
req->mask = SET_PROCESS_INFO_PRIORITY;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetPriorityClass (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetPriorityClass(HANDLE hprocess)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hprocess;
|
||||
if (!wine_server_call_err( req )) ret = reply->priority;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessAffinityMask (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( set_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
req->affinity = affmask;
|
||||
req->mask = SET_PROCESS_INFO_AFFINITY;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GetProcessAffinityMask (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
|
||||
LPDWORD lpProcessAffinityMask,
|
||||
LPDWORD lpSystemAffinityMask )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
|
||||
if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessVersion (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetProcessVersion( DWORD processid )
|
||||
{
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
||||
if (processid && processid != GetCurrentProcessId())
|
||||
{
|
||||
FIXME("should use ReadProcessMemory\n");
|
||||
return 0;
|
||||
}
|
||||
if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
|
||||
return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
|
||||
nt->OptionalHeader.MinorSubsystemVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessWorkingSetSize [KERNEL32.@]
|
||||
* 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
|
||||
*/
|
||||
BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess, SIZE_T minset,
|
||||
SIZE_T maxset)
|
||||
{
|
||||
FIXME("(%p,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
|
||||
if(( minset == (SIZE_T)-1) && (maxset == (SIZE_T)-1)) {
|
||||
/* Trim the working set to zero */
|
||||
/* Swap the process out of physical RAM */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessWorkingSetSize (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess, PSIZE_T minset,
|
||||
PSIZE_T maxset)
|
||||
{
|
||||
FIXME("(%p,%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.@)
|
||||
*/
|
||||
BOOL WINAPI SetProcessShutdownParameters(DWORD level, DWORD flags)
|
||||
{
|
||||
FIXME("(%08lx, %08lx): partial stub.\n", level, flags);
|
||||
shutdown_flags = flags;
|
||||
shutdown_priority = level;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessShutdownParameters (KERNEL32.@)
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags )
|
||||
{
|
||||
*lpdwLevel = shutdown_priority;
|
||||
*lpdwFlags = shutdown_flags;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessPriorityBoost (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessPriorityBoost(HANDLE hprocess,PBOOL pDisablePriorityBoost)
|
||||
{
|
||||
FIXME("(%p,%p): semi-stub\n", hprocess, pDisablePriorityBoost);
|
||||
|
||||
/* Report that no boost is present.. */
|
||||
*pDisablePriorityBoost = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessPriorityBoost (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
|
||||
{
|
||||
FIXME("(%p,%d): stub\n",hprocess,disableboost);
|
||||
/* Say we can do it. I doubt the program will notice that we don't. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ReadProcessMemory (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, SIZE_T size,
|
||||
SIZE_T *bytes_read )
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
SERVER_START_REQ( read_process_memory )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (void *)addr;
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_read) *bytes_read = size;
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WriteProcessMemory (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, SIZE_T size,
|
||||
SIZE_T *bytes_written )
|
||||
{
|
||||
static const int zero;
|
||||
unsigned int first_offset, last_offset, first_mask, last_mask;
|
||||
DWORD res;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* compute the mask for the first int */
|
||||
first_mask = ~0;
|
||||
first_offset = (unsigned int)addr % sizeof(int);
|
||||
memset( &first_mask, 0, first_offset );
|
||||
|
||||
/* compute the mask for the last int */
|
||||
last_offset = (size + first_offset) % sizeof(int);
|
||||
last_mask = 0;
|
||||
memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) );
|
||||
|
||||
SERVER_START_REQ( write_process_memory )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (char *)addr - first_offset;
|
||||
req->first_mask = first_mask;
|
||||
req->last_mask = last_mask;
|
||||
if (first_offset) wine_server_add_data( req, &zero, first_offset );
|
||||
wine_server_add_data( req, buffer, size );
|
||||
if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset );
|
||||
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_written) *bytes_written = size;
|
||||
{
|
||||
char dummy[32];
|
||||
SIZE_T read;
|
||||
ReadProcessMemory( process, addr, dummy, sizeof(dummy), &read );
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RegisterServiceProcess (KERNEL.491)
|
||||
* RegisterServiceProcess (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 */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileApisToOEM (KERNEL32.@)
|
||||
*/
|
||||
VOID WINAPI SetFileApisToOEM(void)
|
||||
{
|
||||
oem_file_apis = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileApisToANSI (KERNEL32.@)
|
||||
*/
|
||||
VOID WINAPI SetFileApisToANSI(void)
|
||||
{
|
||||
oem_file_apis = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AreFileApisANSI [KERNEL32.@] Determines if file functions are using ANSI
|
||||
*
|
||||
* RETURNS
|
||||
* TRUE: Set of file functions is using ANSI code page
|
||||
* FALSE: Set of file functions is using OEM code page
|
||||
*/
|
||||
BOOL WINAPI AreFileApisANSI(void)
|
||||
{
|
||||
return !oem_file_apis;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetCurrentProcess (KERNEL32.@)
|
||||
*/
|
||||
#undef GetCurrentProcess
|
||||
HANDLE WINAPI GetCurrentProcess(void)
|
||||
{
|
||||
return (HANDLE)0xffffffff;
|
||||
}
|
|
@ -49,7 +49,6 @@ C_SRCS = \
|
|||
$(TOPOBJDIR)/scheduler/process.c \
|
||||
$(TOPOBJDIR)/scheduler/pthread.c \
|
||||
$(TOPOBJDIR)/scheduler/synchro.c \
|
||||
$(TOPOBJDIR)/scheduler/sysdeps.c \
|
||||
$(TOPOBJDIR)/scheduler/syslevel.c \
|
||||
$(TOPOBJDIR)/scheduler/thread.c \
|
||||
$(TOPOBJDIR)/win32/device.c \
|
||||
|
@ -80,6 +79,7 @@ C_SRCS = \
|
|||
signal_sparc.c \
|
||||
string.c \
|
||||
sync.c \
|
||||
sysdeps.c \
|
||||
thread.c \
|
||||
time.c \
|
||||
virtual.c \
|
||||
|
|
|
@ -55,8 +55,6 @@
|
|||
#include "thread.h"
|
||||
#include "wine/server.h"
|
||||
#include "winbase.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/library.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -100,27 +98,6 @@ void SYSDEPS_SetCurThread( TEB *teb )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_on_thread_stack
|
||||
*
|
||||
* Call a function once we switched to the thread stack.
|
||||
*/
|
||||
static void call_on_thread_stack( void *func )
|
||||
{
|
||||
__TRY
|
||||
{
|
||||
void (*funcptr)(void) = func;
|
||||
funcptr();
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
SYSDEPS_ExitThread(0); /* should never get here */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_temp_stack
|
||||
*
|
||||
|
@ -161,15 +138,7 @@ static void SYSDEPS_StartThread( TEB *teb )
|
|||
SYSDEPS_SetCurThread( teb );
|
||||
SIGNAL_Init();
|
||||
CLIENT_InitThread();
|
||||
__TRY
|
||||
{
|
||||
teb->startup();
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
teb->startup();
|
||||
SYSDEPS_ExitThread(0); /* should never get here */
|
||||
}
|
||||
|
||||
|
@ -230,12 +199,15 @@ int SYSDEPS_SpawnThread( TEB *teb )
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* SYSDEPS_CallOnStack
|
||||
* SYSDEPS_SwitchToThreadStack
|
||||
*
|
||||
* Switch to the stack specified in the current thread TEB
|
||||
* and call the specified function.
|
||||
*/
|
||||
void DECLSPEC_NORETURN SYSDEPS_CallOnStack( void (*func)(LPVOID), LPVOID arg );
|
||||
void DECLSPEC_NORETURN SYSDEPS_SwitchToThreadStack( void (*func)(void *), void *arg );
|
||||
#ifdef __i386__
|
||||
# ifdef __GNUC__
|
||||
__ASM_GLOBAL_FUNC( SYSDEPS_CallOnStack,
|
||||
__ASM_GLOBAL_FUNC( SYSDEPS_SwitchToThreadStack,
|
||||
"movl 4(%esp),%ecx\n\t" /* func */
|
||||
"movl 8(%esp),%edx\n\t" /* arg */
|
||||
".byte 0x64\n\tmovl 0x04,%esp\n\t" /* teb->stack_top */
|
||||
|
@ -244,7 +216,7 @@ __ASM_GLOBAL_FUNC( SYSDEPS_CallOnStack,
|
|||
"call *%ecx\n\t"
|
||||
"int $3" /* we never return here */ );
|
||||
# elif defined(_MSC_VER)
|
||||
__declspec(naked) void SYSDEPS_CallOnStack( void (*func)(LPVOID), LPVOID arg )
|
||||
__declspec(naked) void SYSDEPS_SwitchToThreadStack( void (*func)(void *), void *arg )
|
||||
{
|
||||
__asm mov ecx, 4[esp];
|
||||
__asm mov edx, 8[esp];
|
||||
|
@ -256,7 +228,7 @@ __declspec(naked) void SYSDEPS_CallOnStack( void (*func)(LPVOID), LPVOID arg )
|
|||
}
|
||||
# endif /* defined(__GNUC__) || defined(_MSC_VER) */
|
||||
#elif defined(__sparc__) && defined(__GNUC__)
|
||||
__ASM_GLOBAL_FUNC( SYSDEPS_CallOnStack,
|
||||
__ASM_GLOBAL_FUNC( SYSDEPS_SwitchToThreadStack,
|
||||
"mov %o0, %l0\n\t" /* store first argument */
|
||||
"call " __ASM_NAME("NtCurrentTeb") ", 0\n\t"
|
||||
"mov %o1, %l1\n\t" /* delay slot: store second argument */
|
||||
|
@ -265,7 +237,7 @@ __ASM_GLOBAL_FUNC( SYSDEPS_CallOnStack,
|
|||
"mov %l1, %o0\n\t" /* delay slot: arg for func */
|
||||
"ta 0x01\n\t"); /* breakpoint - we never get here */
|
||||
#else /* !sparc, !i386 */
|
||||
void SYSDEPS_CallOnStack( void (*func)(LPVOID), LPVOID arg )
|
||||
void SYSDEPS_SwitchToThreadStack( void (*func)(void *), void *arg )
|
||||
{
|
||||
func( arg );
|
||||
while(1); /* avoid warning */
|
||||
|
@ -273,15 +245,6 @@ void SYSDEPS_CallOnStack( void (*func)(LPVOID), LPVOID arg )
|
|||
#endif /* !defined(__i386__) && !defined(__sparc__) */
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYSDEPS_SwitchToThreadStack
|
||||
*/
|
||||
void SYSDEPS_SwitchToThreadStack( void (*func)(void) )
|
||||
{
|
||||
SYSDEPS_CallOnStack( call_on_thread_stack, func );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SYSDEPS_ExitThread
|
||||
*
|
||||
|
@ -292,8 +255,10 @@ void SYSDEPS_ExitThread( int status )
|
|||
TEB *teb = NtCurrentTeb();
|
||||
struct thread_cleanup_info info;
|
||||
MEMORY_BASIC_INFORMATION meminfo;
|
||||
DWORD size = 0;
|
||||
|
||||
VirtualQuery( teb->stack_top, &meminfo, sizeof(meminfo) );
|
||||
NtQueryVirtualMemory( GetCurrentProcess(), teb->stack_top, MemoryBasicInformation,
|
||||
&meminfo, sizeof(meminfo), NULL );
|
||||
info.stack_base = meminfo.AllocationBase;
|
||||
info.stack_size = meminfo.RegionSize + ((char *)teb->stack_top - (char *)meminfo.AllocationBase);
|
||||
info.status = status;
|
||||
|
@ -304,14 +269,15 @@ void SYSDEPS_ExitThread( int status )
|
|||
SYSDEPS_AbortThread( status );
|
||||
#else
|
||||
SIGNAL_Reset();
|
||||
VirtualFree( teb->stack_base, 0, MEM_RELEASE | MEM_SYSTEM );
|
||||
size = 0;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &teb->stack_base, &size, MEM_RELEASE | MEM_SYSTEM );
|
||||
close( teb->wait_fd[0] );
|
||||
close( teb->wait_fd[1] );
|
||||
close( teb->reply_fd );
|
||||
close( teb->request_fd );
|
||||
teb->stack_low = get_temp_stack();
|
||||
teb->stack_top = (char *) teb->stack_low + TEMP_STACK_SIZE;
|
||||
SYSDEPS_CallOnStack( cleanup_thread, &info );
|
||||
SYSDEPS_SwitchToThreadStack( cleanup_thread, &info );
|
||||
#endif
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ extern int SYSDEPS_GetUnixTid(void);
|
|||
extern void SYSDEPS_InitErrno(void);
|
||||
extern void DECLSPEC_NORETURN SYSDEPS_ExitThread( int status );
|
||||
extern void DECLSPEC_NORETURN SYSDEPS_AbortThread( int status );
|
||||
extern void DECLSPEC_NORETURN SYSDEPS_SwitchToThreadStack( void (*func)(void) );
|
||||
extern void DECLSPEC_NORETURN SYSDEPS_SwitchToThreadStack( void (*func)(void *), void *arg );
|
||||
|
||||
/* signal handling */
|
||||
extern BOOL SIGNAL_Init(void);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/exception.h"
|
||||
#include "thread.h"
|
||||
|
||||
struct fiber_data
|
||||
|
@ -41,14 +42,22 @@ struct fiber_data
|
|||
|
||||
|
||||
/* call the fiber initial function once we have switched stack */
|
||||
static void start_fiber(void)
|
||||
static void start_fiber( void *arg )
|
||||
{
|
||||
struct fiber_data *fiber = NtCurrentTeb()->fiber;
|
||||
struct fiber_data *fiber = arg;
|
||||
LPFIBER_START_ROUTINE start = fiber->start;
|
||||
|
||||
fiber->start = NULL;
|
||||
start( fiber->param );
|
||||
ExitThread( 1 );
|
||||
__TRY
|
||||
{
|
||||
fiber->start = NULL;
|
||||
start( fiber->param );
|
||||
ExitThread( 1 );
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,7 +189,7 @@ void WINAPI SwitchToFiber( LPVOID fiber )
|
|||
NtCurrentTeb()->stack_low = new_fiber->stack_low;
|
||||
NtCurrentTeb()->stack_base = new_fiber->stack_base;
|
||||
if (new_fiber->start) /* first time */
|
||||
SYSDEPS_SwitchToThreadStack( start_fiber );
|
||||
SYSDEPS_SwitchToThreadStack( start_fiber, new_fiber );
|
||||
else
|
||||
longjmp( new_fiber->jmpbuf, 1 );
|
||||
}
|
||||
|
|
|
@ -109,14 +109,6 @@ PDB current_process;
|
|||
|
||||
static RTL_USER_PROCESS_PARAMETERS process_pmts;
|
||||
|
||||
/* Process flags */
|
||||
#define PDB32_DEBUGGED 0x0001 /* Process is being debugged */
|
||||
#define PDB32_WIN16_PROC 0x0008 /* Win16 process */
|
||||
#define PDB32_DOS_PROC 0x0010 /* Dos process */
|
||||
#define PDB32_CONSOLE_PROC 0x0020 /* Console process */
|
||||
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
|
||||
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
|
||||
|
||||
static char main_exe_name[MAX_PATH];
|
||||
static char *main_exe_name_ptr = main_exe_name;
|
||||
static HANDLE main_exe_file;
|
||||
|
@ -397,78 +389,73 @@ static BOOL process_init( char *argv[] )
|
|||
*
|
||||
* Startup routine of a new process. Runs on the new process stack.
|
||||
*/
|
||||
static void start_process(void)
|
||||
static void start_process( void *arg )
|
||||
{
|
||||
int debugged, console_app;
|
||||
LPTHREAD_START_ROUTINE entry;
|
||||
WINE_MODREF *wm;
|
||||
HANDLE main_file = main_exe_file;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
||||
/* use original argv[0] as name for the main module */
|
||||
if (!main_exe_name[0])
|
||||
__TRY
|
||||
{
|
||||
if (!GetLongPathNameA( full_argv0, main_exe_name, sizeof(main_exe_name) ))
|
||||
lstrcpynA( main_exe_name, full_argv0, sizeof(main_exe_name) );
|
||||
}
|
||||
LPTHREAD_START_ROUTINE entry;
|
||||
HANDLE main_file = main_exe_file;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
PEB *peb = NtCurrentTeb()->Peb;
|
||||
|
||||
if (main_file)
|
||||
if (main_file)
|
||||
{
|
||||
UINT drive_type = GetDriveTypeA( main_exe_name );
|
||||
/* don't keep the file handle open on removable media */
|
||||
if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) main_file = 0;
|
||||
}
|
||||
|
||||
/* Retrieve entry point address */
|
||||
nt = RtlImageNtHeader( peb->ImageBaseAddress );
|
||||
entry = (LPTHREAD_START_ROUTINE)((char*)peb->ImageBaseAddress +
|
||||
nt->OptionalHeader.AddressOfEntryPoint);
|
||||
|
||||
/* Install signal handlers; this cannot be done before, since we cannot
|
||||
* send exceptions to the debugger before the create process event that
|
||||
* is sent by REQ_INIT_PROCESS_DONE.
|
||||
* We do need the handlers in place by the time the request is over, so
|
||||
* we set them up here. If we segfault between here and the server call
|
||||
* something is very wrong... */
|
||||
if (!SIGNAL_Init()) goto error;
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
SERVER_START_REQ( init_process_done )
|
||||
{
|
||||
req->module = peb->ImageBaseAddress;
|
||||
req->module_size = nt->OptionalHeader.SizeOfImage;
|
||||
req->entry = entry;
|
||||
/* API requires a double indirection */
|
||||
req->name = &main_exe_name_ptr;
|
||||
req->exe_file = main_file;
|
||||
req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI);
|
||||
wine_server_add_data( req, main_exe_name, strlen(main_exe_name) );
|
||||
wine_server_call( req );
|
||||
peb->BeingDebugged = reply->debugged;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* create the main modref and load dependencies */
|
||||
if (!PE_CreateModule( peb->ImageBaseAddress, main_exe_name, 0, 0, FALSE )) goto error;
|
||||
|
||||
if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */
|
||||
|
||||
MODULE_DllProcessAttach( NULL, (LPVOID)1 );
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
DPRINTF( "%04lx:Starting process %s (entryproc=%p)\n",
|
||||
GetCurrentThreadId(), main_exe_name, entry );
|
||||
if (peb->BeingDebugged) DbgBreakPoint();
|
||||
SetLastError(0); /* clear error code */
|
||||
ExitThread( entry( NtCurrentTeb()->Peb ) );
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
UINT drive_type = GetDriveTypeA( main_exe_name );
|
||||
/* don't keep the file handle open on removable media */
|
||||
if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) main_file = 0;
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
|
||||
/* Retrieve entry point address */
|
||||
nt = RtlImageNtHeader( current_process.module );
|
||||
entry = (LPTHREAD_START_ROUTINE)((char*)current_process.module +
|
||||
nt->OptionalHeader.AddressOfEntryPoint);
|
||||
console_app = (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
|
||||
if (console_app) current_process.flags |= PDB32_CONSOLE_PROC;
|
||||
|
||||
/* Install signal handlers; this cannot be done before, since we cannot
|
||||
* send exceptions to the debugger before the create process event that
|
||||
* is sent by REQ_INIT_PROCESS_DONE.
|
||||
* We do need the handlers in place by the time the request is over, so
|
||||
* we set them up here. If we segfault between here and the server call
|
||||
* something is very wrong... */
|
||||
if (!SIGNAL_Init()) goto error;
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
SERVER_START_REQ( init_process_done )
|
||||
{
|
||||
req->module = (void *)current_process.module;
|
||||
req->module_size = nt->OptionalHeader.SizeOfImage;
|
||||
req->entry = entry;
|
||||
/* API requires a double indirection */
|
||||
req->name = &main_exe_name_ptr;
|
||||
req->exe_file = main_file;
|
||||
req->gui = !console_app;
|
||||
wine_server_add_data( req, main_exe_name, strlen(main_exe_name) );
|
||||
wine_server_call( req );
|
||||
debugged = reply->debugged;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* create the main modref and load dependencies */
|
||||
if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE )))
|
||||
goto error;
|
||||
|
||||
if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */
|
||||
|
||||
MODULE_DllProcessAttach( NULL, (LPVOID)1 );
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
DPRINTF( "%04lx:Starting process %s (entryproc=%p)\n",
|
||||
GetCurrentThreadId(), main_exe_name, entry );
|
||||
if (debugged) DbgBreakPoint();
|
||||
/* FIXME: should use _PEB as parameter for NT 3.5 programs !
|
||||
* Dunno about other OSs */
|
||||
SetLastError(0); /* clear error code */
|
||||
ExitThread( entry(NULL) );
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
__ENDTRY
|
||||
}
|
||||
|
||||
|
||||
|
@ -586,7 +573,7 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
if (!THREAD_InitStack( NtCurrentTeb(), stack_size )) goto error;
|
||||
|
||||
/* switch to the new stack */
|
||||
SYSDEPS_SwitchToThreadStack( start_process );
|
||||
SYSDEPS_SwitchToThreadStack( start_process, NULL );
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
|
@ -1387,16 +1374,6 @@ void WINAPI ExitProcess( DWORD status )
|
|||
exit( status );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ExitProcess (KERNEL.466)
|
||||
*/
|
||||
void WINAPI ExitProcess16( WORD status )
|
||||
{
|
||||
DWORD count;
|
||||
ReleaseThunkLock( &count );
|
||||
ExitProcess( status );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* TerminateProcess (KERNEL32.@)
|
||||
*/
|
||||
|
@ -1408,441 +1385,6 @@ BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessDword (KERNEL.485)
|
||||
* GetProcessDword (KERNEL32.18)
|
||||
* 'Of course you cannot directly access Windows internal structures'
|
||||
*/
|
||||
DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
|
||||
{
|
||||
DWORD x, y;
|
||||
STARTUPINFOW siw;
|
||||
|
||||
TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset );
|
||||
|
||||
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
case GPD_APP_COMPAT_FLAGS:
|
||||
return GetAppCompatFlags16(0);
|
||||
|
||||
case GPD_LOAD_DONE_EVENT:
|
||||
return (DWORD)current_process.load_done_evt;
|
||||
|
||||
case GPD_HINSTANCE16:
|
||||
return GetTaskDS16();
|
||||
|
||||
case GPD_WINDOWS_VERSION:
|
||||
return GetExeVersion16();
|
||||
|
||||
case GPD_THDB:
|
||||
return (DWORD)NtCurrentTeb() - 0x10 /* FIXME */;
|
||||
|
||||
case GPD_PDB:
|
||||
return (DWORD)¤t_process;
|
||||
|
||||
case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
|
||||
GetStartupInfoW(&siw);
|
||||
return (DWORD)siw.hStdOutput;
|
||||
|
||||
case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
|
||||
GetStartupInfoW(&siw);
|
||||
return (DWORD)siw.hStdInput;
|
||||
|
||||
case GPD_STARTF_SHOWWINDOW:
|
||||
GetStartupInfoW(&siw);
|
||||
return siw.wShowWindow;
|
||||
|
||||
case GPD_STARTF_SIZE:
|
||||
GetStartupInfoW(&siw);
|
||||
x = siw.dwXSize;
|
||||
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
||||
y = siw.dwYSize;
|
||||
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
||||
return MAKELONG( x, y );
|
||||
|
||||
case GPD_STARTF_POSITION:
|
||||
GetStartupInfoW(&siw);
|
||||
x = siw.dwX;
|
||||
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
||||
y = siw.dwY;
|
||||
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
||||
return MAKELONG( x, y );
|
||||
|
||||
case GPD_STARTF_FLAGS:
|
||||
GetStartupInfoW(&siw);
|
||||
return process_pmts.dwFlags;
|
||||
|
||||
case GPD_PARENT:
|
||||
return 0;
|
||||
|
||||
case GPD_FLAGS:
|
||||
return current_process.flags;
|
||||
|
||||
case GPD_USERDATA:
|
||||
return current_process.process_dword;
|
||||
|
||||
default:
|
||||
ERR_(win32)("Unknown offset %d\n", offset );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessDword (KERNEL.484)
|
||||
* 'Of course you cannot directly access Windows internal structures'
|
||||
*/
|
||||
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
|
||||
{
|
||||
TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset );
|
||||
|
||||
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
case GPD_APP_COMPAT_FLAGS:
|
||||
case GPD_LOAD_DONE_EVENT:
|
||||
case GPD_HINSTANCE16:
|
||||
case GPD_WINDOWS_VERSION:
|
||||
case GPD_THDB:
|
||||
case GPD_PDB:
|
||||
case GPD_STARTF_SHELLDATA:
|
||||
case GPD_STARTF_HOTKEY:
|
||||
case GPD_STARTF_SHOWWINDOW:
|
||||
case GPD_STARTF_SIZE:
|
||||
case GPD_STARTF_POSITION:
|
||||
case GPD_STARTF_FLAGS:
|
||||
case GPD_PARENT:
|
||||
case GPD_FLAGS:
|
||||
ERR_(win32)("Not allowed to modify offset %d\n", offset );
|
||||
break;
|
||||
|
||||
case GPD_USERDATA:
|
||||
current_process.process_dword = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_(win32)("Unknown offset %d\n", offset );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* OpenProcess (KERNEL32.@)
|
||||
*/
|
||||
HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
|
||||
{
|
||||
HANDLE ret = 0;
|
||||
SERVER_START_REQ( open_process )
|
||||
{
|
||||
req->pid = id;
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* MapProcessHandle (KERNEL.483)
|
||||
*/
|
||||
DWORD WINAPI MapProcessHandle( HANDLE handle )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!wine_server_call_err( req )) ret = (DWORD)reply->pid;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetPriorityClass (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( set_process_info )
|
||||
{
|
||||
req->handle = hprocess;
|
||||
req->priority = priorityclass;
|
||||
req->mask = SET_PROCESS_INFO_PRIORITY;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetPriorityClass (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetPriorityClass(HANDLE hprocess)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hprocess;
|
||||
if (!wine_server_call_err( req )) ret = reply->priority;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessAffinityMask (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( set_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
req->affinity = affmask;
|
||||
req->mask = SET_PROCESS_INFO_AFFINITY;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetProcessAffinityMask (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
|
||||
LPDWORD lpProcessAffinityMask,
|
||||
LPDWORD lpSystemAffinityMask )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
|
||||
if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessVersion (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetProcessVersion( DWORD processid )
|
||||
{
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
||||
if (processid && processid != GetCurrentProcessId())
|
||||
{
|
||||
FIXME("should use ReadProcessMemory\n");
|
||||
return 0;
|
||||
}
|
||||
if ((nt = RtlImageNtHeader( current_process.module )))
|
||||
return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
|
||||
nt->OptionalHeader.MinorSubsystemVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessFlags (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetProcessFlags( DWORD processid )
|
||||
{
|
||||
if (processid && processid != GetCurrentProcessId()) return 0;
|
||||
return current_process.flags;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessWorkingSetSize [KERNEL32.@]
|
||||
* 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
|
||||
*/
|
||||
BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess, SIZE_T minset,
|
||||
SIZE_T maxset)
|
||||
{
|
||||
FIXME("(%p,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
|
||||
if(( minset == (SIZE_T)-1) && (maxset == (SIZE_T)-1)) {
|
||||
/* Trim the working set to zero */
|
||||
/* Swap the process out of physical RAM */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessWorkingSetSize (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess, PSIZE_T minset,
|
||||
PSIZE_T maxset)
|
||||
{
|
||||
FIXME("(%p,%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)
|
||||
*/
|
||||
static DWORD shutdown_flags = 0;
|
||||
static DWORD shutdown_priority = 0x280;
|
||||
|
||||
BOOL WINAPI SetProcessShutdownParameters(DWORD level, DWORD flags)
|
||||
{
|
||||
FIXME("(%08lx, %08lx): partial stub.\n", level, flags);
|
||||
shutdown_flags = flags;
|
||||
shutdown_priority = level;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessShutdownParameters (KERNEL32.@)
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags )
|
||||
{
|
||||
*lpdwLevel = shutdown_priority;
|
||||
*lpdwFlags = shutdown_flags;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcessPriorityBoost (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetProcessPriorityBoost(HANDLE hprocess,PBOOL pDisablePriorityBoost)
|
||||
{
|
||||
FIXME("(%p,%p): semi-stub\n", hprocess, pDisablePriorityBoost);
|
||||
|
||||
/* Report that no boost is present.. */
|
||||
*pDisablePriorityBoost = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetProcessPriorityBoost (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
|
||||
{
|
||||
FIXME("(%p,%d): stub\n",hprocess,disableboost);
|
||||
/* Say we can do it. I doubt the program will notice that we don't. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ReadProcessMemory (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, SIZE_T size,
|
||||
SIZE_T *bytes_read )
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
SERVER_START_REQ( read_process_memory )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (void *)addr;
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_read) *bytes_read = size;
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WriteProcessMemory (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, SIZE_T size,
|
||||
SIZE_T *bytes_written )
|
||||
{
|
||||
static const int zero;
|
||||
unsigned int first_offset, last_offset, first_mask, last_mask;
|
||||
DWORD res;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* compute the mask for the first int */
|
||||
first_mask = ~0;
|
||||
first_offset = (unsigned int)addr % sizeof(int);
|
||||
memset( &first_mask, 0, first_offset );
|
||||
|
||||
/* compute the mask for the last int */
|
||||
last_offset = (size + first_offset) % sizeof(int);
|
||||
last_mask = 0;
|
||||
memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) );
|
||||
|
||||
SERVER_START_REQ( write_process_memory )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (char *)addr - first_offset;
|
||||
req->first_mask = first_mask;
|
||||
req->last_mask = last_mask;
|
||||
if (first_offset) wine_server_add_data( req, &zero, first_offset );
|
||||
wine_server_add_data( req, buffer, size );
|
||||
if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset );
|
||||
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_written) *bytes_written = size;
|
||||
{
|
||||
char dummy[32];
|
||||
SIZE_T read;
|
||||
ReadProcessMemory( process, addr, dummy, sizeof(dummy), &read );
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RegisterServiceProcess (KERNEL.491)
|
||||
* RegisterServiceProcess (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.@]
|
||||
*
|
||||
|
@ -1879,37 +1421,6 @@ UINT WINAPI SetErrorMode( UINT mode )
|
|||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileApisToOEM (KERNEL32.@)
|
||||
*/
|
||||
VOID WINAPI SetFileApisToOEM(void)
|
||||
{
|
||||
current_process.flags |= PDB32_FILE_APIS_OEM;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SetFileApisToANSI (KERNEL32.@)
|
||||
*/
|
||||
VOID WINAPI SetFileApisToANSI(void)
|
||||
{
|
||||
current_process.flags &= ~PDB32_FILE_APIS_OEM;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AreFileApisANSI [KERNEL32.@] Determines if file functions are using ANSI
|
||||
*
|
||||
* RETURNS
|
||||
* TRUE: Set of file functions is using ANSI code page
|
||||
* FALSE: Set of file functions is using OEM code page
|
||||
*/
|
||||
BOOL WINAPI AreFileApisANSI(void)
|
||||
{
|
||||
return !(current_process.flags & PDB32_FILE_APIS_OEM);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetTickCount (KERNEL32.@)
|
||||
*
|
||||
|
@ -2031,13 +1542,3 @@ BOOL WINAPI TlsSetValue(
|
|||
NtCurrentTeb()->tls_array[index] = value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetCurrentProcess (KERNEL32.@)
|
||||
*/
|
||||
#undef GetCurrentProcess
|
||||
HANDLE WINAPI GetCurrentProcess(void)
|
||||
{
|
||||
return (HANDLE)0xffffffff;
|
||||
}
|
||||
|
|
|
@ -232,8 +232,16 @@ static void THREAD_Start(void)
|
|||
if (TRACE_ON(relay))
|
||||
DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
|
||||
|
||||
MODULE_DllThreadAttach( NULL );
|
||||
ExitThread( func( NtCurrentTeb()->entry_arg ) );
|
||||
__TRY
|
||||
{
|
||||
MODULE_DllThreadAttach( NULL );
|
||||
ExitThread( func( NtCurrentTeb()->entry_arg ) );
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue