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