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