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