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