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