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 *****************************************************************/
16 SIZE_T RtlpAllocDeallocQueryBufferSize
= PAGE_SIZE
;
17 PTEB LdrpTopLevelDllBeingLoadedTeb
= NULL
;
19 /* FUNCTIONS ***************************************************************/
22 // FIXME: Why "Not implemented"???
28 RtlWalkFrameChain(OUT PVOID
*Callers
,
32 /* Not implemented for user-mode */
39 RtlpCheckForActiveDebugger(VOID
)
41 /* Return the flag in the PEB */
42 return NtCurrentPeb()->BeingDebugged
;
47 RtlpSetInDbgPrint(VOID
)
49 /* Check if it's already set and return TRUE if so */
50 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
52 /* Set it and return */
53 NtCurrentTeb()->InDbgPrint
= TRUE
;
59 RtlpClearInDbgPrint(VOID
)
62 NtCurrentTeb()->InDbgPrint
= FALSE
;
77 RtlGetCurrentPeb(VOID
)
79 return NtCurrentPeb();
86 RtlAcquirePebLock(VOID
)
88 PPEB Peb
= NtCurrentPeb ();
89 RtlEnterCriticalSection(Peb
->FastPebLock
);
96 RtlReleasePebLock(VOID
)
98 PPEB Peb
= NtCurrentPeb ();
99 RtlLeaveCriticalSection(Peb
->FastPebLock
);
107 RtlGetNtGlobalFlags(VOID
)
109 PPEB pPeb
= NtCurrentPeb();
110 return pPeb
->NtGlobalFlag
;
115 RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock
)
117 return RtlDeleteCriticalSection(&Lock
->CriticalSection
);
122 RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock
, IN BOOLEAN Exclusive
)
124 UNREFERENCED_PARAMETER(Exclusive
);
126 return RtlEnterCriticalSection(&Lock
->CriticalSection
);
131 RtlInitializeHeapLock(IN OUT PHEAP_LOCK
*Lock
)
133 return RtlInitializeCriticalSection(&(*Lock
)->CriticalSection
);
138 RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock
)
140 return RtlLeaveCriticalSection(&Lock
->CriticalSection
);
145 RtlpAllocateMemory(UINT Bytes
,
148 UNREFERENCED_PARAMETER(Tag
);
150 return RtlAllocateHeap(RtlGetProcessHeap(),
158 RtlpFreeMemory(PVOID Mem
,
161 UNREFERENCED_PARAMETER(Tag
);
163 RtlFreeHeap(RtlGetProcessHeap(),
171 CHECK_PAGED_CODE_RTL(char *file
, int line
)
173 /* meaningless in user mode */
179 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
180 IN ULONG_PTR RegistrationFrameEnd
,
181 IN OUT PULONG_PTR StackLow
,
182 IN OUT PULONG_PTR StackHigh
)
184 /* There's no such thing as a DPC stack in user-mode */
190 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
191 IN PCONTEXT ContextRecord
,
192 IN PVOID ContextData
,
195 /* Exception logging is not done in user-mode */
200 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
201 IN ULONG_PTR
*StackBegin
,
202 IN ULONG_PTR
*StackEnd
)
205 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
206 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
214 OUT PULONG_PTR LowLimit
,
215 OUT PULONG_PTR HighLimit
)
217 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
218 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
225 RtlIsThreadWithinLoaderCallout(VOID
)
227 return LdrpTopLevelDllBeingLoadedTeb
== NtCurrentTeb();
230 /* RTL Atom Tables ************************************************************/
232 typedef struct _RTL_ATOM_HANDLE
234 RTL_HANDLE_TABLE_ENTRY Handle
;
235 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
236 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
239 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
241 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
242 return STATUS_SUCCESS
;
247 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
249 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
254 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
256 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
262 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
264 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
268 /* handle functions */
271 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
273 RtlInitializeHandleTable(0xCFFF,
274 sizeof(RTL_ATOM_HANDLE
),
275 &AtomTable
->RtlHandleTable
);
281 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
283 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
287 RtlpAllocAtomTable(ULONG Size
)
289 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
295 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
297 RtlFreeHeap(RtlGetProcessHeap(),
302 PRTL_ATOM_TABLE_ENTRY
303 RtlpAllocAtomTableEntry(ULONG Size
)
305 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
311 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
313 RtlFreeHeap(RtlGetProcessHeap(),
319 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
321 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
323 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
324 (ULONG
)Entry
->HandleIndex
,
327 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
333 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
336 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
338 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
340 if (RtlHandle
!= NULL
)
342 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
344 /* FIXME - Handle Indexes >= 0xC000 ?! */
345 if (HandleIndex
< 0xC000)
347 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
348 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
350 AtomHandle
->AtomEntry
= Entry
;
351 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
357 /* set the valid flag, otherwise RtlFreeHandle will fail! */
358 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
360 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
368 PRTL_ATOM_TABLE_ENTRY
369 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
371 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
373 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
377 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
379 return AtomHandle
->AtomEntry
;
387 * Ldr Resource support code
390 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
391 LPCWSTR name
, void *root
,
393 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
394 WORD id
, void *root
, int want_dir
);
395 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
396 void *root
, int want_dir
);
397 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
399 /**********************************************************************
402 * Find a resource entry
404 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
405 ULONG level
, void **ret
, int want_dir
)
409 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
410 USHORT list
[9]; /* list of languages to try */
412 LCID user_lcid
, system_lcid
;
414 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
415 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
418 if (!level
--) goto done
;
419 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
420 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
421 if (!level
--) return STATUS_SUCCESS
;
424 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
425 return STATUS_RESOURCE_NAME_NOT_FOUND
;
426 if (!level
--) return STATUS_SUCCESS
;
427 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
429 /* 1. specified language */
430 pos
= push_language( list
, pos
, info
->Language
);
432 /* 2. specified language with neutral sublanguage */
433 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
435 /* 3. neutral language with neutral sublanguage */
436 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
438 /* if no explicitly specified language, try some defaults */
439 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
441 /* user defaults, unless SYS_DEFAULT sublanguage specified */
442 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
444 /* 4. current thread locale language */
445 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
447 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
449 /* 5. user locale language */
450 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
452 /* 6. user locale language with neutral sublanguage */
453 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
457 /* now system defaults */
459 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
461 /* 7. system locale language */
462 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
464 /* 8. system locale language with neutral sublanguage */
465 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
469 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
473 for (i
= 0; i
< pos
; i
++)
474 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
476 /* if no explicitly specified language, return the first entry */
477 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
479 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
481 return STATUS_RESOURCE_LANG_NOT_FOUND
;
485 return STATUS_SUCCESS
;
492 RtlPcToFileHeader(IN PVOID PcValue
,
495 PLIST_ENTRY ModuleListHead
;
497 PLDR_DATA_TABLE_ENTRY Module
;
498 PVOID ImageBase
= NULL
;
500 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
501 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
502 Entry
= ModuleListHead
->Flink
;
503 while (Entry
!= ModuleListHead
)
505 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
507 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
508 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
510 ImageBase
= Module
->DllBase
;
513 Entry
= Entry
->Flink
;
515 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
517 *BaseOfImage
= ImageBase
;
527 RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags
,
528 IN PUNICODE_STRING OriginalName
,
529 IN PUNICODE_STRING Extension
,
530 IN OUT PUNICODE_STRING StaticString
,
531 IN OUT PUNICODE_STRING DynamicString
,
532 IN OUT PUNICODE_STRING
*NewName
,
534 IN PSIZE_T FileNameSize
,
535 IN PSIZE_T RequiredLength
)
537 return STATUS_SXS_KEY_NOT_FOUND
;
546 RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection
)
548 /* This is what Windows returns on x86 */
549 return STATUS_NOT_IMPLEMENTED
;
558 RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection
,
559 OUT PVOID
*OldFsRedirectionLevel
)
561 /* This is what Windows returns on x86 */
562 return STATUS_NOT_IMPLEMENTED
;
571 RtlComputeImportTableHash(IN HANDLE FileHandle
,
573 IN ULONG ImporTTableHashSize
)
576 return STATUS_NOT_IMPLEMENTED
;