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