2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/rtl/libsupp.c
5 * PURPOSE: RTL Support Routines
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES ******************************************************************/
14 #include <internal/debug.h>
16 extern ULONG NtGlobalFlag
;
18 typedef struct _RTL_RANGE_ENTRY
22 } RTL_RANGE_ENTRY
, *PRTL_RANGE_ENTRY
;
24 PAGED_LOOKASIDE_LIST RtlpRangeListEntryLookasideList
;
26 /* FUNCTIONS *****************************************************************/
30 RtlInitializeRangeListPackage(VOID
)
32 /* Setup the lookaside list for allocations (not used yet) */
33 ExInitializePagedLookasideList(&RtlpRangeListEntryLookasideList
,
37 sizeof(RTL_RANGE_ENTRY
),
38 TAG('R', 'R', 'l', 'e'),
44 RtlpCheckForActiveDebugger(BOOLEAN Type
)
46 /* This check is meaningless in kernel-mode */
52 RtlpSetInDbgPrint(IN BOOLEAN NewValue
)
54 /* This check is meaningless in kernel-mode */
67 RtlpAllocateMemory(ULONG Bytes
,
70 return ExAllocatePoolWithTag(PagedPool
,
78 RtlpFreeMemory(PVOID Mem
,
81 ExFreePoolWithTag(Mem
,
89 RtlAcquirePebLock(VOID
)
98 RtlReleasePebLock(VOID
)
105 LdrShutdownThread(VOID
)
107 return STATUS_SUCCESS
;
115 return ((PEPROCESS
)(KeGetCurrentThread()->ApcState
.Process
))->Peb
;
121 PRTL_CRITICAL_SECTION CriticalSection
)
124 return STATUS_SUCCESS
;
130 PRTL_CRITICAL_SECTION CriticalSection
)
133 return STATUS_SUCCESS
;
138 RtlInitializeHeapLock(
139 PRTL_CRITICAL_SECTION CriticalSection
)
142 return STATUS_SUCCESS
;
148 PRTL_CRITICAL_SECTION CriticalSection
)
151 return STATUS_SUCCESS
;
156 CHECK_PAGED_CODE_RTL(char *file
, int line
)
158 if(KeGetCurrentIrql() > APC_LEVEL
)
160 DbgPrint("%s:%i: Pagable code called at IRQL > APC_LEVEL (%d)\n", file
, line
, KeGetCurrentIrql());
168 RtlpCheckLogException(IN PEXCEPTION_RECORD ExceptionRecord
,
169 IN PCONTEXT ContextRecord
,
170 IN PVOID ContextData
,
173 /* Check the global flag */
174 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
176 /* FIXME: Log this exception */
182 RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame
,
183 IN ULONG_PTR RegistrationFrameEnd
,
184 IN OUT PULONG_PTR StackLow
,
185 IN OUT PULONG_PTR StackHigh
)
190 /* Check if we are at DISPATCH or higher */
191 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
193 /* Get the PRCB and DPC Stack */
194 Prcb
= KeGetCurrentPrcb();
195 DpcStack
= (ULONG_PTR
)Prcb
->DpcStack
;
197 /* Check if we are in a DPC and the stack matches */
198 if ((Prcb
->DpcRoutineActive
) &&
199 (RegistrationFrameEnd
<= DpcStack
) &&
200 ((ULONG_PTR
)RegistrationFrame
>= DpcStack
- KERNEL_STACK_SIZE
))
202 /* Update the limits to the DPC Stack's */
203 *StackHigh
= DpcStack
;
204 *StackLow
= DpcStack
- KERNEL_STACK_SIZE
;
209 /* Not in DPC stack */
215 RtlpCaptureStackLimits(IN ULONG_PTR Ebp
,
216 IN ULONG_PTR
*StackBegin
,
217 IN ULONG_PTR
*StackEnd
)
219 PKTHREAD Thread
= KeGetCurrentThread();
221 /* Don't even try at ISR level or later */
222 if (KeGetCurrentIrql() > DISPATCH_LEVEL
) return FALSE
;
224 /* Start with defaults */
225 *StackBegin
= Thread
->StackLimit
;
226 *StackEnd
= (ULONG_PTR
)Thread
->StackBase
;
228 /* Check if EBP is inside the stack */
229 if ((*StackBegin
<= Ebp
) && (Ebp
<= *StackEnd
))
231 /* Then make the stack start at EBP */
236 /* Now we're going to assume we're on the DPC stack */
237 *StackEnd
= (ULONG_PTR
)(KeGetPcr()->Prcb
->DpcStack
);
238 *StackBegin
= *StackEnd
- KERNEL_STACK_SIZE
;
240 /* Check if we seem to be on the DPC stack */
241 if ((*StackEnd
) && (*StackBegin
< Ebp
) && (Ebp
<= *StackEnd
))
243 /* We're on the DPC stack */
248 /* We're somewhere else entirely... use EBP for safety */
250 *StackEnd
= (ULONG_PTR
)PAGE_ALIGN(*StackBegin
);
258 /* RTL Atom Tables ************************************************************/
261 RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
263 ExInitializeFastMutex(&AtomTable
->FastMutex
);
265 return STATUS_SUCCESS
;
270 RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable
)
276 RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable
)
278 ExAcquireFastMutex(&AtomTable
->FastMutex
);
283 RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable
)
285 ExReleaseFastMutex(&AtomTable
->FastMutex
);
289 RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
291 AtomTable
->ExHandleTable
= ExCreateHandleTable(NULL
);
292 return (AtomTable
->ExHandleTable
!= NULL
);
296 RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable
)
298 if (AtomTable
->ExHandleTable
)
300 ExSweepHandleTable(AtomTable
->ExHandleTable
,
303 ExDestroyHandleTable(AtomTable
->ExHandleTable
, NULL
);
304 AtomTable
->ExHandleTable
= NULL
;
309 RtlpAllocAtomTable(ULONG Size
)
311 PRTL_ATOM_TABLE Table
= ExAllocatePool(NonPagedPool
,
323 RtlpFreeAtomTable(PRTL_ATOM_TABLE AtomTable
)
325 ExFreePool(AtomTable
);
328 PRTL_ATOM_TABLE_ENTRY
329 RtlpAllocAtomTableEntry(ULONG Size
)
331 PRTL_ATOM_TABLE_ENTRY Entry
= ExAllocatePool(NonPagedPool
,
343 RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry
)
349 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
351 ExDestroyHandle(AtomTable
->ExHandleTable
,
352 (HANDLE
)((ULONG_PTR
)Entry
->HandleIndex
<< 2),
357 RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable
, PRTL_ATOM_TABLE_ENTRY Entry
)
359 HANDLE_TABLE_ENTRY ExEntry
;
363 ExEntry
.Object
= Entry
;
364 ExEntry
.GrantedAccess
= 0x1; /* FIXME - valid handle */
366 Handle
= ExCreateHandle(AtomTable
->ExHandleTable
,
370 HandleIndex
= (USHORT
)((ULONG_PTR
)Handle
>> 2);
371 /* FIXME - Handle Indexes >= 0xC000 ?! */
372 if ((ULONG_PTR
)HandleIndex
>> 2 < 0xC000)
374 Entry
->HandleIndex
= HandleIndex
;
375 Entry
->Atom
= 0xC000 + HandleIndex
;
380 ExDestroyHandle(AtomTable
->ExHandleTable
,
388 PRTL_ATOM_TABLE_ENTRY
389 RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable
, ULONG Index
)
391 PHANDLE_TABLE_ENTRY ExEntry
;
392 PRTL_ATOM_TABLE_ENTRY Entry
= NULL
;
394 /* NOTE: There's no need to explicitly enter a critical region because it's
395 guaranteed that we're in a critical region right now (as we hold
396 the atom table lock) */
398 ExEntry
= ExMapHandleToPointer(AtomTable
->ExHandleTable
,
399 (HANDLE
)((ULONG_PTR
)Index
<< 2));
402 Entry
= ExEntry
->Object
;
404 ExUnlockHandleTableEntry(AtomTable
->ExHandleTable
,
411 /* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */
413 RtlpCreateUnicodeString(
414 IN OUT PUNICODE_STRING UniDest
,
416 IN POOL_TYPE PoolType
)
420 Length
= (wcslen (Source
) + 1) * sizeof(WCHAR
);
421 UniDest
->Buffer
= ExAllocatePoolWithTag(PoolType
, Length
, TAG('U', 'S', 'T', 'R'));
422 if (UniDest
->Buffer
== NULL
)
425 RtlCopyMemory (UniDest
->Buffer
,
429 UniDest
->MaximumLength
= (USHORT
)Length
;
430 UniDest
->Length
= (USHORT
)Length
- sizeof (WCHAR
);
436 * Ldr Resource support code
439 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
440 LPCWSTR name
, void *root
,
442 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
443 USHORT id
, void *root
, int want_dir
);
444 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
445 void *root
, int want_dir
);
447 /**********************************************************************
450 * Find a resource entry
452 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
453 ULONG level
, void **ret
, int want_dir
)
457 IMAGE_RESOURCE_DIRECTORY
*resdirptr
;
459 root
= RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
460 if (!root
) return STATUS_RESOURCE_DATA_NOT_FOUND
;
463 if (!level
--) goto done
;
464 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Type
, root
, want_dir
|| level
)))
465 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
466 if (!level
--) return STATUS_SUCCESS
;
469 if (!(*ret
= find_entry_by_name( resdirptr
, (LPCWSTR
)info
->Name
, root
, want_dir
|| level
)))
470 return STATUS_RESOURCE_NAME_NOT_FOUND
;
471 if (!level
--) return STATUS_SUCCESS
;
472 if (level
) return STATUS_INVALID_PARAMETER
; /* level > 3 */
476 if ((*ret
= find_first_entry( resdirptr
, root
, want_dir
))) return STATUS_SUCCESS
;
478 return STATUS_RESOURCE_DATA_NOT_FOUND
;
482 return STATUS_SUCCESS
;