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 *****************************************************************/
*/
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 = RVA(AllocatedBase, -PAGE_SIZE);
} while (Status != STATUS_SUCCESS);
/* Initialize the Region */
- MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
+ MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
PAGE_SIZE,
MEM_COMMIT,
PAGE_READWRITE);
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;
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 */
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]);
}
KernelStack,
PAGE_READWRITE,
Page,
- MM_STACK_SIZE / PAGE_SIZE);
+ StackSize / PAGE_SIZE);
/* Check for success */
if (!NT_SUCCESS(Status))
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,
/* 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);
}
/* 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));
/* Store stack information from InitialTeb */
if(InitialTeb != NULL)
{
- /* fixed-size stack */
- if(InitialTeb->PreviousStackBase && InitialTeb->PreviousStackLimit)
- {
- Teb->Tib.StackBase = InitialTeb->PreviousStackBase;
- Teb->Tib.StackLimit = InitialTeb->PreviousStackLimit;
- Teb->DeallocationStack = InitialTeb->PreviousStackLimit;
- }
- /* expandable stack */
- else
- {
- Teb->Tib.StackBase = InitialTeb->StackBase;
- Teb->Tib.StackLimit = InitialTeb->StackLimit;
- Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
- }
+ Teb->Tib.StackBase = InitialTeb->StackBase;
+ Teb->Tib.StackLimit = InitialTeb->StackLimit;
+ Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
}
/* Return TEB Address */
PVOID BaseAddress;
PMEMORY_AREA MemoryArea;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
- ULONG ViewSize = 0;
+ SIZE_T ViewSize = 0;
PVOID ImageBase = 0;
BoundaryAddressMultiple.QuadPart = 0;
/* 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))
{
/* 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))
{
/* 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 map process Image\n");
- ObDereferenceObject(Section);
- goto exit;
+ return Status;
}
- ObDereferenceObject(Section);
/* Save the pointer */
Process->SectionBaseAddress = ImageBase;