4 * This file contains the Rtl* API functions. These should be implementable.
6 * Copyright 1996-1998 Marcus Meissner
13 #include "debugtools.h"
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 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
);
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 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
);
217 /******************************************************************************
218 * RtlCreateHeap [NTDLL]
220 HANDLE WINAPI
RtlCreateHeap(
226 PRTL_HEAP_DEFINITION Definition
)
228 FIXME("(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("(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("(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("(0x%08x) semi stub\n", Heap
);
269 return HeapDestroy(Heap
);
276 /******************************************************************************
279 void WINAPIV
DbgPrint(LPCSTR fmt
, ...) {
284 wvsprintfA(buf
,fmt
, args
);
287 MESSAGE("DbgPrint says: %s",buf
);
288 /* hmm, raise exception? */
291 /******************************************************************************
292 * RtlAcquirePebLock [NTDLL]
294 VOID WINAPI
RtlAcquirePebLock(void) {
296 /* enter critical section ? */
299 /******************************************************************************
300 * RtlReleasePebLock [NTDLL]
302 VOID WINAPI
RtlReleasePebLock(void) {
304 /* leave critical section ? */
307 /******************************************************************************
308 * RtlIntegerToChar [NTDLL]
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
);
314 /******************************************************************************
315 * RtlSetEnvironmentVariable [NTDLL]
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
));
322 /******************************************************************************
323 * RtlNewSecurityObject [NTDLL]
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
);
330 /******************************************************************************
331 * RtlDeleteSecurityObject [NTDLL]
333 DWORD WINAPI
RtlDeleteSecurityObject(DWORD x1
) {
334 FIXME("(0x%08lx),stub!\n",x1
);
338 /**************************************************************************
339 * RtlNormalizeProcessParams [NTDLL.441]
341 LPVOID WINAPI
RtlNormalizeProcessParams(LPVOID x
)
343 FIXME("(%p), stub\n",x
);
347 /**************************************************************************
348 * RtlNtStatusToDosError [NTDLL.442]
350 DWORD WINAPI
RtlNtStatusToDosError(DWORD error
)
352 FIXME("(%lx): map STATUS_ to ERROR_\n",error
);
354 { case STATUS_SUCCESS
: return ERROR_SUCCESS
;
355 case STATUS_INVALID_PARAMETER
: return ERROR_BAD_ARGUMENTS
;
356 case STATUS_BUFFER_TOO_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
357 /* case STATUS_INVALID_SECURITY_DESCR: return ERROR_INVALID_SECURITY_DESCR;*/
358 case STATUS_NO_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
359 /* case STATUS_UNKNOWN_REVISION:
360 case STATUS_BUFFER_OVERFLOW:*/
362 FIXME("unknown status (%lx)\n",error
);
363 return ERROR_SUCCESS
;
366 /**************************************************************************
367 * RtlGetNtProductType [NTDLL.390]
369 BOOLEAN WINAPI
RtlGetNtProductType(LPDWORD type
)
371 FIXME("(%p): stub\n", type
);
372 *type
=3; /* dunno. 1 for client, 3 for server? */
376 /**************************************************************************
377 * NTDLL_chkstk [NTDLL.862]
378 * NTDLL_alloca_probe [NTDLL.861]
379 * Glorified "enter xxxx".
381 void WINAPI
NTDLL_chkstk( CONTEXT86
*context
)
383 ESP_reg(context
) -= EAX_reg(context
);
385 void WINAPI
NTDLL_alloca_probe( CONTEXT86
*context
)
387 ESP_reg(context
) -= EAX_reg(context
);
390 /******************************************************************************
391 * RtlExtendedLargeIntegerDivide [NTDLL.359]
393 INT WINAPI
RtlExtendedLargeIntegerDivide(
394 LARGE_INTEGER dividend
,
398 #if SIZEOF_LONG_LONG==8
399 long long x1
= *(long long*)÷nd
;
402 *rest
= x1
% divisor
;
405 FIXME("((%ld<<32)+%ld,%ld,%p), implement this using normal integer arithmetic!\n",dividend
.HighPart
,dividend
.LowPart
,divisor
,rest
);
410 /******************************************************************************
411 * RtlExtendedLargeIntegerMultiply [NTDLL.359]
412 * Note: This even works, since gcc returns 64bit values in eax/edx just like
413 * the caller expects. However... The relay code won't grok this I think.
415 LARGE_INTEGER WINAPI
RtlExtendedIntegerMultiply(
416 LARGE_INTEGER factor1
,
419 #if SIZEOF_LONG_LONG==8
420 long long result
= (*(long long*)&factor1
) * factor2
;
421 return (*(LARGE_INTEGER
*)&result
);
423 FIXME("((%ld<<32)+%ld,%d), implement this using normal integer arithmetic!\n",factor1
.HighPart
,factor1
.LowPart
,factor2
);
428 /******************************************************************************
429 * RtlFormatCurrentUserKeyPath [NTDLL.371]
431 DWORD WINAPI
RtlFormatCurrentUserKeyPath(PUNICODE_STRING String
)
433 FIXME("(%p): stub\n",String
);
437 /******************************************************************************
438 * RtlOpenCurrentUser [NTDLL]
440 DWORD WINAPI
RtlOpenCurrentUser(DWORD x1
, DWORD
*x2
)
442 /* Note: this is not the correct solution,
443 * But this works pretty good on wine and NT4.0 binaries
445 if ( x1
== 0x2000000 ) {
446 *x2
= HKEY_CURRENT_USER
;
452 /**************************************************************************
453 * RtlDosPathNameToNtPathName_U [NTDLL.338]
455 * FIXME: convert to UNC or whatever is expected here
457 BOOLEAN WINAPI
RtlDosPathNameToNtPathName_U(
458 LPWSTR from
,PUNICODE_STRING us
,DWORD x2
,DWORD x3
)
460 LPSTR fromA
= HEAP_strdupWtoA(GetProcessHeap(),0,from
);
462 FIXME("(%s,%p,%08lx,%08lx)\n",fromA
,us
,x2
,x3
);
464 RtlInitUnicodeString(us
,HEAP_strdupW(GetProcessHeap(),0,from
));
468 /******************************************************************************
469 * RtlCreateEnvironment [NTDLL]
471 DWORD WINAPI
RtlCreateEnvironment(DWORD x1
,DWORD x2
) {
472 FIXME("(0x%08lx,0x%08lx),stub!\n",x1
,x2
);
477 /******************************************************************************
478 * RtlDestroyEnvironment [NTDLL]
480 DWORD WINAPI
RtlDestroyEnvironment(DWORD x
) {
481 FIXME("(0x%08lx),stub!\n",x
);
485 /******************************************************************************
486 * RtlQueryEnvironmentVariable_U [NTDLL]
488 DWORD WINAPI
RtlQueryEnvironmentVariable_U(DWORD x1
,PUNICODE_STRING key
,PUNICODE_STRING val
) {
489 FIXME("(0x%08lx,%s,%p),stub!\n",x1
,debugstr_w(key
->Buffer
),val
);