mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 17:52:56 +00:00
Second part of patch, implements the new RTL functions which will be used (not used by kernel yet).
- RtlCreateUserProcess: * Created RtlpInitEnvironment to manage Environment Block creation. Rougly based on old KlInitPeb code but with some optimizations. * Don't ignore Process Security Descriptor if one was specified. * Don't ignore ZeroBits, get correct entrypoint, and don't assume PEB address. * Don't close handle of section before closing process handle on failure. * Support new undocumented flag which pre-allocates 1MB of memory for Native Processes * FIXME: Hande duplication should be done, but wasn't and still isn't. - RtlpCreateUserStack: * New function to create a stack for a Thread, similar to BasepCreateStack but has some differences related to StackCommit/StackReserve. * Also create Guard Page - RtlpFreeUserStack: * Undoes what the function above does, in case of failure in code using it. - RtlCreateUserThread: * Use the new functions instead of rosrtl. - RtlInitializeContext: * New function similar to BasepInitializeContext but; > Uses a single entrypoint, not many possible thunks like Kernel32 (no need) > The starting EFLAGS is Interrupts Enabled, not IOPL 3. > We don't initialize the same Context Flags > The initial context registers are different - RtlFreeUserThreadStack * Don't assume the TEB address - RtlExitUserThread * Remove deprecated stack-switching semantics and use new TEB flag to tell the Kernel to deallocate the stack for us. svn path=/trunk/; revision=16542
This commit is contained in:
parent
36a1230e2b
commit
e6523bb71e
5 changed files with 611 additions and 350 deletions
|
@ -16,7 +16,7 @@
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
#include <rosrtl/thread.h>
|
#include <rosrtl/thread.h>
|
||||||
|
|
||||||
//#define NDEBUG
|
#define NDEBUG
|
||||||
#include "../include/debug.h"
|
#include "../include/debug.h"
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
@ -1378,11 +1378,11 @@ CreateProcessW(LPCWSTR lpApplicationName,
|
||||||
* Create the thread for the kernel
|
* Create the thread for the kernel
|
||||||
*/
|
*/
|
||||||
DPRINT("Creating thread for process (EntryPoint = 0x%.08x)\n",
|
DPRINT("Creating thread for process (EntryPoint = 0x%.08x)\n",
|
||||||
(PVOID)((ULONG_PTR)ImageBaseAddress + (ULONG_PTR)Sii.TransferAddress));
|
Sii.TransferAddress);
|
||||||
hThread = KlCreateFirstThread(hProcess,
|
hThread = KlCreateFirstThread(hProcess,
|
||||||
lpThreadAttributes,
|
lpThreadAttributes,
|
||||||
&Sii,
|
&Sii,
|
||||||
(PVOID)((ULONG_PTR)ImageBaseAddress + (ULONG_PTR)Sii.TransferAddress),
|
Sii.TransferAddress,
|
||||||
dwCreationFlags,
|
dwCreationFlags,
|
||||||
&lpProcessInformation->dwThreadId);
|
&lpProcessInformation->dwThreadId);
|
||||||
if (hThread == NULL)
|
if (hThread == NULL)
|
||||||
|
|
|
@ -90,4 +90,19 @@ RtlGetVersion(RTL_OSVERSIONINFOW *Info)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
RtlExitUserThread(NTSTATUS Status)
|
||||||
|
{
|
||||||
|
/* Call the Loader and tell him to notify the DLLs */
|
||||||
|
LdrShutdownThread();
|
||||||
|
|
||||||
|
/* Shut us down */
|
||||||
|
NtCurrentTeb()->FreeStackOnTermination = TRUE;
|
||||||
|
NtTerminateThread(NtCurrentThread(), Status);
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -16,51 +16,38 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* INTERNAL FUNCTIONS *******************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
static NTSTATUS
|
STDCALL
|
||||||
RtlpMapFile(PUNICODE_STRING ImageFileName,
|
RtlpMapFile(PUNICODE_STRING ImageFileName,
|
||||||
PRTL_USER_PROCESS_PARAMETERS Ppb,
|
|
||||||
ULONG Attributes,
|
ULONG Attributes,
|
||||||
PHANDLE Section)
|
PHANDLE Section)
|
||||||
{
|
{
|
||||||
HANDLE hFile;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
HANDLE hFile = NULL;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
hFile = NULL;
|
/* Open the Image File */
|
||||||
|
|
||||||
RtlDeNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
/* DbgPrint("ImagePathName 0x%p\n", Ppb->ImagePathName.Buffer); */
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
ImageFileName,
|
ImageFileName,
|
||||||
Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
|
Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
|
||||||
NULL,
|
NULL,
|
||||||
SecurityDescriptor);
|
NULL);
|
||||||
|
|
||||||
RtlNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to open the executable
|
|
||||||
*/
|
|
||||||
|
|
||||||
Status = ZwOpenFile(&hFile,
|
Status = ZwOpenFile(&hFile,
|
||||||
SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
|
SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
FILE_SHARE_DELETE | FILE_SHARE_READ,
|
FILE_SHARE_DELETE | FILE_SHARE_READ,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Failed to read image file from disk\n");
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now create a section for this image */
|
||||||
Status = ZwCreateSection(Section,
|
Status = ZwCreateSection(Section,
|
||||||
SECTION_ALL_ACCESS,
|
SECTION_ALL_ACCESS,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -68,124 +55,122 @@ RtlpMapFile(PUNICODE_STRING ImageFileName,
|
||||||
PAGE_EXECUTE,
|
PAGE_EXECUTE,
|
||||||
SEC_IMAGE,
|
SEC_IMAGE,
|
||||||
hFile);
|
hFile);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create section for image file\n");
|
||||||
|
}
|
||||||
|
|
||||||
ZwClose(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;
|
return Status;
|
||||||
}
|
}
|
||||||
EnvSize = MemInfo.RegionSize;
|
|
||||||
}
|
|
||||||
DPRINT("EnvironmentSize %ld\n", EnvSize);
|
|
||||||
|
|
||||||
/* allocate and initialize new environment block */
|
/* FUNCTIONS ****************************************************************/
|
||||||
if (EnvSize != 0)
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlpInitEnvironment(HANDLE ProcessHandle,
|
||||||
|
PPEB Peb,
|
||||||
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID BaseAddress = NULL;
|
||||||
|
ULONG EnviroSize;
|
||||||
|
ULONG Size;
|
||||||
|
PWCHAR Environment = 0;
|
||||||
|
|
||||||
|
DPRINT("RtlpInitEnvironment (hProcess: %lx, Peb: %p Params: %p)\n",
|
||||||
|
ProcessHandle, Peb, ProcessParameters);
|
||||||
|
|
||||||
|
/* Give the caller 1MB if he requested it */
|
||||||
|
if (ProcessParameters->Flags & PPF_RESERVE_1MB)
|
||||||
|
{
|
||||||
|
/* Give 1MB starting at 0x4 */
|
||||||
|
BaseAddress = (PVOID)4;
|
||||||
|
EnviroSize = 1024 * 1024;
|
||||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
&EnvPtr,
|
&BaseAddress,
|
||||||
0,
|
0,
|
||||||
&EnvSize,
|
&EnviroSize,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to reserve 1MB of space \n");
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the end of the Enviroment Block */
|
||||||
|
if ((Environment = (PWCHAR)ProcessParameters->Environment))
|
||||||
|
{
|
||||||
|
while (*Environment++) while (*Environment++);
|
||||||
|
|
||||||
|
/* Calculate the size of the block */
|
||||||
|
EnviroSize = (ULONG)((ULONG_PTR)Environment -
|
||||||
|
(ULONG_PTR)ProcessParameters->Environment);
|
||||||
|
DPRINT("EnvironmentSize %ld\n", EnviroSize);
|
||||||
|
|
||||||
|
/* Allocate and Initialize new Environment Block */
|
||||||
|
Size = EnviroSize;
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&BaseAddress,
|
||||||
|
0,
|
||||||
|
&Size,
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
MEM_RESERVE | MEM_COMMIT,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Failed to allocate Environment Block\n");
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write the Environment Block */
|
||||||
ZwWriteVirtualMemory(ProcessHandle,
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
EnvPtr,
|
BaseAddress,
|
||||||
Ppb->Environment,
|
ProcessParameters->Environment,
|
||||||
EnvSize,
|
EnviroSize,
|
||||||
&BytesWritten);
|
NULL);
|
||||||
|
|
||||||
|
/* Save pointer */
|
||||||
|
ProcessParameters->Environment = BaseAddress;
|
||||||
}
|
}
|
||||||
DPRINT("EnvironmentPointer %p\n", EnvPtr);
|
|
||||||
|
|
||||||
/* create the PPB */
|
DPRINT("EnvironmentPointer %p\n", BaseAddress);
|
||||||
PpbBase = NULL;
|
DPRINT("Ppb->MaximumLength %x\n", ProcessParameters->MaximumLength);
|
||||||
PpbSize = Ppb->MaximumLength;
|
|
||||||
|
|
||||||
|
/* Now allocate space for the Parameter Block */
|
||||||
|
BaseAddress = NULL;
|
||||||
|
Size = ProcessParameters->MaximumLength;
|
||||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
&PpbBase,
|
&BaseAddress,
|
||||||
0,
|
0,
|
||||||
&PpbSize,
|
&Size,
|
||||||
MEM_RESERVE | MEM_COMMIT,
|
MEM_COMMIT,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Failed to allocate Parameter Block\n");
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
|
/* Write the Parameter Block */
|
||||||
|
|
||||||
/* write process parameters block*/
|
|
||||||
RtlDeNormalizeProcessParams (Ppb);
|
|
||||||
ZwWriteVirtualMemory(ProcessHandle,
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
PpbBase,
|
BaseAddress,
|
||||||
Ppb,
|
ProcessParameters,
|
||||||
Ppb->MaximumLength,
|
ProcessParameters->Length,
|
||||||
|
NULL);
|
||||||
|
|
||||||
&BytesWritten);
|
/* Write pointer to Parameter Block */
|
||||||
RtlNormalizeProcessParams (Ppb);
|
|
||||||
|
|
||||||
/* write pointer to environment */
|
|
||||||
Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
|
|
||||||
ZwWriteVirtualMemory(ProcessHandle,
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
(PVOID)((ULONG_PTR)PpbBase + Offset),
|
&Peb->ProcessParameters,
|
||||||
&EnvPtr,
|
&BaseAddress,
|
||||||
sizeof(EnvPtr),
|
sizeof(BaseAddress),
|
||||||
&BytesWritten);
|
NULL);
|
||||||
|
|
||||||
/* write pointer to process parameter block */
|
/* Return */
|
||||||
Offset = FIELD_OFFSET(PEB, ProcessParameters);
|
return STATUS_SUCCESS;
|
||||||
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
|
* @implemented
|
||||||
*
|
*
|
||||||
|
@ -200,9 +185,9 @@ static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
|
||||||
*
|
*
|
||||||
* -Gunnar
|
* -Gunnar
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
RtlCreateUserProcess(
|
STDCALL
|
||||||
IN PUNICODE_STRING ImageFileName,
|
RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName,
|
||||||
IN ULONG Attributes,
|
IN ULONG Attributes,
|
||||||
IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
||||||
IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
|
IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
|
||||||
|
@ -211,35 +196,58 @@ RtlCreateUserProcess(
|
||||||
IN BOOLEAN InheritHandles,
|
IN BOOLEAN InheritHandles,
|
||||||
IN HANDLE DebugPort OPTIONAL,
|
IN HANDLE DebugPort OPTIONAL,
|
||||||
IN HANDLE ExceptionPort OPTIONAL,
|
IN HANDLE ExceptionPort OPTIONAL,
|
||||||
OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo
|
OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
HANDLE hSection;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
HANDLE hSection;
|
||||||
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
|
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
|
||||||
ULONG retlen;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
SECTION_IMAGE_INFORMATION Sii;
|
|
||||||
ULONG ResultLength;
|
|
||||||
PVOID ImageBaseAddress;
|
|
||||||
|
|
||||||
DPRINT("RtlCreateUserProcess\n");
|
DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
|
||||||
|
|
||||||
|
/* Map and Load the File */
|
||||||
Status = RtlpMapFile(ImageFileName,
|
Status = RtlpMapFile(ImageFileName,
|
||||||
ProcessParameters,
|
|
||||||
Attributes,
|
Attributes,
|
||||||
&hSection);
|
&hSection);
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not map process image\n");
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean out the CurDir Handle if we won't use it */
|
||||||
|
if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
|
||||||
|
|
||||||
|
/* Use us as parent if none other specified */
|
||||||
|
if (!ParentProcess) ParentProcess = NtCurrentProcess();
|
||||||
|
|
||||||
|
/* Initialize the Object Attributes */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
ProcessSecurityDescriptor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new process
|
* If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
|
||||||
|
* watch of WindowsSS
|
||||||
*/
|
*/
|
||||||
if (ParentProcess == NULL)
|
if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) &&
|
||||||
ParentProcess = NtCurrentProcess();
|
(wcsstr(ImageFileName->Buffer, L"csrss")))
|
||||||
|
{
|
||||||
Status = ZwCreateProcess(&(ProcessInfo->ProcessHandle),
|
UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS");
|
||||||
PROCESS_ALL_ACCESS,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&DebugString,
|
||||||
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
|
ProcessSecurityDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create Kernel Process Object */
|
||||||
|
Status = ZwCreateProcess(&ProcessInfo->ProcessHandle,
|
||||||
|
PROCESS_ALL_ACCESS,
|
||||||
|
&ObjectAttributes,
|
||||||
ParentProcess,
|
ParentProcess,
|
||||||
InheritHandles,
|
InheritHandles,
|
||||||
hSection,
|
hSection,
|
||||||
|
@ -247,67 +255,66 @@ RtlCreateUserProcess(
|
||||||
ExceptionPort);
|
ExceptionPort);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Could not create Kernel Process Object\n");
|
||||||
ZwClose(hSection);
|
ZwClose(hSection);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Get some information on the image */
|
||||||
* Get some information about the process
|
Status = ZwQuerySection(hSection,
|
||||||
*/
|
SectionImageInformation,
|
||||||
|
&ProcessInfo->ImageInformation,
|
||||||
|
sizeof(SECTION_IMAGE_INFORMATION),
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not query Section Info\n");
|
||||||
|
ZwClose(ProcessInfo->ProcessHandle);
|
||||||
|
ZwClose(hSection);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get some information about the process */
|
||||||
ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
|
ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
|
||||||
ProcessBasicInformation,
|
ProcessBasicInformation,
|
||||||
&ProcessBasicInfo,
|
&ProcessBasicInfo,
|
||||||
sizeof(ProcessBasicInfo),
|
sizeof(ProcessBasicInfo),
|
||||||
&retlen);
|
NULL);
|
||||||
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.MaximumStackSize,
|
|
||||||
Sii.CommittedStackSize,
|
|
||||||
(PVOID)((ULONG_PTR)ImageBaseAddress + (ULONG_PTR)Sii.TransferAddress),
|
|
||||||
(PVOID)PEB_BASE,
|
|
||||||
&ProcessInfo->ThreadHandle,
|
|
||||||
&ProcessInfo->ClientId
|
|
||||||
);
|
|
||||||
|
|
||||||
ZwClose(hSection);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("Failed to create thread\n");
|
DPRINT1("Could not query Process Info\n");
|
||||||
|
ZwClose(ProcessInfo->ProcessHandle);
|
||||||
|
ZwClose(hSection);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
/* Create Process Environment */
|
||||||
|
RtlpInitEnvironment(ProcessInfo->ProcessHandle,
|
||||||
|
ProcessBasicInfo.PebBaseAddress,
|
||||||
|
ProcessParameters);
|
||||||
|
|
||||||
|
/* Create the first Thread */
|
||||||
|
Status = RtlCreateUserThread(ProcessInfo->ProcessHandle,
|
||||||
|
ThreadSecurityDescriptor,
|
||||||
|
TRUE,
|
||||||
|
ProcessInfo->ImageInformation.ZeroBits,
|
||||||
|
ProcessInfo->ImageInformation.MaximumStackSize,
|
||||||
|
ProcessInfo->ImageInformation.CommittedStackSize,
|
||||||
|
ProcessInfo->ImageInformation.TransferAddress,
|
||||||
|
ProcessBasicInfo.PebBaseAddress,
|
||||||
|
&ProcessInfo->ThreadHandle,
|
||||||
|
&ProcessInfo->ClientId);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not Create Thread\n");
|
||||||
|
ZwClose(ProcessInfo->ProcessHandle);
|
||||||
|
ZwClose(hSection); /* Don't try to optimize this on top! */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close the Section Handle and return */
|
||||||
|
ZwClose(hSection);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -3,35 +3,176 @@
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* PURPOSE: Rtl user thread functions
|
* PURPOSE: Rtl user thread functions
|
||||||
* FILE: lib/ntdll/rtl/thread.c
|
* FILE: lib/ntdll/rtl/thread.c
|
||||||
* PROGRAMER: Eric Kohl
|
* PROGRAMERS:
|
||||||
* REVISION HISTORY:
|
* Alex Ionescu (alex@relsoft.net)
|
||||||
* 09/07/99: Created
|
* Eric Kohl
|
||||||
* 09/10/99: Cleanup and full stack support.
|
* KJK::Hyperion
|
||||||
* 25/04/03: Near rewrite. Made code more readable, replaced
|
|
||||||
* INITIAL_TEB with USER_STACK, added support for
|
|
||||||
* fixed-size stacks
|
|
||||||
* 28/04/03: Moved all code to a new statically linked
|
|
||||||
* library (ROSRTL) so it can be shared with
|
|
||||||
* kernel32.dll without exporting non-standard
|
|
||||||
* functions from ntdll.dll
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "rtl.h"
|
#include "rtl.h"
|
||||||
#include <rosrtl/thread.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS *******************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlpCreateUserStack(HANDLE hProcess,
|
||||||
|
ULONG StackReserve,
|
||||||
|
ULONG StackCommit,
|
||||||
|
ULONG StackZeroBits,
|
||||||
|
PINITIAL_TEB InitialTeb)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
||||||
|
PIMAGE_NT_HEADERS Headers;
|
||||||
|
ULONG_PTR Stack = 0;
|
||||||
|
BOOLEAN UseGuard = FALSE;
|
||||||
|
|
||||||
|
DPRINT("RtlpCreateUserStack\n");
|
||||||
|
|
||||||
|
/* Get some memory information */
|
||||||
|
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||||||
|
&SystemBasicInfo,
|
||||||
|
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failure to query system info\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the Image Settings if we are dealing with the current Process */
|
||||||
|
if (hProcess == NtCurrentProcess())
|
||||||
|
{
|
||||||
|
/* Get the Image Headers */
|
||||||
|
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||||
|
DPRINT("Headers: %p\n", Headers);
|
||||||
|
|
||||||
|
/* If we didn't get the parameters, find them ourselves */
|
||||||
|
StackReserve = (StackReserve) ?
|
||||||
|
StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
|
||||||
|
StackCommit = (StackCommit) ?
|
||||||
|
StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use the System Settings if needed */
|
||||||
|
StackReserve = (StackReserve) ? StackReserve :
|
||||||
|
SystemBasicInfo.AllocationGranularity;
|
||||||
|
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Align everything to Page Size */
|
||||||
|
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
|
||||||
|
StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
|
||||||
|
#if 1 // FIXME: Remove once Guard Page support is here
|
||||||
|
StackCommit = StackReserve;
|
||||||
|
#endif
|
||||||
|
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
|
||||||
|
|
||||||
|
/* Reserve memory for the stack */
|
||||||
|
Status = ZwAllocateVirtualMemory(hProcess,
|
||||||
|
(PVOID*)&Stack,
|
||||||
|
StackZeroBits,
|
||||||
|
&StackReserve,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failure to reserve stack\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now set up some basic Initial TEB Parameters */
|
||||||
|
InitialTeb->AllocatedStackBase = (PVOID)Stack;
|
||||||
|
InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
|
||||||
|
|
||||||
|
/* Update the Stack Position */
|
||||||
|
Stack += StackReserve - StackCommit;
|
||||||
|
|
||||||
|
/* Check if we will need a guard page */
|
||||||
|
if (StackReserve > StackCommit)
|
||||||
|
{
|
||||||
|
Stack -= SystemBasicInfo.PageSize;
|
||||||
|
StackCommit += SystemBasicInfo.PageSize;
|
||||||
|
UseGuard = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %p, StackCommit: %lx\n",
|
||||||
|
InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack,
|
||||||
|
StackCommit);
|
||||||
|
|
||||||
|
/* Allocate memory for the stack */
|
||||||
|
Status = ZwAllocateVirtualMemory(hProcess,
|
||||||
|
(PVOID*)&Stack,
|
||||||
|
0,
|
||||||
|
&StackCommit,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failure to allocate stack\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now set the current Stack Limit */
|
||||||
|
InitialTeb->StackLimit = (PVOID)Stack;
|
||||||
|
DPRINT("StackLimit: %p\n", Stack);
|
||||||
|
|
||||||
|
/* Create a guard page */
|
||||||
|
if (UseGuard)
|
||||||
|
{
|
||||||
|
ULONG GuardPageSize = SystemBasicInfo.PageSize;
|
||||||
|
ULONG Dummy;
|
||||||
|
|
||||||
|
/* Attempt maximum space possible */
|
||||||
|
Status = ZwProtectVirtualMemory(hProcess,
|
||||||
|
(PVOID*)&Stack,
|
||||||
|
&GuardPageSize,
|
||||||
|
PAGE_GUARD | PAGE_READWRITE,
|
||||||
|
&Dummy);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failure to create guard page\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the Stack Limit keeping in mind the Guard Page */
|
||||||
|
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit -
|
||||||
|
GuardPageSize);
|
||||||
|
DPRINT1("StackLimit: %p\n", Stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are done! */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
RtlpFreeUserStack(HANDLE hProcess,
|
||||||
|
PINITIAL_TEB InitialTeb)
|
||||||
|
{
|
||||||
|
ULONG Dummy = 0;
|
||||||
|
|
||||||
|
/* Free the Stack */
|
||||||
|
return ZwFreeVirtualMemory(hProcess,
|
||||||
|
&InitialTeb->AllocatedStackBase,
|
||||||
|
&Dummy,
|
||||||
|
MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@implemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL RtlCreateUserThread
|
NTSTATUS
|
||||||
(
|
STDCALL
|
||||||
HANDLE ProcessHandle,
|
RtlCreateUserThread(HANDLE ProcessHandle,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
BOOLEAN CreateSuspended,
|
BOOLEAN CreateSuspended,
|
||||||
LONG StackZeroBits,
|
LONG StackZeroBits,
|
||||||
|
@ -40,76 +181,171 @@ NTSTATUS STDCALL RtlCreateUserThread
|
||||||
PTHREAD_START_ROUTINE StartAddress,
|
PTHREAD_START_ROUTINE StartAddress,
|
||||||
PVOID Parameter,
|
PVOID Parameter,
|
||||||
PHANDLE ThreadHandle,
|
PHANDLE ThreadHandle,
|
||||||
PCLIENT_ID ClientId
|
PCLIENT_ID ClientId)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES oaThreadAttribs;
|
NTSTATUS Status;
|
||||||
|
HANDLE Handle;
|
||||||
|
CLIENT_ID ThreadCid;
|
||||||
|
INITIAL_TEB InitialTeb;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
CONTEXT Context;
|
||||||
|
|
||||||
InitializeObjectAttributes
|
DPRINT("RtlCreateUserThread: (hProcess: %lx, Suspended: %lx,"
|
||||||
(
|
"ZeroBits: %lx, StackReserve: %lx, StackCommit: %lx,"
|
||||||
&oaThreadAttribs,
|
"StartAddress: %p, Parameter: %lx)\n", ProcessHandle,
|
||||||
|
CreateSuspended, StackZeroBits, StackReserve, StackCommit,
|
||||||
|
StartAddress, Parameter);
|
||||||
|
|
||||||
|
/* First, we'll create the Stack */
|
||||||
|
Status = RtlpCreateUserStack(ProcessHandle,
|
||||||
|
StackReserve,
|
||||||
|
StackCommit,
|
||||||
|
StackZeroBits,
|
||||||
|
&InitialTeb);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failure to create User Stack\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, we'll set up the Initial Context */
|
||||||
|
RtlInitializeContext(ProcessHandle,
|
||||||
|
&Context,
|
||||||
|
Parameter,
|
||||||
|
StartAddress,
|
||||||
|
InitialTeb.StackBase);
|
||||||
|
|
||||||
|
/* We are now ready to create the Kernel Thread Object */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
SecurityDescriptor
|
SecurityDescriptor);
|
||||||
);
|
Status = ZwCreateThread(&Handle,
|
||||||
|
THREAD_ALL_ACCESS,
|
||||||
return RtlRosCreateUserThread
|
&ObjectAttributes,
|
||||||
(
|
|
||||||
ProcessHandle,
|
ProcessHandle,
|
||||||
&oaThreadAttribs,
|
&ThreadCid,
|
||||||
CreateSuspended,
|
&Context,
|
||||||
StackZeroBits,
|
&InitialTeb,
|
||||||
&StackReserve,
|
CreateSuspended);
|
||||||
&StackCommit,
|
if (!NT_SUCCESS(Status))
|
||||||
StartAddress,
|
{
|
||||||
ThreadHandle,
|
DPRINT1("Failure to create Thread\n");
|
||||||
ClientId,
|
|
||||||
1,
|
/* Free the stack */
|
||||||
(ULONG_PTR *)&Parameter
|
RtlpFreeUserStack(ProcessHandle, &InitialTeb);
|
||||||
);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Thread created: %lx\n", Handle);
|
||||||
|
if (ThreadHandle) *ThreadHandle = Handle;
|
||||||
|
if (ClientId) *ClientId = ThreadCid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success or the previous failure */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* FIXME: Should go in /i386
|
||||||
@implemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
VOID STDCALL
|
VOID
|
||||||
RtlInitializeContext(
|
STDCALL
|
||||||
IN HANDLE ProcessHandle,
|
RtlInitializeContext(IN HANDLE ProcessHandle,
|
||||||
OUT PCONTEXT ThreadContext,
|
OUT PCONTEXT ThreadContext,
|
||||||
IN PVOID ThreadStartParam OPTIONAL,
|
IN PVOID ThreadStartParam OPTIONAL,
|
||||||
IN PTHREAD_START_ROUTINE ThreadStartAddress,
|
IN PTHREAD_START_ROUTINE ThreadStartAddress,
|
||||||
IN PINITIAL_TEB InitialTeb)
|
IN PINITIAL_TEB InitialTeb)
|
||||||
{
|
{
|
||||||
RtlRosInitializeContext
|
DPRINT("RtlInitializeContext: (hProcess: %lx, ThreadContext: %p, Teb: %p\n",
|
||||||
(
|
ProcessHandle, ThreadContext, InitialTeb);
|
||||||
ProcessHandle,
|
|
||||||
ThreadContext,
|
/*
|
||||||
ThreadStartAddress,
|
* Set the Initial Registers
|
||||||
InitialTeb,
|
* This is based on NT's default values -- crazy apps might expect this...
|
||||||
1,
|
*/
|
||||||
(ULONG_PTR *)&ThreadStartParam
|
ThreadContext->Ebp = 0;
|
||||||
);
|
ThreadContext->Eax = 0;
|
||||||
|
ThreadContext->Ebx = 1;
|
||||||
|
ThreadContext->Ecx = 2;
|
||||||
|
ThreadContext->Edx = 3;
|
||||||
|
ThreadContext->Esi = 4;
|
||||||
|
ThreadContext->Edi = 5;
|
||||||
|
|
||||||
|
/* Set the Selectors */
|
||||||
|
ThreadContext->SegGs = 0;
|
||||||
|
ThreadContext->SegFs = TEB_SELECTOR;
|
||||||
|
ThreadContext->SegEs = USER_DS;
|
||||||
|
ThreadContext->SegDs = USER_DS;
|
||||||
|
ThreadContext->SegCs = USER_CS;
|
||||||
|
ThreadContext->SegSs = USER_DS;
|
||||||
|
|
||||||
|
/* Enable Interrupts */
|
||||||
|
ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */
|
||||||
|
|
||||||
|
/* Settings passed */
|
||||||
|
ThreadContext->Eip = (ULONG)ThreadStartAddress;
|
||||||
|
ThreadContext->Esp = (ULONG)InitialTeb;
|
||||||
|
|
||||||
|
/* Only the basic Context is initialized */
|
||||||
|
ThreadContext->ContextFlags = CONTEXT_CONTROL |
|
||||||
|
CONTEXT_INTEGER |
|
||||||
|
CONTEXT_SEGMENTS;
|
||||||
|
|
||||||
|
/* Set up ESP to the right value */
|
||||||
|
ThreadContext->Esp -= sizeof(PVOID);
|
||||||
|
ZwWriteVirtualMemory(ProcessHandle,
|
||||||
|
(PVOID)ThreadContext->Esp,
|
||||||
|
(PVOID)&ThreadStartParam,
|
||||||
|
sizeof(PVOID),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Push it down one more notch for RETEIP */
|
||||||
|
ThreadContext->Esp -= sizeof(PVOID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@implemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL RtlFreeUserThreadStack
|
VOID
|
||||||
(
|
STDCALL
|
||||||
HANDLE ProcessHandle,
|
RtlFreeUserThreadStack(HANDLE ProcessHandle,
|
||||||
HANDLE ThreadHandle
|
HANDLE ThreadHandle)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return RtlRosFreeUserThreadStack(ProcessHandle, ThreadHandle);
|
NTSTATUS Status;
|
||||||
|
THREAD_BASIC_INFORMATION ThreadBasicInfo;
|
||||||
|
ULONG Dummy, Size = 0;
|
||||||
|
PVOID StackLocation;
|
||||||
|
|
||||||
|
/* Query the Basic Info */
|
||||||
|
Status = NtQueryInformationThread(ThreadHandle,
|
||||||
|
ThreadBasicInformation,
|
||||||
|
&ThreadBasicInfo,
|
||||||
|
sizeof(THREAD_BASIC_INFORMATION),
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress)
|
||||||
|
{
|
||||||
|
DPRINT1("Could not query info, or TEB is NULL\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Get the deallocation stack */
|
||||||
@implemented
|
Status = NtReadVirtualMemory(ProcessHandle,
|
||||||
*/
|
&((PTEB)ThreadBasicInfo.TebBaseAddress)->
|
||||||
VOID STDCALL RtlExitUserThread(NTSTATUS Status)
|
DeallocationStack,
|
||||||
|
&StackLocation,
|
||||||
|
sizeof(PVOID),
|
||||||
|
&Dummy);
|
||||||
|
if (!NT_SUCCESS(Status) || !StackLocation)
|
||||||
{
|
{
|
||||||
RtlRosExitUserThread(Status);
|
DPRINT1("Could not read Deallocation Base\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free it */
|
||||||
|
NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -483,7 +483,10 @@ l_ReadHeaderFromFile:
|
||||||
ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, AddressOfEntryPoint));
|
ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, AddressOfEntryPoint));
|
||||||
|
|
||||||
if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
|
if(RTL_CONTAINS_FIELD(piohOptHeader, cbOptHeaderSize, AddressOfEntryPoint))
|
||||||
ImageSectionObject->EntryPoint = piohOptHeader->AddressOfEntryPoint;
|
{
|
||||||
|
ImageSectionObject->EntryPoint = piohOptHeader->ImageBase +
|
||||||
|
piohOptHeader->AddressOfEntryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfCode));
|
ASSERT(PEFMT_FIELDS_EQUAL(IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, SizeOfCode));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue