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