4 * This file contains the Rtl* API functions. These should be implementable.
6 * Copyright 1996-1998 Marcus Meissner
16 #include "stackframe.h"
21 DEFAULT_DEBUG_CHANNEL(ntdll
)
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
)
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
)
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
)
80 EnterCriticalSection( &rwl
->rtlCS
);
81 if( rwl
->iNumberActive
== 0 ) /* lock is free */
83 rwl
->iNumberActive
= -1;
86 else if( rwl
->iNumberActive
< 0 ) /* exclusive lock in progress */
88 if( rwl
->hOwningThreadId
== GetCurrentThreadId() )
97 rwl
->uExclusiveWaiters
++;
99 LeaveCriticalSection( &rwl
->rtlCS
);
100 if( WaitForSingleObject( rwl
->hExclusiveReleaseSemaphore
, INFINITE
) == WAIT_FAILED
)
102 goto start
; /* restart the acquisition to avoid deadlocks */
105 else /* one or more shared locks are in progress */
110 rwl
->hOwningThreadId
= GetCurrentThreadId();
112 LeaveCriticalSection( &rwl
->rtlCS
);
116 /***********************************************************************
117 * RtlAcquireResourceShared (NTDLL.257)
119 BYTE WINAPI
RtlAcquireResourceShared(LPRTL_RWLOCK rwl
, BYTE fWait
)
121 DWORD dwWait
= WAIT_FAILED
;
126 EnterCriticalSection( &rwl
->rtlCS
);
127 if( rwl
->iNumberActive
< 0 )
129 if( rwl
->hOwningThreadId
== GetCurrentThreadId() )
131 rwl
->iNumberActive
--;
138 rwl
->uSharedWaiters
++;
139 LeaveCriticalSection( &rwl
->rtlCS
);
140 if( (dwWait
= WaitForSingleObject( rwl
->hSharedReleaseSemaphore
, INFINITE
)) == WAIT_FAILED
)
147 if( dwWait
!= WAIT_OBJECT_0
) /* otherwise RtlReleaseResource() has already done it */
148 rwl
->iNumberActive
++;
152 LeaveCriticalSection( &rwl
->rtlCS
);
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
)
171 rwl
->uExclusiveWaiters
--;
172 ReleaseSemaphore( rwl
->hExclusiveReleaseSemaphore
, 1, NULL
);
177 if( rwl
->iNumberActive
< 0 ) /* have a writer, possibly recursive */
179 if( ++rwl
->iNumberActive
== 0 )
181 rwl
->hOwningThreadId
= 0;
182 if( rwl
->uExclusiveWaiters
)
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
)
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
);
217 /******************************************************************************
218 * RtlCreateHeap [NTDLL]
220 HANDLE WINAPI
RtlCreateHeap(
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(
242 FIXME(ntdll
,"(0x%08x, 0x%08lx, 0x%08lx) semi stub\n",
244 return HeapAlloc(Heap
, Flags
, Size
);
247 /******************************************************************************
248 * RtlFreeHeap [NTDLL]
250 BOOLEAN WINAPI
RtlFreeHeap(
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(
268 FIXME(ntdll
,"(0x%08x) semi stub\n", Heap
);
269 return HeapDestroy(Heap
);
276 /******************************************************************************
279 void __cdecl
DbgPrint(LPCSTR fmt
,LPVOID args
) {
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
);
291 DWORD
RtlRaiseException ( DWORD x
)
292 { FIXME(ntdll
, "0x%08lx\n", x
);
295 /******************************************************************************
296 * RtlAcquirePebLock [NTDLL]
298 VOID WINAPI
RtlAcquirePebLock(void) {
300 /* enter critical section ? */
303 /******************************************************************************
304 * RtlReleasePebLock [NTDLL]
306 VOID WINAPI
RtlReleasePebLock(void) {
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
);
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
));
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
);
334 /******************************************************************************
335 * RtlDeleteSecurityObject [NTDLL]
337 DWORD WINAPI
RtlDeleteSecurityObject(DWORD x1
) {
338 FIXME(ntdll
,"(0x%08lx),stub!\n",x1
);
342 /**************************************************************************
343 * RtlNormalizeProcessParams [NTDLL.441]
345 LPVOID WINAPI
RtlNormalizeProcessParams(LPVOID x
)
347 FIXME(ntdll
,"(%p), stub\n",x
);
351 /**************************************************************************
352 * RtlNtStatusToDosError [NTDLL.442]
354 DWORD WINAPI
RtlNtStatusToDosError(DWORD error
)
356 FIXME(ntdll
, "(%lx): map STATUS_ to ERROR_\n",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? */
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
,
402 #if SIZEOF_LONG_LONG==8
403 long long x1
= *(long long*)÷nd
;
406 *rest
= x1
% divisor
;
409 FIXME(ntdll
,"((%d<<32)+%d,%d,%p), implement this using normal integer arithmetic!\n",dividend
.HighPart
,dividend
.LowPart
,divisor
,rest
);
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
,
423 #if SIZEOF_LONG_LONG==8
424 return (*(long long*)&factor1
) * factor2
;
426 FIXME(ntdll
,"((%d<<32)+%d,%ld), implement this using normal integer arithmetic!\n",factor1
.HighPart
,factor1
.LowPart
,factor2
);
431 /******************************************************************************
432 * RtlFormatCurrentUserKeyPath [NTDLL.371]
434 DWORD WINAPI
RtlFormatCurrentUserKeyPath(DWORD x
)
436 FIXME(ntdll
,"(0x%08lx): stub\n",x
);
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
;
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
);
467 RtlInitUnicodeString(us
,HEAP_strdupW(GetProcessHeap(),0,from
));
471 /******************************************************************************
472 * RtlCreateEnvironment [NTDLL]
474 DWORD WINAPI
RtlCreateEnvironment(DWORD x1
,DWORD x2
) {
475 FIXME(ntdll
,"(0x%08lx,0x%08lx),stub!\n",x1
,x2
);
480 /******************************************************************************
481 * RtlDestroyEnvironment [NTDLL]
483 DWORD WINAPI
RtlDestroyEnvironment(DWORD x
) {
484 FIXME(ntdll
,"(0x%08lx),stub!\n",x
);
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
);