#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
+
+#define TAG_ATMT 'TotA' /* Atom table */
extern ULONG NtGlobalFlag;
+typedef struct _RTL_RANGE_ENTRY
+{
+ LIST_ENTRY Entry;
+ RTL_RANGE Range;
+} RTL_RANGE_ENTRY, *PRTL_RANGE_ENTRY;
+
+PAGED_LOOKASIDE_LIST RtlpRangeListEntryLookasideList;
+SIZE_T RtlpAllocDeallocQueryBufferSize = 128;
+
/* FUNCTIONS *****************************************************************/
+VOID
+NTAPI
+RtlInitializeRangeListPackage(VOID)
+{
+ /* Setup the lookaside list for allocations (not used yet) */
+ ExInitializePagedLookasideList(&RtlpRangeListEntryLookasideList,
+ NULL,
+ NULL,
+ POOL_COLD_ALLOCATION,
+ sizeof(RTL_RANGE_ENTRY),
+ 'elRR',
+ 16);
+}
+
BOOLEAN
NTAPI
-RtlpCheckForActiveDebugger(BOOLEAN Type)
+RtlpCheckForActiveDebugger(VOID)
{
/* This check is meaningless in kernel-mode */
- return Type;
+ return FALSE;
}
BOOLEAN
NTAPI
-RtlpSetInDbgPrint(IN BOOLEAN NewValue)
+RtlpSetInDbgPrint(VOID)
{
- /* This check is meaningless in kernel-mode */
+ /* Nothing to set in kernel mode */
return FALSE;
}
+VOID
+NTAPI
+RtlpClearInDbgPrint(VOID)
+{
+ /* Nothing to clear in kernel mode */
+}
+
KPROCESSOR_MODE
-STDCALL
+NTAPI
RtlpGetMode()
{
return KernelMode;
}
PVOID
-STDCALL
+NTAPI
RtlpAllocateMemory(ULONG Bytes,
ULONG Tag)
{
}
+#define TAG_USTR 'RTSU'
+#define TAG_ASTR 'RTSA'
+#define TAG_OSTR 'RTSO'
VOID
-STDCALL
+NTAPI
RtlpFreeMemory(PVOID Mem,
ULONG Tag)
{
- ExFreePoolWithTag(Mem,
- Tag);
+ if (Tag == TAG_ASTR || Tag == TAG_OSTR || Tag == TAG_USTR)
+ ExFreePool(Mem);
+ else
+ ExFreePoolWithTag(Mem, Tag);
}
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
RtlAcquirePebLock(VOID)
{
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
RtlReleasePebLock(VOID)
{
}
NTSTATUS
-STDCALL
+NTAPI
LdrShutdownThread(VOID)
{
return STATUS_SUCCESS;
PPEB
-STDCALL
-RtlpCurrentPeb(VOID)
+NTAPI
+RtlGetCurrentPeb(VOID)
{
return ((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->Peb;
}
NTSTATUS
-STDCALL
+NTAPI
RtlDeleteHeapLock(
PRTL_CRITICAL_SECTION CriticalSection)
{
- KEBUGCHECK(0);
+ ASSERT(FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
-STDCALL
+NTAPI
RtlEnterHeapLock(
PRTL_CRITICAL_SECTION CriticalSection)
{
- KEBUGCHECK(0);
+ ASSERT(FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
-STDCALL
+NTAPI
RtlInitializeHeapLock(
PRTL_CRITICAL_SECTION CriticalSection)
{
- KEBUGCHECK(0);
+ ASSERT(FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
-STDCALL
+NTAPI
RtlLeaveHeapLock(
PRTL_CRITICAL_SECTION CriticalSection)
{
- KEBUGCHECK(0);
+ ASSERT(FALSE);
return STATUS_SUCCESS;
}
-#ifdef DBG
+#if DBG
VOID FASTCALL
CHECK_PAGED_CODE_RTL(char *file, int line)
{
if(KeGetCurrentIrql() > APC_LEVEL)
{
DbgPrint("%s:%i: Pagable code called at IRQL > APC_LEVEL (%d)\n", file, line, KeGetCurrentIrql());
- KEBUGCHECK(0);
+ ASSERT(FALSE);
}
}
#endif
/* Check if we are in a DPC and the stack matches */
if ((Prcb->DpcRoutineActive) &&
(RegistrationFrameEnd <= DpcStack) &&
- ((ULONG_PTR)RegistrationFrame >= DpcStack - 4096))
+ ((ULONG_PTR)RegistrationFrame >= DpcStack - KERNEL_STACK_SIZE))
{
/* Update the limits to the DPC Stack's */
*StackHigh = DpcStack;
- *StackLow = DpcStack - 4096;
+ *StackLow = DpcStack - KERNEL_STACK_SIZE;
return TRUE;
}
}
return FALSE;
}
+#ifndef _ARM_
+
BOOLEAN
NTAPI
RtlpCaptureStackLimits(IN ULONG_PTR Ebp,
{
PKTHREAD Thread = KeGetCurrentThread();
- /* FIXME: Super native implementation */
+ /* Don't even try at ISR level or later */
+ if (KeGetCurrentIrql() > DISPATCH_LEVEL) return FALSE;
/* Start with defaults */
*StackBegin = Thread->StackLimit;
*StackEnd = (ULONG_PTR)Thread->StackBase;
- /* Check if we seem to be on the DPC stack */
- if ((*StackBegin > Ebp) || (Ebp > *StackEnd))
+ /* Check if EBP is inside the stack */
+ if ((*StackBegin <= Ebp) && (Ebp <= *StackEnd))
{
- /* FIXME: TODO */
- //ASSERT(FALSE);
- DPRINT1("Stacks: %p %p %p\n", Ebp, *StackBegin, *StackEnd);
+ /* Then make the stack start at EBP */
+ *StackBegin = Ebp;
+ }
+ else
+ {
+ /* Now we're going to assume we're on the DPC stack */
+ *StackEnd = (ULONG_PTR)(KeGetPcr()->Prcb->DpcStack);
+ *StackBegin = *StackEnd - KERNEL_STACK_SIZE;
+
+ /* Check if we seem to be on the DPC stack */
+ if ((*StackEnd) && (*StackBegin < Ebp) && (Ebp <= *StackEnd))
+ {
+ /* We're on the DPC stack */
+ *StackBegin = Ebp;
+ }
+ else
+ {
+ /* We're somewhere else entirely... use EBP for safety */
+ *StackBegin = Ebp;
+ *StackEnd = (ULONG_PTR)PAGE_ALIGN(*StackBegin);
+ }
}
/* Return success */
return TRUE;
}
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlWalkFrameChain(OUT PVOID *Callers,
+ IN ULONG Count,
+ IN ULONG Flags)
+{
+ ULONG_PTR Stack, NewStack, StackBegin, StackEnd = 0;
+ ULONG Eip;
+ BOOLEAN Result, StopSearch = FALSE;
+ ULONG i = 0;
+ PETHREAD Thread = PsGetCurrentThread();
+ PTEB Teb;
+ PKTRAP_FRAME TrapFrame;
+
+ /* Get current EBP */
+#if defined(_M_IX86)
+#if defined __GNUC__
+ __asm__("mov %%ebp, %0" : "=r" (Stack) : );
+#elif defined(_MSC_VER)
+ __asm mov Stack, ebp
+#endif
+#elif defined(_M_MIPS)
+ __asm__("move $sp, %0" : "=r" (Stack) : );
+#elif defined(_M_PPC)
+ __asm__("mr %0,1" : "=r" (Stack) : );
+#elif defined(_M_ARM)
+ __asm__("mov sp, %0" : "=r"(Stack) : );
+#else
+#error Unknown architecture
+#endif
+
+ /* Set it as the stack begin limit as well */
+ StackBegin = (ULONG_PTR)Stack;
+
+ /* Check if we're called for non-logging mode */
+ if (!Flags)
+ {
+ /* Get the actual safe limits */
+ Result = RtlpCaptureStackLimits((ULONG_PTR)Stack,
+ &StackBegin,
+ &StackEnd);
+ if (!Result) return 0;
+ }
+
+ /* Use a SEH block for maximum protection */
+ _SEH2_TRY
+ {
+ /* Check if we want the user-mode stack frame */
+ if (Flags == 1)
+ {
+ /* Get the trap frame and TEB */
+ TrapFrame = KeGetTrapFrame(&Thread->Tcb);
+ Teb = Thread->Tcb.Teb;
+
+ /* Make sure we can trust the TEB and trap frame */
+ if (!(Teb) ||
+ !(Thread->SystemThread) ||
+ (KeIsAttachedProcess()) ||
+ (KeGetCurrentIrql() >= DISPATCH_LEVEL))
+ {
+ /* Invalid or unsafe attempt to get the stack */
+ return 0;
+ }
+
+ /* Get the stack limits */
+ StackBegin = (ULONG_PTR)Teb->Tib.StackLimit;
+ StackEnd = (ULONG_PTR)Teb->Tib.StackBase;
+#ifdef _M_IX86
+ Stack = TrapFrame->Ebp;
+#elif defined(_M_PPC)
+ Stack = TrapFrame->Gpr1;
+#else
+#error Unknown architecture
+#endif
+
+ /* Validate them */
+ if (StackEnd <= StackBegin) return 0;
+ ProbeForRead((PVOID)StackBegin,
+ StackEnd - StackBegin,
+ sizeof(CHAR));
+ }
+
+ /* Loop the frames */
+ for (i = 0; i < Count; i++)
+ {
+ /*
+ * Leave if we're past the stack,
+ * if we're before the stack,
+ * or if we've reached ourselves.
+ */
+ if ((Stack >= StackEnd) ||
+ (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) ||
+ ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR))))
+ {
+ /* We're done or hit a bad address */
+ break;
+ }
+
+ /* Get new stack and EIP */
+ NewStack = *(PULONG_PTR)Stack;
+ Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR));
+
+ /* Check if the new pointer is above the oldone and past the end */
+ if (!((Stack < NewStack) && (NewStack < StackEnd)))
+ {
+ /* Stop searching after this entry */
+ StopSearch = TRUE;
+ }
+
+ /* Also make sure that the EIP isn't a stack address */
+ if ((StackBegin < Eip) && (Eip < StackEnd)) break;
+
+ /* Check if we reached a user-mode address */
+ if (!(Flags) && !(Eip & 0x80000000)) break; // FIXME: 3GB breakage
+
+ /* Save this frame */
+ Callers[i] = (PVOID)Eip;
+
+ /* Check if we should continue */
+ if (StopSearch)
+ {
+ /* Return the next index */
+ i++;
+ break;
+ }
+
+ /* Move to the next stack */
+ Stack = NewStack;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* No index */
+ i = 0;
+ }
+ _SEH2_END;
+
+ /* Return frames parsed */
+ return i;
+}
+
+#endif
+
/* RTL Atom Tables ************************************************************/
NTSTATUS
RtlZeroMemory(Table,
Size);
}
-
+
return Table;
}
PRTL_ATOM_TABLE_ENTRY
RtlpAllocAtomTableEntry(ULONG Size)
{
- PRTL_ATOM_TABLE_ENTRY Entry = ExAllocatePool(NonPagedPool,
- Size);
- if (Entry != NULL)
- {
- RtlZeroMemory(Entry,
- Size);
- }
+ PRTL_ATOM_TABLE_ENTRY Entry;
- return Entry;
+ Entry = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_ATMT);
+ if (Entry != NULL)
+ {
+ RtlZeroMemory(Entry, Size);
+ }
+
+ return Entry;
}
VOID
RtlpFreeAtomTableEntry(PRTL_ATOM_TABLE_ENTRY Entry)
{
- ExFreePool(Entry);
+ ExFreePoolWithTag(Entry, TAG_ATMT);
}
VOID
HANDLE_TABLE_ENTRY ExEntry;
HANDLE Handle;
USHORT HandleIndex;
-
+
+ /* Initialize ex handle table entry */
ExEntry.Object = Entry;
ExEntry.GrantedAccess = 0x1; /* FIXME - valid handle */
-
+
+ /* Create ex handle */
Handle = ExCreateHandle(AtomTable->ExHandleTable,
- &ExEntry);
- if (Handle != NULL)
+ &ExEntry);
+ if (!Handle) return FALSE;
+
+ /* Calculate HandleIndex (by getting rid of the first two bits) */
+ HandleIndex = (USHORT)((ULONG_PTR)Handle >> 2);
+
+ /* Index must be less than 0xC000 */
+ if (HandleIndex >= 0xC000)
{
- HandleIndex = (USHORT)((ULONG_PTR)Handle >> 2);
- /* FIXME - Handle Indexes >= 0xC000 ?! */
- if ((ULONG_PTR)HandleIndex >> 2 < 0xC000)
- {
- Entry->HandleIndex = HandleIndex;
- Entry->Atom = 0xC000 + HandleIndex;
-
- return TRUE;
- }
- else
- ExDestroyHandle(AtomTable->ExHandleTable,
- Handle,
- NULL);
+ /* Destroy ex handle */
+ ExDestroyHandle(AtomTable->ExHandleTable,
+ Handle,
+ NULL);
+
+ /* Return failure */
+ return FALSE;
}
-
- return FALSE;
+
+ /* Initialize atom table entry */
+ Entry->HandleIndex = HandleIndex;
+ Entry->Atom = 0xC000 + HandleIndex;
+
+ /* Return success */
+ return TRUE;
}
PRTL_ATOM_TABLE_ENTRY
{
PHANDLE_TABLE_ENTRY ExEntry;
PRTL_ATOM_TABLE_ENTRY Entry = NULL;
-
+
/* NOTE: There's no need to explicitly enter a critical region because it's
guaranteed that we're in a critical region right now (as we hold
the atom table lock) */
-
+
ExEntry = ExMapHandleToPointer(AtomTable->ExHandleTable,
(HANDLE)((ULONG_PTR)Index << 2));
if (ExEntry != NULL)
{
Entry = ExEntry->Object;
-
+
ExUnlockHandleTableEntry(AtomTable->ExHandleTable,
ExEntry);
}
-
- return Entry;
-}
-
-/* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */
-BOOLEAN FASTCALL
-RtlpCreateUnicodeString(
- IN OUT PUNICODE_STRING UniDest,
- IN PCWSTR Source,
- IN POOL_TYPE PoolType)
-{
- ULONG Length;
- Length = (wcslen (Source) + 1) * sizeof(WCHAR);
- UniDest->Buffer = ExAllocatePoolWithTag(PoolType, Length, TAG('U', 'S', 'T', 'R'));
- if (UniDest->Buffer == NULL)
- return FALSE;
-
- RtlCopyMemory (UniDest->Buffer,
- Source,
- Length);
-
- UniDest->MaximumLength = (USHORT)Length;
- UniDest->Length = (USHORT)Length - sizeof (WCHAR);
-
- return TRUE;
+ return Entry;
}
/*