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 /* FUNCTIONS ***************************************************************/
23 RtlWalkFrameChain(OUT PVOID
*Callers
,
27 /* Not implemented for user-mode */
33 RtlpCheckForActiveDebugger(BOOLEAN Type
)
35 return (NtCurrentPeb()->BeingDebugged
);
40 RtlpSetInDbgPrint(IN BOOLEAN NewValue
)
42 /* If we're setting it to false, do it and return */
43 if (NewValue
== FALSE
)
45 NtCurrentTeb()->InDbgPrint
= FALSE
;
49 /* Setting to true; check if it's not already */
50 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
52 /* Set it and return */
53 NtCurrentTeb()->InDbgPrint
= TRUE
;
68 return NtCurrentPeb();
75 RtlAcquirePebLock(VOID
)
77 PPEB Peb
= NtCurrentPeb ();
78 Peb
->FastPebLockRoutine (Peb
->FastPebLock
);
85 RtlReleasePebLock(VOID
)
87 PPEB Peb
= NtCurrentPeb ();
88 Peb
->FastPebUnlockRoutine (Peb
->FastPebLock
);
96 RtlGetNtGlobalFlags(VOID
)
98 PPEB pPeb
= NtCurrentPeb();
99 return pPeb
->NtGlobalFlag
;
105 PRTL_CRITICAL_SECTION CriticalSection
)
107 return RtlDeleteCriticalSection(CriticalSection
);
113 PRTL_CRITICAL_SECTION CriticalSection
)
115 return RtlEnterCriticalSection(CriticalSection
);
120 RtlInitializeHeapLock(
121 PRTL_CRITICAL_SECTION CriticalSection
)
123 return RtlInitializeCriticalSection(CriticalSection
);
129 PRTL_CRITICAL_SECTION CriticalSection
)
131 return RtlLeaveCriticalSection(CriticalSection
);
136 RtlpAllocateMemory(UINT Bytes
,
139 UNREFERENCED_PARAMETER(Tag
);
141 return RtlAllocateHeap(RtlGetProcessHeap(),
149 RtlpFreeMemory(PVOID Mem
,
152 UNREFERENCED_PARAMETER(Tag
);
154 RtlFreeHeap(RtlGetProcessHeap(),
162 CHECK_PAGED_CODE_RTL(char *file
, int line
)
164 /* meaningless in user mode */
170 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
171 IN ULONG_PTR RegistrationFrameEnd
,
172 IN OUT PULONG_PTR StackLow
,
173 IN OUT PULONG_PTR StackHigh
)
175 /* There's no such thing as a DPC stack in user-mode */
181 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
182 IN PCONTEXT ContextRecord
,
183 IN PVOID ContextData
,
186 /* Exception logging is not done in user-mode */
191 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
192 IN ULONG_PTR
*StackBegin
,
193 IN ULONG_PTR
*StackEnd
)
196 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
197 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
201 /* RTL Atom Tables ************************************************************/
203 typedef struct _RTL_ATOM_HANDLE
205 RTL_HANDLE_TABLE_ENTRY Handle
;
206 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
207 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
210 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
212 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
213 return STATUS_SUCCESS
;
218 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
220 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
225 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
227 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
233 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
235 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
239 /* handle functions */
242 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
244 RtlInitializeHandleTable(0xCFFF,
245 sizeof(RTL_ATOM_HANDLE
),
246 &AtomTable
->RtlHandleTable
);
252 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
254 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
258 RtlpAllocAtomTable(ULONG Size
)
260 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
266 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
268 RtlFreeHeap(RtlGetProcessHeap(),
273 PRTL_ATOM_TABLE_ENTRY
274 RtlpAllocAtomTableEntry(ULONG Size
)
276 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
282 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
284 RtlFreeHeap(RtlGetProcessHeap(),
290 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
292 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
294 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
295 (ULONG
)Entry
->HandleIndex
,
298 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
304 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
307 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
309 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
311 if (RtlHandle
!= NULL
)
313 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
315 /* FIXME - Handle Indexes >= 0xC000 ?! */
316 if (HandleIndex
< 0xC000)
318 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
319 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
321 AtomHandle
->AtomEntry
= Entry
;
322 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
328 /* set the valid flag, otherwise RtlFreeHandle will fail! */
329 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
331 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
339 PRTL_ATOM_TABLE_ENTRY
340 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
342 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
344 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
348 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
350 return AtomHandle
->AtomEntry
;
358 * Ldr Resource support code
361 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
362 LPCWSTR name
, void *root
,
364 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
365 WORD id
, void *root
, int want_dir
);
366 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
367 void *root
, int want_dir
);
368 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
370 /**********************************************************************
373 * Find a resource entry
375 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
376 ULONG level
, void **ret
, int want_dir
)
380 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
381 USHORT list
[9]; /* list of languages to try */
383 LCID user_lcid
, system_lcid
;
385 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
386 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
389 if (!level
--) goto done
;
390 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
391 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
392 if (!level
--) return STATUS_SUCCESS
;
395 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
396 return STATUS_RESOURCE_NAME_NOT_FOUND
;
397 if (!level
--) return STATUS_SUCCESS
;
398 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
400 /* 1. specified language */
401 pos
= push_language( list
, pos
, info
->Language
);
403 /* 2. specified language with neutral sublanguage */
404 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
406 /* 3. neutral language with neutral sublanguage */
407 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
409 /* if no explicitly specified language, try some defaults */
410 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
412 /* user defaults, unless SYS_DEFAULT sublanguage specified */
413 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
415 /* 4. current thread locale language */
416 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
418 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
420 /* 5. user locale language */
421 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
423 /* 6. user locale language with neutral sublanguage */
424 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
428 /* now system defaults */
430 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
432 /* 7. system locale language */
433 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
435 /* 8. system locale language with neutral sublanguage */
436 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
440 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
444 for (i
= 0; i
< pos
; i
++)
445 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
447 /* if no explicitly specified language, return the first entry */
448 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
450 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
452 return STATUS_RESOURCE_LANG_NOT_FOUND
;
456 return STATUS_SUCCESS
;