mirror of
https://github.com/reactos/reactos.git
synced 2024-08-16 16:39:08 +00:00
345 lines
11 KiB
C
345 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/mm/procsup.c
|
|
* PURPOSE: Memory functions related to Processes
|
|
*
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
PVOID
|
|
NTAPI
|
|
MiCreatePebOrTeb(PEPROCESS Process,
|
|
PVOID BaseAddress)
|
|
{
|
|
NTSTATUS Status;
|
|
PMMSUPPORT ProcessAddressSpace = &Process->Vm;
|
|
PMEMORY_AREA MemoryArea;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
PVOID AllocatedBase = BaseAddress;
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
/* Acquire the Lock */
|
|
MmLockAddressSpace(ProcessAddressSpace);
|
|
|
|
/*
|
|
* Create a Peb or Teb.
|
|
* Loop until it works, decreasing by PAGE_SIZE each time. The logic here
|
|
* is that a PEB allocation should never fail since the address is free,
|
|
* while TEB allocation can fail, and we should simply try the address
|
|
* below. Is there a nicer way of doing this automagically? (ie: findning)
|
|
* a gap region? -- Alex
|
|
*/
|
|
do {
|
|
DPRINT("Trying to allocate: %x\n", AllocatedBase);
|
|
Status = MmCreateMemoryArea(ProcessAddressSpace,
|
|
MEMORY_AREA_PEB_OR_TEB,
|
|
&AllocatedBase,
|
|
PAGE_SIZE,
|
|
PAGE_READWRITE,
|
|
&MemoryArea,
|
|
TRUE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
|
|
} while (Status != STATUS_SUCCESS);
|
|
|
|
/* Initialize the Region */
|
|
MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
|
|
PAGE_SIZE,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
|
|
/* Reserve the pages */
|
|
MmReserveSwapPages(PAGE_SIZE);
|
|
|
|
/* Unlock Address Space */
|
|
DPRINT("Returning\n");
|
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
|
return RVA(AllocatedBase, PAGE_SIZE);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
MmDeleteTeb(PEPROCESS Process,
|
|
PTEB Teb)
|
|
{
|
|
PMMSUPPORT ProcessAddressSpace = &Process->Vm;
|
|
PMEMORY_AREA MemoryArea;
|
|
|
|
/* Lock the Address Space */
|
|
MmLockAddressSpace(ProcessAddressSpace);
|
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(ProcessAddressSpace, (PVOID)Teb);
|
|
if (MemoryArea)
|
|
{
|
|
/* Delete the Teb */
|
|
MmFreeVirtualMemory(Process, MemoryArea);
|
|
}
|
|
|
|
/* Unlock the Address Space */
|
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
|
{
|
|
PVOID BaseAddress;
|
|
PMEMORY_AREA MemoryArea;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
NTSTATUS Status;
|
|
PMMSUPPORT ProcessAddressSpace = &Process->Vm;
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
/* Create the shared data page */
|
|
BaseAddress = (PVOID)USER_SHARED_DATA;
|
|
Status = MmCreateMemoryArea(ProcessAddressSpace,
|
|
MEMORY_AREA_SHARED_DATA,
|
|
&BaseAddress,
|
|
PAGE_SIZE,
|
|
PAGE_EXECUTE_READ,
|
|
&MemoryArea,
|
|
FALSE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
MmInitializeProcessAddressSpace(IN PEPROCESS Process,
|
|
IN PEPROCESS ProcessClone OPTIONAL,
|
|
IN PVOID Section OPTIONAL,
|
|
IN OUT PULONG Flags,
|
|
IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
|
|
{
|
|
NTSTATUS Status;
|
|
PMMSUPPORT ProcessAddressSpace = &Process->Vm;
|
|
PVOID BaseAddress;
|
|
PMEMORY_AREA MemoryArea;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
SIZE_T ViewSize = 0;
|
|
PVOID ImageBase = 0;
|
|
PROS_SECTION_OBJECT SectionObject = Section;
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
/* Initialize the Addresss Space lock */
|
|
KeInitializeGuardedMutex(&Process->AddressCreationLock);
|
|
Process->Vm.WorkingSetExpansionLinks.Flink = NULL;
|
|
|
|
/* Initialize AVL tree */
|
|
ASSERT(Process->VadRoot.NumberGenericTableElements == 0);
|
|
Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot;
|
|
|
|
/* Acquire the Lock */
|
|
MmLockAddressSpace(ProcessAddressSpace);
|
|
|
|
/* Protect the highest 64KB of the process address space */
|
|
BaseAddress = (PVOID)MmUserProbeAddress;
|
|
Status = MmCreateMemoryArea(ProcessAddressSpace,
|
|
MEMORY_AREA_NO_ACCESS,
|
|
&BaseAddress,
|
|
0x10000,
|
|
PAGE_NOACCESS,
|
|
&MemoryArea,
|
|
FALSE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to protect last 64KB\n");
|
|
goto exit;
|
|
}
|
|
|
|
/* Protect the 60KB above the shared user page */
|
|
BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
|
|
Status = MmCreateMemoryArea(ProcessAddressSpace,
|
|
MEMORY_AREA_NO_ACCESS,
|
|
&BaseAddress,
|
|
0x10000 - PAGE_SIZE,
|
|
PAGE_NOACCESS,
|
|
&MemoryArea,
|
|
FALSE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to protect the memory above the shared user page\n");
|
|
goto exit;
|
|
}
|
|
|
|
/* Create the shared data page */
|
|
BaseAddress = (PVOID)USER_SHARED_DATA;
|
|
Status = MmCreateMemoryArea(ProcessAddressSpace,
|
|
MEMORY_AREA_SHARED_DATA,
|
|
&BaseAddress,
|
|
PAGE_SIZE,
|
|
PAGE_EXECUTE_READ,
|
|
&MemoryArea,
|
|
FALSE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create Shared User Data\n");
|
|
goto exit;
|
|
}
|
|
|
|
/* The process now has an address space */
|
|
Process->HasAddressSpace = TRUE;
|
|
|
|
/* Check if there's a Section Object */
|
|
if (SectionObject)
|
|
{
|
|
UNICODE_STRING FileName;
|
|
PWCHAR szSrc;
|
|
PCHAR szDest;
|
|
USHORT lnFName = 0;
|
|
|
|
/* Unlock the Address Space */
|
|
DPRINT("Unlocking\n");
|
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
|
|
|
DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
|
|
SectionObject, Process, &ImageBase);
|
|
Status = MmMapViewOfSection(Section,
|
|
(PEPROCESS)Process,
|
|
(PVOID*)&ImageBase,
|
|
0,
|
|
0,
|
|
NULL,
|
|
&ViewSize,
|
|
0,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to map process Image\n");
|
|
return Status;
|
|
}
|
|
|
|
/* Save the pointer */
|
|
Process->SectionBaseAddress = ImageBase;
|
|
|
|
/* Determine the image file name and save it to EPROCESS */
|
|
DPRINT("Getting Image name\n");
|
|
FileName = SectionObject->FileObject->FileName;
|
|
szSrc = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length);
|
|
if (FileName.Buffer)
|
|
{
|
|
/* Loop the file name*/
|
|
while (szSrc > FileName.Buffer)
|
|
{
|
|
/* Make sure this isn't a backslash */
|
|
if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
|
|
{
|
|
/* If so, stop it here */
|
|
szSrc++;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise, keep going */
|
|
lnFName++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Copy the to the process and truncate it to 15 characters if necessary */
|
|
szDest = Process->ImageFileName;
|
|
lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
|
|
while (lnFName--) *szDest++ = (UCHAR)*szSrc++;
|
|
*szDest = ANSI_NULL;
|
|
|
|
/* Check if caller wants an audit name */
|
|
if (AuditName)
|
|
{
|
|
/* Setup the audit name */
|
|
SeInitializeProcessAuditName(SectionObject->FileObject,
|
|
FALSE,
|
|
AuditName);
|
|
}
|
|
|
|
/* Return status to caller */
|
|
return Status;
|
|
}
|
|
|
|
exit:
|
|
/* Unlock the Address Space */
|
|
DPRINT("Unlocking\n");
|
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
|
|
|
/* Return status to caller */
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
|
{
|
|
/* FIXME: Add part of MmDeleteProcessAddressSpace here */
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
MmDeleteProcessAddressSpace(PEPROCESS Process)
|
|
{
|
|
PVOID Address;
|
|
PMEMORY_AREA MemoryArea;
|
|
|
|
DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
|
|
Process->ImageFileName);
|
|
|
|
MmLockAddressSpace(&Process->Vm);
|
|
|
|
while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL)
|
|
{
|
|
switch (MemoryArea->Type)
|
|
{
|
|
case MEMORY_AREA_SECTION_VIEW:
|
|
Address = (PVOID)MemoryArea->StartingAddress;
|
|
MmUnlockAddressSpace(&Process->Vm);
|
|
MmUnmapViewOfSection(Process, Address);
|
|
MmLockAddressSpace(&Process->Vm);
|
|
break;
|
|
|
|
case MEMORY_AREA_VIRTUAL_MEMORY:
|
|
case MEMORY_AREA_PEB_OR_TEB:
|
|
MmFreeVirtualMemory(Process, MemoryArea);
|
|
break;
|
|
|
|
case MEMORY_AREA_SHARED_DATA:
|
|
case MEMORY_AREA_NO_ACCESS:
|
|
MmFreeMemoryArea(&Process->Vm,
|
|
MemoryArea,
|
|
NULL,
|
|
NULL);
|
|
break;
|
|
|
|
case MEMORY_AREA_MDL_MAPPING:
|
|
KeBugCheck(PROCESS_HAS_LOCKED_PAGES);
|
|
break;
|
|
|
|
default:
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
}
|
|
}
|
|
|
|
Mmi386ReleaseMmInfo(Process);
|
|
|
|
MmUnlockAddressSpace(&Process->Vm);
|
|
|
|
DPRINT("Finished MmReleaseMmInfo()\n");
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|