4 * This file contains the Rtl* API functions. These should be implementable.
6 * Copyright 1996-1998 Marcus Meissner
16 #include "stackframe.h"
26 /***********************************************************************
27 * RtlInitializeResource (NTDLL.409)
29 * xxxResource() functions implement multiple-reader-single-writer lock.
30 * The code is based on information published in WDJ January 1999 issue.
32 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
36 rwl->iNumberActive = 0;
37 rwl->uExclusiveWaiters = 0;
38 rwl->uSharedWaiters = 0;
39 rwl->hOwningThreadId = 0;
40 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
41 InitializeCriticalSection( &rwl->rtlCS );
42 rwl->hExclusiveReleaseSemaphore = CreateSemaphoreA( NULL, 0, 65535, NULL );
43 rwl->hSharedReleaseSemaphore = CreateSemaphoreA( NULL, 0, 65535, NULL );
48 /***********************************************************************
49 * RtlDeleteResource (NTDLL.330)
51 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
55 EnterCriticalSection( &rwl->rtlCS );
56 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
57 MSG("Deleting active MRSW lock (%p), expect failure\n", rwl );
58 rwl->hOwningThreadId = 0;
59 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
60 rwl->iNumberActive = 0;
61 CloseHandle( rwl->hExclusiveReleaseSemaphore );
62 CloseHandle( rwl->hSharedReleaseSemaphore );
63 LeaveCriticalSection( &rwl->rtlCS );
64 DeleteCriticalSection( &rwl->rtlCS );
69 /***********************************************************************
70 * RtlAcquireResourceExclusive (NTDLL.256)
72 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
78 EnterCriticalSection( &rwl->rtlCS );
79 if( rwl->iNumberActive == 0 ) /* lock is free */
81 rwl->iNumberActive = -1;
84 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
86 if( rwl->hOwningThreadId == GetCurrentThreadId() )
95 rwl->uExclusiveWaiters++;
97 LeaveCriticalSection( &rwl->rtlCS );
98 if( WaitForSingleObject( rwl->hExclusiveReleaseSemaphore, INFINITE ) == WAIT_FAILED )
100 goto start; /* restart the acquisition to avoid deadlocks */
103 else /* one or more shared locks are in progress */
108 rwl->hOwningThreadId = GetCurrentThreadId();
110 LeaveCriticalSection( &rwl->rtlCS );
114 /***********************************************************************
115 * RtlAcquireResourceShared (NTDLL.257)
117 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
119 DWORD dwWait = WAIT_FAILED;
124 EnterCriticalSection( &rwl->rtlCS );
125 if( rwl->iNumberActive < 0 )
127 if( rwl->hOwningThreadId == GetCurrentThreadId() )
129 rwl->iNumberActive--;
136 rwl->uSharedWaiters++;
137 LeaveCriticalSection( &rwl->rtlCS );
138 if( (dwWait = WaitForSingleObject( rwl->hSharedReleaseSemaphore, INFINITE )) == WAIT_FAILED )
145 if( dwWait != WAIT_OBJECT_0 ) /* otherwise RtlReleaseResource() has already done it */
146 rwl->iNumberActive++;
150 LeaveCriticalSection( &rwl->rtlCS );
155 /***********************************************************************
156 * RtlReleaseResource (NTDLL.471)
158 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
160 EnterCriticalSection( &rwl->rtlCS );
162 if( rwl->iNumberActive > 0 ) /* have one or more readers */
164 if( --rwl->iNumberActive == 0 )
166 if( rwl->uExclusiveWaiters )
169 rwl->uExclusiveWaiters--;
170 ReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
175 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
177 if( ++rwl->iNumberActive == 0 )
179 rwl->hOwningThreadId = 0;
180 if( rwl->uExclusiveWaiters )
183 if( rwl->uSharedWaiters )
185 UINT n = rwl->uSharedWaiters;
186 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
187 * all queued readers have done their thing */
188 rwl->uSharedWaiters = 0;
189 ReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
193 LeaveCriticalSection( &rwl->rtlCS );
197 /***********************************************************************
198 * RtlDumpResource (NTDLL.340)
200 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
204 MSG("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
205 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
206 if( rwl->iNumberActive )
207 MSG("\towner thread = %08x\n", rwl->hOwningThreadId );
215 /******************************************************************************
216 * RtlCreateHeap [NTDLL]
218 HANDLE WINAPI RtlCreateHeap(
224 PRTL_HEAP_DEFINITION Definition)
226 FIXME (ntdll,"(0x%08lx, %p, 0x%08lx, 0x%08lx, %p, %p) semi-stub\n",
227 Flags, BaseAddress, SizeToReserve, SizeToCommit, Unknown, Definition);
229 return HeapCreate ( Flags, SizeToCommit, SizeToReserve);
232 /******************************************************************************
233 * RtlAllocateHeap [NTDLL]
235 PVOID WINAPI RtlAllocateHeap(
240 FIXME(ntdll,"(0x%08x, 0x%08lx, 0x%08lx) semi stub\n",
242 return HeapAlloc(Heap, Flags, Size);
245 /******************************************************************************
246 * RtlFreeHeap [NTDLL]
248 BOOLEAN WINAPI RtlFreeHeap(
253 FIXME(ntdll,"(0x%08x, 0x%08lx, %p) semi stub\n",
254 Heap, Flags, Address);
255 return HeapFree(Heap, Flags, Address);
258 /******************************************************************************
259 * RtlDestroyHeap [NTDLL]
261 * FIXME: prototype guessed
263 BOOLEAN WINAPI RtlDestroyHeap(
266 FIXME(ntdll,"(0x%08x) semi stub\n", Heap);
267 return HeapDestroy(Heap);
274 /******************************************************************************
277 void __cdecl DbgPrint(LPCSTR fmt,LPVOID args) {
280 wvsprintfA(buf,fmt,&args);
281 MSG("DbgPrint says: %s",buf);
282 /* hmm, raise exception? */
284 DWORD NtRaiseException ( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,CONST ULONG_PTR *lpArguments)
285 { FIXME(ntdll,"0x%08lx 0x%08lx 0x%08lx %p\n", dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
289 DWORD RtlRaiseException ( DWORD x)
290 { FIXME(ntdll, "0x%08lx\n", x);
293 /******************************************************************************
294 * RtlAcquirePebLock [NTDLL]
296 VOID WINAPI RtlAcquirePebLock(void) {
298 /* enter critical section ? */
301 /******************************************************************************
302 * RtlReleasePebLock [NTDLL]
304 VOID WINAPI RtlReleasePebLock(void) {
306 /* leave critical section ? */
309 /******************************************************************************
310 * RtlIntegerToChar [NTDLL]
312 DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
313 FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
316 /******************************************************************************
317 * RtlSetEnvironmentVariable [NTDLL]
319 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
320 FIXME(ntdll,"(0x%08lx,%s,%s),stub!\n",x1,debugstr_w(key->Buffer),debugstr_w(val->Buffer));
324 /******************************************************************************
325 * RtlNewSecurityObject [NTDLL]
327 DWORD WINAPI RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6) {
328 FIXME(ntdll,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6);
332 /******************************************************************************
333 * RtlDeleteSecurityObject [NTDLL]
335 DWORD WINAPI RtlDeleteSecurityObject(DWORD x1) {
336 FIXME(ntdll,"(0x%08lx),stub!\n",x1);
340 /**************************************************************************
341 * RtlNormalizeProcessParams [NTDLL.441]
343 LPVOID WINAPI RtlNormalizeProcessParams(LPVOID x)
345 FIXME(ntdll,"(%p), stub\n",x);
349 /**************************************************************************
350 * RtlNtStatusToDosError [NTDLL.442]
352 DWORD WINAPI RtlNtStatusToDosError(DWORD error)
354 FIXME(ntdll, "(%lx): map STATUS_ to ERROR_\n",error);
356 { case STATUS_SUCCESS: return ERROR_SUCCESS;
357 case STATUS_INVALID_PARAMETER: return ERROR_BAD_ARGUMENTS;
358 case STATUS_BUFFER_TOO_SMALL: return ERROR_INSUFFICIENT_BUFFER;
359 /* case STATUS_INVALID_SECURITY_DESCR: return ERROR_INVALID_SECURITY_DESCR;*/
360 case STATUS_NO_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
361 /* case STATUS_UNKNOWN_REVISION:
362 case STATUS_BUFFER_OVERFLOW:*/
364 FIXME(ntdll, "unknown status (%lx)\n",error);
365 return ERROR_SUCCESS;
368 /**************************************************************************
369 * RtlGetNtProductType [NTDLL.390]
371 BOOLEAN WINAPI RtlGetNtProductType(LPDWORD type)
373 FIXME(ntdll, "(%p): stub\n", type);
374 *type=3; /* dunno. 1 for client, 3 for server? */
378 /**************************************************************************
379 * NTDLL_chkstk [NTDLL.862]
380 * NTDLL_alloca_probe [NTDLL.861]
381 * Glorified "enter xxxx".
383 REGS_ENTRYPOINT(NTDLL_chkstk)
385 ESP_reg(context) -= EAX_reg(context);
387 REGS_ENTRYPOINT(NTDLL_alloca_probe)
389 ESP_reg(context) -= EAX_reg(context);
392 /******************************************************************************
393 * RtlExtendedLargeIntegerDivide [NTDLL.359]
395 INT WINAPI RtlExtendedLargeIntegerDivide(
396 LARGE_INTEGER dividend,
400 #if SIZEOF_LONG_LONG==8
401 long long x1 = *(long long*)÷nd;
404 *rest = x1 % divisor;
407 FIXME(ntdll,"((%d<<32)+%d,%d,%p), implement this using normal integer arithmetic!\n",dividend.HighPart,dividend.LowPart,divisor,rest);
412 /******************************************************************************
413 * RtlExtendedLargeIntegerMultiply [NTDLL.359]
414 * Note: This even works, since gcc returns 64bit values in eax/edx just like
415 * the caller expects. However... The relay code won't grok this I think.
417 long long WINAPI RtlExtendedIntegerMultiply(
418 LARGE_INTEGER factor1,
421 #if SIZEOF_LONG_LONG==8
422 return (*(long long*)&factor1) * factor2;
424 FIXME(ntdll,"((%d<<32)+%d,%ld), implement this using normal integer arithmetic!\n",factor1.HighPart,factor1.LowPart,factor2);
429 /******************************************************************************
430 * RtlFormatCurrentUserKeyPath [NTDLL.371]
432 DWORD WINAPI RtlFormatCurrentUserKeyPath(DWORD x)
434 FIXME(ntdll,"(0x%08lx): stub\n",x);
438 /******************************************************************************
439 * RtlOpenCurrentUser [NTDLL]
441 DWORD WINAPI RtlOpenCurrentUser(DWORD x1, DWORD *x2)
443 /* Note: this is not the correct solution,
444 * But this works pretty good on wine and NT4.0 binaries
446 if ( x1 == 0x2000000 ) {
447 *x2 = HKEY_CURRENT_USER;
453 /**************************************************************************
454 * RtlDosPathNameToNtPathName_U [NTDLL.338]
456 * FIXME: convert to UNC or whatever is expected here
458 BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(
459 LPWSTR from,PUNICODE_STRING us,DWORD x2,DWORD x3)
461 LPSTR fromA = HEAP_strdupWtoA(GetProcessHeap(),0,from);
463 FIXME(ntdll,"(%s,%p,%08lx,%08lx)\n",fromA,us,x2,x3);
465 RtlInitUnicodeString(us,HEAP_strdupW(GetProcessHeap(),0,from));
469 /******************************************************************************
470 * RtlCreateEnvironment [NTDLL]
472 DWORD WINAPI RtlCreateEnvironment(DWORD x1,DWORD x2) {
473 FIXME(ntdll,"(0x%08lx,0x%08lx),stub!\n",x1,x2);
478 /******************************************************************************
479 * RtlDestroyEnvironment [NTDLL]
481 DWORD WINAPI RtlDestroyEnvironment(DWORD x) {
482 FIXME(ntdll,"(0x%08lx),stub!\n",x);
486 /******************************************************************************
487 * RtlQueryEnvironmentVariable_U [NTDLL]
489 DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
490 FIXME(ntdll,"(0x%08lx,%s,%p),stub!\n",x1,debugstr_w(key->Buffer),val);