2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/process.c
5 * PURPOSE: Memory functions related to Processes
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 extern ULONG NtMajorVersion
;
17 extern ULONG NtMinorVersion
;
18 extern ULONG NtOSCSDVersion
;
20 /* FUNCTIONS *****************************************************************/
24 MiCreatePebOrTeb(PEPROCESS Process
,
28 PMADDRESS_SPACE ProcessAddressSpace
= &Process
->AddressSpace
;
29 PMEMORY_AREA MemoryArea
;
30 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
31 PVOID AllocatedBase
= BaseAddress
;
32 BoundaryAddressMultiple
.QuadPart
= 0;
34 /* Acquire the Lock */
35 MmLockAddressSpace(ProcessAddressSpace
);
38 * Create a Peb or Teb.
39 * Loop until it works, decreasing by PAGE_SIZE each time. The logic here
40 * is that a PEB allocation should never fail since the address is free,
41 * while TEB allocation can fail, and we should simply try the address
42 * below. Is there a nicer way of doing this automagically? (ie: findning)
43 * a gap region? -- Alex
46 DPRINT("Trying to allocate: %x\n", AllocatedBase
);
47 Status
= MmCreateMemoryArea(Process
,
49 MEMORY_AREA_PEB_OR_TEB
,
56 BoundaryAddressMultiple
);
57 AllocatedBase
= RVA(AllocatedBase
, -PAGE_SIZE
);
58 } while (Status
!= STATUS_SUCCESS
);
60 /* Initialize the Region */
61 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
66 /* Reserve the pages */
67 MmReserveSwapPages(PAGE_SIZE
);
69 /* Unlock Address Space */
70 DPRINT("Returning\n");
71 MmUnlockAddressSpace(ProcessAddressSpace
);
72 return RVA(AllocatedBase
, PAGE_SIZE
);
76 MiFreeStackPage(PVOID Context
,
77 MEMORY_AREA
* MemoryArea
,
83 ASSERT(SwapEntry
== 0);
84 if (Page
) MmReleasePageMemoryConsumer(MC_NPPOOL
, Page
);
89 MmDeleteKernelStack(PVOID Stack
,
92 /* Lock the Address Space */
93 MmLockAddressSpace(MmGetKernelAddressSpace());
95 /* Delete the Stack */
96 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
101 /* Unlock the Address Space */
102 MmUnlockAddressSpace(MmGetKernelAddressSpace());
106 MiFreePebPage(PVOID Context
,
107 MEMORY_AREA
* MemoryArea
,
113 PEPROCESS Process
= (PEPROCESS
)Context
;
117 SWAPENTRY SavedSwapEntry
;
118 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
119 if (SavedSwapEntry
!= 0)
121 MmFreeSwapPage(SavedSwapEntry
);
122 MmSetSavedSwapEntryPage(Page
, 0);
124 MmDeleteRmap(Page
, Process
, Address
);
125 MmReleasePageMemoryConsumer(MC_USER
, Page
);
127 else if (SwapEntry
!= 0)
129 MmFreeSwapPage(SwapEntry
);
135 MmDeleteTeb(PEPROCESS Process
,
138 PMADDRESS_SPACE ProcessAddressSpace
= &Process
->AddressSpace
;
140 /* Lock the Address Space */
141 MmLockAddressSpace(ProcessAddressSpace
);
143 /* Delete the Stack */
144 MmFreeMemoryAreaByPtr(ProcessAddressSpace
,
149 /* Unlock the Address Space */
150 MmUnlockAddressSpace(ProcessAddressSpace
);
155 MmCreateKernelStack(BOOLEAN GuiStack
)
157 PMEMORY_AREA StackArea
;
159 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
160 PFN_TYPE Page
[MM_STACK_SIZE
/ PAGE_SIZE
];
161 PVOID KernelStack
= NULL
;
164 /* Initialize the Boundary Address */
165 BoundaryAddressMultiple
.QuadPart
= 0;
167 /* Lock the Kernel Address Space */
168 MmLockAddressSpace(MmGetKernelAddressSpace());
170 /* Create a MAREA for the Kernel Stack */
171 Status
= MmCreateMemoryArea(NULL
,
172 MmGetKernelAddressSpace(),
173 MEMORY_AREA_KERNEL_STACK
,
180 BoundaryAddressMultiple
);
182 /* Unlock the Address Space */
183 MmUnlockAddressSpace(MmGetKernelAddressSpace());
185 /* Check for Success */
186 if (!NT_SUCCESS(Status
))
188 DPRINT1("Failed to create thread stack\n");
192 /* Mark the Stack in use */
193 for (i
= 0; i
< (MM_STACK_SIZE
/ PAGE_SIZE
); i
++)
195 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Page
[i
]);
198 /* Create a Virtual Mapping for it */
199 Status
= MmCreateVirtualMapping(NULL
,
203 MM_STACK_SIZE
/ PAGE_SIZE
);
205 /* Check for success */
206 if (!NT_SUCCESS(Status
))
208 DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
217 MmCreatePeb(PEPROCESS Process
)
220 LARGE_INTEGER SectionOffset
;
222 PVOID TableBase
= NULL
;
224 SectionOffset
.QuadPart
= (ULONGLONG
)0;
226 DPRINT("MmCreatePeb\n");
229 DPRINT("Mapping NLS\n");
230 Status
= MmMapViewOfSection(NlsSectionObject
,
240 if (!NT_SUCCESS(Status
))
242 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
245 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
247 /* Attach to Process */
248 KeAttachProcess(&Process
->Pcb
);
250 /* Allocate the PEB */
251 Peb
= MiCreatePebOrTeb(Process
, (PVOID
)PEB_BASE
);
253 /* Initialize the PEB */
254 DPRINT("Allocated: %x\n", Peb
);
255 RtlZeroMemory(Peb
, sizeof(PEB
));
258 DPRINT("Setting up PEB\n");
259 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
260 Peb
->OSMajorVersion
= NtMajorVersion
;
261 Peb
->OSMinorVersion
= NtMinorVersion
;
262 Peb
->OSBuildNumber
= 2195;
263 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
264 Peb
->OSCSDVersion
= NtOSCSDVersion
;
265 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
266 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
267 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
268 Peb
->NumberOfProcessors
= KeNumberProcessors
;
269 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
274 DPRINT("MmCreatePeb: Peb created at %p\n", Peb
);
275 return STATUS_SUCCESS
;
280 MmCreateTeb(PEPROCESS Process
,
282 PINITIAL_TEB InitialTeb
)
285 BOOLEAN Attached
= FALSE
;
287 /* Attach to the process */
288 DPRINT("MmCreateTeb\n");
289 if (Process
!= PsGetCurrentProcess())
291 /* Attach to Target */
292 KeAttachProcess(&Process
->Pcb
);
296 /* Allocate the TEB */
297 Teb
= MiCreatePebOrTeb(Process
, (PVOID
)TEB_BASE
);
299 /* Initialize the PEB */
300 RtlZeroMemory(Teb
, sizeof(TEB
));
303 Teb
->Tib
.ExceptionList
= (PVOID
)0xFFFFFFFF;
304 Teb
->Tib
.Version
= 1;
305 Teb
->Tib
.Self
= (PNT_TIB
)Teb
;
308 Teb
->Cid
= *ClientId
;
309 Teb
->RealClientId
= *ClientId
;
310 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
311 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
313 /* Store stack information from InitialTeb */
314 if(InitialTeb
!= NULL
)
316 Teb
->Tib
.StackBase
= InitialTeb
->StackBase
;
317 Teb
->Tib
.StackLimit
= InitialTeb
->StackLimit
;
318 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
321 /* Return TEB Address */
322 DPRINT("Allocated: %x\n", Teb
);
323 if (Attached
) KeDetachProcess();
329 MmCreateProcessAddressSpace(IN PEPROCESS Process
,
330 IN PSECTION_OBJECT Section OPTIONAL
)
333 PMADDRESS_SPACE ProcessAddressSpace
= &Process
->AddressSpace
;
335 PMEMORY_AREA MemoryArea
;
336 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
339 BoundaryAddressMultiple
.QuadPart
= 0;
341 /* Initialize the Addresss Space */
342 MmInitializeAddressSpace(Process
, ProcessAddressSpace
);
344 /* Acquire the Lock */
345 MmLockAddressSpace(ProcessAddressSpace
);
347 /* Protect the highest 64KB of the process address space */
348 BaseAddress
= (PVOID
)MmUserProbeAddress
;
349 Status
= MmCreateMemoryArea(Process
,
351 MEMORY_AREA_NO_ACCESS
,
358 BoundaryAddressMultiple
);
359 if (!NT_SUCCESS(Status
))
361 DPRINT1("Failed to protect last 64KB\n");
365 /* Protect the 60KB above the shared user page */
366 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
367 Status
= MmCreateMemoryArea(Process
,
369 MEMORY_AREA_NO_ACCESS
,
376 BoundaryAddressMultiple
);
377 if (!NT_SUCCESS(Status
))
379 DPRINT1("Failed to protect the memory above the shared user page\n");
383 /* Create the shared data page */
384 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
385 Status
= MmCreateMemoryArea(Process
,
387 MEMORY_AREA_SHARED_DATA
,
394 BoundaryAddressMultiple
);
395 if (!NT_SUCCESS(Status
))
397 DPRINT1("Failed to create Shared User Data\n");
401 /* Check if there's a Section Object */
404 UNICODE_STRING FileName
;
409 /* Unlock the Address Space */
410 DPRINT("Unlocking\n");
411 MmUnlockAddressSpace(ProcessAddressSpace
);
413 DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
414 Section
, Process
, &ImageBase
);
415 Status
= MmMapViewOfSection(Section
,
425 if (!NT_SUCCESS(Status
))
427 DPRINT1("Failed to map process Image\n");
428 ObDereferenceObject(Section
);
431 ObDereferenceObject(Section
);
433 /* Save the pointer */
434 Process
->SectionBaseAddress
= ImageBase
;
436 /* Determine the image file name and save it to EPROCESS */
437 DPRINT("Getting Image name\n");
438 FileName
= Section
->FileObject
->FileName
;
439 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
441 while(szSrc
>= FileName
.Buffer
)
455 /* Copy the to the process and truncate it to 15 characters if necessary */
456 DPRINT("Copying and truncating\n");
457 szDest
= Process
->ImageFileName
;
458 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
459 while(lnFName
-- > 0) *(szDest
++) = (UCHAR
)*(szSrc
++);
461 /* Return status to caller */
466 /* Unlock the Address Space */
467 DPRINT("Unlocking\n");
468 MmUnlockAddressSpace(ProcessAddressSpace
);
470 /* Return status to caller */