remove relatives lock, window props lock, classes locks, thread window lock, menu...
[reactos.git] / reactos / subsys / win32k / main / dllmain.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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 /* $Id$
20 *
21 * Entry Point for win32k.sys
22 */
23
24 #include <w32k.h>
25 #include <win32k/ntddraw.h>
26 #include <include/napi.h>
27
28 #define NDEBUG
29 #include <debug.h>
30
31 BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process);
32
33 extern ULONG_PTR Win32kSSDT[];
34 extern UCHAR Win32kSSPT[];
35 extern ULONG Win32kNumberOfSysCalls;
36
37 PSHARED_SECTION_POOL SessionSharedSectionPool = NULL;
38
39 NTSTATUS
40 STDCALL
41 Win32kProcessCallback(struct _EPROCESS *Process,
42 BOOLEAN Create)
43 {
44 PW32PROCESS Win32Process;
45 DECLARE_RETURN(NTSTATUS);
46
47 DPRINT("Enter Win32kProcessCallback\n");
48 UserEnterExclusive();
49
50 /* Get the Win32 Process */
51 Win32Process = PsGetProcessWin32Process(Process);
52
53 /* Allocate one if needed */
54 if (!Win32Process)
55 {
56 /* FIXME - lock the process */
57 Win32Process = ExAllocatePoolWithTag(NonPagedPool,
58 sizeof(W32PROCESS),
59 TAG('W', '3', '2', 'p'));
60
61 if (Win32Process == NULL) RETURN( STATUS_NO_MEMORY);
62
63 RtlZeroMemory(Win32Process, sizeof(W32PROCESS));
64
65 PsSetProcessWin32Process(Process, Win32Process);
66 /* FIXME - unlock the process */
67 }
68
69 if (Create)
70 {
71 DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
72
73 InitializeListHead(&Win32Process->ClassListHead);
74
75 InitializeListHead(&Win32Process->MenuListHead);
76
77 InitializeListHead(&Win32Process->PrivateFontListHead);
78 ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
79
80 InitializeListHead(&Win32Process->DriverObjListHead);
81 ExInitializeFastMutex(&Win32Process->DriverObjListLock);
82
83 Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
84
85 if(Process->Peb != NULL)
86 {
87 /* map the gdi handle table to user land */
88 Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
89 }
90
91 /* setup process flags */
92 Win32Process->Flags = 0;
93 }
94 else
95 {
96 DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
97 IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId);
98 IntCleanupMenus(Process, Win32Process);
99 IntCleanupCurIcons(Process, Win32Process);
100 IntEngCleanupDriverObjs(Process, Win32Process);
101 CleanupMonitorImpl();
102
103
104 GDI_CleanupForProcess(Process);
105
106 co_IntGraphicsCheck(FALSE);
107
108 /*
109 * Deregister logon application automatically
110 */
111 if(LogonProcess == Win32Process)
112 {
113 LogonProcess = NULL;
114 }
115 }
116
117 RETURN( STATUS_SUCCESS);
118
119 CLEANUP:
120 UserLeave();
121 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_);
122 END_CLEANUP;
123 }
124
125
126 NTSTATUS
127 STDCALL
128 Win32kThreadCallback(struct _ETHREAD *Thread,
129 BOOLEAN Create)
130 {
131 struct _EPROCESS *Process;
132 PW32THREAD Win32Thread;
133 DECLARE_RETURN(NTSTATUS);
134
135 DPRINT("Enter Win32kThreadCallback\n");
136 UserEnterExclusive();
137
138 Process = Thread->ThreadsProcess;
139
140 /* Get the Win32 Thread */
141 Win32Thread = PsGetThreadWin32Thread(Thread);
142
143 /* Allocate one if needed */
144 if (!Win32Thread)
145 {
146 /* FIXME - lock the process */
147 Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
148 sizeof(W32THREAD),
149 TAG('W', '3', '2', 't'));
150
151 if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
152
153 RtlZeroMemory(Win32Thread, sizeof(W32THREAD));
154
155 PsSetThreadWin32Thread(Thread, Win32Thread);
156 /* FIXME - unlock the process */
157 }
158 if (Create)
159 {
160 HWINSTA hWinSta = NULL;
161 HDESK hDesk = NULL;
162 NTSTATUS Status;
163 PUNICODE_STRING DesktopPath;
164 PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
165
166 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
167
168 /*
169 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
170 * info structure. See documentation of CreateProcess()
171 */
172 DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
173 Status = IntParseDesktopPath(Process,
174 DesktopPath,
175 &hWinSta,
176 &hDesk);
177 if(NT_SUCCESS(Status))
178 {
179 if(hWinSta != NULL)
180 {
181 if(Process != CsrProcess)
182 {
183 HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
184 if(hProcessWinSta != NULL)
185 {
186 /* our process is already assigned to a different window station, we don't need the handle anymore */
187 NtClose(hWinSta);
188 }
189 }
190 else
191 {
192 NtClose(hWinSta);
193 }
194 }
195
196 if (hDesk != NULL)
197 {
198 Status = ObReferenceObjectByHandle(hDesk,
199 0,
200 ExDesktopObjectType,
201 KernelMode,
202 (PVOID*)&Win32Thread->Desktop,
203 NULL);
204 NtClose(hDesk);
205 if(!NT_SUCCESS(Status))
206 {
207 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
208 Win32Thread->Desktop = NULL;
209 }
210 }
211 }
212 Win32Thread->IsExiting = FALSE;
213 co_IntDestroyCaret(Win32Thread);
214 Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
215 Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
216 Win32Thread->MessagePumpHookValue = 0;
217 InitializeListHead(&Win32Thread->WindowListHead);
218 InitializeListHead(&Win32Thread->W32CallbackListHead);
219 }
220 else
221 {
222 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
223
224 Win32Thread->IsExiting = TRUE;
225 HOOK_DestroyThreadHooks(Thread);
226 UnregisterThreadHotKeys(Thread);
227 co_DestroyThreadWindows(Thread);
228 IntBlockInput(Win32Thread, FALSE);
229 MsqDestroyMessageQueue(Win32Thread->MessageQueue);
230 IntCleanupThreadCallbacks(Win32Thread);
231 if(Win32Thread->Desktop != NULL)
232 {
233 ObDereferenceObject(Win32Thread->Desktop);
234 }
235 }
236
237 RETURN( STATUS_SUCCESS);
238
239 CLEANUP:
240 UserLeave();
241 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_);
242 END_CLEANUP;
243 }
244
245 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
246 not called there anymore, please delete */
247 NTSTATUS
248 Win32kInitWin32Thread(PETHREAD Thread)
249 {
250 PEPROCESS Process;
251
252 Process = Thread->ThreadsProcess;
253
254 if (Process->Win32Process == NULL)
255 {
256 /* FIXME - lock the process */
257 Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(W32PROCESS));
258
259 if (Process->Win32Process == NULL)
260 return STATUS_NO_MEMORY;
261
262 RtlZeroMemory(Process->Win32Process, sizeof(W32PROCESS));
263 /* FIXME - unlock the process */
264
265 Win32kProcessCallback(Process, TRUE);
266 }
267
268 if (Thread->Tcb.Win32Thread == NULL)
269 {
270 Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(W32THREAD));
271 if (Thread->Tcb.Win32Thread == NULL)
272 return STATUS_NO_MEMORY;
273
274 RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(W32THREAD));
275
276 Win32kThreadCallback(Thread, TRUE);
277 }
278
279 return(STATUS_SUCCESS);
280 }
281
282
283 /*
284 * This definition doesn't work
285 */
286 NTSTATUS STDCALL
287 DriverEntry (
288 IN PDRIVER_OBJECT DriverObject,
289 IN PUNICODE_STRING RegistryPath)
290 {
291 NTSTATUS Status;
292 BOOLEAN Result;
293 W32_CALLOUT_DATA CalloutData;
294
295 /*
296 * Register user mode call interface
297 * (system service table index = 1)
298 */
299 Result = KeAddSystemServiceTable (Win32kSSDT,
300 NULL,
301 Win32kNumberOfSysCalls,
302 Win32kSSPT,
303 1);
304 if (Result == FALSE)
305 {
306 DPRINT1("Adding system services failed!\n");
307 return STATUS_UNSUCCESSFUL;
308 }
309
310 /*
311 * Register Object Manager Callbacks
312 */
313 CalloutData.WinStaCreate = IntWinStaObjectOpen;
314 CalloutData.WinStaParse = IntWinStaObjectParse;
315 CalloutData.WinStaDelete = IntWinStaObjectDelete;
316 CalloutData.WinStaFind = IntWinStaObjectFind;
317 CalloutData.DesktopCreate = IntDesktopObjectCreate;
318 CalloutData.DesktopDelete = IntDesktopObjectDelete;
319 CalloutData.W32ProcessCallout = Win32kProcessCallback;
320 CalloutData.W32ThreadCallout = Win32kThreadCallback;
321
322 /*
323 * Register our per-process and per-thread structures.
324 */
325 PsEstablishWin32Callouts(&CalloutData);
326
327 Status = IntUserCreateSharedSectionPool(48 * 1024 * 1024, /* 48 MB by default */
328 &SessionSharedSectionPool);
329 if (!NT_SUCCESS(Status))
330 {
331 DPRINT1("Failed to initialize the shared section pool: Status 0x%x\n", Status);
332 }
333
334 Status = InitUserImpl();
335 if (!NT_SUCCESS(Status))
336 {
337 DPRINT1("Failed to initialize user implementation!\n");
338 return STATUS_UNSUCCESSFUL;
339 }
340
341 Status = InitWindowStationImpl();
342 if (!NT_SUCCESS(Status))
343 {
344 DPRINT1("Failed to initialize window station implementation!\n");
345 return STATUS_UNSUCCESSFUL;
346 }
347
348 Status = InitClassImpl();
349 if (!NT_SUCCESS(Status))
350 {
351 DPRINT1("Failed to initialize window class implementation!\n");
352 return STATUS_UNSUCCESSFUL;
353 }
354
355 Status = InitDesktopImpl();
356 if (!NT_SUCCESS(Status))
357 {
358 DPRINT1("Failed to initialize desktop implementation!\n");
359 return STATUS_UNSUCCESSFUL;
360 }
361
362 Status = InitWindowImpl();
363 if (!NT_SUCCESS(Status))
364 {
365 DPRINT1("Failed to initialize window implementation!\n");
366 return STATUS_UNSUCCESSFUL;
367 }
368
369 Status = InitMenuImpl();
370 if (!NT_SUCCESS(Status))
371 {
372 DPRINT1("Failed to initialize menu implementation!\n");
373 return STATUS_UNSUCCESSFUL;
374 }
375
376 Status = InitInputImpl();
377 if (!NT_SUCCESS(Status))
378 {
379 DPRINT1("Failed to initialize input implementation.\n");
380 return(Status);
381 }
382
383 Status = InitKeyboardImpl();
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT1("Failed to initialize keyboard implementation.\n");
387 return(Status);
388 }
389
390 Status = InitMonitorImpl();
391 if (!NT_SUCCESS(Status))
392 {
393 DbgPrint("Failed to initialize monitor implementation!\n");
394 return STATUS_UNSUCCESSFUL;
395 }
396
397 Status = MsqInitializeImpl();
398 if (!NT_SUCCESS(Status))
399 {
400 DPRINT1("Failed to initialize message queue implementation.\n");
401 return(Status);
402 }
403
404 Status = InitTimerImpl();
405 if (!NT_SUCCESS(Status))
406 {
407 DPRINT1("Failed to initialize timer implementation.\n");
408 return(Status);
409 }
410
411 Status = InitAcceleratorImpl();
412 if (!NT_SUCCESS(Status))
413 {
414 DPRINT1("Failed to initialize accelerator implementation.\n");
415 return(Status);
416 }
417
418 Status = InitGuiCheckImpl();
419 if (!NT_SUCCESS(Status))
420 {
421 DPRINT1("Failed to initialize GUI check implementation.\n");
422 return(Status);
423 }
424
425 InitGdiObjectHandleTable ();
426
427 /* Initialize FreeType library */
428 if (! InitFontSupport())
429 {
430 DPRINT1("Unable to initialize font support\n");
431 return STATUS_UNSUCCESSFUL;
432 }
433
434 /* Create stock objects, ie. precreated objects commonly
435 used by win32 applications */
436 CreateStockObjects();
437 CreateSysColorObjects();
438
439 return STATUS_SUCCESS;
440 }
441
442
443 BOOLEAN STDCALL
444 Win32kInitialize (VOID)
445 {
446 return TRUE;
447 }
448
449 /* EOF */