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
;
269 OBJECT_ATTRIBUTES EventQueueObjAttr
;
271 Process
= Thread
->ThreadsProcess
;
273 pTeb
= NtCurrentTeb();
277 ptiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
280 if (ptiCurrent
== NULL
)
282 ERR_CH(UserThread
, "Failed to allocate pti for TID %p\n", Thread
->Cid
.UniqueThread
);
283 return STATUS_NO_MEMORY
;
286 TRACE_CH(UserThread
,"Create pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
288 RtlZeroMemory(ptiCurrent
, sizeof(THREADINFO
));
290 /* Initialize the THREADINFO */
292 PsSetThreadWin32Thread(Thread
, ptiCurrent
, NULL
);
293 IntReferenceThreadInfo(ptiCurrent
);
294 ptiCurrent
->pEThread
= Thread
;
295 ptiCurrent
->ppi
= PsGetCurrentProcessWin32Process();
296 pTeb
->Win32ThreadInfo
= ptiCurrent
;
297 ptiCurrent
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
299 TRACE_CH(UserThread
, "Allocated pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
301 InitializeListHead(&ptiCurrent
->WindowListHead
);
302 InitializeListHead(&ptiCurrent
->W32CallbackListHead
);
303 InitializeListHead(&ptiCurrent
->PostedMessagesListHead
);
304 InitializeListHead(&ptiCurrent
->SentMessagesListHead
);
305 InitializeListHead(&ptiCurrent
->DispatchingMessagesHead
);
306 InitializeListHead(&ptiCurrent
->LocalDispatchingMessagesHead
);
307 InitializeListHead(&ptiCurrent
->PtiLink
);
308 for (i
= 0; i
< NB_HOOKS
; i
++)
310 InitializeListHead(&ptiCurrent
->aphkStart
[i
]);
312 ptiCurrent
->ptiSibling
= ptiCurrent
->ppi
->ptiList
;
313 ptiCurrent
->ppi
->ptiList
= ptiCurrent
;
314 ptiCurrent
->ppi
->cThreads
++;
316 ptiCurrent
->hEventQueueClient
= NULL
;
317 InitializeObjectAttributes(&EventQueueObjAttr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
318 Status
= ZwCreateEvent(&ptiCurrent
->hEventQueueClient
, EVENT_ALL_ACCESS
,
319 &EventQueueObjAttr
, SynchronizationEvent
, FALSE
);
320 if (!NT_SUCCESS(Status
))
324 Status
= ObReferenceObjectByHandle(ptiCurrent
->hEventQueueClient
, 0,
325 *ExEventObjectType
, KernelMode
,
326 (PVOID
*)&ptiCurrent
->pEventQueueServer
, NULL
);
327 if (!NT_SUCCESS(Status
))
329 ZwClose(ptiCurrent
->hEventQueueClient
);
330 ptiCurrent
->hEventQueueClient
= NULL
;
334 KeQueryTickCount(&LargeTickCount
);
335 ptiCurrent
->timeLast
= LargeTickCount
.u
.LowPart
;
337 ptiCurrent
->MessageQueue
= MsqCreateMessageQueue(ptiCurrent
);
338 if(ptiCurrent
->MessageQueue
== NULL
)
340 ERR_CH(UserThread
,"Failed to allocate message loop\n");
341 Status
= STATUS_NO_MEMORY
;
344 ptiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
345 if (ptiCurrent
->KeyboardLayout
)
346 UserReferenceObject(ptiCurrent
->KeyboardLayout
);
347 ptiCurrent
->TIF_flags
&= ~TIF_INCLEANUP
;
348 if (Process
== gpepCSRSS
) /* If this thread is owned by CSRSS, mark it as such */
349 ptiCurrent
->TIF_flags
|= TIF_CSRSSTHREAD
;
350 ptiCurrent
->pcti
= &ptiCurrent
->cti
;
352 /* Initialize the CLIENTINFO */
353 pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
354 RtlZeroMemory(pci
, sizeof(CLIENTINFO
));
355 pci
->ppi
= ptiCurrent
->ppi
;
356 pci
->fsHooks
= ptiCurrent
->fsHooks
;
357 pci
->dwTIFlags
= ptiCurrent
->TIF_flags
;
358 if (ptiCurrent
->KeyboardLayout
)
360 pci
->hKL
= ptiCurrent
->KeyboardLayout
->hkl
;
361 pci
->CodePage
= ptiCurrent
->KeyboardLayout
->CodePage
;
364 /* Assign a default window station and desktop to the process */
365 /* Do not try to open a desktop or window station before winlogon initializes */
366 if(ptiCurrent
->ppi
->hdeskStartup
== NULL
&& LogonProcess
!= NULL
)
368 HWINSTA hWinSta
= NULL
;
370 UNICODE_STRING DesktopPath
;
372 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
375 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
376 * info structure. See documentation of CreateProcess()
378 ProcessParams
= pTeb
->ProcessEnvironmentBlock
->ProcessParameters
;
380 Status
= STATUS_UNSUCCESSFUL
;
381 if(ProcessParams
&& ProcessParams
->DesktopInfo
.Length
> 0)
383 Status
= IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath
, &ProcessParams
->DesktopInfo
);
385 if(!NT_SUCCESS(Status
))
387 RtlInitUnicodeString(&DesktopPath
, NULL
);
390 Status
= IntParseDesktopPath(Process
,
395 if (DesktopPath
.Buffer
)
396 ExFreePoolWithTag(DesktopPath
.Buffer
, TAG_STRING
);
398 if(!NT_SUCCESS(Status
))
400 ERR_CH(UserThread
, "Failed to assign default dekstop and winsta to process\n");
404 if(!UserSetProcessWindowStation(hWinSta
))
406 Status
= STATUS_UNSUCCESSFUL
;
407 ERR_CH(UserThread
,"Failed to set initial process winsta\n");
411 /* Validate the new desktop. */
412 Status
= IntValidateDesktopHandle(hDesk
, UserMode
, 0, &pdesk
);
413 if(!NT_SUCCESS(Status
))
415 ERR_CH(UserThread
,"Failed to validate initial desktop handle\n");
419 /* Store the parsed desktop as the initial desktop */
420 ptiCurrent
->ppi
->hdeskStartup
= hDesk
;
421 ptiCurrent
->ppi
->rpdeskStartup
= pdesk
;
424 if (ptiCurrent
->ppi
->hdeskStartup
!= NULL
)
426 if (!IntSetThreadDesktop(ptiCurrent
->ppi
->hdeskStartup
, FALSE
))
428 ERR_CH(UserThread
,"Failed to set thread desktop\n");
429 Status
= STATUS_UNSUCCESSFUL
;
434 /* mark the thread as fully initialized */
435 ptiCurrent
->TIF_flags
|= TIF_GUITHREADINITIALIZED
;
437 if (!(ptiCurrent
->ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_APPSTARTING
)) &&
438 (gptiForeground
&& gptiForeground
->ppi
== ptiCurrent
->ppi
))
440 ptiCurrent
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
442 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
443 TRACE_CH(UserThread
,"UserCreateW32Thread pti 0x%p\n",ptiCurrent
);
444 return STATUS_SUCCESS
;
447 ERR_CH(UserThread
,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent
, Thread
->Cid
.UniqueThread
);
448 UserDestroyThreadInfo(Thread
);
453 Called from IntDereferenceThreadInfo.
457 UserDeleteW32Thread(PTHREADINFO pti
)
461 TRACE_CH(UserThread
,"UserDeleteW32Thread pti 0x%p\n",pti
);
462 if (pti
->hEventQueueClient
!= NULL
)
463 ZwClose(pti
->hEventQueueClient
);
464 pti
->hEventQueueClient
= NULL
;
466 /* Free the message queue */
467 if (pti
->MessageQueue
)
469 MsqDestroyMessageQueue(pti
);
472 MsqCleanupThreadMsgs(pti
);
474 IntSetThreadDesktop(NULL
, TRUE
);
476 PsSetThreadWin32Thread(pti
->pEThread
, NULL
, pti
);
477 ExFreePoolWithTag(pti
, USERTAG_THREADINFO
);
483 UserDestroyThreadInfo(struct _ETHREAD
*Thread
)
486 PSINGLE_LIST_ENTRY psle
;
487 PPROCESSINFO ppiCurrent
;
488 struct _EPROCESS
*Process
;
489 PTHREADINFO ptiCurrent
;
491 Process
= Thread
->ThreadsProcess
;
493 /* Get the Win32 Thread */
494 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
498 TRACE_CH(UserThread
,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
500 ptiCurrent
->TIF_flags
|= TIF_INCLEANUP
;
501 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
503 ppiCurrent
= ptiCurrent
->ppi
;
506 IsRemoveAttachThread(ptiCurrent
);
508 ptiCurrent
->TIF_flags
|= TIF_DONTATTACHQUEUE
;
509 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
511 /* Decrement thread count and check if its 0 */
512 ppiCurrent
->cThreads
--;
514 if(ptiCurrent
->TIF_flags
& TIF_GUITHREADINITIALIZED
)
516 /* Do now some process cleanup that requires a valid win32 thread */
517 if(ptiCurrent
->ppi
->cThreads
== 0)
519 /* Check if we have registered the user api hook */
520 if(ptiCurrent
->ppi
== ppiUahServer
)
522 /* Unregister the api hook */
523 UserUnregisterUserApiHook();
526 /* Notify logon application to restart shell if needed */
527 if(ptiCurrent
->pDeskInfo
)
529 if(ptiCurrent
->pDeskInfo
->ppiShellProcess
== ppiCurrent
)
531 DWORD ExitCode
= PsGetProcessExitStatus(Process
);
533 TRACE_CH(UserProcess
, "Shell process is exiting (%lu)\n", ExitCode
);
535 UserPostMessage(hwndSAS
,
540 ptiCurrent
->pDeskInfo
->ppiShellProcess
= NULL
;
545 DceFreeThreadDCE(ptiCurrent
);
546 HOOK_DestroyThreadHooks(Thread
);
547 EVENT_DestroyThreadEvents(Thread
);
548 DestroyTimersForThread(ptiCurrent
);
549 KeSetEvent(ptiCurrent
->pEventQueueServer
, IO_NO_INCREMENT
, FALSE
);
550 UnregisterThreadHotKeys(ptiCurrent
);
552 if (IsListEmpty(&ptiCurrent->WindowListHead))
554 ERR_CH(UserThread,"Thread Window List is Empty!\n");
557 co_DestroyThreadWindows(Thread
);
559 if (ppiCurrent
&& ppiCurrent
->ptiList
== ptiCurrent
&& !ptiCurrent
->ptiSibling
&&
560 ppiCurrent
->W32PF_flags
& W32PF_CLASSESREGISTERED
)
562 TRACE_CH(UserThread
,"DestroyProcessClasses\n");
563 /* no process windows should exist at this point, or the function will assert! */
564 DestroyProcessClasses(ppiCurrent
);
565 ppiCurrent
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
568 IntBlockInput(ptiCurrent
, FALSE
);
569 IntCleanupThreadCallbacks(ptiCurrent
);
571 /* cleanup user object references stack */
572 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
575 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(psle
, USER_REFERENCE_ENTRY
, Entry
);
576 TRACE_CH(UserThread
,"thread clean: remove reference obj 0x%p\n",ref
->obj
);
577 UserDereferenceObject(ref
->obj
);
579 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
583 /* Find the THREADINFO in the PROCESSINFO's list */
584 ppti
= &ppiCurrent
->ptiList
;
585 while (*ppti
!= NULL
&& *ppti
!= ptiCurrent
)
587 ppti
= &((*ppti
)->ptiSibling
);
590 /* we must have found it */
591 ASSERT(*ppti
== ptiCurrent
);
593 /* Remove it from the list */
594 *ppti
= ptiCurrent
->ptiSibling
;
596 if (ptiCurrent
->KeyboardLayout
)
597 UserDereferenceObject(ptiCurrent
->KeyboardLayout
);
599 if (gptiForeground
== ptiCurrent
)
601 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
602 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
604 gptiForeground
= NULL
;
607 // Fixes CORE-6384 & CORE-7030.
608 /* if (ptiLastInput == ptiCurrent)
610 if (!ppiCurrent->ptiList)
611 ptiLastInput = gptiForeground;
613 ptiLastInput = ppiCurrent->ptiList;
614 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
617 TRACE_CH(UserThread
,"Freeing pti 0x%p\n", ptiCurrent
);
619 /* Free the THREADINFO */
620 IntDereferenceThreadInfo(ptiCurrent
);
622 return STATUS_SUCCESS
;
627 Win32kThreadCallback(struct _ETHREAD
*Thread
,
628 PSW32THREADCALLOUTTYPE Type
)
632 UserEnterExclusive();
634 ASSERT(NtCurrentTeb());
636 if (Type
== PsW32ThreadCalloutInitialize
)
638 ASSERT(PsGetThreadWin32Thread(Thread
) == NULL
);
639 Status
= UserCreateThreadInfo(Thread
);
643 ASSERT(PsGetThreadWin32Thread(Thread
) != NULL
);
644 Status
= UserDestroyThreadInfo(Thread
);
653 C_ASSERT(sizeof(SERVERINFO
) <= PAGE_SIZE
);
659 if (!NT_SUCCESS(Status)) \
661 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
666 * This definition doesn't work
672 IN PDRIVER_OBJECT DriverObject
,
673 IN PUNICODE_STRING RegistryPath
)
677 WIN32_CALLOUTS_FPNS CalloutData
= {0};
678 PVOID GlobalUserHeapBase
= NULL
;
681 * Register user mode call interface
682 * (system service table index = 1)
684 Result
= KeAddSystemServiceTable(Win32kSSDT
,
686 Win32kNumberOfSysCalls
,
691 DPRINT1("Adding system services failed!\n");
692 return STATUS_UNSUCCESSFUL
;
695 hModuleWin
= MmPageEntireDriver(DriverEntry
);
696 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin
);
698 /* Register Object Manager Callbacks */
699 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
700 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
701 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
702 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
703 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
704 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
705 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
706 CalloutData
.DesktopCloseProcedure
= IntDesktopObjectClose
;
707 CalloutData
.DesktopOpenProcedure
= IntDesktopObjectOpen
;
708 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
710 /* Register our per-process and per-thread structures. */
711 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS
)&CalloutData
);
713 /* Register service hook callbacks */
715 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
716 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
719 /* Create the global USER heap */
720 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
722 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
723 if (GlobalUserHeap
== NULL
)
725 DPRINT1("Failed to initialize the global heap!\n");
726 return STATUS_UNSUCCESSFUL
;
729 /* Allocate global server info structure */
730 gpsi
= UserHeapAlloc(sizeof(SERVERINFO
));
733 DPRINT1("Failed allocate server info structure!\n");
734 return STATUS_UNSUCCESSFUL
;
737 RtlZeroMemory(gpsi
, sizeof(SERVERINFO
));
738 DPRINT("Global Server Data -> %p\n", gpsi
);
740 NT_ROF(InitGdiHandleTable());
741 NT_ROF(InitPaletteImpl());
743 /* Create stock objects, ie. precreated objects commonly
744 used by win32 applications */
745 CreateStockObjects();
746 CreateSysColorObjects();
748 NT_ROF(InitBrushImpl());
749 NT_ROF(InitPDEVImpl());
750 NT_ROF(InitLDEVImpl());
751 NT_ROF(InitDeviceImpl());
752 NT_ROF(InitDcImpl());
753 NT_ROF(InitUserImpl());
754 NT_ROF(InitWindowStationImpl());
755 NT_ROF(InitDesktopImpl());
756 NT_ROF(InitInputImpl());
757 NT_ROF(InitKeyboardImpl());
758 NT_ROF(MsqInitializeImpl());
759 NT_ROF(InitTimerImpl());
760 NT_ROF(InitDCEImpl());
762 /* Initialize FreeType library */
763 if (!InitFontSupport())
765 DPRINT1("Unable to initialize font support\n");
769 gusLanguageID
= UserGetLanguageID();
771 return STATUS_SUCCESS
;