1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/mm/ARM3/procsup.c 5 * PURPOSE: ARM Memory Manager Process Related Management 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #define MODULE_INVOLVED_IN_ARM3 16 #include <mm/ARM3/miarm.h> 17 18 /* GLOBALS ********************************************************************/ 19 20 ULONG MmProcessColorSeed = 0x12345678; 21 PMMWSL MmWorkingSetList; 22 ULONG MmMaximumDeadKernelStacks = 5; 23 SLIST_HEADER MmDeadStackSListHead; 24 25 /* PRIVATE FUNCTIONS **********************************************************/ 26 27 NTSTATUS 28 NTAPI 29 MiCreatePebOrTeb(IN PEPROCESS Process, 30 IN ULONG Size, 31 OUT PULONG_PTR BaseAddress) 32 { 33 PMMVAD_LONG Vad; 34 NTSTATUS Status; 35 ULONG_PTR HighestAddress, RandomBase; 36 ULONG AlignedSize; 37 LARGE_INTEGER CurrentTime; 38 39 /* Allocate a VAD */ 40 Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV'); 41 if (!Vad) return STATUS_NO_MEMORY; 42 43 /* Setup the primary flags with the size, and make it commited, private, RW */ 44 Vad->u.LongFlags = 0; 45 Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size); 46 Vad->u.VadFlags.MemCommit = TRUE; 47 Vad->u.VadFlags.PrivateMemory = TRUE; 48 Vad->u.VadFlags.Protection = MM_READWRITE; 49 Vad->u.VadFlags.NoChange = TRUE; 50 Vad->u1.Parent = NULL; 51 52 /* Setup the secondary flags to make it a secured, writable, long VAD */ 53 Vad->u2.LongFlags2 = 0; 54 Vad->u2.VadFlags2.OneSecured = TRUE; 55 Vad->u2.VadFlags2.LongVad = TRUE; 56 Vad->u2.VadFlags2.ReadOnly = FALSE; 57 58 Vad->ControlArea = NULL; // For Memory-Area hack 59 Vad->FirstPrototypePte = NULL; 60 61 /* Check if this is a PEB creation */ 62 ASSERT(sizeof(TEB) != sizeof(PEB)); 63 if (Size == sizeof(PEB)) 64 { 65 /* Create a random value to select one page in a 64k region */ 66 KeQueryTickCount(&CurrentTime); 67 CurrentTime.LowPart &= (_64K / PAGE_SIZE) - 1; 68 69 /* Calculate a random base address */ 70 RandomBase = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1; 71 RandomBase -= CurrentTime.LowPart << PAGE_SHIFT; 72 73 /* Make sure the base address is not too high */ 74 AlignedSize = ROUND_TO_PAGES(Size); 75 if ((RandomBase + AlignedSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) 76 { 77 RandomBase = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1 - AlignedSize; 78 } 79 80 /* Calculate the highest allowed address */ 81 HighestAddress = RandomBase + AlignedSize - 1; 82 } 83 else 84 { 85 HighestAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS; 86 } 87 88 *BaseAddress = 0; 89 Status = MiInsertVadEx((PMMVAD)Vad, 90 BaseAddress, 91 Size, 92 HighestAddress, 93 PAGE_SIZE, 94 MEM_TOP_DOWN); 95 if (!NT_SUCCESS(Status)) 96 { 97 ExFreePoolWithTag(Vad, 'ldaV'); 98 return STATUS_NO_MEMORY; 99 } 100 101 /* Success */ 102 return STATUS_SUCCESS; 103 } 104 105 VOID 106 NTAPI 107 MmDeleteTeb(IN PEPROCESS Process, 108 IN PTEB Teb) 109 { 110 ULONG_PTR TebEnd; 111 PETHREAD Thread = PsGetCurrentThread(); 112 PMMVAD Vad; 113 PMM_AVL_TABLE VadTree = &Process->VadRoot; 114 DPRINT("Deleting TEB: %p in %16s\n", Teb, Process->ImageFileName); 115 116 /* TEB is one page */ 117 TebEnd = (ULONG_PTR)Teb + ROUND_TO_PAGES(sizeof(TEB)) - 1; 118 119 /* Attach to the process */ 120 KeAttachProcess(&Process->Pcb); 121 122 /* Lock the process address space */ 123 KeAcquireGuardedMutex(&Process->AddressCreationLock); 124 125 /* Find the VAD, make sure it's a TEB VAD */ 126 Vad = MiLocateAddress(Teb); 127 DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn); 128 ASSERT(Vad != NULL); 129 if (Vad->StartingVpn != ((ULONG_PTR)Teb >> PAGE_SHIFT)) 130 { 131 /* Bug in the AVL code? */ 132 DPRINT1("Corrupted VAD!\n"); 133 } 134 else 135 { 136 /* Sanity checks for a valid TEB VAD */ 137 ASSERT((Vad->StartingVpn == ((ULONG_PTR)Teb >> PAGE_SHIFT) && 138 (Vad->EndingVpn == (TebEnd >> PAGE_SHIFT)))); 139 ASSERT(Vad->u.VadFlags.NoChange == TRUE); 140 ASSERT(Vad->u2.VadFlags2.OneSecured == TRUE); 141 ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE); 142 143 /* Lock the working set */ 144 MiLockProcessWorkingSetUnsafe(Process, Thread); 145 146 /* Remove this VAD from the tree */ 147 ASSERT(VadTree->NumberGenericTableElements >= 1); 148 MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree); 149 150 /* Delete the pages */ 151 MiDeleteVirtualAddresses((ULONG_PTR)Teb, TebEnd, NULL); 152 153 /* Release the working set */ 154 MiUnlockProcessWorkingSetUnsafe(Process, Thread); 155 156 /* Remove the VAD */ 157 ExFreePool(Vad); 158 } 159 160 /* Release the address space lock */ 161 KeReleaseGuardedMutex(&Process->AddressCreationLock); 162 163 /* Detach */ 164 KeDetachProcess(); 165 } 166 167 VOID 168 NTAPI 169 MmDeleteKernelStack(IN PVOID StackBase, 170 IN BOOLEAN GuiStack) 171 { 172 PMMPTE PointerPte; 173 PFN_NUMBER PageFrameNumber, PageTableFrameNumber; 174 PFN_COUNT StackPages; 175 PMMPFN Pfn1, Pfn2; 176 ULONG i; 177 KIRQL OldIrql; 178 179 // 180 // This should be the guard page, so decrement by one 181 // 182 PointerPte = MiAddressToPte(StackBase); 183 PointerPte--; 184 185 // 186 // If this is a small stack, just push the stack onto the dead stack S-LIST 187 // 188 if (!GuiStack) 189 { 190 if (ExQueryDepthSList(&MmDeadStackSListHead) < MmMaximumDeadKernelStacks) 191 { 192 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber); 193 InterlockedPushEntrySList(&MmDeadStackSListHead, 194 (PSLIST_ENTRY)&Pfn1->u1.NextStackPfn); 195 return; 196 } 197 } 198 199 // 200 // Calculate pages used 201 // 202 StackPages = BYTES_TO_PAGES(GuiStack ? 203 MmLargeStackSize : KERNEL_STACK_SIZE); 204 205 /* Acquire the PFN lock */ 206 OldIrql = MiAcquirePfnLock(); 207 208 // 209 // Loop them 210 // 211 for (i = 0; i < StackPages; i++) 212 { 213 // 214 // Check if this is a valid PTE 215 // 216 if (PointerPte->u.Hard.Valid == 1) 217 { 218 /* Get the PTE's page */ 219 PageFrameNumber = PFN_FROM_PTE(PointerPte); 220 Pfn1 = MiGetPfnEntry(PageFrameNumber); 221 222 /* Now get the page of the page table mapping it */ 223 PageTableFrameNumber = Pfn1->u4.PteFrame; 224 Pfn2 = MiGetPfnEntry(PageTableFrameNumber); 225 226 /* Remove a shared reference, since the page is going away */ 227 MiDecrementShareCount(Pfn2, PageTableFrameNumber); 228 229 /* Set the special pending delete marker */ 230 MI_SET_PFN_DELETED(Pfn1); 231 232 /* And now delete the actual stack page */ 233 MiDecrementShareCount(Pfn1, PageFrameNumber); 234 } 235 236 // 237 // Next one 238 // 239 PointerPte--; 240 } 241 242 // 243 // We should be at the guard page now 244 // 245 ASSERT(PointerPte->u.Hard.Valid == 0); 246 247 /* Release the PFN lock */ 248 MiReleasePfnLock(OldIrql); 249 250 // 251 // Release the PTEs 252 // 253 MiReleaseSystemPtes(PointerPte, StackPages + 1, SystemPteSpace); 254 } 255 256 PVOID 257 NTAPI 258 MmCreateKernelStack(IN BOOLEAN GuiStack, 259 IN UCHAR Node) 260 { 261 PFN_COUNT StackPtes, StackPages; 262 PMMPTE PointerPte, StackPte; 263 PVOID BaseAddress; 264 MMPTE TempPte, InvalidPte; 265 KIRQL OldIrql; 266 PFN_NUMBER PageFrameIndex; 267 ULONG i; 268 PMMPFN Pfn1; 269 270 // 271 // Calculate pages needed 272 // 273 if (GuiStack) 274 { 275 // 276 // We'll allocate 64KB stack, but only commit 12K 277 // 278 StackPtes = BYTES_TO_PAGES(MmLargeStackSize); 279 StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT); 280 } 281 else 282 { 283 // 284 // If the dead stack S-LIST has a stack on it, use it instead of allocating 285 // new system PTEs for this stack 286 // 287 if (ExQueryDepthSList(&MmDeadStackSListHead)) 288 { 289 Pfn1 = (PMMPFN)InterlockedPopEntrySList(&MmDeadStackSListHead); 290 if (Pfn1) 291 { 292 PointerPte = Pfn1->PteAddress; 293 BaseAddress = MiPteToAddress(++PointerPte); 294 return BaseAddress; 295 } 296 } 297 298 // 299 // We'll allocate 12K and that's it 300 // 301 StackPtes = BYTES_TO_PAGES(KERNEL_STACK_SIZE); 302 StackPages = StackPtes; 303 } 304 305 // 306 // Reserve stack pages, plus a guard page 307 // 308 StackPte = MiReserveSystemPtes(StackPtes + 1, SystemPteSpace); 309 if (!StackPte) return NULL; 310 311 // 312 // Get the stack address 313 // 314 BaseAddress = MiPteToAddress(StackPte + StackPtes + 1); 315 316 // 317 // Select the right PTE address where we actually start committing pages 318 // 319 PointerPte = StackPte; 320 if (GuiStack) PointerPte += BYTES_TO_PAGES(MmLargeStackSize - 321 KERNEL_LARGE_STACK_COMMIT); 322 323 324 /* Setup the temporary invalid PTE */ 325 MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS); 326 327 /* Setup the template stack PTE */ 328 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0); 329 330 // 331 // Acquire the PFN DB lock 332 // 333 OldIrql = MiAcquirePfnLock(); 334 335 // 336 // Loop each stack page 337 // 338 for (i = 0; i < StackPages; i++) 339 { 340 // 341 // Next PTE 342 // 343 PointerPte++; 344 345 /* Get a page and write the current invalid PTE */ 346 MI_SET_USAGE(MI_USAGE_KERNEL_STACK); 347 MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); 348 PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); 349 MI_WRITE_INVALID_PTE(PointerPte, InvalidPte); 350 351 /* Initialize the PFN entry for this page */ 352 MiInitializePfn(PageFrameIndex, PointerPte, 1); 353 354 /* Write the valid PTE */ 355 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 356 MI_WRITE_VALID_PTE(PointerPte, TempPte); 357 } 358 359 // 360 // Release the PFN lock 361 // 362 MiReleasePfnLock(OldIrql); 363 364 // 365 // Return the stack address 366 // 367 return BaseAddress; 368 } 369 370 NTSTATUS 371 NTAPI 372 MmGrowKernelStackEx(IN PVOID StackPointer, 373 IN ULONG GrowSize) 374 { 375 PKTHREAD Thread = KeGetCurrentThread(); 376 PMMPTE LimitPte, NewLimitPte, LastPte; 377 KIRQL OldIrql; 378 MMPTE TempPte, InvalidPte; 379 PFN_NUMBER PageFrameIndex; 380 381 // 382 // Make sure the stack did not overflow 383 // 384 ASSERT(((ULONG_PTR)Thread->StackBase - (ULONG_PTR)Thread->StackLimit) <= 385 (MmLargeStackSize + PAGE_SIZE)); 386 387 // 388 // Get the current stack limit 389 // 390 LimitPte = MiAddressToPte(Thread->StackLimit); 391 ASSERT(LimitPte->u.Hard.Valid == 1); 392 393 // 394 // Get the new one and make sure this isn't a retarded request 395 // 396 NewLimitPte = MiAddressToPte((PVOID)((ULONG_PTR)StackPointer - GrowSize)); 397 if (NewLimitPte == LimitPte) return STATUS_SUCCESS; 398 399 // 400 // Now make sure you're not going past the reserved space 401 // 402 LastPte = MiAddressToPte((PVOID)((ULONG_PTR)Thread->StackBase - 403 MmLargeStackSize)); 404 if (NewLimitPte < LastPte) 405 { 406 // 407 // Sorry! 408 // 409 DPRINT1("Thread wants too much stack\n"); 410 return STATUS_STACK_OVERFLOW; 411 } 412 413 // 414 // Calculate the number of new pages 415 // 416 LimitPte--; 417 418 /* Setup the temporary invalid PTE */ 419 MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS); 420 421 // 422 // Acquire the PFN DB lock 423 // 424 OldIrql = MiAcquirePfnLock(); 425 426 // 427 // Loop each stack page 428 // 429 while (LimitPte >= NewLimitPte) 430 { 431 /* Get a page and write the current invalid PTE */ 432 MI_SET_USAGE(MI_USAGE_KERNEL_STACK_EXPANSION); 433 MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); 434 PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); 435 MI_WRITE_INVALID_PTE(LimitPte, InvalidPte); 436 437 /* Initialize the PFN entry for this page */ 438 MiInitializePfn(PageFrameIndex, LimitPte, 1); 439 440 /* Setup the template stack PTE */ 441 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex); 442 443 /* Write the valid PTE */ 444 MI_WRITE_VALID_PTE(LimitPte--, TempPte); 445 } 446 447 // 448 // Release the PFN lock 449 // 450 MiReleasePfnLock(OldIrql); 451 452 // 453 // Set the new limit 454 // 455 Thread->StackLimit = (ULONG_PTR)MiPteToAddress(NewLimitPte); 456 return STATUS_SUCCESS; 457 } 458 459 NTSTATUS 460 NTAPI 461 MmGrowKernelStack(IN PVOID StackPointer) 462 { 463 // 464 // Call the extended version 465 // 466 return MmGrowKernelStackEx(StackPointer, KERNEL_LARGE_STACK_COMMIT); 467 } 468 469 NTSTATUS 470 NTAPI 471 MmSetMemoryPriorityProcess(IN PEPROCESS Process, 472 IN UCHAR MemoryPriority) 473 { 474 UCHAR OldPriority; 475 476 // 477 // Check if we have less then 16MB of Physical Memory 478 // 479 if ((MmSystemSize == MmSmallSystem) && 480 (MmNumberOfPhysicalPages < ((15 * 1024 * 1024) / PAGE_SIZE))) 481 { 482 // 483 // Always use background priority 484 // 485 MemoryPriority = MEMORY_PRIORITY_BACKGROUND; 486 } 487 488 // 489 // Save the old priority and update it 490 // 491 OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority; 492 Process->Vm.Flags.MemoryPriority = MemoryPriority; 493 494 // 495 // Return the old priority 496 // 497 return OldPriority; 498 } 499 500 NTSTATUS 501 NTAPI 502 MmCreatePeb(IN PEPROCESS Process, 503 IN PINITIAL_PEB InitialPeb, 504 OUT PPEB *BasePeb) 505 { 506 PPEB Peb = NULL; 507 LARGE_INTEGER SectionOffset; 508 SIZE_T ViewSize = 0; 509 PVOID TableBase = NULL; 510 PIMAGE_NT_HEADERS NtHeaders; 511 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData; 512 NTSTATUS Status; 513 USHORT Characteristics; 514 KAFFINITY ProcessAffinityMask = 0; 515 SectionOffset.QuadPart = (ULONGLONG)0; 516 *BasePeb = NULL; 517 518 // 519 // Attach to Process 520 // 521 KeAttachProcess(&Process->Pcb); 522 523 // 524 // Map NLS Tables 525 // 526 Status = MmMapViewOfSection(ExpNlsSectionPointer, 527 (PEPROCESS)Process, 528 &TableBase, 529 0, 530 0, 531 &SectionOffset, 532 &ViewSize, 533 ViewShare, 534 MEM_TOP_DOWN, 535 PAGE_READONLY); 536 DPRINT("NLS Tables at: %p\n", TableBase); 537 if (!NT_SUCCESS(Status)) 538 { 539 /* Cleanup and exit */ 540 KeDetachProcess(); 541 return Status; 542 } 543 544 // 545 // Allocate the PEB 546 // 547 Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb); 548 DPRINT("PEB at: %p\n", Peb); 549 if (!NT_SUCCESS(Status)) 550 { 551 /* Cleanup and exit */ 552 KeDetachProcess(); 553 return Status; 554 } 555 556 // 557 // Use SEH in case we can't load the PEB 558 // 559 _SEH2_TRY 560 { 561 // 562 // Initialize the PEB 563 // 564 RtlZeroMemory(Peb, sizeof(PEB)); 565 566 // 567 // Set up data 568 // 569 Peb->ImageBaseAddress = Process->SectionBaseAddress; 570 Peb->InheritedAddressSpace = InitialPeb->InheritedAddressSpace; 571 Peb->Mutant = InitialPeb->Mutant; 572 Peb->ImageUsesLargePages = InitialPeb->ImageUsesLargePages; 573 574 // 575 // NLS 576 // 577 Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset; 578 Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset; 579 Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset; 580 581 // 582 // Default Version Data (could get changed below) 583 // 584 Peb->OSMajorVersion = NtMajorVersion; 585 Peb->OSMinorVersion = NtMinorVersion; 586 Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF); 587 Peb->OSPlatformId = VER_PLATFORM_WIN32_NT; 588 Peb->OSCSDVersion = (USHORT)CmNtCSDVersion; 589 590 // 591 // Heap and Debug Data 592 // 593 Peb->NumberOfProcessors = KeNumberProcessors; 594 Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL); 595 Peb->NtGlobalFlag = NtGlobalFlag; 596 Peb->HeapSegmentReserve = MmHeapSegmentReserve; 597 Peb->HeapSegmentCommit = MmHeapSegmentCommit; 598 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold; 599 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold; 600 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout; 601 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes; 602 Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID); 603 Peb->ProcessHeaps = (PVOID*)(Peb + 1); 604 605 // 606 // Session ID 607 // 608 if (Process->Session) Peb->SessionId = MmGetSessionId(Process); 609 } 610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 611 { 612 // 613 // Fail 614 // 615 KeDetachProcess(); 616 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 617 } 618 _SEH2_END; 619 620 // 621 // Use SEH in case we can't load the image 622 // 623 _SEH2_TRY 624 { 625 // 626 // Get NT Headers 627 // 628 NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress); 629 Characteristics = NtHeaders->FileHeader.Characteristics; 630 } 631 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 632 { 633 // 634 // Fail 635 // 636 KeDetachProcess(); 637 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT); 638 } 639 _SEH2_END; 640 641 // 642 // Parse the headers 643 // 644 if (NtHeaders) 645 { 646 // 647 // Use SEH in case we can't load the headers 648 // 649 _SEH2_TRY 650 { 651 // 652 // Get the Image Config Data too 653 // 654 ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 655 TRUE, 656 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 657 (PULONG)&ViewSize); 658 if (ImageConfigData) 659 { 660 // 661 // Probe it 662 // 663 ProbeForRead(ImageConfigData, 664 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY), 665 sizeof(ULONG)); 666 } 667 668 // 669 // Write subsystem data 670 // 671 Peb->ImageSubsystem = NtHeaders->OptionalHeader.Subsystem; 672 Peb->ImageSubsystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion; 673 Peb->ImageSubsystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion; 674 675 // 676 // Check for version data 677 // 678 if (NtHeaders->OptionalHeader.Win32VersionValue) 679 { 680 // 681 // Extract values and write them 682 // 683 Peb->OSMajorVersion = NtHeaders->OptionalHeader.Win32VersionValue & 0xFF; 684 Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF; 685 Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF; 686 Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2; 687 688 /* Process CSD version override */ 689 if ((ImageConfigData) && (ImageConfigData->CSDVersion)) 690 { 691 /* Take the value from the image configuration directory */ 692 Peb->OSCSDVersion = ImageConfigData->CSDVersion; 693 } 694 } 695 696 /* Process optional process affinity mask override */ 697 if ((ImageConfigData) && (ImageConfigData->ProcessAffinityMask)) 698 { 699 /* Take the value from the image configuration directory */ 700 ProcessAffinityMask = ImageConfigData->ProcessAffinityMask; 701 } 702 703 // 704 // Check if this is a UP image 705 if (Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) 706 { 707 // 708 // Force it to use CPU 0 709 // 710 /* FIXME: this should use the MmRotatingUniprocessorNumber */ 711 Peb->ImageProcessAffinityMask = 0; 712 } 713 else 714 { 715 // 716 // Whatever was configured 717 // 718 Peb->ImageProcessAffinityMask = ProcessAffinityMask; 719 } 720 } 721 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 722 { 723 // 724 // Fail 725 // 726 KeDetachProcess(); 727 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT); 728 } 729 _SEH2_END; 730 } 731 732 // 733 // Detach from the Process 734 // 735 KeDetachProcess(); 736 *BasePeb = Peb; 737 return STATUS_SUCCESS; 738 } 739 740 NTSTATUS 741 NTAPI 742 MmCreateTeb(IN PEPROCESS Process, 743 IN PCLIENT_ID ClientId, 744 IN PINITIAL_TEB InitialTeb, 745 OUT PTEB *BaseTeb) 746 { 747 PTEB Teb; 748 NTSTATUS Status = STATUS_SUCCESS; 749 *BaseTeb = NULL; 750 751 // 752 // Attach to Target 753 // 754 KeAttachProcess(&Process->Pcb); 755 756 // 757 // Allocate the TEB 758 // 759 Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb); 760 if (!NT_SUCCESS(Status)) 761 { 762 /* Cleanup and exit */ 763 KeDetachProcess(); 764 return Status; 765 } 766 767 // 768 // Use SEH in case we can't load the TEB 769 // 770 _SEH2_TRY 771 { 772 // 773 // Initialize the PEB 774 // 775 RtlZeroMemory(Teb, sizeof(TEB)); 776 777 // 778 // Set TIB Data 779 // 780 #ifdef _M_AMD64 781 Teb->NtTib.ExceptionList = NULL; 782 #else 783 Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END; 784 #endif 785 Teb->NtTib.Self = (PNT_TIB)Teb; 786 787 // 788 // Identify this as an OS/2 V3.0 ("Cruiser") TIB 789 // 790 Teb->NtTib.Version = 30 << 8; 791 792 // 793 // Set TEB Data 794 // 795 Teb->ClientId = *ClientId; 796 Teb->RealClientId = *ClientId; 797 Teb->ProcessEnvironmentBlock = Process->Peb; 798 Teb->CurrentLocale = PsDefaultThreadLocaleId; 799 800 // 801 // Check if we have a grandparent TEB 802 // 803 if ((InitialTeb->PreviousStackBase == NULL) && 804 (InitialTeb->PreviousStackLimit == NULL)) 805 { 806 // 807 // Use initial TEB values 808 // 809 Teb->NtTib.StackBase = InitialTeb->StackBase; 810 Teb->NtTib.StackLimit = InitialTeb->StackLimit; 811 Teb->DeallocationStack = InitialTeb->AllocatedStackBase; 812 } 813 else 814 { 815 // 816 // Use grandparent TEB values 817 // 818 Teb->NtTib.StackBase = InitialTeb->PreviousStackBase; 819 Teb->NtTib.StackLimit = InitialTeb->PreviousStackLimit; 820 } 821 822 // 823 // Initialize the static unicode string 824 // 825 Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer); 826 Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer; 827 } 828 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 829 { 830 // 831 // Get error code 832 // 833 Status = _SEH2_GetExceptionCode(); 834 } 835 _SEH2_END; 836 837 // 838 // Return 839 // 840 KeDetachProcess(); 841 *BaseTeb = Teb; 842 return Status; 843 } 844 845 VOID 846 NTAPI 847 MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess) 848 { 849 PMMPFN Pfn1; 850 PMMPTE sysPte; 851 MMPTE tempPte; 852 853 /* Setup some bogus list data */ 854 MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize; 855 MmWorkingSetList->HashTable = NULL; 856 MmWorkingSetList->HashTableSize = 0; 857 MmWorkingSetList->NumberOfImageWaiters = 0; 858 MmWorkingSetList->Wsle = (PVOID)(ULONG_PTR)0xDEADBABEDEADBABEULL; 859 MmWorkingSetList->VadBitMapHint = 1; 860 MmWorkingSetList->HashTableStart = (PVOID)(ULONG_PTR)0xBADAB00BBADAB00BULL; 861 MmWorkingSetList->HighestPermittedHashAddress = (PVOID)(ULONG_PTR)0xCAFEBABECAFEBABEULL; 862 MmWorkingSetList->FirstFree = 1; 863 MmWorkingSetList->FirstDynamic = 2; 864 MmWorkingSetList->NextSlot = 3; 865 MmWorkingSetList->LastInitializedWsle = 4; 866 867 /* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */ 868 Pfn1 = MiGetPfnEntry(CurrentProcess->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT); 869 ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1)); 870 Pfn1->u1.Event = (PKEVENT)CurrentProcess; 871 872 /* Map the process working set in kernel space */ 873 sysPte = MiReserveSystemPtes(1, SystemPteSpace); 874 MI_MAKE_HARDWARE_PTE_KERNEL(&tempPte, sysPte, MM_READWRITE, CurrentProcess->WorkingSetPage); 875 MI_WRITE_VALID_PTE(sysPte, tempPte); 876 CurrentProcess->Vm.VmWorkingSetList = MiPteToAddress(sysPte); 877 } 878 879 NTSTATUS 880 NTAPI 881 MmInitializeProcessAddressSpace(IN PEPROCESS Process, 882 IN PEPROCESS ProcessClone OPTIONAL, 883 IN PVOID Section OPTIONAL, 884 IN OUT PULONG Flags, 885 IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL) 886 { 887 NTSTATUS Status = STATUS_SUCCESS; 888 SIZE_T ViewSize = 0; 889 PVOID ImageBase = 0; 890 PROS_SECTION_OBJECT SectionObject = Section; 891 PMMPTE PointerPte; 892 KIRQL OldIrql; 893 PMMPDE PointerPde; 894 PFN_NUMBER PageFrameNumber; 895 UNICODE_STRING FileName; 896 PWCHAR Source; 897 PCHAR Destination; 898 USHORT Length = 0; 899 MMPTE TempPte; 900 901 /* We should have a PDE */ 902 ASSERT(Process->Pcb.DirectoryTableBase[0] != 0); 903 ASSERT(Process->PdeUpdateNeeded == FALSE); 904 905 /* Attach to the process */ 906 KeAttachProcess(&Process->Pcb); 907 908 /* The address space should now been in phase 1 or 0 */ 909 ASSERT(Process->AddressSpaceInitialized <= 1); 910 Process->AddressSpaceInitialized = 2; 911 912 /* Initialize the Addresss Space lock */ 913 KeInitializeGuardedMutex(&Process->AddressCreationLock); 914 Process->Vm.WorkingSetExpansionLinks.Flink = NULL; 915 916 /* Initialize AVL tree */ 917 ASSERT(Process->VadRoot.NumberGenericTableElements == 0); 918 Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot; 919 920 /* Lock PFN database */ 921 OldIrql = MiAcquirePfnLock(); 922 923 /* Setup the PFN for the PDE base of this process */ 924 #ifdef _M_AMD64 925 PointerPte = MiAddressToPte(PXE_BASE); 926 #else 927 PointerPte = MiAddressToPte(PDE_BASE); 928 #endif 929 PageFrameNumber = PFN_FROM_PTE(PointerPte); 930 ASSERT(Process->Pcb.DirectoryTableBase[0] == PageFrameNumber * PAGE_SIZE); 931 MiInitializePfn(PageFrameNumber, PointerPte, TRUE); 932 933 /* Do the same for hyperspace */ 934 #ifdef _M_AMD64 935 PointerPde = MiAddressToPxe((PVOID)HYPER_SPACE); 936 #else 937 PointerPde = MiAddressToPde(HYPER_SPACE); 938 #endif 939 PageFrameNumber = PFN_FROM_PTE(PointerPde); 940 //ASSERT(Process->Pcb.DirectoryTableBase[0] == PageFrameNumber * PAGE_SIZE); // we're not lucky 941 MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE); 942 943 /* Setup the PFN for the PTE for the working set */ 944 PointerPte = MiAddressToPte(MI_WORKING_SET_LIST); 945 MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0); 946 ASSERT(PointerPte->u.Long != 0); 947 PageFrameNumber = PFN_FROM_PTE(PointerPte); 948 MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPte); 949 MiInitializePfn(PageFrameNumber, PointerPte, TRUE); 950 TempPte.u.Hard.PageFrameNumber = PageFrameNumber; 951 MI_WRITE_VALID_PTE(PointerPte, TempPte); 952 953 /* Now initialize the working set list */ 954 MiInitializeWorkingSetList(Process); 955 956 /* Sanity check */ 957 ASSERT(Process->PhysicalVadRoot == NULL); 958 959 /* Release PFN lock */ 960 MiReleasePfnLock(OldIrql); 961 962 /* Check if there's a Section Object */ 963 if (SectionObject) 964 { 965 /* Determine the image file name and save it to EPROCESS */ 966 FileName = SectionObject->FileObject->FileName; 967 Source = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length); 968 if (FileName.Buffer) 969 { 970 /* Loop the file name*/ 971 while (Source > FileName.Buffer) 972 { 973 /* Make sure this isn't a backslash */ 974 if (*--Source == OBJ_NAME_PATH_SEPARATOR) 975 { 976 /* If so, stop it here */ 977 Source++; 978 break; 979 } 980 else 981 { 982 /* Otherwise, keep going */ 983 Length++; 984 } 985 } 986 } 987 988 /* Copy the to the process and truncate it to 15 characters if necessary */ 989 Destination = Process->ImageFileName; 990 Length = min(Length, sizeof(Process->ImageFileName) - 1); 991 while (Length--) *Destination++ = (UCHAR)*Source++; 992 *Destination = ANSI_NULL; 993 994 /* Check if caller wants an audit name */ 995 if (AuditName) 996 { 997 /* Setup the audit name */ 998 Status = SeInitializeProcessAuditName(SectionObject->FileObject, 999 FALSE, 1000 AuditName); 1001 if (!NT_SUCCESS(Status)) 1002 { 1003 /* Fail */ 1004 KeDetachProcess(); 1005 return Status; 1006 } 1007 } 1008 1009 /* Map the section */ 1010 Status = MmMapViewOfSection(Section, 1011 Process, 1012 (PVOID*)&ImageBase, 1013 0, 1014 0, 1015 NULL, 1016 &ViewSize, 1017 0, 1018 MEM_COMMIT, 1019 PAGE_READWRITE); 1020 1021 /* Save the pointer */ 1022 Process->SectionBaseAddress = ImageBase; 1023 } 1024 1025 /* Be nice and detach */ 1026 KeDetachProcess(); 1027 1028 /* Return status to caller */ 1029 return Status; 1030 } 1031 1032 NTSTATUS 1033 NTAPI 1034 INIT_FUNCTION 1035 MmInitializeHandBuiltProcess(IN PEPROCESS Process, 1036 IN PULONG_PTR DirectoryTableBase) 1037 { 1038 /* Share the directory base with the idle process */ 1039 DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]; 1040 DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1]; 1041 1042 /* Initialize the Addresss Space */ 1043 KeInitializeGuardedMutex(&Process->AddressCreationLock); 1044 KeInitializeSpinLock(&Process->HyperSpaceLock); 1045 Process->Vm.WorkingSetExpansionLinks.Flink = NULL; 1046 ASSERT(Process->VadRoot.NumberGenericTableElements == 0); 1047 Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot; 1048 1049 /* Use idle process Working set */ 1050 Process->Vm.VmWorkingSetList = PsGetCurrentProcess()->Vm.VmWorkingSetList; 1051 1052 /* Done */ 1053 Process->HasAddressSpace = TRUE;//?? 1054 return STATUS_SUCCESS; 1055 } 1056 1057 NTSTATUS 1058 NTAPI 1059 INIT_FUNCTION 1060 MmInitializeHandBuiltProcess2(IN PEPROCESS Process) 1061 { 1062 /* Lock the VAD, ARM3-owned ranges away */ 1063 return STATUS_SUCCESS; 1064 } 1065 1066 #ifdef _M_IX86 1067 /* FIXME: Evaluate ways to make this portable yet arch-specific */ 1068 BOOLEAN 1069 NTAPI 1070 MmCreateProcessAddressSpace(IN ULONG MinWs, 1071 IN PEPROCESS Process, 1072 OUT PULONG_PTR DirectoryTableBase) 1073 { 1074 KIRQL OldIrql; 1075 PFN_NUMBER PdeIndex, HyperIndex, WsListIndex; 1076 PMMPTE PointerPte; 1077 MMPTE TempPte, PdePte; 1078 ULONG PdeOffset; 1079 PMMPTE SystemTable, HyperTable; 1080 ULONG Color; 1081 PMMPFN Pfn1; 1082 1083 /* Choose a process color */ 1084 Process->NextPageColor = (USHORT)RtlRandom(&MmProcessColorSeed); 1085 1086 /* Setup the hyperspace lock */ 1087 KeInitializeSpinLock(&Process->HyperSpaceLock); 1088 1089 /* Lock PFN database */ 1090 OldIrql = MiAcquirePfnLock(); 1091 1092 /* Get a zero page for the PDE, if possible */ 1093 Color = MI_GET_NEXT_PROCESS_COLOR(Process); 1094 MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); 1095 PdeIndex = MiRemoveZeroPageSafe(Color); 1096 if (!PdeIndex) 1097 { 1098 /* No zero pages, grab a free one */ 1099 PdeIndex = MiRemoveAnyPage(Color); 1100 1101 /* Zero it outside the PFN lock */ 1102 MiReleasePfnLock(OldIrql); 1103 MiZeroPhysicalPage(PdeIndex); 1104 OldIrql = MiAcquirePfnLock(); 1105 } 1106 1107 /* Get a zero page for hyperspace, if possible */ 1108 MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); 1109 Color = MI_GET_NEXT_PROCESS_COLOR(Process); 1110 HyperIndex = MiRemoveZeroPageSafe(Color); 1111 if (!HyperIndex) 1112 { 1113 /* No zero pages, grab a free one */ 1114 HyperIndex = MiRemoveAnyPage(Color); 1115 1116 /* Zero it outside the PFN lock */ 1117 MiReleasePfnLock(OldIrql); 1118 MiZeroPhysicalPage(HyperIndex); 1119 OldIrql = MiAcquirePfnLock(); 1120 } 1121 1122 /* Get a zero page for the woring set list, if possible */ 1123 MI_SET_USAGE(MI_USAGE_PAGE_TABLE); 1124 Color = MI_GET_NEXT_PROCESS_COLOR(Process); 1125 WsListIndex = MiRemoveZeroPageSafe(Color); 1126 if (!WsListIndex) 1127 { 1128 /* No zero pages, grab a free one */ 1129 WsListIndex = MiRemoveAnyPage(Color); 1130 1131 /* Zero it outside the PFN lock */ 1132 MiReleasePfnLock(OldIrql); 1133 MiZeroPhysicalPage(WsListIndex); 1134 } 1135 else 1136 { 1137 /* Release the PFN lock */ 1138 MiReleasePfnLock(OldIrql); 1139 } 1140 1141 /* Switch to phase 1 initialization */ 1142 ASSERT(Process->AddressSpaceInitialized == 0); 1143 Process->AddressSpaceInitialized = 1; 1144 1145 /* Set the base directory pointers */ 1146 Process->WorkingSetPage = WsListIndex; 1147 DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT; 1148 DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT; 1149 1150 /* Make sure we don't already have a page directory setup */ 1151 ASSERT(Process->Pcb.DirectoryTableBase[0] == 0); 1152 1153 /* Get a PTE to map hyperspace */ 1154 PointerPte = MiReserveSystemPtes(1, SystemPteSpace); 1155 ASSERT(PointerPte != NULL); 1156 1157 /* Build it */ 1158 MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, 1159 PointerPte, 1160 MM_READWRITE, 1161 HyperIndex); 1162 1163 /* Set it dirty and map it */ 1164 MI_MAKE_DIRTY_PAGE(&PdePte); 1165 MI_WRITE_VALID_PTE(PointerPte, PdePte); 1166 1167 /* Now get hyperspace's page table */ 1168 HyperTable = MiPteToAddress(PointerPte); 1169 1170 /* Now write the PTE/PDE entry for the working set list index itself */ 1171 TempPte = ValidKernelPteLocal; 1172 TempPte.u.Hard.PageFrameNumber = WsListIndex; 1173 PdeOffset = MiAddressToPteOffset(MmWorkingSetList); 1174 HyperTable[PdeOffset] = TempPte; 1175 1176 /* Let go of the system PTE */ 1177 MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); 1178 1179 /* Save the PTE address of the page directory itself */ 1180 Pfn1 = MiGetPfnEntry(PdeIndex); 1181 Pfn1->PteAddress = (PMMPTE)PDE_BASE; 1182 1183 /* Insert us into the Mm process list */ 1184 OldIrql = MiAcquireExpansionLock(); 1185 InsertTailList(&MmProcessList, &Process->MmProcessLinks); 1186 MiReleaseExpansionLock(OldIrql); 1187 1188 /* Get a PTE to map the page directory */ 1189 PointerPte = MiReserveSystemPtes(1, SystemPteSpace); 1190 ASSERT(PointerPte != NULL); 1191 1192 /* Build it */ 1193 MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, 1194 PointerPte, 1195 MM_READWRITE, 1196 PdeIndex); 1197 1198 /* Set it dirty and map it */ 1199 MI_MAKE_DIRTY_PAGE(&PdePte); 1200 MI_WRITE_VALID_PTE(PointerPte, PdePte); 1201 1202 /* Now get the page directory (which we'll double map, so call it a page table */ 1203 SystemTable = MiPteToAddress(PointerPte); 1204 1205 /* Copy all the kernel mappings */ 1206 PdeOffset = MiGetPdeOffset(MmSystemRangeStart); 1207 RtlCopyMemory(&SystemTable[PdeOffset], 1208 MiAddressToPde(MmSystemRangeStart), 1209 PAGE_SIZE - PdeOffset * sizeof(MMPTE)); 1210 1211 /* Now write the PTE/PDE entry for hyperspace itself */ 1212 TempPte = ValidKernelPteLocal; 1213 TempPte.u.Hard.PageFrameNumber = HyperIndex; 1214 PdeOffset = MiGetPdeOffset(HYPER_SPACE); 1215 SystemTable[PdeOffset] = TempPte; 1216 1217 /* Sanity check */ 1218 PdeOffset++; 1219 ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset); 1220 1221 /* Now do the x86 trick of making the PDE a page table itself */ 1222 PdeOffset = MiGetPdeOffset(PTE_BASE); 1223 TempPte.u.Hard.PageFrameNumber = PdeIndex; 1224 SystemTable[PdeOffset] = TempPte; 1225 1226 /* Let go of the system PTE */ 1227 MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); 1228 1229 /* Add the process to the session */ 1230 MiSessionAddProcess(Process); 1231 return TRUE; 1232 } 1233 #endif 1234 1235 VOID 1236 NTAPI 1237 MmCleanProcessAddressSpace(IN PEPROCESS Process) 1238 { 1239 PMMVAD Vad; 1240 PMM_AVL_TABLE VadTree; 1241 PETHREAD Thread = PsGetCurrentThread(); 1242 1243 /* Only support this */ 1244 ASSERT(Process->AddressSpaceInitialized == 2); 1245 1246 /* Remove from the session */ 1247 MiSessionRemoveProcess(); 1248 1249 /* Lock the process address space from changes */ 1250 MmLockAddressSpace(&Process->Vm); 1251 MiLockProcessWorkingSetUnsafe(Process, Thread); 1252 1253 /* VM is deleted now */ 1254 Process->VmDeleted = TRUE; 1255 MiUnlockProcessWorkingSetUnsafe(Process, Thread); 1256 1257 /* Enumerate the VADs */ 1258 VadTree = &Process->VadRoot; 1259 while (VadTree->NumberGenericTableElements) 1260 { 1261 /* Grab the current VAD */ 1262 Vad = (PMMVAD)VadTree->BalancedRoot.RightChild; 1263 1264 /* Check for old-style memory areas */ 1265 if (Vad->u.VadFlags.Spare == 1) 1266 { 1267 /* Let RosMm handle this */ 1268 MiRosCleanupMemoryArea(Process, Vad); 1269 continue; 1270 } 1271 1272 /* Lock the working set */ 1273 MiLockProcessWorkingSetUnsafe(Process, Thread); 1274 1275 /* Remove this VAD from the tree */ 1276 ASSERT(VadTree->NumberGenericTableElements >= 1); 1277 MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree); 1278 1279 /* Only regular VADs supported for now */ 1280 ASSERT(Vad->u.VadFlags.VadType == VadNone); 1281 1282 /* Check if this is a section VAD */ 1283 if (!(Vad->u.VadFlags.PrivateMemory) && (Vad->ControlArea)) 1284 { 1285 /* Remove the view */ 1286 MiRemoveMappedView(Process, Vad); 1287 } 1288 else 1289 { 1290 /* Delete the addresses */ 1291 MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT, 1292 (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1), 1293 Vad); 1294 1295 /* Release the working set */ 1296 MiUnlockProcessWorkingSetUnsafe(Process, Thread); 1297 } 1298 1299 /* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */ 1300 if (Vad->u.VadFlags.Spare == 1) 1301 { 1302 /* Set a flag so MmDeleteMemoryArea knows to free, but not to remove */ 1303 Vad->u.VadFlags.Spare = 2; 1304 continue; 1305 } 1306 1307 /* Free the VAD memory */ 1308 ExFreePool(Vad); 1309 } 1310 1311 /* Lock the working set */ 1312 MiLockProcessWorkingSetUnsafe(Process, Thread); 1313 ASSERT(Process->CloneRoot == NULL); 1314 ASSERT(Process->PhysicalVadRoot == NULL); 1315 1316 /* Delete the shared user data section */ 1317 MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL); 1318 1319 /* Release the working set */ 1320 MiUnlockProcessWorkingSetUnsafe(Process, Thread); 1321 1322 /* Release the address space */ 1323 MmUnlockAddressSpace(&Process->Vm); 1324 } 1325 1326 VOID 1327 NTAPI 1328 MmDeleteProcessAddressSpace2(IN PEPROCESS Process) 1329 { 1330 PMMPFN Pfn1, Pfn2; 1331 KIRQL OldIrql; 1332 PFN_NUMBER PageFrameIndex; 1333 1334 //ASSERT(Process->CommitCharge == 0); 1335 1336 /* Acquire the PFN lock */ 1337 OldIrql = MiAcquirePfnLock(); 1338 1339 /* Check for fully initialized process */ 1340 if (Process->AddressSpaceInitialized == 2) 1341 { 1342 /* Map the working set page and its page table */ 1343 Pfn1 = MiGetPfnEntry(Process->WorkingSetPage); 1344 Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame); 1345 1346 /* Nuke it */ 1347 MI_SET_PFN_DELETED(Pfn1); 1348 MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame); 1349 MiDecrementShareCount(Pfn1, Process->WorkingSetPage); 1350 ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress)); 1351 MiReleaseSystemPtes(MiAddressToPte(Process->Vm.VmWorkingSetList), 1, SystemPteSpace); 1352 1353 /* Now map hyperspace and its page table */ 1354 PageFrameIndex = Process->Pcb.DirectoryTableBase[1] >> PAGE_SHIFT; 1355 Pfn1 = MiGetPfnEntry(PageFrameIndex); 1356 Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame); 1357 1358 /* Nuke it */ 1359 MI_SET_PFN_DELETED(Pfn1); 1360 MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame); 1361 MiDecrementShareCount(Pfn1, PageFrameIndex); 1362 ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress)); 1363 1364 /* Finally, nuke the PDE itself */ 1365 PageFrameIndex = Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT; 1366 Pfn1 = MiGetPfnEntry(PageFrameIndex); 1367 MI_SET_PFN_DELETED(Pfn1); 1368 MiDecrementShareCount(Pfn1, PageFrameIndex); 1369 MiDecrementShareCount(Pfn1, PageFrameIndex); 1370 1371 /* Page table is now dead. Bye bye... */ 1372 ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress)); 1373 } 1374 else 1375 { 1376 /* A partly-initialized process should never exit through here */ 1377 ASSERT(FALSE); 1378 } 1379 1380 /* Release the PFN lock */ 1381 MiReleasePfnLock(OldIrql); 1382 1383 /* Drop a reference on the session */ 1384 if (Process->Session) MiReleaseProcessReferenceToSessionDataPage(Process->Session); 1385 1386 /* Clear out the PDE pages */ 1387 Process->Pcb.DirectoryTableBase[0] = 0; 1388 Process->Pcb.DirectoryTableBase[1] = 0; 1389 } 1390 1391 1392 /* SYSTEM CALLS ***************************************************************/ 1393 1394 NTSTATUS 1395 NTAPI 1396 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle, 1397 IN OUT PULONG_PTR NumberOfPages, 1398 IN OUT PULONG_PTR UserPfnArray) 1399 { 1400 UNIMPLEMENTED; 1401 return STATUS_NOT_IMPLEMENTED; 1402 } 1403 1404 NTSTATUS 1405 NTAPI 1406 NtMapUserPhysicalPages(IN PVOID VirtualAddresses, 1407 IN ULONG_PTR NumberOfPages, 1408 IN OUT PULONG_PTR UserPfnArray) 1409 { 1410 UNIMPLEMENTED; 1411 return STATUS_NOT_IMPLEMENTED; 1412 } 1413 1414 NTSTATUS 1415 NTAPI 1416 NtMapUserPhysicalPagesScatter(IN PVOID *VirtualAddresses, 1417 IN ULONG_PTR NumberOfPages, 1418 IN OUT PULONG_PTR UserPfnArray) 1419 { 1420 UNIMPLEMENTED; 1421 return STATUS_NOT_IMPLEMENTED; 1422 } 1423 1424 NTSTATUS 1425 NTAPI 1426 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle, 1427 IN OUT PULONG_PTR NumberOfPages, 1428 IN OUT PULONG_PTR UserPfnArray) 1429 { 1430 UNIMPLEMENTED; 1431 return STATUS_NOT_IMPLEMENTED; 1432 } 1433 1434 /* EOF */ 1435