17600fd8bc20cd569a2041ed1acf14fc35babfb8
[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 #include <limits.h>
28 #include <ddk/ntddk.h>
29 #include <internal/ex.h>
30 #include <internal/ob.h>
31 #include <wchar.h>
32
33 #define NDEBUG
34 #include <internal/debug.h>
35
36 /* DATA **********************************************************************/
37
38 POBJECT_TYPE EXPORTED ExWindowStationObjectType = NULL;
39 POBJECT_TYPE EXPORTED ExDesktopObjectType = NULL;
40
41 static GENERIC_MAPPING ExpWindowStationMapping = {
42 FILE_GENERIC_READ,
43 FILE_GENERIC_WRITE,
44 FILE_GENERIC_EXECUTE,
45 FILE_ALL_ACCESS };
46
47 static GENERIC_MAPPING ExpDesktopMapping = {
48 FILE_GENERIC_READ,
49 FILE_GENERIC_WRITE,
50 FILE_GENERIC_EXECUTE,
51 FILE_ALL_ACCESS };
52
53 /* FUNCTIONS ****************************************************************/
54
55
56 NTSTATUS STDCALL
57 ExpWinStaObjectCreate(PVOID ObjectBody,
58 PVOID Parent,
59 PWSTR RemainingPath,
60 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
61 {
62 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)ObjectBody;
63 UNICODE_STRING UnicodeString;
64 NTSTATUS Status;
65
66 if (RemainingPath == NULL)
67 {
68 return STATUS_SUCCESS;
69 }
70
71 if (wcschr((RemainingPath + 1), '\\') != NULL)
72 {
73 return STATUS_UNSUCCESSFUL;
74 }
75
76 RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
77
78 DPRINT("Creating window station (0x%X) Name (%wZ)\n", WinSta, &UnicodeString);
79
80 Status = RtlCreateUnicodeString(&WinSta->Name, UnicodeString.Buffer);
81 if (!NT_SUCCESS(Status))
82 {
83 return Status;
84 }
85
86 KeInitializeSpinLock(&WinSta->Lock);
87
88 InitializeListHead(&WinSta->DesktopListHead);
89
90 #if 1
91 WinSta->AtomTable = NULL;
92 #endif
93
94 Status = RtlCreateAtomTable(37, &WinSta->AtomTable);
95 if (!NT_SUCCESS(Status))
96 {
97 RtlFreeUnicodeString(&WinSta->Name);
98 return Status;
99 }
100
101 WinSta->SystemMenuTemplate = (HANDLE)0;
102
103 DPRINT("Window station successfully created. Name (%wZ)\n", &WinSta->Name);
104
105 return STATUS_SUCCESS;
106 }
107
108 VOID STDCALL
109 ExpWinStaObjectDelete(PVOID DeletedObject)
110 {
111 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeletedObject;
112
113 DPRINT("Deleting window station (0x%X)\n", WinSta);
114
115 RtlDestroyAtomTable(WinSta->AtomTable);
116
117 RtlFreeUnicodeString(&WinSta->Name);
118 }
119
120 PVOID
121 ExpWinStaObjectFind(PWINSTATION_OBJECT WinStaObject,
122 PWSTR Name,
123 ULONG Attributes)
124 {
125 PLIST_ENTRY Current;
126 PDESKTOP_OBJECT CurrentObject;
127
128 DPRINT("WinStaObject (0x%X) Name (%wS)\n", WinStaObject, Name);
129
130 if (Name[0] == 0)
131 {
132 return NULL;
133 }
134
135 Current = WinStaObject->DesktopListHead.Flink;
136 while (Current != &WinStaObject->DesktopListHead)
137 {
138 CurrentObject = CONTAINING_RECORD(Current, DESKTOP_OBJECT, ListEntry);
139 DPRINT("Scanning %wZ for %wS\n", &CurrentObject->Name, Name);
140 if (Attributes & OBJ_CASE_INSENSITIVE)
141 {
142 if (_wcsicmp(CurrentObject->Name.Buffer, Name) == 0)
143 {
144 DPRINT("Found desktop at (0x%X)\n", CurrentObject);
145 return CurrentObject;
146 }
147 }
148 else
149 {
150 if (wcscmp(CurrentObject->Name.Buffer, Name) == 0)
151 {
152 DPRINT("Found desktop at (0x%X)\n", CurrentObject);
153 return CurrentObject;
154 }
155 }
156 Current = Current->Flink;
157 }
158
159 DPRINT("Returning NULL\n");
160
161 return NULL;
162 }
163
164 NTSTATUS STDCALL
165 ExpWinStaObjectParse(PVOID Object,
166 PVOID *NextObject,
167 PUNICODE_STRING FullPath,
168 PWSTR *Path,
169 ULONG Attributes)
170 {
171 PVOID FoundObject;
172 NTSTATUS Status;
173 PWSTR End;
174
175 DPRINT("Object (0x%X) Path (0x%X) *Path (%wS)\n", Object, Path, *Path);
176
177 *NextObject = NULL;
178
179 if ((Path == NULL) || ((*Path) == NULL))
180 {
181 return STATUS_SUCCESS;
182 }
183
184 End = wcschr((*Path) + 1, '\\');
185 if (End != NULL)
186 {
187 DPRINT("Name contains illegal characters\n");
188 return STATUS_UNSUCCESSFUL;
189 }
190
191 FoundObject = ExpWinStaObjectFind(Object, (*Path) + 1, Attributes);
192 if (FoundObject == NULL)
193 {
194 DPRINT("Name was not found\n");
195 return STATUS_UNSUCCESSFUL;
196 }
197
198 Status = ObReferenceObjectByPointer(
199 FoundObject,
200 STANDARD_RIGHTS_REQUIRED,
201 NULL,
202 UserMode);
203
204 *NextObject = FoundObject;
205 *Path = NULL;
206
207 return Status;
208 }
209
210 NTSTATUS STDCALL
211 ExpDesktopObjectCreate(PVOID ObjectBody,
212 PVOID Parent,
213 PWSTR RemainingPath,
214 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
215 {
216 PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
217 UNICODE_STRING UnicodeString;
218
219 if (RemainingPath == NULL)
220 {
221 return STATUS_SUCCESS;
222 }
223
224 if (wcschr((RemainingPath + 1), '\\') != NULL)
225 {
226 return STATUS_UNSUCCESSFUL;
227 }
228
229 RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
230
231 DPRINT("Creating desktop (0x%X) Name (%wZ)\n", Desktop, &UnicodeString);
232
233 KeInitializeSpinLock(&Desktop->Lock);
234
235 Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
236
237 /* Put the desktop on the window station's list of associcated desktops */
238 ExInterlockedInsertTailList(
239 &Desktop->WindowStation->DesktopListHead,
240 &Desktop->ListEntry,
241 &Desktop->WindowStation->Lock);
242
243 return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
244 }
245
246 VOID STDCALL
247 ExpDesktopObjectDelete(PVOID DeletedObject)
248 {
249 PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
250 KIRQL OldIrql;
251
252 DPRINT("Deleting desktop (0x%X)\n", Desktop);
253
254 /* Remove the desktop from the window station's list of associcated desktops */
255 KeAcquireSpinLock(&Desktop->WindowStation->Lock, &OldIrql);
256 RemoveEntryList(&Desktop->ListEntry);
257 KeReleaseSpinLock(&Desktop->WindowStation->Lock, OldIrql);
258
259 RtlFreeUnicodeString(&Desktop->Name);
260 }
261
262 VOID INIT_FUNCTION
263 ExpWin32kInit(VOID)
264 {
265 /* Create window station object type */
266 ExWindowStationObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
267 if (ExWindowStationObjectType == NULL)
268 {
269 CPRINT("Could not create window station object type\n");
270 KEBUGCHECK(0);
271 }
272
273 ExWindowStationObjectType->Tag = TAG('W', 'I', 'N', 'S');
274 ExWindowStationObjectType->TotalObjects = 0;
275 ExWindowStationObjectType->TotalHandles = 0;
276 ExWindowStationObjectType->MaxObjects = ULONG_MAX;
277 ExWindowStationObjectType->MaxHandles = ULONG_MAX;
278 ExWindowStationObjectType->PagedPoolCharge = 0;
279 ExWindowStationObjectType->NonpagedPoolCharge = sizeof(WINSTATION_OBJECT);
280 ExWindowStationObjectType->Mapping = &ExpWindowStationMapping;
281 ExWindowStationObjectType->Dump = NULL;
282 ExWindowStationObjectType->Open = NULL;
283 ExWindowStationObjectType->Close = NULL;
284 ExWindowStationObjectType->Delete = ExpWinStaObjectDelete;
285 ExWindowStationObjectType->Parse = ExpWinStaObjectParse;
286 ExWindowStationObjectType->Security = NULL;
287 ExWindowStationObjectType->QueryName = NULL;
288 ExWindowStationObjectType->OkayToClose = NULL;
289 ExWindowStationObjectType->Create = ExpWinStaObjectCreate;
290 ExWindowStationObjectType->DuplicationNotify = NULL;
291 RtlInitUnicodeStringFromLiteral(&ExWindowStationObjectType->TypeName, L"WindowStation");
292
293 ObpCreateTypeObject(ExWindowStationObjectType);
294
295 /* Create desktop object type */
296 ExDesktopObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
297 if (ExDesktopObjectType == NULL)
298 {
299 CPRINT("Could not create desktop object type\n");
300 KEBUGCHECK(0);
301 }
302
303 ExDesktopObjectType->Tag = TAG('D', 'E', 'S', 'K');
304 ExDesktopObjectType->TotalObjects = 0;
305 ExDesktopObjectType->TotalHandles = 0;
306 ExDesktopObjectType->MaxObjects = ULONG_MAX;
307 ExDesktopObjectType->MaxHandles = ULONG_MAX;
308 ExDesktopObjectType->PagedPoolCharge = 0;
309 ExDesktopObjectType->NonpagedPoolCharge = sizeof(DESKTOP_OBJECT);
310 ExDesktopObjectType->Mapping = &ExpDesktopMapping;
311 ExDesktopObjectType->Dump = NULL;
312 ExDesktopObjectType->Open = NULL;
313 ExDesktopObjectType->Close = NULL;
314 ExDesktopObjectType->Delete = ExpDesktopObjectDelete;
315 ExDesktopObjectType->Parse = NULL;
316 ExDesktopObjectType->Security = NULL;
317 ExDesktopObjectType->QueryName = NULL;
318 ExDesktopObjectType->OkayToClose = NULL;
319 ExDesktopObjectType->Create = ExpDesktopObjectCreate;
320 ExDesktopObjectType->DuplicationNotify = NULL;
321 RtlInitUnicodeStringFromLiteral(&ExDesktopObjectType->TypeName, L"Desktop");
322
323 ObpCreateTypeObject(ExDesktopObjectType);
324 }
325
326 /* EOF */