mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 08:08:38 +00:00
c501d8112c
svn path=/branches/aicom-network-fixes/; revision=34994
727 lines
22 KiB
C
727 lines
22 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 <internal/debug.h>
|
|
|
|
extern ULONG NtMajorVersion;
|
|
extern ULONG NtMinorVersion;
|
|
extern ULONG CmNtCSDVersion;
|
|
extern ULONG NtBuildNumber;
|
|
extern MM_SYSTEMSIZE MmSystemSize;
|
|
|
|
#define MM_HIGHEST_VAD_ADDRESS \
|
|
(PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
MmSetMemoryPriorityProcess(IN PEPROCESS Process,
|
|
IN UCHAR MemoryPriority)
|
|
{
|
|
UCHAR OldPriority;
|
|
|
|
/* Check if we have less then 16MB of Physical Memory */
|
|
if ((MmSystemSize == MmSmallSystem) &&
|
|
(MmStats.NrTotalPages < ((15 * 1024 * 1024) / PAGE_SIZE)))
|
|
{
|
|
/* Always use background priority */
|
|
MemoryPriority = 0;
|
|
}
|
|
|
|
/* Save the old priority and update it */
|
|
OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority;
|
|
Process->Vm.Flags.MemoryPriority = MemoryPriority;
|
|
|
|
/* Return the old priority */
|
|
return OldPriority;
|
|
}
|
|
|
|
LCID
|
|
NTAPI
|
|
MmGetSessionLocaleId(VOID)
|
|
{
|
|
PEPROCESS Process;
|
|
PAGED_CODE();
|
|
|
|
/* Get the current process */
|
|
Process = PsGetCurrentProcess();
|
|
|
|
/* Check if it's the Session Leader */
|
|
if (Process->Vm.Flags.SessionLeader)
|
|
{
|
|
/* Make sure it has a valid Session */
|
|
if (Process->Session)
|
|
{
|
|
/* Get the Locale ID */
|
|
#if ROS_HAS_SESSIONS
|
|
return ((PMM_SESSION_SPACE)Process->Session)->LocaleId;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* Not a session leader, return the default */
|
|
return PsDefaultThreadLocaleId;
|
|
}
|
|
|
|
PVOID
|
|
STDCALL
|
|
MiCreatePebOrTeb(PEPROCESS Process,
|
|
PVOID BaseAddress)
|
|
{
|
|
NTSTATUS Status;
|
|
PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
|
|
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
|
|
MiFreeStackPage(PVOID Context,
|
|
MEMORY_AREA* MemoryArea,
|
|
PVOID Address,
|
|
PFN_TYPE Page,
|
|
SWAPENTRY SwapEntry,
|
|
BOOLEAN Dirty)
|
|
{
|
|
ASSERT(SwapEntry == 0);
|
|
if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
|
}
|
|
|
|
VOID
|
|
STDCALL
|
|
MmDeleteKernelStack(PVOID Stack,
|
|
BOOLEAN GuiStack)
|
|
{
|
|
/* Lock the Address Space */
|
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
|
|
|
/* Delete the Stack */
|
|
MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
|
|
Stack,
|
|
MiFreeStackPage,
|
|
NULL);
|
|
|
|
/* Unlock the Address Space */
|
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
|
}
|
|
|
|
VOID
|
|
STDCALL
|
|
MmDeleteTeb(PEPROCESS Process,
|
|
PTEB Teb)
|
|
{
|
|
PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
|
|
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);
|
|
}
|
|
|
|
PVOID
|
|
STDCALL
|
|
MmCreateKernelStack(BOOLEAN GuiStack,
|
|
UCHAR Node)
|
|
{
|
|
PMEMORY_AREA StackArea;
|
|
ULONG i;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
ULONG StackSize = GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE;
|
|
PFN_TYPE Page[KERNEL_LARGE_STACK_SIZE / PAGE_SIZE];
|
|
PVOID KernelStack = NULL;
|
|
NTSTATUS Status;
|
|
|
|
/* Initialize the Boundary Address */
|
|
BoundaryAddressMultiple.QuadPart = 0;
|
|
|
|
/* Lock the Kernel Address Space */
|
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
|
|
|
/* Create a MAREA for the Kernel Stack */
|
|
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
|
|
MEMORY_AREA_KERNEL_STACK,
|
|
&KernelStack,
|
|
StackSize,
|
|
PAGE_READWRITE,
|
|
&StackArea,
|
|
FALSE,
|
|
0,
|
|
BoundaryAddressMultiple);
|
|
|
|
/* Unlock the Address Space */
|
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
|
|
|
/* Check for Success */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create thread stack\n");
|
|
KEBUGCHECK(0);
|
|
}
|
|
|
|
/*
|
|
* Mark the Stack in use.
|
|
* Note: Currently we mark all 60KB in use for a GUI Thread.
|
|
* We should only do this inside MmGrowKernelStack. TODO!
|
|
*/
|
|
for (i = 0; i < (StackSize / PAGE_SIZE); i++)
|
|
{
|
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
|
|
}
|
|
|
|
/* Create a Virtual Mapping for it */
|
|
Status = MmCreateVirtualMapping(NULL,
|
|
KernelStack,
|
|
PAGE_READWRITE,
|
|
Page,
|
|
StackSize / PAGE_SIZE);
|
|
|
|
/* Check for success */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
|
|
KEBUGCHECK(0);
|
|
}
|
|
|
|
/* Return the stack base */
|
|
return (PVOID)((ULONG_PTR)KernelStack +
|
|
(GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE));
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS
|
|
STDCALL
|
|
MmGrowKernelStack(PVOID StackPointer)
|
|
{
|
|
PETHREAD Thread = PsGetCurrentThread();
|
|
|
|
/* Make sure we have reserved space for our grow */
|
|
ASSERT(((PCHAR)Thread->Tcb.StackBase - (PCHAR)Thread->Tcb.StackLimit) <=
|
|
(KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
|
|
|
|
/*
|
|
* We'll give you three more pages.
|
|
* NOTE: See note in MmCreateKernelStack. These pages are already being reserved.
|
|
* It would be more efficient to only grow them (commit them) here.
|
|
*/
|
|
Thread->Tcb.StackLimit -= KERNEL_STACK_SIZE;
|
|
|
|
/* Return success */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
STDCALL
|
|
MmCreatePeb(PEPROCESS Process)
|
|
{
|
|
PPEB Peb = NULL;
|
|
LARGE_INTEGER SectionOffset;
|
|
SIZE_T ViewSize = 0;
|
|
PVOID TableBase = NULL;
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
|
|
NTSTATUS Status;
|
|
KAFFINITY ProcessAffinityMask = 0;
|
|
SectionOffset.QuadPart = (ULONGLONG)0;
|
|
DPRINT("MmCreatePeb\n");
|
|
|
|
/* Allocate the PEB */
|
|
Peb = MiCreatePebOrTeb(Process,
|
|
(PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
|
|
ASSERT(Peb == (PVOID)0x7FFDF000);
|
|
|
|
/* Map NLS Tables */
|
|
DPRINT("Mapping NLS\n");
|
|
Status = MmMapViewOfSection(ExpNlsSectionPointer,
|
|
(PEPROCESS)Process,
|
|
&TableBase,
|
|
0,
|
|
0,
|
|
&SectionOffset,
|
|
&ViewSize,
|
|
ViewShare,
|
|
MEM_TOP_DOWN,
|
|
PAGE_READONLY);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
|
|
return(Status);
|
|
}
|
|
DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
|
|
|
|
/* Attach to Process */
|
|
KeAttachProcess(&Process->Pcb);
|
|
|
|
/* Initialize the PEB */
|
|
DPRINT("Allocated: %x\n", Peb);
|
|
RtlZeroMemory(Peb, sizeof(PEB));
|
|
|
|
/* Set up data */
|
|
DPRINT("Setting up PEB\n");
|
|
Peb->ImageBaseAddress = Process->SectionBaseAddress;
|
|
Peb->InheritedAddressSpace = 0;
|
|
Peb->Mutant = NULL;
|
|
|
|
/* NLS */
|
|
Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
|
|
Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
|
|
Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
|
|
|
|
/* Default Version Data (could get changed below) */
|
|
Peb->OSMajorVersion = NtMajorVersion;
|
|
Peb->OSMinorVersion = NtMinorVersion;
|
|
Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
|
|
Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
|
|
Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
|
|
|
|
/* Heap and Debug Data */
|
|
Peb->NumberOfProcessors = KeNumberProcessors;
|
|
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
|
|
Peb->NtGlobalFlag = NtGlobalFlag;
|
|
/*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
|
|
Peb->HeapSegmentCommit = MmHeapSegmentCommit;
|
|
Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
|
|
Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;*/
|
|
Peb->NumberOfHeaps = 0;
|
|
Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
|
|
Peb->ProcessHeaps = (PVOID*)Peb + 1;
|
|
|
|
/* Image Data */
|
|
if ((NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress)))
|
|
{
|
|
/* Write subsystem data */
|
|
Peb->ImageSubSystem = NtHeaders->OptionalHeader.Subsystem;
|
|
Peb->ImageSubSystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
|
|
Peb->ImageSubSystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
|
|
|
|
/* Write Version Data */
|
|
if (NtHeaders->OptionalHeader.Win32VersionValue)
|
|
{
|
|
Peb->OSMajorVersion = NtHeaders->OptionalHeader.Win32VersionValue & 0xFF;
|
|
Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF;
|
|
Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
|
|
|
|
/* Set the Platform ID */
|
|
Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
|
|
}
|
|
|
|
/* Check if the image is not safe for SMP */
|
|
if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
|
|
{
|
|
/* FIXME: Choose one randomly */
|
|
Peb->ImageProcessAffinityMask = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Use affinity from Image Header */
|
|
Peb->ImageProcessAffinityMask = ProcessAffinityMask;
|
|
}
|
|
|
|
_SEH_TRY
|
|
{
|
|
/* Get the Image Config Data too */
|
|
ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
|
|
&ViewSize);
|
|
|
|
ProbeForRead(ImageConfigData,
|
|
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
|
|
sizeof(ULONG));
|
|
|
|
/* Process the image config data overrides if specfied. */
|
|
if (ImageConfigData != NULL)
|
|
{
|
|
if (ImageConfigData->CSDVersion)
|
|
{
|
|
Peb->OSCSDVersion = ImageConfigData->CSDVersion;
|
|
}
|
|
if (ImageConfigData->ProcessAffinityMask)
|
|
{
|
|
ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
|
|
}
|
|
}
|
|
}
|
|
_SEH_HANDLE
|
|
{
|
|
Status = _SEH_GetExceptionCode();
|
|
}
|
|
_SEH_END;
|
|
}
|
|
|
|
/* Misc data */
|
|
Peb->SessionId = Process->Session;
|
|
Process->Peb = Peb;
|
|
|
|
/* Detach from the Process */
|
|
KeDetachProcess();
|
|
|
|
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
|
|
return Status;
|
|
}
|
|
|
|
PTEB
|
|
STDCALL
|
|
MmCreateTeb(PEPROCESS Process,
|
|
PCLIENT_ID ClientId,
|
|
PINITIAL_TEB InitialTeb)
|
|
{
|
|
PTEB Teb;
|
|
BOOLEAN Attached = FALSE;
|
|
|
|
/* Attach to the process */
|
|
DPRINT("MmCreateTeb\n");
|
|
if (Process != PsGetCurrentProcess())
|
|
{
|
|
/* Attach to Target */
|
|
KeAttachProcess(&Process->Pcb);
|
|
Attached = TRUE;
|
|
}
|
|
|
|
/* Allocate the TEB */
|
|
Teb = MiCreatePebOrTeb(Process,
|
|
(PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
|
|
|
|
/* Initialize the PEB */
|
|
RtlZeroMemory(Teb, sizeof(TEB));
|
|
|
|
/* Set TIB Data */
|
|
Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
|
|
Teb->Tib.Version = 1;
|
|
Teb->Tib.Self = (PNT_TIB)Teb;
|
|
|
|
/* Set TEB Data */
|
|
Teb->Cid = *ClientId;
|
|
Teb->RealClientId = *ClientId;
|
|
Teb->ProcessEnvironmentBlock = Process->Peb;
|
|
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
|
|
|
/* Store stack information from InitialTeb */
|
|
if(InitialTeb != NULL)
|
|
{
|
|
Teb->Tib.StackBase = InitialTeb->StackBase;
|
|
Teb->Tib.StackLimit = InitialTeb->StackLimit;
|
|
Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
|
|
}
|
|
|
|
/* Initialize the static unicode string */
|
|
Teb->StaticUnicodeString.Length = 0;
|
|
Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
|
|
Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
|
|
|
|
/* Return TEB Address */
|
|
DPRINT("Allocated: %x\n", Teb);
|
|
if (Attached) KeDetachProcess();
|
|
return Teb;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
|
{
|
|
PVOID BaseAddress;
|
|
PMEMORY_AREA MemoryArea;
|
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
|
NTSTATUS Status;
|
|
PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
|
|
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;
|
|
PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
|
|
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->VadRoot.BalancedRoot.u1.Parent = NULL;
|
|
|
|
/* 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->VadRoot);
|
|
|
|
while ((MemoryArea = (PMEMORY_AREA)Process->VadRoot.BalancedRoot.u1.Parent) != NULL)
|
|
{
|
|
switch (MemoryArea->Type)
|
|
{
|
|
case MEMORY_AREA_SECTION_VIEW:
|
|
Address = (PVOID)MemoryArea->StartingAddress;
|
|
MmUnlockAddressSpace(&Process->VadRoot);
|
|
MmUnmapViewOfSection(Process, Address);
|
|
MmLockAddressSpace(&Process->VadRoot);
|
|
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->VadRoot,
|
|
MemoryArea,
|
|
NULL,
|
|
NULL);
|
|
break;
|
|
|
|
case MEMORY_AREA_MDL_MAPPING:
|
|
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
|
|
break;
|
|
|
|
default:
|
|
KEBUGCHECK(0);
|
|
}
|
|
}
|
|
|
|
Mmi386ReleaseMmInfo(Process);
|
|
|
|
MmUnlockAddressSpace(&Process->VadRoot);
|
|
|
|
DPRINT("Finished MmReleaseMmInfo()\n");
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|