[WIN32K]
[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
258 Process = Thread->ThreadsProcess;
259
260 pTeb = NtCurrentTeb();
261
262 ASSERT(pTeb);
263
264 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
265 sizeof(THREADINFO),
266 USERTAG_THREADINFO);
267 if (ptiCurrent == NULL)
268 {
269 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
270 return STATUS_NO_MEMORY;
271 }
272
273 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
274
275 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
276
277 PsSetThreadWin32Thread(Thread, ptiCurrent);
278 pTeb->Win32ThreadInfo = ptiCurrent;
279 ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
280
281 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
282
283 /* Initialize the THREADINFO */
284 InitializeListHead(&ptiCurrent->WindowListHead);
285 InitializeListHead(&ptiCurrent->W32CallbackListHead);
286 InitializeListHead(&ptiCurrent->PtiLink);
287 for (i = 0; i < NB_HOOKS; i++)
288 {
289 InitializeListHead(&ptiCurrent->aphkStart[i]);
290 }
291 ptiCurrent->pEThread = Thread;
292 ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
293 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
294 ptiCurrent->ppi->ptiList = ptiCurrent;
295 ptiCurrent->ppi->cThreads++;
296 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
297 if(ptiCurrent->MessageQueue == NULL)
298 {
299 ERR_CH(UserThread,"Failed to allocate message loop\n");
300 Status = STATUS_NO_MEMORY;
301 goto error;
302 }
303 ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
304 if (ptiCurrent->KeyboardLayout)
305 UserReferenceObject(ptiCurrent->KeyboardLayout);
306 ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
307 if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */
308 ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD;
309 ptiCurrent->pcti = &ptiCurrent->cti;
310
311 /* Initialize the CLIENTINFO */
312 pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
313 RtlZeroMemory(pci, sizeof(CLIENTINFO));
314 pci->ppi = ptiCurrent->ppi;
315 pci->fsHooks = ptiCurrent->fsHooks;
316 pci->dwTIFlags = ptiCurrent->TIF_flags;
317 if (ptiCurrent->KeyboardLayout)
318 {
319 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
320 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
321 }
322
323 /* Assign a default window station and desktop to the process */
324 /* Do not try to open a desktop or window station before winlogon initializes */
325 if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL)
326 {
327 HWINSTA hWinSta = NULL;
328 HDESK hDesk = NULL;
329 UNICODE_STRING DesktopPath;
330 PDESKTOP pdesk;
331 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
332
333 /*
334 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
335 * info structure. See documentation of CreateProcess()
336 */
337 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
338
339 Status = STATUS_UNSUCCESSFUL;
340 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
341 {
342 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
343 }
344 if(!NT_SUCCESS(Status))
345 {
346 RtlInitUnicodeString(&DesktopPath, NULL);
347 }
348
349 Status = IntParseDesktopPath(Process,
350 &DesktopPath,
351 &hWinSta,
352 &hDesk);
353
354 if (DesktopPath.Buffer)
355 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
356
357 if(!NT_SUCCESS(Status))
358 {
359 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
360 goto error;
361 }
362
363 if(!UserSetProcessWindowStation(hWinSta))
364 {
365 Status = STATUS_UNSUCCESSFUL;
366 ERR_CH(UserThread,"Failed to set initial process winsta\n");
367 goto error;
368 }
369
370 /* Validate the new desktop. */
371 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
372 if(!NT_SUCCESS(Status))
373 {
374 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
375 goto error;
376 }
377
378 /* Store the parsed desktop as the initial desktop */
379 ptiCurrent->ppi->hdeskStartup = hDesk;
380 ptiCurrent->ppi->rpdeskStartup = pdesk;
381 }
382
383 if (ptiCurrent->ppi->hdeskStartup != NULL)
384 {
385 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
386 {
387 ERR_CH(UserThread,"Failed to set thread desktop\n");
388 Status = STATUS_UNSUCCESSFUL;
389 goto error;
390 }
391 }
392
393 /* mark the thread as fully initialized */
394 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
395 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
396
397 return STATUS_SUCCESS;
398
399 error:
400 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
401 UserDestroyThreadInfo(Thread);
402 return Status;
403 }
404
405 NTSTATUS
406 NTAPI
407 UserDestroyThreadInfo(struct _ETHREAD *Thread)
408 {
409 PTHREADINFO *ppti;
410 PSINGLE_LIST_ENTRY psle;
411 PPROCESSINFO ppiCurrent;
412 struct _EPROCESS *Process;
413 PTHREADINFO ptiCurrent;
414
415 Process = Thread->ThreadsProcess;
416
417 /* Get the Win32 Thread */
418 ptiCurrent = PsGetThreadWin32Thread(Thread);
419
420 ASSERT(ptiCurrent);
421
422 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
423
424 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
425 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
426
427 ppiCurrent = ptiCurrent->ppi;
428 ASSERT(ppiCurrent);
429
430 // ptiTo
431 if (IsThreadAttach(ptiCurrent))
432 {
433 PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
434 TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
435 UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
436 }
437
438 // ptiFrom
439 if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
440 {
441 PTHREADINFO ptiTo;
442 ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
443 TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
444 if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
445 else
446 {
447 // eThread maybe okay but Win32Thread already made NULL!
448 ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
449 }
450 }
451
452 /* Decrement thread count and check if its 0 */
453 ppiCurrent->cThreads--;
454
455 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
456 {
457 /* Do now some process cleanup that requires a valid win32 thread */
458 if(ptiCurrent->ppi->cThreads == 0)
459 {
460 /* Check if we have registered the user api hook */
461 if(ptiCurrent->ppi == ppiUahServer)
462 {
463 /* Unregister the api hook */
464 UserUnregisterUserApiHook();
465 }
466
467 /* Notify logon application to restart shell if needed */
468 if(ptiCurrent->pDeskInfo)
469 {
470 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
471 {
472 DWORD ExitCode = PsGetProcessExitStatus(Process);
473
474 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
475
476 UserPostMessage(hwndSAS,
477 WM_LOGONNOTIFY,
478 LN_SHELL_EXITED,
479 ExitCode);
480
481 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
482 }
483 }
484 }
485
486 DceFreeThreadDCE(ptiCurrent);
487 HOOK_DestroyThreadHooks(Thread);
488 EVENT_DestroyThreadEvents(Thread);
489 DestroyTimersForThread(ptiCurrent);
490 KeSetEvent(ptiCurrent->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
491 UnregisterThreadHotKeys(Thread);
492 /*
493 if (IsListEmpty(&ptiCurrent->WindowListHead))
494 {
495 ERR_CH(UserThread,"Thread Window List is Empty!\n");
496 }
497 */
498 co_DestroyThreadWindows(Thread);
499
500 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling)
501 {
502 //ERR_CH(UserThread,"DestroyProcessClasses\n");
503 /* no process windows should exist at this point, or the function will assert! */
504 DestroyProcessClasses(ppiCurrent);
505 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
506 }
507
508 IntBlockInput(ptiCurrent, FALSE);
509 IntCleanupThreadCallbacks(ptiCurrent);
510
511 /* cleanup user object references stack */
512 psle = PopEntryList(&ptiCurrent->ReferencesList);
513 while (psle)
514 {
515 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
516 TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj);
517 UserDereferenceObject(ref->obj);
518
519 psle = PopEntryList(&ptiCurrent->ReferencesList);
520 }
521 }
522
523 /* Free the message queue */
524 if (ptiCurrent->MessageQueue)
525 {
526 MsqDestroyMessageQueue(ptiCurrent);
527 }
528
529 /* Find the THREADINFO in the PROCESSINFO's list */
530 ppti = &ppiCurrent->ptiList;
531 while (*ppti != NULL && *ppti != ptiCurrent)
532 {
533 ppti = &((*ppti)->ptiSibling);
534 }
535
536 /* we must have found it */
537 ASSERT(*ppti == ptiCurrent);
538
539 /* Remove it from the list */
540 *ppti = ptiCurrent->ptiSibling;
541
542 if (ptiCurrent->KeyboardLayout)
543 UserDereferenceObject(ptiCurrent->KeyboardLayout);
544
545 IntSetThreadDesktop(NULL, TRUE);
546
547 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
548
549 /* Free the THREADINFO */
550 PsSetThreadWin32Thread(Thread, NULL);
551 ExFreePoolWithTag(ptiCurrent, USERTAG_THREADINFO);
552
553 return STATUS_SUCCESS;
554 }
555
556 NTSTATUS
557 APIENTRY
558 Win32kThreadCallback(struct _ETHREAD *Thread,
559 PSW32THREADCALLOUTTYPE Type)
560 {
561 NTSTATUS Status;
562
563 UserEnterExclusive();
564
565 ASSERT(NtCurrentTeb());
566
567 if (Type == PsW32ThreadCalloutInitialize)
568 {
569 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
570 Status = UserCreateThreadInfo(Thread);
571 }
572 else
573 {
574 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
575 Status = UserDestroyThreadInfo(Thread);
576 }
577
578 UserLeave();
579
580 return Status;
581 }
582
583 #ifdef _M_IX86
584 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
585 #endif
586
587 // Return on failure
588 #define NT_ROF(x) \
589 Status = (x); \
590 if (!NT_SUCCESS(Status)) \
591 { \
592 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
593 return Status; \
594 }
595
596 /*
597 * This definition doesn't work
598 */
599 INIT_FUNCTION
600 NTSTATUS
601 APIENTRY
602 DriverEntry(
603 IN PDRIVER_OBJECT DriverObject,
604 IN PUNICODE_STRING RegistryPath)
605 {
606 NTSTATUS Status;
607 BOOLEAN Result;
608 WIN32_CALLOUTS_FPNS CalloutData = {0};
609 PVOID GlobalUserHeapBase = NULL;
610
611 /*
612 * Register user mode call interface
613 * (system service table index = 1)
614 */
615 Result = KeAddSystemServiceTable(Win32kSSDT,
616 NULL,
617 Win32kNumberOfSysCalls,
618 Win32kSSPT,
619 1);
620 if (Result == FALSE)
621 {
622 DPRINT1("Adding system services failed!\n");
623 return STATUS_UNSUCCESSFUL;
624 }
625
626 hModuleWin = MmPageEntireDriver(DriverEntry);
627 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
628
629 /* Register Object Manager Callbacks */
630 CalloutData.ProcessCallout = Win32kProcessCallback;
631 CalloutData.ThreadCallout = Win32kThreadCallback;
632 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
633 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
634 CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
635 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
636 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
637 CalloutData.DesktopCloseProcedure = IntDesktopObjectClose;
638 CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen;
639 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
640
641 /* Register our per-process and per-thread structures. */
642 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
643
644 /* Register service hook callbacks */
645 #if DBG
646 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
647 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
648 #endif
649
650 /* Create the global USER heap */
651 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
652 &GlobalUserHeapBase,
653 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
654 if (GlobalUserHeap == NULL)
655 {
656 DPRINT1("Failed to initialize the global heap!\n");
657 return STATUS_UNSUCCESSFUL;
658 }
659
660 /* Allocate global server info structure */
661 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
662 if (!gpsi)
663 {
664 DPRINT1("Failed allocate server info structure!\n");
665 return STATUS_UNSUCCESSFUL;
666 }
667
668 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
669 DPRINT("Global Server Data -> %p\n", gpsi);
670
671 NT_ROF(InitGdiHandleTable());
672 NT_ROF(InitPaletteImpl());
673
674 /* Create stock objects, ie. precreated objects commonly
675 used by win32 applications */
676 CreateStockObjects();
677 CreateSysColorObjects();
678
679 NT_ROF(InitBrushImpl());
680 NT_ROF(InitPDEVImpl());
681 NT_ROF(InitLDEVImpl());
682 NT_ROF(InitDeviceImpl());
683 NT_ROF(InitDcImpl());
684 NT_ROF(InitUserImpl());
685 NT_ROF(InitWindowStationImpl());
686 NT_ROF(InitDesktopImpl());
687 NT_ROF(InitInputImpl());
688 NT_ROF(InitKeyboardImpl());
689 NT_ROF(MsqInitializeImpl());
690 NT_ROF(InitTimerImpl());
691 NT_ROF(InitDCEImpl());
692
693 /* Initialize FreeType library */
694 if (!InitFontSupport())
695 {
696 DPRINT1("Unable to initialize font support\n");
697 return Status;
698 }
699
700 gusLanguageID = UserGetLanguageID();
701
702 return STATUS_SUCCESS;
703 }
704
705 /* EOF */