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