Moved some of the process functions to dlls/kernel.
Removed kernel dependencies from sysdeps.c and moved it to dlls/ntdll.
diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index 2636e27..403951a 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -35,6 +35,7 @@
lcformat.c \
local16.c \
locale.c \
+ process.c \
resource.c \
resource16.c \
stress.c \
diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c
new file mode 100644
index 0000000..32aa36e
--- /dev/null
+++ b/dlls/kernel/process.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;
+}
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index b0b1d13..7890956 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -49,7 +49,6 @@
$(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 @@
signal_sparc.c \
string.c \
sync.c \
+ sysdeps.c \
thread.c \
time.c \
virtual.c \
diff --git a/scheduler/sysdeps.c b/dlls/ntdll/sysdeps.c
similarity index 89%
rename from scheduler/sysdeps.c
rename to dlls/ntdll/sysdeps.c
index 933b24c..c6ddba8 100644
--- a/scheduler/sysdeps.c
+++ b/dlls/ntdll/sysdeps.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"
@@ -101,27 +99,6 @@
/***********************************************************************
- * 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
*
* Get a temporary stack address to run the thread exit code on.
@@ -161,15 +138,7 @@
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 @@
/***********************************************************************
- * 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 @@
"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 @@
}
# 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 @@
"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 */
@@ -274,15 +246,6 @@
/***********************************************************************
- * SYSDEPS_SwitchToThreadStack
- */
-void SYSDEPS_SwitchToThreadStack( void (*func)(void) )
-{
- SYSDEPS_CallOnStack( call_on_thread_stack, func );
-}
-
-
-/***********************************************************************
* SYSDEPS_ExitThread
*
* Exit a running thread; must not return.
@@ -292,8 +255,10 @@
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 @@
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
}
diff --git a/include/thread.h b/include/thread.h
index 9d51d0f..fb14e7b 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -150,7 +150,7 @@
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);
diff --git a/scheduler/fiber.c b/scheduler/fiber.c
index 570aa41..7a816ce 100644
--- a/scheduler/fiber.c
+++ b/scheduler/fiber.c
@@ -25,6 +25,7 @@
#include "winbase.h"
#include "winerror.h"
+#include "wine/exception.h"
#include "thread.h"
struct fiber_data
@@ -41,14 +42,22 @@
/* 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 @@
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 );
}
diff --git a/scheduler/process.c b/scheduler/process.c
index e32a7b1..f21c55e 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -109,14 +109,6 @@
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 @@
*
* 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 @@
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 @@
exit( status );
}
-/***********************************************************************
- * ExitProcess (KERNEL.466)
- */
-void WINAPI ExitProcess16( WORD status )
-{
- DWORD count;
- ReleaseThunkLock( &count );
- ExitProcess( status );
-}
-
/******************************************************************************
* TerminateProcess (KERNEL32.@)
*/
@@ -1409,441 +1386,6 @@
/***********************************************************************
- * 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.@]
*
* Gets termination status of specified process
@@ -1879,37 +1421,6 @@
}
-/**************************************************************************
- * 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 @@
NtCurrentTeb()->tls_array[index] = value;
return TRUE;
}
-
-
-/***********************************************************************
- * GetCurrentProcess (KERNEL32.@)
- */
-#undef GetCurrentProcess
-HANDLE WINAPI GetCurrentProcess(void)
-{
- return (HANDLE)0xffffffff;
-}
diff --git a/scheduler/thread.c b/scheduler/thread.c
index e285465..04f3f03 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -232,8 +232,16 @@
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
}