[CLT2012]
[reactos.git] / 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 #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_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse;
22 extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete;
23 extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose;
24 extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose;
25 extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete;
26 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
27
28 /* PRIVATE FUNCTIONS *********************************************************/
29
30 NTSTATUS
31 NTAPI
32 PsConvertToGuiThread(VOID)
33 {
34 ULONG_PTR NewStack;
35 PVOID OldStack;
36 PETHREAD Thread = PsGetCurrentThread();
37 PEPROCESS Process = PsGetCurrentProcess();
38 NTSTATUS Status;
39 PAGED_CODE();
40
41 /* Validate the previous mode */
42 if (KeGetPreviousMode() == KernelMode) return STATUS_INVALID_PARAMETER;
43
44 /* If no win32k, crashes later */
45 ASSERT(PspW32ProcessCallout != NULL);
46
47 /* Make sure win32k is here */
48 if (!PspW32ProcessCallout) return STATUS_ACCESS_DENIED;
49
50 /* Make sure it's not already win32 */
51 if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
52 {
53 /* We're already a win32 thread */
54 return STATUS_ALREADY_WIN32;
55 }
56
57 /* Check if we don't already have a kernel-mode stack */
58 if (!Thread->Tcb.LargeStack)
59 {
60 /* We don't create one */
61 NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE, 0);
62 if (!NewStack)
63 {
64 /* Panic in user-mode */
65 NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
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 /* This check is bizare. Check out win32k later */
84 if (!Process->Win32Process)
85 {
86 /* Now tell win32k about us */
87 Status = PspW32ProcessCallout(Process, TRUE);
88 if (!NT_SUCCESS(Status)) return Status;
89 }
90
91 /* Set the new service table */
92 Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
93 ASSERT(Thread->Tcb.Win32Thread == 0);
94
95 /* Tell Win32k about our thread */
96 Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize);
97 if (!NT_SUCCESS(Status))
98 {
99 /* Revert our table */
100 Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
101 }
102
103 /* Return status */
104 return Status;
105 }
106
107 /* PUBLIC FUNCTIONS **********************************************************/
108
109 /*
110 * @implemented
111 */
112 VOID
113 NTAPI
114 PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData)
115 {
116 /* Setup the callback pointers */
117 PspW32ProcessCallout = CalloutData->ProcessCallout;
118 PspW32ThreadCallout = CalloutData->ThreadCallout;
119 ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
120 ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
121 ExpWindowStationObjectOkToClose = CalloutData->WindowStationOkToCloseProcedure;
122 ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure;
123 ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
124 PopEventCallout = CalloutData->PowerEventCallout;
125 KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine;
126 }
127
128 NTSTATUS
129 NTAPI
130 NtW32Call(IN ULONG RoutineIndex,
131 IN PVOID Argument,
132 IN ULONG ArgumentLength,
133 OUT PVOID* Result,
134 OUT PULONG ResultLength)
135 {
136 PVOID RetResult;
137 ULONG RetResultLength;
138 NTSTATUS Status;
139 ASSERT(KeGetPreviousMode() != KernelMode);
140
141 /* Enter SEH for probing */
142 _SEH2_TRY
143 {
144 /* Probe arguments */
145 ProbeForWritePointer(Result);
146 ProbeForWriteUlong(ResultLength);
147 }
148 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
149 {
150 /* Return the exception code */
151 _SEH2_YIELD(return _SEH2_GetExceptionCode());
152 }
153 _SEH2_END;
154
155 /* Call kernel function */
156 Status = KeUserModeCallback(RoutineIndex,
157 Argument,
158 ArgumentLength,
159 &RetResult,
160 &RetResultLength);
161 if (NT_SUCCESS(Status))
162 {
163 /* Enter SEH for write back */
164 _SEH2_TRY
165 {
166 /* Return results to user mode */
167 *Result = RetResult;
168 *ResultLength = RetResultLength;
169 }
170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
171 {
172 /* Get the exception code */
173 Status = _SEH2_GetExceptionCode();
174 }
175 _SEH2_END;
176 }
177
178 /* Return the result */
179 return Status;
180 }
181
182 /* EOF */