2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NT User-Mode DLL
4 * FILE: lib/ntdll/rtl/libsup.c
5 * PURPOSE: RTL Support Routines
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
17 SIZE_T RtlpAllocDeallocQueryBufferSize
= PAGE_SIZE
;
18 PTEB LdrpTopLevelDllBeingLoadedTeb
= NULL
;
19 PVOID MmHighestUserAddress
= (PVOID
)MI_HIGHEST_USER_ADDRESS
;
21 /* FUNCTIONS ***************************************************************/
24 // FIXME: Why "Not implemented"???
30 RtlWalkFrameChain(OUT PVOID
*Callers
,
34 /* Not implemented for user-mode */
41 RtlpCheckForActiveDebugger(VOID
)
43 /* Return the flag in the PEB */
44 return NtCurrentPeb()->BeingDebugged
;
49 RtlpSetInDbgPrint(VOID
)
51 /* Check if it's already set and return TRUE if so */
52 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
54 /* Set it and return */
55 NtCurrentTeb()->InDbgPrint
= TRUE
;
61 RtlpClearInDbgPrint(VOID
)
64 NtCurrentTeb()->InDbgPrint
= FALSE
;
79 RtlGetCurrentPeb(VOID
)
81 return NtCurrentPeb();
88 RtlAcquirePebLock(VOID
)
90 PPEB Peb
= NtCurrentPeb ();
91 RtlEnterCriticalSection(Peb
->FastPebLock
);
98 RtlReleasePebLock(VOID
)
100 PPEB Peb
= NtCurrentPeb ();
101 RtlLeaveCriticalSection(Peb
->FastPebLock
);
109 RtlGetNtGlobalFlags(VOID
)
111 PPEB pPeb
= NtCurrentPeb();
112 return pPeb
->NtGlobalFlag
;
117 RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock
)
119 return RtlDeleteCriticalSection(&Lock
->CriticalSection
);
124 RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock
, IN BOOLEAN Exclusive
)
126 UNREFERENCED_PARAMETER(Exclusive
);
128 return RtlEnterCriticalSection(&Lock
->CriticalSection
);
133 RtlTryEnterHeapLock(IN OUT PHEAP_LOCK Lock
, IN BOOLEAN Exclusive
)
135 UNREFERENCED_PARAMETER(Exclusive
);
137 return RtlTryEnterCriticalSection(&Lock
->CriticalSection
);
142 RtlInitializeHeapLock(IN OUT PHEAP_LOCK
*Lock
)
144 return RtlInitializeCriticalSection(&(*Lock
)->CriticalSection
);
149 RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock
)
151 return RtlLeaveCriticalSection(&Lock
->CriticalSection
);
156 RtlpAllocateMemory(UINT Bytes
,
159 UNREFERENCED_PARAMETER(Tag
);
161 return RtlAllocateHeap(RtlGetProcessHeap(),
169 RtlpFreeMemory(PVOID Mem
,
172 UNREFERENCED_PARAMETER(Tag
);
174 RtlFreeHeap(RtlGetProcessHeap(),
182 CHECK_PAGED_CODE_RTL(char *file
, int line
)
184 /* meaningless in user mode */
190 RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters
)
195 Peb
= RtlGetCurrentPeb();
197 /* Apply defaults for non-set parameters */
198 if (!Parameters
->SegmentCommit
) Parameters
->SegmentCommit
= Peb
->HeapSegmentCommit
;
199 if (!Parameters
->SegmentReserve
) Parameters
->SegmentReserve
= Peb
->HeapSegmentReserve
;
200 if (!Parameters
->DeCommitFreeBlockThreshold
) Parameters
->DeCommitFreeBlockThreshold
= Peb
->HeapDeCommitFreeBlockThreshold
;
201 if (!Parameters
->DeCommitTotalFreeThreshold
) Parameters
->DeCommitTotalFreeThreshold
= Peb
->HeapDeCommitTotalFreeThreshold
;
206 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
207 IN ULONG_PTR RegistrationFrameEnd
,
208 IN OUT PULONG_PTR StackLow
,
209 IN OUT PULONG_PTR StackHigh
)
211 /* There's no such thing as a DPC stack in user-mode */
217 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
218 IN PCONTEXT ContextRecord
,
219 IN PVOID ContextData
,
222 /* Exception logging is not done in user-mode */
227 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
228 IN ULONG_PTR
*StackBegin
,
229 IN ULONG_PTR
*StackEnd
)
232 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
233 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
241 OUT PULONG_PTR LowLimit
,
242 OUT PULONG_PTR HighLimit
)
244 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
245 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
252 RtlIsThreadWithinLoaderCallout(VOID
)
254 return LdrpTopLevelDllBeingLoadedTeb
== NtCurrentTeb();
257 /* RTL Atom Tables ************************************************************/
259 typedef struct _RTL_ATOM_HANDLE
261 RTL_HANDLE_TABLE_ENTRY Handle
;
262 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
263 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
266 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
268 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
269 return STATUS_SUCCESS
;
274 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
276 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
281 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
283 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
289 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
291 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
295 /* handle functions */
298 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
300 RtlInitializeHandleTable(0xCFFF,
301 sizeof(RTL_ATOM_HANDLE
),
302 &AtomTable
->RtlHandleTable
);
308 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
310 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
314 RtlpAllocAtomTable(ULONG Size
)
316 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
322 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
324 RtlFreeHeap(RtlGetProcessHeap(),
329 PRTL_ATOM_TABLE_ENTRY
330 RtlpAllocAtomTableEntry(ULONG Size
)
332 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
338 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
340 RtlFreeHeap(RtlGetProcessHeap(),
346 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
348 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
350 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
351 (ULONG
)Entry
->HandleIndex
,
354 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
360 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
363 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
365 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
367 if (RtlHandle
!= NULL
)
369 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
371 /* FIXME - Handle Indexes >= 0xC000 ?! */
372 if (HandleIndex
< 0xC000)
374 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
375 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
377 AtomHandle
->AtomEntry
= Entry
;
378 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
384 /* set the valid flag, otherwise RtlFreeHandle will fail! */
385 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
387 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
395 PRTL_ATOM_TABLE_ENTRY
396 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
398 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
400 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
404 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
406 return AtomHandle
->AtomEntry
;
414 * Ldr Resource support code
417 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
418 LPCWSTR name
, void *root
,
420 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
421 WORD id
, void *root
, int want_dir
);
422 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
423 void *root
, int want_dir
);
424 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
426 /**********************************************************************
429 * Find a resource entry
431 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
432 ULONG level
, void **ret
, int want_dir
)
436 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
437 USHORT list
[9]; /* list of languages to try */
439 LCID user_lcid
, system_lcid
;
441 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
442 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
443 if (size
< sizeof(*resdirptr
)) return STATUS_RESOURCE_DATA_NOT_FOUND
;
446 if (!level
--) goto done
;
447 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
448 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
449 if (!level
--) return STATUS_SUCCESS
;
452 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
453 return STATUS_RESOURCE_NAME_NOT_FOUND
;
454 if (!level
--) return STATUS_SUCCESS
;
455 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
457 /* 1. specified language */
458 pos
= push_language( list
, pos
, info
->Language
);
460 /* 2. specified language with neutral sublanguage */
461 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
463 /* 3. neutral language with neutral sublanguage */
464 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
466 /* if no explicitly specified language, try some defaults */
467 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
469 /* user defaults, unless SYS_DEFAULT sublanguage specified */
470 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
472 /* 4. current thread locale language */
473 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
475 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
477 /* 5. user locale language */
478 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
480 /* 6. user locale language with neutral sublanguage */
481 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
485 /* now system defaults */
487 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
489 /* 7. system locale language */
490 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
492 /* 8. system locale language with neutral sublanguage */
493 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
497 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
501 for (i
= 0; i
< pos
; i
++)
502 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
504 /* if no explicitly specified language, return the first entry */
505 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
507 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
509 return STATUS_RESOURCE_LANG_NOT_FOUND
;
513 return STATUS_SUCCESS
;
520 RtlPcToFileHeader(IN PVOID PcValue
,
523 PLIST_ENTRY ModuleListHead
;
525 PLDR_DATA_TABLE_ENTRY Module
;
526 PVOID ImageBase
= NULL
;
528 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
529 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
530 Entry
= ModuleListHead
->Flink
;
531 while (Entry
!= ModuleListHead
)
533 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
535 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
536 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
538 ImageBase
= Module
->DllBase
;
541 Entry
= Entry
->Flink
;
543 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
545 *BaseOfImage
= ImageBase
;
555 RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags
,
556 IN PUNICODE_STRING OriginalName
,
557 IN PUNICODE_STRING Extension
,
558 IN OUT PUNICODE_STRING StaticString
,
559 IN OUT PUNICODE_STRING DynamicString
,
560 IN OUT PUNICODE_STRING
*NewName
,
562 IN PSIZE_T FileNameSize
,
563 IN PSIZE_T RequiredLength
)
565 return STATUS_SXS_KEY_NOT_FOUND
;
574 RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection
)
576 /* This is what Windows returns on x86 */
577 return STATUS_NOT_IMPLEMENTED
;
586 RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection
,
587 OUT PVOID
*OldFsRedirectionLevel
)
589 /* This is what Windows returns on x86 */
590 return STATUS_NOT_IMPLEMENTED
;
599 RtlComputeImportTableHash(IN HANDLE FileHandle
,
601 IN ULONG ImportTableHashSize
)
604 return STATUS_NOT_IMPLEMENTED
;
610 _Out_writes_bytes_all_(Length
) VOID UNALIGNED
*Destination
,
611 _In_reads_bytes_(Length
) CONST VOID UNALIGNED
*Source
,
616 RtlCopyMemory(Destination
, Source
, Length
);
618 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
620 _SEH2_YIELD(return _SEH2_GetExceptionCode());
624 return STATUS_SUCCESS
;
627 /* FIXME: code duplication with kernel32/client/time.c */
630 RtlGetTickCount(VOID
)
632 ULARGE_INTEGER TickCount
;
635 TickCount
.QuadPart
= *((volatile ULONG64
*)&SharedUserData
->TickCount
);
639 TickCount
.HighPart
= (ULONG
)SharedUserData
->TickCount
.High1Time
;
640 TickCount
.LowPart
= SharedUserData
->TickCount
.LowPart
;
642 if (TickCount
.HighPart
== (ULONG
)SharedUserData
->TickCount
.High2Time
)
649 return (ULONG
)((UInt32x32To64(TickCount
.LowPart
,
650 SharedUserData
->TickCountMultiplier
) >> 24) +
651 UInt32x32To64((TickCount
.HighPart
<< 8) & 0xFFFFFFFF,
652 SharedUserData
->TickCountMultiplier
));