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