blob: 76e9d6349b658cb12dbd55a959c478253fedfb62 [file] [log] [blame]
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001/*
2 * Win32 'syslevel' routines
3 *
4 * Copyright 1998 Ulrich Weigand
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard767e6f61998-08-09 12:47:43 +000019 */
20
Patrik Stridvalld016f812002-08-17 00:43:16 +000021#include "config.h"
22
23#ifdef HAVE_UNISTD_H
24# include <unistd.h>
25#endif
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000026#include <sys/types.h>
Patrik Stridvall9c1de6d2002-09-12 22:07:02 +000027#include "winternl.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000028#include "syslevel.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000029#include "stackframe.h"
Alexandre Julliard59008672002-05-16 20:32:16 +000030#include "wine/library.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000031#include "wine/debug.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000032
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000033WINE_DEFAULT_DEBUG_CHANNEL(win32);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000034
Alexandre Julliard301df6b2001-08-16 18:12:56 +000035static SYSLEVEL Win16Mutex = { CRITICAL_SECTION_INIT("Win16Mutex"), 1 };
Alexandre Julliard767e6f61998-08-09 12:47:43 +000036
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000037/* Global variable to save current TEB while in 16-bit code */
38WORD SYSLEVEL_Win16CurrentTeb = 0;
39
Alexandre Julliard767e6f61998-08-09 12:47:43 +000040
41/************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +000042 * GetpWin16Lock (KERNEL32.93)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000043 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000044VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000045{
46 *lock = &Win16Mutex;
47}
48
49/************************************************************************
Patrik Stridvall15a3b742001-04-27 18:03:51 +000050 * GetpWin16Lock (KERNEL.449)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000051 */
Alexandre Julliardab687972000-11-15 23:41:46 +000052SEGPTR WINAPI GetpWin16Lock16(void)
53{
Alexandre Julliardd7b76822001-12-20 00:19:40 +000054 static SYSLEVEL *w16Mutex;
Alexandre Julliardab687972000-11-15 23:41:46 +000055 static SEGPTR segpWin16Mutex;
Alexandre Julliardd7b76822001-12-20 00:19:40 +000056
Alexandre Julliardab687972000-11-15 23:41:46 +000057 if (!segpWin16Mutex)
58 {
Alexandre Julliardd7b76822001-12-20 00:19:40 +000059 w16Mutex = &Win16Mutex;
60 segpWin16Mutex = MapLS( &w16Mutex );
Alexandre Julliardab687972000-11-15 23:41:46 +000061 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +000062 return segpWin16Mutex;
63}
64
65/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000066 * _CreateSysLevel (KERNEL.438)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000067 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000068VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
Alexandre Julliard767e6f61998-08-09 12:47:43 +000069{
Eric Pouechc962a692003-06-23 18:12:28 +000070 RtlInitializeCriticalSection( &lock->crst );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000071 lock->level = level;
72
Andrew John Hughesed800c62002-11-21 03:45:01 +000073 TRACE("(%p, %d): handle is %p\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000074 lock, level, lock->crst.LockSemaphore );
75}
76
77/************************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +000078 * _EnterSysLevel (KERNEL32.97)
79 * _EnterSysLevel (KERNEL.439)
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000080 */
81VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
82{
Alexandre Julliard0a860a01999-06-22 11:43:42 +000083 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000084 int i;
85
Alexandre Julliard54f22872002-10-03 19:54:57 +000086 TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count before %ld\n",
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000087 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +000088 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000089
90 for ( i = 3; i > lock->level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +000091 if ( teb->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000092 {
Vincent Béron9a624912002-05-31 23:06:46 +000093 ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
Alexandre Julliard0a860a01999-06-22 11:43:42 +000094 lock, lock->level, teb->sys_mutex[i], i );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000095 }
96
Eric Pouechc962a692003-06-23 18:12:28 +000097 RtlEnterCriticalSection( &lock->crst );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +000098
Alexandre Julliard0a860a01999-06-22 11:43:42 +000099 teb->sys_count[lock->level]++;
100 teb->sys_mutex[lock->level] = lock;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000101
Alexandre Julliard54f22872002-10-03 19:54:57 +0000102 TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count after %ld\n",
Vincent Béron9a624912002-05-31 23:06:46 +0000103 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000104 teb->sys_count[lock->level] );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000105
106 if (lock == &Win16Mutex)
Alexandre Julliard59008672002-05-16 20:32:16 +0000107 SYSLEVEL_Win16CurrentTeb = wine_get_fs();
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000108}
109
110/************************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000111 * _LeaveSysLevel (KERNEL32.98)
112 * _LeaveSysLevel (KERNEL.440)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000113 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000114VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000115{
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000116 TEB *teb = NtCurrentTeb();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000117
Alexandre Julliard54f22872002-10-03 19:54:57 +0000118 TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count before %ld\n",
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000119 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000120 teb->sys_count[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000121
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000122 if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000123 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000124 ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
Vincent Béron9a624912002-05-31 23:06:46 +0000125 lock, lock->level, teb->sys_count[lock->level],
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000126 teb->sys_mutex[lock->level] );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000127 }
128 else
129 {
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000130 if ( --teb->sys_count[lock->level] == 0 )
131 teb->sys_mutex[lock->level] = NULL;
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000132 }
133
Eric Pouechc962a692003-06-23 18:12:28 +0000134 RtlLeaveCriticalSection( &lock->crst );
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000135
Alexandre Julliard54f22872002-10-03 19:54:57 +0000136 TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count after %ld\n",
Vincent Béron9a624912002-05-31 23:06:46 +0000137 lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000138 teb->sys_count[lock->level] );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000139}
140
141/************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000142 * @ (KERNEL32.86)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000143 */
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000144VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000145{
146 _LeaveSysLevel(lock);
147}
148
149/************************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000150 * _ConfirmSysLevel (KERNEL32.95)
151 * _ConfirmSysLevel (KERNEL.436)
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000152 */
153DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
154{
Alexandre Julliard73755972002-07-31 19:26:03 +0000155 if ( lock && lock->crst.OwningThread == (HANDLE)GetCurrentThreadId() )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000156 return lock->crst.RecursionCount;
157 else
158 return 0L;
159}
160
161/************************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000162 * _CheckNotSysLevel (KERNEL32.94)
163 * _CheckNotSysLevel (KERNEL.437)
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000164 */
165VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
166{
Alexandre Julliard73755972002-07-31 19:26:03 +0000167 if (lock && lock->crst.OwningThread == (HANDLE)GetCurrentThreadId() &&
168 lock->crst.RecursionCount)
Alexandre Julliard181e3d82001-08-15 23:32:47 +0000169 {
170 ERR( "Holding lock %p level %d\n", lock, lock->level );
171 DbgBreakPoint();
172 }
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000173}
174
175
176/************************************************************************
Alexandre Julliardab687972000-11-15 23:41:46 +0000177 * _EnterWin16Lock [KERNEL.480]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000178 */
Alexandre Julliardab687972000-11-15 23:41:46 +0000179VOID WINAPI _EnterWin16Lock(void)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000180{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000181 _EnterSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000182}
183
184/************************************************************************
Alexandre Julliardab687972000-11-15 23:41:46 +0000185 * _LeaveWin16Lock [KERNEL.481]
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000186 */
Alexandre Julliardab687972000-11-15 23:41:46 +0000187VOID WINAPI _LeaveWin16Lock(void)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000188{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000189 _LeaveSysLevel(&Win16Mutex);
190}
Alexandre Julliardab687972000-11-15 23:41:46 +0000191
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000192/************************************************************************
193 * _ConfirmWin16Lock (KERNEL32.96)
194 */
195DWORD WINAPI _ConfirmWin16Lock(void)
196{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000197 return _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000198}
199
200/************************************************************************
201 * ReleaseThunkLock (KERNEL32.48)
202 */
203VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
204{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000205 DWORD count = _ConfirmSysLevel(&Win16Mutex);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000206 *mutex_count = count;
207
208 while (count-- > 0)
209 _LeaveSysLevel(&Win16Mutex);
210}
211
212/************************************************************************
213 * RestoreThunkLock (KERNEL32.49)
214 */
215VOID WINAPI RestoreThunkLock(DWORD mutex_count)
216{
217 while (mutex_count-- > 0)
218 _EnterSysLevel(&Win16Mutex);
219}
220
221/************************************************************************
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000222 * SYSLEVEL_CheckNotLevel
223 */
224VOID SYSLEVEL_CheckNotLevel( INT level )
225{
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000226 INT i;
227
228 for ( i = 3; i >= level; i-- )
Alexandre Julliard0a860a01999-06-22 11:43:42 +0000229 if ( NtCurrentTeb()->sys_count[i] > 0 )
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000230 {
Vincent Béron9a624912002-05-31 23:06:46 +0000231 ERR("(%d): Holding lock of level %d!\n",
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000232 level, i );
Alexandre Julliardafb49ea2000-09-29 20:48:04 +0000233 DbgBreakPoint();
Ulrich Weigandc5b8b3a1999-05-22 16:28:47 +0000234 break;
235 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000236}