xref: /reactos/ntoskrnl/ps/win32.c (revision c2c66aff)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/ps/win32.c
5  * PURPOSE:         Process Manager: Win32K Initialization and Support
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ****************************************************************/
10 
11 #include <ntoskrnl.h>
12 #include <winerror.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* GLOBALS ******************************************************************/
17 
18 PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout = NULL;
19 PKWIN32_THREAD_CALLOUT PspW32ThreadCallout = NULL;
20 PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch = NULL;
21 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectParse;
22 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectDelete;
23 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectOkToClose;
24 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOkToClose;
25 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectDelete;
26 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOpen;
27 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectClose;
28 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
29 
30 /* PRIVATE FUNCTIONS *********************************************************/
31 
32 NTSTATUS
33 NTAPI
PsConvertToGuiThread(VOID)34 PsConvertToGuiThread(VOID)
35 {
36     ULONG_PTR NewStack;
37     PVOID OldStack;
38     PETHREAD Thread = PsGetCurrentThread();
39     PEPROCESS Process = PsGetCurrentProcess();
40     NTSTATUS Status;
41     PAGED_CODE();
42 
43     /* Validate the previous mode */
44     if (KeGetPreviousMode() == KernelMode) return STATUS_INVALID_PARAMETER;
45 
46     /* If no win32k, crashes later */
47     ASSERT(PspW32ProcessCallout != NULL);
48 
49     /* Make sure win32k is here */
50     if (!PspW32ProcessCallout) return STATUS_ACCESS_DENIED;
51 
52     /* Make sure it's not already win32 */
53     if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
54     {
55         /* We're already a win32 thread */
56         return STATUS_ALREADY_WIN32;
57     }
58 
59     /* Check if we don't already have a kernel-mode stack */
60     if (!Thread->Tcb.LargeStack)
61     {
62         /* We don't create one */
63         NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE, 0);
64         if (!NewStack)
65         {
66             /* Panic in user-mode */
67             NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
68             return STATUS_NO_MEMORY;
69         }
70 
71         /* We're about to switch stacks. Enter a guarded region */
72         KeEnterGuardedRegion();
73 
74         /* Switch stacks */
75         OldStack = KeSwitchKernelStack((PVOID)NewStack,
76                                        (PVOID)(NewStack - KERNEL_STACK_SIZE));
77 
78         /* Leave the guarded region */
79         KeLeaveGuardedRegion();
80 
81         /* Delete the old stack */
82         MmDeleteKernelStack(OldStack, FALSE);
83     }
84 
85     /* Always do the process callout! */
86     Status = PspW32ProcessCallout(Process, TRUE);
87     if (!NT_SUCCESS(Status)) return Status;
88 
89     /* Set the new service table */
90     Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
91     ASSERT(Thread->Tcb.Win32Thread == 0);
92 
93     /* Tell Win32k about our thread */
94     Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize);
95     if (!NT_SUCCESS(Status))
96     {
97         /* Revert our table */
98         Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
99     }
100 
101     /* Return status */
102     return Status;
103 }
104 
105 /* PUBLIC FUNCTIONS **********************************************************/
106 
107 /*
108  * @implemented
109  */
110 VOID
111 NTAPI
PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData)112 PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData)
113 {
114     /* Setup the callback pointers */
115     PspW32ProcessCallout = CalloutData->ProcessCallout;
116     PspW32ThreadCallout = CalloutData->ThreadCallout;
117     ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
118     ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
119     ExpWindowStationObjectOkToClose = CalloutData->WindowStationOkToCloseProcedure;
120     ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure;
121     ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
122     ExpDesktopObjectOpen = CalloutData->DesktopOpenProcedure;
123     ExpDesktopObjectClose = CalloutData->DesktopCloseProcedure;
124     PopEventCallout = CalloutData->PowerEventCallout;
125     KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine;
126 }
127 
128 /* EOF */
129