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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
* FILE: lib/kernel32/thread/i386/thread.S
|
* FILE: lib/kernel32/thread/i386/thread.S
|
||||||
* PURPOSE: Thread Start Thunks
|
* PURPOSE: Thread Start Thunks
|
||||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.globl _BaseThreadStartupThunk@0
|
.globl _BaseThreadStartupThunk@0
|
||||||
.globl _BaseProcessStartThunk@0
|
.globl _BaseProcessStartThunk@0
|
||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
_BaseThreadStartupThunk@0:
|
_BaseThreadStartupThunk@0:
|
||||||
|
|
||||||
/* Start out fresh */
|
/* Start out fresh */
|
||||||
xor ebp, ebp
|
xor ebp, ebp
|
||||||
|
|
||||||
push ebx /* lpParameter */
|
push ebx /* lpParameter */
|
||||||
push eax /* lpStartAddress */
|
push eax /* lpStartAddress */
|
||||||
push 0 /* Return EIP */
|
push 0 /* Return EIP */
|
||||||
//jmp _BaseThreadStartup@8
|
jmp _BaseThreadStartup@8
|
||||||
|
|
||||||
_BaseProcessStartThunk@0:
|
_BaseProcessStartThunk@0:
|
||||||
|
|
||||||
/* Start out fresh */
|
/* Start out fresh */
|
||||||
xor ebp, ebp
|
xor ebp, ebp
|
||||||
|
|
||||||
push eax /* lpStartAddress */
|
push eax /* lpStartAddress */
|
||||||
push 0 /* Return EIP */
|
push 0 /* Return EIP */
|
||||||
//jmp _BaseProcessStartup@4
|
jmp _BaseProcessStartup@4
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
* FILE: lib/kernel32/thread/thread.c
|
* FILE: lib/kernel32/thread/thread.c
|
||||||
* PURPOSE: Thread functions
|
* PURPOSE: Thread functions
|
||||||
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
* Tls functions are modified from WINE
|
* Ariadne ( ariadne@xs4all.nl)
|
||||||
* UPDATE HISTORY:
|
|
||||||
* Created 01/11/98
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -15,13 +12,9 @@
|
||||||
|
|
||||||
#include <k32.h>
|
#include <k32.h>
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "../include/debug.h"
|
#include "../include/debug.h"
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
_SEH_FILTER(BaseThreadExceptionFilter)
|
_SEH_FILTER(BaseThreadExceptionFilter)
|
||||||
{
|
{
|
||||||
|
@ -68,199 +61,196 @@ BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
||||||
ExitThread(uExitCode);
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HANDLE STDCALL
|
HANDLE
|
||||||
CreateThread
|
STDCALL
|
||||||
(
|
CreateRemoteThread(HANDLE hProcess,
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
DWORD dwStackSize,
|
DWORD dwStackSize,
|
||||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||||
LPVOID lpParameter,
|
LPVOID lpParameter,
|
||||||
DWORD dwCreationFlags,
|
DWORD dwCreationFlags,
|
||||||
LPDWORD lpThreadId
|
LPDWORD lpThreadId)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return CreateRemoteThread
|
NTSTATUS Status;
|
||||||
(
|
INITIAL_TEB InitialTeb;
|
||||||
NtCurrentProcess(),
|
CONTEXT Context;
|
||||||
lpThreadAttributes,
|
CLIENT_ID ClientId;
|
||||||
dwStackSize,
|
OBJECT_ATTRIBUTES LocalObjectAttributes;
|
||||||
lpStartAddress,
|
POBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
lpParameter,
|
HANDLE hThread;
|
||||||
dwCreationFlags,
|
ULONG Dummy;
|
||||||
lpThreadId
|
|
||||||
);
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
HANDLE STDCALL
|
VOID
|
||||||
CreateRemoteThread
|
STDCALL
|
||||||
(
|
ExitThread(DWORD uExitCode)
|
||||||
HANDLE hProcess,
|
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
||||||
DWORD dwStackSize,
|
|
||||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
||||||
LPVOID lpParameter,
|
|
||||||
DWORD dwCreationFlags,
|
|
||||||
LPDWORD lpThreadId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
HANDLE hThread;
|
NTSTATUS Status;
|
||||||
CLIENT_ID cidClientId;
|
BOOLEAN LastThread;
|
||||||
NTSTATUS nErrCode;
|
|
||||||
ULONG_PTR nStackReserve;
|
/*
|
||||||
ULONG_PTR nStackCommit;
|
* Terminate process if this is the last thread
|
||||||
OBJECT_ATTRIBUTES oaThreadAttribs;
|
* of the current process
|
||||||
PIMAGE_NT_HEADERS pinhHeader =
|
*/
|
||||||
RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
Status = NtQueryInformationThread(NtCurrentThread(),
|
||||||
|
ThreadAmILastThread,
|
||||||
|
&LastThread,
|
||||||
|
sizeof(BOOLEAN),
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status) && LastThread)
|
||||||
|
{
|
||||||
|
/* Exit the Process */
|
||||||
|
ExitProcess(uExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT
|
/* Notify DLLs and TLS Callbacks of termination */
|
||||||
(
|
LdrShutdownThread();
|
||||||
"hProcess %08X\n"
|
|
||||||
"lpThreadAttributes %08X\n"
|
/* Tell the Kernel to free the Stack */
|
||||||
"dwStackSize %08X\n"
|
NtCurrentTeb()->FreeStackOnTermination = TRUE;
|
||||||
"lpStartAddress %08X\n"
|
NtTerminateThread(NULL, uExitCode);
|
||||||
"lpParameter %08X\n"
|
|
||||||
"dwCreationFlags %08X\n"
|
/* We will never reach this place. This silences the compiler */
|
||||||
"lpThreadId %08X\n",
|
ExitThread(uExitCode);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -330,37 +320,6 @@ GetCurrentThreadId(VOID)
|
||||||
return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,483 +1,472 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/process.c
|
* FILE: ntoskrnl/mm/process.c
|
||||||
* PURPOSE: Memory functions related to Processes
|
* PURPOSE: Memory functions related to Processes
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
extern ULONG NtMajorVersion;
|
extern ULONG NtMajorVersion;
|
||||||
extern ULONG NtMinorVersion;
|
extern ULONG NtMinorVersion;
|
||||||
extern ULONG NtOSCSDVersion;
|
extern ULONG NtOSCSDVersion;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
STDCALL
|
STDCALL
|
||||||
MiCreatePebOrTeb(PEPROCESS Process,
|
MiCreatePebOrTeb(PEPROCESS Process,
|
||||||
PVOID BaseAddress)
|
PVOID BaseAddress)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
||||||
PMEMORY_AREA MemoryArea;
|
PMEMORY_AREA MemoryArea;
|
||||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||||
PVOID AllocatedBase = BaseAddress;
|
PVOID AllocatedBase = BaseAddress;
|
||||||
BoundaryAddressMultiple.QuadPart = 0;
|
BoundaryAddressMultiple.QuadPart = 0;
|
||||||
|
|
||||||
/* Acquire the Lock */
|
/* Acquire the Lock */
|
||||||
MmLockAddressSpace(ProcessAddressSpace);
|
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
|
* 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,
|
* 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
|
* while TEB allocation can fail, and we should simply try the address
|
||||||
* below. Is there a nicer way of doing this automagically? (ie: findning)
|
* below. Is there a nicer way of doing this automagically? (ie: findning)
|
||||||
* a gap region? -- Alex
|
* a gap region? -- Alex
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
DPRINT("Trying to allocate: %x\n", AllocatedBase);
|
DPRINT("Trying to allocate: %x\n", AllocatedBase);
|
||||||
Status = MmCreateMemoryArea(Process,
|
Status = MmCreateMemoryArea(Process,
|
||||||
ProcessAddressSpace,
|
ProcessAddressSpace,
|
||||||
MEMORY_AREA_PEB_OR_TEB,
|
MEMORY_AREA_PEB_OR_TEB,
|
||||||
&AllocatedBase,
|
&AllocatedBase,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
&MemoryArea,
|
&MemoryArea,
|
||||||
TRUE,
|
TRUE,
|
||||||
FALSE,
|
FALSE,
|
||||||
BoundaryAddressMultiple);
|
BoundaryAddressMultiple);
|
||||||
AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
|
AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
|
||||||
} while (Status != STATUS_SUCCESS);
|
} while (Status != STATUS_SUCCESS);
|
||||||
|
|
||||||
/* Initialize the Region */
|
/* Initialize the Region */
|
||||||
MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
|
MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
MEM_COMMIT,
|
MEM_COMMIT,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
|
|
||||||
/* Reserve the pages */
|
/* Reserve the pages */
|
||||||
MmReserveSwapPages(PAGE_SIZE);
|
MmReserveSwapPages(PAGE_SIZE);
|
||||||
|
|
||||||
/* Unlock Address Space */
|
/* Unlock Address Space */
|
||||||
DPRINT("Returning\n");
|
DPRINT("Returning\n");
|
||||||
MmUnlockAddressSpace(ProcessAddressSpace);
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||||
return RVA(AllocatedBase, PAGE_SIZE);
|
return RVA(AllocatedBase, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MiFreeStackPage(PVOID Context,
|
MiFreeStackPage(PVOID Context,
|
||||||
MEMORY_AREA* MemoryArea,
|
MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
PFN_TYPE Page,
|
PFN_TYPE Page,
|
||||||
SWAPENTRY SwapEntry,
|
SWAPENTRY SwapEntry,
|
||||||
BOOLEAN Dirty)
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
ASSERT(SwapEntry == 0);
|
ASSERT(SwapEntry == 0);
|
||||||
if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
MmDeleteKernelStack(PVOID Stack,
|
MmDeleteKernelStack(PVOID Stack,
|
||||||
BOOLEAN GuiStack)
|
BOOLEAN GuiStack)
|
||||||
{
|
{
|
||||||
/* Lock the Address Space */
|
/* Lock the Address Space */
|
||||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
|
||||||
/* Delete the Stack */
|
/* Delete the Stack */
|
||||||
MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
|
MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
|
||||||
Stack,
|
Stack,
|
||||||
MiFreeStackPage,
|
MiFreeStackPage,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Unlock the Address Space */
|
/* Unlock the Address Space */
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MiFreePebPage(PVOID Context,
|
MiFreePebPage(PVOID Context,
|
||||||
MEMORY_AREA* MemoryArea,
|
MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
PFN_TYPE Page,
|
PFN_TYPE Page,
|
||||||
SWAPENTRY SwapEntry,
|
SWAPENTRY SwapEntry,
|
||||||
BOOLEAN Dirty)
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
PEPROCESS Process = (PEPROCESS)Context;
|
PEPROCESS Process = (PEPROCESS)Context;
|
||||||
|
|
||||||
if (Page != 0)
|
if (Page != 0)
|
||||||
{
|
{
|
||||||
SWAPENTRY SavedSwapEntry;
|
SWAPENTRY SavedSwapEntry;
|
||||||
SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
|
SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
|
||||||
if (SavedSwapEntry != 0)
|
if (SavedSwapEntry != 0)
|
||||||
{
|
{
|
||||||
MmFreeSwapPage(SavedSwapEntry);
|
MmFreeSwapPage(SavedSwapEntry);
|
||||||
MmSetSavedSwapEntryPage(Page, 0);
|
MmSetSavedSwapEntryPage(Page, 0);
|
||||||
}
|
}
|
||||||
MmDeleteRmap(Page, Process, Address);
|
MmDeleteRmap(Page, Process, Address);
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
}
|
}
|
||||||
else if (SwapEntry != 0)
|
else if (SwapEntry != 0)
|
||||||
{
|
{
|
||||||
MmFreeSwapPage(SwapEntry);
|
MmFreeSwapPage(SwapEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
MmDeleteTeb(PEPROCESS Process,
|
MmDeleteTeb(PEPROCESS Process,
|
||||||
PTEB Teb)
|
PTEB Teb)
|
||||||
{
|
{
|
||||||
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
||||||
|
|
||||||
/* Lock the Address Space */
|
/* Lock the Address Space */
|
||||||
MmLockAddressSpace(ProcessAddressSpace);
|
MmLockAddressSpace(ProcessAddressSpace);
|
||||||
|
|
||||||
/* Delete the Stack */
|
/* Delete the Stack */
|
||||||
MmFreeMemoryAreaByPtr(ProcessAddressSpace,
|
MmFreeMemoryAreaByPtr(ProcessAddressSpace,
|
||||||
Teb,
|
Teb,
|
||||||
MiFreePebPage,
|
MiFreePebPage,
|
||||||
Process);
|
Process);
|
||||||
|
|
||||||
/* Unlock the Address Space */
|
/* Unlock the Address Space */
|
||||||
MmUnlockAddressSpace(ProcessAddressSpace);
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
STDCALL
|
STDCALL
|
||||||
MmCreateKernelStack(BOOLEAN GuiStack)
|
MmCreateKernelStack(BOOLEAN GuiStack)
|
||||||
{
|
{
|
||||||
PMEMORY_AREA StackArea;
|
PMEMORY_AREA StackArea;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||||
PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
|
PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
|
||||||
PVOID KernelStack = NULL;
|
PVOID KernelStack = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* Initialize the Boundary Address */
|
/* Initialize the Boundary Address */
|
||||||
BoundaryAddressMultiple.QuadPart = 0;
|
BoundaryAddressMultiple.QuadPart = 0;
|
||||||
|
|
||||||
/* Lock the Kernel Address Space */
|
/* Lock the Kernel Address Space */
|
||||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
|
||||||
/* Create a MAREA for the Kernel Stack */
|
/* Create a MAREA for the Kernel Stack */
|
||||||
Status = MmCreateMemoryArea(NULL,
|
Status = MmCreateMemoryArea(NULL,
|
||||||
MmGetKernelAddressSpace(),
|
MmGetKernelAddressSpace(),
|
||||||
MEMORY_AREA_KERNEL_STACK,
|
MEMORY_AREA_KERNEL_STACK,
|
||||||
&KernelStack,
|
&KernelStack,
|
||||||
MM_STACK_SIZE,
|
MM_STACK_SIZE,
|
||||||
0,
|
0,
|
||||||
&StackArea,
|
&StackArea,
|
||||||
FALSE,
|
FALSE,
|
||||||
FALSE,
|
FALSE,
|
||||||
BoundaryAddressMultiple);
|
BoundaryAddressMultiple);
|
||||||
|
|
||||||
/* Unlock the Address Space */
|
/* Unlock the Address Space */
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
|
||||||
/* Check for Success */
|
/* Check for Success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to create thread stack\n");
|
DPRINT1("Failed to create thread stack\n");
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECK(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark the Stack in use */
|
/* Mark the Stack in use */
|
||||||
for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
|
for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
|
||||||
{
|
{
|
||||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a Virtual Mapping for it */
|
/* Create a Virtual Mapping for it */
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
KernelStack,
|
KernelStack,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
Page,
|
Page,
|
||||||
MM_STACK_SIZE / PAGE_SIZE);
|
MM_STACK_SIZE / PAGE_SIZE);
|
||||||
|
|
||||||
/* Check for success */
|
/* Check for success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
|
DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECK(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelStack;
|
return KernelStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
MmCreatePeb(PEPROCESS Process)
|
MmCreatePeb(PEPROCESS Process)
|
||||||
{
|
{
|
||||||
PPEB Peb = NULL;
|
PPEB Peb = NULL;
|
||||||
LARGE_INTEGER SectionOffset;
|
LARGE_INTEGER SectionOffset;
|
||||||
ULONG ViewSize = 0;
|
ULONG ViewSize = 0;
|
||||||
PVOID TableBase = NULL;
|
PVOID TableBase = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
SectionOffset.QuadPart = (ULONGLONG)0;
|
SectionOffset.QuadPart = (ULONGLONG)0;
|
||||||
|
|
||||||
DPRINT("MmCreatePeb\n");
|
DPRINT("MmCreatePeb\n");
|
||||||
|
|
||||||
/* Map NLS Tables */
|
/* Map NLS Tables */
|
||||||
DPRINT("Mapping NLS\n");
|
DPRINT("Mapping NLS\n");
|
||||||
Status = MmMapViewOfSection(NlsSectionObject,
|
Status = MmMapViewOfSection(NlsSectionObject,
|
||||||
Process,
|
Process,
|
||||||
&TableBase,
|
&TableBase,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
&SectionOffset,
|
&SectionOffset,
|
||||||
&ViewSize,
|
&ViewSize,
|
||||||
ViewShare,
|
ViewShare,
|
||||||
MEM_TOP_DOWN,
|
MEM_TOP_DOWN,
|
||||||
PAGE_READONLY);
|
PAGE_READONLY);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
|
DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
|
DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
|
||||||
|
|
||||||
/* Attach to Process */
|
/* Attach to Process */
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
|
||||||
/* Allocate the PEB */
|
/* Allocate the PEB */
|
||||||
Peb = MiCreatePebOrTeb(Process, (PVOID)PEB_BASE);
|
Peb = MiCreatePebOrTeb(Process, (PVOID)PEB_BASE);
|
||||||
|
|
||||||
/* Initialize the PEB */
|
/* Initialize the PEB */
|
||||||
DPRINT("Allocated: %x\n", Peb);
|
DPRINT("Allocated: %x\n", Peb);
|
||||||
RtlZeroMemory(Peb, sizeof(PEB));
|
RtlZeroMemory(Peb, sizeof(PEB));
|
||||||
|
|
||||||
/* Set up data */
|
/* Set up data */
|
||||||
DPRINT("Setting up PEB\n");
|
DPRINT("Setting up PEB\n");
|
||||||
Peb->ImageBaseAddress = Process->SectionBaseAddress;
|
Peb->ImageBaseAddress = Process->SectionBaseAddress;
|
||||||
Peb->OSMajorVersion = NtMajorVersion;
|
Peb->OSMajorVersion = NtMajorVersion;
|
||||||
Peb->OSMinorVersion = NtMinorVersion;
|
Peb->OSMinorVersion = NtMinorVersion;
|
||||||
Peb->OSBuildNumber = 2195;
|
Peb->OSBuildNumber = 2195;
|
||||||
Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
|
Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
|
||||||
Peb->OSCSDVersion = NtOSCSDVersion;
|
Peb->OSCSDVersion = NtOSCSDVersion;
|
||||||
Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
|
Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
|
||||||
Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
|
Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
|
||||||
Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
|
Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
|
||||||
Peb->NumberOfProcessors = KeNumberProcessors;
|
Peb->NumberOfProcessors = KeNumberProcessors;
|
||||||
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
|
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
|
||||||
|
|
||||||
Process->Peb = Peb;
|
Process->Peb = Peb;
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
|
|
||||||
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
|
DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PTEB
|
PTEB
|
||||||
STDCALL
|
STDCALL
|
||||||
MmCreateTeb(PEPROCESS Process,
|
MmCreateTeb(PEPROCESS Process,
|
||||||
PCLIENT_ID ClientId,
|
PCLIENT_ID ClientId,
|
||||||
PINITIAL_TEB InitialTeb)
|
PINITIAL_TEB InitialTeb)
|
||||||
{
|
{
|
||||||
PTEB Teb;
|
PTEB Teb;
|
||||||
BOOLEAN Attached = FALSE;
|
BOOLEAN Attached = FALSE;
|
||||||
|
|
||||||
/* Attach to the process */
|
/* Attach to the process */
|
||||||
DPRINT("MmCreateTeb\n");
|
DPRINT("MmCreateTeb\n");
|
||||||
if (Process != PsGetCurrentProcess())
|
if (Process != PsGetCurrentProcess())
|
||||||
{
|
{
|
||||||
/* Attach to Target */
|
/* Attach to Target */
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
Attached = TRUE;
|
Attached = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the TEB */
|
/* Allocate the TEB */
|
||||||
Teb = MiCreatePebOrTeb(Process, (PVOID)TEB_BASE);
|
Teb = MiCreatePebOrTeb(Process, (PVOID)TEB_BASE);
|
||||||
|
|
||||||
/* Initialize the PEB */
|
/* Initialize the PEB */
|
||||||
RtlZeroMemory(Teb, sizeof(TEB));
|
RtlZeroMemory(Teb, sizeof(TEB));
|
||||||
|
|
||||||
/* Set TIB Data */
|
/* Set TIB Data */
|
||||||
Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
|
Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
|
||||||
Teb->Tib.Version = 1;
|
Teb->Tib.Version = 1;
|
||||||
Teb->Tib.Self = (PNT_TIB)Teb;
|
Teb->Tib.Self = (PNT_TIB)Teb;
|
||||||
|
|
||||||
/* Set TEB Data */
|
/* Set TEB Data */
|
||||||
Teb->Cid = *ClientId;
|
Teb->Cid = *ClientId;
|
||||||
Teb->RealClientId = *ClientId;
|
Teb->RealClientId = *ClientId;
|
||||||
Teb->ProcessEnvironmentBlock = Process->Peb;
|
Teb->ProcessEnvironmentBlock = Process->Peb;
|
||||||
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
||||||
|
|
||||||
/* Store stack information from InitialTeb */
|
/* Store stack information from InitialTeb */
|
||||||
if(InitialTeb != NULL)
|
if(InitialTeb != NULL)
|
||||||
{
|
{
|
||||||
/* fixed-size stack */
|
Teb->Tib.StackBase = InitialTeb->StackBase;
|
||||||
if(InitialTeb->PreviousStackBase && InitialTeb->PreviousStackLimit)
|
Teb->Tib.StackLimit = InitialTeb->StackLimit;
|
||||||
{
|
Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
|
||||||
Teb->Tib.StackBase = InitialTeb->PreviousStackBase;
|
}
|
||||||
Teb->Tib.StackLimit = InitialTeb->PreviousStackLimit;
|
|
||||||
Teb->DeallocationStack = InitialTeb->PreviousStackLimit;
|
/* Return TEB Address */
|
||||||
}
|
DPRINT("Allocated: %x\n", Teb);
|
||||||
/* expandable stack */
|
if (Attached) KeDetachProcess();
|
||||||
else
|
return Teb;
|
||||||
{
|
}
|
||||||
Teb->Tib.StackBase = InitialTeb->StackBase;
|
|
||||||
Teb->Tib.StackLimit = InitialTeb->StackLimit;
|
NTSTATUS
|
||||||
Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
|
STDCALL
|
||||||
}
|
MmCreateProcessAddressSpace(IN PEPROCESS Process,
|
||||||
}
|
IN PSECTION_OBJECT Section OPTIONAL)
|
||||||
|
{
|
||||||
/* Return TEB Address */
|
NTSTATUS Status;
|
||||||
DPRINT("Allocated: %x\n", Teb);
|
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
||||||
if (Attached) KeDetachProcess();
|
PVOID BaseAddress;
|
||||||
return Teb;
|
PMEMORY_AREA MemoryArea;
|
||||||
}
|
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||||
|
ULONG ViewSize = 0;
|
||||||
NTSTATUS
|
PVOID ImageBase = 0;
|
||||||
STDCALL
|
BoundaryAddressMultiple.QuadPart = 0;
|
||||||
MmCreateProcessAddressSpace(IN PEPROCESS Process,
|
|
||||||
IN PSECTION_OBJECT Section OPTIONAL)
|
/* Initialize the Addresss Space */
|
||||||
{
|
MmInitializeAddressSpace(Process, ProcessAddressSpace);
|
||||||
NTSTATUS Status;
|
|
||||||
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
|
/* Acquire the Lock */
|
||||||
PVOID BaseAddress;
|
MmLockAddressSpace(ProcessAddressSpace);
|
||||||
PMEMORY_AREA MemoryArea;
|
|
||||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
/* Protect the highest 64KB of the process address space */
|
||||||
ULONG ViewSize = 0;
|
BaseAddress = (PVOID)MmUserProbeAddress;
|
||||||
PVOID ImageBase = 0;
|
Status = MmCreateMemoryArea(Process,
|
||||||
BoundaryAddressMultiple.QuadPart = 0;
|
ProcessAddressSpace,
|
||||||
|
MEMORY_AREA_NO_ACCESS,
|
||||||
/* Initialize the Addresss Space */
|
&BaseAddress,
|
||||||
MmInitializeAddressSpace(Process, ProcessAddressSpace);
|
0x10000,
|
||||||
|
PAGE_NOACCESS,
|
||||||
/* Acquire the Lock */
|
&MemoryArea,
|
||||||
MmLockAddressSpace(ProcessAddressSpace);
|
FALSE,
|
||||||
|
FALSE,
|
||||||
/* Protect the highest 64KB of the process address space */
|
BoundaryAddressMultiple);
|
||||||
BaseAddress = (PVOID)MmUserProbeAddress;
|
if (!NT_SUCCESS(Status))
|
||||||
Status = MmCreateMemoryArea(Process,
|
{
|
||||||
ProcessAddressSpace,
|
DPRINT1("Failed to protect last 64KB\n");
|
||||||
MEMORY_AREA_NO_ACCESS,
|
goto exit;
|
||||||
&BaseAddress,
|
}
|
||||||
0x10000,
|
|
||||||
PAGE_NOACCESS,
|
/* Protect the 60KB above the shared user page */
|
||||||
&MemoryArea,
|
BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
|
||||||
FALSE,
|
Status = MmCreateMemoryArea(Process,
|
||||||
FALSE,
|
ProcessAddressSpace,
|
||||||
BoundaryAddressMultiple);
|
MEMORY_AREA_NO_ACCESS,
|
||||||
if (!NT_SUCCESS(Status))
|
&BaseAddress,
|
||||||
{
|
0x10000 - PAGE_SIZE,
|
||||||
DPRINT1("Failed to protect last 64KB\n");
|
PAGE_NOACCESS,
|
||||||
goto exit;
|
&MemoryArea,
|
||||||
}
|
FALSE,
|
||||||
|
FALSE,
|
||||||
/* Protect the 60KB above the shared user page */
|
BoundaryAddressMultiple);
|
||||||
BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
|
if (!NT_SUCCESS(Status))
|
||||||
Status = MmCreateMemoryArea(Process,
|
{
|
||||||
ProcessAddressSpace,
|
DPRINT1("Failed to protect the memory above the shared user page\n");
|
||||||
MEMORY_AREA_NO_ACCESS,
|
goto exit;
|
||||||
&BaseAddress,
|
}
|
||||||
0x10000 - PAGE_SIZE,
|
|
||||||
PAGE_NOACCESS,
|
/* Create the shared data page */
|
||||||
&MemoryArea,
|
BaseAddress = (PVOID)USER_SHARED_DATA;
|
||||||
FALSE,
|
Status = MmCreateMemoryArea(Process,
|
||||||
FALSE,
|
ProcessAddressSpace,
|
||||||
BoundaryAddressMultiple);
|
MEMORY_AREA_SHARED_DATA,
|
||||||
if (!NT_SUCCESS(Status))
|
&BaseAddress,
|
||||||
{
|
PAGE_SIZE,
|
||||||
DPRINT1("Failed to protect the memory above the shared user page\n");
|
PAGE_READONLY,
|
||||||
goto exit;
|
&MemoryArea,
|
||||||
}
|
FALSE,
|
||||||
|
FALSE,
|
||||||
/* Create the shared data page */
|
BoundaryAddressMultiple);
|
||||||
BaseAddress = (PVOID)USER_SHARED_DATA;
|
if (!NT_SUCCESS(Status))
|
||||||
Status = MmCreateMemoryArea(Process,
|
{
|
||||||
ProcessAddressSpace,
|
DPRINT1("Failed to create Shared User Data\n");
|
||||||
MEMORY_AREA_SHARED_DATA,
|
goto exit;
|
||||||
&BaseAddress,
|
}
|
||||||
PAGE_SIZE,
|
|
||||||
PAGE_READONLY,
|
/* Check if there's a Section Object */
|
||||||
&MemoryArea,
|
if (Section)
|
||||||
FALSE,
|
{
|
||||||
FALSE,
|
UNICODE_STRING FileName;
|
||||||
BoundaryAddressMultiple);
|
PWCHAR szSrc;
|
||||||
if (!NT_SUCCESS(Status))
|
PCHAR szDest;
|
||||||
{
|
USHORT lnFName = 0;
|
||||||
DPRINT1("Failed to create Shared User Data\n");
|
|
||||||
goto exit;
|
/* Unlock the Address Space */
|
||||||
}
|
DPRINT("Unlocking\n");
|
||||||
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||||
/* Check if there's a Section Object */
|
|
||||||
if (Section)
|
DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
|
||||||
{
|
Section, Process, &ImageBase);
|
||||||
UNICODE_STRING FileName;
|
Status = MmMapViewOfSection(Section,
|
||||||
PWCHAR szSrc;
|
Process,
|
||||||
PCHAR szDest;
|
(PVOID*)&ImageBase,
|
||||||
USHORT lnFName = 0;
|
0,
|
||||||
|
0,
|
||||||
/* Unlock the Address Space */
|
NULL,
|
||||||
DPRINT("Unlocking\n");
|
&ViewSize,
|
||||||
MmUnlockAddressSpace(ProcessAddressSpace);
|
0,
|
||||||
|
MEM_COMMIT,
|
||||||
DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
|
PAGE_READWRITE);
|
||||||
Section, Process, &ImageBase);
|
if (!NT_SUCCESS(Status))
|
||||||
Status = MmMapViewOfSection(Section,
|
{
|
||||||
Process,
|
DPRINT1("Failed to map process Image\n");
|
||||||
(PVOID*)&ImageBase,
|
ObDereferenceObject(Section);
|
||||||
0,
|
goto exit;
|
||||||
0,
|
}
|
||||||
NULL,
|
ObDereferenceObject(Section);
|
||||||
&ViewSize,
|
|
||||||
0,
|
/* Save the pointer */
|
||||||
MEM_COMMIT,
|
Process->SectionBaseAddress = ImageBase;
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
/* Determine the image file name and save it to EPROCESS */
|
||||||
{
|
DPRINT("Getting Image name\n");
|
||||||
DPRINT1("Failed to map process Image\n");
|
FileName = Section->FileObject->FileName;
|
||||||
ObDereferenceObject(Section);
|
szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
|
||||||
goto exit;
|
|
||||||
}
|
while(szSrc >= FileName.Buffer)
|
||||||
ObDereferenceObject(Section);
|
{
|
||||||
|
if(*szSrc == L'\\')
|
||||||
/* Save the pointer */
|
{
|
||||||
Process->SectionBaseAddress = ImageBase;
|
szSrc++;
|
||||||
|
break;
|
||||||
/* Determine the image file name and save it to EPROCESS */
|
}
|
||||||
DPRINT("Getting Image name\n");
|
else
|
||||||
FileName = Section->FileObject->FileName;
|
{
|
||||||
szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
|
szSrc--;
|
||||||
|
lnFName++;
|
||||||
while(szSrc >= FileName.Buffer)
|
}
|
||||||
{
|
}
|
||||||
if(*szSrc == L'\\')
|
|
||||||
{
|
/* Copy the to the process and truncate it to 15 characters if necessary */
|
||||||
szSrc++;
|
DPRINT("Copying and truncating\n");
|
||||||
break;
|
szDest = Process->ImageFileName;
|
||||||
}
|
lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
|
||||||
else
|
while(lnFName-- > 0) *(szDest++) = (UCHAR)*(szSrc++);
|
||||||
{
|
|
||||||
szSrc--;
|
/* Return status to caller */
|
||||||
lnFName++;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
exit:
|
||||||
/* Copy the to the process and truncate it to 15 characters if necessary */
|
/* Unlock the Address Space */
|
||||||
DPRINT("Copying and truncating\n");
|
DPRINT("Unlocking\n");
|
||||||
szDest = Process->ImageFileName;
|
MmUnlockAddressSpace(ProcessAddressSpace);
|
||||||
lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
|
|
||||||
while(lnFName-- > 0) *(szDest++) = (UCHAR)*(szSrc++);
|
/* Return status to caller */
|
||||||
|
return Status;
|
||||||
/* 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