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: win32ss/user/ntuser/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 NTSTATUS ExitProcessCallback(PEPROCESS Process); 19 NTSTATUS NTAPI ExitThreadCallback(PETHREAD Thread); 20 21 // TODO: Should be moved to some GDI header 22 NTSTATUS GdiProcessCreate(PEPROCESS Process); 23 NTSTATUS GdiProcessDestroy(PEPROCESS Process); 24 NTSTATUS GdiThreadCreate(PETHREAD Thread); 25 NTSTATUS GdiThreadDestroy(PETHREAD Thread); 26 27 PSERVERINFO gpsi = NULL; // Global User Server Information. 28 29 USHORT gusLanguageID; 30 PPROCESSINFO ppiScrnSaver; 31 PPROCESSINFO gppiList = NULL; 32 33 extern ULONG_PTR Win32kSSDT[]; 34 extern UCHAR Win32kSSPT[]; 35 extern ULONG Win32kNumberOfSysCalls; 36 37 #if DBG 38 void 39 NTAPI 40 DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments) 41 { 42 GdiDbgPreServiceHook(ulSyscallId, pulArguments); 43 UserDbgPreServiceHook(ulSyscallId, pulArguments); 44 } 45 46 ULONG_PTR 47 NTAPI 48 DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) 49 { 50 ulResult = GdiDbgPostServiceHook(ulSyscallId, ulResult); 51 ulResult = UserDbgPostServiceHook(ulSyscallId, ulResult); 52 return ulResult; 53 } 54 #endif 55 56 57 NTSTATUS 58 AllocW32Process(IN PEPROCESS Process, 59 OUT PPROCESSINFO* W32Process) 60 { 61 PPROCESSINFO ppiCurrent; 62 63 TRACE_CH(UserProcess, "In AllocW32Process(0x%p)\n", Process); 64 65 /* Check that we were not called with an already existing Win32 process info */ 66 ppiCurrent = PsGetProcessWin32Process(Process); 67 if (ppiCurrent) return STATUS_SUCCESS; 68 69 /* Allocate a new Win32 process info */ 70 ppiCurrent = ExAllocatePoolWithTag(NonPagedPool, 71 sizeof(*ppiCurrent), 72 USERTAG_PROCESSINFO); 73 if (ppiCurrent == NULL) 74 { 75 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", 76 HandleToUlong(Process->UniqueProcessId)); 77 return STATUS_NO_MEMORY; 78 } 79 80 TRACE_CH(UserProcess, "Allocated ppi 0x%p for PID:0x%lx\n", 81 ppiCurrent, HandleToUlong(Process->UniqueProcessId)); 82 83 RtlZeroMemory(ppiCurrent, sizeof(*ppiCurrent)); 84 85 PsSetProcessWin32Process(Process, ppiCurrent, NULL); 86 IntReferenceProcessInfo(ppiCurrent); 87 88 *W32Process = ppiCurrent; 89 return STATUS_SUCCESS; 90 } 91 92 /* 93 * Called from IntDereferenceProcessInfo 94 */ 95 VOID 96 UserDeleteW32Process( 97 _Pre_notnull_ __drv_freesMem(Mem) PPROCESSINFO ppiCurrent) 98 { 99 if (ppiCurrent->InputIdleEvent) 100 { 101 /* Free the allocated memory */ 102 ExFreePoolWithTag(ppiCurrent->InputIdleEvent, USERTAG_EVENT); 103 } 104 105 /* Close the startup desktop */ 106 if (ppiCurrent->rpdeskStartup) 107 ObDereferenceObject(ppiCurrent->rpdeskStartup); 108 109 #if DBG 110 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) 111 { 112 TRACE_PPI(ppiCurrent, UserObj, "Dumping user handles now that process info %p is gets freed.\n", ppiCurrent); 113 DbgUserDumpHandleTable(); 114 } 115 #endif 116 117 /* Free the PROCESSINFO */ 118 ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); 119 } 120 121 NTSTATUS 122 UserProcessCreate(PEPROCESS Process) 123 { 124 PPROCESSINFO ppiCurrent = PsGetProcessWin32Process(Process); 125 ASSERT(ppiCurrent); 126 127 InitializeListHead(&ppiCurrent->DriverObjListHead); 128 ExInitializeFastMutex(&ppiCurrent->DriverObjListLock); 129 130 { 131 PKEVENT Event; 132 133 /* Allocate memory for the event structure */ 134 Event = ExAllocatePoolWithTag(NonPagedPool, 135 sizeof(*Event), 136 USERTAG_EVENT); 137 if (Event) 138 { 139 /* Initialize the kernel event */ 140 KeInitializeEvent(Event, 141 SynchronizationEvent, 142 FALSE); 143 } 144 else 145 { 146 /* Out of memory */ 147 DPRINT("CreateEvent() failed\n"); 148 KeBugCheck(0); 149 } 150 151 /* Set the event */ 152 ppiCurrent->InputIdleEvent = Event; 153 KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE); 154 } 155 156 ppiCurrent->peProcess = Process; 157 ppiCurrent->W32Pid = HandleToUlong(PsGetProcessId(Process)); 158 159 /* Setup process flags */ 160 ppiCurrent->W32PF_flags |= W32PF_PROCESSCONNECTED; 161 if (Process->Peb->ProcessParameters && 162 (Process->Peb->ProcessParameters->WindowFlags & STARTF_SCREENSAVER)) 163 { 164 ppiScrnSaver = ppiCurrent; 165 ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; 166 } 167 168 // FIXME: check if this process is allowed. 169 ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application will get it toggled off. 170 171 return STATUS_SUCCESS; 172 } 173 174 NTSTATUS 175 UserProcessDestroy(PEPROCESS Process) 176 { 177 PPROCESSINFO ppiCurrent = PsGetProcessWin32Process(Process); 178 ASSERT(ppiCurrent); 179 180 if (ppiScrnSaver == ppiCurrent) 181 ppiScrnSaver = NULL; 182 183 /* Destroy user objects */ 184 UserDestroyObjectsForOwner(gHandleTable, ppiCurrent); 185 186 TRACE_CH(UserProcess, "Freeing ppi 0x%p\n", ppiCurrent); 187 #if DBG 188 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) 189 { 190 TRACE_CH(UserObj, "Dumping user handles at the end of the process %s (Info %p).\n", 191 ppiCurrent->peProcess->ImageFileName, ppiCurrent); 192 DbgUserDumpHandleTable(); 193 } 194 #endif 195 196 /* Remove it from the list of GUI apps */ 197 co_IntGraphicsCheck(FALSE); 198 199 /* 200 * Deregister logon application automatically 201 */ 202 if (gpidLogon == ppiCurrent->peProcess->UniqueProcessId) 203 gpidLogon = 0; 204 205 /* Close the current window station */ 206 UserSetProcessWindowStation(NULL); 207 208 if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL; 209 210 if (ppiCurrent->hdeskStartup) 211 { 212 ZwClose(ppiCurrent->hdeskStartup); 213 ppiCurrent->hdeskStartup = NULL; 214 } 215 216 /* Clean up the process icon cache */ 217 IntCleanupCurIconCache(ppiCurrent); 218 219 return STATUS_SUCCESS; 220 } 221 222 NTSTATUS 223 InitProcessCallback(PEPROCESS Process) 224 { 225 NTSTATUS Status; 226 PPROCESSINFO ppiCurrent; 227 PVOID KernelMapping = NULL, UserMapping = NULL; 228 229 /* We might be called with an already allocated win32 process */ 230 ppiCurrent = PsGetProcessWin32Process(Process); 231 if (ppiCurrent != NULL) 232 { 233 /* There is no more to do for us (this is a success code!) */ 234 return STATUS_ALREADY_WIN32; 235 } 236 // if (ppiCurrent->W32PF_flags & W32PF_PROCESSCONNECTED) 237 // return STATUS_ALREADY_WIN32; 238 239 /* Allocate a new Win32 process info */ 240 Status = AllocW32Process(Process, &ppiCurrent); 241 if (!NT_SUCCESS(Status)) 242 { 243 ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", 244 HandleToUlong(Process->UniqueProcessId)); 245 return Status; 246 } 247 248 #if DBG 249 DbgInitDebugChannels(); 250 #if defined(KDBG) 251 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback); 252 #endif 253 #endif 254 255 /* Map the global user heap into the process */ 256 Status = MapGlobalUserHeap(Process, &KernelMapping, &UserMapping); 257 if (!NT_SUCCESS(Status)) 258 { 259 TRACE_CH(UserProcess, "Failed to map the global heap! 0x%x\n", Status); 260 goto error; 261 } 262 263 TRACE_CH(UserProcess, "InitProcessCallback -- We have KernelMapping 0x%p and UserMapping 0x%p with delta = 0x%x\n", 264 KernelMapping, UserMapping, (ULONG_PTR)KernelMapping - (ULONG_PTR)UserMapping); 265 266 /* Initialize USER process info */ 267 Status = UserProcessCreate(Process); 268 if (!NT_SUCCESS(Status)) 269 { 270 ERR_CH(UserProcess, "UserProcessCreate failed, Status 0x%08lx\n", Status); 271 goto error; 272 } 273 274 /* Initialize GDI process info */ 275 Status = GdiProcessCreate(Process); 276 if (!NT_SUCCESS(Status)) 277 { 278 ERR_CH(UserProcess, "GdiProcessCreate failed, Status 0x%08lx\n", Status); 279 goto error; 280 } 281 282 /* Add the process to the global list */ 283 ppiCurrent->ppiNext = gppiList; 284 gppiList = ppiCurrent; 285 286 return STATUS_SUCCESS; 287 288 error: 289 ERR_CH(UserProcess, "InitProcessCallback failed! Freeing ppi 0x%p for PID:0x%lx\n", 290 ppiCurrent, HandleToUlong(Process->UniqueProcessId)); 291 ExitProcessCallback(Process); 292 return Status; 293 } 294 295 NTSTATUS 296 ExitProcessCallback(PEPROCESS Process) 297 { 298 PPROCESSINFO ppiCurrent, *pppi; 299 300 /* Get the Win32 Process */ 301 ppiCurrent = PsGetProcessWin32Process(Process); 302 ASSERT(ppiCurrent); 303 ASSERT(ppiCurrent->peProcess == Process); 304 305 TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent); 306 ppiCurrent->W32PF_flags |= W32PF_TERMINATED; 307 308 /* Remove it from the list */ 309 pppi = &gppiList; 310 while (*pppi != NULL && *pppi != ppiCurrent) 311 { 312 pppi = &(*pppi)->ppiNext; 313 } 314 ASSERT(*pppi == ppiCurrent); 315 *pppi = ppiCurrent->ppiNext; 316 317 /* Cleanup GDI info */ 318 GdiProcessDestroy(Process); 319 320 /* Cleanup USER info */ 321 UserProcessDestroy(Process); 322 323 /* The process is dying */ 324 PsSetProcessWin32Process(Process, NULL, ppiCurrent); 325 ppiCurrent->peProcess = NULL; 326 327 /* Finally, dereference */ 328 IntDereferenceProcessInfo(ppiCurrent); 329 330 return STATUS_SUCCESS; 331 } 332 333 NTSTATUS 334 APIENTRY 335 Win32kProcessCallback(PEPROCESS Process, 336 BOOLEAN Initialize) 337 { 338 NTSTATUS Status; 339 340 ASSERT(Process->Peb); 341 342 TRACE_CH(UserProcess, "Win32kProcessCallback -->\n"); 343 344 UserEnterExclusive(); 345 346 if (Initialize) 347 { 348 Status = InitProcessCallback(Process); 349 } 350 else 351 { 352 Status = ExitProcessCallback(Process); 353 } 354 355 UserLeave(); 356 357 TRACE_CH(UserProcess, "<-- Win32kProcessCallback\n"); 358 359 return Status; 360 } 361 362 363 364 NTSTATUS 365 AllocW32Thread(IN PETHREAD Thread, 366 OUT PTHREADINFO* W32Thread) 367 { 368 PTHREADINFO ptiCurrent; 369 370 TRACE_CH(UserThread, "In AllocW32Thread(0x%p)\n", Thread); 371 372 /* Check that we were not called with an already existing Win32 thread info */ 373 ptiCurrent = PsGetThreadWin32Thread(Thread); 374 NT_ASSERT(ptiCurrent == NULL); 375 376 /* Allocate a new Win32 thread info */ 377 ptiCurrent = ExAllocatePoolWithTag(NonPagedPool, 378 sizeof(*ptiCurrent), 379 USERTAG_THREADINFO); 380 if (ptiCurrent == NULL) 381 { 382 ERR_CH(UserThread, "Failed to allocate pti for TID:0x%lx\n", 383 HandleToUlong(Thread->Cid.UniqueThread)); 384 return STATUS_NO_MEMORY; 385 } 386 387 TRACE_CH(UserThread, "Allocated pti 0x%p for TID:0x%lx\n", 388 ptiCurrent, HandleToUlong(Thread->Cid.UniqueThread)); 389 390 RtlZeroMemory(ptiCurrent, sizeof(*ptiCurrent)); 391 392 PsSetThreadWin32Thread(Thread, ptiCurrent, NULL); 393 ObReferenceObject(Thread); 394 IntReferenceThreadInfo(ptiCurrent); 395 396 *W32Thread = ptiCurrent; 397 return STATUS_SUCCESS; 398 } 399 400 /* 401 * Called from IntDereferenceThreadInfo 402 */ 403 VOID 404 UserDeleteW32Thread(PTHREADINFO pti) 405 { 406 PPROCESSINFO ppi = pti->ppi; 407 408 TRACE_CH(UserThread, "UserDeleteW32Thread pti 0x%p\n",pti); 409 410 /* Free the message queue */ 411 if (pti->MessageQueue) 412 { 413 MsqDestroyMessageQueue(pti); 414 } 415 416 MsqCleanupThreadMsgs(pti); 417 418 ObDereferenceObject(pti->pEThread); 419 420 ExFreePoolWithTag(pti, USERTAG_THREADINFO); 421 422 IntDereferenceProcessInfo(ppi); 423 424 { 425 // Find another queue for mouse cursor. 426 MSG msg; 427 msg.message = WM_MOUSEMOVE; 428 msg.wParam = UserGetMouseButtonsState(); 429 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); 430 msg.pt = gpsi->ptCursor; 431 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE); 432 } 433 } 434 435 NTSTATUS 436 UserThreadCreate(PETHREAD Thread) 437 { 438 return STATUS_SUCCESS; 439 } 440 441 NTSTATUS 442 UserThreadDestroy(PETHREAD Thread) 443 { 444 return STATUS_SUCCESS; 445 } 446 447 NTSTATUS NTAPI 448 InitThreadCallback(PETHREAD Thread) 449 { 450 PEPROCESS Process; 451 PCLIENTINFO pci; 452 PTHREADINFO ptiCurrent; 453 int i; 454 NTSTATUS Status = STATUS_SUCCESS; 455 PTEB pTeb; 456 PRTL_USER_PROCESS_PARAMETERS ProcessParams; 457 458 Process = Thread->ThreadsProcess; 459 460 pTeb = NtCurrentTeb(); 461 ASSERT(pTeb); 462 463 ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters; 464 465 /* Allocate a new Win32 thread info */ 466 Status = AllocW32Thread(Thread, &ptiCurrent); 467 if (!NT_SUCCESS(Status)) 468 { 469 ERR_CH(UserThread, "Failed to allocate pti for TID:0x%lx\n", 470 HandleToUlong(Thread->Cid.UniqueThread)); 471 return Status; 472 } 473 474 /* Initialize the THREADINFO */ 475 ptiCurrent->pEThread = Thread; 476 ptiCurrent->ppi = PsGetProcessWin32Process(Process); 477 IntReferenceProcessInfo(ptiCurrent->ppi); 478 pTeb->Win32ThreadInfo = ptiCurrent; 479 ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; 480 ptiCurrent->pcti = &ptiCurrent->cti; 481 482 /* Mark the process as having threads */ 483 ptiCurrent->ppi->W32PF_flags |= W32PF_THREADCONNECTED; 484 485 InitializeListHead(&ptiCurrent->WindowListHead); 486 InitializeListHead(&ptiCurrent->W32CallbackListHead); 487 InitializeListHead(&ptiCurrent->PostedMessagesListHead); 488 InitializeListHead(&ptiCurrent->SentMessagesListHead); 489 InitializeListHead(&ptiCurrent->PtiLink); 490 for (i = 0; i < NB_HOOKS; i++) 491 { 492 InitializeListHead(&ptiCurrent->aphkStart[i]); 493 } 494 ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList; 495 ptiCurrent->ppi->ptiList = ptiCurrent; 496 ptiCurrent->ppi->cThreads++; 497 498 ptiCurrent->hEventQueueClient = NULL; 499 Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS, 500 NULL, SynchronizationEvent, FALSE); 501 if (!NT_SUCCESS(Status)) 502 { 503 ERR_CH(UserThread, "Event creation failed, Status 0x%08x.\n", Status); 504 goto error; 505 } 506 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, 507 *ExEventObjectType, UserMode, 508 (PVOID*)&ptiCurrent->pEventQueueServer, NULL); 509 if (!NT_SUCCESS(Status)) 510 { 511 ERR_CH(UserThread, "Failed referencing the event object, Status 0x%08x.\n", Status); 512 ObCloseHandle(ptiCurrent->hEventQueueClient, UserMode); 513 ptiCurrent->hEventQueueClient = NULL; 514 goto error; 515 } 516 517 ptiCurrent->pcti->timeLastRead = EngGetTickCount32(); 518 519 ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent); 520 if (ptiCurrent->MessageQueue == NULL) 521 { 522 ERR_CH(UserThread, "Failed to allocate message loop\n"); 523 Status = STATUS_NO_MEMORY; 524 goto error; 525 } 526 527 ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); 528 if (ptiCurrent->KeyboardLayout) 529 UserReferenceObject(ptiCurrent->KeyboardLayout); 530 531 ptiCurrent->TIF_flags &= ~TIF_INCLEANUP; 532 533 // FIXME: Flag SYSTEM threads with... TIF_SYSTEMTHREAD !! 534 535 /* CSRSS threads have some special features */ 536 if (Process == gpepCSRSS || !gpepCSRSS) 537 ptiCurrent->TIF_flags = TIF_CSRSSTHREAD | TIF_DONTATTACHQUEUE; 538 539 /* Initialize the CLIENTINFO */ 540 pci = (PCLIENTINFO)pTeb->Win32ClientInfo; 541 RtlZeroMemory(pci, sizeof(*pci)); 542 pci->ppi = ptiCurrent->ppi; 543 pci->fsHooks = ptiCurrent->fsHooks; 544 pci->dwTIFlags = ptiCurrent->TIF_flags; 545 if (ptiCurrent->KeyboardLayout) 546 { 547 pci->hKL = ptiCurrent->KeyboardLayout->hkl; 548 pci->CodePage = ptiCurrent->KeyboardLayout->CodePage; 549 } 550 551 /* Need to pass the user Startup Information to the current process. */ 552 if ( ProcessParams ) 553 { 554 if ( ptiCurrent->ppi->usi.cb == 0 ) // Not initialized yet. 555 { 556 if ( ProcessParams->WindowFlags != 0 ) // Need window flags set. 557 { 558 ptiCurrent->ppi->usi.cb = sizeof(USERSTARTUPINFO); 559 ptiCurrent->ppi->usi.dwX = ProcessParams->StartingX; 560 ptiCurrent->ppi->usi.dwY = ProcessParams->StartingY; 561 ptiCurrent->ppi->usi.dwXSize = ProcessParams->CountX; 562 ptiCurrent->ppi->usi.dwYSize = ProcessParams->CountY; 563 ptiCurrent->ppi->usi.dwFlags = ProcessParams->WindowFlags; 564 ptiCurrent->ppi->usi.wShowWindow = (WORD)ProcessParams->ShowWindowFlags; 565 } 566 } 567 } 568 569 /* 570 * Assign a default window station and desktop to the process. 571 * Do not try to open a desktop or window station before the very first 572 * (interactive) window station has been created by Winlogon. 573 */ 574 if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) && 575 ptiCurrent->ppi->hdeskStartup == NULL && 576 InputWindowStation != NULL) 577 { 578 HWINSTA hWinSta = NULL; 579 HDESK hDesk = NULL; 580 UNICODE_STRING DesktopPath; 581 PDESKTOP pdesk; 582 583 /* 584 * Inherit the thread desktop and process window station (if not yet inherited) 585 * from the process startup info structure. See documentation of CreateProcess(). 586 */ 587 Status = STATUS_UNSUCCESSFUL; 588 if (ProcessParams && ProcessParams->DesktopInfo.Length > 0) 589 { 590 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo); 591 } 592 if (!NT_SUCCESS(Status)) 593 { 594 RtlInitUnicodeString(&DesktopPath, NULL); 595 } 596 597 Status = IntResolveDesktop(Process, 598 &DesktopPath, 599 !!(ProcessParams->WindowFlags & STARTF_INHERITDESKTOP), 600 &hWinSta, 601 &hDesk); 602 603 if (DesktopPath.Buffer) 604 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING); 605 606 if (!NT_SUCCESS(Status)) 607 { 608 ERR_CH(UserThread, "Failed to assign default desktop and winsta to process\n"); 609 goto error; 610 } 611 612 if (!UserSetProcessWindowStation(hWinSta)) 613 { 614 Status = STATUS_UNSUCCESSFUL; 615 ERR_CH(UserThread, "Failed to set initial process winsta\n"); 616 goto error; 617 } 618 619 /* Validate the new desktop */ 620 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk); 621 if (!NT_SUCCESS(Status)) 622 { 623 ERR_CH(UserThread, "Failed to validate initial desktop handle\n"); 624 goto error; 625 } 626 627 /* Store the parsed desktop as the initial desktop */ 628 ASSERT(ptiCurrent->ppi->hdeskStartup == NULL); 629 ASSERT(Process->UniqueProcessId != gpidLogon); 630 ptiCurrent->ppi->hdeskStartup = hDesk; 631 ptiCurrent->ppi->rpdeskStartup = pdesk; 632 } 633 634 if (ptiCurrent->ppi->hdeskStartup != NULL) 635 { 636 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE)) 637 { 638 ERR_CH(UserThread, "Failed to set thread desktop\n"); 639 Status = STATUS_UNSUCCESSFUL; 640 goto error; 641 } 642 } 643 644 /* Mark the thread as fully initialized */ 645 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; 646 647 if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && 648 (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) 649 { 650 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 651 } 652 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 653 654 /* Last things to do only if we are not a SYSTEM or CSRSS thread */ 655 if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) 656 { 657 /* Callback to User32 Client Thread Setup */ 658 TRACE_CH(UserThread, "Call co_IntClientThreadSetup...\n"); 659 Status = co_IntClientThreadSetup(); 660 if (!NT_SUCCESS(Status)) 661 { 662 ERR_CH(UserThread, "ClientThreadSetup failed with Status 0x%08lx\n", Status); 663 goto error; 664 } 665 TRACE_CH(UserThread, "co_IntClientThreadSetup succeeded!\n"); 666 } 667 else 668 { 669 TRACE_CH(UserThread, "co_IntClientThreadSetup cannot be called...\n"); 670 } 671 672 TRACE_CH(UserThread, "UserCreateW32Thread pti 0x%p\n", ptiCurrent); 673 return STATUS_SUCCESS; 674 675 error: 676 ERR_CH(UserThread, "InitThreadCallback failed! Freeing pti 0x%p for TID:0x%lx\n", 677 ptiCurrent, HandleToUlong(Thread->Cid.UniqueThread)); 678 ExitThreadCallback(Thread); 679 return Status; 680 } 681 682 VOID 683 UserDisplayNotifyShutdown(PPROCESSINFO ppiCurrent); 684 685 NTSTATUS 686 NTAPI 687 ExitThreadCallback(PETHREAD Thread) 688 { 689 PTHREADINFO *ppti; 690 PSINGLE_LIST_ENTRY psle; 691 PPROCESSINFO ppiCurrent; 692 PEPROCESS Process; 693 PTHREADINFO ptiCurrent; 694 695 Process = Thread->ThreadsProcess; 696 697 /* Get the Win32 Thread */ 698 ptiCurrent = PsGetThreadWin32Thread(Thread); 699 ASSERT(ptiCurrent); 700 701 TRACE_CH(UserThread, "Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); 702 703 ptiCurrent->TIF_flags |= TIF_INCLEANUP; 704 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 705 706 ppiCurrent = ptiCurrent->ppi; 707 ASSERT(ppiCurrent); 708 709 IsRemoveAttachThread(ptiCurrent); 710 711 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; 712 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 713 714 UserCloseClipboard(); 715 716 /* Decrement thread count and check if its 0 */ 717 ppiCurrent->cThreads--; 718 719 if (ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED) 720 { 721 /* Do now some process cleanup that requires a valid win32 thread */ 722 if (ptiCurrent->ppi->cThreads == 0) 723 { 724 /* Check if we have registered the user api hook */ 725 if (ptiCurrent->ppi == ppiUahServer) 726 { 727 /* Unregister the api hook */ 728 UserUnregisterUserApiHook(); 729 } 730 731 /* Notify logon application to restart shell if needed */ 732 if (ptiCurrent->pDeskInfo) 733 { 734 if (ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent) 735 { 736 DWORD ExitCode = PsGetProcessExitStatus(Process); 737 738 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode); 739 740 UserPostMessage(hwndSAS, 741 WM_LOGONNOTIFY, 742 LN_SHELL_EXITED, 743 ExitCode); 744 745 ptiCurrent->pDeskInfo->ppiShellProcess = NULL; 746 } 747 } 748 } 749 750 DceFreeThreadDCE(ptiCurrent); 751 DestroyTimersForThread(ptiCurrent); 752 KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE); 753 UnregisterThreadHotKeys(ptiCurrent); 754 755 if (!UserDestroyObjectsForOwner(gHandleTable, ptiCurrent)) 756 { 757 DPRINT1("Failed to delete objects belonging to thread %p. This is VERY BAD!.\n", ptiCurrent); 758 ASSERT(FALSE); 759 return STATUS_UNSUCCESSFUL; 760 } 761 762 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && 763 ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) 764 { 765 TRACE_CH(UserThread, "DestroyProcessClasses\n"); 766 /* no process windows should exist at this point, or the function will assert! */ 767 DestroyProcessClasses(ppiCurrent); 768 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; 769 } 770 771 IntBlockInput(ptiCurrent, FALSE); 772 IntCleanupThreadCallbacks(ptiCurrent); 773 774 /* cleanup user object references stack */ 775 psle = PopEntryList(&ptiCurrent->ReferencesList); 776 while (psle) 777 { 778 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry); 779 TRACE_CH(UserThread, "thread clean: remove reference obj 0x%p\n",ref->obj); 780 UserDereferenceObject(ref->obj); 781 782 psle = PopEntryList(&ptiCurrent->ReferencesList); 783 } 784 } 785 786 if (ptiCurrent->cEnterCount) 787 { 788 KeSetKernelStackSwapEnable(TRUE); 789 ptiCurrent->cEnterCount = 0; 790 } 791 792 /* Find the THREADINFO in the PROCESSINFO's list */ 793 ppti = &ppiCurrent->ptiList; 794 while (*ppti != NULL && *ppti != ptiCurrent) 795 { 796 ppti = &((*ppti)->ptiSibling); 797 } 798 799 /* we must have found it */ 800 ASSERT(*ppti == ptiCurrent); 801 802 /* Remove it from the list */ 803 *ppti = ptiCurrent->ptiSibling; 804 805 if (ptiCurrent->KeyboardLayout) 806 UserDereferenceObject(ptiCurrent->KeyboardLayout); 807 808 if (gptiForeground == ptiCurrent) 809 { 810 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); 811 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); 812 813 gptiForeground = NULL; 814 } 815 816 /* Restore display mode when we are the last thread, and we changed the display mode */ 817 if (ppiCurrent->cThreads == 0) 818 UserDisplayNotifyShutdown(ppiCurrent); 819 820 821 // Fixes CORE-6384 & CORE-7030. 822 /* if (ptiLastInput == ptiCurrent) 823 { 824 if (!ppiCurrent->ptiList) 825 ptiLastInput = gptiForeground; 826 else 827 ptiLastInput = ppiCurrent->ptiList; 828 ERR_CH(UserThread, "DTI: ptiLastInput is Cleared!!\n"); 829 } 830 */ 831 TRACE_CH(UserThread, "Freeing pti 0x%p\n", ptiCurrent); 832 833 IntSetThreadDesktop(NULL, TRUE); 834 835 if (ptiCurrent->hEventQueueClient != NULL) 836 { 837 ObCloseHandle(ptiCurrent->hEventQueueClient, UserMode); 838 ObDereferenceObject(ptiCurrent->pEventQueueServer); 839 } 840 ptiCurrent->hEventQueueClient = NULL; 841 842 /* The thread is dying */ 843 PsSetThreadWin32Thread(Thread /*ptiCurrent->pEThread*/, NULL, ptiCurrent); 844 845 /* Dereference the THREADINFO */ 846 IntDereferenceThreadInfo(ptiCurrent); 847 848 return STATUS_SUCCESS; 849 } 850 851 NTSTATUS 852 APIENTRY 853 Win32kThreadCallback(PETHREAD Thread, 854 PSW32THREADCALLOUTTYPE Type) 855 { 856 NTSTATUS Status; 857 858 ASSERT(NtCurrentTeb()); 859 860 UserEnterExclusive(); 861 862 if (Type == PsW32ThreadCalloutInitialize) 863 { 864 ASSERT(PsGetThreadWin32Thread(Thread) == NULL); 865 Status = InitThreadCallback(Thread); 866 } 867 else // if (Type == PsW32ThreadCalloutExit) 868 { 869 ASSERT(PsGetThreadWin32Thread(Thread) != NULL); 870 Status = ExitThreadCallback(Thread); 871 } 872 873 UserLeave(); 874 875 return Status; 876 } 877 878 _Function_class_(DRIVER_UNLOAD) 879 VOID NTAPI 880 DriverUnload(IN PDRIVER_OBJECT DriverObject) 881 { 882 // TODO: Do more cleanup! 883 884 ResetCsrApiPort(); 885 ResetCsrProcess(); 886 } 887 888 // Return on failure 889 #define NT_ROF(x) \ 890 { \ 891 Status = (x); \ 892 if (!NT_SUCCESS(Status)) \ 893 { \ 894 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \ 895 return Status; \ 896 } \ 897 } 898 899 /* 900 * This definition doesn't work 901 */ 902 INIT_FUNCTION 903 NTSTATUS 904 APIENTRY 905 DriverEntry( 906 IN PDRIVER_OBJECT DriverObject, 907 IN PUNICODE_STRING RegistryPath) 908 { 909 NTSTATUS Status; 910 BOOLEAN Result; 911 WIN32_CALLOUTS_FPNS CalloutData = {0}; 912 PVOID GlobalUserHeapBase = NULL; 913 914 /* 915 * Register user mode call interface 916 * (system service table index = 1) 917 */ 918 Result = KeAddSystemServiceTable(Win32kSSDT, 919 NULL, 920 Win32kNumberOfSysCalls, 921 Win32kSSPT, 922 1); 923 if (Result == FALSE) 924 { 925 DPRINT1("Adding system services failed!\n"); 926 return STATUS_UNSUCCESSFUL; 927 } 928 929 hModuleWin = MmPageEntireDriver(DriverEntry); 930 DPRINT("Win32k hInstance 0x%p!\n", hModuleWin); 931 932 DriverObject->DriverUnload = DriverUnload; 933 934 /* Register Object Manager Callbacks */ 935 CalloutData.ProcessCallout = Win32kProcessCallback; 936 CalloutData.ThreadCallout = Win32kThreadCallback; 937 // CalloutData.GlobalAtomTableCallout = NULL; 938 // CalloutData.PowerEventCallout = NULL; 939 // CalloutData.PowerStateCallout = NULL; 940 // CalloutData.JobCallout = NULL; 941 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch; 942 CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen; 943 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose; 944 CalloutData.DesktopCloseProcedure = IntDesktopObjectClose; 945 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete; 946 CalloutData.WindowStationOkToCloseProcedure = IntWinStaOkToClose; 947 // CalloutData.WindowStationCloseProcedure = NULL; 948 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete; 949 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse; 950 // CalloutData.WindowStationOpenProcedure = NULL; 951 952 /* Register our per-process and per-thread structures. */ 953 PsEstablishWin32Callouts(&CalloutData); 954 955 /* Register service hook callbacks */ 956 #if DBG && defined(KDBG) 957 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0); 958 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0); 959 #endif 960 961 /* Create the global USER heap */ 962 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection, 963 &GlobalUserHeapBase, 964 1 * 1024 * 1024); /* FIXME: 1 MB for now... */ 965 if (GlobalUserHeap == NULL) 966 { 967 DPRINT1("Failed to initialize the global heap!\n"); 968 return STATUS_UNSUCCESSFUL; 969 } 970 971 /* Allocate global server info structure */ 972 gpsi = UserHeapAlloc(sizeof(*gpsi)); 973 if (!gpsi) 974 { 975 DPRINT1("Failed allocate server info structure!\n"); 976 return STATUS_UNSUCCESSFUL; 977 } 978 979 RtlZeroMemory(gpsi, sizeof(*gpsi)); 980 DPRINT("Global Server Data -> %p\n", gpsi); 981 982 NT_ROF(InitGdiHandleTable()); 983 NT_ROF(InitPaletteImpl()); 984 985 /* Create stock objects, ie. precreated objects commonly 986 used by win32 applications */ 987 CreateStockObjects(); 988 CreateSysColorObjects(); 989 990 NT_ROF(InitBrushImpl()); 991 NT_ROF(InitPDEVImpl()); 992 NT_ROF(InitLDEVImpl()); 993 NT_ROF(InitDeviceImpl()); 994 NT_ROF(InitDcImpl()); 995 NT_ROF(InitUserImpl()); 996 NT_ROF(InitWindowStationImpl()); 997 NT_ROF(InitDesktopImpl()); 998 NT_ROF(InitInputImpl()); 999 NT_ROF(InitKeyboardImpl()); 1000 NT_ROF(MsqInitializeImpl()); 1001 NT_ROF(InitTimerImpl()); 1002 NT_ROF(InitDCEImpl()); 1003 1004 gusLanguageID = UserGetLanguageID(); 1005 1006 /* Initialize FreeType library */ 1007 if (!InitFontSupport()) 1008 { 1009 DPRINT1("Unable to initialize font support\n"); 1010 return Status; 1011 } 1012 1013 return STATUS_SUCCESS; 1014 } 1015 1016 /* EOF */ 1017