xref: /reactos/ntoskrnl/ex/win32k.c (revision 53221834)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel
4  * FILE:            ntoskrnl/ex/win32k.c
5  * PURPOSE:         Executive Win32 Object Support (Desktop/WinStation)
6  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7  */
8 
9 #include <ntoskrnl.h>
10 #define NDEBUG
11 #include <debug.h>
12 
13 typedef struct _WIN32_KERNEL_OBJECT_HEADER
14 {
15     ULONG SessionId;
16 } WIN32_KERNEL_OBJECT_HEADER, *PWIN32_KERNEL_OBJECT_HEADER;
17 
18 
19 /* DATA **********************************************************************/
20 
21 POBJECT_TYPE ExWindowStationObjectType = NULL;
22 POBJECT_TYPE ExDesktopObjectType = NULL;
23 
24 GENERIC_MAPPING ExpWindowStationMapping =
25 {
26     STANDARD_RIGHTS_READ,
27     STANDARD_RIGHTS_WRITE,
28     STANDARD_RIGHTS_EXECUTE,
29     STANDARD_RIGHTS_REQUIRED
30 };
31 
32 GENERIC_MAPPING ExpDesktopMapping =
33 {
34     STANDARD_RIGHTS_READ,
35     STANDARD_RIGHTS_WRITE,
36     STANDARD_RIGHTS_EXECUTE,
37     STANDARD_RIGHTS_REQUIRED
38 };
39 
40 PKWIN32_SESSION_CALLOUT ExpWindowStationObjectParse = NULL;
41 PKWIN32_SESSION_CALLOUT ExpWindowStationObjectDelete = NULL;
42 PKWIN32_SESSION_CALLOUT ExpWindowStationObjectOkToClose = NULL;
43 PKWIN32_SESSION_CALLOUT ExpDesktopObjectOkToClose = NULL;
44 PKWIN32_SESSION_CALLOUT ExpDesktopObjectDelete = NULL;
45 PKWIN32_SESSION_CALLOUT ExpDesktopObjectOpen = NULL;
46 PKWIN32_SESSION_CALLOUT ExpDesktopObjectClose = NULL;
47 
48 /* FUNCTIONS ****************************************************************/
49 
50 NTSTATUS
51 NTAPI
52 ExpWin32SessionCallout(
53     _In_ PVOID Object,
54     _In_ PKWIN32_SESSION_CALLOUT CalloutProcedure,
55     _Inout_opt_ PVOID Parameter)
56 {
57     PWIN32_KERNEL_OBJECT_HEADER Win32ObjectHeader;
58     PVOID SessionEntry = NULL;
59     KAPC_STATE ApcState;
60     NTSTATUS Status;
61 
62     /* The objects have a common header. And the kernel accesses it!
63        Thanks MS for this kind of retarded "design"! */
64     Win32ObjectHeader = Object;
65 
66     /* Check if we are not already in the correct session */
67     if (!PsGetCurrentProcess()->ProcessInSession ||
68         (PsGetCurrentProcessSessionId() != Win32ObjectHeader->SessionId))
69     {
70         /* Get the session from the objects session Id */
71         DPRINT("SessionId == %d\n", Win32ObjectHeader->SessionId);
72         SessionEntry = MmGetSessionById(Win32ObjectHeader->SessionId);
73         if (SessionEntry == NULL)
74         {
75             /* The requested session does not even exist! */
76             ASSERT(FALSE);
77             return STATUS_NOT_FOUND;
78         }
79 
80         /* Attach to the session */
81         Status = MmAttachSession(SessionEntry, &ApcState);
82         if (!NT_SUCCESS(Status))
83         {
84             DPRINT1("Could not attach to 0x%p, object %p, callout 0x%p\n",
85                     SessionEntry,
86                     Win32ObjectHeader,
87                     CalloutProcedure);
88 
89             /* Cleanup and return */
90             MmQuitNextSession(SessionEntry);
91             ASSERT(FALSE);
92             return Status;
93         }
94     }
95 
96     /* Call the callout routine */
97     Status = CalloutProcedure(Parameter);
98 
99     /* Check if we have a session */
100     if (SessionEntry != NULL)
101     {
102         /* Detach from the session and quit using it */
103         MmDetachSession(SessionEntry, &ApcState);
104         MmQuitNextSession(SessionEntry);
105     }
106 
107     /* Return the callback status */
108     return Status;
109 }
110 
111 BOOLEAN
112 NTAPI
113 ExpDesktopOkToClose( IN PEPROCESS Process OPTIONAL,
114                      IN PVOID Object,
115                      IN HANDLE Handle,
116                      IN KPROCESSOR_MODE AccessMode)
117 {
118     WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
119     NTSTATUS Status;
120 
121     Parameters.Process = Process;
122     Parameters.Object = Object;
123     Parameters.Handle = Handle;
124     Parameters.PreviousMode = AccessMode;
125 
126     Status = ExpWin32SessionCallout(Object,
127                                     ExpDesktopObjectOkToClose,
128                                     &Parameters);
129 
130     return NT_SUCCESS(Status);
131 }
132 
133 BOOLEAN
134 NTAPI
135 ExpWindowStationOkToClose( IN PEPROCESS Process OPTIONAL,
136                      IN PVOID Object,
137                      IN HANDLE Handle,
138                      IN KPROCESSOR_MODE AccessMode)
139 {
140     WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
141     NTSTATUS Status;
142 
143     Parameters.Process = Process;
144     Parameters.Object = Object;
145     Parameters.Handle = Handle;
146     Parameters.PreviousMode = AccessMode;
147 
148     Status = ExpWin32SessionCallout(Object,
149                                     ExpWindowStationObjectOkToClose,
150                                     &Parameters);
151 
152     return NT_SUCCESS(Status);
153 }
154 
155 VOID
156 NTAPI
157 ExpWinStaObjectDelete(PVOID DeletedObject)
158 {
159     WIN32_DELETEMETHOD_PARAMETERS Parameters;
160 
161     /* Fill out the callback structure */
162     Parameters.Object = DeletedObject;
163 
164     ExpWin32SessionCallout(DeletedObject,
165                            ExpWindowStationObjectDelete,
166                            &Parameters);
167 }
168 
169 NTSTATUS
170 NTAPI
171 ExpWinStaObjectParse(IN PVOID ParseObject,
172                      IN PVOID ObjectType,
173                      IN OUT PACCESS_STATE AccessState,
174                      IN KPROCESSOR_MODE AccessMode,
175                      IN ULONG Attributes,
176                      IN OUT PUNICODE_STRING CompleteName,
177                      IN OUT PUNICODE_STRING RemainingName,
178                      IN OUT PVOID Context OPTIONAL,
179                      IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
180                      OUT PVOID *Object)
181 {
182     WIN32_PARSEMETHOD_PARAMETERS Parameters;
183 
184     /* Fill out the callback structure */
185     Parameters.ParseObject = ParseObject;
186     Parameters.ObjectType = ObjectType;
187     Parameters.AccessState = AccessState;
188     Parameters.AccessMode = AccessMode;
189     Parameters.Attributes = Attributes;
190     Parameters.CompleteName = CompleteName;
191     Parameters.RemainingName = RemainingName;
192     Parameters.Context = Context;
193     Parameters.SecurityQos = SecurityQos;
194     Parameters.Object = Object;
195 
196     return ExpWin32SessionCallout(ParseObject,
197                                   ExpWindowStationObjectParse,
198                                   &Parameters);
199 }
200 VOID
201 NTAPI
202 ExpDesktopDelete(PVOID DeletedObject)
203 {
204     WIN32_DELETEMETHOD_PARAMETERS Parameters;
205 
206     /* Fill out the callback structure */
207     Parameters.Object = DeletedObject;
208 
209     ExpWin32SessionCallout(DeletedObject,
210                            ExpDesktopObjectDelete,
211                            &Parameters);
212 }
213 
214 NTSTATUS
215 NTAPI
216 ExpDesktopOpen(IN OB_OPEN_REASON Reason,
217                IN PEPROCESS Process OPTIONAL,
218                IN PVOID ObjectBody,
219                IN ACCESS_MASK GrantedAccess,
220                IN ULONG HandleCount)
221 {
222     WIN32_OPENMETHOD_PARAMETERS Parameters;
223 
224     Parameters.OpenReason = Reason;
225     Parameters.Process = Process;
226     Parameters.Object = ObjectBody;
227     Parameters.GrantedAccess = GrantedAccess;
228     Parameters.HandleCount = HandleCount;
229 
230     return ExpWin32SessionCallout(ObjectBody,
231                                   ExpDesktopObjectOpen,
232                                   &Parameters);
233 }
234 
235 VOID
236 NTAPI
237 ExpDesktopClose(IN PEPROCESS Process OPTIONAL,
238                 IN PVOID Object,
239                 IN ACCESS_MASK GrantedAccess,
240                 IN ULONG ProcessHandleCount,
241                 IN ULONG SystemHandleCount)
242 {
243     WIN32_CLOSEMETHOD_PARAMETERS Parameters;
244 
245     Parameters.Process = Process;
246     Parameters.Object = Object;
247     Parameters.AccessMask = GrantedAccess;
248     Parameters.ProcessHandleCount = ProcessHandleCount;
249     Parameters.SystemHandleCount = SystemHandleCount;
250 
251     ExpWin32SessionCallout(Object,
252                            ExpDesktopObjectClose,
253                            &Parameters);
254 }
255 
256 CODE_SEG("INIT")
257 BOOLEAN
258 NTAPI
259 ExpWin32kInit(VOID)
260 {
261     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
262     UNICODE_STRING Name;
263     NTSTATUS Status;
264     DPRINT("Creating Win32 Object Types\n");
265 
266     /* Create the window station Object Type */
267     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
268     RtlInitUnicodeString(&Name, L"WindowStation");
269     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
270     ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping;
271     ObjectTypeInitializer.PoolType = NonPagedPool;
272     ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete;
273     ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse;
274     ObjectTypeInitializer.OkayToCloseProcedure = ExpWindowStationOkToClose;
275     ObjectTypeInitializer.SecurityRequired = TRUE;
276     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK |
277                                               OBJ_PERMANENT |
278                                               OBJ_EXCLUSIVE;
279     ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_REQUIRED;
280     Status = ObCreateObjectType(&Name,
281                                 &ObjectTypeInitializer,
282                                 NULL,
283                                 &ExWindowStationObjectType);
284     if (!NT_SUCCESS(Status)) return FALSE;
285 
286     /* Create desktop object type */
287     RtlInitUnicodeString(&Name, L"Desktop");
288     ObjectTypeInitializer.GenericMapping = ExpDesktopMapping;
289     ObjectTypeInitializer.DeleteProcedure = ExpDesktopDelete;
290     ObjectTypeInitializer.ParseProcedure = NULL;
291     ObjectTypeInitializer.OkayToCloseProcedure = ExpDesktopOkToClose;
292     ObjectTypeInitializer.OpenProcedure = ExpDesktopOpen;
293     ObjectTypeInitializer.CloseProcedure = ExpDesktopClose;
294     Status = ObCreateObjectType(&Name,
295                                 &ObjectTypeInitializer,
296                                 NULL,
297                                 &ExDesktopObjectType);
298     if (!NT_SUCCESS(Status)) return FALSE;
299 
300     return TRUE;
301 }
302 
303 /* EOF */
304