Advertisement
RusNuker

Source code for CreateProcessInternalW @ kernel32.dll

Jul 7th, 2023 (edited)
1,105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 87.03 KB | Source Code | 0 0
  1. BOOL
  2. WINAPI
  3. CreateProcessInternalW(
  4.     HANDLE hUserToken,
  5.     LPCWSTR lpApplicationName,
  6.     LPWSTR lpCommandLine,
  7.     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  8.     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  9.     BOOL bInheritHandles,
  10.     DWORD dwCreationFlags,
  11.     LPVOID lpEnvironment,
  12.     LPCWSTR lpCurrentDirectory,
  13.     LPSTARTUPINFOW lpStartupInfo,
  14.     LPPROCESS_INFORMATION lpProcessInformation,
  15.     PHANDLE hRestrictedUserToken
  16.     )
  17.  
  18. /*++
  19.  
  20. Routine Description:
  21.  
  22.     This is the worker routine for CreateProcess and CreateProcessAsUser.
  23.     CreateProcessAsUser supplies a User token to be stamped on the new process.
  24.     CreateProcess supplies NULL and the current process token is used.
  25.  
  26.     A process and thread object are created and a handle opened to each
  27.     object using CreateProcessInternal.  Note that WinExec and LoadModule are
  28.     still supported, but are implemented as a call to CreateProcess.
  29.  
  30. Arguments:
  31.  
  32.     hUserToken - Supplies an optional token handle to be set on the new process.
  33.         Process token is used is this parameter is NULL.
  34.  
  35.     lpApplicationName - Supplies an optional pointer to a null terminated
  36.         character string that contains the name of the image file to
  37.         execute.  This is a fully qualified DOS path name.  If not
  38.         specified, then the image file name is the first whitespace
  39.         delimited token on the command line.
  40.  
  41.     lpCommandLine - Supplies a null terminated character string that
  42.         contains the command line for the application to be executed.
  43.         The entire command line is made available to the new process
  44.         using GetCommandLine.  If the lpApplicationName parameter was
  45.         not specified, then the first token of the command line
  46.         specifies file name of the application (note that this token
  47.         begins at the beginning of the command line and ends at the
  48.         first "white space" character).  If the file name does not
  49.         contain an extension (the presence of a "."), then .EXE is
  50.         assumed.  If the file name does not contain a directory path,
  51.         Windows will search for the executable file in:
  52.  
  53.           - The current directory
  54.  
  55.           - The windows directory
  56.  
  57.           - The windows system directory
  58.  
  59.           - The directories listed in the path environment variable
  60.  
  61.         This parameter is optional onlu if the lpApplicationName
  62.         parameter is specified.  In this case the command line the
  63.         application receives will be the application name.
  64.  
  65.     lpProcessAttributes - An optional parameter that may be used to
  66.         specify the attributes of the new process.  If the parameter is
  67.         not specified, then the process is created without a security
  68.         descriptor, and the resulting handle is not inherited on process
  69.         creation:
  70.  
  71.         SECURITY_ATTRIBUTES Structure:
  72.  
  73.         DWORD nLength - Specifies the length of this structure.  Must be
  74.             set to sizeof( SECURITY_ATTRUBUTES ).
  75.  
  76.         LPVOID lpSecurityDescriptor - Points to a security descriptor for
  77.             the object (must be NULL for Win32, used on NT/Win32). The
  78.             security descriptor controls the sharing of an object.
  79.  
  80.         BOOL bInheritHandle - Supplies a flag that indicates whether
  81.             or not the returned handle is to be inherited by a new
  82.             process during process creation.  A value of TRUE
  83.             indicates that the new process will inherit the handle.
  84.  
  85.     lpThreadAttributes - An optional parameter that may be used to specify
  86.         the attributes of the new thread.  If the parameter is not
  87.         specified, then the thread is created without a security
  88.         descriptor, and the resulting handle is not inherited on
  89.         process creation.
  90.  
  91.     dwCreationFlags - Supplies additional flags that control the creation
  92.         of the process.
  93.  
  94.         dwCreationFlags Flags:
  95.  
  96.         DEBUG_PROCESS - If this flag bit is set, then the creating
  97.             process is treated as a debugger, and the process being
  98.             created is created as a debugee.  All debug events occuring
  99.             in the debugee are reported to the debugger.  If this bit is
  100.             clear, but the calling process is a debugee, then the
  101.             process becomes a debugee of the calling processes debugger.
  102.             If this bit is clear and the calling processes is not a
  103.             debugee then no debug related actions occur.
  104.  
  105.         DEBUG_ONLY_THIS_PROCESS - If this flag is set, then the
  106.             DEBUG_PROCESS flag bit must also be set.  The calling
  107.             process is is treated as a debugger, and the new process is
  108.             created as its debuggee.  If the new process creates
  109.             additional processes, no debug related activities (with
  110.             respect to the debugger) occur.
  111.  
  112.         CREATE_SUSPENDED - The process is created, but the initial thread
  113.             of the process remains suspended. The creator can resume this
  114.             thread using ResumeThread. Until this is done, code in the
  115.             process will not execute.
  116.  
  117.         CREATE_UNICODE_ENVIRONMENT - If set, the environment pointer
  118.             points to a Unicode environment block.  Otherwise, the
  119.             block is ANSI (actually OEM.)
  120.  
  121.     bInheritHandles - Supplies a flag that specifies whether or not the
  122.         new process is to inherit handles to objects visible to the
  123.         calling process.  A value of TRUE causes handles to be inherited
  124.         by the new process.  If TRUE was specified, then for each handle
  125.         visible to the calling process, if the handle was created with
  126.         the inherit handle option, the handle is inherited to the new
  127.         process.  The handle has the same granted access in the new
  128.         process as it has in the calling process, and the value of the
  129.         handle is the same.
  130.  
  131.     lpEnvironment - An optional parameter, that if specified, supplies a
  132.         pointer to an environment block.  If the parameter is not
  133.         specified, the environment block of the current process is used.
  134.         This environment block is made available to the new process
  135.         using GetEnvironmentStrings.
  136.  
  137.     lpCurrentDirectory - An optional parameter, that if specified,
  138.         supplies a string representing the current drive and directory
  139.         for the new process.  The string must be a fully qualified
  140.         pathname that includes a drive letter.  If the parameter is not
  141.         specified, then the new process is created with the same current
  142.         drive and directory as the calling process.  This option is
  143.         provided primarily for shells that want to start an application
  144.         and specify its initial drive and working directory.
  145.  
  146.     lpStartupInfo - Supplies information that specified how the
  147.         applications window is to be shown. This structure is described
  148.         in the Win32 User Interface API Book.
  149.  
  150.     lpProcessInformation - Returns identification information about the
  151.         new process.
  152.  
  153.     PROCESS_INFORMATION Structure:
  154.  
  155.         HANDLE hProcess - Returns a handle to the newly created process.
  156.             Through the handle, all operations on process objects are
  157.             allowed.
  158.  
  159.         HANDLE hThread - Returns a handle to the newly created thread.
  160.             Through the handle, all operations on thread objects are
  161.             allowed.
  162.  
  163.         DWORD dwProcessId - Returns a global process id that may be used
  164.             to identify a process.  The value is valid from the time the
  165.             process is created until the time the process is terminated.
  166.  
  167.         DWORD dwThreadId - Returns a global thread id that may be used
  168.             to identify a thread.  The value is valid from the time the
  169.             thread is created until the time the thread is terminated.
  170.  
  171.     hRestrictedUserToken - Returns a restricted token if a UsetToken was
  172.         supplied. This is applicable for the CreateProcessAsUser case.
  173.         The token is released by CreateProcessAsUser.
  174.  
  175. Return Value:
  176.  
  177.     TRUE - The operation was successful
  178.  
  179.     FALSE/NULL - The operation failed. Extended error status is available
  180.         using GetLastError.
  181.  
  182. --*/
  183.  
  184. {
  185.     NTSTATUS Status;
  186.     OBJECT_ATTRIBUTES Obja;
  187.     POBJECT_ATTRIBUTES pObja;
  188.     HANDLE ProcessHandle, ThreadHandle, VdmWaitHandle = NULL;
  189.     HANDLE FileHandle, SectionHandle;
  190.     CLIENT_ID ClientId;
  191.     UNICODE_STRING PathName;
  192.     IO_STATUS_BLOCK IoStatusBlock;
  193.     BOOLEAN TranslationStatus;
  194.     RTL_RELATIVE_NAME RelativeName;
  195.     PVOID FreeBuffer;
  196.     LPWSTR NameBuffer;
  197.     LPWSTR WhiteScan;
  198.     ULONG Length,i;
  199.     PROCESS_BASIC_INFORMATION ProcessInfo;
  200.     SECTION_IMAGE_INFORMATION ImageInformation;
  201.     NTSTATUS StackStatus;
  202.     BOOLEAN bStatus;
  203.     INITIAL_TEB InitialTeb;
  204.     CONTEXT ThreadContext;
  205.     PPEB Peb;
  206.     BASE_API_MSG m;
  207.     PBASE_CREATEPROCESS_MSG a = &m.u.CreateProcess;
  208.     PBASE_CHECKVDM_MSG b = &m.u.CheckVDM;
  209.     PWCH TempNull = NULL;
  210.     WCHAR TempChar;
  211.     UNICODE_STRING VdmNameString;
  212.     PVOID BaseAddress;
  213.     ULONG VdmReserve;
  214.     SIZE_T BigVdmReserve;
  215.     ULONG iTask=0;
  216.     LPWSTR CurdirBuffer, CurdirFilePart;
  217.     DWORD CurdirLength,CurdirLength2;
  218.     ULONG VDMCreationState=0;
  219.     ULONG VdmBinaryType = 0;
  220.     BOOL  bMeowBinary = FALSE;
  221.     UNICODE_STRING  SubSysCommandLine;
  222.     PIMAGE_NT_HEADERS NtHeaders;
  223.     DWORD dwNoWindow = (dwCreationFlags & CREATE_NO_WINDOW);
  224.     ANSI_STRING AnsiStringVDMEnv;
  225.     UNICODE_STRING UnicodeStringVDMEnv;
  226.     WCHAR ImageFileDebuggerCommand[ MAX_PATH ];
  227.     LPWSTR QuotedBuffer;
  228.     BOOLEAN QuoteInsert;
  229.     BOOLEAN QuoteCmdLine = FALSE;
  230.     BOOLEAN QuoteFound;
  231.     BOOL bSaferChecksNeeded = FALSE;
  232.     BOOLEAN SearchRetry;
  233.     BOOLEAN IsWowBinary = FALSE;
  234.     STARTUPINFOW StartupInfo;
  235.     DWORD LastError;
  236.     DWORD fileattr;
  237.     PROCESS_PRIORITY_CLASS PriClass;
  238.     PVOID State;
  239.     HANDLE DebugPortHandle = NULL;
  240.     PVOID pAppCompatDataTemp;
  241.     PVOID pAppCompatData  = NULL;
  242.     DWORD cbAppCompatData = 0;    // for the future
  243.     BOOLEAN bVdmRetry = FALSE;
  244.     DWORD Flags;
  245.     PVOID pAppCompatSxsData = NULL;
  246.     DWORD cbAppCompatSxsData = 0;
  247.     SXS_OVERRIDE_STREAM AppCompatSxsManifest;
  248.     PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
  249.     SIZE_T SxsConglomeratedBufferSizeBytes;
  250.     PBYTE SxsConglomeratedByteBuffer = NULL; // this contains all the of the below in one large right-sized heap allocation
  251.                             // if we compute its size wrong, other code (if it gets it right..) should
  252.                             // do more heap allocation
  253.     ULONG sxsi; // for loop counter
  254.     RTL_UNICODE_STRING_BUFFER SxsWin32ManifestPathBuffer;
  255.     RTL_UNICODE_STRING_BUFFER SxsWin32PolicyPathBuffer;
  256.     RTL_UNICODE_STRING_BUFFER SxsWin32AssemblyDirectoryBuffer;
  257.     RTL_UNICODE_STRING_BUFFER SxsNtManifestPathBuffer;
  258.     RTL_UNICODE_STRING_BUFFER SxsNtPolicyPathBuffer;
  259.     const PRTL_UNICODE_STRING_BUFFER SxsStringBuffers[] = {
  260.         // The order here does not matter.
  261.         &SxsWin32ManifestPathBuffer,
  262.         &SxsWin32PolicyPathBuffer,
  263.         &SxsWin32AssemblyDirectoryBuffer,
  264.         &SxsNtManifestPathBuffer,
  265.         &SxsNtPolicyPathBuffer
  266.     };
  267.     UNICODE_STRING SxsWin32ExePath;
  268.     UNICODE_STRING SxsNtExePath;
  269.     BASE_MSG_SXS_HANDLES SxsExeHandles = {0};
  270.     BASE_MSG_SXS_HANDLES SxsManifestFileHandles = {0};
  271.     CONST SXS_CONSTANT_WIN32_NT_PATH_PAIR SxsExePathPair = { &SxsWin32ExePath, &SxsNtExePath };
  272.     CONST SXS_WIN32_NT_PATH_PAIR SxsManifestPathPair = { &SxsWin32ManifestPathBuffer, &SxsNtManifestPathBuffer };
  273.     CONST SXS_WIN32_NT_PATH_PAIR SxsPolicyPathPair = { &SxsWin32PolicyPathBuffer, &SxsNtPolicyPathBuffer };
  274.     BASE_MSG_SXS_HANDLES SxsPolicyHandles = {0};
  275.     PWSTR ExePathFullBuffer = NULL;
  276.  
  277.     DWORD dwJobMemberLevel = 0;
  278.     HANDLE hSaferAssignmentJob = NULL;
  279.     HANDLE hSaferRestrictedToken = NULL;
  280.  
  281.     DWORD dwBasePushProcessParametersFlags = 0;
  282.  
  283. #if defined(BUILD_WOW6432) || defined(_WIN64)
  284.     BOOLEAN ComPlusILImage;
  285.     LPCWSTR lpOriginalApplicationName = lpApplicationName;
  286.     LPWSTR lpOriginalCommandLine = lpCommandLine;
  287. #endif
  288.  
  289. #if defined(WX86)
  290.     HANDLE Wx86Info = NULL;
  291. #endif
  292.  
  293. #if defined WX86
  294.     BOOLEAN UseKnownWx86Dll;
  295.     UseKnownWx86Dll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
  296.     NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  297. #endif
  298.  
  299.     RtlZeroMemory(&a->Sxs, sizeof(a->Sxs));
  300.     RtlZeroMemory(lpProcessInformation,sizeof(*lpProcessInformation));
  301.  
  302.     if (ARGUMENT_PRESENT( hRestrictedUserToken )) {
  303.         *hRestrictedUserToken = NULL;
  304.         }
  305.  
  306.     // Private VDM flag should be ignored; Its meant for internal use only.
  307.     dwCreationFlags &= (ULONG)~CREATE_NO_WINDOW;
  308.  
  309.     if ((dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) ==
  310.         (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) {
  311.  
  312.         SetLastError(ERROR_INVALID_PARAMETER);
  313.         return FALSE;
  314.         }
  315.  
  316.     AnsiStringVDMEnv.Buffer = NULL;
  317.     UnicodeStringVDMEnv.Buffer = NULL;
  318.  
  319.     //
  320.     // the lowest specified priority class is used.
  321.     //
  322.  
  323.     if (dwCreationFlags & IDLE_PRIORITY_CLASS ) {
  324.         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
  325.         }
  326.     else if (dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS ) {
  327.         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
  328.         }
  329.     else if (dwCreationFlags & NORMAL_PRIORITY_CLASS ) {
  330.         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
  331.         }
  332.     else if (dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS ) {
  333.         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
  334.         }
  335.     else if (dwCreationFlags & HIGH_PRIORITY_CLASS ) {
  336.         PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_HIGH;
  337.         }
  338.     else if (dwCreationFlags & REALTIME_PRIORITY_CLASS ) {
  339.         if ( BasepIsRealtimeAllowed(FALSE) ) {
  340.             PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_REALTIME;
  341.             }
  342.         else {
  343.             PriClass.PriorityClass =  PROCESS_PRIORITY_CLASS_HIGH;
  344.             }
  345.         }
  346.     else {
  347.         PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_UNKNOWN;
  348.         }
  349.     PriClass.Foreground = FALSE;
  350.  
  351.     dwCreationFlags = (dwCreationFlags & ~PRIORITY_CLASS_MASK );
  352.  
  353.     //
  354.     // Default separate/shared VDM option if not explicitly specified.
  355.     //
  356.  
  357.     if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM) {
  358.         if (dwCreationFlags & CREATE_SHARED_WOW_VDM) {
  359.             SetLastError(ERROR_INVALID_PARAMETER);
  360.  
  361.             return FALSE;
  362.             }
  363.         }
  364.     else
  365.     if ((dwCreationFlags & CREATE_SHARED_WOW_VDM) == 0) {
  366.         if (BaseStaticServerData->DefaultSeparateVDM) {
  367.             dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
  368.             }
  369.         }
  370.  
  371.     if ((dwCreationFlags & CREATE_SEPARATE_WOW_VDM) == 0) {
  372.         //
  373.         // If the creator is running inside a job object, always
  374.         // set SEPERATE_WOW_VDM so the VDM is part of the job.
  375.         //
  376.         JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
  377.  
  378.         Status = NtQueryInformationJobObject(NULL,
  379.                                              JobObjectBasicUIRestrictions,
  380.                                              &UiRestrictions,
  381.                                              sizeof(UiRestrictions),
  382.                                              NULL);
  383.         if (Status != STATUS_ACCESS_DENIED) {
  384.             //
  385.             // Anything other than STATUS_ACCESS_DENIED indicates the
  386.             // current process is inside a job.
  387.             //
  388.             dwCreationFlags = (dwCreationFlags & (~CREATE_SHARED_WOW_VDM)) |
  389.                                   CREATE_SEPARATE_WOW_VDM;
  390.             }
  391.         }
  392.  
  393.  
  394.     //
  395.     //  If ANSI environment, convert to Unicode
  396.     //
  397.  
  398.     if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
  399.         PUCHAR s;
  400.         STRING Ansi;
  401.         UNICODE_STRING Unicode;
  402.         MEMORY_BASIC_INFORMATION MemoryInformation;
  403.  
  404.         Ansi.Buffer = s = lpEnvironment;
  405.         while (*s || *(s+1))            // find end of block
  406.             s++;
  407.  
  408.         Ansi.Length = (USHORT)(s - Ansi.Buffer) + 1;
  409.         Ansi.MaximumLength = Ansi.Length + 1;
  410.         MemoryInformation.RegionSize = Ansi.MaximumLength * sizeof(WCHAR);
  411.         Unicode.Buffer = NULL;
  412.         Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  413.                                           &Unicode.Buffer,
  414.                                           0,
  415.                                           &MemoryInformation.RegionSize,
  416.                                           MEM_COMMIT,
  417.                                           PAGE_READWRITE
  418.                                         );
  419.         if (!NT_SUCCESS(Status) ) {
  420.             BaseSetLastNTError(Status);
  421.  
  422.             return FALSE;
  423.             }
  424.  
  425.         Unicode.MaximumLength = (USHORT)MemoryInformation.RegionSize;
  426.         Status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, FALSE);
  427.         if (!NT_SUCCESS(Status) ) {
  428.             NtFreeVirtualMemory( NtCurrentProcess(),
  429.                                  &Unicode.Buffer,
  430.                                  &MemoryInformation.RegionSize,
  431.                                  MEM_RELEASE
  432.                                );
  433.             BaseSetLastNTError(Status);
  434.  
  435.             return FALSE;
  436.             }
  437.         lpEnvironment = Unicode.Buffer;
  438.         }
  439.  
  440.     FileHandle = NULL;
  441.     SectionHandle = NULL;
  442.     ProcessHandle = NULL;
  443.     ThreadHandle = NULL;
  444.     FreeBuffer = NULL;
  445.     NameBuffer = NULL;
  446.     VdmNameString.Buffer = NULL;
  447.     BaseAddress = (PVOID)1;
  448.     VdmReserve = 0;
  449.     CurdirBuffer = NULL;
  450.     CurdirFilePart = NULL;
  451.     SubSysCommandLine.Buffer = NULL;
  452.     QuoteFound = FALSE;
  453.     QuoteInsert = FALSE;
  454.     QuotedBuffer = NULL;
  455.  
  456.     try {
  457.  
  458.         //
  459.         // Make a copy of the startup info so we can change it.
  460.         //
  461.  
  462.         StartupInfo = *lpStartupInfo;
  463.  
  464.         //
  465.         // STARTF_USEHOTKEY means hStdInput is really the hotkey value.
  466.         // STARTF_HASSHELLDATA means std handles are used for shell-private
  467.         // data.  This flag is used if an icon is passed to ShellExecuteEx.
  468.         // As a result they cannot be specified with STARTF_USESTDHANDLES.
  469.         // Consistent with Win95, USESTDHANDLES is ignored.
  470.         //
  471.  
  472.         if (StartupInfo.dwFlags & STARTF_USESTDHANDLES &&
  473.             StartupInfo.dwFlags & (STARTF_USEHOTKEY | STARTF_HASSHELLDATA)) {
  474.  
  475.             StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES;
  476.             }
  477.  
  478. VdmRetry:
  479.         //
  480.         // None of this cleanup/reinit occurs for launching a Win32 or Win64 .exe,
  481.         // but they generally do occur for launching 16bit, .bat, etc.
  482.         //
  483.         if (NameBuffer) {
  484.             RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
  485.             NameBuffer = NULL;
  486.         }
  487.         if (FreeBuffer) {
  488.             RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  489.             FreeBuffer = NULL;
  490.         }
  491.         if (FileHandle) {
  492.             NtClose(FileHandle);
  493.             FileHandle = NULL;
  494.         }
  495.  
  496.         LastError = 0;
  497.         SearchRetry = TRUE;
  498.         QuoteInsert = FALSE;
  499.         QuoteCmdLine = FALSE;
  500.         if (!ARGUMENT_PRESENT( lpApplicationName )) {
  501.  
  502.             //
  503.             // Locate the image
  504.             //
  505.  
  506.             // forgot to free NameBuffer before goto VdmRetry???
  507.             ASSERT(NameBuffer == NULL);
  508.  
  509.             NameBuffer = RtlAllocateHeap( RtlProcessHeap(),
  510.                                           MAKE_TAG( TMP_TAG ),
  511.                                           MAX_PATH * sizeof( WCHAR ));
  512.             if ( !NameBuffer ) {
  513.                 BaseSetLastNTError(STATUS_NO_MEMORY);
  514.                 return FALSE;
  515.                 }
  516.             lpApplicationName = lpCommandLine;
  517.             TempNull = (PWCH)lpApplicationName;
  518.             WhiteScan = (LPWSTR)lpApplicationName;
  519.  
  520.             //
  521.             // check for lead quote
  522.             //
  523.             if ( *WhiteScan == L'\"' ) {
  524.                 SearchRetry = FALSE;
  525.                 WhiteScan++;
  526.                 lpApplicationName = WhiteScan;
  527.                 while(*WhiteScan) {
  528.                     if ( *WhiteScan == (WCHAR)'\"' ) {
  529.                         TempNull = (PWCH)WhiteScan;
  530.                         QuoteFound = TRUE;
  531.                         break;
  532.                         }
  533.                     WhiteScan++;
  534.                     TempNull = (PWCH)WhiteScan;
  535.                     }
  536.                 }
  537.             else {
  538. retrywsscan:
  539.                 lpApplicationName = lpCommandLine;
  540.                 while(*WhiteScan) {
  541.                     if ( *WhiteScan == (WCHAR)' ' ||
  542.                          *WhiteScan == (WCHAR)'\t' ) {
  543.                         TempNull = (PWCH)WhiteScan;
  544.                         break;
  545.                         }
  546.                     WhiteScan++;
  547.                     TempNull = (PWCH)WhiteScan;
  548.                     }
  549.                 }
  550.             TempChar = *TempNull;
  551.             *TempNull = UNICODE_NULL;
  552.  
  553. #ifdef WX86
  554.  
  555.             //
  556.             // Wx86 applications must use x86 version of known exes
  557.             // for compatibility.
  558.             //
  559.  
  560.             if (UseKnownWx86Dll) {
  561.                LPWSTR KnownName;
  562.  
  563.                NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  564.  
  565.                KnownName = BasepWx86KnownExe(lpApplicationName);
  566.                if (KnownName) {
  567.                   lpApplicationName = KnownName;
  568.                   }
  569.                }
  570. #endif
  571.  
  572.  
  573.             Length = SearchPathW(
  574.                         NULL,
  575.                         lpApplicationName,
  576.                         L".exe",
  577.                         MAX_PATH,
  578.                         NameBuffer,
  579.                         NULL
  580.                         )*2;
  581.  
  582.             if (Length != 0 && Length < MAX_PATH * sizeof( WCHAR )) {
  583.                 //
  584.                 // SearchPathW worked, but file might be a directory
  585.                 // if this happens, we need to keep trying
  586.                 //
  587.                 fileattr = GetFileAttributesW(NameBuffer);
  588.                 if ( fileattr != 0xffffffff &&
  589.                      (fileattr & FILE_ATTRIBUTE_DIRECTORY) ) {
  590.                     Length = 0;
  591.                 } else {
  592.                     Length++;
  593.                     Length++;
  594.                 }
  595.             }
  596.  
  597.             if ( !Length || Length >= MAX_PATH<<1 ) {
  598.  
  599.                 //
  600.                 // If we search pathed, then return file not found.
  601.                 // otherwise, try to be more specific.
  602.                 //
  603.                 RTL_PATH_TYPE PathType;
  604.                 HANDLE hFile;
  605.  
  606.                 PathType = RtlDetermineDosPathNameType_U(lpApplicationName);
  607.                 if ( PathType != RtlPathTypeRelative ) {
  608.  
  609.                     //
  610.                     // The failed open should set get last error properly.
  611.                     //
  612.  
  613.                     hFile = CreateFileW(
  614.                                 lpApplicationName,
  615.                                 GENERIC_READ,
  616.                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
  617.                                 NULL,
  618.                                 OPEN_EXISTING,
  619.                                 FILE_ATTRIBUTE_NORMAL,
  620.                                 NULL
  621.                                 );
  622.                     if ( hFile != INVALID_HANDLE_VALUE ) {
  623.                         CloseHandle(hFile);
  624.                         BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
  625.                         }
  626.                     }
  627.                 else {
  628.                     BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
  629.                     }
  630.  
  631.                 //
  632.                 // remember initial last error value for the retry scan path
  633.                 //
  634.  
  635.                 if ( LastError ) {
  636.                     SetLastError(LastError);
  637.                     }
  638.                 else {
  639.                     LastError = GetLastError();
  640.                     }
  641.  
  642.                 //
  643.                 // restore the command line
  644.                 //
  645.  
  646.                 *TempNull = TempChar;
  647.                 lpApplicationName = NameBuffer;
  648.  
  649.                 //
  650.                 // If we still have command line left, then keep going
  651.                 // the point is to march through the command line looking
  652.                 // for whitespace so we can try to find an image name
  653.                 // launches of things like:
  654.                 // c:\word 95\winword.exe /embedding -automation
  655.                 // require this. Our first iteration will stop at c:\word, our next
  656.                 // will stop at c:\word 95\winword.exe
  657.                 //
  658.                 if (*WhiteScan && SearchRetry) {
  659.                     WhiteScan++;
  660.                     TempNull = WhiteScan;
  661.                     QuoteInsert = TRUE;
  662.                     QuoteFound = TRUE;
  663.                     goto retrywsscan;
  664.                 }
  665.  
  666.                 return FALSE;
  667.                 }
  668.             //
  669.             // restore the command line
  670.             //
  671.  
  672.             *TempNull = TempChar;
  673.             lpApplicationName = NameBuffer;
  674.  
  675.             //
  676.             // check whether it is setup.exe started by winlogon.exe
  677.             //
  678.             if (BasepIsSetupInvokedByWinLogon(lpApplicationName))
  679.             {
  680.                 // validate the flag
  681.                 if (!(dwCreationFlags & CREATE_IGNORE_SYSTEM_DEFAULT))
  682.                 {
  683.                     //
  684.                     // BUGBUBGUBGUBUGBUGBUGUBGBUGUBGUB
  685.                     //    Winlogon does not set the flag correctly
  686.                     //    in phase1, ignore it(now)
  687.                     //    in phase2, ASSERT it
  688.                     // BUGBUBGUBGUBUGBUGBUGUBGBUGUBGUB
  689.                     //
  690.                     dwCreationFlags |= CREATE_IGNORE_SYSTEM_DEFAULT;
  691.                 }
  692.             }
  693.            
  694.         }
  695.         else
  696.         if (!ARGUMENT_PRESENT( lpCommandLine ) || *lpCommandLine == UNICODE_NULL ) {
  697.             QuoteCmdLine = TRUE;
  698.             lpCommandLine = (LPWSTR)lpApplicationName;
  699.             }
  700.  
  701.  
  702. #ifdef WX86
  703.  
  704.        //
  705.        // Wx86 applications must use x86 version of known exes
  706.        // for compatibility.
  707.        //
  708.  
  709.        if (UseKnownWx86Dll) {
  710.            LPWSTR KnownName;
  711.  
  712.            NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  713.  
  714.            KnownName = BasepWx86KnownExe(lpApplicationName);
  715.            if (KnownName) {
  716.  
  717.                RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
  718.                NameBuffer = KnownName;
  719.                lpApplicationName = KnownName;
  720.                }
  721.            }
  722.  
  723. #endif
  724.  
  725.         //
  726.         // Translate to an NT name.
  727.         //
  728.  
  729.         TranslationStatus = RtlDosPathNameToNtPathName_U(
  730.                                 lpApplicationName,
  731.                                 &PathName,
  732.                                 NULL,
  733.                                 &RelativeName
  734.                                 );
  735.  
  736.         if ( !TranslationStatus ) {
  737.             SetLastError(ERROR_PATH_NOT_FOUND);
  738.  
  739.             return FALSE;
  740.             }
  741.  
  742.         // forgot to free FreeBuffer before goto VdmRetry????
  743.         ASSERT(FreeBuffer == NULL);
  744.         FreeBuffer = PathName.Buffer;
  745.  
  746.         RtlInitUnicodeString(&SxsWin32ExePath, lpApplicationName);
  747.  
  748.         {
  749.             RTL_PATH_TYPE SxsWin32ExePathType = RtlDetermineDosPathNameType_U(lpApplicationName);
  750.  
  751.             if ((SxsWin32ExePathType != RtlPathTypeDriveAbsolute) &&
  752.                 (SxsWin32ExePathType != RtlPathTypeUncAbsolute)) {
  753.                 if (ExePathFullBuffer == NULL) {
  754.                     // It seems that with VDM things, we can rerun this code with a new lpApplication, so
  755.                     // we protect against double-allocating the buffer and just allocate a big
  756.                     // MAX_PATH one the first time through, assuming it's good enough for the 2ndary times
  757.                     // too.
  758.                     ExePathFullBuffer = RtlAllocateHeap(RtlProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR));
  759.                     if (ExePathFullBuffer == NULL) {
  760.                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  761.                         return FALSE;
  762.                     }
  763.                 }
  764.  
  765.                 RtlGetFullPathName_U(lpApplicationName, (MAX_PATH + 1) * sizeof(WCHAR), ExePathFullBuffer, NULL);
  766.  
  767.                 RtlInitUnicodeString(&SxsWin32ExePath, ExePathFullBuffer);
  768.             }
  769.         }
  770.  
  771.  
  772.         SxsNtExePath = PathName;
  773.  
  774.         if ( RelativeName.RelativeName.Length ) {
  775.             PathName = *(PUNICODE_STRING)&RelativeName.RelativeName;
  776.             }
  777.         else {
  778.             RelativeName.ContainingDirectory = NULL;
  779.             }
  780.  
  781.         InitializeObjectAttributes(
  782.             &Obja,
  783.             &PathName,
  784.             OBJ_CASE_INSENSITIVE,
  785.             RelativeName.ContainingDirectory,
  786.             NULL
  787.             );
  788.  
  789.         //
  790.         // Open the file for red and execute access
  791.         //
  792.  
  793.         Status = NtOpenFile(
  794.                     &FileHandle,
  795.                     SYNCHRONIZE | FILE_EXECUTE | FILE_READ_ATTRIBUTES | FILE_READ_DATA,
  796.                     &Obja,
  797.                     &IoStatusBlock,
  798.                     FILE_SHARE_READ | FILE_SHARE_DELETE,
  799.                     FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
  800.                     );
  801.  
  802.         if (!NT_SUCCESS(Status) ) {
  803.  
  804.             //
  805.             // We failed. Open the file for lesser access.
  806.             //
  807.  
  808.             Status = NtOpenFile(
  809.                         &FileHandle,
  810.                         SYNCHRONIZE | FILE_EXECUTE,
  811.                         &Obja,
  812.                         &IoStatusBlock,
  813.                         FILE_SHARE_READ | FILE_SHARE_DELETE,
  814.                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
  815.                         );
  816.  
  817.             if (!NT_SUCCESS(Status) ) {
  818.                 //
  819.                 // if we failed, see if this is a device. If it is a device,
  820.                 // then just return invalid image format
  821.                 //
  822.  
  823.                 if ( RtlIsDosDeviceName_U(RTL_CONST_CAST(PWSTR)(lpApplicationName)) ) {
  824.                     SetLastError(ERROR_BAD_DEVICE);
  825.                     }
  826.                 else {
  827.                     BaseSetLastNTError(Status);
  828.                     }
  829.  
  830.                 return FALSE;
  831.             }
  832.  
  833.         }
  834.  
  835.         //
  836.         // If no desktop has been specified, use the caller's
  837.         // desktop.
  838.         //
  839.  
  840.         if (StartupInfo.lpDesktop == NULL) {
  841.             StartupInfo.lpDesktop =
  842.                     (LPWSTR)((PRTL_USER_PROCESS_PARAMETERS)NtCurrentPeb()->
  843.                         ProcessParameters)->DesktopInfo.Buffer;
  844.             }
  845.  
  846.         //
  847.         // Create a section object backed by the file
  848.         //
  849.  
  850.         Status = NtCreateSection(
  851.                     &SectionHandle,
  852.                     SECTION_ALL_ACCESS,
  853.                     NULL,
  854.                     NULL,
  855.                     PAGE_EXECUTE,
  856.                     SEC_IMAGE,
  857.                     FileHandle
  858.                     );
  859.  
  860.         //
  861.         // App Certification DLL
  862.         //
  863.  
  864.         if (NT_SUCCESS(Status)) {
  865.             Status = BasepIsProcessAllowed(lpApplicationName);
  866.  
  867.             if (!NT_SUCCESS(Status)) {
  868.                 BaseSetLastNTError(Status);
  869.                 NtClose(SectionHandle);
  870.                 return FALSE;
  871.             }
  872.  
  873.  
  874.        
  875.           //
  876.           // If Meow subsystem is enabled and caller specified CREATE_FORECEDOS for a win32 image
  877.           // push it into the meow subsystem
  878.           //
  879.  
  880.           if ((dwCreationFlags & CREATE_FORCEDOS) && BaseStaticServerData->ForceDos) {
  881.                dwCreationFlags &= ~(CREATE_SHARED_WOW_VDM | CREATE_FORCEDOS);
  882.                dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
  883.                Status = STATUS_INVALID_IMAGE_WIN_16;
  884.                bMeowBinary = TRUE;
  885.  
  886.                NtClose(SectionHandle);
  887.                SectionHandle = NULL;
  888.           }
  889.  
  890.  
  891.        }
  892.  
  893.         //
  894.         // check appcompat (aka apphelp)
  895.         //
  896.         // if we are running under debugger, bVdmRetry will be FALSE
  897.         // yet pAppCompatData may have some data (from the app itself)
  898.         // debugger will do a separate CreateProcess on debugee
  899.         //
  900.         // apphelp gets called if it is win32 app or if it is a .bat or .cmd
  901.  
  902.        if(!bVdmRetry &&
  903.           (NT_SUCCESS(Status) ||
  904.            (Status == STATUS_INVALID_IMAGE_NOT_MZ && !BaseIsDosApplication(&PathName,Status)))
  905.          ) {
  906.             NTSTATUS BadAppStatus;
  907.  
  908.             if (NULL != pAppCompatData) {
  909.                 RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
  910.                 pAppCompatData = NULL;
  911.                 }
  912.              
  913.             if (NULL != pAppCompatSxsData) {
  914.                 RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatSxsData);
  915.                 pAppCompatSxsData = NULL;
  916.                 }
  917.              
  918.             //
  919.             // we only check ONCE --
  920.             // the second time around is rather meaningless - to check for posix/ntvdm/os2 emulation
  921.             //
  922.             BadAppStatus = BasepCheckBadapp(FileHandle,
  923.                                             PathName.Buffer,
  924.                                             (WCHAR*)lpEnvironment,
  925.                                             &pAppCompatData,
  926.                                             &cbAppCompatData,
  927.                                             &pAppCompatSxsData,
  928.                                             &cbAppCompatSxsData);
  929.                    
  930.             if (!NT_SUCCESS(BadAppStatus)) {
  931.                 if (BadAppStatus == STATUS_ACCESS_DENIED) {
  932.                     SetLastError(ERROR_CANCELLED);
  933.                     }
  934.                 else {
  935.                     BaseSetLastNTError(BadAppStatus);
  936.                     }
  937.  
  938.                 if (SectionHandle) {
  939.                     NtClose(SectionHandle);
  940.                     SectionHandle = NULL;
  941.                     }
  942.                 return FALSE;
  943.                 }
  944.             }
  945.  
  946.        //
  947.        // Winsafer code
  948.        //
  949.        // If this is the first time then we will have to do Safer checks.
  950.        // Note that we do not impose any restrictions on the interpreter
  951.        // itself since it is part of OS.
  952.        //
  953.  
  954.  
  955.        if ((!bVdmRetry) &&
  956.            ( (dwCreationFlags & CREATE_PRESERVE_CODE_AUTHZ_LEVEL) == 0 )) {
  957.  
  958.            NTSTATUS SaferStatus;
  959.  
  960.  
  961.            {
  962.  
  963.                //
  964.                // WinSafer process sandbox restrictions handling.
  965.                // Should be done for non .NET images only.
  966.                //
  967.  
  968.                SaferStatus = BasepCheckWinSaferRestrictions(
  969.                                                       hUserToken,
  970.                                                       lpApplicationName,   // same as PathName.Buffer
  971.                                                       FileHandle,
  972.                                                       &dwJobMemberLevel,
  973.                                                       &hSaferRestrictedToken,
  974.                                                       &hSaferAssignmentJob);
  975.                if (SaferStatus == -1) {
  976.                    SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
  977.                    bStatus =  FALSE;
  978.                    leave;
  979.                } else if (!NT_SUCCESS(SaferStatus)) {
  980.                    BaseSetLastNTError(SaferStatus);
  981.                    bStatus = FALSE;
  982.                    leave;
  983.                }
  984.            }
  985.        }
  986.  
  987.  
  988.         if (!NT_SUCCESS(Status)) {
  989.             switch (Status) {
  990.                 // 16 bit OS/2 exe
  991.                 case STATUS_INVALID_IMAGE_NE_FORMAT:
  992. #if defined(i386) && defined(OS2_SUPPORT_ENABLED)
  993.                 //
  994.                 // Use OS/2 if x86 (OS/2 not supported on risc),
  995.                 //    and CreationFlags don't have forcedos bit
  996.                 //    and Registry didn't specify ForceDos
  997.                 //
  998.                 // else execute as a DOS bound app.
  999.                 //
  1000.                 //
  1001.  
  1002.                 if (!(dwCreationFlags & CREATE_FORCEDOS) &&
  1003.                     !BaseStaticServerData->ForceDos)
  1004.                   {
  1005.  
  1006.                     if ( !BuildSubSysCommandLine( L"OS2 /P ",
  1007.                                                   lpApplicationName,
  1008.                                                   lpCommandLine,
  1009.                                                   &SubSysCommandLine
  1010.                                                 ) ) {
  1011.                         return FALSE;
  1012.                         }
  1013.  
  1014.                     lpCommandLine = SubSysCommandLine.Buffer;
  1015.  
  1016.                     lpApplicationName = NULL;
  1017.  
  1018.                     bVdmRetry = TRUE;
  1019.                     goto VdmRetry;
  1020.                     }
  1021. #endif
  1022.                     // Falls into Dos case, so that stub message will be
  1023.                     // printed, and bound apps will run w/o OS/2 subsytem
  1024.  
  1025.                 // Dos .exe or .com
  1026.  
  1027.                 case STATUS_INVALID_IMAGE_PROTECT:
  1028.                 case STATUS_INVALID_IMAGE_NOT_MZ:
  1029. ForceDos:
  1030.                     {
  1031.                     ULONG BinarySubType;
  1032.  
  1033.                     BinarySubType = BINARY_TYPE_DOS_EXE;
  1034.                     if (Status == STATUS_INVALID_IMAGE_PROTECT   ||
  1035.                         Status == STATUS_INVALID_IMAGE_NE_FORMAT ||
  1036.                        (BinarySubType = BaseIsDosApplication(&PathName,Status)) )
  1037.                        {
  1038. #if defined(_WIN64) || defined(BUILD_WOW6432)
  1039.                         //
  1040.                         // If this a DOS application, then we need to pop up a dialog
  1041.                         // saying that this an invalid win32 application.
  1042.                         //
  1043.                         goto RaiseInvalidWin32Error;
  1044. #endif
  1045.                         VdmBinaryType = BINARY_TYPE_DOS;
  1046.  
  1047.                         // create the environment before going to the
  1048.                         // server. This was done becuase we want NTVDM
  1049.                         // to have the new environment when it gets
  1050.                         // created.
  1051.                         if (!BaseCreateVDMEnvironment(
  1052.                                     lpEnvironment,
  1053.                                     &AnsiStringVDMEnv,
  1054.                                     &UnicodeStringVDMEnv
  1055.                                     )) {
  1056.                             return FALSE;
  1057.                         }
  1058.  
  1059.                         if(!BaseCheckVDM(VdmBinaryType | BinarySubType,
  1060.                                          lpApplicationName,
  1061.                                          lpCommandLine,
  1062.                                          lpCurrentDirectory,
  1063.                                          &AnsiStringVDMEnv,
  1064.                                          &m,
  1065.                                          &iTask,
  1066.                                          dwCreationFlags,
  1067.                                          &StartupInfo
  1068.                                          )) {
  1069.  
  1070.                             return FALSE;
  1071.                         }
  1072.  
  1073.                         // Check the return value from the server
  1074.                         switch (b->VDMState & VDM_STATE_MASK) {
  1075.                             case VDM_NOT_PRESENT:
  1076.                                 // mark this so the server can undo
  1077.                                 // creation if something goes wrong.
  1078.                                 // We marked it "partially created" because
  1079.                                 // the NTVDM has yet not been fully created.
  1080.                                 // a call to UpdateVdmEntry to update
  1081.                                 // process handle will signal the NTVDM
  1082.                                 // process completed creation
  1083.                                 VDMCreationState = VDM_PARTIALLY_CREATED;
  1084.                                 // fail the call if NTVDM process is being
  1085.                                 // created DETACHED.
  1086.                                 // note that, we let it go if NTVDM process
  1087.                                 // is already running.
  1088.                                 if (dwCreationFlags & DETACHED_PROCESS) {
  1089.                                     SetLastError(ERROR_ACCESS_DENIED);
  1090.                                     return FALSE;
  1091.                                     }
  1092.                                 if (!BaseGetVdmConfigInfo(lpCommandLine,
  1093.                                                           iTask,
  1094.                                                           VdmBinaryType,
  1095.                                                           &VdmNameString,
  1096.                                                           &VdmReserve)) {
  1097.                                     BaseSetLastNTError(Status);
  1098.                                     return FALSE;
  1099.                                     }
  1100.  
  1101.                                 lpCommandLine = VdmNameString.Buffer;
  1102.                                 lpApplicationName = NULL;
  1103.  
  1104.                                 break;
  1105.  
  1106.                             case VDM_PRESENT_NOT_READY:
  1107.                                 SetLastError (ERROR_NOT_READY);
  1108.                                 return FALSE;
  1109.  
  1110.                             case VDM_PRESENT_AND_READY:
  1111.                                 VDMCreationState = VDM_BEING_REUSED;
  1112.                                 VdmWaitHandle = b->WaitObjectForParent;
  1113.                                 break;
  1114.                             }
  1115.                          VdmReserve--;               // we reserve from addr 1
  1116.                          if(VdmWaitHandle)
  1117.                             goto VdmExists;
  1118.                          else{
  1119.                             bInheritHandles = FALSE;
  1120.                             if (lpEnvironment &&
  1121.                                 !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)){
  1122.                                 RtlDestroyEnvironment(lpEnvironment);
  1123.                                 }
  1124.                             lpEnvironment = UnicodeStringVDMEnv.Buffer;
  1125.                             bVdmRetry = TRUE;
  1126.                             goto VdmRetry;
  1127.                             }
  1128.                         }
  1129.                     else {
  1130.  
  1131.                         //
  1132.                         //  must be a .bat or .cmd file
  1133.                         //
  1134.  
  1135.                         static PWCHAR CmdPrefix = L"cmd /c ";
  1136.                         PWCHAR NewCommandLine;
  1137.                         ULONG Length;
  1138.                         PWCHAR Last4 = &PathName.Buffer[PathName.Length / sizeof( WCHAR )-4];
  1139.  
  1140.                         if ( PathName.Length < 8 ) {
  1141.                             SetLastError(ERROR_BAD_EXE_FORMAT);
  1142.                             return FALSE;
  1143.                             }
  1144.  
  1145.                         if (_wcsnicmp( Last4, L".bat", 4 ) && _wcsnicmp( Last4, L".cmd", 4 )) {
  1146.                             SetLastError(ERROR_BAD_EXE_FORMAT);
  1147.                             return FALSE;
  1148.                         }
  1149.  
  1150.                         Length = wcslen( CmdPrefix )
  1151.                                  + (QuoteCmdLine || QuoteFound )
  1152.                                  + wcslen( lpCommandLine )
  1153.                                  + (QuoteCmdLine || QuoteFound)
  1154.                                  + 1;
  1155.  
  1156.                         NewCommandLine = RtlAllocateHeap( RtlProcessHeap( ),
  1157.                                                           MAKE_TAG( TMP_TAG ),
  1158.                                                           Length * sizeof( WCHAR ) );
  1159.  
  1160.                         if (NewCommandLine == NULL) {
  1161.                             BaseSetLastNTError(STATUS_NO_MEMORY);
  1162.                             return FALSE;
  1163.                         }
  1164.  
  1165.                         wcscpy( NewCommandLine, CmdPrefix );
  1166.                         if (QuoteCmdLine || QuoteFound) {
  1167.                             wcscat( NewCommandLine, L"\"" );
  1168.                         }
  1169.                         wcscat( NewCommandLine, lpCommandLine );
  1170.                         if (QuoteCmdLine || QuoteFound) {
  1171.                             wcscat( NewCommandLine, L"\"" );
  1172.                         }
  1173.  
  1174.                         RtlInitUnicodeString( &SubSysCommandLine, NewCommandLine );
  1175.  
  1176.                         lpCommandLine = SubSysCommandLine.Buffer;
  1177.  
  1178.                         lpApplicationName = NULL;
  1179.  
  1180.                         bVdmRetry = TRUE;
  1181.                         goto VdmRetry;
  1182.  
  1183.                         }
  1184.  
  1185.                     }
  1186.  
  1187.                 // 16 bit windows exe
  1188.                 case STATUS_INVALID_IMAGE_WIN_16:
  1189. #if defined(BUILD_WOW6432) || defined(_WIN64)
  1190.                    if (lpOriginalApplicationName == NULL) {
  1191.                        // pass in the part of the command line after the exe name
  1192.                        // including whitespace
  1193.                        lpCommandLine = ((*TempNull == '\"') ? TempNull + 1 : TempNull);
  1194.                    } else {
  1195.                        lpCommandLine = lpOriginalCommandLine;
  1196.                    }
  1197.  
  1198.                    return NtVdm64CreateProcess(lpOriginalApplicationName == NULL,
  1199.                                                lpApplicationName,             // this is now the real file name we've loaded
  1200.                                                lpCommandLine,
  1201.                                                lpProcessAttributes,
  1202.                                                lpThreadAttributes,
  1203.                                                bInheritHandles,
  1204.                                                (dwCreationFlags & ~CREATE_UNICODE_ENVIRONMENT),  // the environment has already been converted to unicode
  1205.                                                lpEnvironment,
  1206.                                                lpCurrentDirectory,
  1207.                                                lpStartupInfo,
  1208.                                                lpProcessInformation
  1209.                                                );
  1210. #endif
  1211.                    if (dwCreationFlags & CREATE_FORCEDOS) {
  1212.                        goto ForceDos;
  1213.                        }
  1214.  
  1215.                     IsWowBinary = TRUE;
  1216.                     if (!BaseCreateVDMEnvironment(lpEnvironment,
  1217.                                                   &AnsiStringVDMEnv,
  1218.                                                   &UnicodeStringVDMEnv)) {
  1219.                         return FALSE;
  1220.                         }
  1221.  
  1222. RetrySepWow:
  1223.                     VdmBinaryType = dwCreationFlags & CREATE_SEPARATE_WOW_VDM
  1224.                                      ? BINARY_TYPE_SEPWOW : BINARY_TYPE_WIN16;
  1225.  
  1226.                     if (!BaseCheckVDM(VdmBinaryType,
  1227.                                       lpApplicationName,
  1228.                                       lpCommandLine,
  1229.                                       lpCurrentDirectory,
  1230.                                       &AnsiStringVDMEnv,
  1231.                                       &m,
  1232.                                       &iTask,
  1233.                                       dwCreationFlags,
  1234.                                       &StartupInfo
  1235.                                       ))
  1236.                        {
  1237.                         //
  1238.                         // If we failed with access denied, caller may not
  1239.                         // be allowed allowed to access the shared wow's
  1240.                         // desktop, so retry as a separate wow
  1241.                         //
  1242.                         if (VdmBinaryType == BINARY_TYPE_WIN16 &&
  1243.                             GetLastError() == ERROR_ACCESS_DENIED)
  1244.                           {
  1245.                            dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
  1246.                            }
  1247.                         else {
  1248.                             return FALSE;
  1249.                             }
  1250.                         goto RetrySepWow;
  1251.                         }
  1252.  
  1253.                     // Check the return value from the server
  1254.                     switch (b->VDMState & VDM_STATE_MASK){
  1255.                         case VDM_NOT_PRESENT:
  1256.                             // mark this so the server can undo
  1257.                             // creation if something goes wrong.
  1258.                             // We marked it "partitially created" because
  1259.                             // the NTVDM has yet not been fully created.
  1260.                             // a call to UpdateVdmEntry to update
  1261.                             // process handle will signal the NTVDM
  1262.                             // process completed creation
  1263.  
  1264.                             VDMCreationState = VDM_PARTIALLY_CREATED;
  1265.  
  1266.                             // jarbats: 1/8/2001
  1267.                             // Tell BaseGetVdmConfigInfo to create
  1268.                             // vdm commandline for meow
  1269.                             //
  1270.  
  1271.                             if (bMeowBinary)
  1272.                                {
  1273.                                VdmReserve = 1;
  1274.                                }
  1275.  
  1276.                             if (!BaseGetVdmConfigInfo(
  1277.                                     lpCommandLine,
  1278.                                     iTask,
  1279.                                     VdmBinaryType,
  1280.                                     &VdmNameString,
  1281.                                     &VdmReserve
  1282.                                     )) {
  1283.                                 BaseSetLastNTError(Status);
  1284.                                 return FALSE;
  1285.                                 }
  1286.  
  1287.                             lpCommandLine = VdmNameString.Buffer;
  1288.                             lpApplicationName = NULL;
  1289.  
  1290.  
  1291.                             //
  1292.                             // Wow must have a hidden console
  1293.                             // Throw away DETACHED_PROCESS flag which isn't
  1294.                             // meaningful for Win16 apps.
  1295.                             //
  1296.  
  1297.                             dwCreationFlags |= CREATE_NO_WINDOW;
  1298.                             dwCreationFlags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS);
  1299.  
  1300.  
  1301.                             //
  1302.                             // We're starting a WOW VDM, turn on feedback unless
  1303.                             // the creator passed STARTF_FORCEOFFFEEDBACK.
  1304.                             //
  1305.  
  1306.                             StartupInfo.dwFlags |= STARTF_FORCEONFEEDBACK;
  1307.  
  1308.                             break;
  1309.  
  1310.                         case VDM_PRESENT_NOT_READY:
  1311.                             SetLastError (ERROR_NOT_READY);
  1312.                             return FALSE;
  1313.  
  1314.                         case VDM_PRESENT_AND_READY:
  1315.                             VDMCreationState = VDM_BEING_REUSED;
  1316.                             VdmWaitHandle = b->WaitObjectForParent;
  1317.                             break;
  1318.                         }
  1319.  
  1320.                     VdmReserve--;               // we reserve from addr 1
  1321.                     if(VdmWaitHandle)
  1322.                         goto VdmExists;
  1323.                     else {
  1324.                         bInheritHandles = FALSE;
  1325.                         // replace the environment with ours
  1326.                         if (lpEnvironment &&
  1327.                             !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) {
  1328.                             RtlDestroyEnvironment(lpEnvironment);
  1329.                             }
  1330.                         lpEnvironment = UnicodeStringVDMEnv.Buffer;
  1331.                         bVdmRetry = TRUE;
  1332.                         goto VdmRetry;
  1333.                         }
  1334.  
  1335.                 case STATUS_FILE_IS_OFFLINE:
  1336.                     SetLastError(ERROR_FILE_OFFLINE);
  1337.                     break;
  1338.  
  1339.                 default :
  1340.                     SetLastError(ERROR_BAD_EXE_FORMAT);
  1341.                     return FALSE;
  1342.             }
  1343.         }
  1344.  
  1345.         //
  1346.         // Make sure only WOW apps can have the CREATE_SEPARATE_WOW_VDM flag.
  1347.         //
  1348.  
  1349.         if (!IsWowBinary && (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)) {
  1350.             dwCreationFlags &= ~CREATE_SEPARATE_WOW_VDM;
  1351.         }
  1352.  
  1353.         //
  1354.         // Query the section to determine the stack parameters and
  1355.         // image entrypoint.
  1356.         //
  1357.  
  1358.         Status = NtQuerySection(
  1359.                     SectionHandle,
  1360.                     SectionImageInformation,
  1361.                     &ImageInformation,
  1362.                     sizeof( ImageInformation ),
  1363.                     NULL
  1364.                     );
  1365.  
  1366.         if (!NT_SUCCESS( Status )) {
  1367.             BaseSetLastNTError(Status);
  1368.             return FALSE;
  1369.             }
  1370.  
  1371.         if (ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL) {
  1372.             SetLastError(ERROR_BAD_EXE_FORMAT);
  1373.             return FALSE;
  1374.             }
  1375.  
  1376.         ImageFileDebuggerCommand[ 0 ] = UNICODE_NULL;
  1377.         if (!(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) ||
  1378.             NtCurrentPeb()->ReadImageFileExecOptions
  1379.            ) {
  1380.             LdrQueryImageFileExecutionOptions( &PathName,
  1381.                                                L"Debugger",
  1382.                                                REG_SZ,
  1383.                                                ImageFileDebuggerCommand,
  1384.                                                sizeof( ImageFileDebuggerCommand ),
  1385.                                                NULL
  1386.                                              );
  1387.             }
  1388.  
  1389.  
  1390.         if ((ImageInformation.Machine < USER_SHARED_DATA->ImageNumberLow) ||
  1391.             (ImageInformation.Machine > USER_SHARED_DATA->ImageNumberHigh)) {
  1392. #if defined(_WIN64) || defined(BUILD_WOW6432)
  1393.             if (ImageInformation.Machine == IMAGE_FILE_MACHINE_I386) {
  1394.                // Fall through since this is a valid machine type.
  1395.                 }
  1396.              else
  1397. #endif
  1398.                 {
  1399.                 ULONG_PTR ErrorParameters[2];
  1400.                 ULONG ErrorResponse;
  1401.  
  1402. #if defined(_WIN64) || defined(BUILD_WOW6432)
  1403. RaiseInvalidWin32Error:
  1404. #endif
  1405.                 ErrorResponse = ResponseOk;
  1406.                 ErrorParameters[0] = (ULONG_PTR)&PathName;
  1407.  
  1408.                 NtRaiseHardError( STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
  1409.                                   1,
  1410.                                   1,
  1411.                                   ErrorParameters,
  1412.                                   OptionOk,
  1413.                                   &ErrorResponse
  1414.                                 );
  1415.                 if ( NtCurrentPeb()->ImageSubsystemMajorVersion <= 3 ) {
  1416.                     SetLastError(ERROR_BAD_EXE_FORMAT);
  1417.                     }
  1418.                 else {
  1419.                     SetLastError(ERROR_EXE_MACHINE_TYPE_MISMATCH);
  1420.                     }
  1421.                 return FALSE;
  1422.                 }
  1423.             }
  1424.  
  1425.         if ( ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_GUI &&
  1426.              ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_CUI ) {
  1427.  
  1428.             // POSIX exe
  1429.  
  1430.             NtClose(SectionHandle);
  1431.             SectionHandle = NULL;
  1432.  
  1433.             if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_POSIX_CUI ) {
  1434.  
  1435.                 if ( !BuildSubSysCommandLine( L"POSIX /P ",
  1436.                                               lpApplicationName,
  1437.                                               lpCommandLine,
  1438.                                               &SubSysCommandLine
  1439.                                             ) ) {
  1440.                     return FALSE;
  1441.                 }
  1442.  
  1443.                 lpCommandLine = SubSysCommandLine.Buffer;
  1444.  
  1445.                 lpApplicationName = NULL;
  1446.                 bVdmRetry = TRUE;
  1447.                 goto VdmRetry;
  1448.                 }
  1449.             else {
  1450.                 SetLastError(ERROR_CHILD_NOT_COMPLETE);
  1451.                 return FALSE;
  1452.                 }
  1453.             }
  1454.         else {
  1455.             if (!BasepIsImageVersionOk( ImageInformation.SubSystemMajorVersion,
  1456.                                         ImageInformation.SubSystemMinorVersion) ) {
  1457.                 SetLastError(ERROR_BAD_EXE_FORMAT);
  1458.                 return FALSE;
  1459.                 }
  1460.             }
  1461.  
  1462.         if (ImageFileDebuggerCommand[ 0 ] != UNICODE_NULL) {
  1463.             SIZE_T n;
  1464.  
  1465.             n = wcslen( lpCommandLine );
  1466.             if (n == 0) {
  1467.                 lpCommandLine = (LPWSTR)lpApplicationName;
  1468.                 n = wcslen( lpCommandLine );
  1469.                 }
  1470.  
  1471.             n += wcslen( ImageFileDebuggerCommand ) + 1 + 2;
  1472.             n *= sizeof( WCHAR );
  1473.  
  1474.             SubSysCommandLine.Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), n );
  1475.             SubSysCommandLine.Length = 0;
  1476.             SubSysCommandLine.MaximumLength = (USHORT)n;
  1477.             RtlAppendUnicodeToString( &SubSysCommandLine, ImageFileDebuggerCommand );
  1478.             RtlAppendUnicodeToString( &SubSysCommandLine, L" " );
  1479.             RtlAppendUnicodeToString( &SubSysCommandLine, lpCommandLine );
  1480. #if DBG
  1481.             DbgPrint( "BASE: Calling debugger with '%wZ'\n", &SubSysCommandLine );
  1482. #endif
  1483.             lpCommandLine = SubSysCommandLine.Buffer;
  1484.             lpApplicationName = NULL;
  1485.             NtClose(SectionHandle);
  1486.             SectionHandle = NULL;
  1487.             RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
  1488.             NameBuffer = NULL;
  1489.             RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  1490.             FreeBuffer = NULL;
  1491.             goto VdmRetry;
  1492.             }
  1493.  
  1494.         //
  1495.         // Create the process object
  1496.         //
  1497.  
  1498.         pObja = BaseFormatObjectAttributes(&Obja,lpProcessAttributes,NULL);
  1499.  
  1500.         Flags = 0;
  1501.         if (dwCreationFlags & CREATE_BREAKAWAY_FROM_JOB ) {
  1502.             Flags |= PROCESS_CREATE_FLAGS_BREAKAWAY;
  1503.         }
  1504.  
  1505.         if ( dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) ) {
  1506.             Status = DbgUiConnectToDbg();
  1507.             if ( !NT_SUCCESS(Status) ) {
  1508.                 BaseSetLastNTError(Status);
  1509.                 return FALSE;
  1510.             }
  1511.             DebugPortHandle = DbgUiGetThreadDebugObject ();
  1512.             if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS) {
  1513.                 Flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT;
  1514.             }
  1515.         }
  1516.  
  1517.         if (bInheritHandles) {
  1518.             Flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES;
  1519.         }
  1520.  
  1521.         if (((ImageInformation.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS) != 0)) {
  1522.  
  1523. #if defined(_WIN64) || defined(BUILD_WOW6432)
  1524.  
  1525.             //
  1526.             // Check if this is a 32-bit IL_ONLY COM+ image that needs to run natively
  1527.             // on Win64.
  1528.             //
  1529.  
  1530.             if ( ImageInformation.Machine == IMAGE_FILE_MACHINE_I386 ) {
  1531.  
  1532.                 Status = BasepIsComplusILImage(
  1533.                                               SectionHandle,
  1534.                                               &ImageInformation,
  1535.                                               &ComPlusILImage
  1536.                                               );
  1537.  
  1538.                 if ((NT_SUCCESS (Status)) && (ComPlusILImage != FALSE)) {
  1539.                     Flags |= PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE;
  1540.                 }
  1541.             }
  1542.  
  1543. #endif
  1544.         }
  1545.            
  1546.         //
  1547.         // This is temporary till we get Shim dlls support for native Win64 applications.
  1548.         //
  1549.  
  1550.         if (ImageInformation.Machine != IMAGE_FILE_MACHINE_I386) {
  1551.             pAppCompatDataTemp = NULL;
  1552.         } else {
  1553.             pAppCompatDataTemp = pAppCompatData;
  1554.         }
  1555.  
  1556.         Status = NtCreateProcessEx(
  1557.                     &ProcessHandle,
  1558.                     PROCESS_ALL_ACCESS,
  1559.                     pObja,
  1560.                     NtCurrentProcess(),
  1561.                     Flags,
  1562.                     SectionHandle,
  1563.                     DebugPortHandle,
  1564.                     NULL,
  1565.                     dwJobMemberLevel         // Job member level
  1566.                     );
  1567.         if ( !NT_SUCCESS(Status) ) {
  1568.             BaseSetLastNTError(Status);
  1569.             return FALSE;
  1570.         }
  1571.  
  1572.         //
  1573.         // NtCreateProcess will set to normal OR inherit if parent is IDLE or Below
  1574.         // only override if a mask is given during the create.
  1575.         //
  1576.  
  1577.         if ( PriClass.PriorityClass != PROCESS_PRIORITY_CLASS_UNKNOWN ) {
  1578.             State = NULL;
  1579.             if ( PriClass.PriorityClass ==  PROCESS_PRIORITY_CLASS_REALTIME ) {
  1580.                 State = BasepIsRealtimeAllowed(TRUE);
  1581.                 }
  1582.             Status = NtSetInformationProcess(
  1583.                         ProcessHandle,
  1584.                         ProcessPriorityClass,
  1585.                         (PVOID)&PriClass,
  1586.                         sizeof(PriClass)
  1587.                         );
  1588.             if ( State ) {
  1589.                 BasepReleasePrivilege( State );
  1590.                 }
  1591.  
  1592.             if ( !NT_SUCCESS(Status) ) {
  1593.                 BaseSetLastNTError(Status);
  1594.                 return FALSE;
  1595.                 }
  1596.             }
  1597.  
  1598.         if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE) {
  1599.             UINT NewMode;
  1600.             NewMode = SEM_FAILCRITICALERRORS;
  1601.             NtSetInformationProcess(
  1602.                 ProcessHandle,
  1603.                 ProcessDefaultHardErrorMode,
  1604.                 &NewMode,
  1605.                 sizeof(NewMode)
  1606.                 );
  1607.             }
  1608.  
  1609.         //
  1610.         // If the process is being created for a VDM call the server with
  1611.         // process handle.
  1612.         //
  1613.  
  1614.         if (VdmBinaryType) {
  1615.             VdmWaitHandle = ProcessHandle;
  1616.             if (!BaseUpdateVDMEntry(UPDATE_VDM_PROCESS_HANDLE,
  1617.                                     &VdmWaitHandle,
  1618.                                     iTask,
  1619.                                     VdmBinaryType
  1620.                                     ))
  1621.                 {
  1622.                 //make sure we don't close the handle twice --
  1623.                 //(VdmWaitHandle == ProcessHandle) if we don't do this.
  1624.                 VdmWaitHandle = NULL;
  1625.                 return FALSE;
  1626.                 }
  1627.  
  1628.             //
  1629.             // For Sep wow the VdmWaitHandle = NULL (there is none!)
  1630.             //
  1631.  
  1632.             VDMCreationState |= VDM_FULLY_CREATED;
  1633.             }
  1634.  
  1635.  
  1636. #if defined(i386)
  1637.         //
  1638.         // Reserve memory in the new process' address space if necessary
  1639.         // (for vdms). This is required only for x86 system.
  1640.         //
  1641.  
  1642.     if ( VdmReserve ) {
  1643.             BigVdmReserve = VdmReserve;
  1644.             Status = NtAllocateVirtualMemory(
  1645.                         ProcessHandle,
  1646.                         &BaseAddress,
  1647.                         0L,
  1648.                         &BigVdmReserve,
  1649.                         MEM_RESERVE,
  1650.                         PAGE_EXECUTE_READWRITE
  1651.                         );
  1652.             if ( !NT_SUCCESS(Status) ){
  1653.                 BaseSetLastNTError(Status);
  1654.                 return FALSE;
  1655.             }
  1656.     }
  1657. #endif
  1658.  
  1659.         //
  1660.         // Abuse the StaticSize fields temporarily.
  1661.         // They are somewhat private, but we are using them for temporary space, sort of.
  1662.         // These are the right values for them, but we need to call the proper initialization function,
  1663.         // which will store the values a second time (possibly optimized away).
  1664.         //
  1665.         SxsWin32ManifestPathBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(SXS_MANIFEST_SUFFIX);
  1666.         SxsWin32PolicyPathBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(SXS_POLICY_SUFFIX);
  1667.         SxsWin32AssemblyDirectoryBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(WCHAR); // Win32AssemblyDirectory overestimate
  1668.         SxsNtManifestPathBuffer.ByteBuffer.StaticSize = SxsNtExePath.Length + sizeof(SXS_MANIFEST_SUFFIX);
  1669.         SxsNtPolicyPathBuffer.ByteBuffer.StaticSize = SxsNtExePath.Length + sizeof(SXS_POLICY_SUFFIX);
  1670.         //
  1671.         // now add them up as BYTE sizes
  1672.         //
  1673.         SxsConglomeratedBufferSizeBytes = 0;
  1674.         for (sxsi = 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
  1675.             SxsConglomeratedBufferSizeBytes += SxsStringBuffers[sxsi]->ByteBuffer.StaticSize;
  1676.         }
  1677. #if DBG
  1678.         DbgPrintEx(
  1679.             DPFLTR_SXS_ID,
  1680.             DPFLTR_INFO_LEVEL,
  1681.             "SXS: SxsConglomeratedBufferSizeBytes:%Id\n",
  1682.             SxsConglomeratedBufferSizeBytes
  1683.             );
  1684. #endif
  1685.         //
  1686.         // one honking heap allocation
  1687.         //
  1688.         SxsConglomeratedByteBuffer = (PBYTE)RtlAllocateHeap(RtlProcessHeap(), 0, SxsConglomeratedBufferSizeBytes);
  1689.         if (SxsConglomeratedByteBuffer == NULL) {
  1690.             BaseSetLastNTError(STATUS_NO_MEMORY);
  1691.             return FALSE;
  1692.         }
  1693.         //
  1694.         // now dole out pieces, calling the proper initialization function
  1695.         //
  1696.         for (sxsi= 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
  1697.             RtlInitUnicodeStringBuffer(
  1698.                 SxsStringBuffers[sxsi],
  1699.                 (sxsi != 0) ? SxsStringBuffers[sxsi - 1]->ByteBuffer.Buffer + SxsStringBuffers[sxsi- 1]->ByteBuffer.StaticSize
  1700.                          : SxsConglomeratedByteBuffer,
  1701.                 SxsStringBuffers[sxsi]->ByteBuffer.StaticSize
  1702.                 );
  1703.         }
  1704.  
  1705.         SxsExeHandles.Process = ProcessHandle;
  1706.         SxsExeHandles.File = FileHandle;
  1707.          // The 1 bit here means something different than in the loader.
  1708.         ASSERT((((ULONG_PTR)SectionHandle) & (ULONG_PTR)1) == 0);
  1709.         SxsExeHandles.Section = SectionHandle;
  1710.  
  1711.         // if we have an override stream, use it
  1712.         if (NULL != pAppCompatSxsData) {
  1713.             AppCompatSxsManifest.Name    = SxsWin32ExePath;     // unicode string
  1714.             AppCompatSxsManifest.Address = pAppCompatSxsData;   // pointer to unicode manifest
  1715.             AppCompatSxsManifest.Size    = cbAppCompatSxsData;  // byte count
  1716.         }
  1717.  
  1718.         Status = BasepSxsCreateProcessCsrMessage(
  1719.             (NULL != pAppCompatSxsData) ? &AppCompatSxsManifest : NULL, // override manifest (appcompat hook)
  1720.             NULL, // override policy (appcompat hook)
  1721.             &SxsManifestPathPair,
  1722.             &SxsManifestFileHandles,
  1723.             &SxsExePathPair,
  1724.             &SxsExeHandles,
  1725.             &SxsPolicyPathPair,
  1726.             &SxsPolicyHandles,
  1727.             &SxsWin32AssemblyDirectoryBuffer,
  1728.             &a->Sxs
  1729.             );
  1730. #if DBG
  1731.         // verify the buffer size calculation
  1732.         for (sxsi = 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi)
  1733.         {
  1734.             if (SxsStringBuffers[sxsi]->ByteBuffer.Buffer != SxsStringBuffers[sxsi]->ByteBuffer.StaticBuffer)
  1735.             {
  1736.                 DbgPrintEx(
  1737.                     DPFLTR_SXS_ID,
  1738.                     DPFLTR_WARNING_LEVEL,
  1739.                     "SXS: SxsStringBuffers[%lu]'s StaticSize was computed too small (%Id, %Id)\n",
  1740.                     sxsi,
  1741.                     SxsStringBuffers[sxsi]->ByteBuffer.StaticSize,
  1742.                     SxsStringBuffers[sxsi]->ByteBuffer.Size
  1743.                     );
  1744.             }
  1745.         }
  1746. #endif
  1747.         if ( !NT_SUCCESS( Status ) ) {
  1748.             BaseSetLastNTError(Status);
  1749.             return FALSE;
  1750.             }
  1751.  
  1752.         //
  1753.         // Determine the location of the
  1754.         // processes PEB.
  1755.         //
  1756.  
  1757.         Status = NtQueryInformationProcess(
  1758.                     ProcessHandle,
  1759.                     ProcessBasicInformation,
  1760.                     &ProcessInfo,
  1761.                     sizeof( ProcessInfo ),
  1762.                     NULL
  1763.                     );
  1764.         if ( !NT_SUCCESS( Status ) ) {
  1765.             BaseSetLastNTError(Status);
  1766.             return FALSE;
  1767.             }
  1768.  
  1769.         Peb = ProcessInfo.PebBaseAddress;
  1770.  
  1771.         //
  1772.         // Push the parameters into the address space of the new process
  1773.         //
  1774.  
  1775.         if ( ARGUMENT_PRESENT(lpCurrentDirectory) ) {
  1776.             CurdirBuffer = RtlAllocateHeap( RtlProcessHeap(),
  1777.                                             MAKE_TAG( TMP_TAG ),
  1778.                                             (MAX_PATH + 1) * sizeof( WCHAR ) );
  1779.             if ( !CurdirBuffer ) {
  1780.                 BaseSetLastNTError(STATUS_NO_MEMORY);
  1781.                 return FALSE;
  1782.                 }
  1783.             CurdirLength2 = GetFullPathNameW(
  1784.                                 lpCurrentDirectory,
  1785.                                 MAX_PATH,
  1786.                                 CurdirBuffer,
  1787.                                 &CurdirFilePart
  1788.                                 );
  1789.             if ( CurdirLength2 > MAX_PATH ) {
  1790.                 SetLastError(ERROR_DIRECTORY);
  1791.                 return FALSE;
  1792.                 }
  1793.  
  1794.             //
  1795.             // now make sure the directory exists
  1796.             //
  1797.  
  1798.             CurdirLength = GetFileAttributesW(CurdirBuffer);
  1799.             if ( (CurdirLength == 0xffffffff) ||
  1800.                  !(CurdirLength & FILE_ATTRIBUTE_DIRECTORY) ) {
  1801.                 SetLastError(ERROR_DIRECTORY);
  1802.                 return FALSE;
  1803.                 }
  1804.             }
  1805.  
  1806.  
  1807.         if ( QuoteInsert || QuoteCmdLine) {
  1808.             QuotedBuffer = RtlAllocateHeap(RtlProcessHeap(),0,wcslen(lpCommandLine)*2+6);
  1809.  
  1810.             if ( QuotedBuffer ) {
  1811.                 wcscpy(QuotedBuffer,L"\"");
  1812.  
  1813.                 if ( QuoteInsert ) {
  1814.                     TempChar = *TempNull;
  1815.                     *TempNull = UNICODE_NULL;
  1816.                     }
  1817.  
  1818.                 wcscat(QuotedBuffer,lpCommandLine);
  1819.                 wcscat(QuotedBuffer,L"\"");
  1820.  
  1821.                 if ( QuoteInsert ) {
  1822.                     *TempNull = TempChar;
  1823.                     wcscat(QuotedBuffer,TempNull);
  1824.                     }
  1825.  
  1826.                 }
  1827.             else {
  1828.                 if ( QuoteInsert ) {
  1829.                     QuoteInsert = FALSE;
  1830.                     }
  1831.                 if ( QuoteCmdLine ) {
  1832.                     QuoteCmdLine = FALSE;
  1833.                     }
  1834.                 }
  1835.             }
  1836.  
  1837.  
  1838.         // If we found a manifest, we want to push that fact to the new process.
  1839.         if (a->Sxs.Flags & BASE_MSG_SXS_MANIFEST_PRESENT)
  1840.             dwBasePushProcessParametersFlags |= BASE_PUSH_PROCESS_PARAMETERS_FLAG_APP_MANIFEST_PRESENT;
  1841.  
  1842.         if (!BasePushProcessParameters(
  1843.                 dwBasePushProcessParametersFlags,
  1844.                 ProcessHandle,
  1845.                 Peb,
  1846.                 lpApplicationName,
  1847.                 CurdirBuffer,
  1848.                 QuoteInsert || QuoteCmdLine ? QuotedBuffer : lpCommandLine,
  1849.                 lpEnvironment,
  1850.                 &StartupInfo,
  1851.                 dwCreationFlags | dwNoWindow,
  1852.                 bInheritHandles,
  1853.                 IsWowBinary ? IMAGE_SUBSYSTEM_WINDOWS_GUI : 0,
  1854.                 pAppCompatDataTemp,
  1855.                 cbAppCompatData
  1856.                 ) ) {
  1857.             return FALSE;
  1858.             }
  1859.  
  1860.  
  1861.         RtlFreeUnicodeString(&VdmNameString);
  1862.         VdmNameString.Buffer = NULL;
  1863.  
  1864.         //
  1865.         // Stuff in the standard handles if needed
  1866.         //
  1867.         if (!VdmBinaryType &&
  1868.             !bInheritHandles &&
  1869.             !(StartupInfo.dwFlags & STARTF_USESTDHANDLES) &&
  1870.             !(dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE | CREATE_NO_WINDOW)) &&
  1871.             ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI
  1872.            ) {
  1873.             PRTL_USER_PROCESS_PARAMETERS ParametersInNewProcess;
  1874.  
  1875.             Status = NtReadVirtualMemory( ProcessHandle,
  1876.                                           &Peb->ProcessParameters,
  1877.                                           &ParametersInNewProcess,
  1878.                                           sizeof( ParametersInNewProcess ),
  1879.                                           NULL
  1880.                                         );
  1881.             if (NT_SUCCESS( Status )) {
  1882.                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardInput )) {
  1883.                     StuffStdHandle( ProcessHandle,
  1884.                                     NtCurrentPeb()->ProcessParameters->StandardInput,
  1885.                                     &ParametersInNewProcess->StandardInput
  1886.                                   );
  1887.                     }
  1888.                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardOutput )) {
  1889.                     StuffStdHandle( ProcessHandle,
  1890.                                     NtCurrentPeb()->ProcessParameters->StandardOutput,
  1891.                                     &ParametersInNewProcess->StandardOutput
  1892.                                   );
  1893.                     }
  1894.                 if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardError )) {
  1895.                     StuffStdHandle( ProcessHandle,
  1896.                                     NtCurrentPeb()->ProcessParameters->StandardError,
  1897.                                     &ParametersInNewProcess->StandardError
  1898.                                   );
  1899.                     }
  1900.                 }
  1901.             }
  1902.  
  1903.         //
  1904.         // Create the thread...
  1905.         //
  1906.  
  1907.         //
  1908.         // Allocate a stack for this thread in the address space of the target
  1909.         // process.
  1910.         //
  1911.  
  1912.         StackStatus = BaseCreateStack(
  1913.                         ProcessHandle,
  1914.                         ImageInformation.CommittedStackSize,
  1915.                         (ImageInformation.MaximumStackSize < 256*1024) ? 256*1024 : ImageInformation.MaximumStackSize,
  1916.                         &InitialTeb
  1917.                         );
  1918.  
  1919.         if ( !NT_SUCCESS(StackStatus) ) {
  1920.             BaseSetLastNTError(StackStatus);
  1921.             return FALSE;
  1922.             }
  1923.  
  1924.  
  1925.         //
  1926.         // Create an initial context for the new thread.
  1927.         //
  1928.  
  1929.         BaseInitializeContext(
  1930.             &ThreadContext,
  1931.             Peb,
  1932.             ImageInformation.TransferAddress,
  1933.             InitialTeb.StackBase,
  1934.             BaseContextTypeProcess
  1935.             );
  1936.  
  1937.  
  1938.         //
  1939.         // Create the actual thread object
  1940.         //
  1941.  
  1942.         pObja = BaseFormatObjectAttributes(&Obja,lpThreadAttributes,NULL);
  1943.  
  1944.         Status = NtCreateThread(
  1945.                     &ThreadHandle,
  1946.                     THREAD_ALL_ACCESS,
  1947.                     pObja,
  1948.                     ProcessHandle,
  1949.                     &ClientId,
  1950.                     &ThreadContext,
  1951.                     &InitialTeb,
  1952.                     TRUE
  1953.                     );
  1954.  
  1955.         if (!NT_SUCCESS(Status) ) {
  1956.             BaseSetLastNTError(Status);
  1957.             return FALSE;
  1958.             }
  1959.  
  1960.         a->Peb = (ULONGLONG) Peb;
  1961.  
  1962.         //
  1963.         // From here on out, do not modify the address space of the
  1964.         // new process.  WOW64's implementation of NtCreateThread()
  1965.         // reshuffles the new process' address space if the current
  1966.         // process is 32-bit and the new process is 64-bit.
  1967.         //
  1968. #if DBG
  1969.         Peb = NULL;
  1970. #endif
  1971.  
  1972. #if defined(WX86)
  1973.  
  1974.         //
  1975.         // if this is a Wx86 Process, setup for a Wx86 emulated Thread
  1976.         //
  1977.  
  1978.         if (Wx86Info) {
  1979.  
  1980.             //
  1981.             // create a WX86Tib and initialize it's Teb->Vdm.
  1982.             //
  1983.             Status = BaseCreateWx86Tib(ProcessHandle,
  1984.                                        ThreadHandle,
  1985.                                        (ULONG)((ULONG_PTR)ImageInformation.TransferAddress),
  1986.                                        (ULONG)ImageInformation.CommittedStackSize,
  1987.                                        (ULONG)ImageInformation.MaximumStackSize,
  1988.                                        TRUE
  1989.                                        );
  1990.  
  1991.             if (!NT_SUCCESS(Status)) {
  1992.                 BaseSetLastNTError(Status);
  1993.                 return( FALSE );
  1994.                 }
  1995.  
  1996.  
  1997.             //
  1998.             // Mark Process as WX86
  1999.             //
  2000.             Status = NtSetInformationProcess (ProcessHandle,
  2001.                                               ProcessWx86Information,
  2002.                                               &Wx86Info,
  2003.                                               sizeof(Wx86Info)
  2004.                                               );
  2005.  
  2006.             if (!NT_SUCCESS(Status)) {
  2007.                 BaseSetLastNTError(Status);
  2008.                 return( FALSE );
  2009.                 }
  2010.             }
  2011. #endif
  2012.  
  2013.  
  2014.         //
  2015.         // Call the Windows server to let it know about the
  2016.         // process.
  2017.         //
  2018.  
  2019.         a->ProcessHandle = ProcessHandle;
  2020.         a->ThreadHandle = ThreadHandle;
  2021.         a->ClientId = ClientId;
  2022.  
  2023.         switch (ImageInformation.Machine) {
  2024.         case IMAGE_FILE_MACHINE_I386:
  2025. #if defined(_WIN64) || defined(BUILD_WOW6432)
  2026.             a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA32_ON_WIN64;
  2027. #else
  2028.             a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  2029. #endif
  2030.             break;
  2031.  
  2032.         case IMAGE_FILE_MACHINE_IA64:
  2033.             a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
  2034.             break;
  2035.  
  2036.         case IMAGE_FILE_MACHINE_AMD64:
  2037.             a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
  2038.             break;
  2039.  
  2040.         default:
  2041.             DbgPrint("kernel32: No mapping for ImageInformation.Machine == %04x\n", ImageInformation.Machine);
  2042.             a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  2043.             break;
  2044.         }
  2045.  
  2046.         //
  2047.         // remove debug flags now its not being done by CSR
  2048.         //
  2049.         a->CreationFlags = dwCreationFlags & ~ (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS);
  2050.         a->DebuggerClientId.UniqueProcess = NULL;
  2051.         a->DebuggerClientId.UniqueThread = NULL;
  2052.  
  2053.  
  2054.         //
  2055.         // Set the 2 bit if a gui app is starting. The window manager needs to
  2056.         // know this so it can synchronize the startup of this app
  2057.         // (WaitForInputIdle api). This info is passed using the process
  2058.         // handle tag bits.  The 1 bit asks the window manager to turn on
  2059.         // or turn off the application start cursor (hourglass/pointer).
  2060.         //
  2061.         // When starting a WOW process, lie and tell UserSrv NTVDM.EXE is a GUI
  2062.         // process.  We also turn on bit 0x8 so that UserSrv can ignore the
  2063.         // UserNotifyConsoleApplication call made by the console during startup.
  2064.         //
  2065.  
  2066.         if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI ||
  2067.              IsWowBinary ) {
  2068.  
  2069.             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 2);
  2070.  
  2071.             //
  2072.             // If the creating process is a GUI app, turn on the app. start cursor
  2073.             // by default.  This can be overridden by STARTF_FORCEOFFFEEDBACK.
  2074.             //
  2075.  
  2076.             NtHeaders = RtlImageNtHeader((PVOID)GetModuleHandle(NULL));
  2077.             if ( NtHeaders
  2078.                  && (NtHeaders->OptionalHeader.Subsystem
  2079.                      == IMAGE_SUBSYSTEM_WINDOWS_GUI ) ) {
  2080.                 a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
  2081.                 }
  2082.             }
  2083.  
  2084.  
  2085.         //
  2086.         // If feedback is forced on, turn it on. If forced off, turn it off.
  2087.         // Off overrides on.
  2088.         //
  2089.  
  2090.         if (StartupInfo.dwFlags & STARTF_FORCEONFEEDBACK)
  2091.             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
  2092.         if (StartupInfo.dwFlags & STARTF_FORCEOFFFEEDBACK)
  2093.             a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle & ~1);
  2094.  
  2095.         a->VdmBinaryType = VdmBinaryType; // just tell server the truth
  2096.  
  2097.         if (VdmBinaryType){
  2098.            a->hVDM    = iTask ? 0 : NtCurrentPeb()->ProcessParameters->ConsoleHandle;
  2099.            a->VdmTask = iTask;
  2100.         }
  2101.  
  2102. #if defined(BUILD_WOW6432)
  2103.         m.ReturnValue = CsrBasepCreateProcess(a);
  2104. #else
  2105.         m.u.CreateProcess = *a;
  2106.         if (m.u.CreateProcess.Sxs.Flags != 0)
  2107.         {
  2108.             const PUNICODE_STRING StringsToCapture[] =
  2109.             {
  2110.                 &m.u.CreateProcess.Sxs.Manifest.Path,
  2111.                     &m.u.CreateProcess.Sxs.Policy.Path,
  2112.                     &m.u.CreateProcess.Sxs.AssemblyDirectory
  2113.             };
  2114.  
  2115.             Status =
  2116.                 CsrCaptureMessageMultiUnicodeStringsInPlace(
  2117.                 &CaptureBuffer,
  2118.                 RTL_NUMBER_OF(StringsToCapture),
  2119.                 StringsToCapture
  2120.                 );
  2121.             if (!NT_SUCCESS(Status)) {
  2122.                 BaseSetLastNTError(Status);
  2123.                 return FALSE;
  2124.             }
  2125.         }
  2126.  
  2127.         CsrClientCallServer( (PCSR_API_MSG)&m,
  2128.                              CaptureBuffer,
  2129.                              CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
  2130.                                                   BasepCreateProcess
  2131.                                                 ),
  2132.                              sizeof( *a )
  2133.                            );
  2134.  
  2135.         if ( CaptureBuffer ) {
  2136.             CsrFreeCaptureBuffer( CaptureBuffer );
  2137.             CaptureBuffer = NULL;
  2138.         }
  2139.  
  2140. #endif
  2141.  
  2142.         if (!NT_SUCCESS((NTSTATUS)m.ReturnValue)) {
  2143.             BaseSetLastNTError((NTSTATUS)m.ReturnValue);
  2144.             NtTerminateProcess(ProcessHandle, (NTSTATUS)m.ReturnValue);
  2145.             return FALSE;
  2146.             }
  2147.  
  2148.  
  2149.  
  2150.         //
  2151.         // If the WinSafer sandboxing policy indicates that the
  2152.         // process needs to be run with a restricted token or placed
  2153.         // into a restricted job object, then do those actions now.
  2154.         // Do not replace the token if the restricted token was created
  2155.         // from a caller supplied token i.e. the CreateProcessAsUser case.
  2156.         //
  2157.         if ((hSaferRestrictedToken != NULL) && (hUserToken == NULL)) {
  2158.             Status = BasepReplaceProcessThreadTokens(
  2159.                     hSaferRestrictedToken,
  2160.                     ProcessHandle,
  2161.                     ThreadHandle);
  2162.             if (!NT_SUCCESS(Status)) {
  2163.                 // kill and cleanup.
  2164.                 NtTerminateProcess(ProcessHandle, Status);
  2165.                 BaseSetLastNTError(Status);
  2166.                 return FALSE;
  2167.             }
  2168.         }
  2169.         if (hSaferAssignmentJob != NULL) {
  2170.             Status = NtAssignProcessToJobObject(
  2171.                     hSaferAssignmentJob, ProcessHandle);
  2172.             if (!NT_SUCCESS(Status)) {
  2173.                 // kill and cleanup.
  2174.                 NtTerminateProcess(ProcessHandle, STATUS_ACCESS_DENIED);
  2175.                 BaseSetLastNTError(Status);
  2176.                 return FALSE;
  2177.             }
  2178.         }
  2179.  
  2180.  
  2181.         //
  2182.         // Make the thread start execution if we are allowed to.
  2183.         //
  2184.         if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
  2185.             NtResumeThread(ThreadHandle,&i);
  2186.             }
  2187.  
  2188. VdmExists:
  2189.         bStatus = TRUE;
  2190.         if (VDMCreationState)
  2191.             VDMCreationState |= VDM_CREATION_SUCCESSFUL;
  2192.  
  2193.         try {
  2194.             if (VdmWaitHandle) {
  2195.  
  2196.                 //
  2197.                 // tag Shared WOW VDM handles so that wait for input idle has a
  2198.                 // chance to work.  Shared WOW VDM "process" handles are actually
  2199.                 // event handles,  Separate WOW VDM handles are real process
  2200.                 // handles. Also mark DOS handles with 0x1 so WaitForInputIdle
  2201.                 // has a way to distinguish DOS apps and not block forever.
  2202.                 //
  2203.  
  2204.                 if (VdmBinaryType == BINARY_TYPE_WIN16)  {
  2205.                     lpProcessInformation->hProcess =
  2206.                             (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x2);
  2207.  
  2208.                     //
  2209.                     // Shared WOW doesn't always start a process, so
  2210.                     // we don't have a process ID or thread ID to
  2211.                     // return if the VDM already existed.
  2212.                     //
  2213.                     // Separate WOW doesn't hit this codepath
  2214.                     // (no VdmWaitHandle).
  2215.                     //
  2216.  
  2217.                     if (VDMCreationState & VDM_BEING_REUSED) {
  2218.                         ClientId.UniqueProcess = 0;
  2219.                         ClientId.UniqueThread = 0;
  2220.                         }
  2221.  
  2222.                     }
  2223.                 else  {
  2224.                     lpProcessInformation->hProcess =
  2225.                             (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x1);
  2226.                     }
  2227.  
  2228.  
  2229.                 //
  2230.                 // Close the ProcessHandle, since we are returning the
  2231.                 // VdmProcessHandle instead.
  2232.                 //
  2233.  
  2234.                 if (ProcessHandle != NULL)
  2235.                     NtClose(ProcessHandle);
  2236.                 }
  2237.             else{
  2238.                 lpProcessInformation->hProcess = ProcessHandle;
  2239.                 }
  2240.  
  2241.             lpProcessInformation->hThread = ThreadHandle;
  2242.             lpProcessInformation->dwProcessId = HandleToUlong(ClientId.UniqueProcess);
  2243.             lpProcessInformation->dwThreadId = HandleToUlong(ClientId.UniqueThread);
  2244.             ProcessHandle = NULL;
  2245.             ThreadHandle = NULL;
  2246.             }
  2247.         __except ( EXCEPTION_EXECUTE_HANDLER ) {
  2248.             NtClose( ProcessHandle );
  2249.             NtClose( ThreadHandle );
  2250.             ProcessHandle = NULL;
  2251.             ThreadHandle = NULL;
  2252.             if (VDMCreationState)
  2253.                 VDMCreationState &= ~VDM_CREATION_SUCCESSFUL;
  2254.             }
  2255.         }
  2256.     __finally {
  2257.  
  2258.         if (ExePathFullBuffer != NULL) {
  2259.             SxsWin32ExePath.Buffer = NULL;
  2260.             SxsWin32ExePath.Length = 0;
  2261.             SxsWin32ExePath.MaximumLength = 0;
  2262.             RtlFreeHeap(RtlProcessHeap(), 0, ExePathFullBuffer);
  2263.             ExePathFullBuffer = NULL;
  2264.         }
  2265.  
  2266.         if (!VdmBinaryType) {
  2267.             NTSTATUS Status1;
  2268.  
  2269.             BasepSxsCloseHandles(&SxsManifestFileHandles);
  2270.             BasepSxsCloseHandles(&SxsPolicyHandles);
  2271.             //
  2272.             // don't close SxsExeHandles, they are
  2273.             // aliases of other variables that are either closed
  2274.             // or returned to the caller
  2275.             //
  2276.  
  2277.             //
  2278.             // This loop only really frees any memory if our computation
  2279.             // of the overall buffer size was too low, which it is not supposed to be.
  2280.             //
  2281.             if (SxsConglomeratedByteBuffer != NULL) {
  2282.                 for (sxsi= 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
  2283.                     RtlFreeUnicodeStringBuffer(SxsStringBuffers[sxsi]);
  2284.                     }
  2285.                 RtlFreeHeap(RtlProcessHeap(), 0,SxsConglomeratedByteBuffer);
  2286.                 }
  2287.             }
  2288.         if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
  2289.             RtlDestroyEnvironment(lpEnvironment);
  2290.             lpEnvironment = NULL;
  2291.             }
  2292.         RtlFreeHeap(RtlProcessHeap(), 0,QuotedBuffer);
  2293.         RtlFreeHeap(RtlProcessHeap(), 0,NameBuffer);
  2294.         RtlFreeHeap(RtlProcessHeap(), 0,CurdirBuffer);
  2295.         RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  2296.         if ( FileHandle ) {
  2297.             NtClose(FileHandle);
  2298.             }
  2299.         if ( SectionHandle ) {
  2300.             NtClose(SectionHandle);
  2301.             }
  2302.         if ( ThreadHandle ) {
  2303.             NtTerminateProcess(ProcessHandle,STATUS_SUCCESS);
  2304.             NtClose(ThreadHandle);
  2305.             }
  2306.         if ( ProcessHandle ) {
  2307.             NtClose(ProcessHandle);
  2308.             }
  2309.         if ( hSaferAssignmentJob ) {
  2310.             NtClose(hSaferAssignmentJob);
  2311.             }
  2312.         if ( hSaferRestrictedToken ) {
  2313.             if (hUserToken == NULL) {
  2314.                 // CreateProcess case
  2315.                 NtClose(hSaferRestrictedToken);
  2316.                 }
  2317.             else{
  2318.                 // CreateProcessAsUser case
  2319.                 *hRestrictedUserToken = hSaferRestrictedToken;
  2320.                 }
  2321.             }
  2322.  
  2323.         if (NULL != pAppCompatData) {
  2324.             RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
  2325.             }
  2326.  
  2327.         if (NULL != pAppCompatSxsData) {
  2328.             RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatSxsData);
  2329.             }
  2330.  
  2331.         RtlFreeUnicodeString(&VdmNameString);
  2332.         RtlFreeUnicodeString(&SubSysCommandLine);
  2333.         if (AnsiStringVDMEnv.Buffer || UnicodeStringVDMEnv.Buffer)
  2334.             BaseDestroyVDMEnvironment(&AnsiStringVDMEnv, &UnicodeStringVDMEnv);
  2335.  
  2336.         if (VDMCreationState && !(VDMCreationState & VDM_CREATION_SUCCESSFUL)){
  2337.             BaseUpdateVDMEntry (
  2338.                 UPDATE_VDM_UNDO_CREATION,
  2339.                 (HANDLE *)&iTask,
  2340.                 VDMCreationState,
  2341.                 VdmBinaryType
  2342.                 );
  2343.             if(VdmWaitHandle) {
  2344.                 NtClose(VdmWaitHandle);
  2345.                 }
  2346.             }
  2347.         }
  2348.  
  2349.     if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
  2350.         RtlDestroyEnvironment(lpEnvironment);
  2351.         }
  2352.     return bStatus;
  2353. }
  2354.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement