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