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