Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- BOOL
- WINAPI
- CreateProcessInternalW(
- HANDLE hUserToken,
- LPCWSTR lpApplicationName,
- LPWSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCWSTR lpCurrentDirectory,
- LPSTARTUPINFOW lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation,
- PHANDLE hRestrictedUserToken
- )
- /*++
- Routine Description:
- This is the worker routine for CreateProcess and CreateProcessAsUser.
- CreateProcessAsUser supplies a User token to be stamped on the new process.
- CreateProcess supplies NULL and the current process token is used.
- A process and thread object are created and a handle opened to each
- object using CreateProcessInternal. Note that WinExec and LoadModule are
- still supported, but are implemented as a call to CreateProcess.
- Arguments:
- hUserToken - Supplies an optional token handle to be set on the new process.
- Process token is used is this parameter is NULL.
- lpApplicationName - Supplies an optional pointer to a null terminated
- character string that contains the name of the image file to
- execute. This is a fully qualified DOS path name. If not
- specified, then the image file name is the first whitespace
- delimited token on the command line.
- lpCommandLine - Supplies a null terminated character string that
- contains the command line for the application to be executed.
- The entire command line is made available to the new process
- using GetCommandLine. If the lpApplicationName parameter was
- not specified, then the first token of the command line
- specifies file name of the application (note that this token
- begins at the beginning of the command line and ends at the
- first "white space" character). If the file name does not
- contain an extension (the presence of a "."), then .EXE is
- assumed. If the file name does not contain a directory path,
- Windows will search for the executable file in:
- - The current directory
- - The windows directory
- - The windows system directory
- - The directories listed in the path environment variable
- This parameter is optional onlu if the lpApplicationName
- parameter is specified. In this case the command line the
- application receives will be the application name.
- lpProcessAttributes - An optional parameter that may be used to
- specify the attributes of the new process. If the parameter is
- not specified, then the process is created without a security
- descriptor, and the resulting handle is not inherited on process
- creation:
- SECURITY_ATTRIBUTES Structure:
- DWORD nLength - Specifies the length of this structure. Must be
- set to sizeof( SECURITY_ATTRUBUTES ).
- LPVOID lpSecurityDescriptor - Points to a security descriptor for
- the object (must be NULL for Win32, used on NT/Win32). The
- security descriptor controls the sharing of an object.
- BOOL bInheritHandle - Supplies a flag that indicates whether
- or not the returned handle is to be inherited by a new
- process during process creation. A value of TRUE
- indicates that the new process will inherit the handle.
- lpThreadAttributes - An optional parameter that may be used to specify
- the attributes of the new thread. If the parameter is not
- specified, then the thread is created without a security
- descriptor, and the resulting handle is not inherited on
- process creation.
- dwCreationFlags - Supplies additional flags that control the creation
- of the process.
- dwCreationFlags Flags:
- DEBUG_PROCESS - If this flag bit is set, then the creating
- process is treated as a debugger, and the process being
- created is created as a debugee. All debug events occuring
- in the debugee are reported to the debugger. If this bit is
- clear, but the calling process is a debugee, then the
- process becomes a debugee of the calling processes debugger.
- If this bit is clear and the calling processes is not a
- debugee then no debug related actions occur.
- DEBUG_ONLY_THIS_PROCESS - If this flag is set, then the
- DEBUG_PROCESS flag bit must also be set. The calling
- process is is treated as a debugger, and the new process is
- created as its debuggee. If the new process creates
- additional processes, no debug related activities (with
- respect to the debugger) occur.
- CREATE_SUSPENDED - The process is created, but the initial thread
- of the process remains suspended. The creator can resume this
- thread using ResumeThread. Until this is done, code in the
- process will not execute.
- CREATE_UNICODE_ENVIRONMENT - If set, the environment pointer
- points to a Unicode environment block. Otherwise, the
- block is ANSI (actually OEM.)
- bInheritHandles - Supplies a flag that specifies whether or not the
- new process is to inherit handles to objects visible to the
- calling process. A value of TRUE causes handles to be inherited
- by the new process. If TRUE was specified, then for each handle
- visible to the calling process, if the handle was created with
- the inherit handle option, the handle is inherited to the new
- process. The handle has the same granted access in the new
- process as it has in the calling process, and the value of the
- handle is the same.
- lpEnvironment - An optional parameter, that if specified, supplies a
- pointer to an environment block. If the parameter is not
- specified, the environment block of the current process is used.
- This environment block is made available to the new process
- using GetEnvironmentStrings.
- lpCurrentDirectory - An optional parameter, that if specified,
- supplies a string representing the current drive and directory
- for the new process. The string must be a fully qualified
- pathname that includes a drive letter. If the parameter is not
- specified, then the new process is created with the same current
- drive and directory as the calling process. This option is
- provided primarily for shells that want to start an application
- and specify its initial drive and working directory.
- lpStartupInfo - Supplies information that specified how the
- applications window is to be shown. This structure is described
- in the Win32 User Interface API Book.
- lpProcessInformation - Returns identification information about the
- new process.
- PROCESS_INFORMATION Structure:
- HANDLE hProcess - Returns a handle to the newly created process.
- Through the handle, all operations on process objects are
- allowed.
- HANDLE hThread - Returns a handle to the newly created thread.
- Through the handle, all operations on thread objects are
- allowed.
- DWORD dwProcessId - Returns a global process id that may be used
- to identify a process. The value is valid from the time the
- process is created until the time the process is terminated.
- DWORD dwThreadId - Returns a global thread id that may be used
- to identify a thread. The value is valid from the time the
- thread is created until the time the thread is terminated.
- hRestrictedUserToken - Returns a restricted token if a UsetToken was
- supplied. This is applicable for the CreateProcessAsUser case.
- The token is released by CreateProcessAsUser.
- Return Value:
- TRUE - The operation was successful
- FALSE/NULL - The operation failed. Extended error status is available
- using GetLastError.
- --*/
- {
- NTSTATUS Status;
- OBJECT_ATTRIBUTES Obja;
- POBJECT_ATTRIBUTES pObja;
- HANDLE ProcessHandle, ThreadHandle, VdmWaitHandle = NULL;
- HANDLE FileHandle, SectionHandle;
- CLIENT_ID ClientId;
- UNICODE_STRING PathName;
- IO_STATUS_BLOCK IoStatusBlock;
- BOOLEAN TranslationStatus;
- RTL_RELATIVE_NAME RelativeName;
- PVOID FreeBuffer;
- LPWSTR NameBuffer;
- LPWSTR WhiteScan;
- ULONG Length,i;
- PROCESS_BASIC_INFORMATION ProcessInfo;
- SECTION_IMAGE_INFORMATION ImageInformation;
- NTSTATUS StackStatus;
- BOOLEAN bStatus;
- INITIAL_TEB InitialTeb;
- CONTEXT ThreadContext;
- PPEB Peb;
- BASE_API_MSG m;
- PBASE_CREATEPROCESS_MSG a = &m.u.CreateProcess;
- PBASE_CHECKVDM_MSG b = &m.u.CheckVDM;
- PWCH TempNull = NULL;
- WCHAR TempChar;
- UNICODE_STRING VdmNameString;
- PVOID BaseAddress;
- ULONG VdmReserve;
- SIZE_T BigVdmReserve;
- ULONG iTask=0;
- LPWSTR CurdirBuffer, CurdirFilePart;
- DWORD CurdirLength,CurdirLength2;
- ULONG VDMCreationState=0;
- ULONG VdmBinaryType = 0;
- BOOL bMeowBinary = FALSE;
- UNICODE_STRING SubSysCommandLine;
- PIMAGE_NT_HEADERS NtHeaders;
- DWORD dwNoWindow = (dwCreationFlags & CREATE_NO_WINDOW);
- ANSI_STRING AnsiStringVDMEnv;
- UNICODE_STRING UnicodeStringVDMEnv;
- WCHAR ImageFileDebuggerCommand[ MAX_PATH ];
- LPWSTR QuotedBuffer;
- BOOLEAN QuoteInsert;
- BOOLEAN QuoteCmdLine = FALSE;
- BOOLEAN QuoteFound;
- BOOL bSaferChecksNeeded = FALSE;
- BOOLEAN SearchRetry;
- BOOLEAN IsWowBinary = FALSE;
- STARTUPINFOW StartupInfo;
- DWORD LastError;
- DWORD fileattr;
- PROCESS_PRIORITY_CLASS PriClass;
- PVOID State;
- HANDLE DebugPortHandle = NULL;
- PVOID pAppCompatDataTemp;
- PVOID pAppCompatData = NULL;
- DWORD cbAppCompatData = 0; // for the future
- BOOLEAN bVdmRetry = FALSE;
- DWORD Flags;
- PVOID pAppCompatSxsData = NULL;
- DWORD cbAppCompatSxsData = 0;
- SXS_OVERRIDE_STREAM AppCompatSxsManifest;
- PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
- SIZE_T SxsConglomeratedBufferSizeBytes;
- PBYTE SxsConglomeratedByteBuffer = NULL; // this contains all the of the below in one large right-sized heap allocation
- // if we compute its size wrong, other code (if it gets it right..) should
- // do more heap allocation
- ULONG sxsi; // for loop counter
- RTL_UNICODE_STRING_BUFFER SxsWin32ManifestPathBuffer;
- RTL_UNICODE_STRING_BUFFER SxsWin32PolicyPathBuffer;
- RTL_UNICODE_STRING_BUFFER SxsWin32AssemblyDirectoryBuffer;
- RTL_UNICODE_STRING_BUFFER SxsNtManifestPathBuffer;
- RTL_UNICODE_STRING_BUFFER SxsNtPolicyPathBuffer;
- const PRTL_UNICODE_STRING_BUFFER SxsStringBuffers[] = {
- // The order here does not matter.
- &SxsWin32ManifestPathBuffer,
- &SxsWin32PolicyPathBuffer,
- &SxsWin32AssemblyDirectoryBuffer,
- &SxsNtManifestPathBuffer,
- &SxsNtPolicyPathBuffer
- };
- UNICODE_STRING SxsWin32ExePath;
- UNICODE_STRING SxsNtExePath;
- BASE_MSG_SXS_HANDLES SxsExeHandles = {0};
- BASE_MSG_SXS_HANDLES SxsManifestFileHandles = {0};
- CONST SXS_CONSTANT_WIN32_NT_PATH_PAIR SxsExePathPair = { &SxsWin32ExePath, &SxsNtExePath };
- CONST SXS_WIN32_NT_PATH_PAIR SxsManifestPathPair = { &SxsWin32ManifestPathBuffer, &SxsNtManifestPathBuffer };
- CONST SXS_WIN32_NT_PATH_PAIR SxsPolicyPathPair = { &SxsWin32PolicyPathBuffer, &SxsNtPolicyPathBuffer };
- BASE_MSG_SXS_HANDLES SxsPolicyHandles = {0};
- PWSTR ExePathFullBuffer = NULL;
- DWORD dwJobMemberLevel = 0;
- HANDLE hSaferAssignmentJob = NULL;
- HANDLE hSaferRestrictedToken = NULL;
- DWORD dwBasePushProcessParametersFlags = 0;
- #if defined(BUILD_WOW6432) || defined(_WIN64)
- BOOLEAN ComPlusILImage;
- LPCWSTR lpOriginalApplicationName = lpApplicationName;
- LPWSTR lpOriginalCommandLine = lpCommandLine;
- #endif
- #if defined(WX86)
- HANDLE Wx86Info = NULL;
- #endif
- #if defined WX86
- BOOLEAN UseKnownWx86Dll;
- UseKnownWx86Dll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
- NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
- #endif
- RtlZeroMemory(&a->Sxs, sizeof(a->Sxs));
- RtlZeroMemory(lpProcessInformation,sizeof(*lpProcessInformation));
- if (ARGUMENT_PRESENT( hRestrictedUserToken )) {
- *hRestrictedUserToken = NULL;
- }
- // Private VDM flag should be ignored; Its meant for internal use only.
- dwCreationFlags &= (ULONG)~CREATE_NO_WINDOW;
- if ((dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) ==
- (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- AnsiStringVDMEnv.Buffer = NULL;
- UnicodeStringVDMEnv.Buffer = NULL;
- //
- // the lowest specified priority class is used.
- //
- if (dwCreationFlags & IDLE_PRIORITY_CLASS ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
- }
- else if (dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
- }
- else if (dwCreationFlags & NORMAL_PRIORITY_CLASS ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
- }
- else if (dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
- }
- else if (dwCreationFlags & HIGH_PRIORITY_CLASS ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
- }
- else if (dwCreationFlags & REALTIME_PRIORITY_CLASS ) {
- if ( BasepIsRealtimeAllowed(FALSE) ) {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
- }
- else {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
- }
- }
- else {
- PriClass.PriorityClass = PROCESS_PRIORITY_CLASS_UNKNOWN;
- }
- PriClass.Foreground = FALSE;
- dwCreationFlags = (dwCreationFlags & ~PRIORITY_CLASS_MASK );
- //
- // Default separate/shared VDM option if not explicitly specified.
- //
- if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM) {
- if (dwCreationFlags & CREATE_SHARED_WOW_VDM) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- }
- else
- if ((dwCreationFlags & CREATE_SHARED_WOW_VDM) == 0) {
- if (BaseStaticServerData->DefaultSeparateVDM) {
- dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
- }
- }
- if ((dwCreationFlags & CREATE_SEPARATE_WOW_VDM) == 0) {
- //
- // If the creator is running inside a job object, always
- // set SEPERATE_WOW_VDM so the VDM is part of the job.
- //
- JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
- Status = NtQueryInformationJobObject(NULL,
- JobObjectBasicUIRestrictions,
- &UiRestrictions,
- sizeof(UiRestrictions),
- NULL);
- if (Status != STATUS_ACCESS_DENIED) {
- //
- // Anything other than STATUS_ACCESS_DENIED indicates the
- // current process is inside a job.
- //
- dwCreationFlags = (dwCreationFlags & (~CREATE_SHARED_WOW_VDM)) |
- CREATE_SEPARATE_WOW_VDM;
- }
- }
- //
- // If ANSI environment, convert to Unicode
- //
- if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
- PUCHAR s;
- STRING Ansi;
- UNICODE_STRING Unicode;
- MEMORY_BASIC_INFORMATION MemoryInformation;
- Ansi.Buffer = s = lpEnvironment;
- while (*s || *(s+1)) // find end of block
- s++;
- Ansi.Length = (USHORT)(s - Ansi.Buffer) + 1;
- Ansi.MaximumLength = Ansi.Length + 1;
- MemoryInformation.RegionSize = Ansi.MaximumLength * sizeof(WCHAR);
- Unicode.Buffer = NULL;
- Status = NtAllocateVirtualMemory( NtCurrentProcess(),
- &Unicode.Buffer,
- 0,
- &MemoryInformation.RegionSize,
- MEM_COMMIT,
- PAGE_READWRITE
- );
- if (!NT_SUCCESS(Status) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- Unicode.MaximumLength = (USHORT)MemoryInformation.RegionSize;
- Status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, FALSE);
- if (!NT_SUCCESS(Status) ) {
- NtFreeVirtualMemory( NtCurrentProcess(),
- &Unicode.Buffer,
- &MemoryInformation.RegionSize,
- MEM_RELEASE
- );
- BaseSetLastNTError(Status);
- return FALSE;
- }
- lpEnvironment = Unicode.Buffer;
- }
- FileHandle = NULL;
- SectionHandle = NULL;
- ProcessHandle = NULL;
- ThreadHandle = NULL;
- FreeBuffer = NULL;
- NameBuffer = NULL;
- VdmNameString.Buffer = NULL;
- BaseAddress = (PVOID)1;
- VdmReserve = 0;
- CurdirBuffer = NULL;
- CurdirFilePart = NULL;
- SubSysCommandLine.Buffer = NULL;
- QuoteFound = FALSE;
- QuoteInsert = FALSE;
- QuotedBuffer = NULL;
- try {
- //
- // Make a copy of the startup info so we can change it.
- //
- StartupInfo = *lpStartupInfo;
- //
- // STARTF_USEHOTKEY means hStdInput is really the hotkey value.
- // STARTF_HASSHELLDATA means std handles are used for shell-private
- // data. This flag is used if an icon is passed to ShellExecuteEx.
- // As a result they cannot be specified with STARTF_USESTDHANDLES.
- // Consistent with Win95, USESTDHANDLES is ignored.
- //
- if (StartupInfo.dwFlags & STARTF_USESTDHANDLES &&
- StartupInfo.dwFlags & (STARTF_USEHOTKEY | STARTF_HASSHELLDATA)) {
- StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES;
- }
- VdmRetry:
- //
- // None of this cleanup/reinit occurs for launching a Win32 or Win64 .exe,
- // but they generally do occur for launching 16bit, .bat, etc.
- //
- if (NameBuffer) {
- RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
- NameBuffer = NULL;
- }
- if (FreeBuffer) {
- RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
- FreeBuffer = NULL;
- }
- if (FileHandle) {
- NtClose(FileHandle);
- FileHandle = NULL;
- }
- LastError = 0;
- SearchRetry = TRUE;
- QuoteInsert = FALSE;
- QuoteCmdLine = FALSE;
- if (!ARGUMENT_PRESENT( lpApplicationName )) {
- //
- // Locate the image
- //
- // forgot to free NameBuffer before goto VdmRetry???
- ASSERT(NameBuffer == NULL);
- NameBuffer = RtlAllocateHeap( RtlProcessHeap(),
- MAKE_TAG( TMP_TAG ),
- MAX_PATH * sizeof( WCHAR ));
- if ( !NameBuffer ) {
- BaseSetLastNTError(STATUS_NO_MEMORY);
- return FALSE;
- }
- lpApplicationName = lpCommandLine;
- TempNull = (PWCH)lpApplicationName;
- WhiteScan = (LPWSTR)lpApplicationName;
- //
- // check for lead quote
- //
- if ( *WhiteScan == L'\"' ) {
- SearchRetry = FALSE;
- WhiteScan++;
- lpApplicationName = WhiteScan;
- while(*WhiteScan) {
- if ( *WhiteScan == (WCHAR)'\"' ) {
- TempNull = (PWCH)WhiteScan;
- QuoteFound = TRUE;
- break;
- }
- WhiteScan++;
- TempNull = (PWCH)WhiteScan;
- }
- }
- else {
- retrywsscan:
- lpApplicationName = lpCommandLine;
- while(*WhiteScan) {
- if ( *WhiteScan == (WCHAR)' ' ||
- *WhiteScan == (WCHAR)'\t' ) {
- TempNull = (PWCH)WhiteScan;
- break;
- }
- WhiteScan++;
- TempNull = (PWCH)WhiteScan;
- }
- }
- TempChar = *TempNull;
- *TempNull = UNICODE_NULL;
- #ifdef WX86
- //
- // Wx86 applications must use x86 version of known exes
- // for compatibility.
- //
- if (UseKnownWx86Dll) {
- LPWSTR KnownName;
- NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
- KnownName = BasepWx86KnownExe(lpApplicationName);
- if (KnownName) {
- lpApplicationName = KnownName;
- }
- }
- #endif
- Length = SearchPathW(
- NULL,
- lpApplicationName,
- L".exe",
- MAX_PATH,
- NameBuffer,
- NULL
- )*2;
- if (Length != 0 && Length < MAX_PATH * sizeof( WCHAR )) {
- //
- // SearchPathW worked, but file might be a directory
- // if this happens, we need to keep trying
- //
- fileattr = GetFileAttributesW(NameBuffer);
- if ( fileattr != 0xffffffff &&
- (fileattr & FILE_ATTRIBUTE_DIRECTORY) ) {
- Length = 0;
- } else {
- Length++;
- Length++;
- }
- }
- if ( !Length || Length >= MAX_PATH<<1 ) {
- //
- // If we search pathed, then return file not found.
- // otherwise, try to be more specific.
- //
- RTL_PATH_TYPE PathType;
- HANDLE hFile;
- PathType = RtlDetermineDosPathNameType_U(lpApplicationName);
- if ( PathType != RtlPathTypeRelative ) {
- //
- // The failed open should set get last error properly.
- //
- hFile = CreateFileW(
- lpApplicationName,
- GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL
- );
- if ( hFile != INVALID_HANDLE_VALUE ) {
- CloseHandle(hFile);
- BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
- }
- }
- else {
- BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND);
- }
- //
- // remember initial last error value for the retry scan path
- //
- if ( LastError ) {
- SetLastError(LastError);
- }
- else {
- LastError = GetLastError();
- }
- //
- // restore the command line
- //
- *TempNull = TempChar;
- lpApplicationName = NameBuffer;
- //
- // If we still have command line left, then keep going
- // the point is to march through the command line looking
- // for whitespace so we can try to find an image name
- // launches of things like:
- // c:\word 95\winword.exe /embedding -automation
- // require this. Our first iteration will stop at c:\word, our next
- // will stop at c:\word 95\winword.exe
- //
- if (*WhiteScan && SearchRetry) {
- WhiteScan++;
- TempNull = WhiteScan;
- QuoteInsert = TRUE;
- QuoteFound = TRUE;
- goto retrywsscan;
- }
- return FALSE;
- }
- //
- // restore the command line
- //
- *TempNull = TempChar;
- lpApplicationName = NameBuffer;
- //
- // check whether it is setup.exe started by winlogon.exe
- //
- if (BasepIsSetupInvokedByWinLogon(lpApplicationName))
- {
- // validate the flag
- if (!(dwCreationFlags & CREATE_IGNORE_SYSTEM_DEFAULT))
- {
- //
- // BUGBUBGUBGUBUGBUGBUGUBGBUGUBGUB
- // Winlogon does not set the flag correctly
- // in phase1, ignore it(now)
- // in phase2, ASSERT it
- // BUGBUBGUBGUBUGBUGBUGUBGBUGUBGUB
- //
- dwCreationFlags |= CREATE_IGNORE_SYSTEM_DEFAULT;
- }
- }
- }
- else
- if (!ARGUMENT_PRESENT( lpCommandLine ) || *lpCommandLine == UNICODE_NULL ) {
- QuoteCmdLine = TRUE;
- lpCommandLine = (LPWSTR)lpApplicationName;
- }
- #ifdef WX86
- //
- // Wx86 applications must use x86 version of known exes
- // for compatibility.
- //
- if (UseKnownWx86Dll) {
- LPWSTR KnownName;
- NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
- KnownName = BasepWx86KnownExe(lpApplicationName);
- if (KnownName) {
- RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
- NameBuffer = KnownName;
- lpApplicationName = KnownName;
- }
- }
- #endif
- //
- // Translate to an NT name.
- //
- TranslationStatus = RtlDosPathNameToNtPathName_U(
- lpApplicationName,
- &PathName,
- NULL,
- &RelativeName
- );
- if ( !TranslationStatus ) {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return FALSE;
- }
- // forgot to free FreeBuffer before goto VdmRetry????
- ASSERT(FreeBuffer == NULL);
- FreeBuffer = PathName.Buffer;
- RtlInitUnicodeString(&SxsWin32ExePath, lpApplicationName);
- {
- RTL_PATH_TYPE SxsWin32ExePathType = RtlDetermineDosPathNameType_U(lpApplicationName);
- if ((SxsWin32ExePathType != RtlPathTypeDriveAbsolute) &&
- (SxsWin32ExePathType != RtlPathTypeUncAbsolute)) {
- if (ExePathFullBuffer == NULL) {
- // It seems that with VDM things, we can rerun this code with a new lpApplication, so
- // we protect against double-allocating the buffer and just allocate a big
- // MAX_PATH one the first time through, assuming it's good enough for the 2ndary times
- // too.
- ExePathFullBuffer = RtlAllocateHeap(RtlProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR));
- if (ExePathFullBuffer == NULL) {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- }
- RtlGetFullPathName_U(lpApplicationName, (MAX_PATH + 1) * sizeof(WCHAR), ExePathFullBuffer, NULL);
- RtlInitUnicodeString(&SxsWin32ExePath, ExePathFullBuffer);
- }
- }
- SxsNtExePath = PathName;
- if ( RelativeName.RelativeName.Length ) {
- PathName = *(PUNICODE_STRING)&RelativeName.RelativeName;
- }
- else {
- RelativeName.ContainingDirectory = NULL;
- }
- InitializeObjectAttributes(
- &Obja,
- &PathName,
- OBJ_CASE_INSENSITIVE,
- RelativeName.ContainingDirectory,
- NULL
- );
- //
- // Open the file for red and execute access
- //
- Status = NtOpenFile(
- &FileHandle,
- SYNCHRONIZE | FILE_EXECUTE | FILE_READ_ATTRIBUTES | FILE_READ_DATA,
- &Obja,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
- );
- if (!NT_SUCCESS(Status) ) {
- //
- // We failed. Open the file for lesser access.
- //
- Status = NtOpenFile(
- &FileHandle,
- SYNCHRONIZE | FILE_EXECUTE,
- &Obja,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
- );
- if (!NT_SUCCESS(Status) ) {
- //
- // if we failed, see if this is a device. If it is a device,
- // then just return invalid image format
- //
- if ( RtlIsDosDeviceName_U(RTL_CONST_CAST(PWSTR)(lpApplicationName)) ) {
- SetLastError(ERROR_BAD_DEVICE);
- }
- else {
- BaseSetLastNTError(Status);
- }
- return FALSE;
- }
- }
- //
- // If no desktop has been specified, use the caller's
- // desktop.
- //
- if (StartupInfo.lpDesktop == NULL) {
- StartupInfo.lpDesktop =
- (LPWSTR)((PRTL_USER_PROCESS_PARAMETERS)NtCurrentPeb()->
- ProcessParameters)->DesktopInfo.Buffer;
- }
- //
- // Create a section object backed by the file
- //
- Status = NtCreateSection(
- &SectionHandle,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_EXECUTE,
- SEC_IMAGE,
- FileHandle
- );
- //
- // App Certification DLL
- //
- if (NT_SUCCESS(Status)) {
- Status = BasepIsProcessAllowed(lpApplicationName);
- if (!NT_SUCCESS(Status)) {
- BaseSetLastNTError(Status);
- NtClose(SectionHandle);
- return FALSE;
- }
- //
- // If Meow subsystem is enabled and caller specified CREATE_FORECEDOS for a win32 image
- // push it into the meow subsystem
- //
- if ((dwCreationFlags & CREATE_FORCEDOS) && BaseStaticServerData->ForceDos) {
- dwCreationFlags &= ~(CREATE_SHARED_WOW_VDM | CREATE_FORCEDOS);
- dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
- Status = STATUS_INVALID_IMAGE_WIN_16;
- bMeowBinary = TRUE;
- NtClose(SectionHandle);
- SectionHandle = NULL;
- }
- }
- //
- // check appcompat (aka apphelp)
- //
- // if we are running under debugger, bVdmRetry will be FALSE
- // yet pAppCompatData may have some data (from the app itself)
- // debugger will do a separate CreateProcess on debugee
- //
- // apphelp gets called if it is win32 app or if it is a .bat or .cmd
- if(!bVdmRetry &&
- (NT_SUCCESS(Status) ||
- (Status == STATUS_INVALID_IMAGE_NOT_MZ && !BaseIsDosApplication(&PathName,Status)))
- ) {
- NTSTATUS BadAppStatus;
- if (NULL != pAppCompatData) {
- RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
- pAppCompatData = NULL;
- }
- if (NULL != pAppCompatSxsData) {
- RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatSxsData);
- pAppCompatSxsData = NULL;
- }
- //
- // we only check ONCE --
- // the second time around is rather meaningless - to check for posix/ntvdm/os2 emulation
- //
- BadAppStatus = BasepCheckBadapp(FileHandle,
- PathName.Buffer,
- (WCHAR*)lpEnvironment,
- &pAppCompatData,
- &cbAppCompatData,
- &pAppCompatSxsData,
- &cbAppCompatSxsData);
- if (!NT_SUCCESS(BadAppStatus)) {
- if (BadAppStatus == STATUS_ACCESS_DENIED) {
- SetLastError(ERROR_CANCELLED);
- }
- else {
- BaseSetLastNTError(BadAppStatus);
- }
- if (SectionHandle) {
- NtClose(SectionHandle);
- SectionHandle = NULL;
- }
- return FALSE;
- }
- }
- //
- // Winsafer code
- //
- // If this is the first time then we will have to do Safer checks.
- // Note that we do not impose any restrictions on the interpreter
- // itself since it is part of OS.
- //
- if ((!bVdmRetry) &&
- ( (dwCreationFlags & CREATE_PRESERVE_CODE_AUTHZ_LEVEL) == 0 )) {
- NTSTATUS SaferStatus;
- {
- //
- // WinSafer process sandbox restrictions handling.
- // Should be done for non .NET images only.
- //
- SaferStatus = BasepCheckWinSaferRestrictions(
- hUserToken,
- lpApplicationName, // same as PathName.Buffer
- FileHandle,
- &dwJobMemberLevel,
- &hSaferRestrictedToken,
- &hSaferAssignmentJob);
- if (SaferStatus == -1) {
- SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
- bStatus = FALSE;
- leave;
- } else if (!NT_SUCCESS(SaferStatus)) {
- BaseSetLastNTError(SaferStatus);
- bStatus = FALSE;
- leave;
- }
- }
- }
- if (!NT_SUCCESS(Status)) {
- switch (Status) {
- // 16 bit OS/2 exe
- case STATUS_INVALID_IMAGE_NE_FORMAT:
- #if defined(i386) && defined(OS2_SUPPORT_ENABLED)
- //
- // Use OS/2 if x86 (OS/2 not supported on risc),
- // and CreationFlags don't have forcedos bit
- // and Registry didn't specify ForceDos
- //
- // else execute as a DOS bound app.
- //
- //
- if (!(dwCreationFlags & CREATE_FORCEDOS) &&
- !BaseStaticServerData->ForceDos)
- {
- if ( !BuildSubSysCommandLine( L"OS2 /P ",
- lpApplicationName,
- lpCommandLine,
- &SubSysCommandLine
- ) ) {
- return FALSE;
- }
- lpCommandLine = SubSysCommandLine.Buffer;
- lpApplicationName = NULL;
- bVdmRetry = TRUE;
- goto VdmRetry;
- }
- #endif
- // Falls into Dos case, so that stub message will be
- // printed, and bound apps will run w/o OS/2 subsytem
- // Dos .exe or .com
- case STATUS_INVALID_IMAGE_PROTECT:
- case STATUS_INVALID_IMAGE_NOT_MZ:
- ForceDos:
- {
- ULONG BinarySubType;
- BinarySubType = BINARY_TYPE_DOS_EXE;
- if (Status == STATUS_INVALID_IMAGE_PROTECT ||
- Status == STATUS_INVALID_IMAGE_NE_FORMAT ||
- (BinarySubType = BaseIsDosApplication(&PathName,Status)) )
- {
- #if defined(_WIN64) || defined(BUILD_WOW6432)
- //
- // If this a DOS application, then we need to pop up a dialog
- // saying that this an invalid win32 application.
- //
- goto RaiseInvalidWin32Error;
- #endif
- VdmBinaryType = BINARY_TYPE_DOS;
- // create the environment before going to the
- // server. This was done becuase we want NTVDM
- // to have the new environment when it gets
- // created.
- if (!BaseCreateVDMEnvironment(
- lpEnvironment,
- &AnsiStringVDMEnv,
- &UnicodeStringVDMEnv
- )) {
- return FALSE;
- }
- if(!BaseCheckVDM(VdmBinaryType | BinarySubType,
- lpApplicationName,
- lpCommandLine,
- lpCurrentDirectory,
- &AnsiStringVDMEnv,
- &m,
- &iTask,
- dwCreationFlags,
- &StartupInfo
- )) {
- return FALSE;
- }
- // Check the return value from the server
- switch (b->VDMState & VDM_STATE_MASK) {
- case VDM_NOT_PRESENT:
- // mark this so the server can undo
- // creation if something goes wrong.
- // We marked it "partially created" because
- // the NTVDM has yet not been fully created.
- // a call to UpdateVdmEntry to update
- // process handle will signal the NTVDM
- // process completed creation
- VDMCreationState = VDM_PARTIALLY_CREATED;
- // fail the call if NTVDM process is being
- // created DETACHED.
- // note that, we let it go if NTVDM process
- // is already running.
- if (dwCreationFlags & DETACHED_PROCESS) {
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- if (!BaseGetVdmConfigInfo(lpCommandLine,
- iTask,
- VdmBinaryType,
- &VdmNameString,
- &VdmReserve)) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- lpCommandLine = VdmNameString.Buffer;
- lpApplicationName = NULL;
- break;
- case VDM_PRESENT_NOT_READY:
- SetLastError (ERROR_NOT_READY);
- return FALSE;
- case VDM_PRESENT_AND_READY:
- VDMCreationState = VDM_BEING_REUSED;
- VdmWaitHandle = b->WaitObjectForParent;
- break;
- }
- VdmReserve--; // we reserve from addr 1
- if(VdmWaitHandle)
- goto VdmExists;
- else{
- bInheritHandles = FALSE;
- if (lpEnvironment &&
- !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)){
- RtlDestroyEnvironment(lpEnvironment);
- }
- lpEnvironment = UnicodeStringVDMEnv.Buffer;
- bVdmRetry = TRUE;
- goto VdmRetry;
- }
- }
- else {
- //
- // must be a .bat or .cmd file
- //
- static PWCHAR CmdPrefix = L"cmd /c ";
- PWCHAR NewCommandLine;
- ULONG Length;
- PWCHAR Last4 = &PathName.Buffer[PathName.Length / sizeof( WCHAR )-4];
- if ( PathName.Length < 8 ) {
- SetLastError(ERROR_BAD_EXE_FORMAT);
- return FALSE;
- }
- if (_wcsnicmp( Last4, L".bat", 4 ) && _wcsnicmp( Last4, L".cmd", 4 )) {
- SetLastError(ERROR_BAD_EXE_FORMAT);
- return FALSE;
- }
- Length = wcslen( CmdPrefix )
- + (QuoteCmdLine || QuoteFound )
- + wcslen( lpCommandLine )
- + (QuoteCmdLine || QuoteFound)
- + 1;
- NewCommandLine = RtlAllocateHeap( RtlProcessHeap( ),
- MAKE_TAG( TMP_TAG ),
- Length * sizeof( WCHAR ) );
- if (NewCommandLine == NULL) {
- BaseSetLastNTError(STATUS_NO_MEMORY);
- return FALSE;
- }
- wcscpy( NewCommandLine, CmdPrefix );
- if (QuoteCmdLine || QuoteFound) {
- wcscat( NewCommandLine, L"\"" );
- }
- wcscat( NewCommandLine, lpCommandLine );
- if (QuoteCmdLine || QuoteFound) {
- wcscat( NewCommandLine, L"\"" );
- }
- RtlInitUnicodeString( &SubSysCommandLine, NewCommandLine );
- lpCommandLine = SubSysCommandLine.Buffer;
- lpApplicationName = NULL;
- bVdmRetry = TRUE;
- goto VdmRetry;
- }
- }
- // 16 bit windows exe
- case STATUS_INVALID_IMAGE_WIN_16:
- #if defined(BUILD_WOW6432) || defined(_WIN64)
- if (lpOriginalApplicationName == NULL) {
- // pass in the part of the command line after the exe name
- // including whitespace
- lpCommandLine = ((*TempNull == '\"') ? TempNull + 1 : TempNull);
- } else {
- lpCommandLine = lpOriginalCommandLine;
- }
- return NtVdm64CreateProcess(lpOriginalApplicationName == NULL,
- lpApplicationName, // this is now the real file name we've loaded
- lpCommandLine,
- lpProcessAttributes,
- lpThreadAttributes,
- bInheritHandles,
- (dwCreationFlags & ~CREATE_UNICODE_ENVIRONMENT), // the environment has already been converted to unicode
- lpEnvironment,
- lpCurrentDirectory,
- lpStartupInfo,
- lpProcessInformation
- );
- #endif
- if (dwCreationFlags & CREATE_FORCEDOS) {
- goto ForceDos;
- }
- IsWowBinary = TRUE;
- if (!BaseCreateVDMEnvironment(lpEnvironment,
- &AnsiStringVDMEnv,
- &UnicodeStringVDMEnv)) {
- return FALSE;
- }
- RetrySepWow:
- VdmBinaryType = dwCreationFlags & CREATE_SEPARATE_WOW_VDM
- ? BINARY_TYPE_SEPWOW : BINARY_TYPE_WIN16;
- if (!BaseCheckVDM(VdmBinaryType,
- lpApplicationName,
- lpCommandLine,
- lpCurrentDirectory,
- &AnsiStringVDMEnv,
- &m,
- &iTask,
- dwCreationFlags,
- &StartupInfo
- ))
- {
- //
- // If we failed with access denied, caller may not
- // be allowed allowed to access the shared wow's
- // desktop, so retry as a separate wow
- //
- if (VdmBinaryType == BINARY_TYPE_WIN16 &&
- GetLastError() == ERROR_ACCESS_DENIED)
- {
- dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
- }
- else {
- return FALSE;
- }
- goto RetrySepWow;
- }
- // Check the return value from the server
- switch (b->VDMState & VDM_STATE_MASK){
- case VDM_NOT_PRESENT:
- // mark this so the server can undo
- // creation if something goes wrong.
- // We marked it "partitially created" because
- // the NTVDM has yet not been fully created.
- // a call to UpdateVdmEntry to update
- // process handle will signal the NTVDM
- // process completed creation
- VDMCreationState = VDM_PARTIALLY_CREATED;
- // jarbats: 1/8/2001
- // Tell BaseGetVdmConfigInfo to create
- // vdm commandline for meow
- //
- if (bMeowBinary)
- {
- VdmReserve = 1;
- }
- if (!BaseGetVdmConfigInfo(
- lpCommandLine,
- iTask,
- VdmBinaryType,
- &VdmNameString,
- &VdmReserve
- )) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- lpCommandLine = VdmNameString.Buffer;
- lpApplicationName = NULL;
- //
- // Wow must have a hidden console
- // Throw away DETACHED_PROCESS flag which isn't
- // meaningful for Win16 apps.
- //
- dwCreationFlags |= CREATE_NO_WINDOW;
- dwCreationFlags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS);
- //
- // We're starting a WOW VDM, turn on feedback unless
- // the creator passed STARTF_FORCEOFFFEEDBACK.
- //
- StartupInfo.dwFlags |= STARTF_FORCEONFEEDBACK;
- break;
- case VDM_PRESENT_NOT_READY:
- SetLastError (ERROR_NOT_READY);
- return FALSE;
- case VDM_PRESENT_AND_READY:
- VDMCreationState = VDM_BEING_REUSED;
- VdmWaitHandle = b->WaitObjectForParent;
- break;
- }
- VdmReserve--; // we reserve from addr 1
- if(VdmWaitHandle)
- goto VdmExists;
- else {
- bInheritHandles = FALSE;
- // replace the environment with ours
- if (lpEnvironment &&
- !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) {
- RtlDestroyEnvironment(lpEnvironment);
- }
- lpEnvironment = UnicodeStringVDMEnv.Buffer;
- bVdmRetry = TRUE;
- goto VdmRetry;
- }
- case STATUS_FILE_IS_OFFLINE:
- SetLastError(ERROR_FILE_OFFLINE);
- break;
- default :
- SetLastError(ERROR_BAD_EXE_FORMAT);
- return FALSE;
- }
- }
- //
- // Make sure only WOW apps can have the CREATE_SEPARATE_WOW_VDM flag.
- //
- if (!IsWowBinary && (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)) {
- dwCreationFlags &= ~CREATE_SEPARATE_WOW_VDM;
- }
- //
- // Query the section to determine the stack parameters and
- // image entrypoint.
- //
- Status = NtQuerySection(
- SectionHandle,
- SectionImageInformation,
- &ImageInformation,
- sizeof( ImageInformation ),
- NULL
- );
- if (!NT_SUCCESS( Status )) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- if (ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL) {
- SetLastError(ERROR_BAD_EXE_FORMAT);
- return FALSE;
- }
- ImageFileDebuggerCommand[ 0 ] = UNICODE_NULL;
- if (!(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) ||
- NtCurrentPeb()->ReadImageFileExecOptions
- ) {
- LdrQueryImageFileExecutionOptions( &PathName,
- L"Debugger",
- REG_SZ,
- ImageFileDebuggerCommand,
- sizeof( ImageFileDebuggerCommand ),
- NULL
- );
- }
- if ((ImageInformation.Machine < USER_SHARED_DATA->ImageNumberLow) ||
- (ImageInformation.Machine > USER_SHARED_DATA->ImageNumberHigh)) {
- #if defined(_WIN64) || defined(BUILD_WOW6432)
- if (ImageInformation.Machine == IMAGE_FILE_MACHINE_I386) {
- // Fall through since this is a valid machine type.
- }
- else
- #endif
- {
- ULONG_PTR ErrorParameters[2];
- ULONG ErrorResponse;
- #if defined(_WIN64) || defined(BUILD_WOW6432)
- RaiseInvalidWin32Error:
- #endif
- ErrorResponse = ResponseOk;
- ErrorParameters[0] = (ULONG_PTR)&PathName;
- NtRaiseHardError( STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
- 1,
- 1,
- ErrorParameters,
- OptionOk,
- &ErrorResponse
- );
- if ( NtCurrentPeb()->ImageSubsystemMajorVersion <= 3 ) {
- SetLastError(ERROR_BAD_EXE_FORMAT);
- }
- else {
- SetLastError(ERROR_EXE_MACHINE_TYPE_MISMATCH);
- }
- return FALSE;
- }
- }
- if ( ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_GUI &&
- ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_CUI ) {
- // POSIX exe
- NtClose(SectionHandle);
- SectionHandle = NULL;
- if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_POSIX_CUI ) {
- if ( !BuildSubSysCommandLine( L"POSIX /P ",
- lpApplicationName,
- lpCommandLine,
- &SubSysCommandLine
- ) ) {
- return FALSE;
- }
- lpCommandLine = SubSysCommandLine.Buffer;
- lpApplicationName = NULL;
- bVdmRetry = TRUE;
- goto VdmRetry;
- }
- else {
- SetLastError(ERROR_CHILD_NOT_COMPLETE);
- return FALSE;
- }
- }
- else {
- if (!BasepIsImageVersionOk( ImageInformation.SubSystemMajorVersion,
- ImageInformation.SubSystemMinorVersion) ) {
- SetLastError(ERROR_BAD_EXE_FORMAT);
- return FALSE;
- }
- }
- if (ImageFileDebuggerCommand[ 0 ] != UNICODE_NULL) {
- SIZE_T n;
- n = wcslen( lpCommandLine );
- if (n == 0) {
- lpCommandLine = (LPWSTR)lpApplicationName;
- n = wcslen( lpCommandLine );
- }
- n += wcslen( ImageFileDebuggerCommand ) + 1 + 2;
- n *= sizeof( WCHAR );
- SubSysCommandLine.Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), n );
- SubSysCommandLine.Length = 0;
- SubSysCommandLine.MaximumLength = (USHORT)n;
- RtlAppendUnicodeToString( &SubSysCommandLine, ImageFileDebuggerCommand );
- RtlAppendUnicodeToString( &SubSysCommandLine, L" " );
- RtlAppendUnicodeToString( &SubSysCommandLine, lpCommandLine );
- #if DBG
- DbgPrint( "BASE: Calling debugger with '%wZ'\n", &SubSysCommandLine );
- #endif
- lpCommandLine = SubSysCommandLine.Buffer;
- lpApplicationName = NULL;
- NtClose(SectionHandle);
- SectionHandle = NULL;
- RtlFreeHeap(RtlProcessHeap(), 0, NameBuffer);
- NameBuffer = NULL;
- RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
- FreeBuffer = NULL;
- goto VdmRetry;
- }
- //
- // Create the process object
- //
- pObja = BaseFormatObjectAttributes(&Obja,lpProcessAttributes,NULL);
- Flags = 0;
- if (dwCreationFlags & CREATE_BREAKAWAY_FROM_JOB ) {
- Flags |= PROCESS_CREATE_FLAGS_BREAKAWAY;
- }
- if ( dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) ) {
- Status = DbgUiConnectToDbg();
- if ( !NT_SUCCESS(Status) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- DebugPortHandle = DbgUiGetThreadDebugObject ();
- if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS) {
- Flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT;
- }
- }
- if (bInheritHandles) {
- Flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES;
- }
- if (((ImageInformation.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS) != 0)) {
- #if defined(_WIN64) || defined(BUILD_WOW6432)
- //
- // Check if this is a 32-bit IL_ONLY COM+ image that needs to run natively
- // on Win64.
- //
- if ( ImageInformation.Machine == IMAGE_FILE_MACHINE_I386 ) {
- Status = BasepIsComplusILImage(
- SectionHandle,
- &ImageInformation,
- &ComPlusILImage
- );
- if ((NT_SUCCESS (Status)) && (ComPlusILImage != FALSE)) {
- Flags |= PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE;
- }
- }
- #endif
- }
- //
- // This is temporary till we get Shim dlls support for native Win64 applications.
- //
- if (ImageInformation.Machine != IMAGE_FILE_MACHINE_I386) {
- pAppCompatDataTemp = NULL;
- } else {
- pAppCompatDataTemp = pAppCompatData;
- }
- Status = NtCreateProcessEx(
- &ProcessHandle,
- PROCESS_ALL_ACCESS,
- pObja,
- NtCurrentProcess(),
- Flags,
- SectionHandle,
- DebugPortHandle,
- NULL,
- dwJobMemberLevel // Job member level
- );
- if ( !NT_SUCCESS(Status) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- //
- // NtCreateProcess will set to normal OR inherit if parent is IDLE or Below
- // only override if a mask is given during the create.
- //
- if ( PriClass.PriorityClass != PROCESS_PRIORITY_CLASS_UNKNOWN ) {
- State = NULL;
- if ( PriClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME ) {
- State = BasepIsRealtimeAllowed(TRUE);
- }
- Status = NtSetInformationProcess(
- ProcessHandle,
- ProcessPriorityClass,
- (PVOID)&PriClass,
- sizeof(PriClass)
- );
- if ( State ) {
- BasepReleasePrivilege( State );
- }
- if ( !NT_SUCCESS(Status) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE) {
- UINT NewMode;
- NewMode = SEM_FAILCRITICALERRORS;
- NtSetInformationProcess(
- ProcessHandle,
- ProcessDefaultHardErrorMode,
- &NewMode,
- sizeof(NewMode)
- );
- }
- //
- // If the process is being created for a VDM call the server with
- // process handle.
- //
- if (VdmBinaryType) {
- VdmWaitHandle = ProcessHandle;
- if (!BaseUpdateVDMEntry(UPDATE_VDM_PROCESS_HANDLE,
- &VdmWaitHandle,
- iTask,
- VdmBinaryType
- ))
- {
- //make sure we don't close the handle twice --
- //(VdmWaitHandle == ProcessHandle) if we don't do this.
- VdmWaitHandle = NULL;
- return FALSE;
- }
- //
- // For Sep wow the VdmWaitHandle = NULL (there is none!)
- //
- VDMCreationState |= VDM_FULLY_CREATED;
- }
- #if defined(i386)
- //
- // Reserve memory in the new process' address space if necessary
- // (for vdms). This is required only for x86 system.
- //
- if ( VdmReserve ) {
- BigVdmReserve = VdmReserve;
- Status = NtAllocateVirtualMemory(
- ProcessHandle,
- &BaseAddress,
- 0L,
- &BigVdmReserve,
- MEM_RESERVE,
- PAGE_EXECUTE_READWRITE
- );
- if ( !NT_SUCCESS(Status) ){
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- #endif
- //
- // Abuse the StaticSize fields temporarily.
- // They are somewhat private, but we are using them for temporary space, sort of.
- // These are the right values for them, but we need to call the proper initialization function,
- // which will store the values a second time (possibly optimized away).
- //
- SxsWin32ManifestPathBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(SXS_MANIFEST_SUFFIX);
- SxsWin32PolicyPathBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(SXS_POLICY_SUFFIX);
- SxsWin32AssemblyDirectoryBuffer.ByteBuffer.StaticSize = SxsWin32ExePath.Length + sizeof(WCHAR); // Win32AssemblyDirectory overestimate
- SxsNtManifestPathBuffer.ByteBuffer.StaticSize = SxsNtExePath.Length + sizeof(SXS_MANIFEST_SUFFIX);
- SxsNtPolicyPathBuffer.ByteBuffer.StaticSize = SxsNtExePath.Length + sizeof(SXS_POLICY_SUFFIX);
- //
- // now add them up as BYTE sizes
- //
- SxsConglomeratedBufferSizeBytes = 0;
- for (sxsi = 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
- SxsConglomeratedBufferSizeBytes += SxsStringBuffers[sxsi]->ByteBuffer.StaticSize;
- }
- #if DBG
- DbgPrintEx(
- DPFLTR_SXS_ID,
- DPFLTR_INFO_LEVEL,
- "SXS: SxsConglomeratedBufferSizeBytes:%Id\n",
- SxsConglomeratedBufferSizeBytes
- );
- #endif
- //
- // one honking heap allocation
- //
- SxsConglomeratedByteBuffer = (PBYTE)RtlAllocateHeap(RtlProcessHeap(), 0, SxsConglomeratedBufferSizeBytes);
- if (SxsConglomeratedByteBuffer == NULL) {
- BaseSetLastNTError(STATUS_NO_MEMORY);
- return FALSE;
- }
- //
- // now dole out pieces, calling the proper initialization function
- //
- for (sxsi= 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
- RtlInitUnicodeStringBuffer(
- SxsStringBuffers[sxsi],
- (sxsi != 0) ? SxsStringBuffers[sxsi - 1]->ByteBuffer.Buffer + SxsStringBuffers[sxsi- 1]->ByteBuffer.StaticSize
- : SxsConglomeratedByteBuffer,
- SxsStringBuffers[sxsi]->ByteBuffer.StaticSize
- );
- }
- SxsExeHandles.Process = ProcessHandle;
- SxsExeHandles.File = FileHandle;
- // The 1 bit here means something different than in the loader.
- ASSERT((((ULONG_PTR)SectionHandle) & (ULONG_PTR)1) == 0);
- SxsExeHandles.Section = SectionHandle;
- // if we have an override stream, use it
- if (NULL != pAppCompatSxsData) {
- AppCompatSxsManifest.Name = SxsWin32ExePath; // unicode string
- AppCompatSxsManifest.Address = pAppCompatSxsData; // pointer to unicode manifest
- AppCompatSxsManifest.Size = cbAppCompatSxsData; // byte count
- }
- Status = BasepSxsCreateProcessCsrMessage(
- (NULL != pAppCompatSxsData) ? &AppCompatSxsManifest : NULL, // override manifest (appcompat hook)
- NULL, // override policy (appcompat hook)
- &SxsManifestPathPair,
- &SxsManifestFileHandles,
- &SxsExePathPair,
- &SxsExeHandles,
- &SxsPolicyPathPair,
- &SxsPolicyHandles,
- &SxsWin32AssemblyDirectoryBuffer,
- &a->Sxs
- );
- #if DBG
- // verify the buffer size calculation
- for (sxsi = 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi)
- {
- if (SxsStringBuffers[sxsi]->ByteBuffer.Buffer != SxsStringBuffers[sxsi]->ByteBuffer.StaticBuffer)
- {
- DbgPrintEx(
- DPFLTR_SXS_ID,
- DPFLTR_WARNING_LEVEL,
- "SXS: SxsStringBuffers[%lu]'s StaticSize was computed too small (%Id, %Id)\n",
- sxsi,
- SxsStringBuffers[sxsi]->ByteBuffer.StaticSize,
- SxsStringBuffers[sxsi]->ByteBuffer.Size
- );
- }
- }
- #endif
- if ( !NT_SUCCESS( Status ) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- //
- // Determine the location of the
- // processes PEB.
- //
- Status = NtQueryInformationProcess(
- ProcessHandle,
- ProcessBasicInformation,
- &ProcessInfo,
- sizeof( ProcessInfo ),
- NULL
- );
- if ( !NT_SUCCESS( Status ) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- Peb = ProcessInfo.PebBaseAddress;
- //
- // Push the parameters into the address space of the new process
- //
- if ( ARGUMENT_PRESENT(lpCurrentDirectory) ) {
- CurdirBuffer = RtlAllocateHeap( RtlProcessHeap(),
- MAKE_TAG( TMP_TAG ),
- (MAX_PATH + 1) * sizeof( WCHAR ) );
- if ( !CurdirBuffer ) {
- BaseSetLastNTError(STATUS_NO_MEMORY);
- return FALSE;
- }
- CurdirLength2 = GetFullPathNameW(
- lpCurrentDirectory,
- MAX_PATH,
- CurdirBuffer,
- &CurdirFilePart
- );
- if ( CurdirLength2 > MAX_PATH ) {
- SetLastError(ERROR_DIRECTORY);
- return FALSE;
- }
- //
- // now make sure the directory exists
- //
- CurdirLength = GetFileAttributesW(CurdirBuffer);
- if ( (CurdirLength == 0xffffffff) ||
- !(CurdirLength & FILE_ATTRIBUTE_DIRECTORY) ) {
- SetLastError(ERROR_DIRECTORY);
- return FALSE;
- }
- }
- if ( QuoteInsert || QuoteCmdLine) {
- QuotedBuffer = RtlAllocateHeap(RtlProcessHeap(),0,wcslen(lpCommandLine)*2+6);
- if ( QuotedBuffer ) {
- wcscpy(QuotedBuffer,L"\"");
- if ( QuoteInsert ) {
- TempChar = *TempNull;
- *TempNull = UNICODE_NULL;
- }
- wcscat(QuotedBuffer,lpCommandLine);
- wcscat(QuotedBuffer,L"\"");
- if ( QuoteInsert ) {
- *TempNull = TempChar;
- wcscat(QuotedBuffer,TempNull);
- }
- }
- else {
- if ( QuoteInsert ) {
- QuoteInsert = FALSE;
- }
- if ( QuoteCmdLine ) {
- QuoteCmdLine = FALSE;
- }
- }
- }
- // If we found a manifest, we want to push that fact to the new process.
- if (a->Sxs.Flags & BASE_MSG_SXS_MANIFEST_PRESENT)
- dwBasePushProcessParametersFlags |= BASE_PUSH_PROCESS_PARAMETERS_FLAG_APP_MANIFEST_PRESENT;
- if (!BasePushProcessParameters(
- dwBasePushProcessParametersFlags,
- ProcessHandle,
- Peb,
- lpApplicationName,
- CurdirBuffer,
- QuoteInsert || QuoteCmdLine ? QuotedBuffer : lpCommandLine,
- lpEnvironment,
- &StartupInfo,
- dwCreationFlags | dwNoWindow,
- bInheritHandles,
- IsWowBinary ? IMAGE_SUBSYSTEM_WINDOWS_GUI : 0,
- pAppCompatDataTemp,
- cbAppCompatData
- ) ) {
- return FALSE;
- }
- RtlFreeUnicodeString(&VdmNameString);
- VdmNameString.Buffer = NULL;
- //
- // Stuff in the standard handles if needed
- //
- if (!VdmBinaryType &&
- !bInheritHandles &&
- !(StartupInfo.dwFlags & STARTF_USESTDHANDLES) &&
- !(dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE | CREATE_NO_WINDOW)) &&
- ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI
- ) {
- PRTL_USER_PROCESS_PARAMETERS ParametersInNewProcess;
- Status = NtReadVirtualMemory( ProcessHandle,
- &Peb->ProcessParameters,
- &ParametersInNewProcess,
- sizeof( ParametersInNewProcess ),
- NULL
- );
- if (NT_SUCCESS( Status )) {
- if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardInput )) {
- StuffStdHandle( ProcessHandle,
- NtCurrentPeb()->ProcessParameters->StandardInput,
- &ParametersInNewProcess->StandardInput
- );
- }
- if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardOutput )) {
- StuffStdHandle( ProcessHandle,
- NtCurrentPeb()->ProcessParameters->StandardOutput,
- &ParametersInNewProcess->StandardOutput
- );
- }
- if (!CONSOLE_HANDLE( NtCurrentPeb()->ProcessParameters->StandardError )) {
- StuffStdHandle( ProcessHandle,
- NtCurrentPeb()->ProcessParameters->StandardError,
- &ParametersInNewProcess->StandardError
- );
- }
- }
- }
- //
- // Create the thread...
- //
- //
- // Allocate a stack for this thread in the address space of the target
- // process.
- //
- StackStatus = BaseCreateStack(
- ProcessHandle,
- ImageInformation.CommittedStackSize,
- (ImageInformation.MaximumStackSize < 256*1024) ? 256*1024 : ImageInformation.MaximumStackSize,
- &InitialTeb
- );
- if ( !NT_SUCCESS(StackStatus) ) {
- BaseSetLastNTError(StackStatus);
- return FALSE;
- }
- //
- // Create an initial context for the new thread.
- //
- BaseInitializeContext(
- &ThreadContext,
- Peb,
- ImageInformation.TransferAddress,
- InitialTeb.StackBase,
- BaseContextTypeProcess
- );
- //
- // Create the actual thread object
- //
- pObja = BaseFormatObjectAttributes(&Obja,lpThreadAttributes,NULL);
- Status = NtCreateThread(
- &ThreadHandle,
- THREAD_ALL_ACCESS,
- pObja,
- ProcessHandle,
- &ClientId,
- &ThreadContext,
- &InitialTeb,
- TRUE
- );
- if (!NT_SUCCESS(Status) ) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- a->Peb = (ULONGLONG) Peb;
- //
- // From here on out, do not modify the address space of the
- // new process. WOW64's implementation of NtCreateThread()
- // reshuffles the new process' address space if the current
- // process is 32-bit and the new process is 64-bit.
- //
- #if DBG
- Peb = NULL;
- #endif
- #if defined(WX86)
- //
- // if this is a Wx86 Process, setup for a Wx86 emulated Thread
- //
- if (Wx86Info) {
- //
- // create a WX86Tib and initialize it's Teb->Vdm.
- //
- Status = BaseCreateWx86Tib(ProcessHandle,
- ThreadHandle,
- (ULONG)((ULONG_PTR)ImageInformation.TransferAddress),
- (ULONG)ImageInformation.CommittedStackSize,
- (ULONG)ImageInformation.MaximumStackSize,
- TRUE
- );
- if (!NT_SUCCESS(Status)) {
- BaseSetLastNTError(Status);
- return( FALSE );
- }
- //
- // Mark Process as WX86
- //
- Status = NtSetInformationProcess (ProcessHandle,
- ProcessWx86Information,
- &Wx86Info,
- sizeof(Wx86Info)
- );
- if (!NT_SUCCESS(Status)) {
- BaseSetLastNTError(Status);
- return( FALSE );
- }
- }
- #endif
- //
- // Call the Windows server to let it know about the
- // process.
- //
- a->ProcessHandle = ProcessHandle;
- a->ThreadHandle = ThreadHandle;
- a->ClientId = ClientId;
- switch (ImageInformation.Machine) {
- case IMAGE_FILE_MACHINE_I386:
- #if defined(_WIN64) || defined(BUILD_WOW6432)
- a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA32_ON_WIN64;
- #else
- a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
- #endif
- break;
- case IMAGE_FILE_MACHINE_IA64:
- a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
- break;
- case IMAGE_FILE_MACHINE_AMD64:
- a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
- break;
- default:
- DbgPrint("kernel32: No mapping for ImageInformation.Machine == %04x\n", ImageInformation.Machine);
- a->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
- break;
- }
- //
- // remove debug flags now its not being done by CSR
- //
- a->CreationFlags = dwCreationFlags & ~ (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS);
- a->DebuggerClientId.UniqueProcess = NULL;
- a->DebuggerClientId.UniqueThread = NULL;
- //
- // Set the 2 bit if a gui app is starting. The window manager needs to
- // know this so it can synchronize the startup of this app
- // (WaitForInputIdle api). This info is passed using the process
- // handle tag bits. The 1 bit asks the window manager to turn on
- // or turn off the application start cursor (hourglass/pointer).
- //
- // When starting a WOW process, lie and tell UserSrv NTVDM.EXE is a GUI
- // process. We also turn on bit 0x8 so that UserSrv can ignore the
- // UserNotifyConsoleApplication call made by the console during startup.
- //
- if ( ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI ||
- IsWowBinary ) {
- a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 2);
- //
- // If the creating process is a GUI app, turn on the app. start cursor
- // by default. This can be overridden by STARTF_FORCEOFFFEEDBACK.
- //
- NtHeaders = RtlImageNtHeader((PVOID)GetModuleHandle(NULL));
- if ( NtHeaders
- && (NtHeaders->OptionalHeader.Subsystem
- == IMAGE_SUBSYSTEM_WINDOWS_GUI ) ) {
- a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
- }
- }
- //
- // If feedback is forced on, turn it on. If forced off, turn it off.
- // Off overrides on.
- //
- if (StartupInfo.dwFlags & STARTF_FORCEONFEEDBACK)
- a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle | 1);
- if (StartupInfo.dwFlags & STARTF_FORCEOFFFEEDBACK)
- a->ProcessHandle = (HANDLE)((ULONG_PTR)a->ProcessHandle & ~1);
- a->VdmBinaryType = VdmBinaryType; // just tell server the truth
- if (VdmBinaryType){
- a->hVDM = iTask ? 0 : NtCurrentPeb()->ProcessParameters->ConsoleHandle;
- a->VdmTask = iTask;
- }
- #if defined(BUILD_WOW6432)
- m.ReturnValue = CsrBasepCreateProcess(a);
- #else
- m.u.CreateProcess = *a;
- if (m.u.CreateProcess.Sxs.Flags != 0)
- {
- const PUNICODE_STRING StringsToCapture[] =
- {
- &m.u.CreateProcess.Sxs.Manifest.Path,
- &m.u.CreateProcess.Sxs.Policy.Path,
- &m.u.CreateProcess.Sxs.AssemblyDirectory
- };
- Status =
- CsrCaptureMessageMultiUnicodeStringsInPlace(
- &CaptureBuffer,
- RTL_NUMBER_OF(StringsToCapture),
- StringsToCapture
- );
- if (!NT_SUCCESS(Status)) {
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- CsrClientCallServer( (PCSR_API_MSG)&m,
- CaptureBuffer,
- CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
- BasepCreateProcess
- ),
- sizeof( *a )
- );
- if ( CaptureBuffer ) {
- CsrFreeCaptureBuffer( CaptureBuffer );
- CaptureBuffer = NULL;
- }
- #endif
- if (!NT_SUCCESS((NTSTATUS)m.ReturnValue)) {
- BaseSetLastNTError((NTSTATUS)m.ReturnValue);
- NtTerminateProcess(ProcessHandle, (NTSTATUS)m.ReturnValue);
- return FALSE;
- }
- //
- // If the WinSafer sandboxing policy indicates that the
- // process needs to be run with a restricted token or placed
- // into a restricted job object, then do those actions now.
- // Do not replace the token if the restricted token was created
- // from a caller supplied token i.e. the CreateProcessAsUser case.
- //
- if ((hSaferRestrictedToken != NULL) && (hUserToken == NULL)) {
- Status = BasepReplaceProcessThreadTokens(
- hSaferRestrictedToken,
- ProcessHandle,
- ThreadHandle);
- if (!NT_SUCCESS(Status)) {
- // kill and cleanup.
- NtTerminateProcess(ProcessHandle, Status);
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- if (hSaferAssignmentJob != NULL) {
- Status = NtAssignProcessToJobObject(
- hSaferAssignmentJob, ProcessHandle);
- if (!NT_SUCCESS(Status)) {
- // kill and cleanup.
- NtTerminateProcess(ProcessHandle, STATUS_ACCESS_DENIED);
- BaseSetLastNTError(Status);
- return FALSE;
- }
- }
- //
- // Make the thread start execution if we are allowed to.
- //
- if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
- NtResumeThread(ThreadHandle,&i);
- }
- VdmExists:
- bStatus = TRUE;
- if (VDMCreationState)
- VDMCreationState |= VDM_CREATION_SUCCESSFUL;
- try {
- if (VdmWaitHandle) {
- //
- // tag Shared WOW VDM handles so that wait for input idle has a
- // chance to work. Shared WOW VDM "process" handles are actually
- // event handles, Separate WOW VDM handles are real process
- // handles. Also mark DOS handles with 0x1 so WaitForInputIdle
- // has a way to distinguish DOS apps and not block forever.
- //
- if (VdmBinaryType == BINARY_TYPE_WIN16) {
- lpProcessInformation->hProcess =
- (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x2);
- //
- // Shared WOW doesn't always start a process, so
- // we don't have a process ID or thread ID to
- // return if the VDM already existed.
- //
- // Separate WOW doesn't hit this codepath
- // (no VdmWaitHandle).
- //
- if (VDMCreationState & VDM_BEING_REUSED) {
- ClientId.UniqueProcess = 0;
- ClientId.UniqueThread = 0;
- }
- }
- else {
- lpProcessInformation->hProcess =
- (HANDLE)((ULONG_PTR)VdmWaitHandle | 0x1);
- }
- //
- // Close the ProcessHandle, since we are returning the
- // VdmProcessHandle instead.
- //
- if (ProcessHandle != NULL)
- NtClose(ProcessHandle);
- }
- else{
- lpProcessInformation->hProcess = ProcessHandle;
- }
- lpProcessInformation->hThread = ThreadHandle;
- lpProcessInformation->dwProcessId = HandleToUlong(ClientId.UniqueProcess);
- lpProcessInformation->dwThreadId = HandleToUlong(ClientId.UniqueThread);
- ProcessHandle = NULL;
- ThreadHandle = NULL;
- }
- __except ( EXCEPTION_EXECUTE_HANDLER ) {
- NtClose( ProcessHandle );
- NtClose( ThreadHandle );
- ProcessHandle = NULL;
- ThreadHandle = NULL;
- if (VDMCreationState)
- VDMCreationState &= ~VDM_CREATION_SUCCESSFUL;
- }
- }
- __finally {
- if (ExePathFullBuffer != NULL) {
- SxsWin32ExePath.Buffer = NULL;
- SxsWin32ExePath.Length = 0;
- SxsWin32ExePath.MaximumLength = 0;
- RtlFreeHeap(RtlProcessHeap(), 0, ExePathFullBuffer);
- ExePathFullBuffer = NULL;
- }
- if (!VdmBinaryType) {
- NTSTATUS Status1;
- BasepSxsCloseHandles(&SxsManifestFileHandles);
- BasepSxsCloseHandles(&SxsPolicyHandles);
- //
- // don't close SxsExeHandles, they are
- // aliases of other variables that are either closed
- // or returned to the caller
- //
- //
- // This loop only really frees any memory if our computation
- // of the overall buffer size was too low, which it is not supposed to be.
- //
- if (SxsConglomeratedByteBuffer != NULL) {
- for (sxsi= 0 ; sxsi != RTL_NUMBER_OF(SxsStringBuffers) ; ++sxsi) {
- RtlFreeUnicodeStringBuffer(SxsStringBuffers[sxsi]);
- }
- RtlFreeHeap(RtlProcessHeap(), 0,SxsConglomeratedByteBuffer);
- }
- }
- if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
- RtlDestroyEnvironment(lpEnvironment);
- lpEnvironment = NULL;
- }
- RtlFreeHeap(RtlProcessHeap(), 0,QuotedBuffer);
- RtlFreeHeap(RtlProcessHeap(), 0,NameBuffer);
- RtlFreeHeap(RtlProcessHeap(), 0,CurdirBuffer);
- RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
- if ( FileHandle ) {
- NtClose(FileHandle);
- }
- if ( SectionHandle ) {
- NtClose(SectionHandle);
- }
- if ( ThreadHandle ) {
- NtTerminateProcess(ProcessHandle,STATUS_SUCCESS);
- NtClose(ThreadHandle);
- }
- if ( ProcessHandle ) {
- NtClose(ProcessHandle);
- }
- if ( hSaferAssignmentJob ) {
- NtClose(hSaferAssignmentJob);
- }
- if ( hSaferRestrictedToken ) {
- if (hUserToken == NULL) {
- // CreateProcess case
- NtClose(hSaferRestrictedToken);
- }
- else{
- // CreateProcessAsUser case
- *hRestrictedUserToken = hSaferRestrictedToken;
- }
- }
- if (NULL != pAppCompatData) {
- RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
- }
- if (NULL != pAppCompatSxsData) {
- RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatSxsData);
- }
- RtlFreeUnicodeString(&VdmNameString);
- RtlFreeUnicodeString(&SubSysCommandLine);
- if (AnsiStringVDMEnv.Buffer || UnicodeStringVDMEnv.Buffer)
- BaseDestroyVDMEnvironment(&AnsiStringVDMEnv, &UnicodeStringVDMEnv);
- if (VDMCreationState && !(VDMCreationState & VDM_CREATION_SUCCESSFUL)){
- BaseUpdateVDMEntry (
- UPDATE_VDM_UNDO_CREATION,
- (HANDLE *)&iTask,
- VDMCreationState,
- VdmBinaryType
- );
- if(VdmWaitHandle) {
- NtClose(VdmWaitHandle);
- }
- }
- }
- if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ) {
- RtlDestroyEnvironment(lpEnvironment);
- }
- return bStatus;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement