update for HEAD-2003091401
[reactos.git] / 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 <wchar.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   WinSta->SystemMenuTemplate = (HANDLE)0;
101
102   DPRINT("Window station successfully created. Name (%wZ)\n", &WinSta->Name);
103
104   return STATUS_SUCCESS;
105 }
106
107 VOID STDCALL
108 ExpWinStaObjectDelete(PVOID DeletedObject)
109 {
110   PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeletedObject;
111
112   DPRINT("Deleting window station (0x%X)\n", WinSta);
113
114   RtlDestroyAtomTable(WinSta->AtomTable);
115
116   RtlFreeUnicodeString(&WinSta->Name);
117 }
118
119 PVOID
120 ExpWinStaObjectFind(PWINSTATION_OBJECT WinStaObject,
121                     PWSTR Name,
122                     ULONG Attributes)
123 {
124   PLIST_ENTRY Current;
125   PDESKTOP_OBJECT CurrentObject;
126
127   DPRINT("WinStaObject (0x%X)  Name (%wS)\n", WinStaObject, Name);
128
129   if (Name[0] == 0)
130   {
131     return NULL;
132   }
133
134   Current = WinStaObject->DesktopListHead.Flink;
135   while (Current != &WinStaObject->DesktopListHead)
136   {
137     CurrentObject = CONTAINING_RECORD(Current, DESKTOP_OBJECT, ListEntry);
138     DPRINT("Scanning %wZ for %wS\n", &CurrentObject->Name, Name);
139     if (Attributes & OBJ_CASE_INSENSITIVE)
140     {
141       if (_wcsicmp(CurrentObject->Name.Buffer, Name) == 0)
142       {
143         DPRINT("Found desktop at (0x%X)\n", CurrentObject);
144         return CurrentObject;
145       }
146     }
147     else
148     {
149       if (wcscmp(CurrentObject->Name.Buffer, Name) == 0)
150       {
151         DPRINT("Found desktop at (0x%X)\n", CurrentObject);
152         return CurrentObject;
153       }
154     }
155     Current = Current->Flink;
156   }
157
158   DPRINT("Returning NULL\n");
159
160   return NULL;
161 }
162
163 NTSTATUS STDCALL
164 ExpWinStaObjectParse(PVOID Object,
165                      PVOID *NextObject,
166                      PUNICODE_STRING FullPath,
167                      PWSTR *Path,
168                      ULONG Attributes)
169 {
170   PVOID FoundObject;
171   NTSTATUS Status;
172   PWSTR End;
173
174   DPRINT("Object (0x%X)  Path (0x%X)  *Path (%wS)\n", Object, Path, *Path);
175
176   *NextObject = NULL;
177
178   if ((Path == NULL) || ((*Path) == NULL))
179   {
180     return STATUS_SUCCESS;
181   }
182
183   End = wcschr((*Path) + 1, '\\');
184   if (End != NULL)
185   {
186     DPRINT("Name contains illegal characters\n");
187     return STATUS_UNSUCCESSFUL;
188   }
189
190   FoundObject = ExpWinStaObjectFind(Object, (*Path) + 1, Attributes);
191   if (FoundObject == NULL)
192   {
193     DPRINT("Name was not found\n");
194     return STATUS_UNSUCCESSFUL;
195   }
196
197   Status = ObReferenceObjectByPointer(
198     FoundObject,
199     STANDARD_RIGHTS_REQUIRED,
200     NULL,
201     UserMode);
202
203   *Path = NULL;
204
205   return Status;
206 }
207
208 NTSTATUS STDCALL
209 ExpDesktopObjectCreate(PVOID ObjectBody,
210                        PVOID Parent,
211                        PWSTR RemainingPath,
212                        struct _OBJECT_ATTRIBUTES* ObjectAttributes)
213 {
214   PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
215   UNICODE_STRING UnicodeString;
216
217   if (RemainingPath == NULL)
218         {
219                 return STATUS_SUCCESS;
220         }
221
222   if (wcschr((RemainingPath + 1), '\\') != NULL)
223         {
224                 return STATUS_UNSUCCESSFUL;
225         }
226
227   RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
228
229   DPRINT("Creating desktop (0x%X)  Name (%wZ)\n", Desktop, &UnicodeString);
230
231   KeInitializeSpinLock(&Desktop->Lock);
232
233   Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
234
235   /* Put the desktop on the window station's list of associcated desktops */
236   ExInterlockedInsertTailList(
237     &Desktop->WindowStation->DesktopListHead,
238     &Desktop->ListEntry,
239     &Desktop->WindowStation->Lock);
240
241   return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
242 }
243
244 VOID STDCALL
245 ExpDesktopObjectDelete(PVOID DeletedObject)
246 {
247   PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
248   KIRQL OldIrql;
249
250   DPRINT("Deleting desktop (0x%X)\n", Desktop);
251
252   /* Remove the desktop from the window station's list of associcated desktops */
253   KeAcquireSpinLock(&Desktop->WindowStation->Lock, &OldIrql);
254   RemoveEntryList(&Desktop->ListEntry);
255   KeReleaseSpinLock(&Desktop->WindowStation->Lock, OldIrql);
256
257   RtlFreeUnicodeString(&Desktop->Name);
258 }
259
260 VOID
261 ExpWin32kInit(VOID)
262 {
263   /* Create window station object type */
264   ExWindowStationObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
265   if (ExWindowStationObjectType == NULL)
266   {
267     CPRINT("Could not create window station object type\n");
268     KEBUGCHECK(0);
269   }
270
271   ExWindowStationObjectType->Tag = TAG('W', 'I', 'N', 'S');
272   ExWindowStationObjectType->TotalObjects = 0;
273   ExWindowStationObjectType->TotalHandles = 0;
274   ExWindowStationObjectType->MaxObjects = ULONG_MAX;
275   ExWindowStationObjectType->MaxHandles = ULONG_MAX;
276   ExWindowStationObjectType->PagedPoolCharge = 0;
277   ExWindowStationObjectType->NonpagedPoolCharge = sizeof(WINSTATION_OBJECT);
278   ExWindowStationObjectType->Mapping = &ExpWindowStationMapping;
279   ExWindowStationObjectType->Dump = NULL;
280   ExWindowStationObjectType->Open = NULL;
281   ExWindowStationObjectType->Close = NULL;
282   ExWindowStationObjectType->Delete = ExpWinStaObjectDelete;
283   ExWindowStationObjectType->Parse = ExpWinStaObjectParse;
284   ExWindowStationObjectType->Security = NULL;
285   ExWindowStationObjectType->QueryName = NULL;
286   ExWindowStationObjectType->OkayToClose = NULL;
287   ExWindowStationObjectType->Create = ExpWinStaObjectCreate;
288   ExWindowStationObjectType->DuplicationNotify = NULL;
289   RtlInitUnicodeStringFromLiteral(&ExWindowStationObjectType->TypeName, L"WindowStation");
290
291   /* Create desktop object type */
292   ExDesktopObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
293   if (ExDesktopObjectType == NULL)
294   {
295     CPRINT("Could not create desktop object type\n");
296     KEBUGCHECK(0);
297   }
298
299   ExDesktopObjectType->Tag = TAG('D', 'E', 'S', 'K');
300   ExDesktopObjectType->TotalObjects = 0;
301   ExDesktopObjectType->TotalHandles = 0;
302   ExDesktopObjectType->MaxObjects = ULONG_MAX;
303   ExDesktopObjectType->MaxHandles = ULONG_MAX;
304   ExDesktopObjectType->PagedPoolCharge = 0;
305   ExDesktopObjectType->NonpagedPoolCharge = sizeof(DESKTOP_OBJECT);
306   ExDesktopObjectType->Mapping = &ExpDesktopMapping;
307   ExDesktopObjectType->Dump = NULL;
308   ExDesktopObjectType->Open = NULL;
309   ExDesktopObjectType->Close = NULL;
310   ExDesktopObjectType->Delete = ExpDesktopObjectDelete;
311   ExDesktopObjectType->Parse = NULL;
312   ExDesktopObjectType->Security = NULL;
313   ExDesktopObjectType->QueryName = NULL;
314   ExDesktopObjectType->OkayToClose = NULL;
315   ExDesktopObjectType->Create = ExpDesktopObjectCreate;
316   ExDesktopObjectType->DuplicationNotify = NULL;
317   RtlInitUnicodeStringFromLiteral(&ExDesktopObjectType->TypeName, L"Desktop");
318 }
319
320 /* EOF */