mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
-move rtl thread/process stuff from ntdll to rtl and make ntoskrnl\ldr\init.c use those
-fix RtlCreateUserProcess to create the thread suspended and update all users of RtlCreateUserProcess to manually resume the thread svn path=/trunk/; revision=14430
This commit is contained in:
parent
c8e0c8df83
commit
95daa63b61
10 changed files with 469 additions and 814 deletions
|
@ -377,6 +377,21 @@ RemoveTailList(
|
||||||
|
|
||||||
#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination), (Source), (Length)))
|
#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination), (Source), (Length)))
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlCreateUserThread (
|
||||||
|
IN HANDLE ProcessHandle,
|
||||||
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
IN BOOLEAN CreateSuspended,
|
||||||
|
IN LONG StackZeroBits,
|
||||||
|
IN OUT PULONG StackReserve,
|
||||||
|
IN OUT PULONG StackCommit,
|
||||||
|
IN PTHREAD_START_ROUTINE StartAddress,
|
||||||
|
IN PVOID Parameter,
|
||||||
|
IN OUT PHANDLE ThreadHandle,
|
||||||
|
IN OUT PCLIENT_ID ClientId
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
RtlAppendUnicodeToString (
|
RtlAppendUnicodeToString (
|
||||||
|
|
|
@ -23,7 +23,7 @@ TARGET_LFLAGS = -Wl,--file-alignment,0x1000 \
|
||||||
-Wl,--section-alignment,0x1000 \
|
-Wl,--section-alignment,0x1000 \
|
||||||
-nostartfiles -nostdlib
|
-nostartfiles -nostdlib
|
||||||
|
|
||||||
TARGET_SDKLIBS = rosrtl.a rtl.a string.a
|
TARGET_SDKLIBS = rtl.a rosrtl.a string.a
|
||||||
|
|
||||||
TARGET_GCCLIBS = gcc
|
TARGET_GCCLIBS = gcc
|
||||||
|
|
||||||
|
@ -81,7 +81,6 @@ RTL_OBJECTS = \
|
||||||
rtl/rangelist.o \
|
rtl/rangelist.o \
|
||||||
rtl/resource.o \
|
rtl/resource.o \
|
||||||
rtl/teb.o \
|
rtl/teb.o \
|
||||||
rtl/thread.o \
|
|
||||||
rtl/timerqueue.o \
|
rtl/timerqueue.o \
|
||||||
rtl/libsupp.o
|
rtl/libsupp.o
|
||||||
|
|
||||||
|
|
|
@ -23,30 +23,6 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
static NTSTATUS RtlpCreateFirstThread
|
|
||||||
(
|
|
||||||
HANDLE ProcessHandle,
|
|
||||||
ULONG StackReserve,
|
|
||||||
ULONG StackCommit,
|
|
||||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
||||||
PCLIENT_ID ClientId,
|
|
||||||
PHANDLE ThreadHandle
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return RtlCreateUserThread
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
NULL,
|
|
||||||
FALSE,
|
|
||||||
0,
|
|
||||||
&StackReserve,
|
|
||||||
&StackCommit,
|
|
||||||
lpStartAddress,
|
|
||||||
(PVOID)PEB_BASE,
|
|
||||||
ThreadHandle,
|
|
||||||
ClientId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
PPEB
|
PPEB
|
||||||
STDCALL
|
STDCALL
|
||||||
|
@ -55,273 +31,26 @@ RtlpCurrentPeb(VOID)
|
||||||
return NtCurrentPeb();
|
return NtCurrentPeb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
RtlpMapFile(PUNICODE_STRING ImageFileName,
|
|
||||||
PRTL_USER_PROCESS_PARAMETERS Ppb,
|
|
||||||
ULONG Attributes,
|
|
||||||
PHANDLE Section)
|
|
||||||
{
|
|
||||||
HANDLE hFile;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
hFile = NULL;
|
|
||||||
|
|
||||||
RtlDeNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
// DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
ImageFileName,
|
|
||||||
Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
|
|
||||||
NULL,
|
|
||||||
SecurityDescriptor);
|
|
||||||
|
|
||||||
RtlNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to open the executable
|
|
||||||
*/
|
|
||||||
|
|
||||||
Status = NtOpenFile(&hFile,
|
|
||||||
SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
FILE_SHARE_DELETE|FILE_SHARE_READ,
|
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = NtCreateSection(Section,
|
|
||||||
SECTION_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
PAGE_EXECUTE,
|
|
||||||
SEC_IMAGE,
|
|
||||||
hFile);
|
|
||||||
NtClose(hFile);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
|
|
||||||
PRTL_USER_PROCESS_PARAMETERS Ppb,
|
|
||||||
PVOID* ImageBaseAddress)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PVOID PpbBase;
|
|
||||||
ULONG PpbSize;
|
|
||||||
ULONG BytesWritten;
|
|
||||||
ULONG Offset;
|
|
||||||
PVOID EnvPtr = NULL;
|
|
||||||
ULONG EnvSize = 0;
|
|
||||||
|
|
||||||
/* create the Environment */
|
|
||||||
if (Ppb->Environment != NULL)
|
|
||||||
{
|
|
||||||
MEMORY_BASIC_INFORMATION MemInfo;
|
|
||||||
|
|
||||||
Status = NtQueryVirtualMemory (NtCurrentProcess (),
|
|
||||||
Ppb->Environment,
|
|
||||||
MemoryBasicInformation,
|
|
||||||
&MemInfo,
|
|
||||||
sizeof(MEMORY_BASIC_INFORMATION),
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
EnvSize = MemInfo.RegionSize;
|
|
||||||
}
|
|
||||||
DPRINT("EnvironmentSize %ld\n", EnvSize);
|
|
||||||
|
|
||||||
/* allocate and initialize new environment block */
|
|
||||||
if (EnvSize != 0)
|
|
||||||
{
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&EnvPtr,
|
|
||||||
0,
|
|
||||||
&EnvSize,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
EnvPtr,
|
|
||||||
Ppb->Environment,
|
|
||||||
EnvSize,
|
|
||||||
&BytesWritten);
|
|
||||||
}
|
|
||||||
DPRINT("EnvironmentPointer %p\n", EnvPtr);
|
|
||||||
|
|
||||||
/* create the PPB */
|
|
||||||
PpbBase = NULL;
|
|
||||||
PpbSize = Ppb->AllocationSize;
|
|
||||||
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&PpbBase,
|
|
||||||
0,
|
|
||||||
&PpbSize,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Ppb->MaximumLength %x\n", Ppb->AllocationSize);
|
|
||||||
|
|
||||||
/* write process parameters block*/
|
|
||||||
RtlDeNormalizeProcessParams (Ppb);
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
PpbBase,
|
|
||||||
Ppb,
|
|
||||||
Ppb->AllocationSize,
|
|
||||||
|
|
||||||
&BytesWritten);
|
|
||||||
RtlNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
/* write pointer to environment */
|
|
||||||
Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID)(PpbBase + Offset),
|
|
||||||
&EnvPtr,
|
|
||||||
sizeof(EnvPtr),
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
/* write pointer to process parameter block */
|
|
||||||
Offset = FIELD_OFFSET(PEB, ProcessParameters);
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID)(PEB_BASE + Offset),
|
|
||||||
&PpbBase,
|
|
||||||
sizeof(PpbBase),
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
/* Read image base address. */
|
|
||||||
Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
|
|
||||||
NtReadVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID)(PEB_BASE + Offset),
|
|
||||||
ImageBaseAddress,
|
|
||||||
sizeof(PVOID),
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
VOID STDCALL
|
||||||
RtlCreateUserProcess(PUNICODE_STRING ImageFileName,
|
RtlAcquirePebLock(VOID)
|
||||||
ULONG Attributes,
|
|
||||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
|
||||||
PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
|
|
||||||
PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
|
|
||||||
HANDLE ParentProcess,
|
|
||||||
BOOLEAN CurrentDirectory,
|
|
||||||
HANDLE DebugPort,
|
|
||||||
HANDLE ExceptionPort,
|
|
||||||
PRTL_PROCESS_INFO ProcessInfo)
|
|
||||||
{
|
{
|
||||||
HANDLE hSection;
|
PPEB Peb = NtCurrentPeb ();
|
||||||
NTSTATUS Status;
|
Peb->FastPebLockRoutine (Peb->FastPebLock);
|
||||||
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
|
}
|
||||||
ULONG retlen;
|
|
||||||
SECTION_IMAGE_INFORMATION Sii;
|
|
||||||
ULONG ResultLength;
|
|
||||||
PVOID ImageBaseAddress;
|
|
||||||
|
|
||||||
DPRINT("RtlCreateUserProcess\n");
|
|
||||||
|
|
||||||
Status = RtlpMapFile(ImageFileName,
|
/*
|
||||||
ProcessParameters,
|
* @implemented
|
||||||
Attributes,
|
|
||||||
&hSection);
|
|
||||||
if( !NT_SUCCESS( Status ) )
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new process
|
|
||||||
*/
|
*/
|
||||||
if (ParentProcess == NULL)
|
VOID STDCALL
|
||||||
ParentProcess = NtCurrentProcess();
|
RtlReleasePebLock(VOID)
|
||||||
|
{
|
||||||
Status = NtCreateProcess(&(ProcessInfo->ProcessHandle),
|
PPEB Peb = NtCurrentPeb ();
|
||||||
PROCESS_ALL_ACCESS,
|
Peb->FastPebUnlockRoutine (Peb->FastPebLock);
|
||||||
NULL,
|
|
||||||
ParentProcess,
|
|
||||||
CurrentDirectory,
|
|
||||||
hSection,
|
|
||||||
DebugPort,
|
|
||||||
ExceptionPort);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
NtClose(hSection);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get some information about the process
|
|
||||||
*/
|
|
||||||
NtQueryInformationProcess(ProcessInfo->ProcessHandle,
|
|
||||||
ProcessBasicInformation,
|
|
||||||
&ProcessBasicInfo,
|
|
||||||
sizeof(ProcessBasicInfo),
|
|
||||||
&retlen);
|
|
||||||
DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
|
|
||||||
ProcessBasicInfo.UniqueProcessId);
|
|
||||||
ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create Process Environment Block
|
|
||||||
*/
|
|
||||||
DPRINT("Creating peb\n");
|
|
||||||
KlInitPeb(ProcessInfo->ProcessHandle,
|
|
||||||
ProcessParameters,
|
|
||||||
&ImageBaseAddress);
|
|
||||||
|
|
||||||
Status = NtQuerySection(hSection,
|
|
||||||
SectionImageInformation,
|
|
||||||
&Sii,
|
|
||||||
sizeof(Sii),
|
|
||||||
&ResultLength);
|
|
||||||
if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
|
|
||||||
{
|
|
||||||
DPRINT("Failed to get section image information.\n");
|
|
||||||
NtClose(hSection);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Creating thread for process\n");
|
|
||||||
Status = RtlpCreateFirstThread(ProcessInfo->ProcessHandle,
|
|
||||||
Sii.StackReserve,
|
|
||||||
Sii.StackCommit,
|
|
||||||
ImageBaseAddress + (ULONG)Sii.EntryPoint,
|
|
||||||
&ProcessInfo->ClientId,
|
|
||||||
&ProcessInfo->ThreadHandle);
|
|
||||||
|
|
||||||
NtClose(hSection);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("Failed to create thread\n");
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,25 +14,5 @@ PTEB STDCALL
|
||||||
_NtCurrentTeb() { return NtCurrentTeb(); }
|
_NtCurrentTeb() { return NtCurrentTeb(); }
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID STDCALL
|
|
||||||
RtlAcquirePebLock(VOID)
|
|
||||||
{
|
|
||||||
PPEB Peb = NtCurrentPeb ();
|
|
||||||
Peb->FastPebLockRoutine (Peb->FastPebLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID STDCALL
|
|
||||||
RtlReleasePebLock(VOID)
|
|
||||||
{
|
|
||||||
PPEB Peb = NtCurrentPeb ();
|
|
||||||
Peb->FastPebUnlockRoutine (Peb->FastPebLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -20,6 +20,8 @@ TARGET_OBJECTS = \
|
||||||
acl.o \
|
acl.o \
|
||||||
ppb.o \
|
ppb.o \
|
||||||
bit.o \
|
bit.o \
|
||||||
|
thread.o \
|
||||||
|
process.o \
|
||||||
bitmap.o \
|
bitmap.o \
|
||||||
bootdata.o \
|
bootdata.o \
|
||||||
compress.o \
|
compress.o \
|
||||||
|
|
318
reactos/lib/rtl/process.c
Normal file
318
reactos/lib/rtl/process.c
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
/* $Id$
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* FILE: lib/ntdll/rtl/process.c
|
||||||
|
* PURPOSE: Process functions
|
||||||
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* Created 01/11/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <napi/i386/segment.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <ntdll/base.h>
|
||||||
|
#include <ntdll/rtl.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <ntdll/ntdll.h>
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
RtlpMapFile(PUNICODE_STRING ImageFileName,
|
||||||
|
PRTL_USER_PROCESS_PARAMETERS Ppb,
|
||||||
|
ULONG Attributes,
|
||||||
|
PHANDLE Section)
|
||||||
|
{
|
||||||
|
HANDLE hFile;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
hFile = NULL;
|
||||||
|
|
||||||
|
RtlDeNormalizeProcessParams (Ppb);
|
||||||
|
|
||||||
|
// DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
ImageFileName,
|
||||||
|
Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
|
||||||
|
NULL,
|
||||||
|
SecurityDescriptor);
|
||||||
|
|
||||||
|
RtlNormalizeProcessParams (Ppb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to open the executable
|
||||||
|
*/
|
||||||
|
|
||||||
|
Status = ZwOpenFile(&hFile,
|
||||||
|
SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FILE_SHARE_DELETE|FILE_SHARE_READ,
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ZwCreateSection(Section,
|
||||||
|
SECTION_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
PAGE_EXECUTE,
|
||||||
|
SEC_IMAGE,
|
||||||
|
hFile);
|
||||||
|
ZwClose(hFile);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
|
||||||
|
PRTL_USER_PROCESS_PARAMETERS Ppb,
|
||||||
|
PVOID* ImageBaseAddress)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID PpbBase;
|
||||||
|
ULONG PpbSize;
|
||||||
|
ULONG BytesWritten;
|
||||||
|
ULONG Offset;
|
||||||
|
PVOID EnvPtr = NULL;
|
||||||
|
ULONG EnvSize = 0;
|
||||||
|
|
||||||
|
/* create the Environment */
|
||||||
|
if (Ppb->Environment != NULL)
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION MemInfo;
|
||||||
|
|
||||||
|
Status = ZwQueryVirtualMemory (NtCurrentProcess (),
|
||||||
|
Ppb->Environment,
|
||||||
|
MemoryBasicInformation,
|
||||||
|
&MemInfo,
|
||||||
|
sizeof(MEMORY_BASIC_INFORMATION),
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
EnvSize = MemInfo.RegionSize;
|
||||||
|
}
|
||||||
|
DPRINT("EnvironmentSize %ld\n", EnvSize);
|
||||||
|
|
||||||
|
/* allocate and initialize new environment block */
|
||||||
|
if (EnvSize != 0)
|
||||||
|
{
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&EnvPtr,
|
||||||
|
0,
|
||||||
|
&EnvSize,
|
||||||
|
MEM_RESERVE | MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
|
EnvPtr,
|
||||||
|
Ppb->Environment,
|
||||||
|
EnvSize,
|
||||||
|
&BytesWritten);
|
||||||
|
}
|
||||||
|
DPRINT("EnvironmentPointer %p\n", EnvPtr);
|
||||||
|
|
||||||
|
/* create the PPB */
|
||||||
|
PpbBase = NULL;
|
||||||
|
PpbSize = Ppb->AllocationSize;
|
||||||
|
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&PpbBase,
|
||||||
|
0,
|
||||||
|
&PpbSize,
|
||||||
|
MEM_RESERVE | MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Ppb->MaximumLength %x\n", Ppb->AllocationSize);
|
||||||
|
|
||||||
|
/* write process parameters block*/
|
||||||
|
RtlDeNormalizeProcessParams (Ppb);
|
||||||
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
|
PpbBase,
|
||||||
|
Ppb,
|
||||||
|
Ppb->AllocationSize,
|
||||||
|
|
||||||
|
&BytesWritten);
|
||||||
|
RtlNormalizeProcessParams (Ppb);
|
||||||
|
|
||||||
|
/* write pointer to environment */
|
||||||
|
Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
|
||||||
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
|
(PVOID)(PpbBase + Offset),
|
||||||
|
&EnvPtr,
|
||||||
|
sizeof(EnvPtr),
|
||||||
|
&BytesWritten);
|
||||||
|
|
||||||
|
/* write pointer to process parameter block */
|
||||||
|
Offset = FIELD_OFFSET(PEB, ProcessParameters);
|
||||||
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
|
(PVOID)(PEB_BASE + Offset),
|
||||||
|
&PpbBase,
|
||||||
|
sizeof(PpbBase),
|
||||||
|
&BytesWritten);
|
||||||
|
|
||||||
|
/* Read image base address. */
|
||||||
|
Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
|
||||||
|
ZwReadVirtualMemory(ProcessHandle,
|
||||||
|
(PVOID)(PEB_BASE + Offset),
|
||||||
|
ImageBaseAddress,
|
||||||
|
sizeof(PVOID),
|
||||||
|
&BytesWritten);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*
|
||||||
|
* Creates a process and its initial thread.
|
||||||
|
*
|
||||||
|
* NOTES:
|
||||||
|
* - The first thread is created suspended, so it needs a manual resume!!!
|
||||||
|
* - If ParentProcess is NULL, current process is used
|
||||||
|
* - ProcessParameters must be normalized
|
||||||
|
* - Attributes are object attribute flags used when opening the ImageFileName.
|
||||||
|
* Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
|
||||||
|
*
|
||||||
|
* -Gunnar
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
RtlCreateUserProcess(
|
||||||
|
IN PUNICODE_STRING ImageFileName,
|
||||||
|
IN ULONG Attributes,
|
||||||
|
IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
||||||
|
IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
|
||||||
|
IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
|
||||||
|
IN HANDLE ParentProcess OPTIONAL,
|
||||||
|
IN BOOLEAN InheritHandles,
|
||||||
|
IN HANDLE DebugPort OPTIONAL,
|
||||||
|
IN HANDLE ExceptionPort OPTIONAL,
|
||||||
|
OUT PRTL_PROCESS_INFO ProcessInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HANDLE hSection;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
|
||||||
|
ULONG retlen;
|
||||||
|
SECTION_IMAGE_INFORMATION Sii;
|
||||||
|
ULONG ResultLength;
|
||||||
|
PVOID ImageBaseAddress;
|
||||||
|
|
||||||
|
DPRINT("RtlCreateUserProcess\n");
|
||||||
|
|
||||||
|
Status = RtlpMapFile(ImageFileName,
|
||||||
|
ProcessParameters,
|
||||||
|
Attributes,
|
||||||
|
&hSection);
|
||||||
|
if( !NT_SUCCESS( Status ) )
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new process
|
||||||
|
*/
|
||||||
|
if (ParentProcess == NULL)
|
||||||
|
ParentProcess = NtCurrentProcess();
|
||||||
|
|
||||||
|
Status = ZwCreateProcess(&(ProcessInfo->ProcessHandle),
|
||||||
|
PROCESS_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
ParentProcess,
|
||||||
|
InheritHandles,
|
||||||
|
hSection,
|
||||||
|
DebugPort,
|
||||||
|
ExceptionPort);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ZwClose(hSection);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get some information about the process
|
||||||
|
*/
|
||||||
|
ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
|
||||||
|
ProcessBasicInformation,
|
||||||
|
&ProcessBasicInfo,
|
||||||
|
sizeof(ProcessBasicInfo),
|
||||||
|
&retlen);
|
||||||
|
DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
|
||||||
|
ProcessBasicInfo.UniqueProcessId);
|
||||||
|
ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create Process Environment Block
|
||||||
|
*/
|
||||||
|
DPRINT("Creating peb\n");
|
||||||
|
KlInitPeb(ProcessInfo->ProcessHandle,
|
||||||
|
ProcessParameters,
|
||||||
|
&ImageBaseAddress);
|
||||||
|
|
||||||
|
Status = ZwQuerySection(hSection,
|
||||||
|
SectionImageInformation,
|
||||||
|
&Sii,
|
||||||
|
sizeof(Sii),
|
||||||
|
&ResultLength);
|
||||||
|
if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
|
||||||
|
{
|
||||||
|
DPRINT("Failed to get section image information.\n");
|
||||||
|
ZwClose(hSection);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Creating thread for process\n");
|
||||||
|
Status = RtlCreateUserThread(
|
||||||
|
ProcessInfo->ProcessHandle,
|
||||||
|
NULL,
|
||||||
|
TRUE, /* CreateSuspended? */
|
||||||
|
0,
|
||||||
|
&Sii.StackReserve,
|
||||||
|
&Sii.StackCommit,
|
||||||
|
ImageBaseAddress + (ULONG)Sii.EntryPoint,
|
||||||
|
(PVOID)PEB_BASE,
|
||||||
|
&ProcessInfo->ThreadHandle,
|
||||||
|
&ProcessInfo->ClientId
|
||||||
|
);
|
||||||
|
|
||||||
|
ZwClose(hSection);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Failed to create thread\n");
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#define NTOS_MODE_USER
|
|
||||||
#include <ntos.h>
|
#include <ntos.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
|
@ -11,536 +11,148 @@
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
|
||||||
/* MACROS ******************************************************************/
|
/*
|
||||||
|
* HACK! No matter what i did, i couldnt get it working when i put these into ntos\rtl.h
|
||||||
|
* (got redefinition problems, since ntdll\rtl.h somehow include ntos\rtl.h).
|
||||||
|
* We need to merge ntos\rtl.h and ntdll\rtl.h to get this working. -Gunnar
|
||||||
|
*/
|
||||||
|
typedef struct _RTL_PROCESS_INFO
|
||||||
|
{
|
||||||
|
ULONG Size;
|
||||||
|
HANDLE ProcessHandle;
|
||||||
|
HANDLE ThreadHandle;
|
||||||
|
CLIENT_ID ClientId;
|
||||||
|
SECTION_IMAGE_INFORMATION ImageInfo;
|
||||||
|
} RTL_PROCESS_INFO, *PRTL_PROCESS_INFO;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlCreateUserProcess (
|
||||||
|
IN PUNICODE_STRING ImageFileName,
|
||||||
|
IN ULONG Attributes,
|
||||||
|
IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
||||||
|
IN PSECURITY_DESCRIPTOR ProcessSecutityDescriptor OPTIONAL,
|
||||||
|
IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
|
||||||
|
IN HANDLE ParentProcess OPTIONAL,
|
||||||
|
IN BOOLEAN CurrentDirectory,
|
||||||
|
IN HANDLE DebugPort OPTIONAL,
|
||||||
|
IN HANDLE ExceptionPort OPTIONAL,
|
||||||
|
OUT PRTL_PROCESS_INFO ProcessInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlCreateProcessParameters (
|
||||||
|
OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
|
||||||
|
IN PUNICODE_STRING ImagePathName OPTIONAL,
|
||||||
|
IN PUNICODE_STRING DllPath OPTIONAL,
|
||||||
|
IN PUNICODE_STRING CurrentDirectory OPTIONAL,
|
||||||
|
IN PUNICODE_STRING CommandLine OPTIONAL,
|
||||||
|
IN PWSTR Environment OPTIONAL,
|
||||||
|
IN PUNICODE_STRING WindowTitle OPTIONAL,
|
||||||
|
IN PUNICODE_STRING DesktopInfo OPTIONAL,
|
||||||
|
IN PUNICODE_STRING ShellInfo OPTIONAL,
|
||||||
|
IN PUNICODE_STRING RuntimeInfo OPTIONAL
|
||||||
|
);
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlDestroyProcessParameters (
|
||||||
|
IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters
|
||||||
|
);
|
||||||
|
|
||||||
#define DENORMALIZE(x,addr) {if(x) x=(VOID*)((ULONG)(x)-(ULONG)(addr));}
|
|
||||||
#define ALIGN(x,align) (((ULONG)(x)+(align)-1UL)&(~((align)-1UL)))
|
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
LdrpMapProcessImage(PHANDLE SectionHandle,
|
|
||||||
PUNICODE_STRING ImagePath)
|
|
||||||
{
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
HANDLE FileHandle;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* Open image file */
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
ImagePath,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
DPRINT("Opening image file %S\n", ObjectAttributes.ObjectName->Buffer);
|
|
||||||
Status = NtOpenFile(&FileHandle,
|
|
||||||
FILE_ALL_ACCESS,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
0,
|
|
||||||
FILE_SYNCHRONOUS_IO_ALERT);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a section for the image */
|
|
||||||
DPRINT("Creating section\n");
|
|
||||||
Status = NtCreateSection(SectionHandle,
|
|
||||||
SECTION_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
SEC_COMMIT | SEC_IMAGE,
|
|
||||||
FileHandle);
|
|
||||||
NtClose(FileHandle);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtCreateSection() failed (Status %lx)\n", Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
INIT_FUNCTION
|
||||||
LdrpCreateProcessEnvironment(HANDLE ProcessHandle,
|
NTSTATUS
|
||||||
PUNICODE_STRING ImagePath,
|
|
||||||
PVOID* ImageBaseAddress)
|
|
||||||
{
|
|
||||||
PRTL_USER_PROCESS_PARAMETERS LocalPpb;
|
|
||||||
PRTL_USER_PROCESS_PARAMETERS ProcessPpb;
|
|
||||||
ULONG BytesWritten;
|
|
||||||
ULONG Offset;
|
|
||||||
ULONG Size;
|
|
||||||
ULONG RegionSize;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* Calculate the PPB size */
|
|
||||||
Size = sizeof(RTL_USER_PROCESS_PARAMETERS);
|
|
||||||
Size += ALIGN(ImagePath->Length + sizeof(WCHAR), sizeof(ULONG));
|
|
||||||
RegionSize = ROUND_UP(Size, PAGE_SIZE);
|
|
||||||
DPRINT("Size %lu RegionSize %lu\n", Size, RegionSize);
|
|
||||||
|
|
||||||
/* Allocate the local PPB */
|
|
||||||
LocalPpb = NULL;
|
|
||||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
|
||||||
(PVOID*)&LocalPpb,
|
|
||||||
0,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("LocalPpb %p AllocationSize %lu\n", LocalPpb, RegionSize);
|
|
||||||
|
|
||||||
/* Initialize the local PPB */
|
|
||||||
RtlZeroMemory(LocalPpb,
|
|
||||||
RegionSize);
|
|
||||||
LocalPpb->AllocationSize = RegionSize;
|
|
||||||
LocalPpb->Size = Size;
|
|
||||||
LocalPpb->ImagePathName.Length = ImagePath->Length;
|
|
||||||
LocalPpb->ImagePathName.MaximumLength = ImagePath->Length + sizeof(WCHAR);
|
|
||||||
LocalPpb->ImagePathName.Buffer = (PWCHAR)(LocalPpb + 1);
|
|
||||||
|
|
||||||
/* Copy image path */
|
|
||||||
RtlCopyMemory(LocalPpb->ImagePathName.Buffer,
|
|
||||||
ImagePath->Buffer,
|
|
||||||
ImagePath->Length);
|
|
||||||
LocalPpb->ImagePathName.Buffer[ImagePath->Length / sizeof(WCHAR)] = L'\0';
|
|
||||||
|
|
||||||
/* Denormalize the process parameter block */
|
|
||||||
DENORMALIZE(LocalPpb->ImagePathName.Buffer, LocalPpb);
|
|
||||||
LocalPpb->Flags &= ~PPF_NORMALIZED;
|
|
||||||
|
|
||||||
/* Create the process PPB */
|
|
||||||
ProcessPpb = NULL;
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID*)&ProcessPpb,
|
|
||||||
0,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
|
|
||||||
|
|
||||||
/* Release the local PPB */
|
|
||||||
RegionSize = 0;
|
|
||||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
|
||||||
(PVOID*)&LocalPpb,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy local PPB into the process PPB */
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
ProcessPpb,
|
|
||||||
LocalPpb,
|
|
||||||
LocalPpb->AllocationSize,
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
/* Update pointer to process PPB in the process PEB */
|
|
||||||
Offset = FIELD_OFFSET(PEB, ProcessParameters);
|
|
||||||
NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID)(PEB_BASE + Offset),
|
|
||||||
&ProcessPpb,
|
|
||||||
sizeof(ProcessPpb),
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
/* Release local PPB */
|
|
||||||
RegionSize = 0;
|
|
||||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
|
||||||
(PVOID*)&LocalPpb,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
|
|
||||||
/* Read image base address. */
|
|
||||||
Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
|
|
||||||
NtReadVirtualMemory(ProcessHandle,
|
|
||||||
(PVOID)(PEB_BASE + Offset),
|
|
||||||
ImageBaseAddress,
|
|
||||||
sizeof(PVOID),
|
|
||||||
&BytesWritten);
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME: this sucks. Sucks sucks sucks. This code was duplicated, if you can
|
|
||||||
believe it, in four different places - excluding this, and twice in the two
|
|
||||||
DLLs that contained it (kernel32.dll and ntdll.dll). As much as I'd like to
|
|
||||||
rip the whole RTL out of ntdll.dll and ntoskrnl.exe and into its own static
|
|
||||||
library, ntoskrnl.exe is built separatedly from the rest of ReactOS, coming
|
|
||||||
with its own linker scripts and specifications, and, save for changes and fixes
|
|
||||||
to make it at least compile, I'm not going to touch any of it. If you feel
|
|
||||||
brave enough, you're welcome [KJK::Hyperion]
|
|
||||||
*/
|
|
||||||
static NTSTATUS LdrpCreateStack
|
|
||||||
(
|
|
||||||
HANDLE ProcessHandle,
|
|
||||||
PINITIAL_TEB InitialTeb,
|
|
||||||
PULONG_PTR StackReserve,
|
|
||||||
PULONG_PTR StackCommit
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PVOID pStackLowest = NULL;
|
|
||||||
ULONG_PTR nSize = 0;
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
|
|
||||||
if(StackReserve == NULL || StackCommit == NULL)
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
/* FIXME: no SEH, no guard pages */
|
|
||||||
*StackCommit = *StackReserve;
|
|
||||||
|
|
||||||
InitialTeb->StackBase = NULL;
|
|
||||||
InitialTeb->StackLimit = NULL;
|
|
||||||
InitialTeb->StackCommit = NULL;
|
|
||||||
InitialTeb->StackCommitMax = NULL;
|
|
||||||
InitialTeb->StackReserved = NULL;
|
|
||||||
|
|
||||||
/* FIXME: this code assumes a stack growing downwards */
|
|
||||||
/* fixed stack */
|
|
||||||
if(*StackCommit == *StackReserve)
|
|
||||||
{
|
|
||||||
DPRINT("Fixed stack\n");
|
|
||||||
|
|
||||||
InitialTeb->StackLimit = NULL;
|
|
||||||
|
|
||||||
/* allocate the stack */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->StackLimit),
|
|
||||||
0,
|
|
||||||
StackReserve,
|
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
|
|
||||||
/* store the highest (first) address of the stack */
|
|
||||||
InitialTeb->StackBase =
|
|
||||||
(PUCHAR)(InitialTeb->StackLimit) + *StackReserve;
|
|
||||||
}
|
|
||||||
/* expandable stack */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ULONG_PTR nGuardSize = PAGE_SIZE;
|
|
||||||
PVOID pGuardBase;
|
|
||||||
|
|
||||||
DPRINT("Expandable stack\n");
|
|
||||||
|
|
||||||
InitialTeb->StackLimit = NULL;
|
|
||||||
InitialTeb->StackBase = NULL;
|
|
||||||
InitialTeb->StackReserved = NULL;
|
|
||||||
|
|
||||||
/* reserve the stack */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->StackReserved),
|
|
||||||
0,
|
|
||||||
StackReserve,
|
|
||||||
MEM_RESERVE,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) return nErrCode;
|
|
||||||
|
|
||||||
DPRINT("Reserved %08X bytes\n", *StackReserve);
|
|
||||||
|
|
||||||
/* expandable stack base - the highest address of the stack */
|
|
||||||
InitialTeb->StackCommit =
|
|
||||||
(PUCHAR)(InitialTeb->StackReserved) + *StackReserve;
|
|
||||||
|
|
||||||
/* expandable stack limit - the lowest committed address of the stack */
|
|
||||||
InitialTeb->StackCommitMax =
|
|
||||||
(PUCHAR)(InitialTeb->StackCommit) - *StackCommit;
|
|
||||||
|
|
||||||
DPRINT("Stack commit %p\n", InitialTeb->StackCommit);
|
|
||||||
DPRINT("Stack commit max %p\n", InitialTeb->StackCommitMax);
|
|
||||||
|
|
||||||
/* commit as much stack as requested */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&(InitialTeb->StackCommitMax),
|
|
||||||
0,
|
|
||||||
StackCommit,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
|
||||||
|
|
||||||
DPRINT("Stack commit max %p\n", InitialTeb->StackCommitMax);
|
|
||||||
|
|
||||||
pGuardBase = (PUCHAR)(InitialTeb->StackCommitMax) - PAGE_SIZE;
|
|
||||||
|
|
||||||
DPRINT("Guard base %p\n", InitialTeb->StackCommit);
|
|
||||||
|
|
||||||
/* set up the guard page */
|
|
||||||
nErrCode = NtAllocateVirtualMemory
|
|
||||||
(
|
|
||||||
ProcessHandle,
|
|
||||||
&pGuardBase,
|
|
||||||
0,
|
|
||||||
&nGuardSize,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE | PAGE_GUARD
|
|
||||||
);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
|
||||||
|
|
||||||
DPRINT("Guard base %p\n", InitialTeb->StackCommit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
|
||||||
/* cleanup in case of failure */
|
|
||||||
l_Cleanup:
|
|
||||||
if(InitialTeb->StackLimit)
|
|
||||||
pStackLowest = InitialTeb->StackLimit;
|
|
||||||
else if(InitialTeb->StackReserved)
|
|
||||||
pStackLowest = InitialTeb->StackReserved;
|
|
||||||
|
|
||||||
/* free the stack, if it was allocated */
|
|
||||||
if(pStackLowest != NULL)
|
|
||||||
NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE);
|
|
||||||
|
|
||||||
return nErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS INIT_FUNCTION
|
|
||||||
LdrLoadInitialProcess(PHANDLE ProcessHandle,
|
LdrLoadInitialProcess(PHANDLE ProcessHandle,
|
||||||
PHANDLE ThreadHandle)
|
PHANDLE ThreadHandle)
|
||||||
{
|
{
|
||||||
SECTION_IMAGE_INFORMATION Sii;
|
|
||||||
UNICODE_STRING ImagePath;
|
UNICODE_STRING ImagePath;
|
||||||
HANDLE SectionHandle;
|
|
||||||
CONTEXT Context;
|
|
||||||
INITIAL_TEB InitialTeb;
|
|
||||||
ULONG_PTR nStackReserve = 0;
|
|
||||||
ULONG_PTR nStackCommit = 0;
|
|
||||||
PVOID pStackLowest;
|
|
||||||
PVOID pStackBase;
|
|
||||||
ULONG ResultLength;
|
|
||||||
PVOID ImageBaseAddress;
|
|
||||||
ULONG InitialStack[5];
|
|
||||||
HANDLE SystemProcessHandle;
|
HANDLE SystemProcessHandle;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PRTL_USER_PROCESS_PARAMETERS Params=NULL;
|
||||||
|
RTL_PROCESS_INFO Info;
|
||||||
|
|
||||||
/* Get the absolute path to smss.exe. */
|
/* Get the absolute path to smss.exe. */
|
||||||
RtlRosInitUnicodeStringFromLiteral(&ImagePath,
|
RtlRosInitUnicodeStringFromLiteral(&ImagePath,
|
||||||
L"\\SystemRoot\\system32\\smss.exe");
|
L"\\SystemRoot\\system32\\smss.exe");
|
||||||
|
|
||||||
/* Map process image */
|
|
||||||
Status = LdrpMapProcessImage(&SectionHandle,
|
|
||||||
&ImagePath);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("LdrpMapImage() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get information about the process image. */
|
Status = ObCreateHandle(
|
||||||
Status = NtQuerySection(SectionHandle,
|
PsGetCurrentProcess(),
|
||||||
SectionImageInformation,
|
|
||||||
&Sii,
|
|
||||||
sizeof(Sii),
|
|
||||||
&ResultLength);
|
|
||||||
if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
|
|
||||||
{
|
|
||||||
DPRINT("ZwQuerySection failed (Status %X)\n", Status);
|
|
||||||
NtClose(ProcessHandle);
|
|
||||||
NtClose(SectionHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ObCreateHandle(PsGetCurrentProcess(),
|
|
||||||
PsInitialSystemProcess,
|
PsInitialSystemProcess,
|
||||||
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
|
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
|
||||||
FALSE,
|
FALSE,
|
||||||
&SystemProcessHandle);
|
&SystemProcessHandle
|
||||||
|
);
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to create a handle for the system process!\n");
|
DPRINT1("Failed to create a handle for the system process!\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Status = RtlCreateProcessParameters(
|
||||||
|
&Params,
|
||||||
|
&ImagePath,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create ppb!\n");
|
||||||
|
ZwClose(SystemProcessHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DPRINT("Creating process\n");
|
DPRINT("Creating process\n");
|
||||||
Status = NtCreateProcess(ProcessHandle,
|
|
||||||
PROCESS_ALL_ACCESS,
|
Status = RtlCreateUserProcess(
|
||||||
|
&ImagePath,
|
||||||
|
OBJ_CASE_INSENSITIVE, //Valid are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
|
||||||
|
Params,
|
||||||
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
SystemProcessHandle,
|
SystemProcessHandle,
|
||||||
FALSE,
|
FALSE,
|
||||||
SectionHandle,
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL,
|
||||||
NtClose(SectionHandle);
|
&Info
|
||||||
NtClose(SystemProcessHandle);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtCreateProcess() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create process environment */
|
|
||||||
DPRINT("Creating the process environment\n");
|
|
||||||
Status = LdrpCreateProcessEnvironment(*ProcessHandle,
|
|
||||||
&ImagePath,
|
|
||||||
&ImageBaseAddress);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("LdrpCreateProcessEnvironment() failed (Status %lx)\n", Status);
|
|
||||||
NtClose(*ProcessHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
DPRINT("ImageBaseAddress: %p\n", ImageBaseAddress);
|
|
||||||
|
|
||||||
|
|
||||||
/* Calculate initial stack sizes */
|
|
||||||
if (Sii.StackReserve > 0x100000)
|
|
||||||
nStackReserve = Sii.StackReserve;
|
|
||||||
else
|
|
||||||
nStackReserve = 0x100000; /* 1MByte */
|
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
if (Sii.StackCommit > PAGE_SIZE)
|
|
||||||
nStackCommit = Sii.StackCommit;
|
|
||||||
else
|
|
||||||
nStackCommit = PAGE_SIZE;
|
|
||||||
#endif
|
|
||||||
nStackCommit = nStackReserve - PAGE_SIZE;
|
|
||||||
|
|
||||||
DPRINT("StackReserve 0x%lX StackCommit 0x%lX\n",
|
|
||||||
nStackReserve, nStackCommit);
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the process stack */
|
|
||||||
Status = LdrpCreateStack
|
|
||||||
(
|
|
||||||
*ProcessHandle,
|
|
||||||
&InitialTeb,
|
|
||||||
&nStackReserve,
|
|
||||||
&nStackCommit
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ZwClose(SystemProcessHandle);
|
||||||
|
RtlDestroyProcessParameters(Params);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("Failed to write initial stack.\n");
|
DPRINT1("NtCreateProcess() failed (Status %lx)\n", Status);
|
||||||
NtClose(ProcessHandle);
|
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(InitialTeb.StackBase && InitialTeb.StackLimit)
|
ZwResumeThread(Info.ThreadHandle, NULL);
|
||||||
{
|
|
||||||
pStackBase = InitialTeb.StackBase;
|
|
||||||
pStackLowest = InitialTeb.StackLimit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pStackBase = InitialTeb.StackCommit;
|
|
||||||
pStackLowest = InitialTeb.StackReserved;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("pStackBase = %p\n", pStackBase);
|
*ProcessHandle = Info.ProcessHandle;
|
||||||
DPRINT("pStackLowest = %p\n", pStackLowest);
|
*ThreadHandle= Info.ThreadHandle;
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize context to point to LdrStartup
|
|
||||||
*/
|
|
||||||
#if defined(_M_IX86)
|
|
||||||
memset(&Context,0,sizeof(CONTEXT));
|
|
||||||
Context.ContextFlags = CONTEXT_FULL;
|
|
||||||
Context.FloatSave.ControlWord = 0xffff037f;
|
|
||||||
Context.FloatSave.StatusWord = 0xffff0000;
|
|
||||||
Context.FloatSave.TagWord = 0xffffffff;
|
|
||||||
Context.FloatSave.DataSelector = 0xffff0000;
|
|
||||||
Context.Eip = (ULONG_PTR)((char*)ImageBaseAddress + (ULONG_PTR)Sii.EntryPoint);
|
|
||||||
Context.SegCs = USER_CS;
|
|
||||||
Context.SegDs = USER_DS;
|
|
||||||
Context.SegEs = USER_DS;
|
|
||||||
Context.SegFs = TEB_SELECTOR;
|
|
||||||
Context.SegGs = USER_DS;
|
|
||||||
Context.SegSs = USER_DS;
|
|
||||||
Context.EFlags = 0x202;
|
|
||||||
Context.Esp = (ULONG_PTR)pStackBase - 20;
|
|
||||||
#else
|
|
||||||
#error Unsupported architecture
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write in the initial stack.
|
|
||||||
*/
|
|
||||||
InitialStack[0] = 0;
|
|
||||||
InitialStack[1] = PEB_BASE;
|
|
||||||
Status = NtWriteVirtualMemory(*ProcessHandle,
|
|
||||||
(PVOID)Context.Esp,
|
|
||||||
InitialStack,
|
|
||||||
sizeof(InitialStack),
|
|
||||||
&ResultLength);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ULONG_PTR nSize = 0;
|
|
||||||
|
|
||||||
DPRINT("Failed to write initial stack.\n");
|
|
||||||
|
|
||||||
NtFreeVirtualMemory(*ProcessHandle,
|
|
||||||
pStackLowest,
|
|
||||||
&nSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
NtClose(*ProcessHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create initial thread */
|
|
||||||
DPRINT("Creating thread for initial process\n");
|
|
||||||
Status = NtCreateThread(ThreadHandle,
|
|
||||||
THREAD_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
*ProcessHandle,
|
|
||||||
NULL,
|
|
||||||
&Context,
|
|
||||||
&InitialTeb,
|
|
||||||
FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ULONG_PTR nSize = 0;
|
|
||||||
|
|
||||||
DPRINT("NtCreateThread() failed (Status %lx)\n", Status);
|
|
||||||
|
|
||||||
NtFreeVirtualMemory(*ProcessHandle,
|
|
||||||
pStackLowest,
|
|
||||||
&nSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
|
|
||||||
NtClose(*ProcessHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Process created successfully\n");
|
DPRINT("Process created successfully\n");
|
||||||
|
|
||||||
|
|
|
@ -480,9 +480,10 @@ CsrpRunWinlogon (ULONG argc, PWSTR* argv)
|
||||||
RtlDestroyProcessParameters (ProcessParameters);
|
RtlDestroyProcessParameters (ProcessParameters);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
|
DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
|
||||||
__FUNCTION__, Status);
|
__FUNCTION__, Status);
|
||||||
}
|
}
|
||||||
|
ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ SmCreateUserProcess (LPWSTR ImagePath,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NtResumeThread(pProcessInfo->ThreadHandle, NULL);
|
ZwResumeThread(pProcessInfo->ThreadHandle, NULL);
|
||||||
|
|
||||||
|
|
||||||
/* Wait for process termination */
|
/* Wait for process termination */
|
||||||
|
|
Loading…
Reference in a new issue