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 ***************************************************************/
26 RtlWalkFrameChain(OUT PVOID
*Callers
,
30 /* Not implemented for user-mode */
36 RtlpCheckForActiveDebugger(VOID
)
38 /* Return the flag in the PEB */
39 return NtCurrentPeb()->BeingDebugged
;
44 RtlpSetInDbgPrint(VOID
)
46 /* Check if it's already set and return TRUE if so */
47 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
49 /* Set it and return */
50 NtCurrentTeb()->InDbgPrint
= TRUE
;
56 RtlpClearInDbgPrint(VOID
)
59 NtCurrentTeb()->InDbgPrint
= FALSE
;
74 RtlGetCurrentPeb(VOID
)
76 return NtCurrentPeb();
83 RtlAcquirePebLock(VOID
)
85 PPEB Peb
= NtCurrentPeb ();
86 RtlEnterCriticalSection(Peb
->FastPebLock
);
93 RtlReleasePebLock(VOID
)
95 PPEB Peb
= NtCurrentPeb ();
96 RtlLeaveCriticalSection(Peb
->FastPebLock
);
104 RtlGetNtGlobalFlags(VOID
)
106 PPEB pPeb
= NtCurrentPeb();
107 return pPeb
->NtGlobalFlag
;
113 PRTL_CRITICAL_SECTION CriticalSection
)
115 return RtlDeleteCriticalSection(CriticalSection
);
121 PRTL_CRITICAL_SECTION CriticalSection
)
123 return RtlEnterCriticalSection(CriticalSection
);
128 RtlInitializeHeapLock(
129 PRTL_CRITICAL_SECTION CriticalSection
)
131 return RtlInitializeCriticalSection(CriticalSection
);
137 PRTL_CRITICAL_SECTION CriticalSection
)
139 return RtlLeaveCriticalSection(CriticalSection
);
144 RtlpAllocateMemory(UINT Bytes
,
147 UNREFERENCED_PARAMETER(Tag
);
149 return RtlAllocateHeap(RtlGetProcessHeap(),
157 RtlpFreeMemory(PVOID Mem
,
160 UNREFERENCED_PARAMETER(Tag
);
162 RtlFreeHeap(RtlGetProcessHeap(),
170 CHECK_PAGED_CODE_RTL(char *file
, int line
)
172 /* meaningless in user mode */
178 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
179 IN ULONG_PTR RegistrationFrameEnd
,
180 IN OUT PULONG_PTR StackLow
,
181 IN OUT PULONG_PTR StackHigh
)
183 /* There's no such thing as a DPC stack in user-mode */
189 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
190 IN PCONTEXT ContextRecord
,
191 IN PVOID ContextData
,
194 /* Exception logging is not done in user-mode */
199 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
200 IN ULONG_PTR
*StackBegin
,
201 IN ULONG_PTR
*StackEnd
)
204 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
205 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
213 OUT PULONG_PTR LowLimit
,
214 OUT PULONG_PTR HighLimit
)
216 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
217 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackBase
;
224 RtlIsThreadWithinLoaderCallout(VOID
)
226 return LdrpTopLevelDllBeingLoadedTeb
== NtCurrentTeb();
229 /* RTL Atom Tables ************************************************************/
231 typedef struct _RTL_ATOM_HANDLE
233 RTL_HANDLE_TABLE_ENTRY Handle
;
234 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
235 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
238 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
240 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
241 return STATUS_SUCCESS
;
246 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
248 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
253 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
255 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
261 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
263 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
267 /* handle functions */
270 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
272 RtlInitializeHandleTable(0xCFFF,
273 sizeof(RTL_ATOM_HANDLE
),
274 &AtomTable
->RtlHandleTable
);
280 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
282 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
286 RtlpAllocAtomTable(ULONG Size
)
288 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
294 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
296 RtlFreeHeap(RtlGetProcessHeap(),
301 PRTL_ATOM_TABLE_ENTRY
302 RtlpAllocAtomTableEntry(ULONG Size
)
304 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
310 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
312 RtlFreeHeap(RtlGetProcessHeap(),
318 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
320 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
322 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
323 (ULONG
)Entry
->HandleIndex
,
326 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
332 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
335 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
337 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
339 if (RtlHandle
!= NULL
)
341 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
343 /* FIXME - Handle Indexes >= 0xC000 ?! */
344 if (HandleIndex
< 0xC000)
346 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
347 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
349 AtomHandle
->AtomEntry
= Entry
;
350 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
356 /* set the valid flag, otherwise RtlFreeHandle will fail! */
357 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
359 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
367 PRTL_ATOM_TABLE_ENTRY
368 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
370 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
372 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
376 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
378 return AtomHandle
->AtomEntry
;
386 * Ldr Resource support code
389 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
390 LPCWSTR name
, void *root
,
392 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
393 WORD id
, void *root
, int want_dir
);
394 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
395 void *root
, int want_dir
);
396 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
398 /**********************************************************************
401 * Find a resource entry
403 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
404 ULONG level
, void **ret
, int want_dir
)
408 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
409 USHORT list
[9]; /* list of languages to try */
411 LCID user_lcid
, system_lcid
;
413 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
414 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
417 if (!level
--) goto done
;
418 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
419 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
420 if (!level
--) return STATUS_SUCCESS
;
423 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
424 return STATUS_RESOURCE_NAME_NOT_FOUND
;
425 if (!level
--) return STATUS_SUCCESS
;
426 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
428 /* 1. specified language */
429 pos
= push_language( list
, pos
, info
->Language
);
431 /* 2. specified language with neutral sublanguage */
432 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
434 /* 3. neutral language with neutral sublanguage */
435 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
437 /* if no explicitly specified language, try some defaults */
438 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
440 /* user defaults, unless SYS_DEFAULT sublanguage specified */
441 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
443 /* 4. current thread locale language */
444 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
446 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
448 /* 5. user locale language */
449 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
451 /* 6. user locale language with neutral sublanguage */
452 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
456 /* now system defaults */
458 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
460 /* 7. system locale language */
461 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
463 /* 8. system locale language with neutral sublanguage */
464 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
468 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
472 for (i
= 0; i
< pos
; i
++)
473 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
475 /* if no explicitly specified language, return the first entry */
476 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
478 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
480 return STATUS_RESOURCE_LANG_NOT_FOUND
;
484 return STATUS_SUCCESS
;