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(BOOLEAN Type
)
38 return (NtCurrentPeb()->BeingDebugged
);
43 RtlpSetInDbgPrint(IN BOOLEAN NewValue
)
45 /* If we're setting it to false, do it and return */
46 if (NewValue
== FALSE
)
48 NtCurrentTeb()->InDbgPrint
= FALSE
;
52 /* Setting to true; check if it's not already */
53 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
55 /* Set it and return */
56 NtCurrentTeb()->InDbgPrint
= TRUE
;
72 RtlGetCurrentPeb(VOID
)
74 return NtCurrentPeb();
81 RtlAcquirePebLock(VOID
)
83 PPEB Peb
= NtCurrentPeb ();
84 Peb
->FastPebLockRoutine (Peb
->FastPebLock
);
91 RtlReleasePebLock(VOID
)
93 PPEB Peb
= NtCurrentPeb ();
94 Peb
->FastPebUnlockRoutine (Peb
->FastPebLock
);
102 RtlGetNtGlobalFlags(VOID
)
104 PPEB pPeb
= NtCurrentPeb();
105 return pPeb
->NtGlobalFlag
;
111 PRTL_CRITICAL_SECTION CriticalSection
)
113 return RtlDeleteCriticalSection(CriticalSection
);
119 PRTL_CRITICAL_SECTION CriticalSection
)
121 return RtlEnterCriticalSection(CriticalSection
);
126 RtlInitializeHeapLock(
127 PRTL_CRITICAL_SECTION CriticalSection
)
129 return RtlInitializeCriticalSection(CriticalSection
);
135 PRTL_CRITICAL_SECTION CriticalSection
)
137 return RtlLeaveCriticalSection(CriticalSection
);
142 RtlpAllocateMemory(UINT Bytes
,
145 UNREFERENCED_PARAMETER(Tag
);
147 return RtlAllocateHeap(RtlGetProcessHeap(),
155 RtlpFreeMemory(PVOID Mem
,
158 UNREFERENCED_PARAMETER(Tag
);
160 RtlFreeHeap(RtlGetProcessHeap(),
168 CHECK_PAGED_CODE_RTL(char *file
, int line
)
170 /* meaningless in user mode */
176 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
177 IN ULONG_PTR RegistrationFrameEnd
,
178 IN OUT PULONG_PTR StackLow
,
179 IN OUT PULONG_PTR StackHigh
)
181 /* There's no such thing as a DPC stack in user-mode */
187 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
188 IN PCONTEXT ContextRecord
,
189 IN PVOID ContextData
,
192 /* Exception logging is not done in user-mode */
197 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
198 IN ULONG_PTR
*StackBegin
,
199 IN ULONG_PTR
*StackEnd
)
202 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
203 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
209 RtlIsThreadWithinLoaderCallout(VOID
)
211 return LdrpTopLevelDllBeingLoadedTeb
== NtCurrentTeb();
214 /* RTL Atom Tables ************************************************************/
216 typedef struct _RTL_ATOM_HANDLE
218 RTL_HANDLE_TABLE_ENTRY Handle
;
219 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
220 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
223 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
225 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
226 return STATUS_SUCCESS
;
231 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
233 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
238 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
240 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
246 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
248 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
252 /* handle functions */
255 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
257 RtlInitializeHandleTable(0xCFFF,
258 sizeof(RTL_ATOM_HANDLE
),
259 &AtomTable
->RtlHandleTable
);
265 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
267 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
271 RtlpAllocAtomTable(ULONG Size
)
273 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
279 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
281 RtlFreeHeap(RtlGetProcessHeap(),
286 PRTL_ATOM_TABLE_ENTRY
287 RtlpAllocAtomTableEntry(ULONG Size
)
289 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
295 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
297 RtlFreeHeap(RtlGetProcessHeap(),
303 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
305 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
307 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
308 (ULONG
)Entry
->HandleIndex
,
311 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
317 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
320 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
322 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
324 if (RtlHandle
!= NULL
)
326 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
328 /* FIXME - Handle Indexes >= 0xC000 ?! */
329 if (HandleIndex
< 0xC000)
331 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
332 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
334 AtomHandle
->AtomEntry
= Entry
;
335 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
341 /* set the valid flag, otherwise RtlFreeHandle will fail! */
342 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
344 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
352 PRTL_ATOM_TABLE_ENTRY
353 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
355 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
357 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
361 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
363 return AtomHandle
->AtomEntry
;
371 * Ldr Resource support code
374 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
375 LPCWSTR name
, void *root
,
377 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
378 WORD id
, void *root
, int want_dir
);
379 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
380 void *root
, int want_dir
);
381 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
383 /**********************************************************************
386 * Find a resource entry
388 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
389 ULONG level
, void **ret
, int want_dir
)
393 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
394 USHORT list
[9]; /* list of languages to try */
396 LCID user_lcid
, system_lcid
;
398 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
399 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
402 if (!level
--) goto done
;
403 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
404 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
405 if (!level
--) return STATUS_SUCCESS
;
408 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
409 return STATUS_RESOURCE_NAME_NOT_FOUND
;
410 if (!level
--) return STATUS_SUCCESS
;
411 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
413 /* 1. specified language */
414 pos
= push_language( list
, pos
, info
->Language
);
416 /* 2. specified language with neutral sublanguage */
417 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
419 /* 3. neutral language with neutral sublanguage */
420 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
422 /* if no explicitly specified language, try some defaults */
423 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
425 /* user defaults, unless SYS_DEFAULT sublanguage specified */
426 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
428 /* 4. current thread locale language */
429 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
431 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
433 /* 5. user locale language */
434 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
436 /* 6. user locale language with neutral sublanguage */
437 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
441 /* now system defaults */
443 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
445 /* 7. system locale language */
446 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
448 /* 8. system locale language with neutral sublanguage */
449 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
453 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
457 for (i
= 0; i
< pos
; i
++)
458 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
460 /* if no explicitly specified language, return the first entry */
461 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
463 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
465 return STATUS_RESOURCE_LANG_NOT_FOUND
;
469 return STATUS_SUCCESS
;