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