-include/ndk/rtltypes.h: add MAX_ATOM_LEN define
[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->ClassList);
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 /* no process windows should exist at this point, or the function will assert! */
104 DestroyProcessClasses(Win32Process);
105
106 GDI_CleanupForProcess(Process);
107
108 co_IntGraphicsCheck(FALSE);
109
110 /*
111 * Deregister logon application automatically
112 */
113 if(LogonProcess == Win32Process)
114 {
115 LogonProcess = NULL;
116 }
117 }
118
119 RETURN( STATUS_SUCCESS);
120
121 CLEANUP:
122 UserLeave();
123 DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_);
124 END_CLEANUP;
125 }
126
127
128 NTSTATUS
129 STDCALL
130 Win32kThreadCallback(struct _ETHREAD *Thread,
131 BOOLEAN Create)
132 {
133 struct _EPROCESS *Process;
134 PW32THREAD Win32Thread;
135 DECLARE_RETURN(NTSTATUS);
136
137 DPRINT("Enter Win32kThreadCallback\n");
138 UserEnterExclusive();
139
140 Process = Thread->ThreadsProcess;
141
142 /* Get the Win32 Thread */
143 Win32Thread = PsGetThreadWin32Thread(Thread);
144
145 /* Allocate one if needed */
146 if (!Win32Thread)
147 {
148 /* FIXME - lock the process */
149 Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
150 sizeof(W32THREAD),
151 TAG('W', '3', '2', 't'));
152
153 if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
154
155 RtlZeroMemory(Win32Thread, sizeof(W32THREAD));
156
157 PsSetThreadWin32Thread(Thread, Win32Thread);
158 /* FIXME - unlock the process */
159 }
160 if (Create)
161 {
162 HWINSTA hWinSta = NULL;
163 HDESK hDesk = NULL;
164 NTSTATUS Status;
165 PUNICODE_STRING DesktopPath;
166 PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
167
168 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
169
170 /*
171 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
172 * info structure. See documentation of CreateProcess()
173 */
174 DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
175 Status = IntParseDesktopPath(Process,
176 DesktopPath,
177 &hWinSta,
178 &hDesk);
179 if(NT_SUCCESS(Status))
180 {
181 if(hWinSta != NULL)
182 {
183 if(Process != CsrProcess)
184 {
185 HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
186 if(hProcessWinSta != NULL)
187 {
188 /* our process is already assigned to a different window station, we don't need the handle anymore */
189 NtClose(hWinSta);
190 }
191 }
192 else
193 {
194 NtClose(hWinSta);
195 }
196 }
197
198 if (hDesk != NULL)
199 {
200 Status = ObReferenceObjectByHandle(hDesk,
201 0,
202 ExDesktopObjectType,
203 KernelMode,
204 (PVOID*)&Win32Thread->Desktop,
205 NULL);
206 NtClose(hDesk);
207 if(!NT_SUCCESS(Status))
208 {
209 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
210 Win32Thread->Desktop = NULL;
211 }
212 }
213 }
214 Win32Thread->IsExiting = FALSE;
215 co_IntDestroyCaret(Win32Thread);
216 Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
217 Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
218 Win32Thread->MessagePumpHookValue = 0;
219 InitializeListHead(&Win32Thread->WindowListHead);
220 InitializeListHead(&Win32Thread->W32CallbackListHead);
221 }
222 else
223 {
224 PSINGLE_LIST_ENTRY e;
225
226 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
227
228 Win32Thread->IsExiting = TRUE;
229 HOOK_DestroyThreadHooks(Thread);
230 UnregisterThreadHotKeys(Thread);
231 /* what if this co_ func crash in umode? what will clean us up then? */
232 co_DestroyThreadWindows(Thread);
233 IntBlockInput(Win32Thread, FALSE);
234 MsqDestroyMessageQueue(Win32Thread->MessageQueue);
235 IntCleanupThreadCallbacks(Win32Thread);
236 if(Win32Thread->Desktop != NULL)
237 {
238 ObDereferenceObject(Win32Thread->Desktop);
239 }
240
241 /* cleanup user object references stack */
242 e = PopEntryList(&Win32Thread->ReferencesList);
243 while (e)
244 {
245 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry);
246 DPRINT1("thread clean: remove reference obj 0x%x\n",ref->obj);
247 ObmDereferenceObject(ref->obj);
248
249 e = PopEntryList(&Win32Thread->ReferencesList);
250 }
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 */