Add leftover from sync, fixes build.
[reactos.git] / 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 DECLARE_RETURN(NTSTATUS);
177
178 DPRINT("Enter Win32kThreadCallback\n");
179 UserEnterExclusive();
180
181 Process = Thread->ThreadsProcess;
182
183 /* Get the Win32 Thread */
184 Win32Thread = PsGetThreadWin32Thread(Thread);
185
186 /* Allocate one if needed */
187 if (!Win32Thread)
188 {
189 /* FIXME - lock the process */
190 Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
191 sizeof(THREADINFO),
192 't23W');
193
194 if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
195
196 RtlZeroMemory(Win32Thread, sizeof(THREADINFO));
197
198 PsSetThreadWin32Thread(Thread, Win32Thread);
199 /* FIXME - unlock the process */
200 }
201 if (Type == PsW32ThreadCalloutInitialize)
202 {
203 HWINSTA hWinSta = NULL;
204 PTEB pTeb;
205 HDESK hDesk = NULL;
206 NTSTATUS Status;
207 PUNICODE_STRING DesktopPath;
208 PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
209
210 DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
211
212 InitializeListHead(&Win32Thread->WindowListHead);
213 InitializeListHead(&Win32Thread->W32CallbackListHead);
214 InitializeListHead(&Win32Thread->PtiLink);
215
216 /*
217 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
218 * info structure. See documentation of CreateProcess()
219 */
220 DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
221 Status = IntParseDesktopPath(Process,
222 DesktopPath,
223 &hWinSta,
224 &hDesk);
225 if(NT_SUCCESS(Status))
226 {
227 if(hWinSta != NULL)
228 {
229 if(Process != CsrProcess)
230 {
231 HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
232 if(hProcessWinSta != NULL)
233 {
234 /* our process is already assigned to a different window station, we don't need the handle anymore */
235 NtClose(hWinSta);
236 }
237 }
238 else
239 {
240 NtClose(hWinSta);
241 }
242 }
243
244 if (hDesk != NULL)
245 {
246 PDESKTOP DesktopObject;
247 Win32Thread->rpdesk = NULL;
248 Status = ObReferenceObjectByHandle(hDesk,
249 0,
250 ExDesktopObjectType,
251 KernelMode,
252 (PVOID*)&DesktopObject,
253 NULL);
254 NtClose(hDesk);
255 if(NT_SUCCESS(Status))
256 {
257 if (!IntSetThreadDesktop(DesktopObject,
258 FALSE))
259 {
260 DPRINT1("Unable to set thread desktop\n");
261 }
262 }
263 else
264 {
265 DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
266 }
267 }
268 }
269 Win32Thread->TIF_flags &= ~TIF_INCLEANUP;
270 co_IntDestroyCaret(Win32Thread);
271 Win32Thread->ppi = PsGetCurrentProcessWin32Process();
272 pTeb = NtCurrentTeb();
273 if (pTeb)
274 {
275 Win32Thread->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
276 Win32Thread->pClientInfo->pClientThreadInfo = NULL;
277 }
278 Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
279 Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
280 Win32Thread->pEThread = Thread;
281 }
282 else
283 {
284 PSINGLE_LIST_ENTRY e;
285
286 DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
287
288 Win32Thread->TIF_flags |= TIF_INCLEANUP;
289 DceFreeThreadDCE(Win32Thread);
290 HOOK_DestroyThreadHooks(Thread);
291 /* Cleanup timers */
292 DestroyTimersForThread(Win32Thread);
293 KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
294 UnregisterThreadHotKeys(Thread);
295 /* what if this co_ func crash in umode? what will clean us up then? */
296 co_DestroyThreadWindows(Thread);
297 IntBlockInput(Win32Thread, FALSE);
298 MsqDestroyMessageQueue(Win32Thread->MessageQueue);
299 IntCleanupThreadCallbacks(Win32Thread);
300
301 /* cleanup user object references stack */
302 e = PopEntryList(&Win32Thread->ReferencesList);
303 while (e)
304 {
305 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry);
306 DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj);
307 UserDereferenceObject(ref->obj);
308
309 e = PopEntryList(&Win32Thread->ReferencesList);
310 }
311
312 IntSetThreadDesktop(NULL,
313 TRUE);
314
315 PsSetThreadWin32Thread(Thread, NULL);
316 }
317
318 RETURN( STATUS_SUCCESS);
319
320 CLEANUP:
321 UserLeave();
322 DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_);
323 END_CLEANUP;
324 }
325
326 /* Only used in ntuser/input.c KeyboardThreadMain(). If it's
327 not called there anymore, please delete */
328 NTSTATUS
329 Win32kInitWin32Thread(PETHREAD Thread)
330 {
331 PEPROCESS Process;
332
333 Process = Thread->ThreadsProcess;
334
335 if (Process->Win32Process == NULL)
336 {
337 /* FIXME - lock the process */
338 Process->Win32Process = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_PROCESSINFO);
339
340 if (Process->Win32Process == NULL)
341 return STATUS_NO_MEMORY;
342
343 RtlZeroMemory(Process->Win32Process, sizeof(PROCESSINFO));
344 /* FIXME - unlock the process */
345
346 Win32kProcessCallback(Process, TRUE);
347 }
348
349 if (Thread->Tcb.Win32Thread == NULL)
350 {
351 Thread->Tcb.Win32Thread = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO);
352 if (Thread->Tcb.Win32Thread == NULL)
353 return STATUS_NO_MEMORY;
354
355 RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(THREADINFO));
356
357 Win32kThreadCallback(Thread, PsW32ThreadCalloutInitialize);
358 }
359
360 return(STATUS_SUCCESS);
361 }
362
363 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
364
365 /*
366 * This definition doesn't work
367 */
368 NTSTATUS APIENTRY
369 DriverEntry (
370 IN PDRIVER_OBJECT DriverObject,
371 IN PUNICODE_STRING RegistryPath)
372 {
373 NTSTATUS Status;
374 BOOLEAN Result;
375 WIN32_CALLOUTS_FPNS CalloutData = {0};
376 PVOID GlobalUserHeapBase = NULL;
377
378 /*
379 * Register user mode call interface
380 * (system service table index = 1)
381 */
382 Result = KeAddSystemServiceTable (Win32kSSDT,
383 NULL,
384 Win32kNumberOfSysCalls,
385 Win32kSSPT,
386 1);
387 if (Result == FALSE)
388 {
389 DPRINT1("Adding system services failed!\n");
390 return STATUS_UNSUCCESSFUL;
391 }
392
393 hModuleWin = MmPageEntireDriver(DriverEntry);
394 DPRINT("Win32k hInstance 0x%x!\n",hModuleWin);
395 /*
396 * Register Object Manager Callbacks
397 */
398 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
399 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
400 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
401 CalloutData.ProcessCallout = Win32kProcessCallback;
402 CalloutData.ThreadCallout = Win32kThreadCallback;
403 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
404
405 /*
406 * Register our per-process and per-thread structures.
407 */
408 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
409
410 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
411 &GlobalUserHeapBase,
412 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
413 if (GlobalUserHeap == NULL)
414 {
415 DPRINT1("Failed to initialize the global heap!\n");
416 return STATUS_UNSUCCESSFUL;
417 }
418
419 if (!gpsi)
420 {
421 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
422 if (gpsi)
423 {
424 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
425 DPRINT("Global Server Data -> %x\n", gpsi);
426 }
427 else
428 {
429 ASSERT(FALSE);
430 }
431 }
432
433 if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore();
434
435 GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection);
436 if (GdiHandleTable == NULL)
437 {
438 DPRINT1("Failed to initialize the GDI handle table.\n");
439 return STATUS_UNSUCCESSFUL;
440 }
441
442 /* Initialize default palettes */
443 PALETTE_Init();
444
445 /* Create stock objects, ie. precreated objects commonly
446 used by win32 applications */
447 CreateStockObjects();
448 CreateSysColorObjects();
449
450 InitXlateImpl();
451 InitPDEVImpl();
452 InitLDEVImpl();
453 InitDeviceImpl();
454
455 Status = InitDcImpl();
456 if (!NT_SUCCESS(Status))
457 {
458 DPRINT1("Failed to initialize Device context implementation!\n");
459 return STATUS_UNSUCCESSFUL;
460 }
461
462 Status = InitUserImpl();
463 if (!NT_SUCCESS(Status))
464 {
465 DPRINT1("Failed to initialize user implementation!\n");
466 return STATUS_UNSUCCESSFUL;
467 }
468
469 Status = InitHotkeyImpl();
470 if (!NT_SUCCESS(Status))
471 {
472 DPRINT1("Failed to initialize hotkey implementation!\n");
473 return STATUS_UNSUCCESSFUL;
474 }
475
476 Status = InitWindowStationImpl();
477 if (!NT_SUCCESS(Status))
478 {
479 DPRINT1("Failed to initialize window station implementation!\n");
480 return STATUS_UNSUCCESSFUL;
481 }
482
483 Status = InitDesktopImpl();
484 if (!NT_SUCCESS(Status))
485 {
486 DPRINT1("Failed to initialize desktop implementation!\n");
487 return STATUS_UNSUCCESSFUL;
488 }
489
490 Status = InitWindowImpl();
491 if (!NT_SUCCESS(Status))
492 {
493 DPRINT1("Failed to initialize window implementation!\n");
494 return STATUS_UNSUCCESSFUL;
495 }
496
497 Status = InitMenuImpl();
498 if (!NT_SUCCESS(Status))
499 {
500 DPRINT1("Failed to initialize menu implementation!\n");
501 return STATUS_UNSUCCESSFUL;
502 }
503
504 Status = InitInputImpl();
505 if (!NT_SUCCESS(Status))
506 {
507 DPRINT1("Failed to initialize input implementation.\n");
508 return(Status);
509 }
510
511 Status = InitKeyboardImpl();
512 if (!NT_SUCCESS(Status))
513 {
514 DPRINT1("Failed to initialize keyboard implementation.\n");
515 return(Status);
516 }
517
518 Status = InitMonitorImpl();
519 if (!NT_SUCCESS(Status))
520 {
521 DbgPrint("Failed to initialize monitor implementation!\n");
522 return STATUS_UNSUCCESSFUL;
523 }
524
525 Status = MsqInitializeImpl();
526 if (!NT_SUCCESS(Status))
527 {
528 DPRINT1("Failed to initialize message queue implementation.\n");
529 return(Status);
530 }
531
532 Status = InitTimerImpl();
533 if (!NT_SUCCESS(Status))
534 {
535 DPRINT1("Failed to initialize timer implementation.\n");
536 return(Status);
537 }
538
539 Status = InitAcceleratorImpl();
540 if (!NT_SUCCESS(Status))
541 {
542 DPRINT1("Failed to initialize accelerator implementation.\n");
543 return(Status);
544 }
545
546 Status = InitGuiCheckImpl();
547 if (!NT_SUCCESS(Status))
548 {
549 DPRINT1("Failed to initialize GUI check implementation.\n");
550 return(Status);
551 }
552
553 /* Initialize FreeType library */
554 if (! InitFontSupport())
555 {
556 DPRINT1("Unable to initialize font support\n");
557 return STATUS_UNSUCCESSFUL;
558 }
559
560 gusLanguageID = IntGdiGetLanguageID();
561
562 return STATUS_SUCCESS;
563 }
564
565 /* EOF */