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) 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->ppi->hdeskStartup == NULL && InputWindowStation != NULL) 579 /* Last things to do only if we are not a SYSTEM or CSRSS thread */ 580 // HACK Part #1: Temporarily disabled to have our current USERSRV running, but normally this is its duty to connect itself to the required desktop! 581 if (// !(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) && 582 /**/ptiCurrent->ppi->hdeskStartup == NULL &&/**/ 583 InputWindowStation != NULL) 584 { 585 HWINSTA hWinSta = NULL; 586 HDESK hDesk = NULL; 587 UNICODE_STRING DesktopPath; 588 PDESKTOP pdesk; 589 590 // HACK Part #2: We force USERSRV to connect to WinSta0 by setting the STARTF_INHERITDESKTOP flag. 591 if (ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) 592 ProcessParams->WindowFlags |= STARTF_INHERITDESKTOP; 593 594 /* 595 * Inherit the thread desktop and process window station (if not yet inherited) 596 * from the process startup info structure. See documentation of CreateProcess(). 597 */ 598 599 Status = STATUS_UNSUCCESSFUL; 600 if (ProcessParams && ProcessParams->DesktopInfo.Length > 0) 601 { 602 Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo); 603 } 604 if (!NT_SUCCESS(Status)) 605 { 606 RtlInitUnicodeString(&DesktopPath, NULL); 607 } 608 609 Status = IntResolveDesktop(Process, 610 &DesktopPath, 611 !!(ProcessParams->WindowFlags & STARTF_INHERITDESKTOP), 612 &hWinSta, 613 &hDesk); 614 615 if (DesktopPath.Buffer) 616 ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING); 617 618 if (!NT_SUCCESS(Status)) 619 { 620 ERR_CH(UserThread, "Failed to assign default desktop and winsta to process\n"); 621 goto error; 622 } 623 624 if (!UserSetProcessWindowStation(hWinSta)) 625 { 626 Status = STATUS_UNSUCCESSFUL; 627 ERR_CH(UserThread, "Failed to set initial process winsta\n"); 628 goto error; 629 } 630 631 /* Validate the new desktop */ 632 Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk); 633 if (!NT_SUCCESS(Status)) 634 { 635 ERR_CH(UserThread, "Failed to validate initial desktop handle\n"); 636 goto error; 637 } 638 639 /* Store the parsed desktop as the initial desktop */ 640 ASSERT(ptiCurrent->ppi->hdeskStartup == NULL); 641 ASSERT(Process->UniqueProcessId != gpidLogon); 642 ptiCurrent->ppi->hdeskStartup = hDesk; 643 ptiCurrent->ppi->rpdeskStartup = pdesk; 644 } 645 646 if (ptiCurrent->ppi->hdeskStartup != NULL) 647 { 648 if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE)) 649 { 650 ERR_CH(UserThread, "Failed to set thread desktop\n"); 651 Status = STATUS_UNSUCCESSFUL; 652 goto error; 653 } 654 } 655 656 /* Mark the thread as fully initialized */ 657 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; 658 659 if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && 660 (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) 661 { 662 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 663 } 664 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 665 666 /* Last things to do only if we are not a SYSTEM or CSRSS thread */ 667 if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) 668 { 669 /* Callback to User32 Client Thread Setup */ 670 TRACE_CH(UserThread, "Call co_IntClientThreadSetup...\n"); 671 Status = co_IntClientThreadSetup(); 672 if (!NT_SUCCESS(Status)) 673 { 674 ERR_CH(UserThread, "ClientThreadSetup failed with Status 0x%08lx\n", Status); 675 goto error; 676 } 677 TRACE_CH(UserThread, "co_IntClientThreadSetup succeeded!\n"); 678 } 679 else 680 { 681 TRACE_CH(UserThread, "co_IntClientThreadSetup cannot be called...\n"); 682 } 683 684 TRACE_CH(UserThread, "UserCreateW32Thread pti 0x%p\n", ptiCurrent); 685 return STATUS_SUCCESS; 686 687 error: 688 ERR_CH(UserThread, "InitThreadCallback failed! Freeing pti 0x%p for TID:0x%lx\n", 689 ptiCurrent, HandleToUlong(Thread->Cid.UniqueThread)); 690 ExitThreadCallback(Thread); 691 return Status; 692 } 693 694 VOID 695 UserDisplayNotifyShutdown(PPROCESSINFO ppiCurrent); 696 697 NTSTATUS 698 NTAPI 699 ExitThreadCallback(PETHREAD Thread) 700 { 701 PTHREADINFO *ppti; 702 PSINGLE_LIST_ENTRY psle; 703 PPROCESSINFO ppiCurrent; 704 PEPROCESS Process; 705 PTHREADINFO ptiCurrent; 706 707 Process = Thread->ThreadsProcess; 708 709 /* Get the Win32 Thread */ 710 ptiCurrent = PsGetThreadWin32Thread(Thread); 711 ASSERT(ptiCurrent); 712 713 TRACE_CH(UserThread, "Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); 714 715 ptiCurrent->TIF_flags |= TIF_INCLEANUP; 716 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 717 718 ppiCurrent = ptiCurrent->ppi; 719 ASSERT(ppiCurrent); 720 721 IsRemoveAttachThread(ptiCurrent); 722 723 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; 724 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 725 726 UserCloseClipboard(); 727 728 /* Decrement thread count and check if its 0 */ 729 ppiCurrent->cThreads--; 730 731 if (ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED) 732 { 733 /* Do now some process cleanup that requires a valid win32 thread */ 734 if (ptiCurrent->ppi->cThreads == 0) 735 { 736 /* Check if we have registered the user api hook */ 737 if (ptiCurrent->ppi == ppiUahServer) 738 { 739 /* Unregister the api hook */ 740 UserUnregisterUserApiHook(); 741 } 742 743 /* Notify logon application to restart shell if needed */ 744 if (ptiCurrent->pDeskInfo) 745 { 746 if (ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent) 747 { 748 DWORD ExitCode = PsGetProcessExitStatus(Process); 749 750 TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode); 751 752 UserPostMessage(hwndSAS, 753 WM_LOGONNOTIFY, 754 LN_SHELL_EXITED, 755 ExitCode); 756 757 ptiCurrent->pDeskInfo->ppiShellProcess = NULL; 758 } 759 } 760 } 761 762 DceFreeThreadDCE(ptiCurrent); 763 DestroyTimersForThread(ptiCurrent); 764 KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE); 765 UnregisterThreadHotKeys(ptiCurrent); 766 767 if (!UserDestroyObjectsForOwner(gHandleTable, ptiCurrent)) 768 { 769 DPRINT1("Failed to delete objects belonging to thread %p. This is VERY BAD!.\n", ptiCurrent); 770 ASSERT(FALSE); 771 return STATUS_UNSUCCESSFUL; 772 } 773 774 if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && 775 ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) 776 { 777 TRACE_CH(UserThread, "DestroyProcessClasses\n"); 778 /* no process windows should exist at this point, or the function will assert! */ 779 DestroyProcessClasses(ppiCurrent); 780 ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; 781 } 782 783 IntBlockInput(ptiCurrent, FALSE); 784 IntCleanupThreadCallbacks(ptiCurrent); 785 786 /* cleanup user object references stack */ 787 psle = PopEntryList(&ptiCurrent->ReferencesList); 788 while (psle) 789 { 790 PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry); 791 TRACE_CH(UserThread, "thread clean: remove reference obj 0x%p\n",ref->obj); 792 UserDereferenceObject(ref->obj); 793 794 psle = PopEntryList(&ptiCurrent->ReferencesList); 795 } 796 } 797 798 if (ptiCurrent->cEnterCount) 799 { 800 KeSetKernelStackSwapEnable(TRUE); 801 ptiCurrent->cEnterCount = 0; 802 } 803 804 /* Find the THREADINFO in the PROCESSINFO's list */ 805 ppti = &ppiCurrent->ptiList; 806 while (*ppti != NULL && *ppti != ptiCurrent) 807 { 808 ppti = &((*ppti)->ptiSibling); 809 } 810 811 /* we must have found it */ 812 ASSERT(*ppti == ptiCurrent); 813 814 /* Remove it from the list */ 815 *ppti = ptiCurrent->ptiSibling; 816 817 if (ptiCurrent->KeyboardLayout) 818 UserDereferenceObject(ptiCurrent->KeyboardLayout); 819 820 if (gptiForeground == ptiCurrent) 821 { 822 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); 823 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); 824 825 gptiForeground = NULL; 826 } 827 828 /* Restore display mode when we are the last thread, and we changed the display mode */ 829 if (ppiCurrent->cThreads == 0) 830 UserDisplayNotifyShutdown(ppiCurrent); 831 832 833 // Fixes CORE-6384 & CORE-7030. 834 /* if (ptiLastInput == ptiCurrent) 835 { 836 if (!ppiCurrent->ptiList) 837 ptiLastInput = gptiForeground; 838 else 839 ptiLastInput = ppiCurrent->ptiList; 840 ERR_CH(UserThread, "DTI: ptiLastInput is Cleared!!\n"); 841 } 842 */ 843 TRACE_CH(UserThread, "Freeing pti 0x%p\n", ptiCurrent); 844 845 IntSetThreadDesktop(NULL, TRUE); 846 847 if (ptiCurrent->hEventQueueClient != NULL) 848 { 849 ObCloseHandle(ptiCurrent->hEventQueueClient, UserMode); 850 ObDereferenceObject(ptiCurrent->pEventQueueServer); 851 } 852 ptiCurrent->hEventQueueClient = NULL; 853 854 /* The thread is dying */ 855 PsSetThreadWin32Thread(Thread /*ptiCurrent->pEThread*/, NULL, ptiCurrent); 856 ptiCurrent->pEThread = NULL; 857 858 /* Free the THREADINFO */ 859 FreeW32Thread(/*Thread*/ ptiCurrent); // IntDereferenceThreadInfo(ptiCurrent); 860 861 return STATUS_SUCCESS; 862 } 863 864 NTSTATUS 865 APIENTRY 866 Win32kThreadCallback(PETHREAD Thread, 867 PSW32THREADCALLOUTTYPE Type) 868 { 869 NTSTATUS Status; 870 871 ASSERT(NtCurrentTeb()); 872 873 UserEnterExclusive(); 874 875 if (Type == PsW32ThreadCalloutInitialize) 876 { 877 ASSERT(PsGetThreadWin32Thread(Thread) == NULL); 878 Status = InitThreadCallback(Thread); 879 } 880 else // if (Type == PsW32ThreadCalloutExit) 881 { 882 ASSERT(PsGetThreadWin32Thread(Thread) != NULL); 883 Status = ExitThreadCallback(Thread); 884 } 885 886 UserLeave(); 887 888 return Status; 889 } 890 891 _Function_class_(DRIVER_UNLOAD) 892 VOID NTAPI 893 DriverUnload(IN PDRIVER_OBJECT DriverObject) 894 { 895 // TODO: Do more cleanup! 896 897 ResetCsrApiPort(); 898 ResetCsrProcess(); 899 } 900 901 // Return on failure 902 #define NT_ROF(x) \ 903 { \ 904 Status = (x); \ 905 if (!NT_SUCCESS(Status)) \ 906 { \ 907 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \ 908 return Status; \ 909 } \ 910 } 911 912 /* 913 * This definition doesn't work 914 */ 915 INIT_SECTION 916 NTSTATUS 917 APIENTRY 918 DriverEntry( 919 IN PDRIVER_OBJECT DriverObject, 920 IN PUNICODE_STRING RegistryPath) 921 { 922 NTSTATUS Status; 923 BOOLEAN Result; 924 WIN32_CALLOUTS_FPNS CalloutData = {0}; 925 PVOID GlobalUserHeapBase = NULL; 926 927 /* 928 * Register user mode call interface 929 * (system service table index = 1) 930 */ 931 Result = KeAddSystemServiceTable(Win32kSSDT, 932 NULL, 933 Win32kNumberOfSysCalls, 934 Win32kSSPT, 935 1); 936 if (Result == FALSE) 937 { 938 DPRINT1("Adding system services failed!\n"); 939 return STATUS_UNSUCCESSFUL; 940 } 941 942 hModuleWin = MmPageEntireDriver(DriverEntry); 943 DPRINT("Win32k hInstance 0x%p!\n", hModuleWin); 944 945 DriverObject->DriverUnload = DriverUnload; 946 947 /* Register Object Manager Callbacks */ 948 CalloutData.ProcessCallout = Win32kProcessCallback; 949 CalloutData.ThreadCallout = Win32kThreadCallback; 950 // CalloutData.GlobalAtomTableCallout = NULL; 951 // CalloutData.PowerEventCallout = NULL; 952 // CalloutData.PowerStateCallout = NULL; 953 // CalloutData.JobCallout = NULL; 954 CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch; 955 CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen; 956 CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose; 957 CalloutData.DesktopCloseProcedure = IntDesktopObjectClose; 958 CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete; 959 CalloutData.WindowStationOkToCloseProcedure = IntWinStaOkToClose; 960 // CalloutData.WindowStationCloseProcedure = NULL; 961 CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete; 962 CalloutData.WindowStationParseProcedure = IntWinStaObjectParse; 963 // CalloutData.WindowStationOpenProcedure = NULL; 964 965 /* Register our per-process and per-thread structures. */ 966 PsEstablishWin32Callouts(&CalloutData); 967 968 /* Register service hook callbacks */ 969 #if DBG && defined(KDBG) 970 KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0); 971 KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0); 972 #endif 973 974 /* Create the global USER heap */ 975 GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection, 976 &GlobalUserHeapBase, 977 1 * 1024 * 1024); /* FIXME: 1 MB for now... */ 978 if (GlobalUserHeap == NULL) 979 { 980 DPRINT1("Failed to initialize the global heap!\n"); 981 return STATUS_UNSUCCESSFUL; 982 } 983 984 /* Allocate global server info structure */ 985 gpsi = UserHeapAlloc(sizeof(*gpsi)); 986 if (!gpsi) 987 { 988 DPRINT1("Failed allocate server info structure!\n"); 989 return STATUS_UNSUCCESSFUL; 990 } 991 992 RtlZeroMemory(gpsi, sizeof(*gpsi)); 993 DPRINT("Global Server Data -> %p\n", gpsi); 994 995 NT_ROF(InitGdiHandleTable()); 996 NT_ROF(InitPaletteImpl()); 997 998 /* Create stock objects, ie. precreated objects commonly 999 used by win32 applications */ 1000 CreateStockObjects(); 1001 CreateSysColorObjects(); 1002 1003 NT_ROF(InitBrushImpl()); 1004 NT_ROF(InitPDEVImpl()); 1005 NT_ROF(InitLDEVImpl()); 1006 NT_ROF(InitDeviceImpl()); 1007 NT_ROF(InitDcImpl()); 1008 NT_ROF(InitUserImpl()); 1009 NT_ROF(InitWindowStationImpl()); 1010 NT_ROF(InitDesktopImpl()); 1011 NT_ROF(InitInputImpl()); 1012 NT_ROF(InitKeyboardImpl()); 1013 NT_ROF(MsqInitializeImpl()); 1014 NT_ROF(InitTimerImpl()); 1015 NT_ROF(InitDCEImpl()); 1016 1017 gusLanguageID = UserGetLanguageID(); 1018 1019 /* Initialize FreeType library */ 1020 if (!InitFontSupport()) 1021 { 1022 DPRINT1("Unable to initialize font support\n"); 1023 return Status; 1024 } 1025 1026 return STATUS_SUCCESS; 1027 } 1028 1029 /* EOF */ 1030