Sync with trunk r63502.
[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 NTSTATUS Status;
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
73 /* We might be called with an already allocated win32 process */
74 ppiCurrent = PsGetProcessWin32Process(Process);
75 if (ppiCurrent != NULL)
76 {
77 /* There is no more to do for us (this is a success code!) */
78 Status = STATUS_ALREADY_WIN32;
79 goto Leave;
80 }
81
82 /* Allocate a new win32 process */
83 ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
84 sizeof(PROCESSINFO),
85 USERTAG_PROCESSINFO);
86 if (ppiCurrent == NULL)
87 {
88 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n",
89 HandleToUlong(Process->UniqueProcessId));
90 Status = STATUS_NO_MEMORY;
91 goto Leave;
92 }
93
94 RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
95
96 PsSetProcessWin32Process(Process, ppiCurrent, NULL);
97
98 #if DBG
99 DbgInitDebugChannels();
100 #if KDBG
101 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
102 #endif
103 #endif
104
105 TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
106
107 /* map the global heap into the process */
108 Offset.QuadPart = 0;
109 Status = MmMapViewOfSection(GlobalUserHeapSection,
110 PsGetCurrentProcess(),
111 &UserBase,
112 0,
113 0,
114 &Offset,
115 &ViewSize,
116 ViewUnmap,
117 SEC_NO_CHANGE,
118 PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
119 if (!NT_SUCCESS(Status))
120 {
121 TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
122 goto Leave;
123 }
124 ppiCurrent->HeapMappings.Next = NULL;
125 ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
126 ppiCurrent->HeapMappings.UserMapping = UserBase;
127 ppiCurrent->HeapMappings.Count = 1;
128
129 InitializeListHead(&ppiCurrent->MenuListHead);
130
131 InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
132 InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
133
134 InitializeListHead(&ppiCurrent->PrivateFontListHead);
135 ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
136
137 InitializeListHead(&ppiCurrent->DriverObjListHead);
138 ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
139
140 ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
141 if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
142 {
143 KeBugCheck(0);
144 }
145
146 KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
147
148
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;
153
154 ppiCurrent->peProcess = Process;
155 /* setup process flags */
156 ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
157
158 if ( pParams &&
159 pParams->WindowFlags & STARTF_SCRNSAVER )
160 {
161 ppiScrnSaver = ppiCurrent;
162 ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
163 }
164
165 // Fixme check if this process is allowed.
166 ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off.
167
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);
175
176 /* Add the process to the global list */
177 ppiCurrent->ppiNext = gppiList;
178 gppiList = ppiCurrent;
179 }
180 else
181 {
182 /* Get the Win32 Process */
183 ppiCurrent = PsGetProcessWin32Process(Process);
184
185 ASSERT(ppiCurrent);
186
187 TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
188 ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
189
190 if (ppiScrnSaver == ppiCurrent)
191 ppiScrnSaver = NULL;
192
193 if (ppiCurrent->InputIdleEvent)
194 {
195 EngFreeMem(ppiCurrent->InputIdleEvent);
196 ppiCurrent->InputIdleEvent = NULL;
197 }
198
199 IntCleanupMenus(Process, ppiCurrent);
200 IntCleanupCurIcons(Process, ppiCurrent);
201
202
203 GDI_CleanupForProcess(Process);
204
205 co_IntGraphicsCheck(FALSE);
206
207 /*
208 * Deregister logon application automatically
209 */
210 if(LogonProcess == ppiCurrent)
211 {
212 LogonProcess = NULL;
213 }
214
215 /* Close the startup desktop */
216 if(ppiCurrent->rpdeskStartup)
217 ObDereferenceObject(ppiCurrent->rpdeskStartup);
218 if(ppiCurrent->hdeskStartup)
219 ZwClose(ppiCurrent->hdeskStartup);
220
221 /* Close the current window station */
222 UserSetProcessWindowStation(NULL);
223
224 /* Destroy GDI pools */
225 GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
226 GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
227 GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
228
229 if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
230
231 pppi = &gppiList;
232 while (*pppi != NULL && *pppi != ppiCurrent)
233 pppi = &(*pppi)->ppiNext;
234
235 ASSERT(*pppi == ppiCurrent);
236
237 *pppi = ppiCurrent->ppiNext;
238
239 TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
240 #if DBG
241 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
242 {
243 DbgUserDumpHandleTable();
244 }
245 #endif
246
247 /* Free the PROCESSINFO */
248 PsSetProcessWin32Process(Process, NULL, ppiCurrent);
249 ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
250 }
251
252 Status = STATUS_SUCCESS;
253
254 Leave:
255 UserLeave();
256 return Status;
257 }
258
259 NTSTATUS NTAPI
260 UserCreateThreadInfo(struct _ETHREAD *Thread)
261 {
262 struct _EPROCESS *Process;
263 PCLIENTINFO pci;
264 PTHREADINFO ptiCurrent;
265 int i;
266 NTSTATUS Status = STATUS_SUCCESS;
267 PTEB pTeb;
268 LARGE_INTEGER LargeTickCount;
269
270 Process = Thread->ThreadsProcess;
271
272 pTeb = NtCurrentTeb();
273
274 ASSERT(pTeb);
275
276 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
277 sizeof(THREADINFO),
278 USERTAG_THREADINFO);
279 if (ptiCurrent == NULL)
280 {
281 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
282 return STATUS_NO_MEMORY;
283 }
284
285 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
286
287 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
288
289 /* Initialize the THREADINFO */
290
291 PsSetThreadWin32Thread(Thread, ptiCurrent, NULL);
292 IntReferenceThreadInfo(ptiCurrent);
293 ptiCurrent->pEThread = Thread;
294 ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
295 pTeb->Win32ThreadInfo = ptiCurrent;
296 ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
297
298 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
299
300 InitializeListHead(&ptiCurrent->WindowListHead);
301 InitializeListHead(&ptiCurrent->W32CallbackListHead);
302 InitializeListHead(&ptiCurrent->PostedMessagesListHead);
303 InitializeListHead(&ptiCurrent->SentMessagesListHead);
304 InitializeListHead(&ptiCurrent->DispatchingMessagesHead);
305 InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead);
306 InitializeListHead(&ptiCurrent->PtiLink);
307 for (i = 0; i < NB_HOOKS; i++)
308 {
309 InitializeListHead(&ptiCurrent->aphkStart[i]);
310 }
311 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
312 ptiCurrent->ppi->ptiList = ptiCurrent;
313 ptiCurrent->ppi->cThreads++;
314
315 ptiCurrent->hEventQueueClient = NULL;
316 Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS,
317 NULL, SynchronizationEvent, FALSE);
318 if (!NT_SUCCESS(Status))
319 {
320 goto error;
321 }
322 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
323 *ExEventObjectType, KernelMode,
324 (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
325 if (!NT_SUCCESS(Status))
326 {
327 ZwClose(ptiCurrent->hEventQueueClient);
328 ptiCurrent->hEventQueueClient = NULL;
329 goto error;
330 }
331
332 KeQueryTickCount(&LargeTickCount);
333 ptiCurrent->timeLast = LargeTickCount.u.LowPart;
334
335 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
336 if(ptiCurrent->MessageQueue == NULL)
337 {
338 ERR_CH(UserThread,"Failed to allocate message loop\n");
339 Status = STATUS_NO_MEMORY;
340 goto error;
341 }
342 ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
343 if (ptiCurrent->KeyboardLayout)
344 UserReferenceObject(ptiCurrent->KeyboardLayout);
345 ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
346 if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */
347 ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD;
348 ptiCurrent->pcti = &ptiCurrent->cti;
349
350 /* Initialize the CLIENTINFO */
351 pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
352 RtlZeroMemory(pci, sizeof(CLIENTINFO));
353 pci->ppi = ptiCurrent->ppi;
354 pci->fsHooks = ptiCurrent->fsHooks;
355 pci->dwTIFlags = ptiCurrent->TIF_flags;
356 if (ptiCurrent->KeyboardLayout)
357 {
358 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
359 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
360 }
361
362 /* Assign a default window station and desktop to the process */
363 /* Do not try to open a desktop or window station before winlogon initializes */
364 if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL)
365 {
366 HWINSTA hWinSta = NULL;
367 HDESK hDesk = NULL;
368 UNICODE_STRING DesktopPath;
369 PDESKTOP pdesk;
370 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
371
372 /*
373 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
374 * info structure. See documentation of CreateProcess()
375 */
376 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
377
378 Status = STATUS_UNSUCCESSFUL;
379 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
380 {
381 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
382 }
383 if(!NT_SUCCESS(Status))
384 {
385 RtlInitUnicodeString(&DesktopPath, NULL);
386 }
387
388 Status = IntParseDesktopPath(Process,
389 &DesktopPath,
390 &hWinSta,
391 &hDesk);
392
393 if (DesktopPath.Buffer)
394 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
395
396 if(!NT_SUCCESS(Status))
397 {
398 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
399 goto error;
400 }
401
402 if(!UserSetProcessWindowStation(hWinSta))
403 {
404 Status = STATUS_UNSUCCESSFUL;
405 ERR_CH(UserThread,"Failed to set initial process winsta\n");
406 goto error;
407 }
408
409 /* Validate the new desktop. */
410 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
411 if(!NT_SUCCESS(Status))
412 {
413 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
414 goto error;
415 }
416
417 /* Store the parsed desktop as the initial desktop */
418 ptiCurrent->ppi->hdeskStartup = hDesk;
419 ptiCurrent->ppi->rpdeskStartup = pdesk;
420 }
421
422 if (ptiCurrent->ppi->hdeskStartup != NULL)
423 {
424 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
425 {
426 ERR_CH(UserThread,"Failed to set thread desktop\n");
427 Status = STATUS_UNSUCCESSFUL;
428 goto error;
429 }
430 }
431
432 /* mark the thread as fully initialized */
433 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
434
435 if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) &&
436 (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi ))
437 {
438 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
439 }
440 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
441 TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent);
442 return STATUS_SUCCESS;
443
444 error:
445 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
446 UserDestroyThreadInfo(Thread);
447 return Status;
448 }
449
450 /*
451 Called from IntDereferenceThreadInfo.
452 */
453 VOID
454 FASTCALL
455 UserDeleteW32Thread(PTHREADINFO pti)
456 {
457 if (!pti->RefCount)
458 {
459 TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
460 if (pti->hEventQueueClient != NULL)
461 ZwClose(pti->hEventQueueClient);
462 pti->hEventQueueClient = NULL;
463
464 /* Free the message queue */
465 if (pti->MessageQueue)
466 {
467 MsqDestroyMessageQueue(pti);
468 }
469
470 MsqCleanupThreadMsgs(pti);
471
472 IntSetThreadDesktop(NULL, TRUE);
473
474 PsSetThreadWin32Thread(pti->pEThread, NULL, pti);
475 ExFreePoolWithTag(pti, USERTAG_THREADINFO);
476 }
477 }
478
479 NTSTATUS
480 NTAPI
481 UserDestroyThreadInfo(struct _ETHREAD *Thread)
482 {
483 PTHREADINFO *ppti;
484 PSINGLE_LIST_ENTRY psle;
485 PPROCESSINFO ppiCurrent;
486 struct _EPROCESS *Process;
487 PTHREADINFO ptiCurrent;
488
489 Process = Thread->ThreadsProcess;
490
491 /* Get the Win32 Thread */
492 ptiCurrent = PsGetThreadWin32Thread(Thread);
493
494 ASSERT(ptiCurrent);
495
496 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
497
498 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
499 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
500
501 ppiCurrent = ptiCurrent->ppi;
502 ASSERT(ppiCurrent);
503
504 IsRemoveAttachThread(ptiCurrent);
505
506 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE;
507 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
508
509 /* Decrement thread count and check if its 0 */
510 ppiCurrent->cThreads--;
511
512 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
513 {
514 /* Do now some process cleanup that requires a valid win32 thread */
515 if(ptiCurrent->ppi->cThreads == 0)
516 {
517 /* Check if we have registered the user api hook */
518 if(ptiCurrent->ppi == ppiUahServer)
519 {
520 /* Unregister the api hook */
521 UserUnregisterUserApiHook();
522 }
523
524 /* Notify logon application to restart shell if needed */
525 if(ptiCurrent->pDeskInfo)
526 {
527 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
528 {
529 DWORD ExitCode = PsGetProcessExitStatus(Process);
530
531 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
532
533 UserPostMessage(hwndSAS,
534 WM_LOGONNOTIFY,
535 LN_SHELL_EXITED,
536 ExitCode);
537
538 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
539 }
540 }
541 }
542
543 DceFreeThreadDCE(ptiCurrent);
544 HOOK_DestroyThreadHooks(Thread);
545 EVENT_DestroyThreadEvents(Thread);
546 DestroyTimersForThread(ptiCurrent);
547 KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
548 UnregisterThreadHotKeys(ptiCurrent);
549 /*
550 if (IsListEmpty(&ptiCurrent->WindowListHead))
551 {
552 ERR_CH(UserThread,"Thread Window List is Empty!\n");
553 }
554 */
555 co_DestroyThreadWindows(Thread);
556
557 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
558 ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
559 {
560 TRACE_CH(UserThread,"DestroyProcessClasses\n");
561 /* no process windows should exist at this point, or the function will assert! */
562 DestroyProcessClasses(ppiCurrent);
563 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
564 }
565
566 IntBlockInput(ptiCurrent, FALSE);
567 IntCleanupThreadCallbacks(ptiCurrent);
568
569 /* cleanup user object references stack */
570 psle = PopEntryList(&ptiCurrent->ReferencesList);
571 while (psle)
572 {
573 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
574 TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj);
575 UserDereferenceObject(ref->obj);
576
577 psle = PopEntryList(&ptiCurrent->ReferencesList);
578 }
579 }
580
581 /* Find the THREADINFO in the PROCESSINFO's list */
582 ppti = &ppiCurrent->ptiList;
583 while (*ppti != NULL && *ppti != ptiCurrent)
584 {
585 ppti = &((*ppti)->ptiSibling);
586 }
587
588 /* we must have found it */
589 ASSERT(*ppti == ptiCurrent);
590
591 /* Remove it from the list */
592 *ppti = ptiCurrent->ptiSibling;
593
594 if (ptiCurrent->KeyboardLayout)
595 UserDereferenceObject(ptiCurrent->KeyboardLayout);
596
597 if (gptiForeground == ptiCurrent)
598 {
599 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
600 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
601
602 gptiForeground = NULL;
603 }
604
605 // Fixes CORE-6384 & CORE-7030.
606 /* if (ptiLastInput == ptiCurrent)
607 {
608 if (!ppiCurrent->ptiList)
609 ptiLastInput = gptiForeground;
610 else
611 ptiLastInput = ppiCurrent->ptiList;
612 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
613 }
614 */
615 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
616
617 /* Free the THREADINFO */
618 IntDereferenceThreadInfo(ptiCurrent);
619
620 return STATUS_SUCCESS;
621 }
622
623 NTSTATUS
624 APIENTRY
625 Win32kThreadCallback(struct _ETHREAD *Thread,
626 PSW32THREADCALLOUTTYPE Type)
627 {
628 NTSTATUS Status;
629
630 UserEnterExclusive();
631
632 ASSERT(NtCurrentTeb());
633
634 if (Type == PsW32ThreadCalloutInitialize)
635 {
636 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
637 Status = UserCreateThreadInfo(Thread);
638 }
639 else
640 {
641 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
642 Status = UserDestroyThreadInfo(Thread);
643 }
644
645 UserLeave();
646
647 return Status;
648 }
649
650 #ifdef _M_IX86
651 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
652 #endif
653
654 // Return on failure
655 #define NT_ROF(x) \
656 Status = (x); \
657 if (!NT_SUCCESS(Status)) \
658 { \
659 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
660 return Status; \
661 }
662
663 /*
664 * This definition doesn't work
665 */
666 INIT_FUNCTION
667 NTSTATUS
668 APIENTRY
669 DriverEntry(
670 IN PDRIVER_OBJECT DriverObject,
671 IN PUNICODE_STRING RegistryPath)
672 {
673 NTSTATUS Status;
674 BOOLEAN Result;
675 WIN32_CALLOUTS_FPNS CalloutData = {0};
676 PVOID GlobalUserHeapBase = NULL;
677
678 /*
679 * Register user mode call interface
680 * (system service table index = 1)
681 */
682 Result = KeAddSystemServiceTable(Win32kSSDT,
683 NULL,
684 Win32kNumberOfSysCalls,
685 Win32kSSPT,
686 1);
687 if (Result == FALSE)
688 {
689 DPRINT1("Adding system services failed!\n");
690 return STATUS_UNSUCCESSFUL;
691 }
692
693 hModuleWin = MmPageEntireDriver(DriverEntry);
694 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
695
696 /* Register Object Manager Callbacks */
697 CalloutData.ProcessCallout = Win32kProcessCallback;
698 CalloutData.ThreadCallout = Win32kThreadCallback;
699 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
700 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
701 CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
702 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
703 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
704 CalloutData.DesktopCloseProcedure = IntDesktopObjectClose;
705 CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen;
706 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
707
708 /* Register our per-process and per-thread structures. */
709 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
710
711 /* Register service hook callbacks */
712 #if DBG
713 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
714 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
715 #endif
716
717 /* Create the global USER heap */
718 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
719 &GlobalUserHeapBase,
720 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
721 if (GlobalUserHeap == NULL)
722 {
723 DPRINT1("Failed to initialize the global heap!\n");
724 return STATUS_UNSUCCESSFUL;
725 }
726
727 /* Allocate global server info structure */
728 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
729 if (!gpsi)
730 {
731 DPRINT1("Failed allocate server info structure!\n");
732 return STATUS_UNSUCCESSFUL;
733 }
734
735 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
736 DPRINT("Global Server Data -> %p\n", gpsi);
737
738 NT_ROF(InitGdiHandleTable());
739 NT_ROF(InitPaletteImpl());
740
741 /* Create stock objects, ie. precreated objects commonly
742 used by win32 applications */
743 CreateStockObjects();
744 CreateSysColorObjects();
745
746 NT_ROF(InitBrushImpl());
747 NT_ROF(InitPDEVImpl());
748 NT_ROF(InitLDEVImpl());
749 NT_ROF(InitDeviceImpl());
750 NT_ROF(InitDcImpl());
751 NT_ROF(InitUserImpl());
752 NT_ROF(InitWindowStationImpl());
753 NT_ROF(InitDesktopImpl());
754 NT_ROF(InitInputImpl());
755 NT_ROF(InitKeyboardImpl());
756 NT_ROF(MsqInitializeImpl());
757 NT_ROF(InitTimerImpl());
758 NT_ROF(InitDCEImpl());
759
760 /* Initialize FreeType library */
761 if (!InitFontSupport())
762 {
763 DPRINT1("Unable to initialize font support\n");
764 return Status;
765 }
766
767 gusLanguageID = UserGetLanguageID();
768
769 return STATUS_SUCCESS;
770 }
771
772 /* EOF */