Create a branch for Aleksandar Andrejevic for his work on NTVDM. See http://jira...
[reactos.git] / win32ss / user / ntuser / main.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Driver entry and initialization of win32k
5 * FILE: subsystems/win32/win32k/main/main.c
6 * PROGRAMER:
7 */
8
9 #include <win32k.h>
10 #include <napi.h>
11
12 #define NDEBUG
13 #include <debug.h>
14 #include <kdros.h>
15
16 HANDLE hModuleWin;
17
18 PGDI_HANDLE_TABLE NTAPI GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject);
19 BOOL NTAPI GDI_CleanupForProcess (struct _EPROCESS *Process);
20 NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread);
21
22 HANDLE GlobalUserHeap = NULL;
23 PSECTION_OBJECT GlobalUserHeapSection = NULL;
24
25 PSERVERINFO gpsi = NULL; // Global User Server Information.
26
27 SHORT gusLanguageID;
28 PPROCESSINFO ppiScrnSaver;
29 PPROCESSINFO gppiList = NULL;
30
31 extern ULONG_PTR Win32kSSDT[];
32 extern UCHAR Win32kSSPT[];
33 extern ULONG Win32kNumberOfSysCalls;
34
35 #if DBG
36 void
37 NTAPI
38 DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
39 {
40 GdiDbgPreServiceHook(ulSyscallId, pulArguments);
41 UserDbgPreServiceHook(ulSyscallId, pulArguments);
42 }
43
44 ULONG_PTR
45 NTAPI
46 DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
47 {
48 ulResult = GdiDbgPostServiceHook(ulSyscallId, ulResult);
49 ulResult = UserDbgPostServiceHook(ulSyscallId, ulResult);
50 return ulResult;
51 }
52 #endif
53
54 NTSTATUS
55 APIENTRY
56 Win32kProcessCallback(struct _EPROCESS *Process,
57 BOOLEAN Create)
58 {
59 PPROCESSINFO ppiCurrent, *pppi;
60 DECLARE_RETURN(NTSTATUS);
61
62 ASSERT(Process->Peb);
63
64 UserEnterExclusive();
65
66 if (Create)
67 {
68 SIZE_T ViewSize = 0;
69 LARGE_INTEGER Offset;
70 PVOID UserBase = NULL;
71 PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
72 NTSTATUS Status;
73
74 ASSERT(PsGetProcessWin32Process(Process) == NULL);
75
76 ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
77 sizeof(PROCESSINFO),
78 USERTAG_PROCESSINFO);
79
80 if (ppiCurrent == NULL)
81 {
82 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId));
83 RETURN( STATUS_NO_MEMORY);
84 }
85
86 RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
87
88 PsSetProcessWin32Process(Process, ppiCurrent);
89
90 #if DBG
91 DbgInitDebugChannels();
92 #if KDBG
93 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
94 #endif
95 #endif
96
97 TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
98
99 /* map the global heap into the process */
100 Offset.QuadPart = 0;
101 Status = MmMapViewOfSection(GlobalUserHeapSection,
102 PsGetCurrentProcess(),
103 &UserBase,
104 0,
105 0,
106 &Offset,
107 &ViewSize,
108 ViewUnmap,
109 SEC_NO_CHANGE,
110 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
111 if (!NT_SUCCESS(Status))
112 {
113 TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
114 RETURN(Status);
115 }
116 ppiCurrent->HeapMappings.Next = NULL;
117 ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
118 ppiCurrent->HeapMappings.UserMapping = UserBase;
119 ppiCurrent->HeapMappings.Count = 1;
120
121 InitializeListHead(&ppiCurrent->MenuListHead);
122
123 InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
124 InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
125
126 InitializeListHead(&ppiCurrent->PrivateFontListHead);
127 ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
128
129 InitializeListHead(&ppiCurrent->DriverObjListHead);
130 ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
131
132 ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
133 if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
134 {
135 KeBugCheck(0);
136 }
137
138 KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
139
140
141 /* map the gdi handle table to user land */
142 Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
143 Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
144 pParams = Process->Peb->ProcessParameters;
145
146 ppiCurrent->peProcess = Process;
147 /* setup process flags */
148 ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
149
150 if ( pParams &&
151 pParams->WindowFlags & STARTF_SCRNSAVER )
152 {
153 ppiScrnSaver = ppiCurrent;
154 ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
155 }
156
157 /* Create pools for GDI object attributes */
158 ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
159 ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
160 ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
161 ASSERT(ppiCurrent->pPoolDcAttr);
162 ASSERT(ppiCurrent->pPoolBrushAttr);
163 ASSERT(ppiCurrent->pPoolRgnAttr);
164
165 /* Add the process to the global list */
166 ppiCurrent->ppiNext = gppiList;
167 gppiList = ppiCurrent;
168 }
169 else
170 {
171 /* Get the Win32 Process */
172 ppiCurrent = PsGetProcessWin32Process(Process);
173
174 ASSERT(ppiCurrent);
175
176 TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
177 ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
178
179 if (ppiScrnSaver == ppiCurrent)
180 ppiScrnSaver = NULL;
181
182 if (ppiCurrent->InputIdleEvent)
183 {
184 EngFreeMem(ppiCurrent->InputIdleEvent);
185 ppiCurrent->InputIdleEvent = NULL;
186 }
187
188 IntCleanupMenus(Process, ppiCurrent);
189 IntCleanupCurIcons(Process, ppiCurrent);
190
191
192 GDI_CleanupForProcess(Process);
193
194 co_IntGraphicsCheck(FALSE);
195
196 /*
197 * Deregister logon application automatically
198 */
199 if(LogonProcess == ppiCurrent)
200 {
201 LogonProcess = NULL;
202 }
203
204 /* Close the startup desktop */
205 if(ppiCurrent->rpdeskStartup)
206 ObDereferenceObject(ppiCurrent->rpdeskStartup);
207 if(ppiCurrent->hdeskStartup)
208 ZwClose(ppiCurrent->hdeskStartup);
209
210 /* Close the current window station */
211 UserSetProcessWindowStation(NULL);
212
213 /* Destroy GDI pools */
214 GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
215 GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
216 GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
217
218 if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
219
220 pppi = &gppiList;
221 while (*pppi != NULL && *pppi != ppiCurrent)
222 pppi = &(*pppi)->ppiNext;
223
224 ASSERT(*pppi == ppiCurrent);
225
226 *pppi = ppiCurrent->ppiNext;
227
228 TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
229 #if DBG
230 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
231 {
232 DbgUserDumpHandleTable();
233 }
234 #endif
235
236 /* Free the PROCESSINFO */
237 PsSetProcessWin32Process(Process, NULL);
238 ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
239 }
240
241 RETURN( STATUS_SUCCESS);
242
243 CLEANUP:
244 UserLeave();
245 END_CLEANUP;
246 }
247
248 NTSTATUS NTAPI
249 UserCreateThreadInfo(struct _ETHREAD *Thread)
250 {
251 struct _EPROCESS *Process;
252 PCLIENTINFO pci;
253 PTHREADINFO ptiCurrent;
254 int i;
255 NTSTATUS Status = STATUS_SUCCESS;
256 PTEB pTeb;
257 LARGE_INTEGER LargeTickCount;
258
259 Process = Thread->ThreadsProcess;
260
261 pTeb = NtCurrentTeb();
262
263 ASSERT(pTeb);
264
265 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
266 sizeof(THREADINFO),
267 USERTAG_THREADINFO);
268 if (ptiCurrent == NULL)
269 {
270 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
271 return STATUS_NO_MEMORY;
272 }
273
274 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
275
276 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
277
278 PsSetThreadWin32Thread(Thread, ptiCurrent);
279 pTeb->Win32ThreadInfo = ptiCurrent;
280 ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
281
282 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
283
284 /* Initialize the THREADINFO */
285 IntReferenceThreadInfo(ptiCurrent);
286 InitializeListHead(&ptiCurrent->WindowListHead);
287 InitializeListHead(&ptiCurrent->W32CallbackListHead);
288 InitializeListHead(&ptiCurrent->PostedMessagesListHead);
289 InitializeListHead(&ptiCurrent->SentMessagesListHead);
290 InitializeListHead(&ptiCurrent->DispatchingMessagesHead);
291 InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead);
292 InitializeListHead(&ptiCurrent->PtiLink);
293 for (i = 0; i < NB_HOOKS; i++)
294 {
295 InitializeListHead(&ptiCurrent->aphkStart[i]);
296 }
297 ptiCurrent->pEThread = Thread;
298 ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
299 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
300 ptiCurrent->ppi->ptiList = ptiCurrent;
301 ptiCurrent->ppi->cThreads++;
302
303 ptiCurrent->hEventQueueClient = NULL;
304 Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS,
305 NULL, SynchronizationEvent, FALSE);
306 if (!NT_SUCCESS(Status))
307 {
308 goto error;
309 }
310 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
311 ExEventObjectType, KernelMode,
312 (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
313 if (!NT_SUCCESS(Status))
314 {
315 ZwClose(ptiCurrent->hEventQueueClient);
316 ptiCurrent->hEventQueueClient = NULL;
317 goto error;
318 }
319
320 KeQueryTickCount(&LargeTickCount);
321 ptiCurrent->timeLast = LargeTickCount.u.LowPart;
322
323 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
324 if(ptiCurrent->MessageQueue == NULL)
325 {
326 ERR_CH(UserThread,"Failed to allocate message loop\n");
327 Status = STATUS_NO_MEMORY;
328 goto error;
329 }
330 ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
331 if (ptiCurrent->KeyboardLayout)
332 UserReferenceObject(ptiCurrent->KeyboardLayout);
333 ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
334 if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */
335 ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD;
336 ptiCurrent->pcti = &ptiCurrent->cti;
337
338 /* Initialize the CLIENTINFO */
339 pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
340 RtlZeroMemory(pci, sizeof(CLIENTINFO));
341 pci->ppi = ptiCurrent->ppi;
342 pci->fsHooks = ptiCurrent->fsHooks;
343 pci->dwTIFlags = ptiCurrent->TIF_flags;
344 if (ptiCurrent->KeyboardLayout)
345 {
346 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
347 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
348 }
349
350 /* Assign a default window station and desktop to the process */
351 /* Do not try to open a desktop or window station before winlogon initializes */
352 if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL)
353 {
354 HWINSTA hWinSta = NULL;
355 HDESK hDesk = NULL;
356 UNICODE_STRING DesktopPath;
357 PDESKTOP pdesk;
358 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
359
360 /*
361 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
362 * info structure. See documentation of CreateProcess()
363 */
364 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
365
366 Status = STATUS_UNSUCCESSFUL;
367 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
368 {
369 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
370 }
371 if(!NT_SUCCESS(Status))
372 {
373 RtlInitUnicodeString(&DesktopPath, NULL);
374 }
375
376 Status = IntParseDesktopPath(Process,
377 &DesktopPath,
378 &hWinSta,
379 &hDesk);
380
381 if (DesktopPath.Buffer)
382 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
383
384 if(!NT_SUCCESS(Status))
385 {
386 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
387 goto error;
388 }
389
390 if(!UserSetProcessWindowStation(hWinSta))
391 {
392 Status = STATUS_UNSUCCESSFUL;
393 ERR_CH(UserThread,"Failed to set initial process winsta\n");
394 goto error;
395 }
396
397 /* Validate the new desktop. */
398 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
399 if(!NT_SUCCESS(Status))
400 {
401 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
402 goto error;
403 }
404
405 /* Store the parsed desktop as the initial desktop */
406 ptiCurrent->ppi->hdeskStartup = hDesk;
407 ptiCurrent->ppi->rpdeskStartup = pdesk;
408 }
409
410 if (ptiCurrent->ppi->hdeskStartup != NULL)
411 {
412 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
413 {
414 ERR_CH(UserThread,"Failed to set thread desktop\n");
415 Status = STATUS_UNSUCCESSFUL;
416 goto error;
417 }
418 }
419
420 /* mark the thread as fully initialized */
421 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
422 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
423
424 return STATUS_SUCCESS;
425
426 error:
427 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
428 UserDestroyThreadInfo(Thread);
429 return Status;
430 }
431
432 /*
433 Called from IntDereferenceThreadInfo.
434 */
435 VOID
436 FASTCALL
437 UserDeleteW32Thread(PTHREADINFO pti)
438 {
439 if (!pti->RefCount)
440 {
441 ERR_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
442 if (pti->hEventQueueClient != NULL)
443 ZwClose(pti->hEventQueueClient);
444 pti->hEventQueueClient = NULL;
445
446 /* Free the message queue */
447 if (pti->MessageQueue)
448 {
449 MsqDestroyMessageQueue(pti);
450 }
451
452 MsqCleanupThreadMsgs(pti);
453
454 IntSetThreadDesktop(NULL, TRUE);
455
456 PsSetThreadWin32Thread(pti->pEThread, NULL);
457 ExFreePoolWithTag(pti, USERTAG_THREADINFO);
458 }
459 }
460
461 NTSTATUS
462 NTAPI
463 UserDestroyThreadInfo(struct _ETHREAD *Thread)
464 {
465 PTHREADINFO *ppti;
466 PSINGLE_LIST_ENTRY psle;
467 PPROCESSINFO ppiCurrent;
468 struct _EPROCESS *Process;
469 PTHREADINFO ptiCurrent;
470
471 Process = Thread->ThreadsProcess;
472
473 /* Get the Win32 Thread */
474 ptiCurrent = PsGetThreadWin32Thread(Thread);
475
476 ASSERT(ptiCurrent);
477
478 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
479
480 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
481 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
482
483 ppiCurrent = ptiCurrent->ppi;
484 ASSERT(ppiCurrent);
485
486 // ptiTo
487 if (IsThreadAttach(ptiCurrent))
488 {
489 PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
490 TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
491 UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
492 }
493
494 // ptiFrom
495 if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
496 {
497 PTHREADINFO ptiTo;
498 ptiTo = ptiCurrent->MessageQueue->ptiOwner;
499 TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
500 if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
501 else
502 {
503 // eThread maybe okay but Win32Thread already made NULL!
504 ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
505 }
506 }
507
508 /* Decrement thread count and check if its 0 */
509 ppiCurrent->cThreads--;
510
511 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
512 {
513 /* Do now some process cleanup that requires a valid win32 thread */
514 if(ptiCurrent->ppi->cThreads == 0)
515 {
516 /* Check if we have registered the user api hook */
517 if(ptiCurrent->ppi == ppiUahServer)
518 {
519 /* Unregister the api hook */
520 UserUnregisterUserApiHook();
521 }
522
523 /* Notify logon application to restart shell if needed */
524 if(ptiCurrent->pDeskInfo)
525 {
526 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
527 {
528 DWORD ExitCode = PsGetProcessExitStatus(Process);
529
530 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
531
532 UserPostMessage(hwndSAS,
533 WM_LOGONNOTIFY,
534 LN_SHELL_EXITED,
535 ExitCode);
536
537 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
538 }
539 }
540 }
541
542 DceFreeThreadDCE(ptiCurrent);
543 HOOK_DestroyThreadHooks(Thread);
544 EVENT_DestroyThreadEvents(Thread);
545 DestroyTimersForThread(ptiCurrent);
546 KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
547 UnregisterThreadHotKeys(Thread);
548 /*
549 if (IsListEmpty(&ptiCurrent->WindowListHead))
550 {
551 ERR_CH(UserThread,"Thread Window List is Empty!\n");
552 }
553 */
554 co_DestroyThreadWindows(Thread);
555
556 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling)
557 {
558 //ERR_CH(UserThread,"DestroyProcessClasses\n");
559 /* no process windows should exist at this point, or the function will assert! */
560 DestroyProcessClasses(ppiCurrent);
561 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
562 }
563
564 IntBlockInput(ptiCurrent, FALSE);
565 IntCleanupThreadCallbacks(ptiCurrent);
566
567 /* cleanup user object references stack */
568 psle = PopEntryList(&ptiCurrent->ReferencesList);
569 while (psle)
570 {
571 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
572 TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj);
573 UserDereferenceObject(ref->obj);
574
575 psle = PopEntryList(&ptiCurrent->ReferencesList);
576 }
577 }
578
579 /* Find the THREADINFO in the PROCESSINFO's list */
580 ppti = &ppiCurrent->ptiList;
581 while (*ppti != NULL && *ppti != ptiCurrent)
582 {
583 ppti = &((*ppti)->ptiSibling);
584 }
585
586 /* we must have found it */
587 ASSERT(*ppti == ptiCurrent);
588
589 /* Remove it from the list */
590 *ppti = ptiCurrent->ptiSibling;
591
592 if (ptiCurrent->KeyboardLayout)
593 UserDereferenceObject(ptiCurrent->KeyboardLayout);
594
595 IntSetThreadDesktop(NULL, TRUE);
596
597 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
598
599 /* Free the THREADINFO */
600 IntDereferenceThreadInfo(ptiCurrent);
601
602 return STATUS_SUCCESS;
603 }
604
605 NTSTATUS
606 APIENTRY
607 Win32kThreadCallback(struct _ETHREAD *Thread,
608 PSW32THREADCALLOUTTYPE Type)
609 {
610 NTSTATUS Status;
611
612 UserEnterExclusive();
613
614 ASSERT(NtCurrentTeb());
615
616 if (Type == PsW32ThreadCalloutInitialize)
617 {
618 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
619 Status = UserCreateThreadInfo(Thread);
620 }
621 else
622 {
623 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
624 Status = UserDestroyThreadInfo(Thread);
625 }
626
627 UserLeave();
628
629 return Status;
630 }
631
632 #ifdef _M_IX86
633 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
634 #endif
635
636 // Return on failure
637 #define NT_ROF(x) \
638 Status = (x); \
639 if (!NT_SUCCESS(Status)) \
640 { \
641 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
642 return Status; \
643 }
644
645 /*
646 * This definition doesn't work
647 */
648 INIT_FUNCTION
649 NTSTATUS
650 APIENTRY
651 DriverEntry(
652 IN PDRIVER_OBJECT DriverObject,
653 IN PUNICODE_STRING RegistryPath)
654 {
655 NTSTATUS Status;
656 BOOLEAN Result;
657 WIN32_CALLOUTS_FPNS CalloutData = {0};
658 PVOID GlobalUserHeapBase = NULL;
659
660 /*
661 * Register user mode call interface
662 * (system service table index = 1)
663 */
664 Result = KeAddSystemServiceTable(Win32kSSDT,
665 NULL,
666 Win32kNumberOfSysCalls,
667 Win32kSSPT,
668 1);
669 if (Result == FALSE)
670 {
671 DPRINT1("Adding system services failed!\n");
672 return STATUS_UNSUCCESSFUL;
673 }
674
675 hModuleWin = MmPageEntireDriver(DriverEntry);
676 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
677
678 /* Register Object Manager Callbacks */
679 CalloutData.ProcessCallout = Win32kProcessCallback;
680 CalloutData.ThreadCallout = Win32kThreadCallback;
681 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
682 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
683 CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
684 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
685 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
686 CalloutData.DesktopCloseProcedure = IntDesktopObjectClose;
687 CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen;
688 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
689
690 /* Register our per-process and per-thread structures. */
691 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
692
693 /* Register service hook callbacks */
694 #if DBG
695 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
696 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
697 #endif
698
699 /* Create the global USER heap */
700 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
701 &GlobalUserHeapBase,
702 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
703 if (GlobalUserHeap == NULL)
704 {
705 DPRINT1("Failed to initialize the global heap!\n");
706 return STATUS_UNSUCCESSFUL;
707 }
708
709 /* Allocate global server info structure */
710 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
711 if (!gpsi)
712 {
713 DPRINT1("Failed allocate server info structure!\n");
714 return STATUS_UNSUCCESSFUL;
715 }
716
717 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
718 DPRINT("Global Server Data -> %p\n", gpsi);
719
720 NT_ROF(InitGdiHandleTable());
721 NT_ROF(InitPaletteImpl());
722
723 /* Create stock objects, ie. precreated objects commonly
724 used by win32 applications */
725 CreateStockObjects();
726 CreateSysColorObjects();
727
728 NT_ROF(InitBrushImpl());
729 NT_ROF(InitPDEVImpl());
730 NT_ROF(InitLDEVImpl());
731 NT_ROF(InitDeviceImpl());
732 NT_ROF(InitDcImpl());
733 NT_ROF(InitUserImpl());
734 NT_ROF(InitWindowStationImpl());
735 NT_ROF(InitDesktopImpl());
736 NT_ROF(InitInputImpl());
737 NT_ROF(InitKeyboardImpl());
738 NT_ROF(MsqInitializeImpl());
739 NT_ROF(InitTimerImpl());
740 NT_ROF(InitDCEImpl());
741
742 /* Initialize FreeType library */
743 if (!InitFontSupport())
744 {
745 DPRINT1("Unable to initialize font support\n");
746 return Status;
747 }
748
749 gusLanguageID = UserGetLanguageID();
750
751 return STATUS_SUCCESS;
752 }
753
754 /* EOF */