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