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