- Fix MmCreateKernelStack to actually take into account the GuiStack parameter.
[reactos.git] / reactos / ntoskrnl / ps / win32.c
index f486707..36e394c 100644 (file)
@@ -41,6 +41,13 @@ typedef struct _NTW32CALL_SAVED_STATE
 } NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
 #endif
 
+PVOID
+STDCALL
+KeSwitchKernelStack(
+    IN PVOID StackBase,
+    IN PVOID StackLimit
+);
+
 /* FUNCTIONS ***************************************************************/
 
 /*
@@ -61,34 +68,93 @@ PsEstablishWin32Callouts(PW32_CALLOUT_DATA CalloutData)
 }
 
 NTSTATUS
-PsInitWin32Thread (PETHREAD Thread)
+NTAPI
+PsConvertToGuiThread(VOID)
 {
-    PEPROCESS Process;
-    NTSTATUS Status = STATUS_SUCCESS;
+    PVOID NewStack, OldStack;
+    PETHREAD Thread = PsGetCurrentThread();
+    PEPROCESS Process = PsGetCurrentProcess();
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Validate the previous mode */
+    if (KeGetPreviousMode() == KernelMode)
+    {
+        DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Make sure win32k is here */
+    if (!PspWin32ProcessCallback)
+    {
+        DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
+        return STATUS_ACCESS_DENIED;
+    }
 
-    Process = Thread->ThreadsProcess;
+    /* 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;
+    }
 
-    if (Process->Win32Process == NULL)
+    /* Check if we don't already have a kernel-mode stack */
+    if (!Thread->Tcb.LargeStack)
     {
-        if (PspWin32ProcessCallback != NULL)
+        /* We don't create one */
+        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 */
+        OldStack = KeSwitchKernelStack((PVOID)((ULONG_PTR)NewStack + 0x3000),
+                                       NewStack);
+
+        /* Leave the critical region */
+        KeLeaveCriticalRegion();
+
+        /* Delete the old stack */
+        //MmDeleteKernelStack(OldStack, FALSE);
     }
 
-    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)
 {
   if (Process->Win32Process == NULL)
@@ -105,6 +171,7 @@ PsTerminateWin32Process (PEPROCESS Process)
 
 
 VOID
+NTAPI
 PsTerminateWin32Thread (PETHREAD Thread)
 {
   if (Thread->Tcb.Win32Thread != NULL)
@@ -119,73 +186,6 @@ PsTerminateWin32Thread (PETHREAD Thread)
   }
 }
 
-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,
@@ -278,7 +278,7 @@ NtCallbackReturn (PVOID             Result,
    */
   KeRaiseIrql(HIGH_LEVEL, &oldIrql);
   if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
-      ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
+      &Thread->Tcb != KeGetCurrentPrcb()->NpxThread)
     {
       RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
                     (char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
@@ -295,6 +295,6 @@ NtCallbackReturn (PVOID             Result,
   /* Should never return. */
   KEBUGCHECK(0);
   return(STATUS_UNSUCCESSFUL);
-#endif
 }
+#endif
 /* EOF */