Branch setupapi (again)
[reactos.git] / reactos / ntoskrnl / ex / win32k.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: kernel/ex/win32k.c
22 * PURPOSE: Executive Win32 subsystem support
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 04-06-2001 CSH Created
26 */
27
28 #include <ntoskrnl.h>
29 #define NDEBUG
30 #include <internal/debug.h>
31
32 /* DATA **********************************************************************/
33
34 #define WINSTA_ACCESSCLIPBOARD (0x4L)
35 #define WINSTA_ACCESSGLOBALATOMS (0x20L)
36 #define WINSTA_CREATEDESKTOP (0x8L)
37 #define WINSTA_ENUMDESKTOPS (0x1L)
38 #define WINSTA_ENUMERATE (0x100L)
39 #define WINSTA_EXITWINDOWS (0x40L)
40 #define WINSTA_READATTRIBUTES (0x2L)
41 #define WINSTA_READSCREEN (0x200L)
42 #define WINSTA_WRITEATTRIBUTES (0x10L)
43
44 #define DF_ALLOWOTHERACCOUNTHOOK (0x1L)
45 #define DESKTOP_CREATEMENU (0x4L)
46 #define DESKTOP_CREATEWINDOW (0x2L)
47 #define DESKTOP_ENUMERATE (0x40L)
48 #define DESKTOP_HOOKCONTROL (0x8L)
49 #define DESKTOP_JOURNALPLAYBACK (0x20L)
50 #define DESKTOP_JOURNALRECORD (0x10L)
51 #define DESKTOP_READOBJECTS (0x1L)
52 #define DESKTOP_SWITCHDESKTOP (0x100L)
53 #define DESKTOP_WRITEOBJECTS (0x80L)
54
55 POBJECT_TYPE EXPORTED ExWindowStationObjectType = NULL;
56 POBJECT_TYPE EXPORTED ExDesktopObjectType = NULL;
57
58 static GENERIC_MAPPING ExpWindowStationMapping = {
59 STANDARD_RIGHTS_READ | WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_READATTRIBUTES | WINSTA_READSCREEN,
60 STANDARD_RIGHTS_WRITE | WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES,
61 STANDARD_RIGHTS_EXECUTE | WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS,
62 STANDARD_RIGHTS_REQUIRED | WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS | WINSTA_CREATEDESKTOP |
63 WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |
64 WINSTA_READATTRIBUTES | WINSTA_READSCREEN | WINSTA_WRITEATTRIBUTES
65 };
66
67 static GENERIC_MAPPING ExpDesktopMapping = {
68 STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | DESKTOP_READOBJECTS,
69 STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL |
70 DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_WRITEOBJECTS,
71 STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
72 STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
73 DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
74 DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS
75 };
76
77 /* FUNCTIONS ****************************************************************/
78
79
80 NTSTATUS STDCALL
81 ExpWinStaObjectCreate(PVOID ObjectBody,
82 PVOID Parent,
83 PWSTR RemainingPath,
84 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
85 {
86 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)ObjectBody;
87 UNICODE_STRING UnicodeString;
88 NTSTATUS Status;
89
90 if (RemainingPath == NULL)
91 {
92 return STATUS_SUCCESS;
93 }
94
95 if (wcschr((RemainingPath + 1), '\\') != NULL)
96 {
97 return STATUS_UNSUCCESSFUL;
98 }
99
100 RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
101
102 DPRINT("Creating window station (0x%X) Name (%wZ)\n", WinSta, &UnicodeString);
103
104 Status = RtlCreateUnicodeString(&WinSta->Name, UnicodeString.Buffer);
105 if (!NT_SUCCESS(Status))
106 {
107 return Status;
108 }
109
110 KeInitializeSpinLock(&WinSta->Lock);
111
112 InitializeListHead(&WinSta->DesktopListHead);
113
114 #if 1
115 WinSta->AtomTable = NULL;
116 #endif
117
118 Status = RtlCreateAtomTable(37, &WinSta->AtomTable);
119 if (!NT_SUCCESS(Status))
120 {
121 RtlFreeUnicodeString(&WinSta->Name);
122 return Status;
123 }
124
125 WinSta->SystemMenuTemplate = (HANDLE)0;
126
127 DPRINT("Window station successfully created. Name (%wZ)\n", &WinSta->Name);
128
129 return STATUS_SUCCESS;
130 }
131
132 VOID STDCALL
133 ExpWinStaObjectDelete(PVOID DeletedObject)
134 {
135 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeletedObject;
136
137 DPRINT("Deleting window station (0x%X)\n", WinSta);
138
139 RtlDestroyAtomTable(WinSta->AtomTable);
140
141 RtlFreeUnicodeString(&WinSta->Name);
142 }
143
144 PVOID
145 ExpWinStaObjectFind(PWINSTATION_OBJECT WinStaObject,
146 PWSTR Name,
147 ULONG Attributes)
148 {
149 PLIST_ENTRY Current;
150 PDESKTOP_OBJECT CurrentObject;
151
152 DPRINT("WinStaObject (0x%X) Name (%wS)\n", WinStaObject, Name);
153
154 if (Name[0] == 0)
155 {
156 return NULL;
157 }
158
159 Current = WinStaObject->DesktopListHead.Flink;
160 while (Current != &WinStaObject->DesktopListHead)
161 {
162 CurrentObject = CONTAINING_RECORD(Current, DESKTOP_OBJECT, ListEntry);
163 DPRINT("Scanning %wZ for %wS\n", &CurrentObject->Name, Name);
164 if (Attributes & OBJ_CASE_INSENSITIVE)
165 {
166 if (_wcsicmp(CurrentObject->Name.Buffer, Name) == 0)
167 {
168 DPRINT("Found desktop at (0x%X)\n", CurrentObject);
169 return CurrentObject;
170 }
171 }
172 else
173 {
174 if (wcscmp(CurrentObject->Name.Buffer, Name) == 0)
175 {
176 DPRINT("Found desktop at (0x%X)\n", CurrentObject);
177 return CurrentObject;
178 }
179 }
180 Current = Current->Flink;
181 }
182
183 DPRINT("Returning NULL\n");
184
185 return NULL;
186 }
187
188 NTSTATUS STDCALL
189 ExpWinStaObjectParse(PVOID Object,
190 PVOID *NextObject,
191 PUNICODE_STRING FullPath,
192 PWSTR *Path,
193 ULONG Attributes)
194 {
195 PVOID FoundObject;
196 NTSTATUS Status;
197 PWSTR End;
198
199 DPRINT("Object (0x%X) Path (0x%X) *Path (%wS)\n", Object, Path, *Path);
200
201 *NextObject = NULL;
202
203 if ((Path == NULL) || ((*Path) == NULL))
204 {
205 return STATUS_SUCCESS;
206 }
207
208 End = wcschr((*Path) + 1, '\\');
209 if (End != NULL)
210 {
211 DPRINT("Name contains illegal characters\n");
212 return STATUS_UNSUCCESSFUL;
213 }
214
215 FoundObject = ExpWinStaObjectFind(Object, (*Path) + 1, Attributes);
216 if (FoundObject == NULL)
217 {
218 DPRINT("Name was not found\n");
219 return STATUS_UNSUCCESSFUL;
220 }
221
222 Status = ObReferenceObjectByPointer(
223 FoundObject,
224 STANDARD_RIGHTS_REQUIRED,
225 NULL,
226 UserMode);
227
228 *NextObject = FoundObject;
229 *Path = NULL;
230
231 return Status;
232 }
233
234 NTSTATUS STDCALL
235 ExpDesktopObjectCreate(PVOID ObjectBody,
236 PVOID Parent,
237 PWSTR RemainingPath,
238 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
239 {
240 PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
241 UNICODE_STRING UnicodeString;
242
243 if (RemainingPath == NULL)
244 {
245 return STATUS_SUCCESS;
246 }
247
248 if (wcschr((RemainingPath + 1), '\\') != NULL)
249 {
250 return STATUS_UNSUCCESSFUL;
251 }
252
253 RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
254
255 DPRINT("Creating desktop (0x%X) Name (%wZ)\n", Desktop, &UnicodeString);
256
257 KeInitializeSpinLock(&Desktop->Lock);
258
259 Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
260
261 /* Put the desktop on the window station's list of associcated desktops */
262 ExInterlockedInsertTailList(
263 &Desktop->WindowStation->DesktopListHead,
264 &Desktop->ListEntry,
265 &Desktop->WindowStation->Lock);
266
267 return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
268 }
269
270 VOID STDCALL
271 ExpDesktopObjectDelete(PVOID DeletedObject)
272 {
273 PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
274 KIRQL OldIrql;
275
276 DPRINT("Deleting desktop (0x%X)\n", Desktop);
277
278 /* Remove the desktop from the window station's list of associcated desktops */
279 KeAcquireSpinLock(&Desktop->WindowStation->Lock, &OldIrql);
280 RemoveEntryList(&Desktop->ListEntry);
281 KeReleaseSpinLock(&Desktop->WindowStation->Lock, OldIrql);
282
283 RtlFreeUnicodeString(&Desktop->Name);
284 }
285
286 VOID INIT_FUNCTION
287 ExpWin32kInit(VOID)
288 {
289 /* Create window station object type */
290 ExWindowStationObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
291 if (ExWindowStationObjectType == NULL)
292 {
293 CPRINT("Could not create window station object type\n");
294 KEBUGCHECK(0);
295 }
296
297 ExWindowStationObjectType->Tag = TAG('W', 'I', 'N', 'S');
298 ExWindowStationObjectType->TotalObjects = 0;
299 ExWindowStationObjectType->TotalHandles = 0;
300 ExWindowStationObjectType->MaxObjects = ULONG_MAX;
301 ExWindowStationObjectType->MaxHandles = ULONG_MAX;
302 ExWindowStationObjectType->PagedPoolCharge = 0;
303 ExWindowStationObjectType->NonpagedPoolCharge = sizeof(WINSTATION_OBJECT);
304 ExWindowStationObjectType->Mapping = &ExpWindowStationMapping;
305 ExWindowStationObjectType->Dump = NULL;
306 ExWindowStationObjectType->Open = NULL;
307 ExWindowStationObjectType->Close = NULL;
308 ExWindowStationObjectType->Delete = ExpWinStaObjectDelete;
309 ExWindowStationObjectType->Parse = ExpWinStaObjectParse;
310 ExWindowStationObjectType->Security = NULL;
311 ExWindowStationObjectType->QueryName = NULL;
312 ExWindowStationObjectType->OkayToClose = NULL;
313 ExWindowStationObjectType->Create = ExpWinStaObjectCreate;
314 ExWindowStationObjectType->DuplicationNotify = NULL;
315 RtlRosInitUnicodeStringFromLiteral(&ExWindowStationObjectType->TypeName, L"WindowStation");
316
317 ObpCreateTypeObject(ExWindowStationObjectType);
318
319 /* Create desktop object type */
320 ExDesktopObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
321 if (ExDesktopObjectType == NULL)
322 {
323 CPRINT("Could not create desktop object type\n");
324 KEBUGCHECK(0);
325 }
326
327 ExDesktopObjectType->Tag = TAG('D', 'E', 'S', 'K');
328 ExDesktopObjectType->TotalObjects = 0;
329 ExDesktopObjectType->TotalHandles = 0;
330 ExDesktopObjectType->MaxObjects = ULONG_MAX;
331 ExDesktopObjectType->MaxHandles = ULONG_MAX;
332 ExDesktopObjectType->PagedPoolCharge = 0;
333 ExDesktopObjectType->NonpagedPoolCharge = sizeof(DESKTOP_OBJECT);
334 ExDesktopObjectType->Mapping = &ExpDesktopMapping;
335 ExDesktopObjectType->Dump = NULL;
336 ExDesktopObjectType->Open = NULL;
337 ExDesktopObjectType->Close = NULL;
338 ExDesktopObjectType->Delete = ExpDesktopObjectDelete;
339 ExDesktopObjectType->Parse = NULL;
340 ExDesktopObjectType->Security = NULL;
341 ExDesktopObjectType->QueryName = NULL;
342 ExDesktopObjectType->OkayToClose = NULL;
343 ExDesktopObjectType->Create = ExpDesktopObjectCreate;
344 ExDesktopObjectType->DuplicationNotify = NULL;
345 RtlRosInitUnicodeStringFromLiteral(&ExDesktopObjectType->TypeName, L"Desktop");
346
347 ObpCreateTypeObject(ExDesktopObjectType);
348 }
349
350 /* EOF */