Sync with trunk for console graphics palettes.
[reactos.git] / 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 PVOID *SectionObject);
19 BOOL NTAPI GDI_CleanupForProcess (struct _EPROCESS *Process);
20 NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread);
21
22 HANDLE GlobalUserHeap = NULL;
23 PVOID GlobalUserHeapSection = NULL;
24
25 PSERVERINFO gpsi = NULL; // Global User Server Information.
26
27 SHORT gusLanguageID;
28 PPROCESSINFO ppiScrnSaver;
29 PPROCESSINFO gppiList = NULL;
30
31 extern ULONG_PTR Win32kSSDT[];
32 extern UCHAR Win32kSSPT[];
33 extern ULONG Win32kNumberOfSysCalls;
34
35 #if DBG
36 void
37 NTAPI
38 DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
39 {
40 GdiDbgPreServiceHook(ulSyscallId, pulArguments);
41 UserDbgPreServiceHook(ulSyscallId, pulArguments);
42 }
43
44 ULONG_PTR
45 NTAPI
46 DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
47 {
48 ulResult = GdiDbgPostServiceHook(ulSyscallId, ulResult);
49 ulResult = UserDbgPostServiceHook(ulSyscallId, ulResult);
50 return ulResult;
51 }
52 #endif
53
54 NTSTATUS
55 APIENTRY
56 Win32kProcessCallback(struct _EPROCESS *Process,
57 BOOLEAN Create)
58 {
59 PPROCESSINFO ppiCurrent, *pppi;
60 DECLARE_RETURN(NTSTATUS);
61
62 ASSERT(Process->Peb);
63
64 UserEnterExclusive();
65
66 if (Create)
67 {
68 SIZE_T ViewSize = 0;
69 LARGE_INTEGER Offset;
70 PVOID UserBase = NULL;
71 PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
72 NTSTATUS Status;
73
74 ASSERT(PsGetProcessWin32Process(Process) == NULL);
75
76 ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
77 sizeof(PROCESSINFO),
78 USERTAG_PROCESSINFO);
79
80 if (ppiCurrent == NULL)
81 {
82 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId));
83 RETURN( STATUS_NO_MEMORY);
84 }
85
86 RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
87
88 PsSetProcessWin32Process(Process, ppiCurrent);
89
90 #if DBG
91 DbgInitDebugChannels();
92 #if KDBG
93 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
94 #endif
95 #endif
96
97 TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
98
99 /* map the global heap into the process */
100 Offset.QuadPart = 0;
101 Status = MmMapViewOfSection(GlobalUserHeapSection,
102 PsGetCurrentProcess(),
103 &UserBase,
104 0,
105 0,
106 &Offset,
107 &ViewSize,
108 ViewUnmap,
109 SEC_NO_CHANGE,
110 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
111 if (!NT_SUCCESS(Status))
112 {
113 TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
114 RETURN(Status);
115 }
116 ppiCurrent->HeapMappings.Next = NULL;
117 ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
118 ppiCurrent->HeapMappings.UserMapping = UserBase;
119 ppiCurrent->HeapMappings.Count = 1;
120
121 InitializeListHead(&ppiCurrent->MenuListHead);
122
123 InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
124 InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
125
126 InitializeListHead(&ppiCurrent->PrivateFontListHead);
127 ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
128
129 InitializeListHead(&ppiCurrent->DriverObjListHead);
130 ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
131
132 ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
133 if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
134 {
135 KeBugCheck(0);
136 }
137
138 KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
139
140
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;
145
146 ppiCurrent->peProcess = Process;
147 /* setup process flags */
148 ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
149
150 if ( pParams &&
151 pParams->WindowFlags & STARTF_SCRNSAVER )
152 {
153 ppiScrnSaver = ppiCurrent;
154 ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
155 }
156
157 // Fixme check if this process is allowed.
158 ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off.
159
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);
167
168 /* Add the process to the global list */
169 ppiCurrent->ppiNext = gppiList;
170 gppiList = ppiCurrent;
171 }
172 else
173 {
174 /* Get the Win32 Process */
175 ppiCurrent = PsGetProcessWin32Process(Process);
176
177 ASSERT(ppiCurrent);
178
179 TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
180 ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
181
182 if (ppiScrnSaver == ppiCurrent)
183 ppiScrnSaver = NULL;
184
185 if (ppiCurrent->InputIdleEvent)
186 {
187 EngFreeMem(ppiCurrent->InputIdleEvent);
188 ppiCurrent->InputIdleEvent = NULL;
189 }
190
191 IntCleanupMenus(Process, ppiCurrent);
192 IntCleanupCurIcons(Process, ppiCurrent);
193
194
195 GDI_CleanupForProcess(Process);
196
197 co_IntGraphicsCheck(FALSE);
198
199 /*
200 * Deregister logon application automatically
201 */
202 if(LogonProcess == ppiCurrent)
203 {
204 LogonProcess = NULL;
205 }
206
207 /* Close the startup desktop */
208 if(ppiCurrent->rpdeskStartup)
209 ObDereferenceObject(ppiCurrent->rpdeskStartup);
210 if(ppiCurrent->hdeskStartup)
211 ZwClose(ppiCurrent->hdeskStartup);
212
213 /* Close the current window station */
214 UserSetProcessWindowStation(NULL);
215
216 /* Destroy GDI pools */
217 GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
218 GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
219 GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
220
221 if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
222
223 pppi = &gppiList;
224 while (*pppi != NULL && *pppi != ppiCurrent)
225 pppi = &(*pppi)->ppiNext;
226
227 ASSERT(*pppi == ppiCurrent);
228
229 *pppi = ppiCurrent->ppiNext;
230
231 TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
232 #if DBG
233 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
234 {
235 DbgUserDumpHandleTable();
236 }
237 #endif
238
239 /* Free the PROCESSINFO */
240 PsSetProcessWin32Process(Process, NULL);
241 ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
242 }
243
244 RETURN( STATUS_SUCCESS);
245
246 CLEANUP:
247 UserLeave();
248 END_CLEANUP;
249 }
250
251 NTSTATUS NTAPI
252 UserCreateThreadInfo(struct _ETHREAD *Thread)
253 {
254 struct _EPROCESS *Process;
255 PCLIENTINFO pci;
256 PTHREADINFO ptiCurrent;
257 int i;
258 NTSTATUS Status = STATUS_SUCCESS;
259 PTEB pTeb;
260 LARGE_INTEGER LargeTickCount;
261
262 Process = Thread->ThreadsProcess;
263
264 pTeb = NtCurrentTeb();
265
266 ASSERT(pTeb);
267
268 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
269 sizeof(THREADINFO),
270 USERTAG_THREADINFO);
271 if (ptiCurrent == NULL)
272 {
273 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
274 return STATUS_NO_MEMORY;
275 }
276
277 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
278
279 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
280
281 /* Initialize the THREADINFO */
282
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;
289
290 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
291
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++)
300 {
301 InitializeListHead(&ptiCurrent->aphkStart[i]);
302 }
303 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
304 ptiCurrent->ppi->ptiList = ptiCurrent;
305 ptiCurrent->ppi->cThreads++;
306
307 ptiCurrent->hEventQueueClient = NULL;
308 Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS,
309 NULL, SynchronizationEvent, FALSE);
310 if (!NT_SUCCESS(Status))
311 {
312 goto error;
313 }
314 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
315 ExEventObjectType, KernelMode,
316 (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
317 if (!NT_SUCCESS(Status))
318 {
319 ZwClose(ptiCurrent->hEventQueueClient);
320 ptiCurrent->hEventQueueClient = NULL;
321 goto error;
322 }
323
324 KeQueryTickCount(&LargeTickCount);
325 ptiCurrent->timeLast = LargeTickCount.u.LowPart;
326
327 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
328 if(ptiCurrent->MessageQueue == NULL)
329 {
330 ERR_CH(UserThread,"Failed to allocate message loop\n");
331 Status = STATUS_NO_MEMORY;
332 goto error;
333 }
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;
341
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)
349 {
350 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
351 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
352 }
353
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)
357 {
358 HWINSTA hWinSta = NULL;
359 HDESK hDesk = NULL;
360 UNICODE_STRING DesktopPath;
361 PDESKTOP pdesk;
362 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
363
364 /*
365 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
366 * info structure. See documentation of CreateProcess()
367 */
368 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
369
370 Status = STATUS_UNSUCCESSFUL;
371 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
372 {
373 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
374 }
375 if(!NT_SUCCESS(Status))
376 {
377 RtlInitUnicodeString(&DesktopPath, NULL);
378 }
379
380 Status = IntParseDesktopPath(Process,
381 &DesktopPath,
382 &hWinSta,
383 &hDesk);
384
385 if (DesktopPath.Buffer)
386 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
387
388 if(!NT_SUCCESS(Status))
389 {
390 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
391 goto error;
392 }
393
394 if(!UserSetProcessWindowStation(hWinSta))
395 {
396 Status = STATUS_UNSUCCESSFUL;
397 ERR_CH(UserThread,"Failed to set initial process winsta\n");
398 goto error;
399 }
400
401 /* Validate the new desktop. */
402 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
403 if(!NT_SUCCESS(Status))
404 {
405 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
406 goto error;
407 }
408
409 /* Store the parsed desktop as the initial desktop */
410 ptiCurrent->ppi->hdeskStartup = hDesk;
411 ptiCurrent->ppi->rpdeskStartup = pdesk;
412 }
413
414 if (ptiCurrent->ppi->hdeskStartup != NULL)
415 {
416 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
417 {
418 ERR_CH(UserThread,"Failed to set thread desktop\n");
419 Status = STATUS_UNSUCCESSFUL;
420 goto error;
421 }
422 }
423
424 /* mark the thread as fully initialized */
425 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
426
427 if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) &&
428 (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi ))
429 {
430 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
431 }
432 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
433 ERR_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent);
434 return STATUS_SUCCESS;
435
436 error:
437 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
438 UserDestroyThreadInfo(Thread);
439 return Status;
440 }
441
442 /*
443 Called from IntDereferenceThreadInfo.
444 */
445 VOID
446 FASTCALL
447 UserDeleteW32Thread(PTHREADINFO pti)
448 {
449 if (!pti->RefCount)
450 {
451 ERR_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
452 if (pti->hEventQueueClient != NULL)
453 ZwClose(pti->hEventQueueClient);
454 pti->hEventQueueClient = NULL;
455
456 /* Free the message queue */
457 if (pti->MessageQueue)
458 {
459 MsqDestroyMessageQueue(pti);
460 }
461
462 MsqCleanupThreadMsgs(pti);
463
464 IntSetThreadDesktop(NULL, TRUE);
465
466 PsSetThreadWin32Thread(pti->pEThread, NULL);
467 ExFreePoolWithTag(pti, USERTAG_THREADINFO);
468 }
469 }
470
471 NTSTATUS
472 NTAPI
473 UserDestroyThreadInfo(struct _ETHREAD *Thread)
474 {
475 PTHREADINFO *ppti;
476 PSINGLE_LIST_ENTRY psle;
477 PPROCESSINFO ppiCurrent;
478 struct _EPROCESS *Process;
479 PTHREADINFO ptiCurrent;
480
481 Process = Thread->ThreadsProcess;
482
483 /* Get the Win32 Thread */
484 ptiCurrent = PsGetThreadWin32Thread(Thread);
485
486 ASSERT(ptiCurrent);
487
488 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
489
490 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
491 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
492
493 ppiCurrent = ptiCurrent->ppi;
494 ASSERT(ppiCurrent);
495
496 IsRemoveAttachThread(ptiCurrent);
497
498 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE;
499 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
500
501 /* Decrement thread count and check if its 0 */
502 ppiCurrent->cThreads--;
503
504 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
505 {
506 /* Do now some process cleanup that requires a valid win32 thread */
507 if(ptiCurrent->ppi->cThreads == 0)
508 {
509 /* Check if we have registered the user api hook */
510 if(ptiCurrent->ppi == ppiUahServer)
511 {
512 /* Unregister the api hook */
513 UserUnregisterUserApiHook();
514 }
515
516 /* Notify logon application to restart shell if needed */
517 if(ptiCurrent->pDeskInfo)
518 {
519 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
520 {
521 DWORD ExitCode = PsGetProcessExitStatus(Process);
522
523 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
524
525 UserPostMessage(hwndSAS,
526 WM_LOGONNOTIFY,
527 LN_SHELL_EXITED,
528 ExitCode);
529
530 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
531 }
532 }
533 }
534
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);
541 /*
542 if (IsListEmpty(&ptiCurrent->WindowListHead))
543 {
544 ERR_CH(UserThread,"Thread Window List is Empty!\n");
545 }
546 */
547 co_DestroyThreadWindows(Thread);
548
549 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
550 ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
551 {
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;
556 }
557
558 IntBlockInput(ptiCurrent, FALSE);
559 IntCleanupThreadCallbacks(ptiCurrent);
560
561 /* cleanup user object references stack */
562 psle = PopEntryList(&ptiCurrent->ReferencesList);
563 while (psle)
564 {
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);
568
569 psle = PopEntryList(&ptiCurrent->ReferencesList);
570 }
571 }
572
573 /* Find the THREADINFO in the PROCESSINFO's list */
574 ppti = &ppiCurrent->ptiList;
575 while (*ppti != NULL && *ppti != ptiCurrent)
576 {
577 ppti = &((*ppti)->ptiSibling);
578 }
579
580 /* we must have found it */
581 ASSERT(*ppti == ptiCurrent);
582
583 /* Remove it from the list */
584 *ppti = ptiCurrent->ptiSibling;
585
586 if (ptiCurrent->KeyboardLayout)
587 UserDereferenceObject(ptiCurrent->KeyboardLayout);
588
589 if (gptiForeground == ptiCurrent)
590 {
591 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
592 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
593
594 gptiForeground = NULL;
595 }
596
597 // Fixes CORE-6384 & CORE-7030.
598 /* if (ptiLastInput == ptiCurrent)
599 {
600 if (!ppiCurrent->ptiList)
601 ptiLastInput = gptiForeground;
602 else
603 ptiLastInput = ppiCurrent->ptiList;
604 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
605 }
606 */
607 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
608
609 /* Free the THREADINFO */
610 IntDereferenceThreadInfo(ptiCurrent);
611
612 return STATUS_SUCCESS;
613 }
614
615 NTSTATUS
616 APIENTRY
617 Win32kThreadCallback(struct _ETHREAD *Thread,
618 PSW32THREADCALLOUTTYPE Type)
619 {
620 NTSTATUS Status;
621
622 UserEnterExclusive();
623
624 ASSERT(NtCurrentTeb());
625
626 if (Type == PsW32ThreadCalloutInitialize)
627 {
628 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
629 Status = UserCreateThreadInfo(Thread);
630 }
631 else
632 {
633 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
634 Status = UserDestroyThreadInfo(Thread);
635 }
636
637 UserLeave();
638
639 return Status;
640 }
641
642 #ifdef _M_IX86
643 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
644 #endif
645
646 // Return on failure
647 #define NT_ROF(x) \
648 Status = (x); \
649 if (!NT_SUCCESS(Status)) \
650 { \
651 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
652 return Status; \
653 }
654
655 /*
656 * This definition doesn't work
657 */
658 INIT_FUNCTION
659 NTSTATUS
660 APIENTRY
661 DriverEntry(
662 IN PDRIVER_OBJECT DriverObject,
663 IN PUNICODE_STRING RegistryPath)
664 {
665 NTSTATUS Status;
666 BOOLEAN Result;
667 WIN32_CALLOUTS_FPNS CalloutData = {0};
668 PVOID GlobalUserHeapBase = NULL;
669
670 /*
671 * Register user mode call interface
672 * (system service table index = 1)
673 */
674 Result = KeAddSystemServiceTable(Win32kSSDT,
675 NULL,
676 Win32kNumberOfSysCalls,
677 Win32kSSPT,
678 1);
679 if (Result == FALSE)
680 {
681 DPRINT1("Adding system services failed!\n");
682 return STATUS_UNSUCCESSFUL;
683 }
684
685 hModuleWin = MmPageEntireDriver(DriverEntry);
686 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
687
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;
699
700 /* Register our per-process and per-thread structures. */
701 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
702
703 /* Register service hook callbacks */
704 #if DBG
705 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
706 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
707 #endif
708
709 /* Create the global USER heap */
710 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
711 &GlobalUserHeapBase,
712 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
713 if (GlobalUserHeap == NULL)
714 {
715 DPRINT1("Failed to initialize the global heap!\n");
716 return STATUS_UNSUCCESSFUL;
717 }
718
719 /* Allocate global server info structure */
720 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
721 if (!gpsi)
722 {
723 DPRINT1("Failed allocate server info structure!\n");
724 return STATUS_UNSUCCESSFUL;
725 }
726
727 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
728 DPRINT("Global Server Data -> %p\n", gpsi);
729
730 NT_ROF(InitGdiHandleTable());
731 NT_ROF(InitPaletteImpl());
732
733 /* Create stock objects, ie. precreated objects commonly
734 used by win32 applications */
735 CreateStockObjects();
736 CreateSysColorObjects();
737
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());
751
752 /* Initialize FreeType library */
753 if (!InitFontSupport())
754 {
755 DPRINT1("Unable to initialize font support\n");
756 return Status;
757 }
758
759 gusLanguageID = UserGetLanguageID();
760
761 return STATUS_SUCCESS;
762 }
763
764 /* EOF */