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