-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:
Gunnar Dalsnes 2005-04-02 00:18:46 +00:00
parent c8e0c8df83
commit 95daa63b61
10 changed files with 469 additions and 814 deletions

View file

@ -377,6 +377,21 @@ RemoveTailList(
#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
STDCALL
RtlAppendUnicodeToString (

View file

@ -23,7 +23,7 @@ TARGET_LFLAGS = -Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-nostartfiles -nostdlib
TARGET_SDKLIBS = rosrtl.a rtl.a string.a
TARGET_SDKLIBS = rtl.a rosrtl.a string.a
TARGET_GCCLIBS = gcc
@ -81,7 +81,6 @@ RTL_OBJECTS = \
rtl/rangelist.o \
rtl/resource.o \
rtl/teb.o \
rtl/thread.o \
rtl/timerqueue.o \
rtl/libsupp.o

View file

@ -23,30 +23,6 @@
/* 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
STDCALL
@ -55,273 +31,26 @@ RtlpCurrentPeb(VOID)
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
*/
NTSTATUS STDCALL
RtlCreateUserProcess(PUNICODE_STRING ImageFileName,
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)
VOID STDCALL
RtlAcquirePebLock(VOID)
{
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;
PPEB Peb = NtCurrentPeb ();
Peb->FastPebLockRoutine (Peb->FastPebLock);
}
/*
* Create a new process
*/
if (ParentProcess == NULL)
ParentProcess = NtCurrentProcess();
Status = NtCreateProcess(&(ProcessInfo->ProcessHandle),
PROCESS_ALL_ACCESS,
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);
/*
* @implemented
*/
VOID STDCALL
RtlReleasePebLock(VOID)
{
PPEB Peb = NtCurrentPeb ();
Peb->FastPebUnlockRoutine (Peb->FastPebLock);
}

View file

@ -14,25 +14,5 @@ PTEB STDCALL
_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 */

View file

@ -20,6 +20,8 @@ TARGET_OBJECTS = \
acl.o \
ppb.o \
bit.o \
thread.o \
process.o \
bitmap.o \
bootdata.o \
compress.o \

318
reactos/lib/rtl/process.c Normal file
View 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 */

View file

@ -18,7 +18,6 @@
/* INCLUDES *****************************************************************/
#define NTOS_MODE_USER
#include <ntos.h>
#define NDEBUG

View file

@ -11,540 +11,152 @@
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#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 *****************************************************************/
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
LdrpCreateProcessEnvironment(HANDLE ProcessHandle,
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
INIT_FUNCTION
NTSTATUS
LdrLoadInitialProcess(PHANDLE ProcessHandle,
PHANDLE ThreadHandle)
{
SECTION_IMAGE_INFORMATION Sii;
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;
NTSTATUS Status;
UNICODE_STRING ImagePath;
HANDLE SystemProcessHandle;
NTSTATUS Status;
PRTL_USER_PROCESS_PARAMETERS Params=NULL;
RTL_PROCESS_INFO Info;
/* Get the absolute path to smss.exe. */
RtlRosInitUnicodeStringFromLiteral(&ImagePath,
L"\\SystemRoot\\system32\\smss.exe");
/* Get the absolute path to smss.exe. */
RtlRosInitUnicodeStringFromLiteral(&ImagePath,
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 = NtQuerySection(SectionHandle,
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,
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
FALSE,
&SystemProcessHandle
);
Status = ObCreateHandle(PsGetCurrentProcess(),
PsInitialSystemProcess,
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
FALSE,
&SystemProcessHandle);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to create a handle for the system process!\n");
return Status;
}
Status = RtlCreateProcessParameters(
&Params,
&ImagePath,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to create a handle for the system process!\n");
DPRINT1("Failed to create ppb!\n");
ZwClose(SystemProcessHandle);
return Status;
}
DPRINT("Creating process\n");
Status = NtCreateProcess(ProcessHandle,
PROCESS_ALL_ACCESS,
NULL,
SystemProcessHandle,
FALSE,
SectionHandle,
NULL,
NULL);
NtClose(SectionHandle);
NtClose(SystemProcessHandle);
if (!NT_SUCCESS(Status))
{
DPRINT("NtCreateProcess() failed (Status %lx)\n", Status);
DPRINT("Creating process\n");
Status = RtlCreateUserProcess(
&ImagePath,
OBJ_CASE_INSENSITIVE, //Valid are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
Params,
NULL,
NULL,
SystemProcessHandle,
FALSE,
NULL,
NULL,
&Info
);
ZwClose(SystemProcessHandle);
RtlDestroyProcessParameters(Params);
if (!NT_SUCCESS(Status))
{
DPRINT1("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);
ZwResumeThread(Info.ThreadHandle, NULL);
*ProcessHandle = Info.ProcessHandle;
*ThreadHandle= Info.ThreadHandle;
/* Calculate initial stack sizes */
if (Sii.StackReserve > 0x100000)
nStackReserve = Sii.StackReserve;
else
nStackReserve = 0x100000; /* 1MByte */
DPRINT("Process created successfully\n");
/* 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
);
if (!NT_SUCCESS(Status))
{
DPRINT("Failed to write initial stack.\n");
NtClose(ProcessHandle);
return(Status);
}
if(InitialTeb.StackBase && InitialTeb.StackLimit)
{
pStackBase = InitialTeb.StackBase;
pStackLowest = InitialTeb.StackLimit;
}
else
{
pStackBase = InitialTeb.StackCommit;
pStackLowest = InitialTeb.StackReserved;
}
DPRINT("pStackBase = %p\n", pStackBase);
DPRINT("pStackLowest = %p\n", pStackLowest);
/*
* 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");
return(STATUS_SUCCESS);
return(STATUS_SUCCESS);
}
/* EOF */

View file

@ -480,9 +480,10 @@ CsrpRunWinlogon (ULONG argc, PWSTR* argv)
RtlDestroyProcessParameters (ProcessParameters);
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);
}
ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
return Status;
}

View file

@ -91,7 +91,7 @@ SmCreateUserProcess (LPWSTR ImagePath,
return Status;
}
NtResumeThread(pProcessInfo->ThreadHandle, NULL);
ZwResumeThread(pProcessInfo->ThreadHandle, NULL);
/* Wait for process termination */