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