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 PSECTION_OBJECT
*SectionObject
);
19 BOOL NTAPI
GDI_CleanupForProcess (struct _EPROCESS
*Process
);
20 NTSTATUS NTAPI
UserDestroyThreadInfo(struct _ETHREAD
*Thread
);
22 HANDLE GlobalUserHeap
= NULL
;
23 PSECTION_OBJECT 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 /* 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
);
165 /* Add the process to the global list */
166 ppiCurrent
->ppiNext
= gppiList
;
167 gppiList
= ppiCurrent
;
171 /* Get the Win32 Process */
172 ppiCurrent
= PsGetProcessWin32Process(Process
);
176 TRACE_CH(UserProcess
, "Destroying ppi 0x%p\n", ppiCurrent
);
177 ppiCurrent
->W32PF_flags
|= W32PF_TERMINATED
;
179 if (ppiScrnSaver
== ppiCurrent
)
182 if (ppiCurrent
->InputIdleEvent
)
184 EngFreeMem(ppiCurrent
->InputIdleEvent
);
185 ppiCurrent
->InputIdleEvent
= NULL
;
188 IntCleanupMenus(Process
, ppiCurrent
);
189 IntCleanupCurIcons(Process
, ppiCurrent
);
192 GDI_CleanupForProcess(Process
);
194 co_IntGraphicsCheck(FALSE
);
197 * Deregister logon application automatically
199 if(LogonProcess
== ppiCurrent
)
204 /* Close the startup desktop */
205 if(ppiCurrent
->rpdeskStartup
)
206 ObDereferenceObject(ppiCurrent
->rpdeskStartup
);
207 if(ppiCurrent
->hdeskStartup
)
208 ZwClose(ppiCurrent
->hdeskStartup
);
210 /* Close the current window station */
211 UserSetProcessWindowStation(NULL
);
213 /* Destroy GDI pools */
214 GdiPoolDestroy(ppiCurrent
->pPoolDcAttr
);
215 GdiPoolDestroy(ppiCurrent
->pPoolBrushAttr
);
216 GdiPoolDestroy(ppiCurrent
->pPoolRgnAttr
);
218 if (gppiInputProvider
== ppiCurrent
) gppiInputProvider
= NULL
;
221 while (*pppi
!= NULL
&& *pppi
!= ppiCurrent
)
222 pppi
= &(*pppi
)->ppiNext
;
224 ASSERT(*pppi
== ppiCurrent
);
226 *pppi
= ppiCurrent
->ppiNext
;
228 TRACE_CH(UserProcess
,"Freeing ppi 0x%p\n", ppiCurrent
);
230 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent
, DbgChUserObj
, WARN_LEVEL
))
232 DbgUserDumpHandleTable();
236 /* Free the PROCESSINFO */
237 PsSetProcessWin32Process(Process
, NULL
);
238 ExFreePoolWithTag(ppiCurrent
, USERTAG_PROCESSINFO
);
241 RETURN( STATUS_SUCCESS
);
249 UserCreateThreadInfo(struct _ETHREAD
*Thread
)
251 struct _EPROCESS
*Process
;
253 PTHREADINFO ptiCurrent
;
255 NTSTATUS Status
= STATUS_SUCCESS
;
257 LARGE_INTEGER LargeTickCount
;
259 Process
= Thread
->ThreadsProcess
;
261 pTeb
= NtCurrentTeb();
265 ptiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
268 if (ptiCurrent
== NULL
)
270 ERR_CH(UserThread
, "Failed to allocate pti for TID %p\n", Thread
->Cid
.UniqueThread
);
271 return STATUS_NO_MEMORY
;
274 TRACE_CH(UserThread
,"Create pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
276 RtlZeroMemory(ptiCurrent
, sizeof(THREADINFO
));
278 PsSetThreadWin32Thread(Thread
, ptiCurrent
);
279 pTeb
->Win32ThreadInfo
= ptiCurrent
;
280 ptiCurrent
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
282 TRACE_CH(UserThread
, "Allocated pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
284 /* Initialize the THREADINFO */
285 IntReferenceThreadInfo(ptiCurrent
);
286 InitializeListHead(&ptiCurrent
->WindowListHead
);
287 InitializeListHead(&ptiCurrent
->W32CallbackListHead
);
288 InitializeListHead(&ptiCurrent
->PostedMessagesListHead
);
289 InitializeListHead(&ptiCurrent
->SentMessagesListHead
);
290 InitializeListHead(&ptiCurrent
->DispatchingMessagesHead
);
291 InitializeListHead(&ptiCurrent
->LocalDispatchingMessagesHead
);
292 InitializeListHead(&ptiCurrent
->PtiLink
);
293 for (i
= 0; i
< NB_HOOKS
; i
++)
295 InitializeListHead(&ptiCurrent
->aphkStart
[i
]);
297 ptiCurrent
->pEThread
= Thread
;
298 ptiCurrent
->ppi
= PsGetCurrentProcessWin32Process();
299 ptiCurrent
->ptiSibling
= ptiCurrent
->ppi
->ptiList
;
300 ptiCurrent
->ppi
->ptiList
= ptiCurrent
;
301 ptiCurrent
->ppi
->cThreads
++;
303 ptiCurrent
->hEventQueueClient
= NULL
;
304 Status
= ZwCreateEvent(&ptiCurrent
->hEventQueueClient
, EVENT_ALL_ACCESS
,
305 NULL
, SynchronizationEvent
, FALSE
);
306 if (!NT_SUCCESS(Status
))
310 Status
= ObReferenceObjectByHandle(ptiCurrent
->hEventQueueClient
, 0,
311 ExEventObjectType
, KernelMode
,
312 (PVOID
*)&ptiCurrent
->pEventQueueServer
, NULL
);
313 if (!NT_SUCCESS(Status
))
315 ZwClose(ptiCurrent
->hEventQueueClient
);
316 ptiCurrent
->hEventQueueClient
= NULL
;
320 KeQueryTickCount(&LargeTickCount
);
321 ptiCurrent
->timeLast
= LargeTickCount
.u
.LowPart
;
323 ptiCurrent
->MessageQueue
= MsqCreateMessageQueue(ptiCurrent
);
324 if(ptiCurrent
->MessageQueue
== NULL
)
326 ERR_CH(UserThread
,"Failed to allocate message loop\n");
327 Status
= STATUS_NO_MEMORY
;
330 ptiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
331 if (ptiCurrent
->KeyboardLayout
)
332 UserReferenceObject(ptiCurrent
->KeyboardLayout
);
333 ptiCurrent
->TIF_flags
&= ~TIF_INCLEANUP
;
334 if (Process
== gpepCSRSS
) /* If this thread is owned by CSRSS, mark it as such */
335 ptiCurrent
->TIF_flags
|= TIF_CSRSSTHREAD
;
336 ptiCurrent
->pcti
= &ptiCurrent
->cti
;
338 /* Initialize the CLIENTINFO */
339 pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
340 RtlZeroMemory(pci
, sizeof(CLIENTINFO
));
341 pci
->ppi
= ptiCurrent
->ppi
;
342 pci
->fsHooks
= ptiCurrent
->fsHooks
;
343 pci
->dwTIFlags
= ptiCurrent
->TIF_flags
;
344 if (ptiCurrent
->KeyboardLayout
)
346 pci
->hKL
= ptiCurrent
->KeyboardLayout
->hkl
;
347 pci
->CodePage
= ptiCurrent
->KeyboardLayout
->CodePage
;
350 /* Assign a default window station and desktop to the process */
351 /* Do not try to open a desktop or window station before winlogon initializes */
352 if(ptiCurrent
->ppi
->hdeskStartup
== NULL
&& LogonProcess
!= NULL
)
354 HWINSTA hWinSta
= NULL
;
356 UNICODE_STRING DesktopPath
;
358 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
361 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
362 * info structure. See documentation of CreateProcess()
364 ProcessParams
= pTeb
->ProcessEnvironmentBlock
->ProcessParameters
;
366 Status
= STATUS_UNSUCCESSFUL
;
367 if(ProcessParams
&& ProcessParams
->DesktopInfo
.Length
> 0)
369 Status
= IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath
, &ProcessParams
->DesktopInfo
);
371 if(!NT_SUCCESS(Status
))
373 RtlInitUnicodeString(&DesktopPath
, NULL
);
376 Status
= IntParseDesktopPath(Process
,
381 if (DesktopPath
.Buffer
)
382 ExFreePoolWithTag(DesktopPath
.Buffer
, TAG_STRING
);
384 if(!NT_SUCCESS(Status
))
386 ERR_CH(UserThread
, "Failed to assign default dekstop and winsta to process\n");
390 if(!UserSetProcessWindowStation(hWinSta
))
392 Status
= STATUS_UNSUCCESSFUL
;
393 ERR_CH(UserThread
,"Failed to set initial process winsta\n");
397 /* Validate the new desktop. */
398 Status
= IntValidateDesktopHandle(hDesk
, UserMode
, 0, &pdesk
);
399 if(!NT_SUCCESS(Status
))
401 ERR_CH(UserThread
,"Failed to validate initial desktop handle\n");
405 /* Store the parsed desktop as the initial desktop */
406 ptiCurrent
->ppi
->hdeskStartup
= hDesk
;
407 ptiCurrent
->ppi
->rpdeskStartup
= pdesk
;
410 if (ptiCurrent
->ppi
->hdeskStartup
!= NULL
)
412 if (!IntSetThreadDesktop(ptiCurrent
->ppi
->hdeskStartup
, FALSE
))
414 ERR_CH(UserThread
,"Failed to set thread desktop\n");
415 Status
= STATUS_UNSUCCESSFUL
;
420 /* mark the thread as fully initialized */
421 ptiCurrent
->TIF_flags
|= TIF_GUITHREADINITIALIZED
;
422 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
424 return STATUS_SUCCESS
;
427 ERR_CH(UserThread
,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
428 UserDestroyThreadInfo(Thread
);
433 Called from IntDereferenceThreadInfo.
437 UserDeleteW32Thread(PTHREADINFO pti
)
441 ERR_CH(UserThread
,"UserDeleteW32Thread pti 0x%p\n",pti
);
442 if (pti
->hEventQueueClient
!= NULL
)
443 ZwClose(pti
->hEventQueueClient
);
444 pti
->hEventQueueClient
= NULL
;
446 /* Free the message queue */
447 if (pti
->MessageQueue
)
449 MsqDestroyMessageQueue(pti
);
452 MsqCleanupThreadMsgs(pti
);
454 IntSetThreadDesktop(NULL
, TRUE
);
456 PsSetThreadWin32Thread(pti
->pEThread
, NULL
);
457 ExFreePoolWithTag(pti
, USERTAG_THREADINFO
);
463 UserDestroyThreadInfo(struct _ETHREAD
*Thread
)
466 PSINGLE_LIST_ENTRY psle
;
467 PPROCESSINFO ppiCurrent
;
468 struct _EPROCESS
*Process
;
469 PTHREADINFO ptiCurrent
;
471 Process
= Thread
->ThreadsProcess
;
473 /* Get the Win32 Thread */
474 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
478 TRACE_CH(UserThread
,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
480 ptiCurrent
->TIF_flags
|= TIF_INCLEANUP
;
481 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
483 ppiCurrent
= ptiCurrent
->ppi
;
487 if (IsThreadAttach(ptiCurrent
))
489 PTHREADINFO ptiFrom
= IsThreadAttach(ptiCurrent
);
490 TRACE_CH(UserThread
,"Attached Thread ptiTo is getting switched!\n");
491 UserAttachThreadInput(ptiFrom
, ptiCurrent
, FALSE
);
495 if (ptiCurrent
->pqAttach
&& ptiCurrent
->MessageQueue
)
498 ptiTo
= ptiCurrent
->MessageQueue
->ptiOwner
;
499 TRACE_CH(UserThread
,"Attached Thread ptiFrom is getting switched!\n");
500 if (ptiTo
) UserAttachThreadInput( ptiCurrent
, ptiTo
, FALSE
);
503 // eThread maybe okay but Win32Thread already made NULL!
504 ERR_CH(UserThread
,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
508 /* Decrement thread count and check if its 0 */
509 ppiCurrent
->cThreads
--;
511 if(ptiCurrent
->TIF_flags
& TIF_GUITHREADINITIALIZED
)
513 /* Do now some process cleanup that requires a valid win32 thread */
514 if(ptiCurrent
->ppi
->cThreads
== 0)
516 /* Check if we have registered the user api hook */
517 if(ptiCurrent
->ppi
== ppiUahServer
)
519 /* Unregister the api hook */
520 UserUnregisterUserApiHook();
523 /* Notify logon application to restart shell if needed */
524 if(ptiCurrent
->pDeskInfo
)
526 if(ptiCurrent
->pDeskInfo
->ppiShellProcess
== ppiCurrent
)
528 DWORD ExitCode
= PsGetProcessExitStatus(Process
);
530 TRACE_CH(UserProcess
, "Shell process is exiting (%lu)\n", ExitCode
);
532 UserPostMessage(hwndSAS
,
537 ptiCurrent
->pDeskInfo
->ppiShellProcess
= NULL
;
542 DceFreeThreadDCE(ptiCurrent
);
543 HOOK_DestroyThreadHooks(Thread
);
544 EVENT_DestroyThreadEvents(Thread
);
545 DestroyTimersForThread(ptiCurrent
);
546 KeSetEvent(ptiCurrent
->pEventQueueServer
, IO_NO_INCREMENT
, FALSE
);
547 UnregisterThreadHotKeys(Thread
);
549 if (IsListEmpty(&ptiCurrent->WindowListHead))
551 ERR_CH(UserThread,"Thread Window List is Empty!\n");
554 co_DestroyThreadWindows(Thread
);
556 if (ppiCurrent
&& ppiCurrent
->ptiList
== ptiCurrent
&& !ptiCurrent
->ptiSibling
)
558 //ERR_CH(UserThread,"DestroyProcessClasses\n");
559 /* no process windows should exist at this point, or the function will assert! */
560 DestroyProcessClasses(ppiCurrent
);
561 ppiCurrent
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
564 IntBlockInput(ptiCurrent
, FALSE
);
565 IntCleanupThreadCallbacks(ptiCurrent
);
567 /* cleanup user object references stack */
568 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
571 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(psle
, USER_REFERENCE_ENTRY
, Entry
);
572 TRACE_CH(UserThread
,"thread clean: remove reference obj 0x%p\n",ref
->obj
);
573 UserDereferenceObject(ref
->obj
);
575 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
579 /* Find the THREADINFO in the PROCESSINFO's list */
580 ppti
= &ppiCurrent
->ptiList
;
581 while (*ppti
!= NULL
&& *ppti
!= ptiCurrent
)
583 ppti
= &((*ppti
)->ptiSibling
);
586 /* we must have found it */
587 ASSERT(*ppti
== ptiCurrent
);
589 /* Remove it from the list */
590 *ppti
= ptiCurrent
->ptiSibling
;
592 if (ptiCurrent
->KeyboardLayout
)
593 UserDereferenceObject(ptiCurrent
->KeyboardLayout
);
595 IntSetThreadDesktop(NULL
, TRUE
);
597 TRACE_CH(UserThread
,"Freeing pti 0x%p\n", ptiCurrent
);
599 /* Free the THREADINFO */
600 IntDereferenceThreadInfo(ptiCurrent
);
602 return STATUS_SUCCESS
;
607 Win32kThreadCallback(struct _ETHREAD
*Thread
,
608 PSW32THREADCALLOUTTYPE Type
)
612 UserEnterExclusive();
614 ASSERT(NtCurrentTeb());
616 if (Type
== PsW32ThreadCalloutInitialize
)
618 ASSERT(PsGetThreadWin32Thread(Thread
) == NULL
);
619 Status
= UserCreateThreadInfo(Thread
);
623 ASSERT(PsGetThreadWin32Thread(Thread
) != NULL
);
624 Status
= UserDestroyThreadInfo(Thread
);
633 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
639 if (!NT_SUCCESS(Status)) \
641 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
646 * This definition doesn't work
652 IN PDRIVER_OBJECT DriverObject
,
653 IN PUNICODE_STRING RegistryPath
)
657 WIN32_CALLOUTS_FPNS CalloutData
= {0};
658 PVOID GlobalUserHeapBase
= NULL
;
661 * Register user mode call interface
662 * (system service table index = 1)
664 Result
= KeAddSystemServiceTable(Win32kSSDT
,
666 Win32kNumberOfSysCalls
,
671 DPRINT1("Adding system services failed!\n");
672 return STATUS_UNSUCCESSFUL
;
675 hModuleWin
= MmPageEntireDriver(DriverEntry
);
676 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin
);
678 /* Register Object Manager Callbacks */
679 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
680 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
681 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
682 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
683 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
684 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
685 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
686 CalloutData
.DesktopCloseProcedure
= IntDesktopObjectClose
;
687 CalloutData
.DesktopOpenProcedure
= IntDesktopObjectOpen
;
688 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
690 /* Register our per-process and per-thread structures. */
691 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
693 /* Register service hook callbacks */
695 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
696 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
699 /* Create the global USER heap */
700 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
702 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
703 if (GlobalUserHeap
== NULL
)
705 DPRINT1("Failed to initialize the global heap!\n");
706 return STATUS_UNSUCCESSFUL
;
709 /* Allocate global server info structure */
710 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
713 DPRINT1("Failed allocate server info structure!\n");
714 return STATUS_UNSUCCESSFUL
;
717 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
718 DPRINT("Global Server Data -> %p\n", gpsi
);
720 NT_ROF(InitGdiHandleTable());
721 NT_ROF(InitPaletteImpl());
723 /* Create stock objects, ie. precreated objects commonly
724 used by win32 applications */
725 CreateStockObjects();
726 CreateSysColorObjects();
728 NT_ROF(InitBrushImpl());
729 NT_ROF(InitPDEVImpl());
730 NT_ROF(InitLDEVImpl());
731 NT_ROF(InitDeviceImpl());
732 NT_ROF(InitDcImpl());
733 NT_ROF(InitUserImpl());
734 NT_ROF(InitWindowStationImpl());
735 NT_ROF(InitDesktopImpl());
736 NT_ROF(InitInputImpl());
737 NT_ROF(InitKeyboardImpl());
738 NT_ROF(MsqInitializeImpl());
739 NT_ROF(InitTimerImpl());
740 NT_ROF(InitDCEImpl());
742 /* Initialize FreeType library */
743 if (!InitFontSupport())
745 DPRINT1("Unable to initialize font support\n");
749 gusLanguageID
= UserGetLanguageID();
751 return STATUS_SUCCESS
;