- Remove KiServiceCheck and implement PsConvertToGuiThread in its place. Has support for detecting and returning errors in case of invalid cases, currently disabled code for doing the required 4kb->12kb stack conversion, and handling certain failures.
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
Modified: trunk/reactos/ntoskrnl/ps/win32.c

Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S	2006-01-11 05:24:40 UTC (rev 20778)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S	2006-01-11 05:42:32 UTC (rev 20779)
@@ -614,7 +614,7 @@
     /* Set up Win32K Table */
     push edx
     push ebx
-    call _KiServiceCheck@0
+    call _PsConvertToGuiThread@0
 
     /* FIXME: Handle failure */
     pop eax

Modified: trunk/reactos/ntoskrnl/ke/kthread.c
--- trunk/reactos/ntoskrnl/ke/kthread.c	2006-01-11 05:24:40 UTC (rev 20778)
+++ trunk/reactos/ntoskrnl/ke/kthread.c	2006-01-11 05:42:32 UTC (rev 20779)
@@ -1466,21 +1466,6 @@
     return OldState;
 }
 
-VOID
-NTAPI
-KiServiceCheck(VOID)
-{
-    PKTHREAD Thread = KeGetCurrentThread();
-
-    /* Check if we need to inialize Win32 for this Thread */
-    if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
-
-        /* We do. Initialize it and save the new table */
-        Thread->ServiceTable = KeServiceDescriptorTableShadow;
-        PsInitWin32Thread((PETHREAD)Thread);
-    }
-}
-
 /*
  *
  * NOT EXPORTED

Modified: trunk/reactos/ntoskrnl/ps/win32.c
--- trunk/reactos/ntoskrnl/ps/win32.c	2006-01-11 05:24:40 UTC (rev 20778)
+++ trunk/reactos/ntoskrnl/ps/win32.c	2006-01-11 05:42:32 UTC (rev 20779)
@@ -41,6 +41,13 @@
 } NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
 #endif
 
+PVOID
+STDCALL
+KeSwitchKernelStack(
+    IN PVOID StackBase,
+    IN PVOID StackLimit
+);
+
 /* FUNCTIONS ***************************************************************/
 
 /*
@@ -62,33 +69,105 @@
 
 NTSTATUS
 NTAPI
-PsInitWin32Thread (PETHREAD Thread)
+PsConvertToGuiThread(VOID)
 {
-    PEPROCESS Process;
-    NTSTATUS Status = STATUS_SUCCESS;
+    //PVOID NewStack, OldStack;
+    PETHREAD Thread = PsGetCurrentThread();
+    PEPROCESS Process = PsGetCurrentProcess();
+    NTSTATUS Status;
+    PAGED_CODE();
 
-    Process = Thread->ThreadsProcess;
+    /* Validate the previous mode */
+    if (KeGetPreviousMode() == KernelMode)
+    {
+        DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
 
-    if (Process->Win32Process == NULL)
+    /* Make sure win32k is here */
+    if (!PspWin32ProcessCallback)
     {
-        if (PspWin32ProcessCallback != NULL)
+        DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    /* Make sure it's not already win32 */
+    if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
+    {
+        DPRINT1("Danger: Thread is already a win32 thread. Limit bypassed?\n");
+        return STATUS_ALREADY_WIN32;
+    }
+
+    /* Check if we don't already have a kernel-mode stack */
+#if 0
+    if (!Thread->Tcb.LargeStack)
+    {
+        /* We don't create one */
+        DPRINT1("Creating large stack\n");
+        NewStack = MmCreateKernelStack(TRUE);
+        if (!NewStack)
         {
-            Status = PspWin32ProcessCallback(Process, TRUE);
+            /* Panic in user-mode */
+            NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
+            return STATUS_NO_MEMORY;
         }
+
+        /* We're about to switch stacks. Enter a critical region */
+        KeEnterCriticalRegion();
+
+        /* Switch stacks */
+        DPRINT1("Switching stacks. NS IT, SL, SB, KS %p %p %p %p %p\n",
+                NewStack,
+                Thread->Tcb.InitialStack,
+                Thread->Tcb.StackLimit,
+                Thread->Tcb.StackBase,
+                Thread->Tcb.KernelStack);
+        OldStack = KeSwitchKernelStack((PVOID)((ULONG_PTR)NewStack + 0x3000),
+                                       NewStack);
+
+        /* Leave the critical region */
+        KeLeaveCriticalRegion();
+        DPRINT1("We made it!\n");
+
+        /* Delete the old stack */
+        //MmDeleteKernelStack(OldStack, FALSE);
+        DPRINT1("Old stack deleted. IT, SL, SB, KS %p %p %p %p\n",
+                Thread->Tcb.InitialStack,
+                Thread->Tcb.StackLimit,
+                Thread->Tcb.StackBase,
+                Thread->Tcb.KernelStack);
     }
+#endif
 
-    if (Thread->Tcb.Win32Thread == NULL)
+    /* This check is bizare. Check out win32k later */
+    if (!Process->Win32Process)
     {
-        if (PspWin32ThreadCallback != NULL)
+        /* Now tell win32k about us */
+        Status = PspWin32ProcessCallback(Process, TRUE);
+        if (!NT_SUCCESS(Status))
         {
-            Status = PspWin32ThreadCallback(Thread, TRUE);
+            DPRINT1("Danger: Win32k wasn't happy about us!\n");
+            return Status;
         }
     }
 
+    /* Set the new service table */
+    Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
+    ASSERT(Thread->Tcb.Win32Thread == 0);
+
+    /* Tell Win32k about our thread */
+    Status = PspWin32ThreadCallback(Thread, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Revert our table */
+        DPRINT1("Danger: Win32k wasn't happy about us!\n");
+        Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
+    }
+
+    /* Return status */
     return Status;
 }
 
-
 VOID
 NTAPI
 PsTerminateWin32Process (PEPROCESS Process)
@@ -122,72 +201,6 @@
   }
 }
 
-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(MmGetKernelAddressSpace(),
-                               MEMORY_AREA_KERNEL_STACK,
-                               &KernelStack,
-                               StackSize,
-                               PAGE_READWRITE,
-                               &StackArea,
-                               FALSE,
-                               0,
-                               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,