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 ***************************************************************/
23 // FIXME: Why "Not implemented"???
29 RtlWalkFrameChain(OUT PVOID
*Callers
,
33 /* Not implemented for user-mode */
40 RtlpCheckForActiveDebugger(BOOLEAN Type
)
42 return (NtCurrentPeb()->BeingDebugged
);
47 RtlpSetInDbgPrint(IN BOOLEAN NewValue
)
49 /* If we're setting it to false, do it and return */
50 if (NewValue
== FALSE
)
52 NtCurrentTeb()->InDbgPrint
= FALSE
;
56 /* Setting to true; check if it's not already */
57 if (NtCurrentTeb()->InDbgPrint
) return TRUE
;
59 /* Set it and return */
60 NtCurrentTeb()->InDbgPrint
= TRUE
;
76 RtlGetCurrentPeb(VOID
)
78 return NtCurrentPeb();
85 RtlAcquirePebLock(VOID
)
87 PPEB Peb
= NtCurrentPeb ();
88 Peb
->FastPebLockRoutine (Peb
->FastPebLock
);
95 RtlReleasePebLock(VOID
)
97 PPEB Peb
= NtCurrentPeb ();
98 Peb
->FastPebUnlockRoutine (Peb
->FastPebLock
);
106 RtlGetNtGlobalFlags(VOID
)
108 PPEB pPeb
= NtCurrentPeb();
109 return pPeb
->NtGlobalFlag
;
115 PRTL_CRITICAL_SECTION CriticalSection
)
117 return RtlDeleteCriticalSection(CriticalSection
);
123 PRTL_CRITICAL_SECTION CriticalSection
)
125 return RtlEnterCriticalSection(CriticalSection
);
130 RtlInitializeHeapLock(
131 PRTL_CRITICAL_SECTION CriticalSection
)
133 return RtlInitializeCriticalSection(CriticalSection
);
139 PRTL_CRITICAL_SECTION CriticalSection
)
141 return RtlLeaveCriticalSection(CriticalSection
);
146 RtlpAllocateMemory(UINT Bytes
,
149 UNREFERENCED_PARAMETER(Tag
);
151 return RtlAllocateHeap(RtlGetProcessHeap(),
159 RtlpFreeMemory(PVOID Mem
,
162 UNREFERENCED_PARAMETER(Tag
);
164 RtlFreeHeap(RtlGetProcessHeap(),
172 CHECK_PAGED_CODE_RTL(char *file
, int line
)
174 /* meaningless in user mode */
180 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
181 IN ULONG_PTR RegistrationFrameEnd
,
182 IN OUT PULONG_PTR StackLow
,
183 IN OUT PULONG_PTR StackHigh
)
185 /* There's no such thing as a DPC stack in user-mode */
191 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
192 IN PCONTEXT ContextRecord
,
193 IN PVOID ContextData
,
196 /* Exception logging is not done in user-mode */
201 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
202 IN ULONG_PTR
*StackBegin
,
203 IN ULONG_PTR
*StackEnd
)
206 *StackBegin
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
207 *StackEnd
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
215 OUT PULONG_PTR LowLimit
,
216 OUT PULONG_PTR HighLimit
)
218 *LowLimit
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackLimit
;
219 *HighLimit
= (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
;
224 /* RTL Atom Tables ************************************************************/
226 typedef struct _RTL_ATOM_HANDLE
228 RTL_HANDLE_TABLE_ENTRY Handle
;
229 PRTL_ATOM_TABLE_ENTRY AtomEntry
;
230 } RTL_ATOM_HANDLE
, *PRTL_ATOM_HANDLE
;
233 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
235 RtlInitializeCriticalSection(&AtomTable
->CriticalSection
);
236 return STATUS_SUCCESS
;
241 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
243 RtlDeleteCriticalSection(&AtomTable
->CriticalSection
);
248 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
250 RtlEnterCriticalSection(&AtomTable
->CriticalSection
);
256 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
258 RtlLeaveCriticalSection(&AtomTable
->CriticalSection
);
262 /* handle functions */
265 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
267 RtlInitializeHandleTable(0xCFFF,
268 sizeof(RTL_ATOM_HANDLE
),
269 &AtomTable
->RtlHandleTable
);
275 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
277 RtlDestroyHandleTable(&AtomTable
->RtlHandleTable
);
281 RtlpAllocAtomTable(ULONG Size
)
283 return (PRTL_ATOM_TABLE
)RtlAllocateHeap(RtlGetProcessHeap(),
289 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
291 RtlFreeHeap(RtlGetProcessHeap(),
296 PRTL_ATOM_TABLE_ENTRY
297 RtlpAllocAtomTableEntry(ULONG Size
)
299 return (PRTL_ATOM_TABLE_ENTRY
)RtlAllocateHeap(RtlGetProcessHeap(),
305 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
307 RtlFreeHeap(RtlGetProcessHeap(),
313 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
315 PRTL_HANDLE_TABLE_ENTRY RtlHandleEntry
;
317 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
318 (ULONG
)Entry
->HandleIndex
,
321 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
327 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
330 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
332 RtlHandle
= RtlAllocateHandle(&AtomTable
->RtlHandleTable
,
334 if (RtlHandle
!= NULL
)
336 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
338 /* FIXME - Handle Indexes >= 0xC000 ?! */
339 if (HandleIndex
< 0xC000)
341 Entry
->HandleIndex
= (USHORT
)HandleIndex
;
342 Entry
->Atom
= 0xC000 + (USHORT
)HandleIndex
;
344 AtomHandle
->AtomEntry
= Entry
;
345 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
351 /* set the valid flag, otherwise RtlFreeHandle will fail! */
352 AtomHandle
->Handle
.Flags
= RTL_HANDLE_VALID
;
354 RtlFreeHandle(&AtomTable
->RtlHandleTable
,
362 PRTL_ATOM_TABLE_ENTRY
363 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
365 PRTL_HANDLE_TABLE_ENTRY RtlHandle
;
367 if (RtlIsValidIndexHandle(&AtomTable
->RtlHandleTable
,
371 PRTL_ATOM_HANDLE AtomHandle
= (PRTL_ATOM_HANDLE
)RtlHandle
;
373 return AtomHandle
->AtomEntry
;
381 RtlpLookupModuleBase(
385 MEMORY_BASIC_INFORMATION MemoryInformation
;
386 ULONG_PTR Base
, Limit
;
387 PIMAGE_DOS_HEADER DosHeader
;
388 PIMAGE_NT_HEADERS NtHeader
;
390 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
392 MemoryBasicInformation
,
394 sizeof(MEMORY_BASIC_INFORMATION
),
396 if (!NT_SUCCESS(Status
))
401 /* FIXME: remove these checks? */
402 Base
= (ULONG_PTR
)MemoryInformation
.BaseAddress
;
403 Limit
= Base
+ MemoryInformation
.RegionSize
;
404 if ( ((ULONG_PTR
)Address
< Base
) ||
405 ((ULONG_PTR
)Address
>= Limit
) )
411 /* Check if we got the right kind of memory */
412 if ( (MemoryInformation
.State
!= MEM_COMMIT
) ||
413 (MemoryInformation
.Type
!= MEM_IMAGE
) )
418 /* Check DOS magic */
419 DosHeader
= MemoryInformation
.AllocationBase
;
420 if (DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
425 /* Check NT header */
426 NtHeader
= (PVOID
)((ULONG_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
427 if (NtHeader
->Signature
!= IMAGE_PE_MAGIC
)
432 return MemoryInformation
.AllocationBase
;
437 * Ldr Resource support code
440 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
441 LPCWSTR name
, void *root
,
443 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
444 WORD id
, void *root
, int want_dir
);
445 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
446 void *root
, int want_dir
);
447 int push_language( USHORT
*list
, ULONG pos
, WORD lang
);
449 /**********************************************************************
452 * Find a resource entry
454 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
455 ULONG level
, void **ret
, int want_dir
)
459 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
460 USHORT list
[9]; /* list of languages to try */
462 LCID user_lcid
, system_lcid
;
464 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
465 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
468 if (!level
--) goto done
;
469 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
470 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
471 if (!level
--) return STATUS_SUCCESS
;
474 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
475 return STATUS_RESOURCE_NAME_NOT_FOUND
;
476 if (!level
--) return STATUS_SUCCESS
;
477 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
479 /* 1. specified language */
480 pos
= push_language( list
, pos
, info
->Language
);
482 /* 2. specified language with neutral sublanguage */
483 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(info
->Language
), SUBLANG_NEUTRAL
) );
485 /* 3. neutral language with neutral sublanguage */
486 pos
= push_language( list
, pos
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
488 /* if no explicitly specified language, try some defaults */
489 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
491 /* user defaults, unless SYS_DEFAULT sublanguage specified */
492 if (SUBLANGID(info
->Language
) != SUBLANG_SYS_DEFAULT
)
494 /* 4. current thread locale language */
495 pos
= push_language( list
, pos
, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale
) );
497 if (NT_SUCCESS(NtQueryDefaultLocale(TRUE
, &user_lcid
)))
499 /* 5. user locale language */
500 pos
= push_language( list
, pos
, LANGIDFROMLCID(user_lcid
) );
502 /* 6. user locale language with neutral sublanguage */
503 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(user_lcid
), SUBLANG_NEUTRAL
) );
507 /* now system defaults */
509 if (NT_SUCCESS(NtQueryDefaultLocale(FALSE
, &system_lcid
)))
511 /* 7. system locale language */
512 pos
= push_language( list
, pos
, LANGIDFROMLCID( system_lcid
) );
514 /* 8. system locale language with neutral sublanguage */
515 pos
= push_language( list
, pos
, MAKELANGID( PRIMARYLANGID(system_lcid
), SUBLANG_NEUTRAL
) );
519 pos
= push_language( list
, pos
, MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
) );
523 for (i
= 0; i
< pos
; i
++)
524 if ((*ret
= find_entry_by_id( resdirptr
, list
[i
], root
, want_dir
))) return STATUS_SUCCESS
;
526 /* if no explicitly specified language, return the first entry */
527 if (PRIMARYLANGID(info
->Language
) == LANG_NEUTRAL
)
529 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
531 return STATUS_RESOURCE_LANG_NOT_FOUND
;
535 return STATUS_SUCCESS
;