-/*\r
- * COPYRIGHT: See COPYING in the top level directory\r
- * PROJECT: ReactOS kernel\r
- * FILE: ntoskrnl/mm/process.c\r
- * PURPOSE: Memory functions related to Processes\r
- *\r
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)\r
- */\r
-\r
-/* INCLUDES *****************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-extern ULONG NtMajorVersion;\r
-extern ULONG NtMinorVersion;\r
-extern ULONG NtOSCSDVersion;\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-PVOID\r
-STDCALL\r
-MiCreatePebOrTeb(PEPROCESS Process,\r
- PVOID BaseAddress)\r
-{\r
- NTSTATUS Status;\r
- PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;\r
- PMEMORY_AREA MemoryArea;\r
- PHYSICAL_ADDRESS BoundaryAddressMultiple;\r
- PVOID AllocatedBase = BaseAddress;\r
- BoundaryAddressMultiple.QuadPart = 0;\r
-\r
- /* Acquire the Lock */\r
- MmLockAddressSpace(ProcessAddressSpace);\r
-\r
- /*\r
- * Create a Peb or Teb.\r
- * Loop until it works, decreasing by PAGE_SIZE each time. The logic here\r
- * is that a PEB allocation should never fail since the address is free,\r
- * while TEB allocation can fail, and we should simply try the address\r
- * below. Is there a nicer way of doing this automagically? (ie: findning)\r
- * a gap region? -- Alex\r
- */\r
- do {\r
- DPRINT("Trying to allocate: %x\n", AllocatedBase);\r
- Status = MmCreateMemoryArea(Process,\r
- ProcessAddressSpace,\r
- MEMORY_AREA_PEB_OR_TEB,\r
- &AllocatedBase,\r
- PAGE_SIZE,\r
- PAGE_READWRITE,\r
- &MemoryArea,\r
- TRUE,\r
- FALSE,\r
- BoundaryAddressMultiple);\r
- AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);\r
- } while (Status != STATUS_SUCCESS);\r
-\r
- /* Initialize the Region */\r
- MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,\r
- PAGE_SIZE,\r
- MEM_COMMIT,\r
- PAGE_READWRITE);\r
-\r
- /* Reserve the pages */\r
- MmReserveSwapPages(PAGE_SIZE);\r
-\r
- /* Unlock Address Space */\r
- DPRINT("Returning\n");\r
- MmUnlockAddressSpace(ProcessAddressSpace);\r
- return RVA(AllocatedBase, PAGE_SIZE);\r
-}\r
-\r
-VOID\r
-MiFreeStackPage(PVOID Context,\r
- MEMORY_AREA* MemoryArea,\r
- PVOID Address,\r
- PFN_TYPE Page,\r
- SWAPENTRY SwapEntry,\r
- BOOLEAN Dirty)\r
-{\r
- ASSERT(SwapEntry == 0);\r
- if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);\r
-}\r
-\r
-VOID\r
-STDCALL\r
-MmDeleteKernelStack(PVOID Stack,\r
- BOOLEAN GuiStack)\r
-{\r
- /* Lock the Address Space */\r
- MmLockAddressSpace(MmGetKernelAddressSpace());\r
-\r
- /* Delete the Stack */\r
- MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),\r
- Stack,\r
- MiFreeStackPage,\r
- NULL);\r
-\r
- /* Unlock the Address Space */\r
- MmUnlockAddressSpace(MmGetKernelAddressSpace());\r
-}\r
-\r
-VOID\r
-MiFreePebPage(PVOID Context,\r
- MEMORY_AREA* MemoryArea,\r
- PVOID Address,\r
- PFN_TYPE Page,\r
- SWAPENTRY SwapEntry,\r
- BOOLEAN Dirty)\r
-{\r
- PEPROCESS Process = (PEPROCESS)Context;\r
-\r
- if (Page != 0)\r
- {\r
- SWAPENTRY SavedSwapEntry;\r
- SavedSwapEntry = MmGetSavedSwapEntryPage(Page);\r
- if (SavedSwapEntry != 0)\r
- {\r
- MmFreeSwapPage(SavedSwapEntry);\r
- MmSetSavedSwapEntryPage(Page, 0);\r
- }\r
- MmDeleteRmap(Page, Process, Address);\r
- MmReleasePageMemoryConsumer(MC_USER, Page);\r
- }\r
- else if (SwapEntry != 0)\r
- {\r
- MmFreeSwapPage(SwapEntry);\r
- }\r
-}\r
-\r
-VOID\r
-STDCALL\r
-MmDeleteTeb(PEPROCESS Process,\r
- PTEB Teb)\r
-{\r
- PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;\r
-\r
- /* Lock the Address Space */\r
- MmLockAddressSpace(ProcessAddressSpace);\r
-\r
- /* Delete the Stack */\r
- MmFreeMemoryAreaByPtr(ProcessAddressSpace,\r
- Teb,\r
- MiFreePebPage,\r
- Process);\r
-\r
- /* Unlock the Address Space */\r
- MmUnlockAddressSpace(ProcessAddressSpace);\r
-}\r
-\r
-PVOID\r
-STDCALL\r
-MmCreateKernelStack(BOOLEAN GuiStack)\r
-{\r
- PMEMORY_AREA StackArea;\r
- ULONG i;\r
- PHYSICAL_ADDRESS BoundaryAddressMultiple;\r
- PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];\r
- PVOID KernelStack = NULL;\r
- NTSTATUS Status;\r
-\r
- /* Initialize the Boundary Address */\r
- BoundaryAddressMultiple.QuadPart = 0;\r
-\r
- /* Lock the Kernel Address Space */\r
- MmLockAddressSpace(MmGetKernelAddressSpace());\r
-\r
- /* Create a MAREA for the Kernel Stack */\r
- Status = MmCreateMemoryArea(NULL,\r
- MmGetKernelAddressSpace(),\r
- MEMORY_AREA_KERNEL_STACK,\r
- &KernelStack,\r
- MM_STACK_SIZE,\r
- 0,\r
- &StackArea,\r
- FALSE,\r
- FALSE,\r
- BoundaryAddressMultiple);\r
-\r
- /* Unlock the Address Space */\r
- MmUnlockAddressSpace(MmGetKernelAddressSpace());\r
-\r
- /* Check for Success */\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Failed to create thread stack\n");\r
- KEBUGCHECK(0);\r
- }\r
-\r
- /* Mark the Stack in use */\r
- for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)\r
- {\r
- Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);\r
- }\r
-\r
- /* Create a Virtual Mapping for it */\r
- Status = MmCreateVirtualMapping(NULL,\r
- KernelStack,\r
- PAGE_READWRITE,\r
- Page,\r
- MM_STACK_SIZE / PAGE_SIZE);\r
-\r
- /* Check for success */\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");\r
- KEBUGCHECK(0);\r
- }\r
-\r
- return KernelStack;\r
-}\r
-\r
-NTSTATUS\r
-STDCALL\r
-MmCreatePeb(PEPROCESS Process)\r
-{\r
- PPEB Peb = NULL;\r
- LARGE_INTEGER SectionOffset;\r
- ULONG ViewSize = 0;\r
- PVOID TableBase = NULL;\r
- NTSTATUS Status;\r
- SectionOffset.QuadPart = (ULONGLONG)0;\r
-\r
- DPRINT("MmCreatePeb\n");\r
-\r
- /* Map NLS Tables */\r
- DPRINT("Mapping NLS\n");\r
- Status = MmMapViewOfSection(NlsSectionObject,\r
- Process,\r
- &TableBase,\r
- 0,\r
- 0,\r
- &SectionOffset,\r
- &ViewSize,\r
- ViewShare,\r
- MEM_TOP_DOWN,\r
- PAGE_READONLY);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);\r
- return(Status);\r
- }\r
- DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);\r
-\r
- /* Attach to Process */\r
- KeAttachProcess(&Process->Pcb);\r
-\r
- /* Allocate the PEB */\r
- Peb = MiCreatePebOrTeb(Process, (PVOID)PEB_BASE);\r
-\r
- /* Initialize the PEB */\r
- DPRINT("Allocated: %x\n", Peb);\r
- RtlZeroMemory(Peb, sizeof(PEB));\r
-\r
- /* Set up data */\r
- DPRINT("Setting up PEB\n");\r
- Peb->ImageBaseAddress = Process->SectionBaseAddress;\r
- Peb->OSMajorVersion = NtMajorVersion;\r
- Peb->OSMinorVersion = NtMinorVersion;\r
- Peb->OSBuildNumber = 2195;\r
- Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;\r
- Peb->OSCSDVersion = NtOSCSDVersion;\r
- Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;\r
- Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;\r
- Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;\r
- Peb->NumberOfProcessors = KeNumberProcessors;\r
- Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);\r
-\r
- Process->Peb = Peb;\r
- KeDetachProcess();\r
-\r
- DPRINT("MmCreatePeb: Peb created at %p\n", Peb);\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-PTEB\r
-STDCALL\r
-MmCreateTeb(PEPROCESS Process,\r
- PCLIENT_ID ClientId,\r
- PINITIAL_TEB InitialTeb)\r
-{\r
- PTEB Teb;\r
- BOOLEAN Attached = FALSE;\r
-\r
- /* Attach to the process */\r
- DPRINT("MmCreateTeb\n");\r
- if (Process != PsGetCurrentProcess())\r
- {\r
- /* Attach to Target */\r
- KeAttachProcess(&Process->Pcb);\r
- Attached = TRUE;\r
- }\r
-\r
- /* Allocate the TEB */\r
- Teb = MiCreatePebOrTeb(Process, (PVOID)TEB_BASE);\r
-\r
- /* Initialize the PEB */\r
- RtlZeroMemory(Teb, sizeof(TEB));\r
-\r
- /* Set TIB Data */\r
- Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;\r
- Teb->Tib.Version = 1;\r
- Teb->Tib.Self = (PNT_TIB)Teb;\r
-\r
- /* Set TEB Data */\r
- Teb->Cid = *ClientId;\r
- Teb->RealClientId = *ClientId;\r
- Teb->ProcessEnvironmentBlock = Process->Peb;\r
- Teb->CurrentLocale = PsDefaultThreadLocaleId;\r
-\r
- /* Store stack information from InitialTeb */\r
- if(InitialTeb != NULL)\r
- {\r
- Teb->Tib.StackBase = InitialTeb->StackBase;\r
- Teb->Tib.StackLimit = InitialTeb->StackLimit;\r
- Teb->DeallocationStack = InitialTeb->AllocatedStackBase;\r
- }\r
-\r
- /* Return TEB Address */\r
- DPRINT("Allocated: %x\n", Teb);\r
- if (Attached) KeDetachProcess();\r
- return Teb;\r
-}\r
-\r
-NTSTATUS\r
-STDCALL\r
-MmCreateProcessAddressSpace(IN PEPROCESS Process,\r
- IN PSECTION_OBJECT Section OPTIONAL)\r
-{\r
- NTSTATUS Status;\r
- PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;\r
- PVOID BaseAddress;\r
- PMEMORY_AREA MemoryArea;\r
- PHYSICAL_ADDRESS BoundaryAddressMultiple;\r
- ULONG ViewSize = 0;\r
- PVOID ImageBase = 0;\r
- BoundaryAddressMultiple.QuadPart = 0;\r
-\r
- /* Initialize the Addresss Space */\r
- MmInitializeAddressSpace(Process, ProcessAddressSpace);\r
-\r
- /* Acquire the Lock */\r
- MmLockAddressSpace(ProcessAddressSpace);\r
-\r
- /* Protect the highest 64KB of the process address space */\r
- BaseAddress = (PVOID)MmUserProbeAddress;\r
- Status = MmCreateMemoryArea(Process,\r
- ProcessAddressSpace,\r
- MEMORY_AREA_NO_ACCESS,\r
- &BaseAddress,\r
- 0x10000,\r
- PAGE_NOACCESS,\r
- &MemoryArea,\r
- FALSE,\r
- FALSE,\r
- BoundaryAddressMultiple);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Failed to protect last 64KB\n");\r
- goto exit;\r
- }\r
-\r
- /* Protect the 60KB above the shared user page */\r
- BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;\r
- Status = MmCreateMemoryArea(Process,\r
- ProcessAddressSpace,\r
- MEMORY_AREA_NO_ACCESS,\r
- &BaseAddress,\r
- 0x10000 - PAGE_SIZE,\r
- PAGE_NOACCESS,\r
- &MemoryArea,\r
- FALSE,\r
- FALSE,\r
- BoundaryAddressMultiple);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Failed to protect the memory above the shared user page\n");\r
- goto exit;\r
- }\r
-\r
- /* Create the shared data page */\r
- BaseAddress = (PVOID)USER_SHARED_DATA;\r
- Status = MmCreateMemoryArea(Process,\r
- ProcessAddressSpace,\r
- MEMORY_AREA_SHARED_DATA,\r
- &BaseAddress,\r
- PAGE_SIZE,\r
- PAGE_READONLY,\r
- &MemoryArea,\r
- FALSE,\r
- FALSE,\r
- BoundaryAddressMultiple);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Failed to create Shared User Data\n");\r
- goto exit;\r
- }\r
-\r
- /* Check if there's a Section Object */\r
- if (Section)\r
- {\r
- UNICODE_STRING FileName;\r
- PWCHAR szSrc;\r
- PCHAR szDest;\r
- USHORT lnFName = 0;\r
-\r
- /* Unlock the Address Space */\r
- DPRINT("Unlocking\n");\r
- MmUnlockAddressSpace(ProcessAddressSpace);\r
-\r
- DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",\r
- Section, Process, &ImageBase);\r
- Status = MmMapViewOfSection(Section,\r
- Process,\r
- (PVOID*)&ImageBase,\r
- 0,\r
- 0,\r
- NULL,\r
- &ViewSize,\r
- 0,\r
- MEM_COMMIT,\r
- PAGE_READWRITE);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- DPRINT1("Failed to map process Image\n");\r
- ObDereferenceObject(Section);\r
- goto exit;\r
- }\r
- ObDereferenceObject(Section);\r
-\r
- /* Save the pointer */\r
- Process->SectionBaseAddress = ImageBase;\r
-\r
- /* Determine the image file name and save it to EPROCESS */\r
- DPRINT("Getting Image name\n");\r
- FileName = Section->FileObject->FileName;\r
- szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);\r
-\r
- while(szSrc >= FileName.Buffer)\r
- {\r
- if(*szSrc == L'\\')\r
- {\r
- szSrc++;\r
- break;\r
- }\r
- else\r
- {\r
- szSrc--;\r
- lnFName++;\r
- }\r
- }\r
-\r
- /* Copy the to the process and truncate it to 15 characters if necessary */\r
- DPRINT("Copying and truncating\n");\r
- szDest = Process->ImageFileName;\r
- lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);\r
- while(lnFName-- > 0) *(szDest++) = (UCHAR)*(szSrc++);\r
-\r
- /* Return status to caller */\r
- return Status;\r
- }\r
-\r
-exit:\r
- /* Unlock the Address Space */\r
- DPRINT("Unlocking\n");\r
- MmUnlockAddressSpace(ProcessAddressSpace);\r
-\r
- /* Return status to caller */\r
- return Status;\r
-}\r
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/mm/process.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 NtOSCSDVersion;
+extern ULONG NtGlobalFlag;
+
+#define MM_HIGHEST_VAD_ADDRESS \
+ (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+STDCALL
+MiCreatePebOrTeb(PROS_EPROCESS Process,
+ PVOID BaseAddress)
+{
+ NTSTATUS Status;
+ PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
+ 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(PROS_EPROCESS Process,
+ PTEB Teb)
+{
+ PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
+ 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)
+{
+ 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 */
+ 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 */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+STDCALL
+MmCreatePeb(PROS_EPROCESS 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(NlsSectionObject,
+ (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 = (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->OSCSDVersion = NtOSCSDVersion;
+
+ /* 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);
+ return STATUS_SUCCESS;
+}
+
+PTEB
+STDCALL
+MmCreateTeb(PROS_EPROCESS Process,
+ PCLIENT_ID ClientId,
+ PINITIAL_TEB InitialTeb)
+{
+ PTEB Teb;
+ BOOLEAN Attached = FALSE;
+
+ /* Attach to the process */
+ DPRINT("MmCreateTeb\n");
+ if (Process != (PROS_EPROCESS)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;
+ }
+
+ /* Return TEB Address */
+ DPRINT("Allocated: %x\n", Teb);
+ if (Attached) KeDetachProcess();
+ return Teb;
+}
+
+NTSTATUS
+STDCALL
+MmCreateProcessAddressSpace(IN PROS_EPROCESS Process,
+ IN PROS_SECTION_OBJECT Section OPTIONAL)
+{
+ NTSTATUS Status;
+ PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
+ PVOID BaseAddress;
+ PMEMORY_AREA MemoryArea;
+ PHYSICAL_ADDRESS BoundaryAddressMultiple;
+ SIZE_T ViewSize = 0;
+ PVOID ImageBase = 0;
+ BoundaryAddressMultiple.QuadPart = 0;
+
+ /* Initialize the Addresss Space */
+ MmInitializeAddressSpace(Process, ProcessAddressSpace);
+
+ /* 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;
+ }
+
+ /* Check if there's a Section Object */
+ 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,
+ (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 = Section->FileObject->FileName;
+ szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
+
+ while(szSrc >= FileName.Buffer)
+ {
+ if(*szSrc == L'\\')
+ {
+ szSrc++;
+ break;
+ }
+ else
+ {
+ szSrc--;
+ lnFName++;
+ }
+ }
+
+ /* Copy the to the process and truncate it to 15 characters if necessary */
+ DPRINT("Copying and truncating\n");
+ 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;
+}