reactos/ntoskrnl/mm/procsup.c
Timo Kreuzer 9ea495ba33 Create a branch for header work.
svn path=/branches/header-work/; revision=45691
2010-02-26 22:57:55 +00:00

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);
}