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