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