[WIN32K]
[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 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 OBJECT_ATTRIBUTES EventQueueObjAttr;
270
271 Process = Thread->ThreadsProcess;
272
273 pTeb = NtCurrentTeb();
274
275 ASSERT(pTeb);
276
277 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
278 sizeof(THREADINFO),
279 USERTAG_THREADINFO);
280 if (ptiCurrent == NULL)
281 {
282 ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread);
283 return STATUS_NO_MEMORY;
284 }
285
286 TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
287
288 RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
289
290 /* Initialize the THREADINFO */
291
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;
298
299 TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
300
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++)
309 {
310 InitializeListHead(&ptiCurrent->aphkStart[i]);
311 }
312 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
313 ptiCurrent->ppi->ptiList = ptiCurrent;
314 ptiCurrent->ppi->cThreads++;
315
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))
321 {
322 goto error;
323 }
324 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
325 *ExEventObjectType, KernelMode,
326 (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
327 if (!NT_SUCCESS(Status))
328 {
329 ZwClose(ptiCurrent->hEventQueueClient);
330 ptiCurrent->hEventQueueClient = NULL;
331 goto error;
332 }
333
334 KeQueryTickCount(&LargeTickCount);
335 ptiCurrent->timeLast = LargeTickCount.u.LowPart;
336
337 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
338 if(ptiCurrent->MessageQueue == NULL)
339 {
340 ERR_CH(UserThread,"Failed to allocate message loop\n");
341 Status = STATUS_NO_MEMORY;
342 goto error;
343 }
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;
351
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)
359 {
360 pci->hKL = ptiCurrent->KeyboardLayout->hkl;
361 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage;
362 }
363
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)
367 {
368 HWINSTA hWinSta = NULL;
369 HDESK hDesk = NULL;
370 UNICODE_STRING DesktopPath;
371 PDESKTOP pdesk;
372 PRTL_USER_PROCESS_PARAMETERS ProcessParams;
373
374 /*
375 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
376 * info structure. See documentation of CreateProcess()
377 */
378 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters;
379
380 Status = STATUS_UNSUCCESSFUL;
381 if(ProcessParams && ProcessParams->DesktopInfo.Length > 0)
382 {
383 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo);
384 }
385 if(!NT_SUCCESS(Status))
386 {
387 RtlInitUnicodeString(&DesktopPath, NULL);
388 }
389
390 Status = IntParseDesktopPath(Process,
391 &DesktopPath,
392 &hWinSta,
393 &hDesk);
394
395 if (DesktopPath.Buffer)
396 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
397
398 if(!NT_SUCCESS(Status))
399 {
400 ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
401 goto error;
402 }
403
404 if(!UserSetProcessWindowStation(hWinSta))
405 {
406 Status = STATUS_UNSUCCESSFUL;
407 ERR_CH(UserThread,"Failed to set initial process winsta\n");
408 goto error;
409 }
410
411 /* Validate the new desktop. */
412 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
413 if(!NT_SUCCESS(Status))
414 {
415 ERR_CH(UserThread,"Failed to validate initial desktop handle\n");
416 goto error;
417 }
418
419 /* Store the parsed desktop as the initial desktop */
420 ptiCurrent->ppi->hdeskStartup = hDesk;
421 ptiCurrent->ppi->rpdeskStartup = pdesk;
422 }
423
424 if (ptiCurrent->ppi->hdeskStartup != NULL)
425 {
426 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
427 {
428 ERR_CH(UserThread,"Failed to set thread desktop\n");
429 Status = STATUS_UNSUCCESSFUL;
430 goto error;
431 }
432 }
433
434 /* mark the thread as fully initialized */
435 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
436
437 if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) &&
438 (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi ))
439 {
440 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
441 }
442 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
443 TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent);
444 return STATUS_SUCCESS;
445
446 error:
447 ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
448 UserDestroyThreadInfo(Thread);
449 return Status;
450 }
451
452 /*
453 Called from IntDereferenceThreadInfo.
454 */
455 VOID
456 FASTCALL
457 UserDeleteW32Thread(PTHREADINFO pti)
458 {
459 if (!pti->RefCount)
460 {
461 TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
462 if (pti->hEventQueueClient != NULL)
463 ZwClose(pti->hEventQueueClient);
464 pti->hEventQueueClient = NULL;
465
466 /* Free the message queue */
467 if (pti->MessageQueue)
468 {
469 MsqDestroyMessageQueue(pti);
470 }
471
472 MsqCleanupThreadMsgs(pti);
473
474 IntSetThreadDesktop(NULL, TRUE);
475
476 PsSetThreadWin32Thread(pti->pEThread, NULL, pti);
477 ExFreePoolWithTag(pti, USERTAG_THREADINFO);
478 }
479 }
480
481 NTSTATUS
482 NTAPI
483 UserDestroyThreadInfo(struct _ETHREAD *Thread)
484 {
485 PTHREADINFO *ppti;
486 PSINGLE_LIST_ENTRY psle;
487 PPROCESSINFO ppiCurrent;
488 struct _EPROCESS *Process;
489 PTHREADINFO ptiCurrent;
490
491 Process = Thread->ThreadsProcess;
492
493 /* Get the Win32 Thread */
494 ptiCurrent = PsGetThreadWin32Thread(Thread);
495
496 ASSERT(ptiCurrent);
497
498 TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);
499
500 ptiCurrent->TIF_flags |= TIF_INCLEANUP;
501 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
502
503 ppiCurrent = ptiCurrent->ppi;
504 ASSERT(ppiCurrent);
505
506 IsRemoveAttachThread(ptiCurrent);
507
508 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE;
509 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
510
511 /* Decrement thread count and check if its 0 */
512 ppiCurrent->cThreads--;
513
514 if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
515 {
516 /* Do now some process cleanup that requires a valid win32 thread */
517 if(ptiCurrent->ppi->cThreads == 0)
518 {
519 /* Check if we have registered the user api hook */
520 if(ptiCurrent->ppi == ppiUahServer)
521 {
522 /* Unregister the api hook */
523 UserUnregisterUserApiHook();
524 }
525
526 /* Notify logon application to restart shell if needed */
527 if(ptiCurrent->pDeskInfo)
528 {
529 if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
530 {
531 DWORD ExitCode = PsGetProcessExitStatus(Process);
532
533 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);
534
535 UserPostMessage(hwndSAS,
536 WM_LOGONNOTIFY,
537 LN_SHELL_EXITED,
538 ExitCode);
539
540 ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
541 }
542 }
543 }
544
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);
551 /*
552 if (IsListEmpty(&ptiCurrent->WindowListHead))
553 {
554 ERR_CH(UserThread,"Thread Window List is Empty!\n");
555 }
556 */
557 co_DestroyThreadWindows(Thread);
558
559 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
560 ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
561 {
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;
566 }
567
568 IntBlockInput(ptiCurrent, FALSE);
569 IntCleanupThreadCallbacks(ptiCurrent);
570
571 /* cleanup user object references stack */
572 psle = PopEntryList(&ptiCurrent->ReferencesList);
573 while (psle)
574 {
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);
578
579 psle = PopEntryList(&ptiCurrent->ReferencesList);
580 }
581 }
582
583 /* Find the THREADINFO in the PROCESSINFO's list */
584 ppti = &ppiCurrent->ptiList;
585 while (*ppti != NULL && *ppti != ptiCurrent)
586 {
587 ppti = &((*ppti)->ptiSibling);
588 }
589
590 /* we must have found it */
591 ASSERT(*ppti == ptiCurrent);
592
593 /* Remove it from the list */
594 *ppti = ptiCurrent->ptiSibling;
595
596 if (ptiCurrent->KeyboardLayout)
597 UserDereferenceObject(ptiCurrent->KeyboardLayout);
598
599 if (gptiForeground == ptiCurrent)
600 {
601 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
602 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
603
604 gptiForeground = NULL;
605 }
606
607 // Fixes CORE-6384 & CORE-7030.
608 /* if (ptiLastInput == ptiCurrent)
609 {
610 if (!ppiCurrent->ptiList)
611 ptiLastInput = gptiForeground;
612 else
613 ptiLastInput = ppiCurrent->ptiList;
614 ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
615 }
616 */
617 TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
618
619 /* Free the THREADINFO */
620 IntDereferenceThreadInfo(ptiCurrent);
621
622 return STATUS_SUCCESS;
623 }
624
625 NTSTATUS
626 APIENTRY
627 Win32kThreadCallback(struct _ETHREAD *Thread,
628 PSW32THREADCALLOUTTYPE Type)
629 {
630 NTSTATUS Status;
631
632 UserEnterExclusive();
633
634 ASSERT(NtCurrentTeb());
635
636 if (Type == PsW32ThreadCalloutInitialize)
637 {
638 ASSERT(PsGetThreadWin32Thread(Thread) == NULL);
639 Status = UserCreateThreadInfo(Thread);
640 }
641 else
642 {
643 ASSERT(PsGetThreadWin32Thread(Thread) != NULL);
644 Status = UserDestroyThreadInfo(Thread);
645 }
646
647 UserLeave();
648
649 return Status;
650 }
651
652 #ifdef _M_IX86
653 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
654 #endif
655
656 // Return on failure
657 #define NT_ROF(x) \
658 Status = (x); \
659 if (!NT_SUCCESS(Status)) \
660 { \
661 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
662 return Status; \
663 }
664
665 /*
666 * This definition doesn't work
667 */
668 INIT_FUNCTION
669 NTSTATUS
670 APIENTRY
671 DriverEntry(
672 IN PDRIVER_OBJECT DriverObject,
673 IN PUNICODE_STRING RegistryPath)
674 {
675 NTSTATUS Status;
676 BOOLEAN Result;
677 WIN32_CALLOUTS_FPNS CalloutData = {0};
678 PVOID GlobalUserHeapBase = NULL;
679
680 /*
681 * Register user mode call interface
682 * (system service table index = 1)
683 */
684 Result = KeAddSystemServiceTable(Win32kSSDT,
685 NULL,
686 Win32kNumberOfSysCalls,
687 Win32kSSPT,
688 1);
689 if (Result == FALSE)
690 {
691 DPRINT1("Adding system services failed!\n");
692 return STATUS_UNSUCCESSFUL;
693 }
694
695 hModuleWin = MmPageEntireDriver(DriverEntry);
696 DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
697
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;
709
710 /* Register our per-process and per-thread structures. */
711 PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
712
713 /* Register service hook callbacks */
714 #if DBG
715 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
716 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
717 #endif
718
719 /* Create the global USER heap */
720 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
721 &GlobalUserHeapBase,
722 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
723 if (GlobalUserHeap == NULL)
724 {
725 DPRINT1("Failed to initialize the global heap!\n");
726 return STATUS_UNSUCCESSFUL;
727 }
728
729 /* Allocate global server info structure */
730 gpsi = UserHeapAlloc(sizeof(SERVERINFO));
731 if (!gpsi)
732 {
733 DPRINT1("Failed allocate server info structure!\n");
734 return STATUS_UNSUCCESSFUL;
735 }
736
737 RtlZeroMemory(gpsi, sizeof(SERVERINFO));
738 DPRINT("Global Server Data -> %p\n", gpsi);
739
740 NT_ROF(InitGdiHandleTable());
741 NT_ROF(InitPaletteImpl());
742
743 /* Create stock objects, ie. precreated objects commonly
744 used by win32 applications */
745 CreateStockObjects();
746 CreateSysColorObjects();
747
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());
761
762 /* Initialize FreeType library */
763 if (!InitFontSupport())
764 {
765 DPRINT1("Unable to initialize font support\n");
766 return Status;
767 }
768
769 gusLanguageID = UserGetLanguageID();
770
771 return STATUS_SUCCESS;
772 }
773
774 /* EOF */