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@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@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@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@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]