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