Fix CreateProcessA to implement correct actions on ambiguous command
[wine/multimedia.git] / dlls / ntdll / rtl.c
blobd0c8c93beca6a506282e33ae54770bad0067bfef
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 */
10 #include <stdlib.h>
11 #include <string.h>
12 #include "heap.h"
13 #include "debug.h"
14 #include "winuser.h"
15 #include "winerror.h"
16 #include "stackframe.h"
18 #include "ntddk.h"
19 #include "winreg.h"
21 DEFAULT_DEBUG_CHANNEL(ntdll)
25 * resource functions
28 /***********************************************************************
29 * RtlInitializeResource (NTDLL.409)
31 * xxxResource() functions implement multiple-reader-single-writer lock.
32 * The code is based on information published in WDJ January 1999 issue.
34 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
36 if( rwl )
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 );
50 /***********************************************************************
51 * RtlDeleteResource (NTDLL.330)
53 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
55 if( rwl )
57 EnterCriticalSection( &rwl->rtlCS );
58 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
59 MSG("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 );
71 /***********************************************************************
72 * RtlAcquireResourceExclusive (NTDLL.256)
74 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
76 BYTE retVal = 0;
77 if( !rwl ) return 0;
79 start:
80 EnterCriticalSection( &rwl->rtlCS );
81 if( rwl->iNumberActive == 0 ) /* lock is free */
83 rwl->iNumberActive = -1;
84 retVal = 1;
86 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
88 if( rwl->hOwningThreadId == GetCurrentThreadId() )
90 retVal = 1;
91 rwl->iNumberActive--;
92 goto done;
94 wait:
95 if( fWait )
97 rwl->uExclusiveWaiters++;
99 LeaveCriticalSection( &rwl->rtlCS );
100 if( WaitForSingleObject( rwl->hExclusiveReleaseSemaphore, INFINITE ) == WAIT_FAILED )
101 goto done;
102 goto start; /* restart the acquisition to avoid deadlocks */
105 else /* one or more shared locks are in progress */
106 if( fWait )
107 goto wait;
109 if( retVal == 1 )
110 rwl->hOwningThreadId = GetCurrentThreadId();
111 done:
112 LeaveCriticalSection( &rwl->rtlCS );
113 return retVal;
116 /***********************************************************************
117 * RtlAcquireResourceShared (NTDLL.257)
119 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
121 DWORD dwWait = WAIT_FAILED;
122 BYTE retVal = 0;
123 if( !rwl ) return 0;
125 start:
126 EnterCriticalSection( &rwl->rtlCS );
127 if( rwl->iNumberActive < 0 )
129 if( rwl->hOwningThreadId == GetCurrentThreadId() )
131 rwl->iNumberActive--;
132 retVal = 1;
133 goto done;
136 if( fWait )
138 rwl->uSharedWaiters++;
139 LeaveCriticalSection( &rwl->rtlCS );
140 if( (dwWait = WaitForSingleObject( rwl->hSharedReleaseSemaphore, INFINITE )) == WAIT_FAILED )
141 goto done;
142 goto start;
145 else
147 if( dwWait != WAIT_OBJECT_0 ) /* otherwise RtlReleaseResource() has already done it */
148 rwl->iNumberActive++;
149 retVal = 1;
151 done:
152 LeaveCriticalSection( &rwl->rtlCS );
153 return retVal;
157 /***********************************************************************
158 * RtlReleaseResource (NTDLL.471)
160 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
162 EnterCriticalSection( &rwl->rtlCS );
164 if( rwl->iNumberActive > 0 ) /* have one or more readers */
166 if( --rwl->iNumberActive == 0 )
168 if( rwl->uExclusiveWaiters )
170 wake_exclusive:
171 rwl->uExclusiveWaiters--;
172 ReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
176 else
177 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
179 if( ++rwl->iNumberActive == 0 )
181 rwl->hOwningThreadId = 0;
182 if( rwl->uExclusiveWaiters )
183 goto wake_exclusive;
184 else
185 if( rwl->uSharedWaiters )
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 );
195 LeaveCriticalSection( &rwl->rtlCS );
199 /***********************************************************************
200 * RtlDumpResource (NTDLL.340)
202 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
204 if( rwl )
206 MSG("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 MSG("\towner thread = %08x\n", rwl->hOwningThreadId );
214 * heap functions
217 /******************************************************************************
218 * RtlCreateHeap [NTDLL]
220 HANDLE WINAPI RtlCreateHeap(
221 ULONG Flags,
222 PVOID BaseAddress,
223 ULONG SizeToReserve,
224 ULONG SizeToCommit,
225 PVOID Unknown,
226 PRTL_HEAP_DEFINITION Definition)
228 FIXME (ntdll,"(0x%08lx, %p, 0x%08lx, 0x%08lx, %p, %p) semi-stub\n",
229 Flags, BaseAddress, SizeToReserve, SizeToCommit, Unknown, Definition);
231 return HeapCreate ( Flags, SizeToCommit, SizeToReserve);
234 /******************************************************************************
235 * RtlAllocateHeap [NTDLL]
237 PVOID WINAPI RtlAllocateHeap(
238 HANDLE Heap,
239 ULONG Flags,
240 ULONG Size)
242 FIXME(ntdll,"(0x%08x, 0x%08lx, 0x%08lx) semi stub\n",
243 Heap, Flags, Size);
244 return HeapAlloc(Heap, Flags, Size);
247 /******************************************************************************
248 * RtlFreeHeap [NTDLL]
250 BOOLEAN WINAPI RtlFreeHeap(
251 HANDLE Heap,
252 ULONG Flags,
253 PVOID Address)
255 FIXME(ntdll,"(0x%08x, 0x%08lx, %p) semi stub\n",
256 Heap, Flags, Address);
257 return HeapFree(Heap, Flags, Address);
260 /******************************************************************************
261 * RtlDestroyHeap [NTDLL]
263 * FIXME: prototype guessed
265 BOOLEAN WINAPI RtlDestroyHeap(
266 HANDLE Heap)
268 FIXME(ntdll,"(0x%08x) semi stub\n", Heap);
269 return HeapDestroy(Heap);
273 * misc functions
276 /******************************************************************************
277 * DbgPrint [NTDLL]
279 void __cdecl DbgPrint(LPCSTR fmt,LPVOID args) {
280 char buf[512];
282 wvsprintfA(buf,fmt,&args);
283 MSG("DbgPrint says: %s",buf);
284 /* hmm, raise exception? */
286 DWORD NtRaiseException ( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,CONST ULONG_PTR *lpArguments)
287 { FIXME(ntdll,"0x%08lx 0x%08lx 0x%08lx %p\n", dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
288 return 0;
291 DWORD RtlRaiseException ( DWORD x)
292 { FIXME(ntdll, "0x%08lx\n", x);
293 return 0;
295 /******************************************************************************
296 * RtlAcquirePebLock [NTDLL]
298 VOID WINAPI RtlAcquirePebLock(void) {
299 FIXME(ntdll,"()\n");
300 /* enter critical section ? */
303 /******************************************************************************
304 * RtlReleasePebLock [NTDLL]
306 VOID WINAPI RtlReleasePebLock(void) {
307 FIXME(ntdll,"()\n");
308 /* leave critical section ? */
311 /******************************************************************************
312 * RtlIntegerToChar [NTDLL]
314 DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
315 FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
316 return 0;
318 /******************************************************************************
319 * RtlSetEnvironmentVariable [NTDLL]
321 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
322 FIXME(ntdll,"(0x%08lx,%s,%s),stub!\n",x1,debugstr_w(key->Buffer),debugstr_w(val->Buffer));
323 return 0;
326 /******************************************************************************
327 * RtlNewSecurityObject [NTDLL]
329 DWORD WINAPI RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
330 FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6);
331 return 0;
334 /******************************************************************************
335 * RtlDeleteSecurityObject [NTDLL]
337 DWORD WINAPI RtlDeleteSecurityObject(DWORD x1) {
338 FIXME(ntdll,"(0x%08lx),stub!\n",x1);
339 return 0;
342 /**************************************************************************
343 * RtlNormalizeProcessParams [NTDLL.441]
345 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
347 FIXME(ntdll,"(%p), stub\n",x);
348 return x;
351 /**************************************************************************
352 * RtlNtStatusToDosError [NTDLL.442]
354 DWORD WINAPI RtlNtStatusToDosError(DWORD error)
356 FIXME(ntdll, "(%lx): map STATUS_ to ERROR_\n",error);
357 switch (error)
358 { case STATUS_SUCCESS: return ERROR_SUCCESS;
359 case STATUS_INVALID_PARAMETER: return ERROR_BAD_ARGUMENTS;
360 case STATUS_BUFFER_TOO_SMALL: return ERROR_INSUFFICIENT_BUFFER;
361 /* case STATUS_INVALID_SECURITY_DESCR: return ERROR_INVALID_SECURITY_DESCR;*/
362 case STATUS_NO_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
363 /* case STATUS_UNKNOWN_REVISION:
364 case STATUS_BUFFER_OVERFLOW:*/
366 FIXME(ntdll, "unknown status (%lx)\n",error);
367 return ERROR_SUCCESS;
370 /**************************************************************************
371 * RtlGetNtProductType [NTDLL.390]
373 BOOLEAN WINAPI RtlGetNtProductType(LPDWORD type)
375 FIXME(ntdll, "(%p): stub\n", type);
376 *type=3; /* dunno. 1 for client, 3 for server? */
377 return 1;
380 /**************************************************************************
381 * NTDLL_chkstk [NTDLL.862]
382 * NTDLL_alloca_probe [NTDLL.861]
383 * Glorified "enter xxxx".
385 REGS_ENTRYPOINT(NTDLL_chkstk)
387 ESP_reg(context) -= EAX_reg(context);
389 REGS_ENTRYPOINT(NTDLL_alloca_probe)
391 ESP_reg(context) -= EAX_reg(context);
394 /******************************************************************************
395 * RtlExtendedLargeIntegerDivide [NTDLL.359]
397 INT WINAPI RtlExtendedLargeIntegerDivide(
398 LARGE_INTEGER dividend,
399 DWORD divisor,
400 LPDWORD rest
402 #if SIZEOF_LONG_LONG==8
403 long long x1 = *(long long*)&dividend;
405 if (*rest)
406 *rest = x1 % divisor;
407 return x1/divisor;
408 #else
409 FIXME(ntdll,"((%d<<32)+%d,%d,%p), implement this using normal integer arithmetic!\n",dividend.HighPart,dividend.LowPart,divisor,rest);
410 return 0;
411 #endif
414 /******************************************************************************
415 * RtlExtendedLargeIntegerMultiply [NTDLL.359]
416 * Note: This even works, since gcc returns 64bit values in eax/edx just like
417 * the caller expects. However... The relay code won't grok this I think.
419 long long WINAPI RtlExtendedIntegerMultiply(
420 LARGE_INTEGER factor1,
421 INT factor2)
423 #if SIZEOF_LONG_LONG==8
424 return (*(long long*)&factor1) * factor2;
425 #else
426 FIXME(ntdll,"((%d<<32)+%d,%ld), implement this using normal integer arithmetic!\n",factor1.HighPart,factor1.LowPart,factor2);
427 return 0;
428 #endif
431 /******************************************************************************
432 * RtlFormatCurrentUserKeyPath [NTDLL.371]
434 DWORD WINAPI RtlFormatCurrentUserKeyPath(DWORD x)
436 FIXME(ntdll,"(0x%08lx): stub\n",x);
437 return 1;
440 /******************************************************************************
441 * RtlOpenCurrentUser [NTDLL]
443 DWORD WINAPI RtlOpenCurrentUser(DWORD x1, DWORD *x2)
445 /* Note: this is not the correct solution,
446 * But this works pretty good on wine and NT4.0 binaries
448 if ( x1 == 0x2000000 ) {
449 *x2 = HKEY_CURRENT_USER;
450 return TRUE;
453 return FALSE;
455 /**************************************************************************
456 * RtlDosPathNameToNtPathName_U [NTDLL.338]
458 * FIXME: convert to UNC or whatever is expected here
460 BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(
461 LPWSTR from,PUNICODE_STRING us,DWORD x2,DWORD x3)
463 LPSTR fromA = HEAP_strdupWtoA(GetProcessHeap(),0,from);
465 FIXME(ntdll,"(%s,%p,%08lx,%08lx)\n",fromA,us,x2,x3);
466 if (us)
467 RtlInitUnicodeString(us,HEAP_strdupW(GetProcessHeap(),0,from));
468 return TRUE;
471 /******************************************************************************
472 * RtlCreateEnvironment [NTDLL]
474 DWORD WINAPI RtlCreateEnvironment(DWORD x1,DWORD x2) {
475 FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n",x1,x2);
476 return 0;
480 /******************************************************************************
481 * RtlDestroyEnvironment [NTDLL]
483 DWORD WINAPI RtlDestroyEnvironment(DWORD x) {
484 FIXME(ntdll,"(0x%08lx),stub!\n",x);
485 return 0;
488 /******************************************************************************
489 * RtlQueryEnvironmentVariable_U [NTDLL]
491 DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
492 FIXME(ntdll,"(0x%08lx,%s,%p),stub!\n",x1,debugstr_w(key->Buffer),val);
493 return 0;