__PdxSpawnPosixProcess() now initializes process parameters too. Almost working!

svn path=/trunk/; revision=2698
This commit is contained in:
KJK::Hyperion 2002-03-11 20:46:38 +00:00
parent 5306bd86fb
commit 65b82fb4d2

View file

@ -1,4 +1,4 @@
/* $Id: spawn.c,v 1.3 2002/03/10 17:09:46 hyperion Exp $ /* $Id: spawn.c,v 1.4 2002/03/11 20:46:38 hyperion Exp $
*/ */
/* /*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
@ -27,9 +27,10 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <pthread.h> #include <unistd.h>
#include <psx/debug.h> #include <psx/debug.h>
#include <psx/pdata.h> #include <psx/pdata.h>
#include <psx/spawn.h>
#include <psx/stdlib.h> #include <psx/stdlib.h>
NTSTATUS STDCALL __PdxSpawnPosixProcess NTSTATUS STDCALL __PdxSpawnPosixProcess
@ -42,22 +43,28 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
IN __PPDX_PDATA ProcessData IN __PPDX_PDATA ProcessData
) )
{ {
__PPDX_SERIALIZED_PDATA pspdProcessData; __PPDX_SERIALIZED_PDATA pspdProcessData;
IO_STATUS_BLOCK isbStatus; IO_STATUS_BLOCK isbStatus;
PROCESS_BASIC_INFORMATION pbiProcessInfo; PROCESS_BASIC_INFORMATION pbiProcessInfo;
ANSI_STRING strStartEntry; ANSI_STRING strStartEntry;
PVOID pStartAddress; PVOID pStartAddress;
INITIAL_TEB itInitialTeb; INITIAL_TEB itInitialTeb;
CONTEXT ctxThreadContext; PRTL_USER_PROCESS_PARAMETERS pppProcessParameters;
CLIENT_ID ciClientId; CONTEXT ctxThreadContext;
CLIENT_ID ciClientId;
NTSTATUS nErrCode; NTSTATUS nErrCode;
HANDLE hExeFile; HANDLE hExeFile;
HANDLE hExeImage; HANDLE hExeImage;
HANDLE hProcess; HANDLE hProcess;
HANDLE hThread; HANDLE hThread;
PVOID pDestBuffer; PVOID pPdataBuffer = 0;
PVOID pParamsBuffer = 0;
ULONG nDestBufferSize; ULONG nDestBufferSize;
ULONG nCurFilDesOffset; ULONG nCurFilDesOffset;
ULONG nVirtualSize;
ULONG nCommitSize;
PVOID pCommitBottom;
ULONG nOldProtect;
int i; int i;
/* STEP 1: map executable image in memory */ /* STEP 1: map executable image in memory */
@ -79,7 +86,7 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
return (nErrCode); return (nErrCode);
} }
/* 1.2: create a memory section for the file */ /* 1.2: create an image section for the file */
nErrCode = NtCreateSection nErrCode = NtCreateSection
( (
&hExeImage, &hExeImage,
@ -124,22 +131,31 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
return (nErrCode); return (nErrCode);
} }
/* STEP 3: write process environment */ /* STEP 3: write process environment and process parameters */
/* 3.1: serialize the process data for transfer */ /* 3.1: convert process data into process parameters */
__PdxProcessDataToProcessParameters
(
&pppProcessParameters,
ProcessData,
FileObjectAttributes->ObjectName
);
/* 3.2: serialize the process data for transfer */
/* FIXME: the serialized data can be allocated and written directly in the /* FIXME: the serialized data can be allocated and written directly in the
destination process */ destination process */
__PdxSerializeProcessData(ProcessData, &pspdProcessData); __PdxSerializeProcessData(ProcessData, &pspdProcessData);
/* 3.1.1: adjust some fields */ /* 3.2.1: adjust some fields */
pspdProcessData->ProcessData.Spawned = TRUE; pspdProcessData->ProcessData.Spawned = TRUE;
/* 3.2: allocate memory in the destination process */ /* 3.3: allocate memory in the destination process */
/* 3.3.1: process data */
nDestBufferSize = pspdProcessData->AllocSize; nDestBufferSize = pspdProcessData->AllocSize;
nErrCode = NtAllocateVirtualMemory nErrCode = NtAllocateVirtualMemory
( (
hProcess, hProcess,
&pDestBuffer, &pPdataBuffer,
0, 0,
&nDestBufferSize, &nDestBufferSize,
MEM_COMMIT, MEM_COMMIT,
@ -153,7 +169,27 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
goto undoPData; goto undoPData;
} }
/* 3.3: get pointer to the PEB */ /* 3.3.2: process parameters */
nDestBufferSize = pppProcessParameters->Length;
nErrCode = NtAllocateVirtualMemory
(
hProcess,
&pParamsBuffer,
0,
&nDestBufferSize,
MEM_COMMIT,
PAGE_READWRITE
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtAllocateVirtualMemory() failed with status 0x%08X\n", nErrCode);
goto undoPData;
}
/* 3.4: get pointer to the PEB */
nErrCode = NtQueryInformationProcess nErrCode = NtQueryInformationProcess
( (
hProcess, hProcess,
@ -170,12 +206,13 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
goto undoPData; goto undoPData;
} }
/* 3.4: write pointer to process data in the SubSystemData field of the PEB */ /* 3.5: write pointers in the PEB */
/* 3.5.1: process data */
nErrCode = NtWriteVirtualMemory nErrCode = NtWriteVirtualMemory
( (
hProcess, hProcess,
(PVOID)((ULONG)pbiProcessInfo.PebBaseAddress + offsetof(PEB, SubSystemData)), (PVOID)((ULONG)pbiProcessInfo.PebBaseAddress + offsetof(PEB, SubSystemData)),
&pDestBuffer, &pPdataBuffer,
sizeof(PVOID), sizeof(PVOID),
NULL NULL
); );
@ -187,11 +224,28 @@ NTSTATUS STDCALL __PdxSpawnPosixProcess
goto undoPData; goto undoPData;
} }
/* 3.5: write the process data */ /* 3.5.2: process parameters */
nErrCode = NtWriteVirtualMemory nErrCode = NtWriteVirtualMemory
( (
hProcess, hProcess,
pDestBuffer, (PVOID)((ULONG)pbiProcessInfo.PebBaseAddress + offsetof(PEB, ProcessParameters)),
&pParamsBuffer,
sizeof(PVOID),
NULL
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
goto undoPData;
}
/* 3.6: write the process data */
nErrCode = NtWriteVirtualMemory
(
hProcess,
pPdataBuffer,
pspdProcessData, pspdProcessData,
pspdProcessData->AllocSize, pspdProcessData->AllocSize,
NULL NULL
@ -207,9 +261,12 @@ undoPData:
MEM_RELEASE MEM_RELEASE
); );
/* destroy process parameters */
RtlDestroyProcessParameters(pppProcessParameters);
/* failure */ /* failure */
if(!NT_SUCCESS(nErrCode)) if(!NT_SUCCESS(nErrCode))
return (nErrCode); goto failProcess;
/* STEP 4: duplicate handles */ /* STEP 4: duplicate handles */
/* 4.1: handles in the structure itself */ /* 4.1: handles in the structure itself */
@ -219,7 +276,7 @@ undoPData:
NtCurrentProcess(), NtCurrentProcess(),
ProcessData->RootHandle, ProcessData->RootHandle,
hProcess, hProcess,
(PHANDLE)((ULONG)pDestBuffer + offsetof(__PDX_PDATA, RootHandle)), (PHANDLE)((ULONG)pPdataBuffer + offsetof(__PDX_PDATA, RootHandle)),
0, 0,
0, 0,
DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */ DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */
@ -260,28 +317,94 @@ undoPData:
ProcessData->FdTable.Descriptors[i].FileHandle, ProcessData->FdTable.Descriptors[i].FileHandle,
hProcess, hProcess,
(PHANDLE)( (PHANDLE)(
(ULONG)pDestBuffer + nCurFilDesOffset + offsetof(__fildes_t, FileHandle) (ULONG)pPdataBuffer + nCurFilDesOffset + offsetof(__fildes_t, FileHandle)
), ),
0, 0,
0, 0,
DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */ DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */
); );
/* failure */ /* failure */
if(!NT_SUCCESS(nErrCode)) if(!NT_SUCCESS(nErrCode))
{ {
ERR("NtDuplicateObject() failed with status 0x%08X\n", nErrCode); ERR("NtDuplicateObject() failed with status 0x%08X\n", nErrCode);
goto failProcess; goto failProcess;
} }
/* duplicate standard handles */
/* standard input */
if(i == STDIN_FILENO)
{
nErrCode = NtDuplicateObject
(
NtCurrentProcess(),
ProcessData->FdTable.Descriptors[i].FileHandle,
hProcess,
(PHANDLE)((ULONG)pParamsBuffer + offsetof(RTL_USER_PROCESS_PARAMETERS, InputHandle)),
0,
0,
DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtDuplicateObject() failed with status 0x%08X\n", nErrCode);
goto failProcess;
}
}
/* standard output */
else if(i == STDOUT_FILENO)
{
nErrCode = NtDuplicateObject
(
NtCurrentProcess(),
ProcessData->FdTable.Descriptors[i].FileHandle,
hProcess,
(PHANDLE)((ULONG)pParamsBuffer + offsetof(RTL_USER_PROCESS_PARAMETERS, OutputHandle)),
0,
0,
DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtDuplicateObject() failed with status 0x%08X\n", nErrCode);
goto failProcess;
}
}
/* standard error */
else if(i == STDERR_FILENO)
{
nErrCode = NtDuplicateObject
(
NtCurrentProcess(),
ProcessData->FdTable.Descriptors[i].FileHandle,
hProcess,
(PHANDLE)((ULONG)pParamsBuffer + offsetof(RTL_USER_PROCESS_PARAMETERS, ErrorHandle)),
0,
0,
DUPLICATE_SAME_ACCESS | 4 /* | DUPLICATE_SAME_ATTRIBUTES */ /* FIXME */
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtDuplicateObject() failed with status 0x%08X\n", nErrCode);
goto failProcess;
}
}
} }
/* STEP 5: create first thread */ /* STEP 5: create first thread */
/* 5.1: get thunk routine's address */ /* 5.1: get thunk routine's address */
RtlInitAnsiString(&strStartEntry, "LdrInitializeThunk"); RtlInitAnsiString(&strStartEntry, "LdrInitializeThunk");
#if 1
nErrCode = LdrGetProcedureAddress nErrCode = LdrGetProcedureAddress
( (
(PVOID)NTDLL_BASE, (PVOID)0x78460000, /* NTDLL_BASE */
&strStartEntry, &strStartEntry,
0, 0,
&pStartAddress &pStartAddress
@ -293,25 +416,22 @@ undoPData:
ERR("LdrGetProcedureAddress() failed with status 0x%08X\n", nErrCode); ERR("LdrGetProcedureAddress() failed with status 0x%08X\n", nErrCode);
goto failProcess; goto failProcess;
} }
#else
pStartAddress = LdrGetProcedureAddress;
#endif
/* 5.2: set up the initial TEB */ /* 5.2: set up the stack */
itInitialTeb.StackAllocate = NULL; itInitialTeb.StackAllocate = NULL;
nVirtualSize = 0x100000;
nCommitSize = 0x100000 - PAGESIZE;
/* FIXME: allow the caller to specify these values */ /* 5.2.1: reserve the stack */
itInitialTeb.StackReserve = 0x100000;
itInitialTeb.StackCommit = itInitialTeb.StackReserve - PAGESIZE;
/* guard page */
itInitialTeb.StackCommit += PAGESIZE;
/* 5.2.1: set up the stack */
/* 5.2.1.1: reserve the stack */
nErrCode = NtAllocateVirtualMemory nErrCode = NtAllocateVirtualMemory
( (
hProcess, hProcess,
&itInitialTeb.StackAllocate, &itInitialTeb.StackAllocate,
0, 0,
&itInitialTeb.StackReserve, &nVirtualSize,
MEM_RESERVE, MEM_RESERVE,
PAGE_READWRITE PAGE_READWRITE
); );
@ -324,18 +444,22 @@ undoPData:
} }
itInitialTeb.StackBase = itInitialTeb.StackBase =
(PVOID)((ULONG)itInitialTeb.StackAllocate + itInitialTeb.StackReserve); (PVOID)((ULONG)itInitialTeb.StackAllocate + nVirtualSize);
itInitialTeb.StackLimit = itInitialTeb.StackLimit =
(PVOID)((ULONG)itInitialTeb.StackBase - itInitialTeb.StackCommit); (PVOID)((ULONG)itInitialTeb.StackBase - nCommitSize);
/* 5.2.2: commit the stack */
nVirtualSize = nCommitSize + PAGESIZE;
pCommitBottom =
(PVOID)((ULONG)itInitialTeb.StackBase - nVirtualSize);
/* 5.2.1.2: commit the stack */
nErrCode = NtAllocateVirtualMemory nErrCode = NtAllocateVirtualMemory
( (
hProcess, hProcess,
&itInitialTeb.StackLimit, &pCommitBottom,
0, 0,
&itInitialTeb.StackCommit, &nVirtualSize,
MEM_COMMIT, MEM_COMMIT,
PAGE_READWRITE PAGE_READWRITE
); );
@ -347,14 +471,16 @@ undoPData:
goto failProcess; goto failProcess;
} }
/* 5.2.1.3: set up the guard page */ /* 5.2.3: set up the guard page */
nVirtualSize = PAGESIZE;
nErrCode = NtProtectVirtualMemory nErrCode = NtProtectVirtualMemory
( (
hProcess, hProcess,
itInitialTeb.StackLimit, &pCommitBottom,
PAGESIZE, &nVirtualSize,
PAGE_GUARD | PAGE_READWRITE, PAGE_GUARD | PAGE_READWRITE,
NULL &nOldProtect
); );
/* failure */ /* failure */
@ -364,7 +490,7 @@ undoPData:
goto failProcess; goto failProcess;
} }
/* 5.2.1.4: initialize the thread context */ /* 5.3: initialize the thread context */
memset(&ctxThreadContext, 0, sizeof(ctxThreadContext)); memset(&ctxThreadContext, 0, sizeof(ctxThreadContext));
ctxThreadContext.Eip = (ULONG)pStartAddress; ctxThreadContext.Eip = (ULONG)pStartAddress;
@ -379,10 +505,10 @@ undoPData:
ctxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 5 * 4; ctxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 5 * 4;
ctxThreadContext.EFlags = (1 << 1) + (1 << 9); ctxThreadContext.EFlags = (1 << 1) + (1 << 9);
/* 5.3: create the thread object */ /* 5.4: create the thread object */
nErrCode = NtCreateThread nErrCode = NtCreateThread
( (
NULL, ThreadHandle,
THREAD_ALL_ACCESS, THREAD_ALL_ACCESS,
NULL, NULL,
hProcess, hProcess,