Use DrawFrameControl instead of bitmaps in certain cases.
[wine] / dlls / ntdll / rtl.c
1 /*
2  * NT basis DLL
3  * 
4  * This file contains the Rtl* API functions. These should be implementable.
5  * 
6  * Copyright 1996-1998 Marcus Meissner
7  *                1999 Alex Korobka
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "debugtools.h"
14 #include "windef.h"
15 #include "winerror.h"
16 #include "stackframe.h"
17
18 #include "ntddk.h"
19 #include "winreg.h"
20
21 DEFAULT_DEBUG_CHANNEL(ntdll);
22
23
24 static RTL_CRITICAL_SECTION peb_lock = CRITICAL_SECTION_INIT("peb_lock");
25
26 /*
27  *      resource functions
28  */
29
30 /***********************************************************************
31  *           RtlInitializeResource      (NTDLL.@)
32  *
33  * xxxResource() functions implement multiple-reader-single-writer lock.
34  * The code is based on information published in WDJ January 1999 issue.
35  */
36 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
37 {
38     if( rwl )
39     {
40         rwl->iNumberActive = 0;
41         rwl->uExclusiveWaiters = 0;
42         rwl->uSharedWaiters = 0;
43         rwl->hOwningThreadId = 0;
44         rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
45         RtlInitializeCriticalSection( &rwl->rtlCS );
46         NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, 0, NULL, 0, 65535 );
47         NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, 0, NULL, 0, 65535 );
48     }
49 }
50
51
52 /***********************************************************************
53  *           RtlDeleteResource          (NTDLL.@)
54  */
55 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
56 {
57     if( rwl )
58     {
59         RtlEnterCriticalSection( &rwl->rtlCS );
60         if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
61             MESSAGE("Deleting active MRSW lock (%p), expect failure\n", rwl );
62         rwl->hOwningThreadId = 0;
63         rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
64         rwl->iNumberActive = 0;
65         NtClose( rwl->hExclusiveReleaseSemaphore );
66         NtClose( rwl->hSharedReleaseSemaphore );
67         RtlLeaveCriticalSection( &rwl->rtlCS );
68         RtlDeleteCriticalSection( &rwl->rtlCS );
69     }
70 }
71
72
73 /***********************************************************************
74  *          RtlAcquireResourceExclusive (NTDLL.@)
75  */
76 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
77 {
78     BYTE retVal = 0;
79     if( !rwl ) return 0;
80
81 start:
82     RtlEnterCriticalSection( &rwl->rtlCS );
83     if( rwl->iNumberActive == 0 ) /* lock is free */
84     {
85         rwl->iNumberActive = -1;
86         retVal = 1;
87     }
88     else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
89     {
90          if( rwl->hOwningThreadId == GetCurrentThreadId() )
91          {
92              retVal = 1;
93              rwl->iNumberActive--;
94              goto done;
95          }
96 wait:
97          if( fWait )
98          {
99              rwl->uExclusiveWaiters++;
100
101              RtlLeaveCriticalSection( &rwl->rtlCS );
102              if( WaitForSingleObject( rwl->hExclusiveReleaseSemaphore, INFINITE ) == WAIT_FAILED )
103                  goto done;
104              goto start; /* restart the acquisition to avoid deadlocks */
105          }
106     }
107     else  /* one or more shared locks are in progress */
108          if( fWait )
109              goto wait;
110          
111     if( retVal == 1 )
112         rwl->hOwningThreadId = GetCurrentThreadId();
113 done:
114     RtlLeaveCriticalSection( &rwl->rtlCS );
115     return retVal;
116 }
117
118 /***********************************************************************
119  *          RtlAcquireResourceShared    (NTDLL.@)
120  */
121 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
122 {
123     DWORD dwWait = WAIT_FAILED;
124     BYTE retVal = 0;
125     if( !rwl ) return 0;
126
127 start:
128     RtlEnterCriticalSection( &rwl->rtlCS );
129     if( rwl->iNumberActive < 0 )
130     {
131         if( rwl->hOwningThreadId == GetCurrentThreadId() )
132         {
133             rwl->iNumberActive--;
134             retVal = 1;
135             goto done;
136         }
137         
138         if( fWait )
139         {
140             rwl->uSharedWaiters++;
141             RtlLeaveCriticalSection( &rwl->rtlCS );
142             if( (dwWait = WaitForSingleObject( rwl->hSharedReleaseSemaphore, INFINITE )) == WAIT_FAILED )
143                 goto done;
144             goto start;
145         }
146     }
147     else 
148     {
149         if( dwWait != WAIT_OBJECT_0 ) /* otherwise RtlReleaseResource() has already done it */
150             rwl->iNumberActive++;
151         retVal = 1;
152     }
153 done:
154     RtlLeaveCriticalSection( &rwl->rtlCS );
155     return retVal;
156 }
157
158
159 /***********************************************************************
160  *           RtlReleaseResource         (NTDLL.@)
161  */
162 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
163 {
164     RtlEnterCriticalSection( &rwl->rtlCS );
165
166     if( rwl->iNumberActive > 0 ) /* have one or more readers */
167     {
168         if( --rwl->iNumberActive == 0 )
169         {
170             if( rwl->uExclusiveWaiters )
171             {
172 wake_exclusive:
173                 rwl->uExclusiveWaiters--;
174                 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
175             }
176         }
177     }
178     else 
179     if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
180     {
181         if( ++rwl->iNumberActive == 0 )
182         {
183             rwl->hOwningThreadId = 0;
184             if( rwl->uExclusiveWaiters )
185                 goto wake_exclusive;
186             else
187                 if( rwl->uSharedWaiters )
188                 {
189                     UINT n = rwl->uSharedWaiters;
190                     rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
191                                                                * all queued readers have done their thing */
192                     rwl->uSharedWaiters = 0;
193                     NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
194                 }
195         }
196     }
197     RtlLeaveCriticalSection( &rwl->rtlCS );
198 }
199
200
201 /***********************************************************************
202  *           RtlDumpResource            (NTDLL.@)
203  */
204 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
205 {
206     if( rwl )
207     {
208         MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",  
209                 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
210         if( rwl->iNumberActive )
211             MESSAGE("\towner thread = %08x\n", rwl->hOwningThreadId );
212     }
213 }
214
215 /*
216  *      misc functions
217  */
218
219 /******************************************************************************
220  *      DbgPrint        [NTDLL.@]
221  */
222 void WINAPIV DbgPrint(LPCSTR fmt, ...)
223 {
224        char buf[512];
225        va_list args;
226
227        va_start(args, fmt);
228        vsprintf(buf,fmt, args);
229        va_end(args); 
230
231         MESSAGE("DbgPrint says: %s",buf);
232         /* hmm, raise exception? */
233 }
234
235 /******************************************************************************
236  *  RtlAcquirePebLock           [NTDLL.@]
237  */
238 VOID WINAPI RtlAcquirePebLock(void)
239 {
240     RtlEnterCriticalSection( &peb_lock );
241 }
242
243 /******************************************************************************
244  *  RtlReleasePebLock           [NTDLL.@]
245  */
246 VOID WINAPI RtlReleasePebLock(void)
247 {
248     RtlLeaveCriticalSection( &peb_lock );
249 }
250
251 /******************************************************************************
252  *  RtlIntegerToChar    [NTDLL.@]
253  */
254 DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
255         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
256         return 0;
257 }
258 /******************************************************************************
259  *  RtlSetEnvironmentVariable           [NTDLL.@]
260  */
261 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
262         FIXME("(0x%08lx,%s,%s),stub!\n",x1,debugstr_w(key->Buffer),debugstr_w(val->Buffer));
263         return 0;
264 }
265
266 /******************************************************************************
267  *  RtlNewSecurityObject                [NTDLL.@]
268  */
269 DWORD WINAPI RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
270         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6);
271         return 0;
272 }
273
274 /******************************************************************************
275  *  RtlDeleteSecurityObject             [NTDLL.@]
276  */
277 DWORD WINAPI RtlDeleteSecurityObject(DWORD x1) {
278         FIXME("(0x%08lx),stub!\n",x1);
279         return 0;
280 }
281
282 /**************************************************************************
283  *                 RtlNormalizeProcessParams            [NTDLL.@]
284  */
285 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
286 {
287     FIXME("(%p), stub\n",x);
288     return x;
289 }
290
291 /**************************************************************************
292  *                 RtlGetNtProductType                  [NTDLL.@]
293  */
294 BOOLEAN WINAPI RtlGetNtProductType(LPDWORD type)
295 {
296     FIXME("(%p): stub\n", type);
297     *type=3; /* dunno. 1 for client, 3 for server? */
298     return 1;
299 }
300
301 /**************************************************************************
302  *                 _chkstk                              [NTDLL.@]
303  *
304  * Glorified "enter xxxx".
305  */
306 void WINAPI NTDLL_chkstk( CONTEXT86 *context )
307 {
308     context->Esp -= context->Eax;
309 }
310
311 /**************************************************************************
312  *                 _alloca_probe                        [NTDLL.@]
313  *
314  * Glorified "enter xxxx".
315  */
316 void WINAPI NTDLL_alloca_probe( CONTEXT86 *context )
317 {
318     context->Esp -= context->Eax;
319 }
320
321 /**************************************************************************
322  *                 RtlDosPathNameToNtPathName_U         [NTDLL.@]
323  *
324  * FIXME: convert to UNC or whatever is expected here
325  */
326 BOOLEAN  WINAPI RtlDosPathNameToNtPathName_U(
327         LPWSTR from,PUNICODE_STRING us,DWORD x2,DWORD x3)
328 {
329     FIXME("(%s,%p,%08lx,%08lx)\n",debugstr_w(from),us,x2,x3);
330     if (us) RtlCreateUnicodeString( us, from );
331     return TRUE;
332 }
333
334
335 /***********************************************************************
336  *           RtlImageNtHeader   (NTDLL.@)
337  */
338 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
339 {
340     IMAGE_NT_HEADERS *ret = NULL;
341     IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
342
343     if (dos->e_magic == IMAGE_DOS_SIGNATURE)
344     {
345         ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
346         if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
347     }
348     return ret;
349 }
350
351
352 /******************************************************************************
353  *  RtlCreateEnvironment                [NTDLL.@]
354  */
355 DWORD WINAPI RtlCreateEnvironment(DWORD x1,DWORD x2) {
356         FIXME("(0x%08lx,0x%08lx),stub!\n",x1,x2);
357         return 0;
358 }
359
360
361 /******************************************************************************
362  *  RtlDestroyEnvironment               [NTDLL.@]
363  */
364 DWORD WINAPI RtlDestroyEnvironment(DWORD x) {
365         FIXME("(0x%08lx),stub!\n",x);
366         return 0;
367 }
368
369 /******************************************************************************
370  *  RtlQueryEnvironmentVariable_U               [NTDLL.@]
371  */
372 DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
373         FIXME("(0x%08lx,%s,%p),stub!\n",x1,debugstr_w(key->Buffer),val);
374         return 0;
375 }
376 /******************************************************************************
377  *  RtlInitializeGenericTable           [NTDLL.@]
378  */
379 DWORD WINAPI RtlInitializeGenericTable(void)
380 {
381         FIXME("\n");
382         return 0;
383 }
384
385 /******************************************************************************
386  *  RtlInitializeBitMap                 [NTDLL.@]
387  * 
388  */
389 NTSTATUS WINAPI RtlInitializeBitMap(DWORD x1,DWORD x2,DWORD x3)
390 {
391         FIXME("(0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3);
392         return 0;
393 }
394
395 /******************************************************************************
396  *  RtlSetBits                          [NTDLL.@]
397  * 
398  */
399 NTSTATUS WINAPI RtlSetBits(DWORD x1,DWORD x2,DWORD x3)
400 {
401         FIXME("(0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3);
402         return 0;
403 }
404
405 /******************************************************************************
406  *  RtlFindClearBits                    [NTDLL.@]
407  * 
408  */
409 NTSTATUS WINAPI RtlFindClearBits(DWORD x1,DWORD x2,DWORD x3)
410 {
411         FIXME("(0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3);
412         return 0;
413 }
414
415 /******************************************************************************
416  *  RtlClearBits                        [NTDLL.@]
417  * 
418  */
419 NTSTATUS WINAPI RtlClearBits(DWORD x1,DWORD x2,DWORD x3)
420 {
421         FIXME("(0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3);
422         return 0;
423 }
424
425 /******************************************************************************
426  *  RtlCopyMemory   [NTDLL] 
427  * 
428  */
429 #undef RtlCopyMemory
430 VOID WINAPI RtlCopyMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
431 {
432     memcpy(Destination, Source, Length);
433 }       
434
435 /******************************************************************************
436  *  RtlMoveMemory   [NTDLL.@]
437  */
438 #undef RtlMoveMemory
439 VOID WINAPI RtlMoveMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
440 {
441     memmove(Destination, Source, Length);
442 }
443
444 /******************************************************************************
445  *  RtlFillMemory   [NTDLL.@]
446  */
447 #undef RtlFillMemory
448 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
449 {
450     memset(Destination, Fill, Length);
451 }
452
453 /******************************************************************************
454  *  RtlZeroMemory   [NTDLL.@]
455  */
456 #undef RtlZeroMemory
457 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
458 {
459     memset(Destination, 0, Length);
460 }
461
462 /******************************************************************************
463  *  RtlCompareMemory   [NTDLL.@]
464  */
465 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
466 {
467     int i;
468     for(i=0; (i<Length) && (((LPBYTE)Source1)[i]==((LPBYTE)Source2)[i]); i++);
469     return i;
470 }
471
472 /******************************************************************************
473  *  RtlAssert                           [NTDLL.@]
474  *
475  * Not implemented in non-debug versions.
476  */
477 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
478 {
479         FIXME("(%p,%p,0x%08lx,0x%08lx),stub\n",x1,x2,x3,x4);
480 }