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