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 #define IMAGE_DOS_MAGIC 0x5a4d
18 #define IMAGE_PE_MAGIC 0x00004550
20 /* FUNCTIONS ***************************************************************/
27 RtlWalkFrameChain(OUT PVOID
*Callers
,
31 /* Not implemented for user-mode */
37 RtlpCheckForActiveDebugger(BOOLEAN Type
)
39 return (NtCurrentPeb()->BeingDebugged
);
44 RtlpSetInDbgPrint(IN BOOLEAN NewValue
)
46 /* If we're setting it to false, do it and return */
47 if (NewValue
== FALSE
)
49 NtCurrentTeb()->InDbgPrint
= FALSE
;
53 /* Setting to true; check if it's not already */
54 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
56 /* Set it and return */
57 NtCurrentTeb()->InDbgPrint
= TRUE
;
73 RtlGetCurrentPeb(VOID
)
75 return NtCurrentPeb();
82 RtlAcquirePebLock(VOID
)
84 PPEB Peb
= NtCurrentPeb ();
85 Peb
->FastPebLockRoutine (Peb
->FastPebLock
);
92 RtlReleasePebLock(VOID
)
94 PPEB Peb
= NtCurrentPeb ();
95 Peb
->FastPebUnlockRoutine (Peb
->FastPebLock
);
103 RtlGetNtGlobalFlags(VOID
)
105 PPEB pPeb
= NtCurrentPeb();
106 return pPeb
->NtGlobalFlag
;
112 PRTL_CRITICAL_SECTION CriticalSection
)
114 return RtlDeleteCriticalSection(CriticalSection
);
120 PRTL_CRITICAL_SECTION CriticalSection
)
122 return RtlEnterCriticalSection(CriticalSection
);
127 RtlInitializeHeapLock(
128 PRTL_CRITICAL_SECTION CriticalSection
)
130 return RtlInitializeCriticalSection(CriticalSection
);
136 PRTL_CRITICAL_SECTION CriticalSection
)
138 return RtlLeaveCriticalSection(CriticalSection
);
143 RtlpAllocateMemory(UINT Bytes
,
146 UNREFERENCED_PARAMETER(Tag
);
148 return RtlAllocateHeap(RtlGetProcessHeap(),
156 RtlpFreeMemory(PVOID Mem
,
159 UNREFERENCED_PARAMETER(Tag
);
161 RtlFreeHeap(RtlGetProcessHeap(),
169 CHECK_PAGED_CODE_RTL(char *file
, int line
)
171 /* meaningless in user mode */
177 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
178 IN ULONG_PTR RegistrationFrameEnd
,
179 IN OUT PULONG_PTR StackLow
,
180 IN OUT PULONG_PTR StackHigh
)
182 /* There's no such thing as a DPC stack in user-mode */
188 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
189 IN PCONTEXT ContextRecord
,
190 IN PVOID ContextData
,
193 /* Exception logging is not done in user-mode */
198 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
199 IN ULONG_PTR
*StackBegin
,
200 IN ULONG_PTR
*StackEnd
)
203 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
204 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
212 OUT PULONG_PTR LowLimit
,
213 OUT PULONG_PTR HighLimit
)
215 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
216 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
221 /* RTL Atom Tables ************************************************************/
223 typedef struct _RTL_ATOM_HANDLE
225 RTL_HANDLE_TABLE_ENTRY Handle
;
226 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
227 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
230 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
232 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
233 return STATUS_SUCCESS
;
238 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
240 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
245 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
247 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
253 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
255 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
259 /* handle functions */
262 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
264 RtlInitializeHandleTable(0xCFFF,
265 sizeof(RTL_ATOM_HANDLE
),
266 &AtomTable
->RtlHandleTable
);
272 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
274 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
278 RtlpAllocAtomTable(ULONG Size
)
280 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
286 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
288 RtlFreeHeap(RtlGetProcessHeap(),
293 PRTL_ATOM_TABLE_ENTRY
294 RtlpAllocAtomTableEntry(ULONG Size
)
296 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
302 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
304 RtlFreeHeap(RtlGetProcessHeap(),
310 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
312 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
314 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
315 (ULONG
)Entry
->HandleIndex
,
318 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
324 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
327 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
329 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
331 if (RtlHandle
!= NULL
)
333 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
335 /* FIXME - Handle Indexes >= 0xC000 ?! */
336 if (HandleIndex
< 0xC000)
338 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
339 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
341 AtomHandle
->AtomEntry
= Entry
;
342 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
348 /* set the valid flag, otherwise RtlFreeHandle will fail! */
349 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
351 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
359 PRTL_ATOM_TABLE_ENTRY
360 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
362 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
364 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
368 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
370 return AtomHandle
->AtomEntry
;
378 RtlpLookupModuleBase(
382 MEMORY_BASIC_INFORMATION MemoryInformation
;
383 ULONG_PTR Base
, Limit
;
384 PIMAGE_DOS_HEADER DosHeader
;
385 PIMAGE_NT_HEADERS NtHeader
;
387 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
389 MemoryBasicInformation
,
391 sizeof(MEMORY_BASIC_INFORMATION
),
393 if (!NT_SUCCESS(Status
))
398 /* FIXME: remove these checks? */
399 Base
= (ULONG_PTR
)MemoryInformation
.BaseAddress
;
400 Limit
= Base
+ MemoryInformation
.RegionSize
;
401 if ( ((ULONG_PTR
)Address
< Base
) ||
402 ((ULONG_PTR
)Address
>= Limit
) )
408 /* Check if we got the right kind of memory */
409 if ( (MemoryInformation
.State
!= MEM_COMMIT
) ||
410 (MemoryInformation
.Type
!= MEM_IMAGE
) )
415 /* Check DOS magic */
416 DosHeader
= MemoryInformation
.AllocationBase
;
417 if (DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
422 /* Check NT header */
423 NtHeader
= (PVOID
)((ULONG_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
424 if (NtHeader
->Signature
!= IMAGE_PE_MAGIC
)
429 return MemoryInformation
.AllocationBase
;
434 * Ldr Resource support code
437 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
438 LPCWSTR name
, void *root
,
440 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
441 WORD id
, void *root
, int want_dir
);
442 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
443 void *root
, int want_dir
);
444 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
446 /**********************************************************************
449 * Find a resource entry
451 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
452 ULONG level
, void **ret
, int want_dir
)
456 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
457 USHORT list
[9]; /* list of languages to try */
459 LCID user_lcid
, system_lcid
;
461 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
462 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
465 if (!level
--) goto done
;
466 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
467 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
468 if (!level
--) return STATUS_SUCCESS
;
471 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
472 return STATUS_RESOURCE_NAME_NOT_FOUND
;
473 if (!level
--) return STATUS_SUCCESS
;
474 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
476 /* 1. specified language */
477 pos
= push_language( list
, pos
, info
->Language
);
479 /* 2. specified language with neutral sublanguage */
480 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
482 /* 3. neutral language with neutral sublanguage */
483 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
485 /* if no explicitly specified language, try some defaults */
486 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
488 /* user defaults, unless SYS_DEFAULT sublanguage specified */
489 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
491 /* 4. current thread locale language */
492 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
494 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
496 /* 5. user locale language */
497 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
499 /* 6. user locale language with neutral sublanguage */
500 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
504 /* now system defaults */
506 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
508 /* 7. system locale language */
509 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
511 /* 8. system locale language with neutral sublanguage */
512 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
516 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
520 for (i
= 0; i
< pos
; i
++)
521 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
523 /* if no explicitly specified language, return the first entry */
524 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
526 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
528 return STATUS_RESOURCE_LANG_NOT_FOUND
;
532 return STATUS_SUCCESS
;