转载请您注明出处:http://www.cnblogs.com/lsh123/p/7405796.html

0x01 CreateProcessW

  CreateProcess的使用有ANSI版本的CreateProcessA和UNICODE版本的CreateProcessW:

进程创建过程详解 CreateProcess

  不过查看源码就可以发现其实CreateProcessA内部调用的还是CreateProcessW:

BOOL
WINAPI
CreateProcessA(
    LPCSTR lpApplicationName,
    LPSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCSTR lpCurrentDirectory,
    LPSTARTUPINFOA lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation
    )

/*++

    ANSI thunk to CreateProcessW

--*/

{
    NTSTATUS Status;
    PUNICODE_STRING CommandLine;
    UNICODE_STRING ApplicationName;
    UNICODE_STRING CurrentDirectory;
    STARTUPINFOW StartupInfo;
    ANSI_STRING AnsiString;
    UNICODE_STRING Unicode;
    UNICODE_STRING DynamicCommandLine;
    UNICODE_STRING NullUnicodeString;
    BOOL ReturnStatus;

    if (ARGUMENT_PRESENT (lpCommandLine)) {
        if ( (strlen( lpCommandLine ) + 1) * sizeof( WCHAR ) <
             NtCurrentTeb()->StaticUnicodeString.MaximumLength ) {

            DynamicCommandLine.Buffer = NULL;

            CommandLine = Basep8BitStringToStaticUnicodeString( lpCommandLine );
            if (CommandLine == NULL) {
                return FALSE;
            }
        } else {
            if (!Basep8BitStringToDynamicUnicodeString( &DynamicCommandLine,
                                                        lpCommandLine )) {
                return FALSE;
            }
        }
    } else {
         DynamicCommandLine.Buffer = NULL;
         CommandLine = &NullUnicodeString;
         CommandLine->Buffer = NULL;
    }

    ApplicationName.Buffer = NULL;
    ApplicationName.Buffer = NULL;
    CurrentDirectory.Buffer = NULL;
    RtlMoveMemory(&StartupInfo,lpStartupInfo,sizeof(*lpStartupInfo));
    ASSERT(sizeof(StartupInfo) == sizeof(*lpStartupInfo));
    StartupInfo.lpReserved = NULL;
    StartupInfo.lpDesktop = NULL;
    StartupInfo.lpTitle = NULL;

    try {
        try {
            if (ARGUMENT_PRESENT(lpApplicationName)) {

                if (!Basep8BitStringToDynamicUnicodeString( &ApplicationName,
                                                            lpApplicationName )) {
                    ReturnStatus = FALSE;
                    goto tryexit;
                }
            }

            if (ARGUMENT_PRESENT(lpCurrentDirectory)) {
                if (!Basep8BitStringToDynamicUnicodeString( &CurrentDirectory,
                                                            lpCurrentDirectory )) {
                    ReturnStatus = FALSE;
                    goto tryexit;
                }
            }

            if (ARGUMENT_PRESENT(lpStartupInfo->lpReserved)) {

                //
                // Win95 does not touch reserved, and Intergraph Voxtel passes
                // garbage for this. Handle this by probing lpReserved, and if
                // the pointer is bad, ignore it
                //

                try {

                    RtlInitAnsiString(&AnsiString,lpStartupInfo->lpReserved);

                    }
                except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
                            ? EXCEPTION_EXECUTE_HANDLER
                            : EXCEPTION_CONTINUE_SEARCH) {
                    goto bail_on_reserved;
                    }

                Unicode.MaximumLength = (USHORT)RtlAnsiStringToUnicodeSize(&AnsiString) ;
                StartupInfo.lpReserved = RtlAllocateHeap( RtlProcessHeap(),
                                                          MAKE_TAG( TMP_TAG ),
                                                          Unicode.MaximumLength);
                if ( !StartupInfo.lpReserved ) {
                    BaseSetLastNTError(STATUS_NO_MEMORY);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                Unicode.Buffer = StartupInfo.lpReserved;
                Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
                if ( !NT_SUCCESS(Status) ) {
                    BaseSetLastNTError(Status);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                }

bail_on_reserved:
            if (ARGUMENT_PRESENT(lpStartupInfo->lpDesktop)) {
                RtlInitAnsiString(&AnsiString,lpStartupInfo->lpDesktop);
                Unicode.MaximumLength = (USHORT)RtlAnsiStringToUnicodeSize(&AnsiString) ;
                StartupInfo.lpDesktop = RtlAllocateHeap( RtlProcessHeap(),
                                                         MAKE_TAG( TMP_TAG ),
                                                         Unicode.MaximumLength);
                if ( !StartupInfo.lpDesktop ) {
                    BaseSetLastNTError(STATUS_NO_MEMORY);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                Unicode.Buffer = StartupInfo.lpDesktop;
                Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
                if ( !NT_SUCCESS(Status) ) {
                    BaseSetLastNTError(Status);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                }

            if (ARGUMENT_PRESENT(lpStartupInfo->lpTitle)) {
                RtlInitAnsiString(&AnsiString,lpStartupInfo->lpTitle);
                Unicode.MaximumLength = (USHORT)RtlAnsiStringToUnicodeSize(&AnsiString) ;
                StartupInfo.lpTitle = RtlAllocateHeap( RtlProcessHeap(),
                                                       MAKE_TAG( TMP_TAG ),
                                                       Unicode.MaximumLength);
                if ( !StartupInfo.lpTitle ) {
                    BaseSetLastNTError(STATUS_NO_MEMORY);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                Unicode.Buffer = StartupInfo.lpTitle;
                Status = RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,FALSE);
                if ( !NT_SUCCESS(Status) ) {
                    BaseSetLastNTError(Status);
                    ReturnStatus = FALSE;
                    goto tryexit;
                    }
                }
            }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
                    ? EXCEPTION_EXECUTE_HANDLER
                    : EXCEPTION_CONTINUE_SEARCH) {
            BaseSetLastNTError(GetExceptionCode());
            ReturnStatus = FALSE;
            goto tryexit;
            }
        ReturnStatus = CreateProcessW(
                            ApplicationName.Buffer,
                            DynamicCommandLine.Buffer ? DynamicCommandLine.Buffer
                                                      : CommandLine->Buffer,
                            lpProcessAttributes,
                            lpThreadAttributes,
                            bInheritHandles,
                            dwCreationFlags,
                            lpEnvironment,
                            CurrentDirectory.Buffer,
                            &StartupInfo,
                            lpProcessInformation
                            );
tryexit:;
        }
    finally {
        RtlFreeUnicodeString(&DynamicCommandLine);
        RtlFreeUnicodeString(&ApplicationName);
        RtlFreeUnicodeString(&CurrentDirectory);
        RtlFreeHeap(RtlProcessHeap(), 0,StartupInfo.lpReserved);
        RtlFreeHeap(RtlProcessHeap(), 0,StartupInfo.lpDesktop);
        RtlFreeHeap(RtlProcessHeap(), 0,StartupInfo.lpTitle);
        }

    return ReturnStatus;

}

  CreateProcessW的十个参数:

WINBASEAPI
BOOL
WINAPI
CreateProcessW(
    LPCWSTR lpApplicationName,    //指向一个NULL结尾的,新进程的可执行文件的名称
    LPWSTR lpCommandLine,          //指向一个NULL结尾的,传给新进程的命令行字符串
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    //指向一个SECURITY_ATTRIBUTES结构体,分配给新的进程对象
    //SECURITY_ATTRIBUTES结构可以决定是否返回的句柄可以被子进程继承(bInheritHandle )。如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。
    //SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员可以指定新进程的安全描述符,如果参数为空,新进程使用默认的安全描述符。
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    //指向一个SECURITY_ATTRIBUTES结构体,分配给新的线程对象
    BOOL bInheritHandles,
    //标识新进程是否可以从调用进程处继承所有可继承的句柄。被继承的句柄与原进程拥有完全相同的值和访问权限。
    DWORD dwCreationFlags,
    //标识了影响新进程创建方式的标志,多个标志按位或进行组合
    LPVOID lpEnvironment,
    //指向一块内存,其中包含新进程要使用的环境字符串。如果此参数为空,新进程继承父进程的一组环境字符串。
    LPCWSTR lpCurrentDirectory,
    //指向一个以NULL结尾的字符串,用来设置新进程的当前驱动器和目录,这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与父进程相同的驱动器和目录。
    LPSTARTUPINFOW lpStartupInfo,
    //指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。
    LPPROCESS_INFORMATION lpProcessInformation
    //指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。 
    );

  (1)STARTUPINFO 和 PROCESS_INFORMATION的使用前初始化为空:

  STARTUPINFO StartupInfo = { 0 };
  StartupInfo.cb = sizeof(STARTUPINFO);
  PROCESS_INFORMATION ProcessInfo = { 0 };

 

  (2)第六参数:dwCreationFlags 的部分标志:

  ⑴值:CREATE_DEFAULT_ERROR_MODE
  含义:新的进程不继承调用进程的错误模式。CreateProcess函数赋予新进程当前的默认错误模式作为替代。应用程序可以调用SetErrorMode函数设置当前的默认错误模式。
  这个标志对于那些运行在没有硬件错误环境下的多线程外壳程序是十分有用的。
  对于CreateProcess函数,默认的行为是为新进程继承调用者的错误模式。设置这个标志以改变默认的处理方式。
 
  ⑵值:CREATE_NEW_CONSOLE
  含义:新的进程将使用一个新的控制台,而不是继承父进程的控制台。这个标志不能与DETACHED_PROCESS标志一起使用。
 
  ⑶值:CREATE_NEW_PROCESS_GROUP
  含义:新进程将是一个进程树的根进程。进程树中的全部进程都是根进程的子进程。新进程树的用户标识符与这个进程的标识符是相同的,由lpProcessInformation参数返回。进程树经常使用GenerateConsoleCtrlEvent函数允许发送CTRL+C或   CTRL+BREAK信号到一组控制台进程。
 
  ⑷值:CREATE_SEPARATE_WOW_VDM
  如果被设置,新进程将会在一个私有的虚拟DOS机(VDM)中运行。另外,默认情况下所有的16位Windows应用程序都会在同一个共享的VDM中以线程的方式运行。单独运行一个16位程序的优点是一个应用程序的崩溃只会结束这一个VDM的运行;其他那些在不同VDM中运行的程序会继续正常的运行。同样的,在不同VDM中运行的16位Windows应用程序拥有不同的输入队列,这意味着如果一个程序暂时失去响应,在独立的VDM中的应用程序能够继续获得输入。
 
  ⑸值:CREATE_SHARED_WOW_VDM
如果WIN.INI中的Windows段的DefaultSeparateVDM选项被设置为真,这个标识使得CreateProcess函数越过这个选项并在共享的虚拟DOS机中运行新进程。
 
  ⑹值:CREATE_SUSPENDED
  含义:新进程的主线程会以挂起的状态被创建,直到调用ResumeThread函数被调用时才运行。
 
  ⑺值:CREATE_UNICODE_ENVIRONMENT
  含义:如果被设置,由lpEnvironment参数指定环境块使用Unicode字符,如果为空,环境块默认使用ANSI字符。
 
  ⑻值:DEBUG_PROCESS
  含义:如果这个标志被设置,调用进程将被当做一个调试程序,并且新进程会被当做被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。
  如果你使用这个标志创建进程,只有调用进程(调用CreateProcess函数的进程)可以调用WaitForDebugEvent函数。
 
  ⑼值:DEBUG_ONLY_THIS_PROCESS
  含义:如果此标志没有被设置且调用进程正在被调试,新进程将成为调试调用进程的调试器的另一个调试对象。如果调用进程没有被调试,有关调试的行为就不会产生。
 
  ⑽值:DETACHED_PROCESS
  含义:对于控制台进程,新进程没有访问父进程控制台的权限。新进程可以通过AllocConsole函数自己创建一个新的控制台。这个标志不可以与CREATE_NEW_CONSOLE标志一起使用。
 
  〔11〕值:CREATE_NO_WINDOW
  含义:系统不为新进程创建CUI窗口,使用该标志可以创建不含窗口的CUI程序。
 
 
 
 
 
 
 
 
 
 
0x02  创建进程详细步骤1:打开目标映像文件,创建进程对象,线程对象
    
   CreateProcessW源代码(windows2000)
   
   1 BOOL
   2 WINAPI
   3 CreateProcessW(
   4     LPCWSTR lpApplicationName,
   5     LPWSTR lpCommandLine,
   6     LPSECURITY_ATTRIBUTES lpProcessAttributes,
   7     LPSECURITY_ATTRIBUTES lpThreadAttributes,
   8     BOOL bInheritHandles,
   9     DWORD dwCreationFlags,
  10     LPVOID lpEnvironment,
  11     LPCWSTR lpCurrentDirectory,
  12     LPSTARTUPINFOW lpStartupInfo,
  13     LPPROCESS_INFORMATION lpProcessInformation
  14     )
  15 
  16 {
  17     NTSTATUS Status;
  18     OBJECT_ATTRIBUTES Obja;
  19     POBJECT_ATTRIBUTES pObja;
  20     HANDLE ProcessHandle, ThreadHandle, VdmWaitHandle = NULL;
  21     HANDLE FileHandle, SectionHandle;
  22     CLIENT_ID ClientId;
  23     UNICODE_STRING PathName;
  24     IO_STATUS_BLOCK IoStatusBlock;
  25     BOOLEAN TranslationStatus;
  26     RTL_RELATIVE_NAME RelativeName;
  27     PVOID FreeBuffer;
  28     LPWSTR NameBuffer;
  29     LPWSTR WhiteScan;
  30     ULONG Length,i;
  31     PROCESS_BASIC_INFORMATION ProcessInfo;
  32     SECTION_IMAGE_INFORMATION ImageInformation;
  33     NTSTATUS StackStatus;
  34     BOOLEAN bStatus;
  35     INITIAL_TEB InitialTeb;
  36     CONTEXT ThreadContext;
  37     PPEB Peb;
  38     BASE_API_MSG m;
  39     PBASE_CREATEPROCESS_MSG a= (PBASE_CREATEPROCESS_MSG)&m.u.CreateProcess;
  40     PBASE_CHECKVDM_MSG b= (PBASE_CHECKVDM_MSG)&m.u.CheckVDM;
  41     PWCH TempNull = NULL;
  42     WCHAR TempChar;
  43     UNICODE_STRING VdmNameString;
  44     PVOID BaseAddress;
  45     ULONG VdmReserve;
  46     SIZE_T BigVdmReserve;
  47     ULONG iTask=0;
  48     LPWSTR CurdirBuffer, CurdirFilePart;
  49     DWORD CurdirLength,CurdirLength2;
  50     ULONG VDMCreationState=0;
  51     ULONG VdmBinaryType = 0;
  52     UNICODE_STRING  SubSysCommandLine;
  53     PIMAGE_NT_HEADERS NtHeaders;
  54     DWORD dwNoWindow = (dwCreationFlags & CREATE_NO_WINDOW);
  55     ANSI_STRING AnsiStringVDMEnv;
  56     UNICODE_STRING UnicodeStringVDMEnv;
  57     WCHAR ImageFileDebuggerCommand[ 64 ];
  58     LPWSTR QuotedBuffer;
  59     BOOLEAN QuoteInsert;
  60     BOOLEAN QuoteCmdLine = FALSE;
  61     BOOLEAN QuoteFound;
  62     BOOLEAN SearchRetry;
  63     BOOLEAN IsWowBinary = FALSE;
  64     STARTUPINFOW StartupInfo;
  65     DWORD LastError;
  66     DWORD fileattr;
  67     PROCESS_PRIORITY_CLASS PriClass;
  68     PVOID State;
  69 #if defined(BUILD_WOW6432) || defined(_WIN64)
  70     LPCWSTR lpOriginalApplicationName = lpApplicationName;
  71     LPWSTR lpOriginalCommandLine = lpCommandLine;
  72 #endif
  73 
  74 #if defined(WX86) || defined(_AXP64_)
  75     HANDLE Wx86Info = NULL;
  76 #endif
  77 
  78 #if defined WX86
  79     BOOLEAN UseKnownWx86Dll;
  80     UseKnownWx86Dll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
  81     NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  82 #endif
  83 
  84 
  85     RtlZeroMemory(lpProcessInformation,sizeof(*lpProcessInformation));
  86 
  87     // Private VDM flag should be ignored; Its meant for internal use only.
  88     dwCreationFlags &= (ULONG)~CREATE_NO_WINDOW;
  89 
  90     //
  91     // CREATE_WITH_USERPROFILE is the new Create Flag that is used
  92     // only by CreateProcessWithLogonW.  If this flags ends up getting
  93     // passed to CreateProcess, we must reject it.
  94     //
  95     if (dwCreationFlags & CREATE_WITH_USERPROFILE ) {
  96         SetLastError(ERROR_INVALID_PARAMETER);
  97         return FALSE;
  98         }
  99 
 100     if ((dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) ==
 101         (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) {
 102 
 103         SetLastError(ERROR_INVALID_PARAMETER);
 104         return FALSE;
 105         }
 106 
 107     AnsiStringVDMEnv.Buffer = NULL;
 108     UnicodeStringVDMEnv.Buffer = NULL;
 109 
 110     //
 111     // the lowest specified priority class is used.
 112     //
 113 
 114     if (dwCreationFlags & IDLE_PRIORITY_CLASS ) {
 115         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
 116         }
 117     else if (dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS ) {
 118         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
 119         }
 120     else if (dwCreationFlags & NORMAL_PRIORITY_CLASS ) {
 121         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
 122         }
 123     else if (dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS ) {
 124         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
 125         }
 126     else if (dwCreationFlags & HIGH_PRIORITY_CLASS ) {
 127         PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_HIGH;
 128         }
 129     else if (dwCreationFlags & REALTIME_PRIORITY_CLASS ) {
 130         if ( BasepIsRealtimeAllowed(FALSE) ) {
 131             PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_REALTIME;
 132             }
 133         else {
 134             PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_HIGH;
 135             }
 136         }
 137     else {
 138         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_UNKNOWN;
 139         }
 140     PriClass.Foreground = FALSE;
 141 
 142     dwCreationFlags = (dwCreationFlags & ~PRIORITY_CLASS_MASK );
 143 
 144     //
 145     // Default separate/shared VDM option if not explicitly specified.
 146     //
 147 
 148     if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM) {
 149         if (dwCreationFlags & CREATE_SHARED_WOW_VDM) {
 150             SetLastError(ERROR_INVALID_PARAMETER);
 151 
 152             return FALSE;
 153             }
 154         }
 155     else
 156     if ((dwCreationFlags & CREATE_SHARED_WOW_VDM) == 0) {
 157         if (BaseStaticServerData->DefaultSeparateVDM) {
 158             dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
 159             }
 160         }
 161 
 162     if ((dwCreationFlags & CREATE_SEPARATE_WOW_VDM) == 0) {
 163         //
 164         // If the creator is running inside a job object, always
 165         // set SEPERATE_WOW_VDM so the VDM is part of the job.
 166         //
 167         JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
 168 
 169         Status = NtQueryInformationJobObject(NULL,
 170                                              JobObjectBasicUIRestrictions,
 171                                              &UiRestrictions,
 172                                              sizeof(UiRestrictions),
 173                                              NULL);
 174         if (Status != STATUS_ACCESS_DENIED) {
 175             //
 176             // Anything other than STATUS_ACCESS_DENIED indicates the
 177             // current process is inside a job.
 178             //
 179             dwCreationFlags = (dwCreationFlags & (~CREATE_SHARED_WOW_VDM)) |
 180                                   CREATE_SEPARATE_WOW_VDM;
 181             }
 182         }
 183 
 184 
 185     //
 186     //  If ANSI environment, convert to Unicode
 187     //
 188 
 189     if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
 190         PUCHAR s;
 191         STRING Ansi;
 192         UNICODE_STRING Unicode;
 193         MEMORY_BASIC_INFORMATION MemoryInformation;
 194 
 195         Ansi.Buffer = s = lpEnvironment;
 196         while (*s || *(s+1))            // find end of block
 197             s++;
 198 
 199         Ansi.Length = (USHORT)(s - Ansi.Buffer) + 1;
 200         Ansi.MaximumLength = Ansi.Length + 1;
 201         MemoryInformation.RegionSize = Ansi.MaximumLength * sizeof(WCHAR);
 202         Unicode.Buffer = NULL;
 203         Status = NtAllocateVirtualMemory( NtCurrentProcess(),
 204                                           &Unicode.Buffer,
 205                                           0,
 206                                           &MemoryInformation.RegionSize,
 207                                           MEM_COMMIT,
 208                                           PAGE_READWRITE
 209                                         );
 210         if (!NT_SUCCESS(Status) ) {
 211             BaseSetLastNTError(Status);
 212 
 213             return FALSE;
 214             }
 215 
 216         Unicode.MaximumLength = (USHORT)MemoryInformation.RegionSize;
 217         Status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, FALSE);
 218         if (!NT_SUCCESS(Status) ) {
 219             NtFreeVirtualMemory( NtCurrentProcess(),
 220                                  &Unicode.Buffer,
 221                                  &MemoryInformation.RegionSize,
 222                                  MEM_RELEASE
 223                                );
 224             BaseSetLastNTError(Status);
 225 
 226             return FALSE;
 227             }
 228         lpEnvironment = Unicode.Buffer;
 229         }
 230 
 231     FileHandle = NULL;
 232     SectionHandle = NULL;
 233     ProcessHandle = NULL;
 234     ThreadHandle = NULL;
 235     FreeBuffer = NULL;
 236     NameBuffer = NULL;
 237     VdmNameString.Buffer = NULL;
 238     BaseAddress = (PVOID)1;
 239     VdmReserve = 0;
 240     CurdirBuffer = NULL;
 241     CurdirFilePart = NULL;
 242     SubSysCommandLine.Buffer = NULL;
 243     QuoteFound = FALSE;
 244     QuoteInsert = FALSE;
 245     QuotedBuffer = NULL;
 246 
 247     try {
 248 
 249         //
 250         // Make a copy of the startup info so we can change it.
 251         //
 252 
 253         StartupInfo = *lpStartupInfo;
 254 
 255         //
 256         // STARTF_USEHOTKEY means hStdInput is really the hotkey value.
 257         // STARTF_HASSHELLDATA means std handles are used for shell-private
 258         // data.  This flag is used if an icon is passed to ShellExecuteEx.
 259         // As a result they cannot be specified with STARTF_USESTDHANDLES.
 260         // Consistent with Win95, USESTDHANDLES is ignored.
 261         //
 262 
 263         if (StartupInfo.dwFlags & STARTF_USESTDHANDLES &&
 264             StartupInfo.dwFlags & (STARTF_USEHOTKEY | STARTF_HASSHELLDATA)) {
 265 
 266             StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES;
 267             }
 268 
 269 VdmRetry:
 270         LastError = 0;
 271         SearchRetry = TRUE;
 272         QuoteInsert = FALSE;
 273         QuoteCmdLine = FALSE;
 274         if (!ARGUMENT_PRESENT( lpApplicationName )) {
 275 
 276             //
 277             // Locate the image
 278             //
 279 
 280             // forgot to free NameBuffer before goto VdmRetry???
 281             ASSERT(NameBuffer == NULL);
 282 
 283             NameBuffer = RtlAllocateHeap( RtlProcessHeap(),
 284                                           MAKE_TAG( TMP_TAG ),
 285                                           MAX_PATH * sizeof( WCHAR ));
 286             if ( !NameBuffer ) {
 287                 BaseSetLastNTError(STATUS_NO_MEMORY);
 288                 return FALSE;
 289                 }
 290             lpApplicationName = lpCommandLine;
 291             TempNull = (PWCH)lpApplicationName;
 292             WhiteScan = (LPWSTR)lpApplicationName;
 293 
 294             //
 295             // check for lead quote
 296             //
 297             if ( *WhiteScan == L'\"' ) {
 298                 SearchRetry = FALSE;
 299                 WhiteScan++;
 300                 lpApplicationName = WhiteScan;
 301                 while(*WhiteScan) {
 302                     if ( *WhiteScan == (WCHAR)'\"' ) {
 303                         TempNull = (PWCH)WhiteScan;
 304                         QuoteFound = TRUE;
 305                         break;
 306                         }
 307                     WhiteScan++;
 308                     TempNull = (PWCH)WhiteScan;
 309                     }
 310                 }
 311             else {
 312 retrywsscan:
 313                 lpApplicationName = lpCommandLine;
 314                 while(*WhiteScan) {
 315                     if ( *WhiteScan == (WCHAR)' ' ||
 316                          *WhiteScan == (WCHAR)'\t' ) {
 317                         TempNull = (PWCH)WhiteScan;
 318                         break;
 319                         }
 320                     WhiteScan++;
 321                     TempNull = (PWCH)WhiteScan;
 322                     }
 323                 }
 324             TempChar = *TempNull;
 325             *TempNull = UNICODE_NULL;
 326 
 327 #ifdef WX86
 328 
 329             //
 330             // Wx86 applications must use x86 version of known exes
 331             // for compatibility.
 332             //
 333 
 334             if (UseKnownWx86Dll) {
 335                LPWSTR KnownName;
 336 
 337                NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
 338 
 339                KnownName = BasepWx86KnownExe(lpApplicationName);
 340                if (KnownName) {
 341                   lpApplicationName = KnownName;
 342                   }
 343                }
 344 #endif
 345 
 346 
 347             Length = SearchPathW(
 348                         NULL,
 349                         lpApplicationName,
 350                         (PWSTR)L".exe",
 351                         MAX_PATH,
 352                         NameBuffer,
 353                         NULL
 354                         )*2;
 355 
 356             if (Length != 0 && Length < MAX_PATH * sizeof( WCHAR )) {
 357                 //
 358                 // SearchPathW worked, but file might be a directory
 359                 // if this happens, we need to keep trying
 360                 //
 361                 fileattr = GetFileAttributesW(NameBuffer);
 362                 if ( fileattr != 0xffffffff &&
 363                      (fileattr & FILE_ATTRIBUTE_DIRECTORY) ) {
 364                     Length = 0;
 365                 } else {
 366                     Length++;
 367                     Length++;
 368                 }
 369             }
 370 
 371             if ( !Length || Length >= MAX_PATH<<1 ) {
 372 
 373                 //
 374                 // If we search pathed, then return file not found.
 375                 // otherwise, try to be more specific.
 376                 //
 377                 RTL_PATH_TYPE PathType;
 378                 HANDLE hFile;
 379 
 380                 PathType = RtlDetermineDosPathNameType_U(lpApplicationName);
 381                 if ( PathType != RtlPathTypeRelative ) {
 382 
 383                     //
 384                     // The failed open should set get last error properly.
 385                     //
 386 
 387                     hFile = CreateFileW(
 388                                 lpApplicationName,
 389                                 GENERIC_READ,
 390                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
 391                                 NULL,
 392                                 OPEN_EXISTING,
 393                                 FILE_ATTRIBUTE_NORMAL,
 394                                 NULL
 395                                 );
 396                     if ( hFile != INVALID_HANDLE_VALUE ) {
 397                         CloseHandle(hFile);
 398                         BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
 399                         }
 400                     }
 401                 else {
 402                     BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
 403                     }
 404 
 405                 //
 406                 // remember initial last error value for the retry scan path
 407                 //
 408 
 409                 if ( LastError ) {
 410                     SetLastError(LastError);
 411                     }
 412                 else {
 413                     LastError = GetLastError();
 414                     }
 415 
 416                 //
 417                 // restore the command line
 418                 //
 419 
 420                 *TempNull = TempChar;
 421                 lpApplicationName = NameBuffer;
 422 
 423                 //
 424                 // If we still have command line left, then keep going
 425                 // the point is to march through the command line looking
 426                 // for whitespace so we can try to find an image name
 427                 // launches of things like:
 428                 // c:\word 95\winword.exe /embedding -automation
 429                 // require this. Our first iteration will stop at c:\word, our next
 430                 // will stop at c:\word 95\winword.exe
 431                 //
 432                 if (*WhiteScan && SearchRetry) {
 433                     WhiteScan++;
 434                     TempNull = WhiteScan;
 435                     QuoteInsert = TRUE;
 436                     QuoteFound = TRUE;
 437                     goto retrywsscan;
 438                 }
 439 
 440                 return FALSE;
 441                 }
 442             //
 443             // restore the command line
 444             //
 445 
 446             *TempNull = TempChar;
 447             lpApplicationName = NameBuffer;
 448             }
 449         else
 450         if (!ARGUMENT_PRESENT( lpCommandLine ) || *lpCommandLine == UNICODE_NULL ) {
 451             QuoteCmdLine = TRUE;
 452             lpCommandLine = (LPWSTR)lpApplicationName;
 453             }
 454 
 455 
 456 #ifdef WX86
 457 
 458        //
 459        // Wx86 applications must use x86 version of known exes
 460        // for compatibility.
 461        //
 462 
 463        if (UseKnownWx86Dll) {
 464            LPWSTR KnownName;
 465 
 466            NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
 467 
 468            KnownName = BasepWx86KnownExe(lpApplicationName);
 469            if (KnownName) {
 470 
 471                RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
 472                NameBuffer = KnownName;
 473                lpApplicationName = KnownName;
 474                }
 475            }
 476 
 477 #endif
 478 
 479 
 480         //
 481         // Translate to an NT name.
 482         //
 483 
 484         TranslationStatus = RtlDosPathNameToNtPathName_U(
 485                                 lpApplicationName,
 486                                 &PathName,
 487                                 NULL,
 488                                 &RelativeName
 489                                 );
 490 
 491         if ( !TranslationStatus ) {
 492             SetLastError(ERROR_PATH_NOT_FOUND);
 493 
 494             return FALSE;
 495             }
 496 
 497         // forgot to free FreeBuffer before goto VdmRetry????
 498         ASSERT(FreeBuffer == NULL);
 499         FreeBuffer = PathName.Buffer;
 500 
 501         if ( RelativeName.RelativeName.Length ) {
 502             PathName = *(PUNICODE_STRING)&RelativeName.RelativeName;
 503             }
 504         else {
 505             RelativeName.ContainingDirectory = NULL;
 506             }
 507 
 508         InitializeObjectAttributes(
 509             &Obja,
 510             &PathName,
 511             OBJ_CASE_INSENSITIVE,
 512             RelativeName.ContainingDirectory,
 513             NULL
 514             );
 515 
 516         //
 517         // Open the file for execute access
 518         //
 519 
 520         Status = NtOpenFile(
 521                     &FileHandle,
 522                     SYNCHRONIZE | FILE_EXECUTE,
 523                     &Obja,
 524                     &IoStatusBlock,
 525                     FILE_SHARE_READ | FILE_SHARE_DELETE,
 526                     FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
 527                     );
 528         if (!NT_SUCCESS(Status) ) {
 529 
 530             //
 531             // if we failed, see if this is a device. If it is a device,
 532             // then just return invalid image format
 533             //
 534 
 535             if ( RtlIsDosDeviceName_U((PWSTR)lpApplicationName) ) {
 536                 SetLastError(ERROR_BAD_DEVICE);
 537                 }
 538             else {
 539                 BaseSetLastNTError(Status);
 540                 }
 541 
 542             return FALSE;
 543             }
 544 
 545         //
 546         // If no desktop has been specified, use the caller's
 547         // desktop.
 548         //
 549 
 550         if (StartupInfo.lpDesktop == NULL) {
 551             StartupInfo.lpDesktop =
 552                     (LPWSTR)((PRTL_USER_PROCESS_PARAMETERS)NtCurrentPeb()->
 553                         ProcessParameters)->DesktopInfo.Buffer;
 554             }
 555 
 556         //
 557         // Create a section object backed by the file
 558         //
 559 
 560         Status = NtCreateSection(
 561                     &SectionHandle,
 562                     SECTION_ALL_ACCESS,
 563                     NULL,
 564                     NULL,
 565                     PAGE_EXECUTE,
 566                     SEC_IMAGE,
 567                     FileHandle
 568                     );
 569 
 570 
 571         NtClose(FileHandle);
 572         FileHandle = NULL;
 573 
 574 
 575 
 576         //
 577         // App Certification DLL
 578         //
 579 
 580        if (NT_SUCCESS(Status)) {
 581 
 582           Status = BasepIsProcessAllowed(lpApplicationName);
 583 
 584           if (!NT_SUCCESS(Status)) {
 585             BaseSetLastNTError(Status);
 586             return FALSE;
 587           }
 588 
 589        }
 590 
 591 
 592 
 593         if (!NT_SUCCESS(Status)) {
 594 
 595             switch (Status) {
 596                 // 16 bit OS/2 exe
 597                 case STATUS_INVALID_IMAGE_NE_FORMAT:
 598 #ifdef i386
 599                 //
 600                 // Use OS/2 if x86 (OS/2 not supported on risc),
 601                 //    and CreationFlags don't have forcedos bit
 602                 //    and Registry didn't specify ForceDos
 603                 //
 604                 // else execute as a DOS bound app.
 605                 //
 606                 //
 607 
 608                 if (!(dwCreationFlags & CREATE_FORCEDOS) &&
 609                     !BaseStaticServerData->ForceDos)
 610                   {
 611 
 612                     if ( !BuildSubSysCommandLine( L"OS2 /P ",
 613                                                   lpApplicationName,
 614                                                   lpCommandLine,
 615                                                   &SubSysCommandLine
 616                                                 ) ) {
 617                         return FALSE;
 618                         }
 619 
 620                     lpCommandLine = SubSysCommandLine.Buffer;
 621 
 622                     lpApplicationName = NULL;
 623 
 624                     RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 625                     FreeBuffer = NULL;
 626                     RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
 627                     NameBuffer = NULL;
 628                     goto VdmRetry;
 629                     }
 630 #endif
 631                     // Falls into Dos case, so that stub message will be
 632                     // printed, and bound apps will run w/o OS/2 subsytem
 633 
 634                 // Dos .exe or .com
 635 
 636                 case STATUS_INVALID_IMAGE_PROTECT:
 637                 case STATUS_INVALID_IMAGE_NOT_MZ:
 638 ForceDos:
 639                     {
 640                     ULONG BinarySubType;
 641 
 642                     BinarySubType = BINARY_TYPE_DOS_EXE;
 643                     if (Status == STATUS_INVALID_IMAGE_PROTECT   ||
 644                         Status == STATUS_INVALID_IMAGE_NE_FORMAT ||
 645                        (BinarySubType = BaseIsDosApplication(&PathName,Status)) )
 646                        {
 647                         VdmBinaryType = BINARY_TYPE_DOS;
 648 
 649                         // create the environment before going to the
 650                         // server. This was done becuase we want NTVDM
 651                         // to have the new environment when it gets
 652                         // created.
 653                         if (!BaseCreateVDMEnvironment(
 654                                     lpEnvironment,
 655                                     &AnsiStringVDMEnv,
 656                                     &UnicodeStringVDMEnv
 657                                     ))
 658                             return FALSE;
 659 
 660                         if(!BaseCheckVDM(VdmBinaryType | BinarySubType,
 661                                          lpApplicationName,
 662                                          lpCommandLine,
 663                                          lpCurrentDirectory,
 664                                          &AnsiStringVDMEnv,
 665                                          &m,
 666                                          &iTask,
 667                                          dwCreationFlags,
 668                                          &StartupInfo
 669                                          ))
 670                             return FALSE;
 671 
 672 
 673                         // Check the return value from the server
 674                         switch (b->VDMState & VDM_STATE_MASK){
 675                             case VDM_NOT_PRESENT:
 676                                 // mark this so the server can undo
 677                                 // creation if something goes wrong.
 678                                 // We marked it "partitially created" because
 679                                 // the NTVDM has yet not been fully created.
 680                                 // a call to UpdateVdmEntry to update
 681                                 // process handle will signal the NTVDM
 682                                 // process completed creation
 683                                 VDMCreationState = VDM_PARTIALLY_CREATED;
 684                                 // fail the call if NTVDM process is being
 685                                 // created DETACHED.
 686                                 // note that, we let it go if NTVDM process
 687                                 // is already running.
 688                                 if (dwCreationFlags & DETACHED_PROCESS) {
 689                                     SetLastError(ERROR_ACCESS_DENIED);
 690                                     return FALSE;
 691                                     }
 692                                 if (!BaseGetVdmConfigInfo(lpCommandLine,
 693                                                           iTask,
 694                                                           VdmBinaryType,
 695                                                           &VdmNameString,
 696                                                           &VdmReserve
 697                                                           ))
 698                                    {
 699                                     BaseSetLastNTError(Status);
 700                                     return FALSE;
 701                                     }
 702 
 703                                 lpCommandLine = VdmNameString.Buffer;
 704                                 lpApplicationName = NULL;
 705 
 706                                 break;
 707 
 708                             case VDM_PRESENT_NOT_READY:
 709                                 SetLastError (ERROR_NOT_READY);
 710                                 return FALSE;
 711 
 712                             case VDM_PRESENT_AND_READY:
 713                                 VDMCreationState = VDM_BEING_REUSED;
 714                                 VdmWaitHandle = b->WaitObjectForParent;
 715                                 break;
 716                             }
 717                          RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 718                          FreeBuffer = NULL;
 719                          RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
 720                          NameBuffer = NULL;
 721                          VdmReserve--;               // we reserve from addr 1
 722                          if(VdmWaitHandle)
 723                             goto VdmExists;
 724                          else{
 725                             bInheritHandles = FALSE;
 726                             if (lpEnvironment &&
 727                                 !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)){
 728                                 RtlDestroyEnvironment(lpEnvironment);
 729                                 }
 730                             lpEnvironment = UnicodeStringVDMEnv.Buffer;
 731                             goto VdmRetry;
 732                             }
 733                         }
 734                     else {
 735 
 736                         //
 737                         //  must be a .bat or .cmd file
 738                         //
 739 
 740                         static PWCHAR CmdPrefix = L"cmd /c ";
 741                         PWCHAR NewCommandLine;
 742                         ULONG Length;
 743                         PWCHAR Last4 = &PathName.Buffer[PathName.Length / sizeof( WCHAR )-4];
 744 
 745                         if ( PathName.Length < 8 ) {
 746                             SetLastError(ERROR_BAD_EXE_FORMAT);
 747                             return FALSE;
 748                             }
 749 
 750                         if (_wcsnicmp( Last4, L".bat", 4 ) && _wcsnicmp( Last4, L".cmd", 4 )) {
 751                             SetLastError(ERROR_BAD_EXE_FORMAT);
 752                             return FALSE;
 753                         }
 754 
 755                         Length = wcslen( CmdPrefix )
 756                                  + (QuoteCmdLine || QuoteFound )
 757                                  + wcslen( lpCommandLine )
 758                                  + (QuoteCmdLine || QuoteFound)
 759                                  + 1;
 760 
 761                         NewCommandLine = RtlAllocateHeap( RtlProcessHeap( ),
 762                                                           MAKE_TAG( TMP_TAG ),
 763                                                           Length * sizeof( WCHAR ) );
 764 
 765                         if (NewCommandLine == NULL) {
 766                             BaseSetLastNTError(STATUS_NO_MEMORY);
 767                             return FALSE;
 768                         }
 769 
 770                         wcscpy( NewCommandLine, CmdPrefix );
 771                         if (QuoteCmdLine || QuoteFound) {
 772                             wcscat( NewCommandLine, L"\"" );
 773                         }
 774                         wcscat( NewCommandLine, lpCommandLine );
 775                         if (QuoteCmdLine || QuoteFound) {
 776                             wcscat( NewCommandLine, L"\"" );
 777                         }
 778 
 779                         RtlInitUnicodeString( &SubSysCommandLine, NewCommandLine );
 780 
 781                         lpCommandLine = SubSysCommandLine.Buffer;
 782 
 783                         lpApplicationName = NULL;
 784 
 785                         RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 786                         FreeBuffer = NULL;
 787                         RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
 788                         NameBuffer = NULL;
 789                         goto VdmRetry;
 790 
 791                         }
 792 
 793                     }
 794 
 795                 // 16 bit windows exe
 796                 case STATUS_INVALID_IMAGE_WIN_16:
 797 #if defined(BUILD_WOW6432) || defined(_WIN64)
 798                    if (lpOriginalApplicationName == NULL) {
 799                        // pass in the part of the command line after the exe name
 800                        // including whitespace
 801                        lpCommandLine = ((*TempNull == '\"') ? TempNull + 1 : TempNull);
 802                    } else {
 803                        lpCommandLine = lpOriginalCommandLine;
 804                    }
 805                    return NtVdm64CreateProcess(lpOriginalApplicationName == NULL,
 806                                                lpApplicationName,             // this is now the real file name we've loaded
 807                                                lpCommandLine,
 808                                                lpProcessAttributes,
 809                                                lpThreadAttributes,
 810                                                bInheritHandles,
 811                                                (dwCreationFlags & ~CREATE_UNICODE_ENVIRONMENT),  // the environment has already been converted to unicode
 812                                                lpEnvironment,
 813                                                lpCurrentDirectory,
 814                                                lpStartupInfo,
 815                                                lpProcessInformation
 816                                                );
 817 #endif
 818                    if (dwCreationFlags & CREATE_FORCEDOS) {
 819                        goto ForceDos;
 820                        }
 821 
 822                     IsWowBinary = TRUE;
 823                     if (!BaseCreateVDMEnvironment(lpEnvironment,
 824                                                   &AnsiStringVDMEnv,
 825                                                   &UnicodeStringVDMEnv
 826                                                   ))
 827                        {
 828                         return FALSE;
 829                         }
 830 
 831 
 832 
 833 RetrySepWow:
 834                     VdmBinaryType = dwCreationFlags & CREATE_SEPARATE_WOW_VDM
 835                                      ? BINARY_TYPE_SEPWOW : BINARY_TYPE_WIN16;
 836 
 837                     if (!BaseCheckVDM(VdmBinaryType,
 838                                       lpApplicationName,
 839                                       lpCommandLine,
 840                                       lpCurrentDirectory,
 841                                       &AnsiStringVDMEnv,
 842                                       &m,
 843                                       &iTask,
 844                                       dwCreationFlags,
 845                                       &StartupInfo
 846                                       ))
 847                        {
 848                         //
 849                         // If we failed with access denied, caller may not
 850                         // be allowed allowed to access the shared wow's
 851                         // desktop, so retry as a separate wow
 852                         //
 853                         if (VdmBinaryType == BINARY_TYPE_WIN16 &&
 854                             GetLastError() == ERROR_ACCESS_DENIED)
 855                           {
 856                            dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
 857                            }
 858                         else {
 859                            return FALSE;
 860                            }
 861                         goto RetrySepWow;
 862                         }
 863 
 864 
 865                     // Check the return value from the server
 866                     switch (b->VDMState & VDM_STATE_MASK){
 867                         case VDM_NOT_PRESENT:
 868                             // mark this so the server can undo
 869                             // creation if something goes wrong.
 870                             // We marked it "partitially created" because
 871                             // the NTVDM has yet not been fully created.
 872                             // a call to UpdateVdmEntry to update
 873                             // process handle will signal the NTVDM
 874                             // process completed creation
 875 
 876                             VDMCreationState = VDM_PARTIALLY_CREATED;
 877 
 878                             if (!BaseGetVdmConfigInfo(
 879                                     lpCommandLine,
 880                                     iTask,
 881                                     VdmBinaryType,
 882                                     &VdmNameString,
 883                                     &VdmReserve
 884                                     ))
 885                                {
 886                                 BaseSetLastNTError(Status);
 887                                 return FALSE;
 888                                 }
 889 
 890                             lpCommandLine = VdmNameString.Buffer;
 891                             lpApplicationName = NULL;
 892 
 893 
 894                             //
 895                             // Wow must have a hidden console
 896                             // Throw away DETACHED_PROCESS flag which isn't
 897                             // meaningful for Win16 apps.
 898                             //
 899 
 900                             dwCreationFlags |= CREATE_NO_WINDOW;
 901                             dwCreationFlags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS);
 902 
 903 
 904                             //
 905                             // We're starting a WOW VDM, turn on feedback unless
 906                             // the creator passed STARTF_FORCEOFFFEEDBACK.
 907                             //
 908 
 909                             StartupInfo.dwFlags |= STARTF_FORCEONFEEDBACK;
 910 
 911                             break;
 912 
 913                         case VDM_PRESENT_NOT_READY:
 914                             SetLastError (ERROR_NOT_READY);
 915                             return FALSE;
 916 
 917                         case VDM_PRESENT_AND_READY:
 918                             VDMCreationState = VDM_BEING_REUSED;
 919                             VdmWaitHandle = b->WaitObjectForParent;
 920                             break;
 921                         }
 922 
 923                     RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 924                     FreeBuffer = NULL;
 925                     RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
 926                     NameBuffer = NULL;
 927                     VdmReserve--;               // we reserve from addr 1
 928                     if(VdmWaitHandle)
 929                         goto VdmExists;
 930                     else {
 931                         bInheritHandles = FALSE;
 932                         // replace the environment with ours
 933                         if (lpEnvironment &&
 934                             !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) {
 935                             RtlDestroyEnvironment(lpEnvironment);
 936                             }
 937                         lpEnvironment = UnicodeStringVDMEnv.Buffer;
 938                         goto VdmRetry;
 939                         }
 940 
 941 
 942                 default :
 943                     SetLastError(ERROR_BAD_EXE_FORMAT);
 944                     return FALSE;
 945             }
 946         }
 947 
 948         //
 949         // Make sure only WOW apps can have the CREATE_SEPARATE_WOW_VDM flag.
 950         //
 951 
 952         if (!IsWowBinary && (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)) {
 953             dwCreationFlags &= ~CREATE_SEPARATE_WOW_VDM;
 954         }
 955 
 956         //
 957         // Query the section to determine the stack parameters and
 958         // image entrypoint.
 959         //
 960 
 961         Status = NtQuerySection(
 962                     SectionHandle,
 963                     SectionImageInformation,
 964                     &ImageInformation,
 965                     sizeof( ImageInformation ),
 966                     NULL
 967                     );
 968 
 969         if (!NT_SUCCESS( Status )) {
 970             BaseSetLastNTError(Status);
 971             RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 972             FreeBuffer = NULL;
 973             return FALSE;
 974             }
 975 
 976         if (ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL) {
 977             SetLastError(ERROR_BAD_EXE_FORMAT);
 978             RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
 979             FreeBuffer = NULL;
 980             return FALSE;
 981             }
 982 
 983         ImageFileDebuggerCommand[ 0 ] = UNICODE_NULL;
 984         if (!(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) ||
 985             NtCurrentPeb()->ReadImageFileExecOptions
 986            ) {
 987             LdrQueryImageFileExecutionOptions( &PathName,
 988                                                L"Debugger",
 989                                                REG_SZ,
 990                                                ImageFileDebuggerCommand,
 991                                                sizeof( ImageFileDebuggerCommand ),
 992                                                NULL
 993                                              );
 994             }
 995 
 996 
 997 
 998         if ((ImageInformation.Machine < USER_SHARED_DATA->ImageNumberLow) ||
 999             (ImageInformation.Machine > USER_SHARED_DATA->ImageNumberHigh)) {
1000 #if defined(WX86) || defined(_AXP64_)
1001             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_I386)
1002                {
1003                 Wx86Info = (HANDLE)UIntToPtr(sizeof(WX86TIB));
1004                 }
1005             else
1006 #endif // WX86
1007 #if defined(_AXP64_)
1008             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_ALPHA) {
1009                // Fall through since this is a valid machine type.
1010                 }
1011              else
1012 #elif defined(_IA64_)
1013             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_I386) {
1014                // Fall through since this is a valid machine type.
1015                 }
1016              else
1017 #endif // _AXP64_
1018 #if defined(BUILD_WOW6432)
1019             // 32-bit kernel32.dll on NT64 can run 64-bit binaries
1020 #if defined(_ALPHA_)
1021             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_ALPHA) {
1022                // Fall through since this is a valid machine type.
1023                 }
1024              else
1025 #elif defined(_X86_)
1026             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_I386) {
1027                // Fall through since this is a valid machine type.
1028                 }
1029              else
1030 #endif  // ALPHA or IA64
1031 #endif  // BUILD_WOW6432
1032                 {
1033                 ULONG_PTR ErrorParameters[2];
1034                 ULONG ErrorResponse;
1035 
1036                 ErrorResponse = ResponseOk;
1037                 ErrorParameters[0] = (ULONG_PTR)&PathName;
1038 
1039                 NtRaiseHardError( STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
1040                                   1,
1041                                   1,
1042                                   ErrorParameters,
1043                                   OptionOk,
1044                                   &ErrorResponse
1045                                 );
1046                 if ( NtCurrentPeb()->ImageSubsystemMajorVersion <= 3 ) {
1047                     SetLastError(ERROR_BAD_EXE_FORMAT);
1048                     }
1049                 else {
1050                     SetLastError(ERROR_EXE_MACHINE_TYPE_MISMATCH);
1051                     }
1052                 RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
1053                 FreeBuffer = NULL;
1054                 return FALSE;
1055                 }
1056             }
1057 
1058         RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
1059         FreeBuffer = NULL;
1060         if ( ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_GUI &&
1061              ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_CUI ) {
1062 
1063             // POSIX exe
1064 
1065             NtClose(SectionHandle);
1066             SectionHandle = NULL;
1067 
1068             if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_POSIX_CUI ) {
1069 
1070                 if ( !BuildSubSysCommandLine( L"POSIX /P ",
1071                                               lpApplicationName,
1072                                               lpCommandLine,
1073                                               &SubSysCommandLine
1074                                             ) ) {
1075                     return FALSE;
1076                 }
1077 
1078                 lpCommandLine = SubSysCommandLine.Buffer;
1079 
1080                 lpApplicationName = NULL;
1081                 RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
1082                 NameBuffer = NULL;
1083                 goto VdmRetry;
1084                 }
1085             else {
1086                 SetLastError(ERROR_CHILD_NOT_COMPLETE);
1087                 return FALSE;
1088                 }
1089             }
1090         else {
1091             if (!BasepIsImageVersionOk( ImageInformation.SubSystemMajorVersion,
1092                                         ImageInformation.SubSystemMinorVersion) ) {
1093                 SetLastError(ERROR_BAD_EXE_FORMAT);
1094                 return FALSE;
1095                 }
1096             }
1097 
1098         if (ImageFileDebuggerCommand[ 0 ] != UNICODE_NULL) {
1099             USHORT n;
1100 
1101             n = (USHORT)wcslen( lpCommandLine );
1102             if (n == 0) {
1103                 lpCommandLine = (LPWSTR)lpApplicationName;
1104                 n = (USHORT)wcslen( lpCommandLine );
1105                 }
1106 
1107             n += wcslen( ImageFileDebuggerCommand ) + 1 + 2;
1108             n *= sizeof( WCHAR );
1109 
1110             SubSysCommandLine.Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), n );
1111             SubSysCommandLine.Length = 0;
1112             SubSysCommandLine.MaximumLength = n;
1113             RtlAppendUnicodeToString( &SubSysCommandLine, ImageFileDebuggerCommand );
1114             RtlAppendUnicodeToString( &SubSysCommandLine, L" " );
1115             RtlAppendUnicodeToString( &SubSysCommandLine, (PWSTR)lpCommandLine );
1116 #if DBG
1117             DbgPrint( "BASE: Calling debugger with '%wZ'\n", &SubSysCommandLine );
1118 #endif
1119             lpCommandLine = SubSysCommandLine.Buffer;
1120             lpApplicationName = NULL;
1121 
1122             NtClose(SectionHandle);
1123             SectionHandle = NULL;
1124             RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
1125             NameBuffer = NULL;
1126             goto VdmRetry;
1127             }
1128 
1129         //
1130         // Create the process object
1131         //
1132 
1133         pObja = BaseFormatObjectAttributes(&Obja,lpProcessAttributes,NULL);
1134 
1135         if (dwCreationFlags & CREATE_BREAKAWAY_FROM_JOB ) {
1136             SectionHandle = (HANDLE)( (UINT_PTR)SectionHandle | 1);
1137             }
1138 
1139         Status = NtCreateProcess(
1140                     &ProcessHandle,
1141                     PROCESS_ALL_ACCESS,
1142                     pObja,
1143                     NtCurrentProcess(),
1144                     (BOOLEAN)bInheritHandles,
1145                     SectionHandle,
1146                     NULL,
1147                     NULL
1148                     );
1149         if ( !NT_SUCCESS(Status) ) {
1150             BaseSetLastNTError(Status);
1151             return FALSE;
1152             }
1153 
1154         //
1155         // NtCreateProcess will set to normal OR inherit if parent is IDLE or Below
1156         // only override if a mask is given during the create.
1157         //
1158 
1159         if ( PriClass.PriorityClass != PROCESS_PRIORITY_CLASS_UNKNOWN ) {
1160             State = NULL;
1161             if ( PriClass.PriorityClass ==  PROCESS_PRIORITY_CLASS_REALTIME ) {
1162                 State = BasepIsRealtimeAllowed(TRUE);
1163                 }
1164             Status = NtSetInformationProcess(
1165                         ProcessHandle,
1166                         ProcessPriorityClass,
1167                         (PVOID)&PriClass,
1168                         sizeof(PriClass)
1169                         );
1170             if ( State ) {
1171                 BasepReleasePrivilege( State );
1172                 }
1173 
1174             if ( !NT_SUCCESS(Status) ) {
1175                 BaseSetLastNTError(Status);
1176                 return FALSE;
1177                 }
1178             }
1179 
1180         NtClose(SectionHandle);
1181         SectionHandle = NULL;
1182 
1183         if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE) {
1184             UINT NewMode;
1185             NewMode = SEM_FAILCRITICALERRORS;
1186             NtSetInformationProcess(
1187                 ProcessHandle,
1188                 ProcessDefaultHardErrorMode,
1189                 (PVOID) &NewMode,
1190                 sizeof(NewMode)
1191                 );
1192             }
1193 
1194         //
1195         // If the process is being created for a VDM call the server with
1196         // process handle.
1197         //
1198 
1199         if (VdmBinaryType) {
1200             VdmWaitHandle = ProcessHandle;
1201             if (!BaseUpdateVDMEntry(UPDATE_VDM_PROCESS_HANDLE,
1202                                     &VdmWaitHandle,
1203                                     iTask,
1204                                     VdmBinaryType
1205                                     ))
1206                {
1207                 //make sure we don't close the handle twice --
1208                 //(VdmWaitHandle == ProcessHandle) if we don't do this.
1209                 VdmWaitHandle = NULL;
1210                 return FALSE;
1211                 }
1212 
1213             //
1214             // For Sep wow the VdmWaitHandle = NULL (there is none!)
1215             //
1216 
1217             VDMCreationState |= VDM_FULLY_CREATED;
1218             }
1219 
1220         //
1221         // if we're a detached priority, we don't have the focus, so
1222         // don't create with boosted priority.
1223         //
1224 
1225         if (dwCreationFlags & DETACHED_PROCESS) {
1226             KPRIORITY SetBasePriority;
1227 
1228             SetBasePriority = (KPRIORITY)NORMAL_BASE_PRIORITY;
1229             Status =  NtSetInformationProcess(ProcessHandle,
1230                                               ProcessBasePriority,
1231                                               (PVOID) &SetBasePriority,
1232                                               sizeof(SetBasePriority)
1233                                               );
1234             ASSERT(NT_SUCCESS(Status));
1235         }
1236 
1237 #if defined(i386) || defined(_IA64_)
1238         //
1239         // Reserve memory in the new process' address space if necessary
1240         // (for vdms). This is required only for x86 system.
1241         //
1242 
1243     if ( VdmReserve ) {
1244             BigVdmReserve = VdmReserve;
1245             Status = NtAllocateVirtualMemory(
1246                         ProcessHandle,
1247                         &BaseAddress,
1248                         0L,
1249                         &BigVdmReserve,
1250                         MEM_RESERVE,
1251                         PAGE_EXECUTE_READWRITE
1252                         );
1253             if ( !NT_SUCCESS(Status) ){
1254                 BaseSetLastNTError(Status);
1255                 return FALSE;
1256             }
1257     }
1258 #endif
1259 
1260         //
1261         // Determine the location of the
1262         // processes PEB.
1263         //
1264 
1265         Status = NtQueryInformationProcess(
1266                     ProcessHandle,
1267                     ProcessBasicInformation,
1268                     &ProcessInfo,
1269                     sizeof( ProcessInfo ),
1270                     NULL
1271                     );
1272         if ( !NT_SUCCESS( Status ) ) {
1273             BaseSetLastNTError(Status);
1274             return FALSE;
1275             }
1276 
1277         Peb = ProcessInfo.PebBaseAddress;
1278 
1279         //
1280         // Push the parameters into the address space of the new process
1281         //
1282 
1283         if ( ARGUMENT_PRESENT(lpCurrentDirectory) ) {
1284             CurdirBuffer = RtlAllocateHeap( RtlProcessHeap(),
1285                                             MAKE_TAG( TMP_TAG ),
1286                                             (MAX_PATH + 1) * sizeof( WCHAR ) );
1287             if ( !CurdirBuffer ) {
1288                 BaseSetLastNTError(STATUS_NO_MEMORY);
1289                 return FALSE;
1290                 }
1291             CurdirLength2 = GetFullPathNameW(
1292                                 lpCurrentDirectory,
1293                                 MAX_PATH,
1294                                 CurdirBuffer,
1295                                 &CurdirFilePart
1296                                 );
1297             if ( CurdirLength2 > MAX_PATH ) {
1298                 SetLastError(ERROR_DIRECTORY);
1299                 return FALSE;
1300                 }
1301 
1302             //
1303             // now make sure the directory exists
1304             //
1305 
1306             CurdirLength = GetFileAttributesW(CurdirBuffer);
1307             if ( (CurdirLength == 0xffffffff) ||
1308                  !(CurdirLength & FILE_ATTRIBUTE_DIRECTORY) ) {
1309                 SetLastError(ERROR_DIRECTORY);
1310                 return FALSE;
1311                 }
1312             }
1313 
1314 
1315         if ( QuoteInsert || QuoteCmdLine) {
1316             QuotedBuffer = RtlAllocateHeap(RtlProcessHeap(),0,wcslen(lpCommandLine)*2+6);
1317 
1318             if ( QuotedBuffer ) {
1319                 wcscpy(QuotedBuffer,L"\"");
1320 
1321                 if ( QuoteInsert ) {
1322                     TempChar = *TempNull;
1323                     *TempNull = UNICODE_NULL;
1324                     }
1325 
1326                 wcscat(QuotedBuffer,lpCommandLine);
1327                 wcscat(QuotedBuffer,L"\"");
1328 
1329                 if ( QuoteInsert ) {
1330                     *TempNull = TempChar;
1331                     wcscat(QuotedBuffer,TempNull);
1332                     }
1333 
1334                 }
1335             else {
1336                 if ( QuoteInsert ) {
1337                     QuoteInsert = FALSE;
1338                     }
1339                 if ( QuoteCmdLine ) {
1340                     QuoteCmdLine = FALSE;
1341                     }
1342                 }
1343             }
1344 
1345 
1346         if (!BasePushProcessParameters(
1347                 ProcessHandle,
1348                 Peb,
1349                 lpApplicationName,
1350                 CurdirBuffer,
1351                 QuoteInsert || QuoteCmdLine ? QuotedBuffer : lpCommandLine,
1352                 lpEnvironment,
1353                 &StartupInfo,
1354                 dwCreationFlags | dwNoWindow,
1355                 bInheritHandles,
1356                 IsWowBinary ? IMAGE_SUBSYSTEM_WINDOWS_GUI : 0
1357                 ) ) {
1358             return FALSE;
1359             }
1360 
1361 
1362         RtlFreeUnicodeString(&VdmNameString);
1363         VdmNameString.Buffer = NULL;
1364 
1365         //
1366         // Stuff in the standard handles if needed
1367         //
1368         if (!VdmBinaryType &&
1369             !bInheritHandles &&
1370             !(StartupInfo.dwFlags & STARTF_USESTDHANDLES) &&
1371             !(dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE | CREATE_NO_WINDOW)) &&
1372             ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI
1373            ) {
1374             PRTL_USER_PROCESS_PARAMETERS ParametersInNewProcess;
1375 
1376             Status = NtReadVirtualMemory( ProcessHandle,
1377                                           &Peb->ProcessParameters,
1378                                           &ParametersInNewProcess,
1379                                           sizeof( ParametersInNewProcess ),
1380                                           NULL
1381                                         );
1382             if (NT_SUCCESS( Status )) {
1383                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardInput )) {
1384                     StuffStdHandle( ProcessHandle,
1385                                     NtCurrentPeb()->ProcessParameters->StandardInput,
1386                                     &ParametersInNewProcess->StandardInput
1387                                   );
1388                     }
1389                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardOutput )) {
1390                     StuffStdHandle( ProcessHandle,
1391                                     NtCurrentPeb()->ProcessParameters->StandardOutput,
1392                                     &ParametersInNewProcess->StandardOutput
1393                                   );
1394                     }
1395                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardError )) {
1396                     StuffStdHandle( ProcessHandle,
1397                                     NtCurrentPeb()->ProcessParameters->StandardError,
1398                                     &ParametersInNewProcess->StandardError
1399                                   );
1400                     }
1401                 }
1402             }
1403 
1404         //
1405         // Create the thread...
1406         //
1407 
1408         //
1409         // Allocate a stack for this thread in the address space of the target
1410         // process.
1411         //
1412 
1413         StackStatus = BaseCreateStack(
1414                         ProcessHandle,
1415                         ImageInformation.CommittedStackSize,
1416                         (ImageInformation.MaximumStackSize < 256*1024) ? 256*1024 : ImageInformation.MaximumStackSize,
1417                         &InitialTeb
1418                         );
1419 
1420         if ( !NT_SUCCESS(StackStatus) ) {
1421             BaseSetLastNTError(StackStatus);
1422             return FALSE;
1423             }
1424 
1425 
1426         //
1427         // Create an initial context for the new thread.
1428         //
1429 
1430         BaseInitializeContext(
1431             &ThreadContext,
1432             Peb,
1433             ImageInformation.TransferAddress,
1434             InitialTeb.StackBase,
1435             BaseContextTypeProcess
1436             );
1437 
1438 
1439         //
1440         // Create the actual thread object
1441         //
1442 
1443         pObja = BaseFormatObjectAttributes(&Obja,lpThreadAttributes,NULL);
1444 
1445         Status = NtCreateThread(
1446                     &ThreadHandle,
1447                     THREAD_ALL_ACCESS,
1448                     pObja,
1449                     ProcessHandle,
1450                     &ClientId,
1451                     &ThreadContext,
1452                     &InitialTeb,
1453                     TRUE
1454                     );
1455 
1456         if (!NT_SUCCESS(Status) ) {
1457             BaseSetLastNTError(Status);
1458             return FALSE;
1459             }
1460 
1461         //
1462         // From here on out, do not modify the address space of the
1463         // new process.  WOW64's implementation of NtCreateThread()
1464         // reshuffles the new process' address space if the current
1465         // process is 32-bit and the new process is 64-bit.
1466         //
1467 #if DBG
1468         Peb = NULL;
1469 #endif
1470 
1471 #if defined(WX86) || defined(_AXP64_)
1472 
1473         //
1474         // if this is a Wx86 Process, setup for a Wx86 emulated Thread
1475         //
1476 
1477         if (Wx86Info) {
1478 
1479             //
1480             // create a WX86Tib and initialize it's Teb->Vdm.
1481             //
1482             Status = BaseCreateWx86Tib(ProcessHandle,
1483                                        ThreadHandle,
1484                                        (ULONG)((ULONG_PTR)ImageInformation.TransferAddress),
1485                                        (ULONG)ImageInformation.CommittedStackSize,
1486                                        (ULONG)ImageInformation.MaximumStackSize,
1487                                        TRUE
1488                                        );
1489 
1490             if (!NT_SUCCESS(Status)) {
1491                 BaseSetLastNTError(Status);
1492                 return( FALSE );
1493                 }
1494 
1495 
1496             //
1497             // Mark Process as WX86
1498             //
1499             Status = NtSetInformationProcess (ProcessHandle,
1500                                               ProcessWx86Information,
1501                                               &Wx86Info,
1502                                               sizeof(Wx86Info)
1503                                               );
1504 
1505             if (!NT_SUCCESS(Status)) {
1506                 BaseSetLastNTError(Status);
1507                 return( FALSE );
1508                 }
1509             }
1510 #endif
1511 
1512 
1513         //
1514         // Call the Windows server to let it know about the
1515         // process.
1516         //
1517 
1518         a->ProcessHandle = ProcessHandle;
1519         a->ThreadHandle = ThreadHandle;
1520         a->ClientId = ClientId;
1521         a->CreationFlags = dwCreationFlags;
1522 
1523         if ( dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) ) {
1524             Status = DbgUiConnectToDbg();
1525             if ( !NT_SUCCESS(Status) ) {
1526                 NtTerminateProcess(ProcessHandle, Status);
1527                 BaseSetLastNTError(Status);
1528                 return FALSE;
1529                 }
1530             a->DebuggerClientId = NtCurrentTeb()->ClientId;
1531             }
1532         else {
1533             a->DebuggerClientId.UniqueProcess = NULL;
1534             a->DebuggerClientId.UniqueThread = NULL;
1535             }
1536 
1537         //
1538         // Set the 2 bit if a gui app is starting. The window manager needs to
1539         // know this so it can synchronize the startup of this app
1540         // (WaitForInputIdle api). This info is passed using the process
1541         // handle tag bits.  The 1 bit asks the window manager to turn on
1542         // or turn off the application start cursor (hourglass/pointer).
1543         //
1544         // When starting a WOW process, lie and tell UserSrv NTVDM.EXE is a GUI
1545         // process.  We also turn on bit 0x8 so that UserSrv can ignore the
1546         // UserNotifyConsoleApplication call made by the console during startup.
1547         //
1548 
1549         if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI ||
1550              IsWowBinary ) {
1551 
1552             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 2);
1553 
1554             //
1555             // If the creating process is a GUI app, turn on the app. start cursor
1556             // by default.  This can be overridden by STARTF_FORCEOFFFEEDBACK.
1557             //
1558 
1559             NtHeaders = RtlImageNtHeader((PVOID)GetModuleHandle(NULL));
1560             if ( NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI )
1561                 a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
1562 
1563             }
1564 
1565 
1566         //
1567         // If feedback is forced on, turn it on. If forced off, turn it off.
1568         // Off overrides on.
1569         //
1570 
1571         if (StartupInfo.dwFlags & STARTF_FORCEONFEEDBACK)
1572             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
1573         if (StartupInfo.dwFlags & STARTF_FORCEOFFFEEDBACK)
1574             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle & ~1);
1575 
1576         a->VdmBinaryType = VdmBinaryType; // just tell server the truth
1577 
1578         if (VdmBinaryType){
1579            a->hVDM    = iTask ? 0 : NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1580            a->VdmTask = iTask;
1581         }
1582 
1583 #if defined(BUILD_WOW6432)
1584         m.ReturnValue = CsrBasepCreateProcess(a);
1585 #else
1586         CsrClientCallServer( (PCSR_API_MSG)&m,
1587                              NULL,
1588                              CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
1589                                                   BasepCreateProcess
1590                                                 ),
1591                              sizeof( *a )
1592                            );
1593 #endif
1594 
1595         if (!NT_SUCCESS((NTSTATUS)m.ReturnValue)) {
1596             BaseSetLastNTError((NTSTATUS)m.ReturnValue);
1597             NtTerminateProcess(ProcessHandle, (NTSTATUS)m.ReturnValue);
1598             return FALSE;
1599             }
1600 
1601 
1602         if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
1603             NtResumeThread(ThreadHandle,&i);
1604             }
1605 
1606 VdmExists:
1607         bStatus = TRUE;
1608         if (VDMCreationState)
1609             VDMCreationState |= VDM_CREATION_SUCCESSFUL;
1610 
1611         try {
1612             if (VdmWaitHandle) {
1613 
1614                 //
1615                 // tag Shared WOW VDM handles so that wait for input idle has a
1616                 // chance to work.  Shared WOW VDM "process" handles are actually
1617                 // event handles,  Separate WOW VDM handles are real process
1618                 // handles. Also mark DOS handles with 0x1 so WaitForInputIdle
1619                 // has a way to distinguish DOS apps and not block forever.
1620                 //
1621 
1622                 if (VdmBinaryType == BINARY_TYPE_WIN16)  {
1623                     lpProcessInformation->hProcess =
1624                             (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x2);
1625 
1626                     //
1627                     // Shared WOW doesn't always start a process, so
1628                     // we don't have a process ID or thread ID to
1629                     // return if the VDM already existed.
1630                     //
1631                     // Separate WOW doesn't hit this codepath
1632                     // (no VdmWaitHandle).
1633                     //
1634 
1635                     if (VDMCreationState & VDM_BEING_REUSED) {
1636                         ClientId.UniqueProcess = 0;
1637                         ClientId.UniqueThread = 0;
1638                         }
1639 
1640                     }
1641                 else  {
1642                     lpProcessInformation->hProcess =
1643                             (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x1);
1644                     }
1645 
1646 
1647                 //
1648                 // Close the ProcessHandle, since we are returning the
1649                 // VdmProcessHandle instead.
1650                 //
1651 
1652                 if (ProcessHandle != NULL)
1653                     NtClose(ProcessHandle);
1654                 }
1655             else{
1656                 lpProcessInformation->hProcess = ProcessHandle;
1657                 }
1658 
1659             lpProcessInformation->hThread = ThreadHandle;
1660             lpProcessInformation->dwProcessId = HandleToUlong(ClientId.UniqueProcess);
1661             lpProcessInformation->dwThreadId = HandleToUlong(ClientId.UniqueThread);
1662             ProcessHandle = NULL;
1663             ThreadHandle = NULL;
1664             }
1665         except ( EXCEPTION_EXECUTE_HANDLER ) {
1666             NtClose( ProcessHandle );
1667             NtClose( ThreadHandle );
1668             ProcessHandle = NULL;
1669             ThreadHandle = NULL;
1670             if (VDMCreationState)
1671                 VDMCreationState &= ~VDM_CREATION_SUCCESSFUL;
1672             }
1673         }
1674     finally {
1675         if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
1676             RtlDestroyEnvironment(lpEnvironment);
1677             lpEnvironment = NULL;
1678             }
1679         RtlFreeHeap(RtlProcessHeap(), 0,QuotedBuffer);
1680         RtlFreeHeap(RtlProcessHeap(), 0,NameBuffer);
1681         RtlFreeHeap(RtlProcessHeap(), 0,CurdirBuffer);
1682         RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
1683         if ( FileHandle ) {
1684             NtClose(FileHandle);
1685             }
1686         if ( SectionHandle ) {
1687             NtClose(SectionHandle);
1688             }
1689         if ( ThreadHandle ) {
1690             NtTerminateProcess(ProcessHandle,STATUS_SUCCESS);
1691             NtClose(ThreadHandle);
1692             }
1693         if ( ProcessHandle ) {
1694             NtClose(ProcessHandle);
1695             }
1696         RtlFreeUnicodeString(&VdmNameString);
1697         RtlFreeUnicodeString(&SubSysCommandLine);
1698         if (AnsiStringVDMEnv.Buffer || UnicodeStringVDMEnv.Buffer)
1699             BaseDestroyVDMEnvironment(&AnsiStringVDMEnv, &UnicodeStringVDMEnv);
1700 
1701         if (VDMCreationState && !(VDMCreationState & VDM_CREATION_SUCCESSFUL)){
1702             BaseUpdateVDMEntry (
1703                 UPDATE_VDM_UNDO_CREATION,
1704                 (HANDLE *)&iTask,
1705                 VDMCreationState,
1706                 VdmBinaryType
1707                 );
1708             if(VdmWaitHandle) {
1709                 NtClose(VdmWaitHandle);
1710                 }
1711             }
1712         }
1713 
1714     if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
1715         RtlDestroyEnvironment(lpEnvironment);
1716         }
1717     return bStatus;
1718 }
CreateProcessW

 

相关文章: