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
18 PGDI_HANDLE_TABLE NTAPI
GDIOBJ_iAllocHandleTable(OUT PVOID
*SectionObject
);
19 BOOL NTAPI
GDI_CleanupForProcess (struct _EPROCESS
*Process
);
20 NTSTATUS NTAPI
UserDestroyThreadInfo(struct _ETHREAD
*Thread
);
22 HANDLE GlobalUserHeap
= NULL
;
23 PVOID GlobalUserHeapSection
= NULL
;
25 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
28 PPROCESSINFO ppiScrnSaver
;
29 PPROCESSINFO gppiList
= NULL
;
31 extern ULONG_PTR Win32kSSDT
[];
32 extern UCHAR Win32kSSPT
[];
33 extern ULONG Win32kNumberOfSysCalls
;
38 DbgPreServiceHook(ULONG ulSyscallId
, PULONG_PTR pulArguments
)
40 GdiDbgPreServiceHook(ulSyscallId
, pulArguments
);
41 UserDbgPreServiceHook(ulSyscallId
, pulArguments
);
46 DbgPostServiceHook(ULONG ulSyscallId
, ULONG_PTR ulResult
)
48 ulResult
= GdiDbgPostServiceHook(ulSyscallId
, ulResult
);
49 ulResult
= UserDbgPostServiceHook(ulSyscallId
, ulResult
);
56 Win32kProcessCallback(struct _EPROCESS
*Process
,
59 PPROCESSINFO ppiCurrent
, *pppi
;
70 PVOID UserBase
= NULL
;
71 PRTL_USER_PROCESS_PARAMETERS pParams
= Process
->Peb
->ProcessParameters
;
73 /* We might be called with an already allocated win32 process */
74 ppiCurrent
= PsGetProcessWin32Process(Process
);
75 if (ppiCurrent
!= NULL
)
77 /* There is no more to do for us (this is a success code!) */
78 Status
= STATUS_ALREADY_WIN32
;
82 /* Allocate a new win32 process */
83 ppiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
86 if (ppiCurrent
== NULL
)
88 ERR_CH(UserProcess
, "Failed to allocate ppi for PID:0x%lx\n",
89 HandleToUlong(Process
->UniqueProcessId
));
90 Status
= STATUS_NO_MEMORY
;
94 RtlZeroMemory(ppiCurrent
, sizeof(PROCESSINFO
));
96 PsSetProcessWin32Process(Process
, ppiCurrent
, NULL
);
99 DbgInitDebugChannels();
101 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback
);
105 TRACE_CH(UserProcess
,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent
, HandleToUlong(Process
->UniqueProcessId
));
107 /* map the global heap into the process */
109 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
110 PsGetCurrentProcess(),
118 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
119 if (!NT_SUCCESS(Status
))
121 TRACE_CH(UserProcess
,"Failed to map the global heap! 0x%x\n", Status
);
124 ppiCurrent
->HeapMappings
.Next
= NULL
;
125 ppiCurrent
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
126 ppiCurrent
->HeapMappings
.UserMapping
= UserBase
;
127 ppiCurrent
->HeapMappings
.Count
= 1;
129 InitializeListHead(&ppiCurrent
->MenuListHead
);
131 InitializeListHead(&ppiCurrent
->GDIBrushAttrFreeList
);
132 InitializeListHead(&ppiCurrent
->GDIDcAttrFreeList
);
134 InitializeListHead(&ppiCurrent
->PrivateFontListHead
);
135 ExInitializeFastMutex(&ppiCurrent
->PrivateFontListLock
);
137 InitializeListHead(&ppiCurrent
->DriverObjListHead
);
138 ExInitializeFastMutex(&ppiCurrent
->DriverObjListLock
);
140 ppiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
141 if (!EngCreateEvent((PEVENT
*)&ppiCurrent
->InputIdleEvent
))
146 KeInitializeEvent(ppiCurrent
->InputIdleEvent
, NotificationEvent
, FALSE
);
149 /* map the gdi handle table to user land */
150 Process
->Peb
->GdiSharedHandleTable
= GDI_MapHandleTable(Process
);
151 Process
->Peb
->GdiDCAttributeList
= GDI_BATCH_LIMIT
;
152 pParams
= Process
->Peb
->ProcessParameters
;
154 ppiCurrent
->peProcess
= Process
;
155 /* setup process flags */
156 ppiCurrent
->W32PF_flags
= W32PF_THREADCONNECTED
;
159 pParams
->WindowFlags
& STARTF_SCRNSAVER
)
161 ppiScrnSaver
= ppiCurrent
;
162 ppiCurrent
->W32PF_flags
|= W32PF_SCREENSAVER
;
165 // Fixme check if this process is allowed.
166 ppiCurrent
->W32PF_flags
|= W32PF_ALLOWFOREGROUNDACTIVATE
; // Starting application it will get toggled off.
168 /* Create pools for GDI object attributes */
169 ppiCurrent
->pPoolDcAttr
= GdiPoolCreate(sizeof(DC_ATTR
), 'acdG');
170 ppiCurrent
->pPoolBrushAttr
= GdiPoolCreate(sizeof(BRUSH_ATTR
), 'arbG');
171 ppiCurrent
->pPoolRgnAttr
= GdiPoolCreate(sizeof(RGN_ATTR
), 'agrG');
172 ASSERT(ppiCurrent
->pPoolDcAttr
);
173 ASSERT(ppiCurrent
->pPoolBrushAttr
);
174 ASSERT(ppiCurrent
->pPoolRgnAttr
);
176 /* Add the process to the global list */
177 ppiCurrent
->ppiNext
= gppiList
;
178 gppiList
= ppiCurrent
;
182 /* Get the Win32 Process */
183 ppiCurrent
= PsGetProcessWin32Process(Process
);
187 TRACE_CH(UserProcess
, "Destroying ppi 0x%p\n", ppiCurrent
);
188 ppiCurrent
->W32PF_flags
|= W32PF_TERMINATED
;
190 if (ppiScrnSaver
== ppiCurrent
)
193 if (ppiCurrent
->InputIdleEvent
)
195 EngFreeMem(ppiCurrent
->InputIdleEvent
);
196 ppiCurrent
->InputIdleEvent
= NULL
;
199 IntCleanupMenus(Process
, ppiCurrent
);
200 IntCleanupCurIcons(Process
, ppiCurrent
);
203 GDI_CleanupForProcess(Process
);
205 co_IntGraphicsCheck(FALSE
);
208 * Deregister logon application automatically
210 if(LogonProcess
== ppiCurrent
)
215 /* Close the startup desktop */
216 if(ppiCurrent
->rpdeskStartup
)
217 ObDereferenceObject(ppiCurrent
->rpdeskStartup
);
218 if(ppiCurrent
->hdeskStartup
)
219 ZwClose(ppiCurrent
->hdeskStartup
);
221 /* Close the current window station */
222 UserSetProcessWindowStation(NULL
);
224 /* Destroy GDI pools */
225 GdiPoolDestroy(ppiCurrent
->pPoolDcAttr
);
226 GdiPoolDestroy(ppiCurrent
->pPoolBrushAttr
);
227 GdiPoolDestroy(ppiCurrent
->pPoolRgnAttr
);
229 if (gppiInputProvider
== ppiCurrent
) gppiInputProvider
= NULL
;
232 while (*pppi
!= NULL
&& *pppi
!= ppiCurrent
)
233 pppi
= &(*pppi
)->ppiNext
;
235 ASSERT(*pppi
== ppiCurrent
);
237 *pppi
= ppiCurrent
->ppiNext
;
239 TRACE_CH(UserProcess
,"Freeing ppi 0x%p\n", ppiCurrent
);
241 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent
, DbgChUserObj
, WARN_LEVEL
))
243 DbgUserDumpHandleTable();
247 /* Free the PROCESSINFO */
248 PsSetProcessWin32Process(Process
, NULL
, ppiCurrent
);
249 ExFreePoolWithTag(ppiCurrent
, USERTAG_PROCESSINFO
);
252 Status
= STATUS_SUCCESS
;
260 UserCreateThreadInfo(struct _ETHREAD
*Thread
)
262 struct _EPROCESS
*Process
;
264 PTHREADINFO ptiCurrent
;
266 NTSTATUS Status
= STATUS_SUCCESS
;
268 LARGE_INTEGER LargeTickCount
;
270 Process
= Thread
->ThreadsProcess
;
272 pTeb
= NtCurrentTeb();
276 ptiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
279 if (ptiCurrent
== NULL
)
281 ERR_CH(UserThread
, "Failed to allocate pti for TID %p\n", Thread
->Cid
.UniqueThread
);
282 return STATUS_NO_MEMORY
;
285 TRACE_CH(UserThread
,"Create pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
287 RtlZeroMemory(ptiCurrent
, sizeof(THREADINFO
));
289 /* Initialize the THREADINFO */
291 PsSetThreadWin32Thread(Thread
, ptiCurrent
, NULL
);
292 IntReferenceThreadInfo(ptiCurrent
);
293 ptiCurrent
->pEThread
= Thread
;
294 ptiCurrent
->ppi
= PsGetCurrentProcessWin32Process();
295 pTeb
->Win32ThreadInfo
= ptiCurrent
;
296 ptiCurrent
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
298 TRACE_CH(UserThread
, "Allocated pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
300 InitializeListHead(&ptiCurrent
->WindowListHead
);
301 InitializeListHead(&ptiCurrent
->W32CallbackListHead
);
302 InitializeListHead(&ptiCurrent
->PostedMessagesListHead
);
303 InitializeListHead(&ptiCurrent
->SentMessagesListHead
);
304 InitializeListHead(&ptiCurrent
->DispatchingMessagesHead
);
305 InitializeListHead(&ptiCurrent
->LocalDispatchingMessagesHead
);
306 InitializeListHead(&ptiCurrent
->PtiLink
);
307 for (i
= 0; i
< NB_HOOKS
; i
++)
309 InitializeListHead(&ptiCurrent
->aphkStart
[i
]);
311 ptiCurrent
->ptiSibling
= ptiCurrent
->ppi
->ptiList
;
312 ptiCurrent
->ppi
->ptiList
= ptiCurrent
;
313 ptiCurrent
->ppi
->cThreads
++;
315 ptiCurrent
->hEventQueueClient
= NULL
;
316 Status
= ZwCreateEvent(&ptiCurrent
->hEventQueueClient
, EVENT_ALL_ACCESS
,
317 NULL
, SynchronizationEvent
, FALSE
);
318 if (!NT_SUCCESS(Status
))
322 Status
= ObReferenceObjectByHandle(ptiCurrent
->hEventQueueClient
, 0,
323 *ExEventObjectType
, KernelMode
,
324 (PVOID
*)&ptiCurrent
->pEventQueueServer
, NULL
);
325 if (!NT_SUCCESS(Status
))
327 ZwClose(ptiCurrent
->hEventQueueClient
);
328 ptiCurrent
->hEventQueueClient
= NULL
;
332 KeQueryTickCount(&LargeTickCount
);
333 ptiCurrent
->timeLast
= LargeTickCount
.u
.LowPart
;
335 ptiCurrent
->MessageQueue
= MsqCreateMessageQueue(ptiCurrent
);
336 if(ptiCurrent
->MessageQueue
== NULL
)
338 ERR_CH(UserThread
,"Failed to allocate message loop\n");
339 Status
= STATUS_NO_MEMORY
;
342 ptiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
343 if (ptiCurrent
->KeyboardLayout
)
344 UserReferenceObject(ptiCurrent
->KeyboardLayout
);
345 ptiCurrent
->TIF_flags
&= ~TIF_INCLEANUP
;
346 if (Process
== gpepCSRSS
) /* If this thread is owned by CSRSS, mark it as such */
347 ptiCurrent
->TIF_flags
|= TIF_CSRSSTHREAD
;
348 ptiCurrent
->pcti
= &ptiCurrent
->cti
;
350 /* Initialize the CLIENTINFO */
351 pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
352 RtlZeroMemory(pci
, sizeof(CLIENTINFO
));
353 pci
->ppi
= ptiCurrent
->ppi
;
354 pci
->fsHooks
= ptiCurrent
->fsHooks
;
355 pci
->dwTIFlags
= ptiCurrent
->TIF_flags
;
356 if (ptiCurrent
->KeyboardLayout
)
358 pci
->hKL
= ptiCurrent
->KeyboardLayout
->hkl
;
359 pci
->CodePage
= ptiCurrent
->KeyboardLayout
->CodePage
;
362 /* Assign a default window station and desktop to the process */
363 /* Do not try to open a desktop or window station before winlogon initializes */
364 if(ptiCurrent
->ppi
->hdeskStartup
== NULL
&& LogonProcess
!= NULL
)
366 HWINSTA hWinSta
= NULL
;
368 UNICODE_STRING DesktopPath
;
370 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
373 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
374 * info structure. See documentation of CreateProcess()
376 ProcessParams
= pTeb
->ProcessEnvironmentBlock
->ProcessParameters
;
378 Status
= STATUS_UNSUCCESSFUL
;
379 if(ProcessParams
&& ProcessParams
->DesktopInfo
.Length
> 0)
381 Status
= IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath
, &ProcessParams
->DesktopInfo
);
383 if(!NT_SUCCESS(Status
))
385 RtlInitUnicodeString(&DesktopPath
, NULL
);
388 Status
= IntParseDesktopPath(Process
,
393 if (DesktopPath
.Buffer
)
394 ExFreePoolWithTag(DesktopPath
.Buffer
, TAG_STRING
);
396 if(!NT_SUCCESS(Status
))
398 ERR_CH(UserThread
, "Failed to assign default dekstop and winsta to process\n");
402 if(!UserSetProcessWindowStation(hWinSta
))
404 Status
= STATUS_UNSUCCESSFUL
;
405 ERR_CH(UserThread
,"Failed to set initial process winsta\n");
409 /* Validate the new desktop. */
410 Status
= IntValidateDesktopHandle(hDesk
, UserMode
, 0, &pdesk
);
411 if(!NT_SUCCESS(Status
))
413 ERR_CH(UserThread
,"Failed to validate initial desktop handle\n");
417 /* Store the parsed desktop as the initial desktop */
418 ptiCurrent
->ppi
->hdeskStartup
= hDesk
;
419 ptiCurrent
->ppi
->rpdeskStartup
= pdesk
;
422 if (ptiCurrent
->ppi
->hdeskStartup
!= NULL
)
424 if (!IntSetThreadDesktop(ptiCurrent
->ppi
->hdeskStartup
, FALSE
))
426 ERR_CH(UserThread
,"Failed to set thread desktop\n");
427 Status
= STATUS_UNSUCCESSFUL
;
432 /* mark the thread as fully initialized */
433 ptiCurrent
->TIF_flags
|= TIF_GUITHREADINITIALIZED
;
435 if (!(ptiCurrent
->ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_APPSTARTING
)) &&
436 (gptiForeground
&& gptiForeground
->ppi
== ptiCurrent
->ppi
))
438 ptiCurrent
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
440 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
441 TRACE_CH(UserThread
,"UserCreateW32Thread pti 0x%p\n",ptiCurrent
);
442 return STATUS_SUCCESS
;
445 ERR_CH(UserThread
,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
446 UserDestroyThreadInfo(Thread
);
451 Called from IntDereferenceThreadInfo.
455 UserDeleteW32Thread(PTHREADINFO pti
)
459 TRACE_CH(UserThread
,"UserDeleteW32Thread pti 0x%p\n",pti
);
460 if (pti
->hEventQueueClient
!= NULL
)
461 ZwClose(pti
->hEventQueueClient
);
462 pti
->hEventQueueClient
= NULL
;
464 /* Free the message queue */
465 if (pti
->MessageQueue
)
467 MsqDestroyMessageQueue(pti
);
470 MsqCleanupThreadMsgs(pti
);
472 IntSetThreadDesktop(NULL
, TRUE
);
474 PsSetThreadWin32Thread(pti
->pEThread
, NULL
, pti
);
475 ExFreePoolWithTag(pti
, USERTAG_THREADINFO
);
481 UserDestroyThreadInfo(struct _ETHREAD
*Thread
)
484 PSINGLE_LIST_ENTRY psle
;
485 PPROCESSINFO ppiCurrent
;
486 struct _EPROCESS
*Process
;
487 PTHREADINFO ptiCurrent
;
489 Process
= Thread
->ThreadsProcess
;
491 /* Get the Win32 Thread */
492 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
496 TRACE_CH(UserThread
,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
498 ptiCurrent
->TIF_flags
|= TIF_INCLEANUP
;
499 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
501 ppiCurrent
= ptiCurrent
->ppi
;
504 IsRemoveAttachThread(ptiCurrent
);
506 ptiCurrent
->TIF_flags
|= TIF_DONTATTACHQUEUE
;
507 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
509 /* Decrement thread count and check if its 0 */
510 ppiCurrent
->cThreads
--;
512 if(ptiCurrent
->TIF_flags
& TIF_GUITHREADINITIALIZED
)
514 /* Do now some process cleanup that requires a valid win32 thread */
515 if(ptiCurrent
->ppi
->cThreads
== 0)
517 /* Check if we have registered the user api hook */
518 if(ptiCurrent
->ppi
== ppiUahServer
)
520 /* Unregister the api hook */
521 UserUnregisterUserApiHook();
524 /* Notify logon application to restart shell if needed */
525 if(ptiCurrent
->pDeskInfo
)
527 if(ptiCurrent
->pDeskInfo
->ppiShellProcess
== ppiCurrent
)
529 DWORD ExitCode
= PsGetProcessExitStatus(Process
);
531 TRACE_CH(UserProcess
, "Shell process is exiting (%lu)\n", ExitCode
);
533 UserPostMessage(hwndSAS
,
538 ptiCurrent
->pDeskInfo
->ppiShellProcess
= NULL
;
543 DceFreeThreadDCE(ptiCurrent
);
544 HOOK_DestroyThreadHooks(Thread
);
545 EVENT_DestroyThreadEvents(Thread
);
546 DestroyTimersForThread(ptiCurrent
);
547 KeSetEvent(ptiCurrent
->pEventQueueServer
, IO_NO_INCREMENT
, FALSE
);
548 UnregisterThreadHotKeys(ptiCurrent
);
550 if (IsListEmpty(&ptiCurrent->WindowListHead))
552 ERR_CH(UserThread,"Thread Window List is Empty!\n");
555 co_DestroyThreadWindows(Thread
);
557 if (ppiCurrent
&& ppiCurrent
->ptiList
== ptiCurrent
&& !ptiCurrent
->ptiSibling
&&
558 ppiCurrent
->W32PF_flags
& W32PF_CLASSESREGISTERED
)
560 TRACE_CH(UserThread
,"DestroyProcessClasses\n");
561 /* no process windows should exist at this point, or the function will assert! */
562 DestroyProcessClasses(ppiCurrent
);
563 ppiCurrent
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
566 IntBlockInput(ptiCurrent
, FALSE
);
567 IntCleanupThreadCallbacks(ptiCurrent
);
569 /* cleanup user object references stack */
570 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
573 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(psle
, USER_REFERENCE_ENTRY
, Entry
);
574 TRACE_CH(UserThread
,"thread clean: remove reference obj 0x%p\n",ref
->obj
);
575 UserDereferenceObject(ref
->obj
);
577 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
581 /* Find the THREADINFO in the PROCESSINFO's list */
582 ppti
= &ppiCurrent
->ptiList
;
583 while (*ppti
!= NULL
&& *ppti
!= ptiCurrent
)
585 ppti
= &((*ppti
)->ptiSibling
);
588 /* we must have found it */
589 ASSERT(*ppti
== ptiCurrent
);
591 /* Remove it from the list */
592 *ppti
= ptiCurrent
->ptiSibling
;
594 if (ptiCurrent
->KeyboardLayout
)
595 UserDereferenceObject(ptiCurrent
->KeyboardLayout
);
597 if (gptiForeground
== ptiCurrent
)
599 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
600 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
602 gptiForeground
= NULL
;
605 // Fixes CORE-6384 & CORE-7030.
606 /* if (ptiLastInput == ptiCurrent)
608 if (!ppiCurrent->ptiList)
609 ptiLastInput = gptiForeground;
611 ptiLastInput = ppiCurrent->ptiList;
612 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
615 TRACE_CH(UserThread
,"Freeing pti 0x%p\n", ptiCurrent
);
617 /* Free the THREADINFO */
618 IntDereferenceThreadInfo(ptiCurrent
);
620 return STATUS_SUCCESS
;
625 Win32kThreadCallback(struct _ETHREAD
*Thread
,
626 PSW32THREADCALLOUTTYPE Type
)
630 UserEnterExclusive();
632 ASSERT(NtCurrentTeb());
634 if (Type
== PsW32ThreadCalloutInitialize
)
636 ASSERT(PsGetThreadWin32Thread(Thread
) == NULL
);
637 Status
= UserCreateThreadInfo(Thread
);
641 ASSERT(PsGetThreadWin32Thread(Thread
) != NULL
);
642 Status
= UserDestroyThreadInfo(Thread
);
651 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
657 if (!NT_SUCCESS(Status)) \
659 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
664 * This definition doesn't work
670 IN PDRIVER_OBJECT DriverObject
,
671 IN PUNICODE_STRING RegistryPath
)
675 WIN32_CALLOUTS_FPNS CalloutData
= {0};
676 PVOID GlobalUserHeapBase
= NULL
;
679 * Register user mode call interface
680 * (system service table index = 1)
682 Result
= KeAddSystemServiceTable(Win32kSSDT
,
684 Win32kNumberOfSysCalls
,
689 DPRINT1("Adding system services failed!\n");
690 return STATUS_UNSUCCESSFUL
;
693 hModuleWin
= MmPageEntireDriver(DriverEntry
);
694 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin
);
696 /* Register Object Manager Callbacks */
697 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
698 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
699 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
700 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
701 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
702 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
703 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
704 CalloutData
.DesktopCloseProcedure
= IntDesktopObjectClose
;
705 CalloutData
.DesktopOpenProcedure
= IntDesktopObjectOpen
;
706 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
708 /* Register our per-process and per-thread structures. */
709 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
711 /* Register service hook callbacks */
713 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
714 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
717 /* Create the global USER heap */
718 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
720 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
721 if (GlobalUserHeap
== NULL
)
723 DPRINT1("Failed to initialize the global heap!\n");
724 return STATUS_UNSUCCESSFUL
;
727 /* Allocate global server info structure */
728 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
731 DPRINT1("Failed allocate server info structure!\n");
732 return STATUS_UNSUCCESSFUL
;
735 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
736 DPRINT("Global Server Data -> %p\n", gpsi
);
738 NT_ROF(InitGdiHandleTable());
739 NT_ROF(InitPaletteImpl());
741 /* Create stock objects, ie. precreated objects commonly
742 used by win32 applications */
743 CreateStockObjects();
744 CreateSysColorObjects();
746 NT_ROF(InitBrushImpl());
747 NT_ROF(InitPDEVImpl());
748 NT_ROF(InitLDEVImpl());
749 NT_ROF(InitDeviceImpl());
750 NT_ROF(InitDcImpl());
751 NT_ROF(InitUserImpl());
752 NT_ROF(InitWindowStationImpl());
753 NT_ROF(InitDesktopImpl());
754 NT_ROF(InitInputImpl());
755 NT_ROF(InitKeyboardImpl());
756 NT_ROF(MsqInitializeImpl());
757 NT_ROF(InitTimerImpl());
758 NT_ROF(InitDCEImpl());
760 /* Initialize FreeType library */
761 if (!InitFontSupport())
763 DPRINT1("Unable to initialize font support\n");
767 gusLanguageID
= UserGetLanguageID();
769 return STATUS_SUCCESS
;