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