[NTOSKRNL]
[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
30 extern ULONG_PTR Win32kSSDT[];
31 extern UCHAR Win32kSSPT[];
32 extern ULONG Win32kNumberOfSysCalls;
33
34 #if DBG
35 void
36 NTAPI
37 DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
38 {
39 GdiDbgPreServiceHook(ulSyscallId, pulArguments);
40 UserDbgPreServiceHook(ulSyscallId, pulArguments);
41 }
42
43 ULONG_PTR
44 NTAPI
45 DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
46 {
47 ulResult = GdiDbgPostServiceHook(ulSyscallId, ulResult);
48 ulResult = UserDbgPostServiceHook(ulSyscallId, ulResult);
49 return ulResult;
50 }
51 #endif
52
53 NTSTATUS
54 APIENTRY
55 Win32kProcessCallback(struct _EPROCESS *Process,
56 BOOLEAN Create)
57 {
58 PPROCESSINFO ppiCurrent;
59 DECLARE_RETURN(NTSTATUS);
60
61 ASSERT(Process->Peb);
62
63 UserEnterExclusive();
64
65 if (Create)
66 {
67 SIZE_T ViewSize = 0;
68 LARGE_INTEGER Offset;
69 PVOID UserBase = NULL;
70 PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
71 NTSTATUS Status;
72
73 ASSERT(PsGetProcessWin32Process(Process) == NULL);
74
75 ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
76 sizeof(PROCESSINFO),
77 USERTAG_PROCESSINFO);
78
79 if (ppiCurrent == NULL)
80 {
81 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId));
82 RETURN( STATUS_NO_MEMORY);
83 }
84
85 RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
86
87 PsSetProcessWin32Process(Process, ppiCurrent);
88
89 #if DBG
90 DbgInitDebugChannels();
91 #if KDBG
92 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
93 #endif
94 #endif
95
96 TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
97
98 /* map the global heap into the process */
99 Offset.QuadPart = 0;
100 Status = MmMapViewOfSection(GlobalUserHeapSection,
101 PsGetCurrentProcess(),
102 &UserBase,
103 0,
104 0,
105 &Offset,
106 &ViewSize,
107 ViewUnmap,
108 SEC_NO_CHANGE,
109 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
110 if (!NT_SUCCESS(Status))
111 {
112 TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
113 RETURN(Status);
114 }
115 ppiCurrent->HeapMappings.Next = NULL;
116 ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
117 ppiCurrent->HeapMappings.UserMapping = UserBase;
118 ppiCurrent->HeapMappings.Count = 1;
119
120 InitializeListHead(&ppiCurrent->MenuListHead);
121
122 InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
123 InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
124
125 InitializeListHead(&ppiCurrent->PrivateFontListHead);
126 ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
127
128 InitializeListHead(&ppiCurrent->DriverObjListHead);
129 ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
130
131 ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
132 if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
133 {
134 KeBugCheck(0);
135 }
136
137 KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
138
139
140 /* map the gdi handle table to user land */
141 Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
142 Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
143 pParams = Process->Peb->ProcessParameters;
144
145 ppiCurrent->peProcess = Process;
146 /* setup process flags */
147 ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
148
149 if ( pParams &&
150 pParams->WindowFlags & STARTF_SCRNSAVER )
151 {
152 ppiScrnSaver = ppiCurrent;
153 ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
154 }
155
156 /* Create pools for GDI object attributes */
157 ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
158 ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
159 ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
160 ASSERT(ppiCurrent->pPoolDcAttr);
161 ASSERT(ppiCurrent->pPoolBrushAttr);
162 ASSERT(ppiCurrent->pPoolRgnAttr);
163 }
164 else
165 {
166 /* Get the Win32 Process */
167 ppiCurrent = PsGetProcessWin32Process(Process);
168
169 ASSERT(ppiCurrent);
170
171 TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
172 ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
173
174 if (ppiScrnSaver == ppiCurrent)
175 ppiScrnSaver = NULL;
176
177 if (ppiCurrent->InputIdleEvent)
178 {
179 EngFreeMem(ppiCurrent->InputIdleEvent);
180 ppiCurrent->InputIdleEvent = NULL;
181 }
182
183 IntCleanupMenus(Process, ppiCurrent);
184 IntCleanupCurIcons(Process, ppiCurrent);
185
186
187 GDI_CleanupForProcess(Process);
188
189 co_IntGraphicsCheck(FALSE);
190
191 /*
192 * Deregister logon application automatically
193 */
194 if(LogonProcess == ppiCurrent)
195 {
196 LogonProcess = NULL;
197 }
198
199 /* Close the startup desktop */
200 if(ppiCurrent->rpdeskStartup)
201 ObDereferenceObject(ppiCurrent->rpdeskStartup);
202 if(ppiCurrent->hdeskStartup)
203 ZwClose(ppiCurrent->hdeskStartup);
204
205 /* Close the current window station */
206 UserSetProcessWindowStation(NULL);
207
208 /* Destroy GDI pools */
209 GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
210 GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
211 GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
212
213 if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
214
215 TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
216
217 /* Ftee the PROCESSINFO */
218 PsSetProcessWin32Process(Process, NULL);
219 ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
220 }
221
222 RETURN( STATUS_SUCCESS);
223
224 CLEANUP:
225 UserLeave();
226 END_CLEANUP;
227 }
228
229 NTSTATUS NTAPI
230 UserCreateThreadInfo(struct _ETHREAD *Thread)
231 {
232 struct _EPROCESS *Process;
233 PCLIENTINFO pci;
234 PTHREADINFO ptiCurrent;
235 int i;
236 NTSTATUS Status = STATUS_SUCCESS;
237 PTEB pTeb;
238
239 Process = Thread->ThreadsProcess;
240
241 pTeb = NtCurrentTeb();
242
243 ASSERT(pTeb);
244
245 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
246 sizeof(THREADINFO),
247 USERTAG_THREADINFO);
248 if (ptiCurrent == NULL)
249 {
250 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
251 return STATUS_NO_MEMORY;
252 }
253
254 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
255
256 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
257
258 PsSetThreadWin32Thread(Thread, ptiCurrent);
259 pTeb->Win32ThreadInfo = ptiCurrent;
260 ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
261
262 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
263
264 /* Initialize the THREADINFO */
265 InitializeListHead(&ptiCurrent->WindowListHead);
266 InitializeListHead(&ptiCurrent->W32CallbackListHead);
267 InitializeListHead(&ptiCurrent->PtiLink);
268 for (i = 0; i < NB_HOOKS; i++)
269 {
270 InitializeListHead(&ptiCurrent->aphkStart[i]);
271 }
272 ptiCurrent->pEThread = Thread;
273 ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
274 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
275 ptiCurrent->ppi->ptiList = ptiCurrent;
276 ptiCurrent->ppi->cThreads++;
277 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
278 if(ptiCurrent->MessageQueue == NULL)
279 {
280 ERR_CH(UserThread,"Failed to allocate message loop\n");
281 Status = STATUS_NO_MEMORY;
282 goto error;
283 }
284 ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
285 if (ptiCurrent->KeyboardLayout)
286 UserReferenceObject(ptiCurrent->KeyboardLayout);
287 ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
288
289 /* Initialize the CLIENTINFO */
290 pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
291 RtlZeroMemory(pci, sizeof(CLIENTINFO));
292 pci->ppi = ptiCurrent->ppi;
293 pci->fsHooks = ptiCurrent->fsHooks;
294 pci->dwTIFlags = ptiCurrent->TIF_flags;
295 if (ptiCurrent->KeyboardLayout)
296 {
297 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
298 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
299 }
300
301 /* Assign a default window station and desktop to the process */
302 /* Do not try to open a desktop or window station before winlogon initializes */
303 if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL)
304 {
305 HWINSTA hWinSta = NULL;
306 HDESK hDesk = NULL;
307 UNICODE_STRING DesktopPath;
308 PDESKTOP pdesk;
309 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
310
311 /*
312 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
313 * info structure. See documentation of CreateProcess()
314 */
315 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
316
317 Status = STATUS_UNSUCCESSFUL;
318 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
319 {
320 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
321 }
322 if(!NT_SUCCESS(Status))
323 {
324 RtlInitUnicodeString(&DesktopPath, NULL);
325 }
326
327 Status = IntParseDesktopPath(Process,
328 &DesktopPath,
329 &hWinSta,
330 &hDesk);
331
332 if (DesktopPath.Buffer)
333 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
334
335 if(!NT_SUCCESS(Status))
336 {
337 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
338 goto error;
339 }
340
341 if(!UserSetProcessWindowStation(hWinSta))
342 {
343 Status = STATUS_UNSUCCESSFUL;
344 ERR_CH(UserThread,"Failed to set initial process winsta\n");
345 goto error;
346 }
347
348 /* Validate the new desktop. */
349 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
350 if(!NT_SUCCESS(Status))
351 {
352 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
353 goto error;
354 }
355
356 /* Store the parsed desktop as the initial desktop */
357 ptiCurrent->ppi->hdeskStartup = hDesk;
358 ptiCurrent->ppi->rpdeskStartup = pdesk;
359 }
360
361 if (ptiCurrent->ppi->hdeskStartup != NULL)
362 {
363 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
364 {
365 ERR_CH(UserThread,"Failed to set thread desktop\n");
366 Status = STATUS_UNSUCCESSFUL;
367 goto error;
368 }
369 }
370
371 /* mark the thread as fully initialized */
372 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
373 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
374
375 return STATUS_SUCCESS;
376
377 error:
378 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
379 UserDestroyThreadInfo(Thread);
380 return Status;
381 }
382
383 NTSTATUS
384 NTAPI
385 UserDestroyThreadInfo(struct _ETHREAD *Thread)
386 {
387 PTHREADINFO *ppti;
388 PSINGLE_LIST_ENTRY psle;
389 PPROCESSINFO ppiCurrent;
390 struct _EPROCESS *Process;
391 PTHREADINFO ptiCurrent;
392
393 Process = Thread->ThreadsProcess;
394
395 /* Get the Win32 Thread */
396 ptiCurrent = PsGetThreadWin32Thread(Thread);
397
398 ASSERT(ptiCurrent);
399
400 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
401
402 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
403 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
404
405 ppiCurrent = ptiCurrent->ppi;
406 ASSERT(ppiCurrent);
407
408 // ptiTo
409 if (IsThreadAttach(ptiCurrent))
410 {
411 PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
412 TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
413 UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
414 }
415
416 // ptiFrom
417 if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
418 {
419 PTHREADINFO ptiTo;
420 ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
421 TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
422 if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
423 else
424 {
425 // eThread maybe okay but Win32Thread already made NULL!
426 ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
427 }
428 }
429
430 /* Decrement thread count and check if its 0 */
431 ppiCurrent->cThreads--;
432
433 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
434 {
435 /* Do now some process cleanup that requires a valid win32 thread */
436 if(ptiCurrent->ppi->cThreads == 0)
437 {
438 /* Check if we have registered the user api hook */
439 if(ptiCurrent->ppi == ppiUahServer)
440 {
441 /* Unregister the api hook */
442 UserUnregisterUserApiHook();
443 }
444
445 /* Notify logon application to restart shell if needed */
446 if(ptiCurrent->pDeskInfo)
447 {
448 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
449 {
450 DWORD ExitCode = PsGetProcessExitStatus(Process);
451
452 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
453
454 UserPostMessage(hwndSAS,
455 WM_LOGONNOTIFY,
456 LN_SHELL_EXITED,
457 ExitCode);
458
459 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
460 }
461 }
462 }
463
464 DceFreeThreadDCE(ptiCurrent);
465 HOOK_DestroyThreadHooks(Thread);
466 EVENT_DestroyThreadEvents(Thread);
467 DestroyTimersForThread(ptiCurrent);
468 KeSetEvent(ptiCurrent->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
469 UnregisterThreadHotKeys(Thread);
470 /*
471 if (IsListEmpty(&ptiCurrent->WindowListHead))
472 {
473 ERR_CH(UserThread,"Thread Window List is Empty!\n");
474 }
475 */
476 co_DestroyThreadWindows(Thread);
477
478 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling)
479 {
480 //ERR_CH(UserThread,"DestroyProcessClasses\n");
481 /* no process windows should exist at this point, or the function will assert! */
482 DestroyProcessClasses(ppiCurrent);
483 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
484 }
485
486 IntBlockInput(ptiCurrent, FALSE);
487 IntCleanupThreadCallbacks(ptiCurrent);
488
489 /* cleanup user object references stack */
490 psle = PopEntryList(&ptiCurrent->ReferencesList);
491 while (psle)
492 {
493 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
494 TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj);
495 UserDereferenceObject(ref->obj);
496
497 psle = PopEntryList(&ptiCurrent->ReferencesList);
498 }
499 }
500
501 /* Free the message queue */
502 if (ptiCurrent->MessageQueue)
503 {
504 MsqDestroyMessageQueue(ptiCurrent);
505 }
506
507 /* Find the THREADINFO in the PROCESSINFO's list */
508 ppti = &ppiCurrent->ptiList;
509 while (*ppti != NULL && *ppti != ptiCurrent)
510 {
511 ppti = &((*ppti)->ptiSibling);
512 }
513
514 /* we must have found it */
515 ASSERT(*ppti == ptiCurrent);
516
517 /* Remove it from the list */
518 *ppti = ptiCurrent->ptiSibling;
519
520 if (ptiCurrent->KeyboardLayout)
521 UserDereferenceObject(ptiCurrent->KeyboardLayout);
522
523 IntSetThreadDesktop(NULL, TRUE);
524
525 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
526
527 /* Free the THREADINFO */
528 PsSetThreadWin32Thread(Thread, NULL);
529 ExFreePoolWithTag(ptiCurrent, USERTAG_THREADINFO);
530
531 return STATUS_SUCCESS;
532 }
533
534 NTSTATUS
535 APIENTRY
536 Win32kThreadCallback(struct _ETHREAD *Thread,
537 PSW32THREADCALLOUTTYPE Type)
538 {
539 NTSTATUS Status;
540
541 UserEnterExclusive();
542
543 ASSERT(NtCurrentTeb());
544
545 if (Type == PsW32ThreadCalloutInitialize)
546 {
547 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
548 Status = UserCreateThreadInfo(Thread);
549 }
550 else
551 {
552 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
553 Status = UserDestroyThreadInfo(Thread);
554 }
555
556 UserLeave();
557
558 return Status;
559 }
560
561 #ifdef _M_IX86
562 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
563 #endif
564
565 // Return on failure
566 #define NT_ROF(x) \
567 Status = (x); \
568 if (!NT_SUCCESS(Status)) \
569 { \
570 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
571 return Status; \
572 }
573
574 /*
575 * This definition doesn't work
576 */
577 INIT_FUNCTION
578 NTSTATUS
579 APIENTRY
580 DriverEntry(
581 IN PDRIVER_OBJECT DriverObject,
582 IN PUNICODE_STRING RegistryPath)
583 {
584 NTSTATUS Status;
585 BOOLEAN Result;
586 WIN32_CALLOUTS_FPNS CalloutData = {0};
587 PVOID GlobalUserHeapBase = NULL;
588
589 /*
590 * Register user mode call interface
591 * (system service table index = 1)
592 */
593 Result = KeAddSystemServiceTable(Win32kSSDT,
594 NULL,
595 Win32kNumberOfSysCalls,
596 Win32kSSPT,
597 1);
598 if (Result == FALSE)
599 {
600 DPRINT1("Adding system services failed!\n");
601 return STATUS_UNSUCCESSFUL;
602 }
603
604 hModuleWin = MmPageEntireDriver(DriverEntry);
605 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
606
607 /* Register Object Manager Callbacks */
608 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
609 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
610 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
611 CalloutData.ProcessCallout = Win32kProcessCallback;
612 CalloutData.ThreadCallout = Win32kThreadCallback;
613 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
614 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
615 CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
616
617 /* Register our per-process and per-thread structures. */
618 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
619
620 /* Register service hook callbacks */
621 #if DBG
622 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
623 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
624 #endif
625
626 /* Create the global USER heap */
627 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
628 &GlobalUserHeapBase,
629 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
630 if (GlobalUserHeap == NULL)
631 {
632 DPRINT1("Failed to initialize the global heap!\n");
633 return STATUS_UNSUCCESSFUL;
634 }
635
636 /* Allocate global server info structure */
637 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
638 if (!gpsi)
639 {
640 DPRINT1("Failed allocate server info structure!\n");
641 return STATUS_UNSUCCESSFUL;
642 }
643
644 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
645 DPRINT("Global Server Data -> %p\n", gpsi);
646
647 NT_ROF(InitGdiHandleTable());
648 NT_ROF(InitPaletteImpl());
649
650 /* Create stock objects, ie. precreated objects commonly
651 used by win32 applications */
652 CreateStockObjects();
653 CreateSysColorObjects();
654
655 NT_ROF(InitBrushImpl());
656 NT_ROF(InitPDEVImpl());
657 NT_ROF(InitLDEVImpl());
658 NT_ROF(InitDeviceImpl());
659 NT_ROF(InitDcImpl());
660 NT_ROF(InitUserImpl());
661 NT_ROF(InitWindowStationImpl());
662 NT_ROF(InitDesktopImpl());
663 NT_ROF(InitInputImpl());
664 NT_ROF(InitKeyboardImpl());
665 NT_ROF(MsqInitializeImpl());
666 NT_ROF(InitTimerImpl());
667 NT_ROF(InitDCEImpl());
668
669 /* Initialize FreeType library */
670 if (!InitFontSupport())
671 {
672 DPRINT1("Unable to initialize font support\n");
673 return Status;
674 }
675
676 gusLanguageID = UserGetLanguageID();
677
678 return STATUS_SUCCESS;
679 }
680
681 /* EOF */