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