mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes: - CreateProcess * Cleanup creation of the initial thread using new utility functions and remove rosrtl * Almost entirely rewrote the function to support features such as: - SxS (locally only, patch will follow), - SFP (SAFER) (locally only, patch will follow), - DllPaths (locally only, patch will follow), - Proper process environment/paramter block creation - Proper console handle management (needs more work in kernel32/csr), - Tokens/CreateProcessAsUser (locally only, patch will follow), - Simpler code for path lookup, and more robust. - Support for "auto-correction" (see Raymond Chen's blog) - 16-bit/NE detection - A variety of creation flags are now properly supported - Added support for an undocumented-yet-known (see comment) shell flag - Alert for flags we don't support yet - Catch invalid flag combinations and other caller errors - Improve and correct path searcing to use documented behaviours - Created a multitude of helper functions to make the code easier to read and allow them to be used for other apis as time goes on. - BaseProcessStartup * Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address. * Correct prototype of Thread Startup function for this case. This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(. svn path=/trunk/; revision=16730
This commit is contained in:
parent
286cccb1de
commit
1e8c8e3fe6
4 changed files with 2083 additions and 2079 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,32 +1,32 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/i386/thread.S
|
||||
* PURPOSE: Thread Start Thunks
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
.globl _BaseThreadStartupThunk@0
|
||||
.globl _BaseProcessStartThunk@0
|
||||
.intel_syntax noprefix
|
||||
|
||||
_BaseThreadStartupThunk@0:
|
||||
|
||||
/* Start out fresh */
|
||||
xor ebp, ebp
|
||||
|
||||
push ebx /* lpParameter */
|
||||
push eax /* lpStartAddress */
|
||||
push 0 /* Return EIP */
|
||||
//jmp _BaseThreadStartup@8
|
||||
|
||||
_BaseProcessStartThunk@0:
|
||||
|
||||
/* Start out fresh */
|
||||
xor ebp, ebp
|
||||
|
||||
push eax /* lpStartAddress */
|
||||
push 0 /* Return EIP */
|
||||
//jmp _BaseProcessStartup@4
|
||||
|
||||
/* EOF */
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/i386/thread.S
|
||||
* PURPOSE: Thread Start Thunks
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
.globl _BaseThreadStartupThunk@0
|
||||
.globl _BaseProcessStartThunk@0
|
||||
.intel_syntax noprefix
|
||||
|
||||
_BaseThreadStartupThunk@0:
|
||||
|
||||
/* Start out fresh */
|
||||
xor ebp, ebp
|
||||
|
||||
push ebx /* lpParameter */
|
||||
push eax /* lpStartAddress */
|
||||
push 0 /* Return EIP */
|
||||
jmp _BaseThreadStartup@8
|
||||
|
||||
_BaseProcessStartThunk@0:
|
||||
|
||||
/* Start out fresh */
|
||||
xor ebp, ebp
|
||||
|
||||
push eax /* lpStartAddress */
|
||||
push 0 /* Return EIP */
|
||||
jmp _BaseProcessStartup@4
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/thread.c
|
||||
* PURPOSE: Thread functions
|
||||
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
||||
* Tls functions are modified from WINE
|
||||
* UPDATE HISTORY:
|
||||
* Created 01/11/98
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
* Ariadne ( ariadne@xs4all.nl)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -15,13 +12,9 @@
|
|||
|
||||
#include <k32.h>
|
||||
|
||||
/* FIXME */
|
||||
#include <rosrtl/thread.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include "../include/debug.h"
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
_SEH_FILTER(BaseThreadExceptionFilter)
|
||||
{
|
||||
|
@ -68,199 +61,196 @@ BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
|||
ExitThread(uExitCode);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId)
|
||||
{
|
||||
/* Act as if we're going to create a remote thread in ourselves */
|
||||
return CreateRemoteThread(NtCurrentProcess(),
|
||||
lpThreadAttributes,
|
||||
dwStackSize,
|
||||
lpStartAddress,
|
||||
lpParameter,
|
||||
dwCreationFlags,
|
||||
lpThreadId);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE STDCALL
|
||||
CreateThread
|
||||
(
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId
|
||||
)
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateRemoteThread(HANDLE hProcess,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId)
|
||||
{
|
||||
return CreateRemoteThread
|
||||
(
|
||||
NtCurrentProcess(),
|
||||
lpThreadAttributes,
|
||||
dwStackSize,
|
||||
lpStartAddress,
|
||||
lpParameter,
|
||||
dwCreationFlags,
|
||||
lpThreadId
|
||||
);
|
||||
}
|
||||
NTSTATUS Status;
|
||||
INITIAL_TEB InitialTeb;
|
||||
CONTEXT Context;
|
||||
CLIENT_ID ClientId;
|
||||
OBJECT_ATTRIBUTES LocalObjectAttributes;
|
||||
POBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hThread;
|
||||
ULONG Dummy;
|
||||
|
||||
DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
|
||||
": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess,
|
||||
dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
|
||||
|
||||
/* Clear the Context */
|
||||
RtlZeroMemory(&Context, sizeof(CONTEXT));
|
||||
|
||||
/* Write PID */
|
||||
ClientId.UniqueProcess = hProcess;
|
||||
|
||||
/* Create the Stack */
|
||||
Status = BasepCreateStack(hProcess,
|
||||
dwStackSize,
|
||||
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
|
||||
dwStackSize : 0,
|
||||
&InitialTeb);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastErrorByStatus(Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create Initial Context */
|
||||
BasepInitializeContext(&Context,
|
||||
lpParameter,
|
||||
lpStartAddress,
|
||||
InitialTeb.StackBase,
|
||||
1);
|
||||
|
||||
/* initialize the attributes for the thread object */
|
||||
ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
|
||||
lpThreadAttributes,
|
||||
NULL);
|
||||
|
||||
/* Create the Kernel Thread Object */
|
||||
Status = NtCreateThread(&hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
ObjectAttributes,
|
||||
hProcess,
|
||||
&ClientId,
|
||||
&Context,
|
||||
&InitialTeb,
|
||||
TRUE);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BasepFreeStack(hProcess, &InitialTeb);
|
||||
SetLastErrorByStatus(Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SXS_SUPPORT_ENABLED
|
||||
/* Are we in the same process? */
|
||||
if (Process = NtCurrentProcess())
|
||||
{
|
||||
PTEB Teb;
|
||||
PVOID ActivationContextStack;
|
||||
PTHREAD_BASIC_INFORMATION ThreadBasicInfo;
|
||||
PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
|
||||
ULONG_PTR Cookie;
|
||||
|
||||
/* Get the TEB */
|
||||
Status = NtQueryInformationThread(hThread,
|
||||
ThreadBasicIformation,
|
||||
&ThreadBasicInfo,
|
||||
sizeof(ThreadBasicInfo),
|
||||
NULL);
|
||||
|
||||
/* Allocate the Activation Context Stack */
|
||||
Status = RtlAllocateActivationContextStack(&ActivationContextStack);
|
||||
Teb = ThreadBasicInfo.TebBaseAddress;
|
||||
|
||||
/* Save it */
|
||||
Teb->ActivationContextStackPointer = ActivationContextStack;
|
||||
|
||||
/* Query the Context */
|
||||
Status = RtlQueryInformationActivationContext(1,
|
||||
0,
|
||||
NULL,
|
||||
ActivationContextBasicInformation,
|
||||
&ActivationCtxInfo,
|
||||
sizeof(ActivationCtxInfo),
|
||||
NULL);
|
||||
|
||||
/* Does it need to be activated? */
|
||||
if (!ActivationCtxInfo.hActCtx)
|
||||
{
|
||||
/* Activate it */
|
||||
Status = RtlActivateActivationContextEx(1,
|
||||
Teb,
|
||||
ActivationCtxInfo.hActCtx,
|
||||
&Cookie);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: Notify CSR */
|
||||
|
||||
/* Success */
|
||||
if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;
|
||||
|
||||
/* Resume it if asked */
|
||||
if (!(dwCreationFlags & CREATE_SUSPENDED))
|
||||
{
|
||||
NtResumeThread(hThread, &Dummy);
|
||||
}
|
||||
|
||||
/* Return handle to thread */
|
||||
return hThread;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HANDLE STDCALL
|
||||
CreateRemoteThread
|
||||
(
|
||||
HANDLE hProcess,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
DWORD dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId
|
||||
)
|
||||
VOID
|
||||
STDCALL
|
||||
ExitThread(DWORD uExitCode)
|
||||
{
|
||||
HANDLE hThread;
|
||||
CLIENT_ID cidClientId;
|
||||
NTSTATUS nErrCode;
|
||||
ULONG_PTR nStackReserve;
|
||||
ULONG_PTR nStackCommit;
|
||||
OBJECT_ATTRIBUTES oaThreadAttribs;
|
||||
PIMAGE_NT_HEADERS pinhHeader =
|
||||
RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||
NTSTATUS Status;
|
||||
BOOLEAN LastThread;
|
||||
|
||||
/*
|
||||
* Terminate process if this is the last thread
|
||||
* of the current process
|
||||
*/
|
||||
Status = NtQueryInformationThread(NtCurrentThread(),
|
||||
ThreadAmILastThread,
|
||||
&LastThread,
|
||||
sizeof(BOOLEAN),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status) && LastThread)
|
||||
{
|
||||
/* Exit the Process */
|
||||
ExitProcess(uExitCode);
|
||||
}
|
||||
|
||||
DPRINT
|
||||
(
|
||||
"hProcess %08X\n"
|
||||
"lpThreadAttributes %08X\n"
|
||||
"dwStackSize %08X\n"
|
||||
"lpStartAddress %08X\n"
|
||||
"lpParameter %08X\n"
|
||||
"dwCreationFlags %08X\n"
|
||||
"lpThreadId %08X\n",
|
||||
hProcess,
|
||||
lpThreadAttributes,
|
||||
dwStackSize,
|
||||
lpStartAddress,
|
||||
lpParameter,
|
||||
dwCreationFlags,
|
||||
lpThreadId
|
||||
);
|
||||
|
||||
/* FIXME: do more checks - e.g. the image may not have an optional header */
|
||||
if(pinhHeader == NULL)
|
||||
{
|
||||
nStackReserve = 0x100000;
|
||||
nStackCommit = PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nStackReserve = pinhHeader->OptionalHeader.SizeOfStackReserve;
|
||||
nStackCommit = pinhHeader->OptionalHeader.SizeOfStackCommit;
|
||||
}
|
||||
|
||||
/* FIXME: this should be defined in winbase.h */
|
||||
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
|
||||
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
|
||||
#endif
|
||||
|
||||
/* use defaults */
|
||||
if(dwStackSize == 0);
|
||||
/* dwStackSize specifies the size to reserve */
|
||||
else if(dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION)
|
||||
nStackReserve = dwStackSize;
|
||||
/* dwStackSize specifies the size to commit */
|
||||
else
|
||||
nStackCommit = dwStackSize;
|
||||
|
||||
/* fix the stack reserve size */
|
||||
if(nStackCommit > nStackReserve)
|
||||
nStackReserve = ROUNDUP(nStackCommit, 0x100000);
|
||||
|
||||
/* initialize the attributes for the thread object */
|
||||
InitializeObjectAttributes
|
||||
(
|
||||
&oaThreadAttribs,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if(lpThreadAttributes)
|
||||
{
|
||||
/* make the handle inheritable */
|
||||
if(lpThreadAttributes->bInheritHandle)
|
||||
oaThreadAttribs.Attributes |= OBJ_INHERIT;
|
||||
|
||||
/* user-defined security descriptor */
|
||||
oaThreadAttribs.SecurityDescriptor = lpThreadAttributes->lpSecurityDescriptor;
|
||||
}
|
||||
|
||||
DPRINT
|
||||
(
|
||||
"RtlRosCreateUserThreadVa\n"
|
||||
"(\n"
|
||||
" ProcessHandle %p,\n"
|
||||
" ObjectAttributes %p,\n"
|
||||
" CreateSuspended %d,\n"
|
||||
" StackZeroBits %d,\n"
|
||||
" StackReserve %lu,\n"
|
||||
" StackCommit %lu,\n"
|
||||
" StartAddress %p,\n"
|
||||
" ThreadHandle %p,\n"
|
||||
" ClientId %p,\n"
|
||||
" ParameterCount %u,\n"
|
||||
" Parameters[0] %p,\n"
|
||||
" Parameters[1] %p\n"
|
||||
")\n",
|
||||
hProcess,
|
||||
&oaThreadAttribs,
|
||||
dwCreationFlags & CREATE_SUSPENDED,
|
||||
0,
|
||||
nStackReserve,
|
||||
nStackCommit,
|
||||
BaseThreadStartup,
|
||||
&hThread,
|
||||
&cidClientId,
|
||||
2,
|
||||
lpStartAddress,
|
||||
lpParameter
|
||||
);
|
||||
|
||||
/* create the thread */
|
||||
nErrCode = RtlRosCreateUserThreadVa
|
||||
(
|
||||
hProcess,
|
||||
&oaThreadAttribs,
|
||||
dwCreationFlags & CREATE_SUSPENDED,
|
||||
0,
|
||||
&nStackReserve,
|
||||
&nStackCommit,
|
||||
(PTHREAD_START_ROUTINE)BaseThreadStartup,
|
||||
&hThread,
|
||||
&cidClientId,
|
||||
2,
|
||||
lpStartAddress,
|
||||
lpParameter
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode))
|
||||
{
|
||||
SetLastErrorByStatus(nErrCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DPRINT
|
||||
(
|
||||
"StackReserve %p\n"
|
||||
"StackCommit %p\n"
|
||||
"ThreadHandle %p\n"
|
||||
"ClientId.UniqueThread %p\n",
|
||||
nStackReserve,
|
||||
nStackCommit,
|
||||
hThread,
|
||||
cidClientId.UniqueThread
|
||||
);
|
||||
|
||||
/* success */
|
||||
if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread;
|
||||
return hThread;
|
||||
/* Notify DLLs and TLS Callbacks of termination */
|
||||
LdrShutdownThread();
|
||||
|
||||
/* Tell the Kernel to free the Stack */
|
||||
NtCurrentTeb()->FreeStackOnTermination = TRUE;
|
||||
NtTerminateThread(NULL, uExitCode);
|
||||
|
||||
/* We will never reach this place. This silences the compiler */
|
||||
ExitThread(uExitCode);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -330,37 +320,6 @@ GetCurrentThreadId(VOID)
|
|||
return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
ExitThread(DWORD uExitCode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN LastThread;
|
||||
|
||||
/*
|
||||
* Terminate process if this is the last thread
|
||||
* of the current process
|
||||
*/
|
||||
Status = NtQueryInformationThread(NtCurrentThread(),
|
||||
ThreadAmILastThread,
|
||||
&LastThread,
|
||||
sizeof(BOOLEAN),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status) && LastThread == TRUE)
|
||||
{
|
||||
ExitProcess(uExitCode);
|
||||
}
|
||||
|
||||
/* FIXME: notify csrss of thread termination */
|
||||
|
||||
LdrShutdownThread();
|
||||
|
||||
RtlRosExitUserThread(uExitCode);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
|
@ -1,483 +1,472 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
MiCreatePebOrTeb(PEPROCESS 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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_PEB_OR_TEB,
|
||||
&AllocatedBase,
|
||||
PAGE_SIZE,
|
||||
PAGE_READWRITE,
|
||||
&MemoryArea,
|
||||
TRUE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
|
||||
} while (Status != STATUS_SUCCESS);
|
||||
|
||||
/* Initialize the Region */
|
||||
MmInitialiseRegion(&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
|
||||
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;
|
||||
|
||||
/* Lock the Address Space */
|
||||
MmLockAddressSpace(ProcessAddressSpace);
|
||||
|
||||
/* Delete the Stack */
|
||||
MmFreeMemoryAreaByPtr(ProcessAddressSpace,
|
||||
Teb,
|
||||
MiFreePebPage,
|
||||
Process);
|
||||
|
||||
/* Unlock the Address Space */
|
||||
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||
}
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
MmCreateKernelStack(BOOLEAN GuiStack)
|
||||
{
|
||||
PMEMORY_AREA StackArea;
|
||||
ULONG i;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
PFN_TYPE Page[MM_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(),
|
||||
MEMORY_AREA_KERNEL_STACK,
|
||||
&KernelStack,
|
||||
MM_STACK_SIZE,
|
||||
0,
|
||||
&StackArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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 */
|
||||
for (i = 0; i < (MM_STACK_SIZE / 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);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
return KernelStack;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
MmCreatePeb(PEPROCESS Process)
|
||||
{
|
||||
PPEB Peb = NULL;
|
||||
LARGE_INTEGER SectionOffset;
|
||||
ULONG ViewSize = 0;
|
||||
PVOID TableBase = NULL;
|
||||
NTSTATUS Status;
|
||||
SectionOffset.QuadPart = (ULONGLONG)0;
|
||||
|
||||
DPRINT("MmCreatePeb\n");
|
||||
|
||||
/* Map NLS Tables */
|
||||
DPRINT("Mapping NLS\n");
|
||||
Status = MmMapViewOfSection(NlsSectionObject,
|
||||
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);
|
||||
|
||||
/* 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->OSMajorVersion = NtMajorVersion;
|
||||
Peb->OSMinorVersion = NtMinorVersion;
|
||||
Peb->OSBuildNumber = 2195;
|
||||
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;
|
||||
Peb->NumberOfProcessors = KeNumberProcessors;
|
||||
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
|
||||
|
||||
Process->Peb = Peb;
|
||||
KeDetachProcess();
|
||||
|
||||
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
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)TEB_BASE);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return TEB Address */
|
||||
DPRINT("Allocated: %x\n", Teb);
|
||||
if (Attached) KeDetachProcess();
|
||||
return Teb;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
MmCreateProcessAddressSpace(IN PEPROCESS Process,
|
||||
IN PSECTION_OBJECT Section OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
||||
PVOID BaseAddress;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
ULONG 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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_NO_ACCESS,
|
||||
&BaseAddress,
|
||||
0x10000,
|
||||
PAGE_NOACCESS,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_NO_ACCESS,
|
||||
&BaseAddress,
|
||||
0x10000 - PAGE_SIZE,
|
||||
PAGE_NOACCESS,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_SHARED_DATA,
|
||||
&BaseAddress,
|
||||
PAGE_SIZE,
|
||||
PAGE_READONLY,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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,
|
||||
Process,
|
||||
(PVOID*)&ImageBase,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
0,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to map process Image\n");
|
||||
ObDereferenceObject(Section);
|
||||
goto exit;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
MiCreatePebOrTeb(PEPROCESS 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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_PEB_OR_TEB,
|
||||
&AllocatedBase,
|
||||
PAGE_SIZE,
|
||||
PAGE_READWRITE,
|
||||
&MemoryArea,
|
||||
TRUE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
|
||||
} while (Status != STATUS_SUCCESS);
|
||||
|
||||
/* Initialize the Region */
|
||||
MmInitialiseRegion(&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
|
||||
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;
|
||||
|
||||
/* Lock the Address Space */
|
||||
MmLockAddressSpace(ProcessAddressSpace);
|
||||
|
||||
/* Delete the Stack */
|
||||
MmFreeMemoryAreaByPtr(ProcessAddressSpace,
|
||||
Teb,
|
||||
MiFreePebPage,
|
||||
Process);
|
||||
|
||||
/* Unlock the Address Space */
|
||||
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||
}
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
MmCreateKernelStack(BOOLEAN GuiStack)
|
||||
{
|
||||
PMEMORY_AREA StackArea;
|
||||
ULONG i;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
PFN_TYPE Page[MM_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(),
|
||||
MEMORY_AREA_KERNEL_STACK,
|
||||
&KernelStack,
|
||||
MM_STACK_SIZE,
|
||||
0,
|
||||
&StackArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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 */
|
||||
for (i = 0; i < (MM_STACK_SIZE / 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);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
return KernelStack;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
MmCreatePeb(PEPROCESS Process)
|
||||
{
|
||||
PPEB Peb = NULL;
|
||||
LARGE_INTEGER SectionOffset;
|
||||
ULONG ViewSize = 0;
|
||||
PVOID TableBase = NULL;
|
||||
NTSTATUS Status;
|
||||
SectionOffset.QuadPart = (ULONGLONG)0;
|
||||
|
||||
DPRINT("MmCreatePeb\n");
|
||||
|
||||
/* Map NLS Tables */
|
||||
DPRINT("Mapping NLS\n");
|
||||
Status = MmMapViewOfSection(NlsSectionObject,
|
||||
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);
|
||||
|
||||
/* 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->OSMajorVersion = NtMajorVersion;
|
||||
Peb->OSMinorVersion = NtMinorVersion;
|
||||
Peb->OSBuildNumber = 2195;
|
||||
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;
|
||||
Peb->NumberOfProcessors = KeNumberProcessors;
|
||||
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
|
||||
|
||||
Process->Peb = Peb;
|
||||
KeDetachProcess();
|
||||
|
||||
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
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)TEB_BASE);
|
||||
|
||||
/* 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 PEPROCESS Process,
|
||||
IN PSECTION_OBJECT Section OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
||||
PVOID BaseAddress;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
ULONG 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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_NO_ACCESS,
|
||||
&BaseAddress,
|
||||
0x10000,
|
||||
PAGE_NOACCESS,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_NO_ACCESS,
|
||||
&BaseAddress,
|
||||
0x10000 - PAGE_SIZE,
|
||||
PAGE_NOACCESS,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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(Process,
|
||||
ProcessAddressSpace,
|
||||
MEMORY_AREA_SHARED_DATA,
|
||||
&BaseAddress,
|
||||
PAGE_SIZE,
|
||||
PAGE_READONLY,
|
||||
&MemoryArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
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,
|
||||
Process,
|
||||
(PVOID*)&ImageBase,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
0,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to map process Image\n");
|
||||
ObDereferenceObject(Section);
|
||||
goto exit;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue