一段CreateProcess的强悍代码

/*
 2004/7/5
 试图写一个自己的exe loader,失败! 
 2004/7/11
 a gui 'hello, world' app is successfully launched
 by this toy CreateProcessW implemention
*/

#include 
< nt.h >
#include 
< ntrtl.h >
#include 
< nturtl.h >
#include 
< stdio.h >

#include 
< windows.h >

#define  ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + 
((ULONG)ROUND 
-   1L ))  &  ( ~ ((ULONG)ROUND  -   1L ))))

#define  MAX_PATH 260
#define  BASESRV_SERVERDLL_INDEX 1

HANDLE BaseNamedObjectDirectory;

typedef 
enum  _BASE_CONTEXT_TYPE  {
 BaseContextTypeProcess,
  BaseContextTypeThread,
  BaseContextTypeFiber
}
 BASE_CONTEXT_TYPE,  * PBASE_CONTEXT_TYPE;

#define  CALL_STDCALL 0
#define  CALL_CDECL 1
#define  CALL_FASTCALL 2

//  #include "var.h"
#include  " ntcsrmsg.h "
#include 
" basemsg.h "

extern  NTSTATUS __declspec(dllimport) _stdcall 
CsrClientCallServer(
 IN OUT PCSR_API_MSG m,
 IN OUT PCSR_CAPTURE_HEADER CaptureBuffer OPTIONAL,
 IN CSR_API_NUMBER ApiNumber,
 IN ULONG ArgLength
 );

ULONG
BaseSetLastNTError(IN NTSTATUS Status)
{
 ULONG dwErrorCode;
 
 dwErrorCode 
= RtlNtStatusToDosError( Status );
 SetLastError( dwErrorCode );
 
return( dwErrorCode );
}


BOOLEAN
BasePushProcessParameters(
        HANDLE Process,
        PPEB Peb,
        LPCWSTR ApplicationPathName,
        LPCWSTR CurrentDirectory,
        LPCWSTR CommandLine,
        PVOID Environment,
        LPSTARTUPINFOW lpStartupInfo,
        ULONG dwCreationFlags,
        BOOLEAN bInheritHandles,
        ULONG dwSubsystem
        )              
{
 UNICODE_STRING ImagePathName;
 UNICODE_STRING CommandLineString;
 UNICODE_STRING CurrentDirString;
 UNICODE_STRING DllPath;
 UNICODE_STRING WindowTitle;
 UNICODE_STRING DesktopInfo;
 UNICODE_STRING ShellInfo;
 UNICODE_STRING RuntimeInfo;
 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
 PRTL_USER_PROCESS_PARAMETERS ParametersInNewProcess;
 ULONG ParameterLength, EnvironmentLength, RegionSize;
 PWCHAR s;
 NTSTATUS Status;
 WCHAR CurDirBuffer[MAX_PATH];
 WCHAR DllPathBuffer[
10240];
 UNICODE_STRING BasePathVariableName;
 
 RtlInitUnicodeString(
&BasePathVariableName, L"PATH");
 DllPath.Length 
= 0;
 DllPath.Buffer 
= DllPathBuffer;
 DllPath.MaximumLength 
= 10240;
 RtlQueryEnvironmentVariable_U( Environment,
  
&BasePathVariableName,
  
&DllPath
  );
 RtlInitUnicodeString(
&ImagePathName, ApplicationPathName);
 RtlInitUnicodeString(
&CommandLineString, CommandLine );
 
if(ARGUMENT_PRESENT(CurrentDirectory)){
  RtlInitUnicodeString(
&CurrentDirString, CurrentDirectory);
 }
else{
  RtlGetCurrentDirectory_U(MAX_PATH, CurDirBuffer);
  RtlInitUnicodeString( 
&CurrentDirString, CurDirBuffer);
 }

 
 
if ( lpStartupInfo->lpDesktop ) {
  RtlInitUnicodeString(
   
&DesktopInfo,
   lpStartupInfo
->lpDesktop
   );
 }

 
else {
  RtlInitUnicodeString( 
&DesktopInfo, L"");
 }

 
 
if ( lpStartupInfo->lpReserved ) {
  RtlInitUnicodeString(
&ShellInfo, lpStartupInfo->lpReserved);
 }

 
else {
  RtlInitUnicodeString( 
&ShellInfo, L"");
 }

 
 RuntimeInfo.Buffer 
= (PWSTR)lpStartupInfo->lpReserved2;
 RuntimeInfo.Length 
= lpStartupInfo->cbReserved2;
 RuntimeInfo.MaximumLength 
= RuntimeInfo.Length;
 
if ( lpStartupInfo->lpTitle ) {
  RtlInitUnicodeString(
&WindowTitle, lpStartupInfo->lpTitle);
 }
else{
  RtlInitUnicodeString( 
&WindowTitle, ApplicationPathName);
 }

 
 Status 
= RtlCreateProcessParameters( &ProcessParameters,
  
&ImagePathName,
  
&DllPath,
  (ARGUMENT_PRESENT(CurrentDirectory)
?
  
&CurrentDirString : NULL
  ),
  
&CommandLineString,
  Environment,
  
&WindowTitle,
  
&DesktopInfo,
  
&ShellInfo,
  
&RuntimeInfo
  );
 
 
if (!NT_SUCCESS( Status )) {
  BaseSetLastNTError(Status);
  
return FALSE;
 }

 
 
if ( !bInheritHandles ) {
  ProcessParameters
->CurrentDirectory.Handle = NULL;
 }

 __try 
{
  
if (s = ProcessParameters->Environment) {
   
while (*s) {
    
while (*s++{
    }

   }

   s
++;
   Environment 
= ProcessParameters->Environment;
   EnvironmentLength 
= (PUCHAR)s - (PUCHAR)Environment;
   
   ProcessParameters
->Environment = NULL;
   RegionSize 
= EnvironmentLength;
   Status 
= NtAllocateVirtualMemory( Process,
    (PVOID 
*)&ProcessParameters->Environment,
    
0,
    
&RegionSize,
    MEM_COMMIT,
    PAGE_READWRITE
    );
   
if ( !NT_SUCCESS( Status ) ) {
    BaseSetLastNTError(Status);
    
return( FALSE );
   }

   
   Status 
= NtWriteVirtualMemory( Process,
    ProcessParameters
->Environment,
    Environment,
    EnvironmentLength,
    NULL
    );
   
if ( !NT_SUCCESS( Status ) ) {
    BaseSetLastNTError(Status);
    
return( FALSE );
   }

  }

  
  
//
  
// Push the parameters into the new process
  
//
  
  ProcessParameters
->StartingX    = lpStartupInfo->dwX;
  ProcessParameters
->StartingY    = lpStartupInfo->dwY;
  ProcessParameters
->CountX     = lpStartupInfo->dwXSize;
  ProcessParameters
->CountY     = lpStartupInfo->dwYSize;
  ProcessParameters
->CountCharsX    =
   lpStartupInfo
->dwXCountChars;
  ProcessParameters
->CountCharsY    =
   lpStartupInfo
->dwYCountChars;
  ProcessParameters
->FillAttribute   =
   lpStartupInfo
->dwFillAttribute;
  ProcessParameters
->WindowFlags    =
   lpStartupInfo
->dwFlags;
  ProcessParameters
->ShowWindowFlags =
   lpStartupInfo
->wShowWindow;
  
  
if(lpStartupInfo->dwFlags & (STARTF_USESTDHANDLES | STARTF_USEHOTKEY
   
/* | STARTF_HASSHELLDATA */
   )) 
{
   ProcessParameters
->StandardInput =
    lpStartupInfo
->hStdInput;
   ProcessParameters
->StandardOutput =
    lpStartupInfo
->hStdOutput;
   ProcessParameters
->StandardError =
    lpStartupInfo
->hStdError;
  }

  
  
if (dwCreationFlags & DETACHED_PROCESS) {
#if 0
   ProcessParameters
->ConsoleHandle =
    (HANDLE)CONSOLE_DETACHED_PROCESS;
  }
 else if (dwCreationFlags & CREATE_NEW_CONSOLE) {
   ProcessParameters
->ConsoleHandle =
    (HANDLE)CONSOLE_NEW_CONSOLE;
  }
 else if (dwCreationFlags & CREATE_NO_WINDOW) {
   ProcessParameters
->ConsoleHandle =
    (HANDLE)CONSOLE_CREATE_NO_WINDOW;
#endif
  }
 else {
   ProcessParameters
->ConsoleHandle =
    NtCurrentPeb()
->ProcessParameters->ConsoleHandle;
   
if (!(lpStartupInfo->dwFlags & STARTF_USESTDHANDLES)) {
    ProcessParameters
->StandardInput =
     NtCurrentPeb()
->ProcessParameters->StandardInput;
    ProcessParameters
->StandardOutput =
     NtCurrentPeb()
->ProcessParameters->StandardOutput;
    ProcessParameters
->StandardError =
     NtCurrentPeb()
->ProcessParameters->StandardError;
   }

  }

  
  
if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP) {
   ProcessParameters
->ConsoleFlags = 1;
  }

  
  ProcessParameters
->Flags |=
   (NtCurrentPeb()
->ProcessParameters->Flags
   
&
   RTL_USER_PROC_DISABLE_HEAP_DECOMMIT
   );
  ParameterLength 
= ProcessParameters->Length;
  
  
//
  
// Allocate memory in the new process to push the parameters
  
//
  
  ParametersInNewProcess 
= NULL;
  Status 
= NtAllocateVirtualMemory(
   Process,
   (PVOID 
*)&ParametersInNewProcess,
   
0,
   
&ParameterLength,
   MEM_COMMIT,
   PAGE_READWRITE
   );
  
if ( !NT_SUCCESS( Status ) ) {
   BaseSetLastNTError(Status);
   
return FALSE;
  }

  ProcessParameters
->MaximumLength = ParameterLength;
  
  
if ( dwCreationFlags & PROFILE_USER ) {
   ProcessParameters
->Flags |= RTL_USER_PROC_PROFILE_USER;
  }

  
  
if ( dwCreationFlags & PROFILE_KERNEL ) {
   ProcessParameters
->Flags |= RTL_USER_PROC_PROFILE_KERNEL;
  }

  
  
if ( dwCreationFlags & PROFILE_SERVER ) {
   ProcessParameters
->Flags |= RTL_USER_PROC_PROFILE_SERVER;
  }

  
  
//
  
// Push the parameters
  
//
  
  Status 
= NtWriteVirtualMemory(
   Process,
   ParametersInNewProcess,
   ProcessParameters,
   ProcessParameters
->Length,
   NULL
   );
  
if ( !NT_SUCCESS( Status ) ) {
   BaseSetLastNTError(Status);
   
return FALSE;
  }

  
  
//
  
// Make the processes PEB point to the parameters.
  
//
  
  Status 
= NtWriteVirtualMemory(
   Process,
   
&Peb->ProcessParameters,
   
&ParametersInNewProcess,
   
sizeof( ParametersInNewProcess ),
   NULL
   );
  
if ( !NT_SUCCESS( Status ) ) {
   BaseSetLastNTError(Status);
   
return FALSE;
  }

  
  
//
  
// Set subsystem type in PEB if requested by caller.
  
// Ignore error
  
//
  
  
if (dwSubsystem != 0{
   NtWriteVirtualMemory(
    Process,
    
&Peb->ImageSubsystem,
    
&dwSubsystem,
    
sizeof( Peb->ImageSubsystem ),
    NULL
    );
  }

 }
__finally{
 }

 
 
return TRUE;
}


HANDLE loadLibrary(
const  wchar_t  *  _dllName)
{
 HANDLE hDll;
 UNICODE_STRING dllName;
 NTSTATUS st;
 
 RtlInitUnicodeString(
&dllName, _dllName);
 st 
= LdrLoadDll(
  NULL, 
  NULL, 
  
&dllName, 
  
&hDll
  );
 
if(!NT_SUCCESS(st)){
  
return 0;
 }

 
 
return hDll;
}


int  callDll(
   
const  wchar_t  *  _dllName, 
   
const   char   *  _procName, 
   
int   *  result,
   
int  callConvention,
   
int  numOfParameters, 
   ...
   )
{
 STRING procName;
 HANDLE hDll;
 PVOID entry;
 NTSTATUS st;
 
 
if(result){
  
*result = 0;
 }

 
 
if(callConvention != CALL_STDCALL){
  
// unimplemented
  return -3;
 }

 
 hDll 
= loadLibrary(_dllName);
 
if ((int)_procName & 0xffff0000{
  RtlInitString(
&procName, _procName);
  st 
= LdrGetProcedureAddress(
   hDll,
   
&procName,
   
0L,
   
&entry
   );
 }
else{
  st 
= LdrGetProcedureAddress(
   hDll,
   NULL,
   (ULONG)_procName,
   
&entry
   );
 }

 
if(!NT_SUCCESS(st)){
  LdrUnloadDll(hDll);
  
return -2;
 }

 
 
/* 
 fake a call stack frame and do a function call
 maybe we should use a thunk to make this bit
 of code more readable
 
*/

 __asm
{
  lea esi, numOfParameters
   mov ecx, [esi]
   add esi, 
4
   lea ebx, [ecx 
* 4]
   sub esp, ebx
   mov edi, esp
   rep movsd
   call entry
   mov entry, eax
 }

 
 
// for debug, leave the dll there
 
// LdrUnloadDll(hDll);
 
 
if(result){
  
*result = (int)entry;
 }

 
 
return 0;
}


NTSTATUS
BaseCreateStack(
    IN HANDLE Process,
    IN ULONG StackSize,
    IN ULONG MaximumStackSize,
    OUT PINITIAL_TEB InitialTeb
    )
{
 NTSTATUS Status;
 PCH Stack;
 BOOLEAN GuardPage;
 ULONG RegionSize;
 ULONG OldProtect;
 ULONG ImageStackSize, ImageStackCommit;
 PIMAGE_NT_HEADERS NtHeaders;
 PPEB Peb;
 ULONG PageSize;
 
 Peb 
= NtCurrentPeb();
 
 PageSize 
= 0X1000;
 
 
//
 
// If the stack size was not supplied, then use the sizes
 
// from the image header.
 
//
 
 NtHeaders 
= RtlImageNtHeader(Peb->ImageBaseAddress);
 ImageStackSize 
=
  NtHeaders
->OptionalHeader.SizeOfStackReserve;
 ImageStackCommit 
=
  NtHeaders
->OptionalHeader.SizeOfStackCommit;
 
 
if ( !MaximumStackSize ) {
  MaximumStackSize 
= ImageStackSize;
 }

 
if (!StackSize) {
  StackSize 
= ImageStackCommit;
 }

 
else {
  
  
//
  
// Now Compute how much additional stack space is to be
  
// reserved.  This is done by...  If the StackSize is <=
  
// Reserved size in the image, then reserve whatever the
  
// image specifies.  Otherwise, round up to 1Mb.
  
//
  
  
if ( StackSize >= MaximumStackSize ) {
   MaximumStackSize 
= ROUND_UP(StackSize, (1024*1024));
  }

 }

 
 
//
 
// Align the stack size to a page boundry and the reserved
 
// size to an allocation granularity boundry.
 
//
 
 StackSize 
= ROUND_UP( StackSize, PageSize );
 MaximumStackSize 
= ROUND_UP(
  MaximumStackSize,
  
0x10000
  
// BaseStaticServerData->SysInfo.AllocationGranularity
  );
 
 
//
 
// Reserve address space for the stack
 
//
 
 Stack 
= NULL,
  Status 
= NtAllocateVirtualMemory(
  Process,
  (PVOID 
*)&Stack,
  
0,
  
&MaximumStackSize,
  MEM_RESERVE,
  PAGE_READWRITE
  );
 
if ( !NT_SUCCESS( Status ) ) {
  
return Status;
 }

 
 InitialTeb
->OldInitialTeb.OldStackBase = NULL;
 InitialTeb
->OldInitialTeb.OldStackLimit = NULL;
 InitialTeb
->StackAllocationBase = Stack;
 InitialTeb
->StackBase = Stack + MaximumStackSize;
 
 Stack 
+= MaximumStackSize - StackSize;
 
if (MaximumStackSize > StackSize) {
  Stack 
-= PageSize;
  StackSize 
+= PageSize;
  GuardPage 
= TRUE;
 }

 
else {
  GuardPage 
= FALSE;
 }

 
 
//
 
// Commit the initially valid portion of the stack
 
//
 
 Status 
= NtAllocateVirtualMemory(
  Process,
  (PVOID 
*)&Stack,
  
0,
  
&StackSize,
  MEM_COMMIT,
  PAGE_READWRITE
  );
 
if ( !NT_SUCCESS( Status ) ) {
  
  
//
  
// If the commit fails, then delete the address space
  
// for the stack
  
//
  
  RegionSize 
= 0;
  NtFreeVirtualMemory(
   Process,
   (PVOID 
*)&Stack,
   
&RegionSize,
   MEM_RELEASE
   );
  
  
return Status;
 }

 
 InitialTeb
->StackLimit = Stack;
 
 
//
 
// if we have space, create a guard page.
 
//
 
 
if (GuardPage) {
  RegionSize 
= PageSize;
  Status 
= NtProtectVirtualMemory(
   Process,
   (PVOID 
*)&Stack,
   
&RegionSize,
   PAGE_GUARD 
| PAGE_READWRITE,
   
&OldProtect
   );
  
if ( !NT_SUCCESS( Status ) ) {
   
return Status;
  }

  InitialTeb
->StackLimit = (PVOID)(
   (PUCHAR)InitialTeb
->StackLimit + RegionSize
   );
 }

 
 
return STATUS_SUCCESS;
}



VOID
BaseInitializeContext(
       OUT PCONTEXT Context,
       IN PVOID Parameter OPTIONAL,
       IN PVOID InitialPc OPTIONAL,
       IN PVOID InitialSp OPTIONAL,
       IN BASE_CONTEXT_TYPE ContextType
       )
{
 
 Context
->Eax = (ULONG)InitialPc;
 Context
->Ebx = (ULONG)Parameter;
 
 Context
->SegGs = 0;
 Context
->SegFs = KGDT_R3_TEB;
 Context
->SegEs = KGDT_R3_DATA;
 Context
->SegDs = KGDT_R3_DATA;
 Context
->SegSs = KGDT_R3_DATA;
 Context
->SegCs = KGDT_R3_CODE;
 
 
//
 
// Start the thread at IOPL=3.
 
//
 
 Context
->EFlags = 0x3000;
 
 
//
 
// Always start the thread at the thread start thunk.
 
//
 
 Context
->Esp = (ULONG) InitialSp;
 Context
->Eip = (ULONG)InitialPc;
 
 
//
 
// add code to check alignment and raise exception...
 
//
 
 Context
->ContextFlags = CONTEXT_FULL;
 
// Reserve room for ret address
 Context->Esp -= sizeof(Parameter);
}


HANDLE
BaseGetNamedObjectDirectory(
       VOID
       )
{
 OBJECT_ATTRIBUTES Obja;
 NTSTATUS Status;
 ACCESS_MASK DirAccess 
= DIRECTORY_ALL_ACCESS &
  
~(DELETE | WRITE_DAC | WRITE_OWNER);
 
 RtlAcquirePebLock();
 
 
if ( !BaseNamedObjectDirectory ) {
  InitializeObjectAttributes(
   
&Obja,
   NULL,
   OBJ_CASE_INSENSITIVE,
   NULL,
   NULL
   );
  Status 
= NtOpenDirectoryObject(
   
&BaseNamedObjectDirectory,
   DirAccess,
   
&Obja
   );
  
if ( !NT_SUCCESS(Status) ) {
   BaseNamedObjectDirectory 
= NULL;
  }

 }

 RtlReleasePebLock();
 
return BaseNamedObjectDirectory;
}


POBJECT_ATTRIBUTES
BaseFormatObjectAttributes(
         OUT POBJECT_ATTRIBUTES ObjectAttributes,
         IN PUNICODE_STRING ObjectName
         )
{
 HANDLE RootDirectory;
 ULONG Attributes;
 PVOID SecurityDescriptor 
= NULL;
 
 
if (ARGUMENT_PRESENT(ObjectName) ) {
  
if ( ARGUMENT_PRESENT(ObjectName) ) {
   RootDirectory 
= BaseGetNamedObjectDirectory();
  }

  
else {
   RootDirectory 
= NULL;
  }

  
  
if ( ARGUMENT_PRESENT(ObjectName) ) {
   Attributes 
|= OBJ_OPENIF;
  }

  
  InitializeObjectAttributes(
   ObjectAttributes,
   ObjectName,
   Attributes,
   RootDirectory,
   SecurityDescriptor
   );
  
return ObjectAttributes;
 }
else{
  
return NULL;
 }

}


UCHAR _stdcall createProcess(
        LPCWSTR lpApplicationName,
        LPWSTR lpCommandLine,
        UCHAR bInheritHandles,
        ULONG dwCreationFlags,
        PVOID lpEnvironment,
        LPCWSTR lpCurrentDirectory,
        LPSTARTUPINFOW lpStartupInfo,
        LPPROCESS_INFORMATION lpProcessInformation
        )
        
{
 HANDLE FileHandle;
 NTSTATUS Status, StackStatus;
 OBJECT_ATTRIBUTES Obja, 
*pObja;
 UNICODE_STRING PathName;
 IO_STATUS_BLOCK IoStatusBlock;
 HANDLE SectionHandle;
 HANDLE ProcessHandle;
 SECTION_IMAGE_INFORMATION ImageInformation;
 PROCESS_BASIC_INFORMATION ProcessInfo;
 PPEB Peb;
 LPWSTR CurdirBuffer, CurdirFilePart;
 ULONG CurdirLength,CurdirLength2;
 HANDLE ThreadHandle;
 INITIAL_TEB InitialTeb;
 CONTEXT ThreadContext;
 CLIENT_ID ClientId;
 STARTUPINFOW StartupInfo;
 BASE_API_MSG m;
 PBASE_CREATEPROCESS_MSG a
=
  (PBASE_CREATEPROCESS_MSG)
&m.u.CreateProcess;
 
 StartupInfo 
= *lpStartupInfo;
 
 
if(ARGUMENT_PRESENT(lpApplicationName)){
  Status 
= RtlDosPathNameToNtPathName_U(
   lpApplicationName,
   
&PathName,
   NULL,
   NULL
   );
  
if(!NT_SUCCESS(Status)){
   
return FALSE;
  }

  
  InitializeObjectAttributes(
   
&Obja,
   
&PathName,
   OBJ_CASE_INSENSITIVE,
   NULL,
   NULL
   );
  
  Status 
= NtOpenFile(
   
&FileHandle,
   SYNCHRONIZE 
| FILE_EXECUTE,// | FILE_WRITE_DATA,
   &Obja,
   
&IoStatusBlock,
   FILE_SHARE_READ 
| FILE_SHARE_WRITE | FILE_SHARE_DELETE,
   FILE_SYNCHRONOUS_IO_NONALERT 
| FILE_NON_DIRECTORY_FILE
   );
  
  
if(!NT_SUCCESS(Status)){
   
return FALSE;
  }

 
  Status 
= NtCreateSection(
   
&SectionHandle,
   SECTION_ALL_ACCESS,
   NULL,
   NULL,
   PAGE_EXECUTE,
   SEC_IMAGE,
   FileHandle
   );
  
  NtClose(FileHandle);
  FileHandle 
= NULL;
  
  
if(!NT_SUCCESS(Status)){
   
return FALSE;
  }

  
//
  
// Query the section to determine the stack parameters and
  
// image entrypoint.
  
//
  
  Status 
= NtQuerySection(
   SectionHandle,
   SectionImageInformation,
   
&ImageInformation,
   
sizeof( ImageInformation ),
   NULL
   );
 }
else{
  
// simulate a fork operation
  SectionHandle = NULL;
 }

 
 
//
 
// Create the process object
 
//
 if(!NT_SUCCESS(Status)){
  
return FALSE;
 }

 
 
if (StartupInfo.lpDesktop == NULL) {
  StartupInfo.lpDesktop 
=
   (LPWSTR)((PRTL_USER_PROCESS_PARAMETERS)NtCurrentPeb()
->
   ProcessParameters)
->DesktopInfo.Buffer;
 }

 
 pObja 
= BaseFormatObjectAttributes(&Obja,  NULL);
 
 Status 
= NtCreateProcess(
  
&ProcessHandle,
  PROCESS_ALL_ACCESS,
  pObja,
  NtCurrentProcess(),
  (BOOLEAN)bInheritHandles,
  SectionHandle,
  NULL,
  NULL
  );
 
 
if ( !NT_SUCCESS(Status) ) {
  
return FALSE;
 }

 
 NtClose(SectionHandle);
 SectionHandle 
= NULL;
 
 
//
 
// Determine the location of the
 
// processes PEB.
 
//
 
 Status 
= NtQueryInformationProcess(
  ProcessHandle,
  ProcessBasicInformation,
  
&ProcessInfo,
  
sizeof( ProcessInfo ),
  NULL
  );
 
if ( !NT_SUCCESS( Status ) ) {
  
return FALSE;
 }

 
 Peb 
= ProcessInfo.PebBaseAddress;
 
#if 1
 
//
 
// Push the parameters into the address space
 
// of the new process
 
//
 
 
if ( ARGUMENT_PRESENT(lpCurrentDirectory) ) {
  CurdirBuffer 
= RtlAllocateHeap(
   RtlProcessHeap(),
   
0//MAKE_TAG( TMP_TAG ),
   (MAX_PATH*2)+sizeof(UNICODE_NULL)
   );
  
if ( !CurdirBuffer ) {
   BaseSetLastNTError(STATUS_NO_MEMORY);
   
return FALSE;
  }

  CurdirLength2 
= GetFullPathNameW(
   lpCurrentDirectory,
   MAX_PATH,
   CurdirBuffer,
   
&CurdirFilePart
   );
  
if ( CurdirLength2 > MAX_PATH ) {
   SetLastError(ERROR_DIRECTORY);
   
return FALSE;
  }

  
  
//
  
// now make sure the directory exists
  
//
  
  CurdirLength 
= GetFileAttributesW(CurdirBuffer);
  
if ( (CurdirLength == 0xffffffff||
   
!(CurdirLength & FILE_ATTRIBUTE_DIRECTORY) ) {
   SetLastError(ERROR_DIRECTORY);
   
return FALSE;
  }

 }

 
 
if (!BasePushProcessParameters(
  ProcessHandle,
  Peb,
  lpApplicationName,
  lpCurrentDirectory,
  lpCommandLine,
  lpEnvironment,
  
&StartupInfo,
  dwCreationFlags,
  bInheritHandles,
  
0
  ) ) 
{
  
return FALSE;
 }

#endif
 
 StackStatus 
= BaseCreateStack(
  ProcessHandle,
  ImageInformation.CommittedStackSize,
  ImageInformation.MaximumStackSize,
  
&InitialTeb
  );
 
 
if ( !NT_SUCCESS(StackStatus) ) {
  BaseSetLastNTError(StackStatus);
  
return FALSE;
 }

 
 
 
//
 
// Create an initial context for the new thread.
 
//
 
 BaseInitializeContext(
  
&ThreadContext,
  Peb,
  ImageInformation.TransferAddress,
  InitialTeb.StackBase,
  BaseContextTypeProcess
  );
 
 
 
//
 
// Create the actual thread object
 
//
 
 pObja 
= BaseFormatObjectAttributes(&Obja, NULL);
 
 Status 
= NtCreateThread(
  
&ThreadHandle,
  THREAD_ALL_ACCESS,
  pObja,
  ProcessHandle,
  
&ClientId,
  
&ThreadContext,
  
&InitialTeb,
  TRUE
  );
 
 
if (!NT_SUCCESS(Status) ) {
  BaseSetLastNTError(Status);
  
return FALSE;
 }

 
 
//
 
// Call the Windows server to let it know about the
 
// process.
 
//
 memset(&m, 0sizeof(m));
 
 a
->ProcessHandle = ProcessHandle;
 a
->ThreadHandle = ThreadHandle;
 a
->ClientId = ClientId;
 a
->CreationFlags = dwCreationFlags;
 
#if 0
 
if(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)){
  Status 
= DbgUiConnectToDbg();
  
if ( !NT_SUCCESS(Status) ) {
   NtTerminateProcess(ProcessHandle,Status);
   BaseSetLastNTError(Status);
   
return FALSE;
  }

  a
->DebuggerClientId = NtCurrentTeb()->ClientId;
 }

 
else {
  a
->DebuggerClientId.UniqueProcess = NULL;
  a
->DebuggerClientId.UniqueThread = NULL;
 }

#endif
 
#if 0
 
//
 
// Set the 2 bit if a gui app is starting. The window
 
// manager needs to
 
// know this so it can synchronize the startup of this app
 
// (WaitForInputIdle api). This info is passed using the
 
// process
 
// handle tag bits.  The 1 bit asks the window manager to
 
// turn on
 
// or turn off the application start cursor
 
// (hourglass/pointer).
 
//
 
// When starting a WOW process, lie and tell UserSrv
 
// NTVDM.EXE is a GUI
 
// process.  We also turn on bit 0x8 so that UserSrv can
 
// ignore the
 
// UserNotifyConsoleApplication call made by the console
 
// during startup.
 
//
 
 
if(ImageInformation.SubSystemType ==
  IMAGE_SUBSYSTEM_WINDOWS_GUI
  
// || IsWowBinary
  ) {
  
  a
->ProcessHandle = (HANDLE)((ULONG)a->ProcessHandle | 2);
  
  
//
  
// If the creating process is a GUI app, turn on the app.
  
// start cursor
  
// by default. This can be overridden by
  
// STARTF_FORCEOFFFEEDBACK.
  
//
  
  NtHeaders 
= RtlImageNtHeader((PVOID)GetModuleHandle(NULL));
  
if ( NtHeaders->OptionalHeader.Subsystem ==
   IMAGE_SUBSYSTEM_WINDOWS_GUI
   )
{
   a
->ProcessHandle = (HANDLE)((ULONG)a->ProcessHandle | 1);
  }

 }

 
#endif
 
#if 1
 
//
 
// If feedback is forced on, turn it on. If forced off,
 
// turn it off.
 
// Off overrides on.
 
//
 if (StartupInfo.dwFlags & STARTF_FORCEONFEEDBACK)
  a
->ProcessHandle = (HANDLE)((ULONG)a->ProcessHandle | 1);
 
if (StartupInfo.dwFlags & STARTF_FORCEOFFFEEDBACK)
  a
->ProcessHandle = (HANDLE)((ULONG)a->ProcessHandle & ~1);
 
 CsrClientCallServer(
  (PCSR_API_MSG)
&m,
  NULL,
  CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess),
  
sizeof*a )
  );
 
 
if (!NT_SUCCESS((NTSTATUS)m.ReturnValue)) {
  BaseSetLastNTError((NTSTATUS)m.ReturnValue);
  NtTerminateProcess(ProcessHandle, 
0);
  
return FALSE;
 }

#endif
 
 
if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
  NtResumeThread(ThreadHandle, (PULONG)NULL);
 }

 
 
return TRUE;
}


int  wmain( int  c,  const  wchar_t  **  v)
{
 
static PROCESS_INFORMATION pi;
 
static STARTUPINFOW si = {sizeof(si)};
 BOOLEAN ret;
 
 
if(c < 2){
  
return -1;
 }


 wprintf(L
"launching %s...", v[1]);
 
 __try
{
  ret 
= createProcess(
   v[
1],
   NULL,
   FALSE,
   
0,
   NULL,
   NULL,
   
&si,
   
&pi
   );
  
if(ret){
   printf(
"Ok. ");
  }
else{
   printf(
"Failed(%d). ", GetLastError());
  }

 }
__except(1){
  ;
 }

 ExitProcess(
0);
 
// NtTerminateProcess(NtCurrentProcess(), 0);
 
// callDll(L"kernel32.dll", "ExitProcess", CALL_STDCALL, 1, 0);
 return 0;
}


void  __declspec(dllexport) _stdcall
startW(HWND hwnd, HINSTANCE h, wchar_t 
*  cmdLine,  int  nCmdShow)
{
 
static PROCESS_INFORMATION pi;
 
static STARTUPINFOW si = {sizeof(si)};
 
 __try
{
  createProcess(
   cmdLine,
   NULL,
   FALSE,
   
0,
   NULL,
   NULL,
   
&si,
   
&pi
   );
 }
__except(1){
  ;
 }

}


BOOLEAN _stdcall dllMain(
int  a,  int  b,  int  c)
{
 
return TRUE;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值