-/*
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/process.c
extern ULONG NtMajorVersion;
extern ULONG NtMinorVersion;
extern ULONG NtOSCSDVersion;
+extern ULONG NtGlobalFlag;
+
+#define MM_HIGHEST_VAD_ADDRESS \
+ (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
/* FUNCTIONS *****************************************************************/
-
+
PVOID
STDCALL
MiCreatePebOrTeb(PEPROCESS Process,
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
PMEMORY_AREA MemoryArea;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
- BoundaryAddressMultiple.QuadPart = 0;
PVOID AllocatedBase = BaseAddress;
-
+ BoundaryAddressMultiple.QuadPart = 0;
+
/* Acquire the Lock */
MmLockAddressSpace(ProcessAddressSpace);
- /*
- * Create a Peb or Teb.
+ /*
+ * 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
*/
do {
DPRINT("Trying to allocate: %x\n", AllocatedBase);
- Status = MmCreateMemoryArea(Process,
- ProcessAddressSpace,
+ Status = MmCreateMemoryArea(ProcessAddressSpace,
MEMORY_AREA_PEB_OR_TEB,
&AllocatedBase,
PAGE_SIZE,
PAGE_READWRITE,
&MemoryArea,
TRUE,
- FALSE,
+ 0,
BoundaryAddressMultiple);
- AllocatedBase = AllocatedBase - PAGE_SIZE;
+ AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
} while (Status != STATUS_SUCCESS);
-
+
/* Initialize the Region */
- MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
- PAGE_SIZE,
- MEM_COMMIT,
+ 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 AllocatedBase + PAGE_SIZE;
+ return RVA(AllocatedBase, PAGE_SIZE);
}
VOID
-MiFreeStackPage(PVOID Context,
- MEMORY_AREA* MemoryArea,
- PVOID Address,
- PFN_TYPE Page,
- SWAPENTRY SwapEntry,
+MiFreeStackPage(PVOID Context,
+ MEMORY_AREA* MemoryArea,
+ PVOID Address,
+ PFN_TYPE Page,
+ SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
ASSERT(SwapEntry == 0);
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
-MiFreePebPage(PVOID Context,
- MEMORY_AREA* MemoryArea,
- PVOID Address,
- PFN_TYPE Page,
- SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
-{
- PEPROCESS Process = (PEPROCESS)Context;
-
- if (Page != 0)
- {
- SWAPENTRY SavedSwapEntry;
- SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
- if (SavedSwapEntry != 0)
- {
- MmFreeSwapPage(SavedSwapEntry);
- MmSetSavedSwapEntryPage(Page, 0);
- }
- MmDeleteRmap(Page, Process, Address);
- MmReleasePageMemoryConsumer(MC_USER, Page);
- }
- else if (SwapEntry != 0)
- {
- MmFreeSwapPage(SwapEntry);
- }
-}
-
VOID
STDCALL
MmDeleteTeb(PEPROCESS Process,
PTEB Teb)
-{
+{
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
-
+ PMEMORY_AREA MemoryArea;
+
/* Lock the Address Space */
MmLockAddressSpace(ProcessAddressSpace);
- /* Delete the Stack */
- MmFreeMemoryAreaByPtr(ProcessAddressSpace,
- Teb,
- MiFreePebPage,
- Process);
-
+ MemoryArea = MmLocateMemoryAreaByAddress(ProcessAddressSpace, (PVOID)Teb);
+ if (MemoryArea)
+ {
+ /* Delete the Teb */
+ MmFreeVirtualMemory(Process, MemoryArea);
+ }
+
/* Unlock the Address Space */
MmUnlockAddressSpace(ProcessAddressSpace);
}
PMEMORY_AREA StackArea;
ULONG i;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
- PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
+ 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(NULL,
- MmGetKernelAddressSpace(),
+ Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_KERNEL_STACK,
&KernelStack,
- MM_STACK_SIZE,
- 0,
+ StackSize,
+ PAGE_READWRITE,
&StackArea,
FALSE,
- FALSE,
+ 0,
BoundaryAddressMultiple);
-
+
/* Unlock the Address Space */
MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
+
/* Check for Success */
- if (!NT_SUCCESS(Status))
- {
+ if (!NT_SUCCESS(Status))
+ {
DPRINT1("Failed to create thread stack\n");
KEBUGCHECK(0);
}
-
- /* Mark the Stack in use */
- for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
+
+ /*
+ * 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,
- MM_STACK_SIZE / PAGE_SIZE);
-
+ StackSize / PAGE_SIZE);
+
/* Check for success */
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
KEBUGCHECK(0);
}
-
+
+ /* Return the stack */
return KernelStack;
}
+/*
+ * @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 */
+ DPRINT1("Thread, Thread Limit, Stack %p %p %p\n", KeGetCurrentThread(),
+ KeGetCurrentThread()->StackLimit,
+ StackPointer);
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
STDCALL
MmCreatePeb(PEPROCESS Process)
-{
+{
PPEB Peb = NULL;
LARGE_INTEGER SectionOffset;
- ULONG ViewSize = 0;
+ 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(NlsSectionObject,
ViewShare,
MEM_TOP_DOWN,
PAGE_READONLY);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
return(Status);
/* Attach to Process */
KeAttachProcess(&Process->Pcb);
-
- /* Allocate the PEB */
- Peb = MiCreatePebOrTeb(Process, (PVOID)PEB_BASE);
-
+
/* 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 = (char*)TableBase + NlsAnsiTableOffset;
+ Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
+ Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
+
+ /* Default Version Data (could get changed below) */
Peb->OSMajorVersion = NtMajorVersion;
Peb->OSMinorVersion = NtMinorVersion;
Peb->OSBuildNumber = 2195;
- Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
+ Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
Peb->OSCSDVersion = NtOSCSDVersion;
- Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
- Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
- Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
+
+ /* 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)))
+ {
+ /* Get the Image Config Data too */
+ ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
+ &ViewSize);
+
+ /* 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;
+
+ /* Lie about the version if requested */
+ if (ImageConfigData && ImageConfigData->CSDVersion)
+ {
+ Peb->OSCSDVersion = ImageConfigData->CSDVersion;
+ }
+
+ /* Set the Platform ID */
+ Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
+ }
+ /* Check for affinity override */
+ if (ImageConfigData && ImageConfigData->ProcessAffinityMask)
+ {
+ ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* Misc data */
+ Peb->SessionId = Process->Session;
Process->Peb = Peb;
+
+ /* Detach from the Process */
KeDetachProcess();
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
{
PTEB Teb;
BOOLEAN Attached = FALSE;
-
+
/* Attach to the process */
DPRINT("MmCreateTeb\n");
if (Process != PsGetCurrentProcess())
KeAttachProcess(&Process->Pcb);
Attached = TRUE;
}
-
+
/* Allocate the TEB */
- Teb = MiCreatePebOrTeb(Process, (PVOID)TEB_BASE);
-
+ 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->Peb = Process->Peb;
+ Teb->ProcessEnvironmentBlock = Process->Peb;
Teb->CurrentLocale = PsDefaultThreadLocaleId;
-
+
/* Store stack information from InitialTeb */
if(InitialTeb != NULL)
{
- /* fixed-size stack */
- if(InitialTeb->StackBase && InitialTeb->StackLimit)
- {
- Teb->Tib.StackBase = InitialTeb->StackBase;
- Teb->Tib.StackLimit = InitialTeb->StackLimit;
- Teb->DeallocationStack = InitialTeb->StackLimit;
- }
- /* expandable stack */
- else
- {
- Teb->Tib.StackBase = InitialTeb->StackCommit;
- Teb->Tib.StackLimit = InitialTeb->StackCommitMax;
- Teb->DeallocationStack = InitialTeb->StackReserved;
- }
+ Teb->Tib.StackBase = InitialTeb->StackBase;
+ Teb->Tib.StackLimit = InitialTeb->StackLimit;
+ Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
}
-
+
/* Return TEB Address */
DPRINT("Allocated: %x\n", Teb);
if (Attached) KeDetachProcess();
PVOID BaseAddress;
PMEMORY_AREA MemoryArea;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
- BoundaryAddressMultiple.QuadPart = 0;
- ULONG ViewSize = 0;
+ SIZE_T ViewSize = 0;
PVOID ImageBase = 0;
-
+ BoundaryAddressMultiple.QuadPart = 0;
+
/* Initialize the Addresss Space */
- MmInitializeAddressSpace(Process, ProcessAddressSpace);
-
+ MmInitializeAddressSpace(Process, ProcessAddressSpace);
+
/* Acquire the Lock */
MmLockAddressSpace(ProcessAddressSpace);
/* Protect the highest 64KB of the process address space */
BaseAddress = (PVOID)MmUserProbeAddress;
- Status = MmCreateMemoryArea(Process,
- ProcessAddressSpace,
+ Status = MmCreateMemoryArea(ProcessAddressSpace,
MEMORY_AREA_NO_ACCESS,
&BaseAddress,
0x10000,
PAGE_NOACCESS,
&MemoryArea,
FALSE,
- FALSE,
+ 0,
BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
+ 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(Process,
- ProcessAddressSpace,
+ Status = MmCreateMemoryArea(ProcessAddressSpace,
MEMORY_AREA_NO_ACCESS,
&BaseAddress,
0x10000 - PAGE_SIZE,
PAGE_NOACCESS,
&MemoryArea,
FALSE,
- FALSE,
+ 0,
BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
+ 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(Process,
- ProcessAddressSpace,
+ Status = MmCreateMemoryArea(ProcessAddressSpace,
MEMORY_AREA_SHARED_DATA,
&BaseAddress,
PAGE_SIZE,
- PAGE_READONLY,
+ PAGE_EXECUTE_READ,
&MemoryArea,
FALSE,
- FALSE,
+ 0,
BoundaryAddressMultiple);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create Shared User Data\n");
goto exit;
}
-
+
/* Check if there's a Section Object */
- if (Section)
+ if (Section)
{
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",
Section, Process, &ImageBase);
Status = MmMapViewOfSection(Section,
0,
MEM_COMMIT,
PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to map process Image\n");
- ObDereferenceObject(Section);
- goto exit;
+ return Status;
}
- ObDereferenceObject(Section);
-
+
/* Save the pointer */
Process->SectionBaseAddress = ImageBase;
-
+
/* Determine the image file name and save it to EPROCESS */
DPRINT("Getting Image name\n");
FileName = Section->FileObject->FileName;
szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
- while(szSrc >= FileName.Buffer)
+ while(szSrc >= FileName.Buffer)
{
- if(*szSrc == L'\\')
+ if(*szSrc == L'\\')
{
szSrc++;
break;
- }
- else
+ }
+ else
{
szSrc--;
lnFName++;
szDest = Process->ImageFileName;
lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
while(lnFName-- > 0) *(szDest++) = (UCHAR)*(szSrc++);
-
+
/* Return status to caller */
return Status;
}
-
+
exit:
/* Unlock the Address Space */
DPRINT("Unlocking\n");
MmUnlockAddressSpace(ProcessAddressSpace);
-
+
/* Return status to caller */
return Status;
}