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