Correct NtW32call to call correct kernel function, add placeholder for
SEH, implement KeUserModeCallback (right now a copy of the old code).
Part I of an incomplete W32Callback rewrite, just to set up the
groundwork to make testing easier. Might look ugly/messy now but it'll
be clean soon
Modified: trunk/reactos/ntoskrnl/Makefile
Modified: trunk/reactos/ntoskrnl/include/internal/i386/fpu.h
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h
Added: trunk/reactos/ntoskrnl/ke/i386/usercall.S
Deleted: trunk/reactos/ntoskrnl/ke/i386/usercall.c
Added: trunk/reactos/ntoskrnl/ke/usercall.c
Modified: trunk/reactos/ntoskrnl/ldr/sysdll.c
Deleted: trunk/reactos/ntoskrnl/ps/w32call.c
Modified: trunk/reactos/ntoskrnl/ps/win32.c
_____
Modified: trunk/reactos/ntoskrnl/Makefile
--- trunk/reactos/ntoskrnl/Makefile 2005-03-19 19:52:36 UTC (rev
14198)
+++ trunk/reactos/ntoskrnl/Makefile 2005-03-19 20:26:46 UTC (rev
14199)
@@ -111,6 +111,7 @@
ke/sem.o \
ke/spinlock.o \
ke/timer.o \
+ ke/usercall.o \
ke/wait.o
# Memory Manager (Mm)
@@ -230,8 +231,7 @@
ps/security.o \
ps/suspend.o \
ps/thread.o \
- ps/win32.o \
- ps/w32call.o
+ ps/win32.o
# Executive Subsystem (Ex)
OBJECTS_EX = \
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/fpu.h
--- trunk/reactos/ntoskrnl/include/internal/i386/fpu.h 2005-03-19
19:52:36 UTC (rev 14198)
+++ trunk/reactos/ntoskrnl/include/internal/i386/fpu.h 2005-03-19
20:26:46 UTC (rev 14199)
@@ -20,6 +20,11 @@
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
#define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
+#define FN_CONTROL_WORD 0x0
+#define FN_STATUS_WORD 0x4
+#define FN_TAG_WORD 0x8
+#define FN_DATA_SELECTOR 0x18
+#define FN_CR0_NPX_STATE 0x20C
#define SIZEOF_FX_SAVE_AREA 528
#ifndef __ASM__
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-03-19
19:52:36 UTC (rev 14198)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-03-19
20:26:46 UTC (rev 14199)
@@ -43,6 +43,7 @@
#define KPCR_BASE 0xFF000000
#define KPCR_EXCEPTION_LIST 0x0
+#define KPCR_INITIAL_STACK 0x4
#define KPCR_SELF 0x1C
#define KPCR_TSS 0x40
#define KPCR_CURRENT_THREAD 0x124
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h
--- trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h 2005-03-19
19:52:36 UTC (rev 14198)
+++ trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h 2005-03-19
20:26:46 UTC (rev 14199)
@@ -66,6 +66,6 @@
/*
*
*/
-#define MM_STACK_SIZE (3*4096)
+#define MM_STACK_SIZE (12*4096)
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
_____
Added: trunk/reactos/ntoskrnl/ke/i386/usercall.S
--- trunk/reactos/ntoskrnl/ke/i386/usercall.S 2005-03-19 19:52:36 UTC
(rev 14198)
+++ trunk/reactos/ntoskrnl/ke/i386/usercall.S 2005-03-19 20:26:46 UTC
(rev 14199)
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ke/i386s/usercall.S
+ * PURPOSE: User-Mode callbacks and return.
+ *
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ */
+
+/* INCLUDES
******************************************************************/
+
+#include <roscfg.h>
+#include <internal/i386/segment.h>
+#include <internal/i386/ke.h>
+#include <internal/i386/fpu.h>
+#include <internal/ps.h>
+#include <ntos/tss.h>
+#include <internal/ntoskrnl.h>
+.intel_syntax noprefix
+
+/* GLOBALS
****************************************************************/
+.extern PVOID _SystemDllCallbackDispatcher
+
+#define CBSTACK_BUFFER_ADDRESS 0x20
+#define CBSTACK_BUFFER_LENGTH 0x24
+/* FUNCTIONS
****************************************************************/
+
+/*++
+ * KiSwitchToUserMode
+ *
+ * The KiSwitchToUserMode routine sets up a Trap Frame and a
Callback stack
+ * for the purpose of switching to user mode. The actual final jump
is done
+ * by KiServiceExit which will treat this as a syscall return.
+ *
+ * Params:
+ * OutputBuffer - Pointer to a caller-allocated buffer where to
receive
+ * the return data from the user-mode function
+ *
+ * OutputLength - Size of the Output Buffer described above.
+ *
+ * Returns:
+ * Jumps into KiServiceExit.
+ *
+ * Remarks:
+ * If there is not enough Kernel Stack space, the routine will
increase the
+ * Kernel Stack.
+ *
+ * User mode execution resumes at ntdll!KiUserCallbackDispatcher.
+ *
+ * This call MUST be paired by interrupt 0x2B or NtCallbackReturn.
+ *
+ *--*/
+.globl _KiSwitchToUserMode@8
+.func KiSwitchToUserMode@8
+_KiSwitchToUserMode@8:
+
+.endfunc
+
+
_____
Deleted: trunk/reactos/ntoskrnl/ke/i386/usercall.c
--- trunk/reactos/ntoskrnl/ke/i386/usercall.c 2005-03-19 19:52:36 UTC
(rev 14198)
+++ trunk/reactos/ntoskrnl/ke/i386/usercall.c 2005-03-19 20:26:46 UTC
(rev 14199)
@@ -1,36 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ke/i386/usercall.c
- * PURPOSE: 2E interrupt handler
- *
- * PROGRAMMERS: David Welch (david.welch(a)seh.ox.ac.uk)
- */
-
-/* INCLUDES
******************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS
*****************************************************************/
-
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-KeUserModeCallback(
- IN ULONG FunctionID,
- IN PVOID InputBuffer,
- IN ULONG InputLength,
- OUT PVOID *OutputBuffer,
- OUT PULONG OutputLength
-)
-{
- UNIMPLEMENTED;
- return 0;
-}
-
-/* EOF */
_____
Added: trunk/reactos/ntoskrnl/ke/usercall.c
--- trunk/reactos/ntoskrnl/ke/usercall.c 2005-03-19 19:52:36 UTC
(rev 14198)
+++ trunk/reactos/ntoskrnl/ke/usercall.c 2005-03-19 20:26:46 UTC
(rev 14199)
@@ -0,0 +1,253 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ke/usercall.c
+ * PURPOSE: User-Mode callbacks. Portable part.
+ *
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ */
+
+/* INCLUDES
******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS
*****************************************************************/
+
+#if ALEX_CB_REWRITE
+
+NTSTATUS
+STDCALL
+KiSwitchToUserMode(IN PVOID *OutputBuffer,
+ IN PULONG OutputLength);
+
+#else
+
+typedef struct _NTW32CALL_SAVED_STATE
+{
+ ULONG_PTR SavedStackLimit;
+ PVOID SavedStackBase;
+ PVOID SavedInitialStack;
+ PVOID CallerResult;
+ PULONG CallerResultLength;
+ PNTSTATUS CallbackStatus;
+ PKTRAP_FRAME SavedTrapFrame;
+ PVOID SavedCallbackStack;
+ PVOID SavedExceptionStack;
+} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
+
+typedef struct
+{
+ PVOID BaseAddress;
+ LIST_ENTRY ListEntry;
+} NTW32CALL_CALLBACK_STACK, *PNTW32CALL_CALLBACK_STACK;
+
+KSPIN_LOCK CallbackStackListLock;
+static LIST_ENTRY CallbackStackListHead;
+
+VOID INIT_FUNCTION
+PsInitialiseW32Call(VOID)
+{
+ InitializeListHead(&CallbackStackListHead);
+ KeInitializeSpinLock(&CallbackStackListLock);
+}
+
+VOID STATIC
+PsFreeCallbackStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID
Address,
+ PFN_TYPE Page, SWAPENTRY SwapEntry,
+ BOOLEAN Dirty)
+{
+ ASSERT(SwapEntry == 0);
+ if (Page != 0)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
+ }
+}
+
+VOID STATIC
+PsFreeCallbackStack(PVOID StackLimit)
+{
+ MmLockAddressSpace(MmGetKernelAddressSpace());
+ MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+ StackLimit,
+ PsFreeCallbackStackPage,
+ NULL);
+ MmUnlockAddressSpace(MmGetKernelAddressSpace());
+}
+
+VOID
+PsFreeCallbackStacks(VOID)
+{
+ PLIST_ENTRY CurrentListEntry;
+ PNTW32CALL_CALLBACK_STACK Current;
+
+ while (!IsListEmpty(&CallbackStackListHead))
+ {
+ CurrentListEntry = RemoveHeadList(&CallbackStackListHead);
+ Current = CONTAINING_RECORD(CurrentListEntry,
NTW32CALL_CALLBACK_STACK,
+ ListEntry);
+ PsFreeCallbackStack(Current->BaseAddress);
+ ExFreePool(Current);
+ }
+}
+
+PVOID STATIC
+PsAllocateCallbackStack(ULONG StackSize)
+{
+ PVOID KernelStack = NULL;
+ NTSTATUS Status;
+ PMEMORY_AREA StackArea;
+ ULONG i, j;
+ PHYSICAL_ADDRESS BoundaryAddressMultiple;
+ PPFN_TYPE Pages = alloca(sizeof(PFN_TYPE) * (StackSize /PAGE_SIZE));
+
+
+ BoundaryAddressMultiple.QuadPart = 0;
+ StackSize = PAGE_ROUND_UP(StackSize);
+ MmLockAddressSpace(MmGetKernelAddressSpace());
+ Status = MmCreateMemoryArea(NULL,
+ MmGetKernelAddressSpace(),
+ MEMORY_AREA_KERNEL_STACK,
+ &KernelStack,
+ StackSize,
+ 0,
+ &StackArea,
+ FALSE,
+ FALSE,
+ BoundaryAddressMultiple);
+ MmUnlockAddressSpace(MmGetKernelAddressSpace());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to create thread stack\n");
+ return(NULL);
+ }
+ for (i = 0; i < (StackSize / PAGE_SIZE); i++)
+ {
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pages[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ for (j = 0; j < i; j++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[j]);
+ }
+ return(NULL);
+ }
+ }
+ Status = MmCreateVirtualMapping(NULL,
+ KernelStack,
+ PAGE_READWRITE,
+ Pages,
+ StackSize / PAGE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ for (i = 0; i < (StackSize / PAGE_SIZE); i++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[i]);
+ }
+ return(NULL);
+ }
+ return(KernelStack);
+}
+#endif
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+KeUserModeCallback(IN ULONG RoutineIndex,
+ IN PVOID Argument,
+ IN ULONG ArgumentLength,
+ OUT PVOID *Result,
+ OUT PULONG ResultLength)
+{
+ PETHREAD Thread;
+ PVOID NewStack;
+ ULONG_PTR StackSize;
+ PKTRAP_FRAME NewFrame;
+ PULONG UserEsp;
+ KIRQL oldIrql;
+ NTSTATUS CallbackStatus;
+ NTW32CALL_SAVED_STATE SavedState;
+ PNTW32CALL_CALLBACK_STACK AssignedStack;
+
+ PAGED_CODE();
+
+ DPRINT("KeUserModeCallback(RoutineIndex %d, Argument %X,
ArgumentLength %d)\n",
+ RoutineIndex, Argument, ArgumentLength);
+
+ Thread = PsGetCurrentThread();
+
+ /* Set up the new kernel and user environment. */
+ StackSize = (ULONG_PTR)Thread->Tcb.StackBase -
Thread->Tcb.StackLimit;
+ KeAcquireSpinLock(&CallbackStackListLock, &oldIrql);
+ if (IsListEmpty(&CallbackStackListHead))
+ {
+ KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
+ NewStack = PsAllocateCallbackStack(StackSize);
+ AssignedStack = ExAllocatePool(NonPagedPool,
+ sizeof(NTW32CALL_CALLBACK_STACK));
+ AssignedStack->BaseAddress = NewStack;
+ }
+ else
+ {
+ PLIST_ENTRY StackEntry;
+
+ StackEntry = RemoveHeadList(&CallbackStackListHead);
+ KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
+ AssignedStack = CONTAINING_RECORD(StackEntry,
NTW32CALL_CALLBACK_STACK,
+ ListEntry);
+ NewStack = AssignedStack->BaseAddress;
+ RtlZeroMemory(NewStack, StackSize);
+ }
+ /* FIXME: Need to check whether we were interrupted from v86 mode. */
+ RtlCopyMemory((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) -
sizeof(FX_SAVE_AREA),
+ Thread->Tcb.TrapFrame, sizeof(KTRAP_FRAME) - (4 *
sizeof(DWORD)));
+ NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize -
sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA));
+ /* We need the stack pointer to remain 4-byte aligned */
+ NewFrame->Esp -= (((ArgumentLength + 3) & (~ 0x3)) + (4 *
sizeof(ULONG)));
+ NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher();
+ UserEsp = (PULONG)NewFrame->Esp;
+ UserEsp[0] = 0; /* Return address. */
+ UserEsp[1] = RoutineIndex;
+ UserEsp[2] = (ULONG)&UserEsp[4];
+ UserEsp[3] = ArgumentLength;
+ RtlCopyMemory((PVOID)&UserEsp[4], Argument, ArgumentLength);
+
+ /* Switch to the new environment and return to user-mode. */
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+ SavedState.SavedStackLimit = Thread->Tcb.StackLimit;
+ SavedState.SavedStackBase = Thread->Tcb.StackBase;
+ SavedState.SavedInitialStack = Thread->Tcb.InitialStack;
+ SavedState.CallerResult = Result;
+ SavedState.CallerResultLength = ResultLength;
+ SavedState.CallbackStatus = &CallbackStatus;
+ SavedState.SavedTrapFrame = Thread->Tcb.TrapFrame;
+ SavedState.SavedCallbackStack = Thread->Tcb.CallbackStack;
+ SavedState.SavedExceptionStack =
(PVOID)KeGetCurrentKPCR()->TSS->Esp0;
+ if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
+ ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
+ {
+ RtlCopyMemory((char*)NewStack + StackSize - sizeof(FX_SAVE_AREA),
+ (char*)SavedState.SavedInitialStack -
sizeof(FX_SAVE_AREA),
+ sizeof(FX_SAVE_AREA));
+ }
+ Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)NewStack +
StackSize;
+ Thread->Tcb.StackLimit = (ULONG)NewStack;
+ Thread->Tcb.KernelStack = (char*)NewStack + StackSize -
sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA);
+ KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack -
sizeof(FX_SAVE_AREA);
+ KePushAndStackSwitchAndSysRet((ULONG)&SavedState,
Thread->Tcb.KernelStack);
+
+ /*
+ * The callback return will have already restored most of the state
we
+ * modified.
+ */
+ KeLowerIrql(DISPATCH_LEVEL);
+ KeAcquireSpinLockAtDpcLevel(&CallbackStackListLock);
+ InsertTailList(&CallbackStackListHead, &AssignedStack->ListEntry);
+ KeReleaseSpinLock(&CallbackStackListLock, PASSIVE_LEVEL);
+ return(CallbackStatus);
+}
+
+/* EOF */
_____
Modified: trunk/reactos/ntoskrnl/ldr/sysdll.c
--- trunk/reactos/ntoskrnl/ldr/sysdll.c 2005-03-19 19:52:36 UTC (rev
14198)
+++ trunk/reactos/ntoskrnl/ldr/sysdll.c 2005-03-19 20:26:46 UTC (rev
14199)
@@ -18,11 +18,11 @@
/* GLOBALS
*******************************************************************/
-static PVOID SystemDllEntryPoint = NULL;
-static PVOID SystemDllApcDispatcher = NULL;
-static PVOID SystemDllCallbackDispatcher = NULL;
-static PVOID SystemDllExceptionDispatcher = NULL;
-static PVOID SystemDllRaiseExceptionDispatcher = NULL;
+PVOID SystemDllEntryPoint = NULL;
+PVOID SystemDllApcDispatcher = NULL;
+PVOID SystemDllCallbackDispatcher = NULL;
+PVOID SystemDllExceptionDispatcher = NULL;
+PVOID SystemDllRaiseExceptionDispatcher = NULL;
/* FUNCTIONS
*****************************************************************/
_____
Deleted: trunk/reactos/ntoskrnl/ps/w32call.c
--- trunk/reactos/ntoskrnl/ps/w32call.c 2005-03-19 19:52:36 UTC (rev
14198)
+++ trunk/reactos/ntoskrnl/ps/w32call.c 2005-03-19 20:26:46 UTC (rev
14199)
@@ -1,343 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ps/w32call.c
- * PURPOSE: Thread managment
- *
- * PROGRAMMERS: David Welch (welch(a)mcmail.com)
- * Phillip Susi
- */
-
-/*
- * NOTE:
- *
- * All of the routines that manipulate the thread queue synchronize on
- * a single spinlock
- *
- */
-
-/* INCLUDES
****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-#if defined(__GNUC__)
-/* void * alloca(size_t size); */
-#elif defined(_MSC_VER)
-void* _alloca(size_t size);
-#else
-#error Unknown compiler for alloca intrinsic stack allocation
"function"
-#endif
-
-/* TYPES
*******************************************************************/
-
-typedef struct _NTW32CALL_SAVED_STATE
-{
- ULONG_PTR SavedStackLimit;
- PVOID SavedStackBase;
- PVOID SavedInitialStack;
- PVOID CallerResult;
- PULONG CallerResultLength;
- PNTSTATUS CallbackStatus;
- PKTRAP_FRAME SavedTrapFrame;
- PVOID SavedCallbackStack;
- PVOID SavedExceptionStack;
-} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
-
-typedef struct
-{
- PVOID BaseAddress;
- LIST_ENTRY ListEntry;
-} NTW32CALL_CALLBACK_STACK, *PNTW32CALL_CALLBACK_STACK;
-
-KSPIN_LOCK CallbackStackListLock;
-static LIST_ENTRY CallbackStackListHead;
-
-/* FUNCTIONS
***************************************************************/
-
-VOID INIT_FUNCTION
-PsInitialiseW32Call(VOID)
-{
- InitializeListHead(&CallbackStackListHead);
- KeInitializeSpinLock(&CallbackStackListLock);
-}
-
-NTSTATUS STDCALL
-NtCallbackReturn (PVOID Result,
- ULONG ResultLength,
- NTSTATUS Status)
-{
- PULONG OldStack;
- PETHREAD Thread;
- PNTSTATUS CallbackStatus;
- PULONG CallerResultLength;
- PVOID* CallerResult;
- PVOID InitialStack;
- PVOID StackBase;
- ULONG_PTR StackLimit;
- KIRQL oldIrql;
- PNTW32CALL_SAVED_STATE State;
- PKTRAP_FRAME SavedTrapFrame;
- PVOID SavedCallbackStack;
- PVOID SavedExceptionStack;
-
- PAGED_CODE();
-
- Thread = PsGetCurrentThread();
- if (Thread->Tcb.CallbackStack == NULL)
- {
- return(STATUS_NO_CALLBACK_ACTIVE);
- }
-
- OldStack = (PULONG)Thread->Tcb.CallbackStack;
-
- /*
- * Get the values that NtW32Call left on the inactive stack for us.
- */
- State = (PNTW32CALL_SAVED_STATE)OldStack[0];
- CallbackStatus = State->CallbackStatus;
- CallerResultLength = State->CallerResultLength;
- CallerResult = State->CallerResult;
- InitialStack = State->SavedInitialStack;
- StackBase = State->SavedStackBase;
- StackLimit = State->SavedStackLimit;
- SavedTrapFrame = State->SavedTrapFrame;
- SavedCallbackStack = State->SavedCallbackStack;
- SavedExceptionStack = State->SavedExceptionStack;
-
- /*
- * Copy the callback status and the callback result to NtW32Call
- */
- *CallbackStatus = Status;
- if (CallerResult != NULL && CallerResultLength != NULL)
- {
- if (Result == NULL)
- {
- *CallerResultLength = 0;
- }
- else
- {
- *CallerResultLength = min(ResultLength, *CallerResultLength);
- RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
- }
- }
-
- /*
- * Restore the old stack.
- */
- KeRaiseIrql(HIGH_LEVEL, &oldIrql);
- if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
- ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
- {
- RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
- (char*)Thread->Tcb.InitialStack -
sizeof(FX_SAVE_AREA),
- sizeof(FX_SAVE_AREA));
- }
- Thread->Tcb.InitialStack = InitialStack;
- Thread->Tcb.StackBase = StackBase;
- Thread->Tcb.StackLimit = StackLimit;
- Thread->Tcb.TrapFrame = SavedTrapFrame;
- Thread->Tcb.CallbackStack = SavedCallbackStack;
- KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
- KeStackSwitchAndRet((PVOID)(OldStack + 1));
-
- /* Should never return. */
- KEBUGCHECK(0);
- return(STATUS_UNSUCCESSFUL);
-}
-
-VOID STATIC
-PsFreeCallbackStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID
Address,
- PFN_TYPE Page, SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
-{
- ASSERT(SwapEntry == 0);
- if (Page != 0)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
- }
-}
-
-VOID STATIC
-PsFreeCallbackStack(PVOID StackLimit)
-{
- MmLockAddressSpace(MmGetKernelAddressSpace());
- MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
- StackLimit,
- PsFreeCallbackStackPage,
- NULL);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-}
-
-VOID
-PsFreeCallbackStacks(VOID)
-{
- PLIST_ENTRY CurrentListEntry;
- PNTW32CALL_CALLBACK_STACK Current;
-
- while (!IsListEmpty(&CallbackStackListHead))
- {
- CurrentListEntry = RemoveHeadList(&CallbackStackListHead);
- Current = CONTAINING_RECORD(CurrentListEntry,
NTW32CALL_CALLBACK_STACK,
- ListEntry);
- PsFreeCallbackStack(Current->BaseAddress);
- ExFreePool(Current);
- }
-}
-
-PVOID STATIC
-PsAllocateCallbackStack(ULONG StackSize)
-{
- PVOID KernelStack = NULL;
- NTSTATUS Status;
- PMEMORY_AREA StackArea;
- ULONG i, j;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
- PPFN_TYPE Pages = alloca(sizeof(PFN_TYPE) * (StackSize /PAGE_SIZE));
-
-
- BoundaryAddressMultiple.QuadPart = 0;
- StackSize = PAGE_ROUND_UP(StackSize);
- MmLockAddressSpace(MmGetKernelAddressSpace());
- Status = MmCreateMemoryArea(NULL,
- MmGetKernelAddressSpace(),
- MEMORY_AREA_KERNEL_STACK,
- &KernelStack,
- StackSize,
- 0,
- &StackArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Failed to create thread stack\n");
- return(NULL);
- }
- for (i = 0; i < (StackSize / PAGE_SIZE); i++)
- {
- Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pages[i]);
- if (!NT_SUCCESS(Status))
- {
- for (j = 0; j < i; j++)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[j]);
- }
- return(NULL);
- }
- }
- Status = MmCreateVirtualMapping(NULL,
- KernelStack,
- PAGE_READWRITE,
- Pages,
- StackSize / PAGE_SIZE);
- if (!NT_SUCCESS(Status))
- {
- for (i = 0; i < (StackSize / PAGE_SIZE); i++)
- {
- MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[i]);
- }
- return(NULL);
- }
- return(KernelStack);
-}
-
-NTSTATUS STDCALL
-NtW32Call (IN ULONG RoutineIndex,
- IN PVOID Argument,
- IN ULONG ArgumentLength,
- OUT PVOID* Result OPTIONAL,
- OUT PULONG ResultLength OPTIONAL)
-{
- PETHREAD Thread;
- PVOID NewStack;
- ULONG_PTR StackSize;
- PKTRAP_FRAME NewFrame;
- PULONG UserEsp;
- KIRQL oldIrql;
- NTSTATUS CallbackStatus;
- NTW32CALL_SAVED_STATE SavedState;
- PNTW32CALL_CALLBACK_STACK AssignedStack;
-
- PAGED_CODE();
-
- DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength
%d)\n",
- RoutineIndex, Argument, ArgumentLength);
-
- Thread = PsGetCurrentThread();
-
- /* Set up the new kernel and user environment. */
- StackSize = (ULONG_PTR)Thread->Tcb.StackBase -
Thread->Tcb.StackLimit;
- KeAcquireSpinLock(&CallbackStackListLock, &oldIrql);
- if (IsListEmpty(&CallbackStackListHead))
- {
- KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
- NewStack = PsAllocateCallbackStack(StackSize);
- AssignedStack = ExAllocatePool(NonPagedPool,
- sizeof(NTW32CALL_CALLBACK_STACK));
- AssignedStack->BaseAddress = NewStack;
- }
- else
- {
- PLIST_ENTRY StackEntry;
-
- StackEntry = RemoveHeadList(&CallbackStackListHead);
- KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
- AssignedStack = CONTAINING_RECORD(StackEntry,
NTW32CALL_CALLBACK_STACK,
- ListEntry);
- NewStack = AssignedStack->BaseAddress;
- RtlZeroMemory(NewStack, StackSize);
- }
- /* FIXME: Need to check whether we were interrupted from v86 mode. */
- RtlCopyMemory((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) -
sizeof(FX_SAVE_AREA),
- Thread->Tcb.TrapFrame, sizeof(KTRAP_FRAME) - (4 *
sizeof(DWORD)));
- NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize -
sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA));
- /* We need the stack pointer to remain 4-byte aligned */
- NewFrame->Esp -= (((ArgumentLength + 3) & (~ 0x3)) + (4 *
sizeof(ULONG)));
- NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher();
- UserEsp = (PULONG)NewFrame->Esp;
- UserEsp[0] = 0; /* Return address. */
- UserEsp[1] = RoutineIndex;
- UserEsp[2] = (ULONG)&UserEsp[4];
- UserEsp[3] = ArgumentLength;
- RtlCopyMemory((PVOID)&UserEsp[4], Argument, ArgumentLength);
-
- /* Switch to the new environment and return to user-mode. */
- KeRaiseIrql(HIGH_LEVEL, &oldIrql);
- SavedState.SavedStackLimit = Thread->Tcb.StackLimit;
- SavedState.SavedStackBase = Thread->Tcb.StackBase;
- SavedState.SavedInitialStack = Thread->Tcb.InitialStack;
- SavedState.CallerResult = Result;
- SavedState.CallerResultLength = ResultLength;
- SavedState.CallbackStatus = &CallbackStatus;
- SavedState.SavedTrapFrame = Thread->Tcb.TrapFrame;
- SavedState.SavedCallbackStack = Thread->Tcb.CallbackStack;
- SavedState.SavedExceptionStack =
(PVOID)KeGetCurrentKPCR()->TSS->Esp0;
- if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
- ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
- {
- RtlCopyMemory((char*)NewStack + StackSize - sizeof(FX_SAVE_AREA),
- (char*)SavedState.SavedInitialStack -
sizeof(FX_SAVE_AREA),
- sizeof(FX_SAVE_AREA));
- }
- Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)NewStack +
StackSize;
- Thread->Tcb.StackLimit = (ULONG)NewStack;
- Thread->Tcb.KernelStack = (char*)NewStack + StackSize -
sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA);
- KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack -
sizeof(FX_SAVE_AREA);
- KePushAndStackSwitchAndSysRet((ULONG)&SavedState,
Thread->Tcb.KernelStack);
-
- /*
- * The callback return will have already restored most of the state
we
- * modified.
- */
- KeLowerIrql(DISPATCH_LEVEL);
- KeAcquireSpinLockAtDpcLevel(&CallbackStackListLock);
- InsertTailList(&CallbackStackListHead, &AssignedStack->ListEntry);
- KeReleaseSpinLock(&CallbackStackListLock, PASSIVE_LEVEL);
- return(CallbackStatus);
-}
-
-/* EOF */
_____
Modified: trunk/reactos/ntoskrnl/ps/win32.c
--- trunk/reactos/ntoskrnl/ps/win32.c 2005-03-19 19:52:36 UTC (rev
14198)
+++ trunk/reactos/ntoskrnl/ps/win32.c 2005-03-19 20:26:46 UTC (rev
14199)
@@ -11,9 +11,9 @@
/* INCLUDES
****************************************************************/
#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
-/* TYPES
*******************************************************************/
-
/* GLOBALS
******************************************************************/
static PW32_PROCESS_CALLBACK PspWin32ProcessCallback = NULL;
@@ -28,6 +28,21 @@
extern OBJECT_CREATE_ROUTINE ExpDesktopObjectCreate;
extern OBJECT_DELETE_ROUTINE ExpDesktopObjectDelete;
+#ifndef ALEX_CB_REWRITE
+typedef struct _NTW32CALL_SAVED_STATE
+{
+ ULONG_PTR SavedStackLimit;
+ PVOID SavedStackBase;
+ PVOID SavedInitialStack;
+ PVOID CallerResult;
+ PULONG CallerResultLength;
+ PNTSTATUS CallbackStatus;
+ PKTRAP_FRAME SavedTrapFrame;
+ PVOID SavedCallbackStack;
+ PVOID SavedExceptionStack;
+} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
+#endif
+
/* FUNCTIONS
***************************************************************/
PW32THREAD STDCALL
@@ -162,4 +177,182 @@
}
}
+VOID
+STDCALL
+DumpEspData(ULONG Esp, ULONG ThLimit, ULONG ThStack, ULONG PcrLimit,
ULONG PcrStack, ULONG Esp0)
+{
+ DPRINT1("Current Esp: %p\n Thread Stack Limit: %p\n Thread Stack:
%p\n Pcr Limit: %p, Pcr Stack: %p\n Esp0 :%p\n",Esp, ThLimit, ThStack,
PcrLimit, PcrStack, Esp0) ;
+}
+
+ PVOID
+STDCALL
+ PsAllocateCallbackStack(ULONG StackSize)
+ {
+ PVOID KernelStack = NULL;
+ NTSTATUS Status;
+ PMEMORY_AREA StackArea;
+ ULONG i, j;
+ PHYSICAL_ADDRESS BoundaryAddressMultiple;
+ PPFN_TYPE Pages = alloca(sizeof(PFN_TYPE) * (StackSize /PAGE_SIZE));
+
+ DPRINT1("PsAllocateCallbackStack\n");
+ BoundaryAddressMultiple.QuadPart = 0;
+ StackSize = PAGE_ROUND_UP(StackSize);
+ MmLockAddressSpace(MmGetKernelAddressSpace());
+ Status = MmCreateMemoryArea(NULL,
+ MmGetKernelAddressSpace(),
+ MEMORY_AREA_KERNEL_STACK,
+ &KernelStack,
+ StackSize,
+ 0,
+ &StackArea,
+ FALSE,
+ FALSE,
+ BoundaryAddressMultiple);
+ MmUnlockAddressSpace(MmGetKernelAddressSpace());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create thread stack\n");
+ return(NULL);
+ }
+ for (i = 0; i < (StackSize / PAGE_SIZE); i++)
+ {
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
&Pages[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ for (j = 0; j < i; j++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[j]);
+ }
+ return(NULL);
+ }
+ }
+ Status = MmCreateVirtualMapping(NULL,
+ KernelStack,
+ PAGE_READWRITE,
+ Pages,
+ StackSize / PAGE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ for (i = 0; i < (StackSize / PAGE_SIZE); i++)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[i]);
+ }
+ return(NULL);
+ }
+ DPRINT1("PsAllocateCallbackStack %x\n", KernelStack);
+ return(KernelStack);
+}
+
+NTSTATUS
+STDCALL
+NtW32Call(IN ULONG RoutineIndex,
+ IN PVOID Argument,
+ IN ULONG ArgumentLength,
+ OUT PVOID* Result OPTIONAL,
+ OUT PULONG ResultLength OPTIONAL)
+{
+ NTSTATUS CallbackStatus;
+
+ DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength
%d)\n",
+ RoutineIndex, Argument, ArgumentLength);
+
+ /* FIXME: SEH!!! */
+
+ /* Call kernel function */
+ CallbackStatus = KeUserModeCallback(RoutineIndex,
+ Argument,
+ ArgumentLength,
+ Result,
+ ResultLength);
+
+ /* Return the result */
+ return(CallbackStatus);
+}
+
+#ifndef ALEX_CB_REWRITE
+NTSTATUS STDCALL
+NtCallbackReturn (PVOID Result,
+ ULONG ResultLength,
+ NTSTATUS Status)
+{
+ PULONG OldStack;
+ PETHREAD Thread;
+ PNTSTATUS CallbackStatus;
+ PULONG CallerResultLength;
+ PVOID* CallerResult;
+ PVOID InitialStack;
+ PVOID StackBase;
+ ULONG_PTR StackLimit;
+ KIRQL oldIrql;
+ PNTW32CALL_SAVED_STATE State;
+ PKTRAP_FRAME SavedTrapFrame;
+ PVOID SavedCallbackStack;
+ PVOID SavedExceptionStack;
+
+ PAGED_CODE();
+
+ Thread = PsGetCurrentThread();
+ if (Thread->Tcb.CallbackStack == NULL)
+ {
+ return(STATUS_NO_CALLBACK_ACTIVE);
+ }
+
+ OldStack = (PULONG)Thread->Tcb.CallbackStack;
+
+ /*
+ * Get the values that NtW32Call left on the inactive stack for us.
+ */
+ State = (PNTW32CALL_SAVED_STATE)OldStack[0];
+ CallbackStatus = State->CallbackStatus;
+ CallerResultLength = State->CallerResultLength;
+ CallerResult = State->CallerResult;
+ InitialStack = State->SavedInitialStack;
+ StackBase = State->SavedStackBase;
+ StackLimit = State->SavedStackLimit;
+ SavedTrapFrame = State->SavedTrapFrame;
+ SavedCallbackStack = State->SavedCallbackStack;
+ SavedExceptionStack = State->SavedExceptionStack;
+
+ /*
+ * Copy the callback status and the callback result to NtW32Call
+ */
+ *CallbackStatus = Status;
+ if (CallerResult != NULL && CallerResultLength != NULL)
+ {
+ if (Result == NULL)
+ {
+ *CallerResultLength = 0;
+ }
+ else
+ {
+ *CallerResultLength = min(ResultLength, *CallerResultLength);
+ RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
+ }
+ }
+
+ /*
+ * Restore the old stack.
+ */
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+ if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
+ ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
+ {
+ RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
+ (char*)Thread->Tcb.InitialStack -
sizeof(FX_SAVE_AREA),
+ sizeof(FX_SAVE_AREA));
[truncated at 1000 lines; 15 more skipped]