/* * Win32 'syslevel' routines * * Copyright 1998 Ulrich Weigand */ #include #include "syslevel.h" #include "heap.h" #include "stackframe.h" #include "debug.h" DEFAULT_DEBUG_CHANNEL(win32) static CRITICAL_SECTION Win16Mutex; static SEGPTR segpWin16Mutex; /* Global variable to save current TEB while in 16-bit code */ WORD SYSLEVEL_Win16CurrentTeb = 0; /* TEB of initial process for emergency use */ WORD SYSLEVEL_EmergencyTeb = 0; /************************************************************************ * SYSLEVEL_Init */ void SYSLEVEL_Init(void) { CRITICAL_SECTION **w16Mutex = SEGPTR_ALLOC(sizeof(CRITICAL_SECTION *)); *w16Mutex = &Win16Mutex; segpWin16Mutex = SEGPTR_GET(w16Mutex); InitializeCriticalSection(&Win16Mutex); MakeCriticalSectionGlobal(&Win16Mutex); } /************************************************************************ * GetpWin16Lock32 (KERNEL32.93) */ VOID WINAPI GetpWin16Lock(CRITICAL_SECTION **lock) { *lock = &Win16Mutex; } /************************************************************************ * GetpWin16Lock16 (KERNEL.449) */ SEGPTR WINAPI GetpWin16Lock16(void) { return segpWin16Mutex; } /************************************************************************ * _EnterSysLevel (KERNEL32.97) */ VOID WINAPI _EnterSysLevel(CRITICAL_SECTION *lock) { EnterCriticalSection(lock); if (lock == &Win16Mutex) GET_FS( SYSLEVEL_Win16CurrentTeb ); } /************************************************************************ * _LeaveSysLevel (KERNEL32.98) */ VOID WINAPI _LeaveSysLevel(CRITICAL_SECTION *lock) { LeaveCriticalSection(lock); } /************************************************************************ * (KERNEL32.86) */ VOID WINAPI _KERNEL32_86(CRITICAL_SECTION *lock) { _LeaveSysLevel(lock); } /************************************************************************ * SYSLEVEL_EnterWin16Lock [KERNEL.480] */ VOID WINAPI SYSLEVEL_EnterWin16Lock(VOID) { TRACE(win32, "thread %04x (pid %d) about to enter\n", THREAD_Current()->teb_sel, getpid()); _EnterSysLevel(&Win16Mutex); TRACE(win32, "thread %04x (pid %d) entered, count is %ld\n", THREAD_Current()->teb_sel, getpid(), Win16Mutex.RecursionCount); } /************************************************************************ * SYSLEVEL_LeaveWin16Lock [KERNEL.481] */ VOID WINAPI SYSLEVEL_LeaveWin16Lock(VOID) { TRACE(win32, "thread %04x (pid %d) about to leave, count is %ld\n", THREAD_Current()->teb_sel, getpid(), Win16Mutex.RecursionCount); _LeaveSysLevel(&Win16Mutex); } /************************************************************************ * _CheckNotSysLevel (KERNEL32.94) */ VOID WINAPI _CheckNotSysLevel(CRITICAL_SECTION *lock) { FIXME(win32, "()\n"); } /************************************************************************ * _ConfirmSysLevel (KERNEL32.95) */ VOID WINAPI _ConfirmSysLevel(CRITICAL_SECTION *lock) { FIXME(win32, "()\n"); } /************************************************************************ * _ConfirmWin16Lock (KERNEL32.96) */ DWORD WINAPI _ConfirmWin16Lock(void) { if ( Win16Mutex.OwningThread == GetCurrentThreadId() ) return Win16Mutex.RecursionCount; else return 0L; } /************************************************************************ * ReleaseThunkLock (KERNEL32.48) */ VOID WINAPI ReleaseThunkLock(DWORD *mutex_count) { DWORD count = Win16Mutex.RecursionCount; *mutex_count = count; while (count-- > 0) _LeaveSysLevel(&Win16Mutex); } /************************************************************************ * RestoreThunkLock (KERNEL32.49) */ VOID WINAPI RestoreThunkLock(DWORD mutex_count) { while (mutex_count-- > 0) _EnterSysLevel(&Win16Mutex); } /************************************************************************ * SYSLEVEL_ReleaseWin16Lock */ VOID SYSLEVEL_ReleaseWin16Lock(VOID) { DWORD count; TRACE(win32, "thread %04x (pid %d) about to release, count is %ld\n", THREAD_Current()->teb_sel, getpid(), Win16Mutex.RecursionCount); ReleaseThunkLock(&count); if (count > 0xffff) ERR(win32, "Win16Mutex recursion count too large!\n"); CURRENT_STACK16->mutex_count = (WORD)count; } /************************************************************************ * SYSLEVEL_RestoreWin16Lock */ VOID SYSLEVEL_RestoreWin16Lock(VOID) { DWORD count = CURRENT_STACK16->mutex_count; if (!count) ERR(win32, "Win16Mutex recursion count is zero!\n"); TRACE(win32, "thread %04x (pid %d) about to restore (count %ld)\n", THREAD_Current()->teb_sel, getpid(), count); RestoreThunkLock(count); TRACE(win32, "thread %04x (pid %d) restored lock, count is %ld\n", THREAD_Current()->teb_sel, getpid(), Win16Mutex.RecursionCount); }