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