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