Implemented RtlDosPathNameToNtPathName_U, RtlGetCurrentDirectory_U,
[wine] / scheduler / syslevel.c
1 /*
2  * Win32 'syslevel' routines
3  *
4  * Copyright 1998 Ulrich Weigand
5  *
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
19  */
20
21 #include "config.h"
22
23 #ifdef HAVE_UNISTD_H
24 # include <unistd.h>
25 #endif
26 #include <sys/types.h>
27 #include "winternl.h"
28 #include "syslevel.h"
29 #include "stackframe.h"
30 #include "wine/library.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(win32);
34
35 static SYSLEVEL Win16Mutex = { CRITICAL_SECTION_INIT("Win16Mutex"), 1 };
36
37 /* Global variable to save current TEB while in 16-bit code */
38 WORD SYSLEVEL_Win16CurrentTeb = 0;
39
40
41 /************************************************************************
42  *           GetpWin16Lock    (KERNEL32.93)
43  */
44 VOID WINAPI GetpWin16Lock(SYSLEVEL **lock)
45 {
46     *lock = &Win16Mutex;
47 }
48
49 /************************************************************************
50  *           GetpWin16Lock    (KERNEL.449)
51  */
52 SEGPTR WINAPI GetpWin16Lock16(void)
53 {
54     static SYSLEVEL *w16Mutex;
55     static SEGPTR segpWin16Mutex;
56
57     if (!segpWin16Mutex)
58     {
59         w16Mutex = &Win16Mutex;
60         segpWin16Mutex = MapLS( &w16Mutex );
61     }
62     return segpWin16Mutex;
63 }
64
65 /************************************************************************
66  *           _CreateSysLevel    (KERNEL.438)
67  */
68 VOID WINAPI _CreateSysLevel(SYSLEVEL *lock, INT level)
69 {
70     InitializeCriticalSection( &lock->crst );
71     lock->level = level;
72
73     TRACE("(%p, %d): handle is %p\n",
74                   lock, level, lock->crst.LockSemaphore );
75 }
76
77 /************************************************************************
78  *           _EnterSysLevel    (KERNEL32.97)
79  *           _EnterSysLevel    (KERNEL.439)
80  */
81 VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
82 {
83     TEB *teb = NtCurrentTeb();
84     int i;
85
86     TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count before %ld\n",
87                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
88                   teb->sys_count[lock->level] );
89
90     for ( i = 3; i > lock->level; i-- )
91         if ( teb->sys_count[i] > 0 )
92         {
93             ERR("(%p, level %d): Holding %p, level %d. Expect deadlock!\n",
94                         lock, lock->level, teb->sys_mutex[i], i );
95         }
96
97     EnterCriticalSection( &lock->crst );
98
99     teb->sys_count[lock->level]++;
100     teb->sys_mutex[lock->level] = lock;
101
102     TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count after  %ld\n",
103                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
104                   teb->sys_count[lock->level] );
105
106     if (lock == &Win16Mutex)
107         SYSLEVEL_Win16CurrentTeb = wine_get_fs();
108 }
109
110 /************************************************************************
111  *           _LeaveSysLevel    (KERNEL32.98)
112  *           _LeaveSysLevel    (KERNEL.440)
113  */
114 VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
115 {
116     TEB *teb = NtCurrentTeb();
117
118     TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count before %ld\n",
119                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
120                   teb->sys_count[lock->level] );
121
122     if ( teb->sys_count[lock->level] <= 0 || teb->sys_mutex[lock->level] != lock )
123     {
124         ERR("(%p, level %d): Invalid state: count %ld mutex %p.\n",
125                     lock, lock->level, teb->sys_count[lock->level],
126                     teb->sys_mutex[lock->level] );
127     }
128     else
129     {
130         if ( --teb->sys_count[lock->level] == 0 )
131             teb->sys_mutex[lock->level] = NULL;
132     }
133
134     LeaveCriticalSection( &lock->crst );
135
136     TRACE("(%p, level %d): thread %lx (fs %04x, pid %ld) count after  %ld\n",
137                   lock, lock->level, teb->tid, teb->teb_sel, (long) getpid(),
138                   teb->sys_count[lock->level] );
139 }
140
141 /************************************************************************
142  *              @ (KERNEL32.86)
143  */
144 VOID WINAPI _KERNEL32_86(SYSLEVEL *lock)
145 {
146     _LeaveSysLevel(lock);
147 }
148
149 /************************************************************************
150  *           _ConfirmSysLevel    (KERNEL32.95)
151  *           _ConfirmSysLevel    (KERNEL.436)
152  */
153 DWORD WINAPI _ConfirmSysLevel(SYSLEVEL *lock)
154 {
155     if ( lock && lock->crst.OwningThread == (HANDLE)GetCurrentThreadId() )
156         return lock->crst.RecursionCount;
157     else
158         return 0L;
159 }
160
161 /************************************************************************
162  *           _CheckNotSysLevel    (KERNEL32.94)
163  *           _CheckNotSysLevel    (KERNEL.437)
164  */
165 VOID WINAPI _CheckNotSysLevel(SYSLEVEL *lock)
166 {
167     if (lock && lock->crst.OwningThread == (HANDLE)GetCurrentThreadId() &&
168         lock->crst.RecursionCount)
169     {
170         ERR( "Holding lock %p level %d\n", lock, lock->level );
171         DbgBreakPoint();
172     }
173 }
174
175
176 /************************************************************************
177  *           _EnterWin16Lock                    [KERNEL.480]
178  */
179 VOID WINAPI _EnterWin16Lock(void)
180 {
181     _EnterSysLevel(&Win16Mutex);
182 }
183
184 /************************************************************************
185  *           _LeaveWin16Lock            [KERNEL.481]
186  */
187 VOID WINAPI _LeaveWin16Lock(void)
188 {
189     _LeaveSysLevel(&Win16Mutex);
190 }
191
192 /************************************************************************
193  *           _ConfirmWin16Lock    (KERNEL32.96)
194  */
195 DWORD WINAPI _ConfirmWin16Lock(void)
196 {
197     return _ConfirmSysLevel(&Win16Mutex);
198 }
199
200 /************************************************************************
201  *           ReleaseThunkLock    (KERNEL32.48)
202  */
203 VOID WINAPI ReleaseThunkLock(DWORD *mutex_count)
204 {
205     DWORD count = _ConfirmSysLevel(&Win16Mutex);
206     *mutex_count = count;
207
208     while (count-- > 0)
209         _LeaveSysLevel(&Win16Mutex);
210 }
211
212 /************************************************************************
213  *           RestoreThunkLock    (KERNEL32.49)
214  */
215 VOID WINAPI RestoreThunkLock(DWORD mutex_count)
216 {
217     while (mutex_count-- > 0)
218         _EnterSysLevel(&Win16Mutex);
219 }
220
221 /************************************************************************
222  *           SYSLEVEL_CheckNotLevel
223  */
224 VOID SYSLEVEL_CheckNotLevel( INT level )
225 {
226     INT i;
227
228     for ( i = 3; i >= level; i-- )
229         if ( NtCurrentTeb()->sys_count[i] > 0 )
230         {
231             ERR("(%d): Holding lock of level %d!\n",
232                        level, i );
233             DbgBreakPoint();
234             break;
235         }
236 }