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
;
60 DECLARE_RETURN(NTSTATUS
);
70 PVOID UserBase
= NULL
;
71 PRTL_USER_PROCESS_PARAMETERS pParams
= Process
->Peb
->ProcessParameters
;
74 ASSERT(PsGetProcessWin32Process(Process
) == NULL
);
76 ppiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
80 if (ppiCurrent
== NULL
)
82 ERR_CH(UserProcess
, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process
->UniqueProcessId
));
83 RETURN( STATUS_NO_MEMORY
);
86 RtlZeroMemory(ppiCurrent
, sizeof(PROCESSINFO
));
88 PsSetProcessWin32Process(Process
, ppiCurrent
);
91 DbgInitDebugChannels();
93 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback
);
97 TRACE_CH(UserProcess
,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent
, HandleToUlong(Process
->UniqueProcessId
));
99 /* map the global heap into the process */
101 Status
= MmMapViewOfSection(GlobalUserHeapSection
,
102 PsGetCurrentProcess(),
110 PAGE_EXECUTE_READ
); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
111 if (!NT_SUCCESS(Status
))
113 TRACE_CH(UserProcess
,"Failed to map the global heap! 0x%x\n", Status
);
116 ppiCurrent
->HeapMappings
.Next
= NULL
;
117 ppiCurrent
->HeapMappings
.KernelMapping
= (PVOID
)GlobalUserHeap
;
118 ppiCurrent
->HeapMappings
.UserMapping
= UserBase
;
119 ppiCurrent
->HeapMappings
.Count
= 1;
121 InitializeListHead(&ppiCurrent
->MenuListHead
);
123 InitializeListHead(&ppiCurrent
->GDIBrushAttrFreeList
);
124 InitializeListHead(&ppiCurrent
->GDIDcAttrFreeList
);
126 InitializeListHead(&ppiCurrent
->PrivateFontListHead
);
127 ExInitializeFastMutex(&ppiCurrent
->PrivateFontListLock
);
129 InitializeListHead(&ppiCurrent
->DriverObjListHead
);
130 ExInitializeFastMutex(&ppiCurrent
->DriverObjListLock
);
132 ppiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
133 if (!EngCreateEvent((PEVENT
*)&ppiCurrent
->InputIdleEvent
))
138 KeInitializeEvent(ppiCurrent
->InputIdleEvent
, NotificationEvent
, FALSE
);
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
;
146 ppiCurrent
->peProcess
= Process
;
147 /* setup process flags */
148 ppiCurrent
->W32PF_flags
= W32PF_THREADCONNECTED
;
151 pParams
->WindowFlags
& STARTF_SCRNSAVER
)
153 ppiScrnSaver
= ppiCurrent
;
154 ppiCurrent
->W32PF_flags
|= W32PF_SCREENSAVER
;
157 // Fixme check if this process is allowed.
158 ppiCurrent
->W32PF_flags
|= W32PF_ALLOWFOREGROUNDACTIVATE
; // Starting application it will get toggled off.
160 /* Create pools for GDI object attributes */
161 ppiCurrent
->pPoolDcAttr
= GdiPoolCreate(sizeof(DC_ATTR
), 'acdG');
162 ppiCurrent
->pPoolBrushAttr
= GdiPoolCreate(sizeof(BRUSH_ATTR
), 'arbG');
163 ppiCurrent
->pPoolRgnAttr
= GdiPoolCreate(sizeof(RGN_ATTR
), 'agrG');
164 ASSERT(ppiCurrent
->pPoolDcAttr
);
165 ASSERT(ppiCurrent
->pPoolBrushAttr
);
166 ASSERT(ppiCurrent
->pPoolRgnAttr
);
168 /* Add the process to the global list */
169 ppiCurrent
->ppiNext
= gppiList
;
170 gppiList
= ppiCurrent
;
174 /* Get the Win32 Process */
175 ppiCurrent
= PsGetProcessWin32Process(Process
);
179 TRACE_CH(UserProcess
, "Destroying ppi 0x%p\n", ppiCurrent
);
180 ppiCurrent
->W32PF_flags
|= W32PF_TERMINATED
;
182 if (ppiScrnSaver
== ppiCurrent
)
185 if (ppiCurrent
->InputIdleEvent
)
187 EngFreeMem(ppiCurrent
->InputIdleEvent
);
188 ppiCurrent
->InputIdleEvent
= NULL
;
191 IntCleanupMenus(Process
, ppiCurrent
);
192 IntCleanupCurIcons(Process
, ppiCurrent
);
195 GDI_CleanupForProcess(Process
);
197 co_IntGraphicsCheck(FALSE
);
200 * Deregister logon application automatically
202 if(LogonProcess
== ppiCurrent
)
207 /* Close the startup desktop */
208 if(ppiCurrent
->rpdeskStartup
)
209 ObDereferenceObject(ppiCurrent
->rpdeskStartup
);
210 if(ppiCurrent
->hdeskStartup
)
211 ZwClose(ppiCurrent
->hdeskStartup
);
213 /* Close the current window station */
214 UserSetProcessWindowStation(NULL
);
216 /* Destroy GDI pools */
217 GdiPoolDestroy(ppiCurrent
->pPoolDcAttr
);
218 GdiPoolDestroy(ppiCurrent
->pPoolBrushAttr
);
219 GdiPoolDestroy(ppiCurrent
->pPoolRgnAttr
);
221 if (gppiInputProvider
== ppiCurrent
) gppiInputProvider
= NULL
;
224 while (*pppi
!= NULL
&& *pppi
!= ppiCurrent
)
225 pppi
= &(*pppi
)->ppiNext
;
227 ASSERT(*pppi
== ppiCurrent
);
229 *pppi
= ppiCurrent
->ppiNext
;
231 TRACE_CH(UserProcess
,"Freeing ppi 0x%p\n", ppiCurrent
);
233 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent
, DbgChUserObj
, WARN_LEVEL
))
235 DbgUserDumpHandleTable();
239 /* Free the PROCESSINFO */
240 PsSetProcessWin32Process(Process
, NULL
);
241 ExFreePoolWithTag(ppiCurrent
, USERTAG_PROCESSINFO
);
244 RETURN( STATUS_SUCCESS
);
252 UserCreateThreadInfo(struct _ETHREAD
*Thread
)
254 struct _EPROCESS
*Process
;
256 PTHREADINFO ptiCurrent
;
258 NTSTATUS Status
= STATUS_SUCCESS
;
260 LARGE_INTEGER LargeTickCount
;
262 Process
= Thread
->ThreadsProcess
;
264 pTeb
= NtCurrentTeb();
268 ptiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
271 if (ptiCurrent
== NULL
)
273 ERR_CH(UserThread
, "Failed to allocate pti for TID %p\n", Thread
->Cid
.UniqueThread
);
274 return STATUS_NO_MEMORY
;
277 TRACE_CH(UserThread
,"Create pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
279 RtlZeroMemory(ptiCurrent
, sizeof(THREADINFO
));
281 /* Initialize the THREADINFO */
283 PsSetThreadWin32Thread(Thread
, ptiCurrent
);
284 IntReferenceThreadInfo(ptiCurrent
);
285 ptiCurrent
->pEThread
= Thread
;
286 ptiCurrent
->ppi
= PsGetCurrentProcessWin32Process();
287 pTeb
->Win32ThreadInfo
= ptiCurrent
;
288 ptiCurrent
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
290 TRACE_CH(UserThread
, "Allocated pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
292 InitializeListHead(&ptiCurrent
->WindowListHead
);
293 InitializeListHead(&ptiCurrent
->W32CallbackListHead
);
294 InitializeListHead(&ptiCurrent
->PostedMessagesListHead
);
295 InitializeListHead(&ptiCurrent
->SentMessagesListHead
);
296 InitializeListHead(&ptiCurrent
->DispatchingMessagesHead
);
297 InitializeListHead(&ptiCurrent
->LocalDispatchingMessagesHead
);
298 InitializeListHead(&ptiCurrent
->PtiLink
);
299 for (i
= 0; i
< NB_HOOKS
; i
++)
301 InitializeListHead(&ptiCurrent
->aphkStart
[i
]);
303 ptiCurrent
->ptiSibling
= ptiCurrent
->ppi
->ptiList
;
304 ptiCurrent
->ppi
->ptiList
= ptiCurrent
;
305 ptiCurrent
->ppi
->cThreads
++;
307 ptiCurrent
->hEventQueueClient
= NULL
;
308 Status
= ZwCreateEvent(&ptiCurrent
->hEventQueueClient
, EVENT_ALL_ACCESS
,
309 NULL
, SynchronizationEvent
, FALSE
);
310 if (!NT_SUCCESS(Status
))
314 Status
= ObReferenceObjectByHandle(ptiCurrent
->hEventQueueClient
, 0,
315 ExEventObjectType
, KernelMode
,
316 (PVOID
*)&ptiCurrent
->pEventQueueServer
, NULL
);
317 if (!NT_SUCCESS(Status
))
319 ZwClose(ptiCurrent
->hEventQueueClient
);
320 ptiCurrent
->hEventQueueClient
= NULL
;
324 KeQueryTickCount(&LargeTickCount
);
325 ptiCurrent
->timeLast
= LargeTickCount
.u
.LowPart
;
327 ptiCurrent
->MessageQueue
= MsqCreateMessageQueue(ptiCurrent
);
328 if(ptiCurrent
->MessageQueue
== NULL
)
330 ERR_CH(UserThread
,"Failed to allocate message loop\n");
331 Status
= STATUS_NO_MEMORY
;
334 ptiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
335 if (ptiCurrent
->KeyboardLayout
)
336 UserReferenceObject(ptiCurrent
->KeyboardLayout
);
337 ptiCurrent
->TIF_flags
&= ~TIF_INCLEANUP
;
338 if (Process
== gpepCSRSS
) /* If this thread is owned by CSRSS, mark it as such */
339 ptiCurrent
->TIF_flags
|= TIF_CSRSSTHREAD
;
340 ptiCurrent
->pcti
= &ptiCurrent
->cti
;
342 /* Initialize the CLIENTINFO */
343 pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
344 RtlZeroMemory(pci
, sizeof(CLIENTINFO
));
345 pci
->ppi
= ptiCurrent
->ppi
;
346 pci
->fsHooks
= ptiCurrent
->fsHooks
;
347 pci
->dwTIFlags
= ptiCurrent
->TIF_flags
;
348 if (ptiCurrent
->KeyboardLayout
)
350 pci
->hKL
= ptiCurrent
->KeyboardLayout
->hkl
;
351 pci
->CodePage
= ptiCurrent
->KeyboardLayout
->CodePage
;
354 /* Assign a default window station and desktop to the process */
355 /* Do not try to open a desktop or window station before winlogon initializes */
356 if(ptiCurrent
->ppi
->hdeskStartup
== NULL
&& LogonProcess
!= NULL
)
358 HWINSTA hWinSta
= NULL
;
360 UNICODE_STRING DesktopPath
;
362 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
365 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
366 * info structure. See documentation of CreateProcess()
368 ProcessParams
= pTeb
->ProcessEnvironmentBlock
->ProcessParameters
;
370 Status
= STATUS_UNSUCCESSFUL
;
371 if(ProcessParams
&& ProcessParams
->DesktopInfo
.Length
> 0)
373 Status
= IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath
, &ProcessParams
->DesktopInfo
);
375 if(!NT_SUCCESS(Status
))
377 RtlInitUnicodeString(&DesktopPath
, NULL
);
380 Status
= IntParseDesktopPath(Process
,
385 if (DesktopPath
.Buffer
)
386 ExFreePoolWithTag(DesktopPath
.Buffer
, TAG_STRING
);
388 if(!NT_SUCCESS(Status
))
390 ERR_CH(UserThread
, "Failed to assign default dekstop and winsta to process\n");
394 if(!UserSetProcessWindowStation(hWinSta
))
396 Status
= STATUS_UNSUCCESSFUL
;
397 ERR_CH(UserThread
,"Failed to set initial process winsta\n");
401 /* Validate the new desktop. */
402 Status
= IntValidateDesktopHandle(hDesk
, UserMode
, 0, &pdesk
);
403 if(!NT_SUCCESS(Status
))
405 ERR_CH(UserThread
,"Failed to validate initial desktop handle\n");
409 /* Store the parsed desktop as the initial desktop */
410 ptiCurrent
->ppi
->hdeskStartup
= hDesk
;
411 ptiCurrent
->ppi
->rpdeskStartup
= pdesk
;
414 if (ptiCurrent
->ppi
->hdeskStartup
!= NULL
)
416 if (!IntSetThreadDesktop(ptiCurrent
->ppi
->hdeskStartup
, FALSE
))
418 ERR_CH(UserThread
,"Failed to set thread desktop\n");
419 Status
= STATUS_UNSUCCESSFUL
;
424 /* mark the thread as fully initialized */
425 ptiCurrent
->TIF_flags
|= TIF_GUITHREADINITIALIZED
;
427 if (!(ptiCurrent
->ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_APPSTARTING
)) &&
428 (gptiForeground
&& gptiForeground
->ppi
== ptiCurrent
->ppi
))
430 ptiCurrent
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
432 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
433 ERR_CH(UserThread
,"UserCreateW32Thread pti 0x%p\n",ptiCurrent
);
434 return STATUS_SUCCESS
;
437 ERR_CH(UserThread
,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
438 UserDestroyThreadInfo(Thread
);
443 Called from IntDereferenceThreadInfo.
447 UserDeleteW32Thread(PTHREADINFO pti
)
451 ERR_CH(UserThread
,"UserDeleteW32Thread pti 0x%p\n",pti
);
452 if (pti
->hEventQueueClient
!= NULL
)
453 ZwClose(pti
->hEventQueueClient
);
454 pti
->hEventQueueClient
= NULL
;
456 /* Free the message queue */
457 if (pti
->MessageQueue
)
459 MsqDestroyMessageQueue(pti
);
462 MsqCleanupThreadMsgs(pti
);
464 IntSetThreadDesktop(NULL
, TRUE
);
466 PsSetThreadWin32Thread(pti
->pEThread
, NULL
);
467 ExFreePoolWithTag(pti
, USERTAG_THREADINFO
);
473 UserDestroyThreadInfo(struct _ETHREAD
*Thread
)
476 PSINGLE_LIST_ENTRY psle
;
477 PPROCESSINFO ppiCurrent
;
478 struct _EPROCESS
*Process
;
479 PTHREADINFO ptiCurrent
;
481 Process
= Thread
->ThreadsProcess
;
483 /* Get the Win32 Thread */
484 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
488 TRACE_CH(UserThread
,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
490 ptiCurrent
->TIF_flags
|= TIF_INCLEANUP
;
491 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
493 ppiCurrent
= ptiCurrent
->ppi
;
496 IsRemoveAttachThread(ptiCurrent
);
498 ptiCurrent
->TIF_flags
|= TIF_DONTATTACHQUEUE
;
499 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
501 /* Decrement thread count and check if its 0 */
502 ppiCurrent
->cThreads
--;
504 if(ptiCurrent
->TIF_flags
& TIF_GUITHREADINITIALIZED
)
506 /* Do now some process cleanup that requires a valid win32 thread */
507 if(ptiCurrent
->ppi
->cThreads
== 0)
509 /* Check if we have registered the user api hook */
510 if(ptiCurrent
->ppi
== ppiUahServer
)
512 /* Unregister the api hook */
513 UserUnregisterUserApiHook();
516 /* Notify logon application to restart shell if needed */
517 if(ptiCurrent
->pDeskInfo
)
519 if(ptiCurrent
->pDeskInfo
->ppiShellProcess
== ppiCurrent
)
521 DWORD ExitCode
= PsGetProcessExitStatus(Process
);
523 TRACE_CH(UserProcess
, "Shell process is exiting (%lu)\n", ExitCode
);
525 UserPostMessage(hwndSAS
,
530 ptiCurrent
->pDeskInfo
->ppiShellProcess
= NULL
;
535 DceFreeThreadDCE(ptiCurrent
);
536 HOOK_DestroyThreadHooks(Thread
);
537 EVENT_DestroyThreadEvents(Thread
);
538 DestroyTimersForThread(ptiCurrent
);
539 KeSetEvent(ptiCurrent
->pEventQueueServer
, IO_NO_INCREMENT
, FALSE
);
540 UnregisterThreadHotKeys(ptiCurrent
);
542 if (IsListEmpty(&ptiCurrent->WindowListHead))
544 ERR_CH(UserThread,"Thread Window List is Empty!\n");
547 co_DestroyThreadWindows(Thread
);
549 if (ppiCurrent
&& ppiCurrent
->ptiList
== ptiCurrent
&& !ptiCurrent
->ptiSibling
&&
550 ppiCurrent
->W32PF_flags
& W32PF_CLASSESREGISTERED
)
552 ERR_CH(UserThread
,"DestroyProcessClasses\n");
553 /* no process windows should exist at this point, or the function will assert! */
554 DestroyProcessClasses(ppiCurrent
);
555 ppiCurrent
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
558 IntBlockInput(ptiCurrent
, FALSE
);
559 IntCleanupThreadCallbacks(ptiCurrent
);
561 /* cleanup user object references stack */
562 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
565 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(psle
, USER_REFERENCE_ENTRY
, Entry
);
566 TRACE_CH(UserThread
,"thread clean: remove reference obj 0x%p\n",ref
->obj
);
567 UserDereferenceObject(ref
->obj
);
569 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
573 /* Find the THREADINFO in the PROCESSINFO's list */
574 ppti
= &ppiCurrent
->ptiList
;
575 while (*ppti
!= NULL
&& *ppti
!= ptiCurrent
)
577 ppti
= &((*ppti
)->ptiSibling
);
580 /* we must have found it */
581 ASSERT(*ppti
== ptiCurrent
);
583 /* Remove it from the list */
584 *ppti
= ptiCurrent
->ptiSibling
;
586 if (ptiCurrent
->KeyboardLayout
)
587 UserDereferenceObject(ptiCurrent
->KeyboardLayout
);
589 if (gptiForeground
== ptiCurrent
)
591 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
592 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
594 gptiForeground
= NULL
;
597 // Fixes CORE-6384 & CORE-7030.
598 /* if (ptiLastInput == ptiCurrent)
600 if (!ppiCurrent->ptiList)
601 ptiLastInput = gptiForeground;
603 ptiLastInput = ppiCurrent->ptiList;
604 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
607 TRACE_CH(UserThread
,"Freeing pti 0x%p\n", ptiCurrent
);
609 /* Free the THREADINFO */
610 IntDereferenceThreadInfo(ptiCurrent
);
612 return STATUS_SUCCESS
;
617 Win32kThreadCallback(struct _ETHREAD
*Thread
,
618 PSW32THREADCALLOUTTYPE Type
)
622 UserEnterExclusive();
624 ASSERT(NtCurrentTeb());
626 if (Type
== PsW32ThreadCalloutInitialize
)
628 ASSERT(PsGetThreadWin32Thread(Thread
) == NULL
);
629 Status
= UserCreateThreadInfo(Thread
);
633 ASSERT(PsGetThreadWin32Thread(Thread
) != NULL
);
634 Status
= UserDestroyThreadInfo(Thread
);
643 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
649 if (!NT_SUCCESS(Status)) \
651 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
656 * This definition doesn't work
662 IN PDRIVER_OBJECT DriverObject
,
663 IN PUNICODE_STRING RegistryPath
)
667 WIN32_CALLOUTS_FPNS CalloutData
= {0};
668 PVOID GlobalUserHeapBase
= NULL
;
671 * Register user mode call interface
672 * (system service table index = 1)
674 Result
= KeAddSystemServiceTable(Win32kSSDT
,
676 Win32kNumberOfSysCalls
,
681 DPRINT1("Adding system services failed!\n");
682 return STATUS_UNSUCCESSFUL
;
685 hModuleWin
= MmPageEntireDriver(DriverEntry
);
686 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin
);
688 /* Register Object Manager Callbacks */
689 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
690 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
691 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
692 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
693 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
694 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
695 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
696 CalloutData
.DesktopCloseProcedure
= IntDesktopObjectClose
;
697 CalloutData
.DesktopOpenProcedure
= IntDesktopObjectOpen
;
698 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
700 /* Register our per-process and per-thread structures. */
701 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
703 /* Register service hook callbacks */
705 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
706 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
709 /* Create the global USER heap */
710 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
712 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
713 if (GlobalUserHeap
== NULL
)
715 DPRINT1("Failed to initialize the global heap!\n");
716 return STATUS_UNSUCCESSFUL
;
719 /* Allocate global server info structure */
720 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
723 DPRINT1("Failed allocate server info structure!\n");
724 return STATUS_UNSUCCESSFUL
;
727 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
728 DPRINT("Global Server Data -> %p\n", gpsi
);
730 NT_ROF(InitGdiHandleTable());
731 NT_ROF(InitPaletteImpl());
733 /* Create stock objects, ie. precreated objects commonly
734 used by win32 applications */
735 CreateStockObjects();
736 CreateSysColorObjects();
738 NT_ROF(InitBrushImpl());
739 NT_ROF(InitPDEVImpl());
740 NT_ROF(InitLDEVImpl());
741 NT_ROF(InitDeviceImpl());
742 NT_ROF(InitDcImpl());
743 NT_ROF(InitUserImpl());
744 NT_ROF(InitWindowStationImpl());
745 NT_ROF(InitDesktopImpl());
746 NT_ROF(InitInputImpl());
747 NT_ROF(InitKeyboardImpl());
748 NT_ROF(MsqInitializeImpl());
749 NT_ROF(InitTimerImpl());
750 NT_ROF(InitDCEImpl());
752 /* Initialize FreeType library */
753 if (!InitFontSupport())
755 DPRINT1("Unable to initialize font support\n");
759 gusLanguageID
= UserGetLanguageID();
761 return STATUS_SUCCESS
;