title: A process created with CreateProcessAsUserW from a 64 bit process exits immediately with exception code 0xc06d007e on Windows 7 64 bit
body: <p>I have a  C# Application, which is launched from a C++ DLL using CreateProcessAsUserW api. The process is launched successfully, but terminates immediately. It works properly on Windows 10 [both as 32 bit and 64 bit] and 32 bit on Windows 7. I found the following link, </p>
  
  <p><a href="https://stackoverflow.com/questions/15581142/why-is-this-process-crashing-as-soon-as-it-is-launched">Why is this process crashing as soon as it is launched?</a></p>
  
  <p>however, process monitor from SysInternals finds no missing dll. [I can attach the saved logs from ProcMon] I also tried passing the path to the application folder, as suggested elsewhere, in the lpCurrentDirectory parameter of the API, but that did not work either. </p>
  
  <p>I followed the guidance in <a href="https://stackoverflow.com/questions/14315013/how-to-get-the-active-user-when-multiple-users-are-logged-on-in-windows">How to get the active user when multiple users are logged on in Windows?</a> to write the code which launches the process,
  and the method which launches the process is called from a windows service.To emulate that from the command line, I used the following
  <a href="https://stackoverflow.com/questions/77528/how-do-you-run-cmd-exe-under-the-local-system-account">How do you run CMD.exe under the Local System Account?</a> [psexec64 -i -s cmd.exe, and then launched the process from cmd.exe]
  The method is as follows
  //<a href="https://stackoverflow.com/questions/14315013/how-to-get-the-active-user-when-multiple-users-are-logged-on-in-windows">How to get the active user when multiple users are logged on in Windows?</a></p>
  
  <pre><code> STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
      {
  
          //char *lpszPath = _com_util::ConvertBSTRToString(processName);
          wchar_t* path = (wchar_t*)processName;//CharToWideChar(lpszPath);
  
          DWORD session_id = -1;
          DWORD session_count = 0;
  
          WTS_SESSION_INFOA *pSession = NULL;
  
  
          if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &amp;pSession, &amp;session_count))
          {
              //log success
          }
          else
          {
              //log error
              return S_OK;
          }
          logger-&gt;Log(L"Session Count", session_count);
          logger-&gt;Log(L"Begin Enumerating Sesions");
          for (int i = 0; i &lt; session_count; i++)
          {
              session_id = pSession[i].SessionId;
              logger-&gt;Log(L"SessionId", session_id);
  
              WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
              WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
  
              DWORD bytes_returned = 0;
              if (::WTSQuerySessionInformation(
                  WTS_CURRENT_SERVER_HANDLE,
                  session_id,
                  WTSConnectState,
                  reinterpret_cast&lt;LPTSTR*&gt;(&amp;ptr_wts_connect_state),
                  &amp;bytes_returned))
              {
                  wts_connect_state = *ptr_wts_connect_state;
                  ::WTSFreeMemory(ptr_wts_connect_state);
                  if (wts_connect_state != WTSActive) continue;
              }
              else
              {
                  //log error
                  continue;
              }
              logger-&gt;Log(L"End Enumerating Sesions");
              logger-&gt;Log(L"Selected Session Id", session_id);
              HANDLE hImpersonationToken;
  
              if (!WTSQueryUserToken(session_id, &amp;hImpersonationToken))
              {
                  //log error
                  logger-&gt;Log(L"Exception in WTSQueryUserToken", GetLastError());
                  continue;
              }
  
  
              //Get real token from impersonation token
              DWORD neededSize1 = 0;
              HANDLE *realToken = new HANDLE;
              if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &amp;neededSize1))
              {
                  CloseHandle(hImpersonationToken);
                  hImpersonationToken = *realToken;
              }
              else
              {
                  //log error
                  logger-&gt;Log(L"Exception in GetTokenInformation", GetLastError());
                  continue;
              }
  
  
              HANDLE hUserToken;
  
              if (!DuplicateTokenEx(hImpersonationToken,
                  //0,
                  //MAXIMUM_ALLOWED,
                  TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
                  NULL,
                  SecurityImpersonation,
                  TokenPrimary,
                  &amp;hUserToken))
              {
                  //log error
                  logger-&gt;Log(L"Exception in DuplicateTokenEx", GetLastError());
                  continue;
              }
  
              // Get user name of this process
              //LPTSTR pUserName = NULL;
              WCHAR* pUserName;
              DWORD user_name_len = 0;
  
              if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &amp;pUserName, &amp;user_name_len))
              {
                  //log username contained in pUserName WCHAR string
                  // char * lpszUserName = WideCharToChar(pUserName);
                  logger-&gt;Log(pUserName);
                  //LocalFree(lpszUserName);
              }
              else
              {
                  logger-&gt;Log(L"Exception in WTSQuerySessionInformation", GetLastError());
              }
  
              //Free memory                         
              if (pUserName) WTSFreeMemory(pUserName);
  
              ImpersonateLoggedOnUser(hUserToken);
  
              STARTUPINFOW StartupInfo;
  
              StartupInfo.cb = sizeof(STARTUPINFOW);
  
  
  
  
              //GetStartupInfoW(&amp;StartupInfo);
              ZeroMemory(&amp;StartupInfo, sizeof(StartupInfo));
              //Uncommented  by Sagar 20th January 20118 1612
              StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
  
              //to Hide Console Process 03-10-2018
              StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
              StartupInfo.wShowWindow = SW_SHOW;//SW_HIDE;
  
  
  
              PROCESS_INFORMATION processInfo;
  
  
  
              SECURITY_ATTRIBUTES Security1;
              ZeroMemory(&amp;Security1, sizeof(Security1));
  
              Security1.nLength = sizeof SECURITY_ATTRIBUTES;
  
  
              SECURITY_ATTRIBUTES Security2;
              ZeroMemory(&amp;Security2, sizeof(Security2));
              Security2.nLength = sizeof SECURITY_ATTRIBUTES;
  
              void* lpEnvironment = NULL;
  
              // Get all necessary environment variables of logged in user
              // to pass them to the new process
              BOOL resultEnv = CreateEnvironmentBlock(&amp;lpEnvironment, hUserToken, FALSE);
  
              if (!resultEnv)
              {
                  //log error
                  DWORD err = GetLastError();
                  logger-&gt;Log(L"Exception in CreateEnvironmentBlock", err);
  
                  continue;
              }
  
              WCHAR PP[1024]; //path and parameters
              ZeroMemory(PP, 1024 * sizeof WCHAR);
              wcscpy_s(PP, path);
              wcscat_s(PP, L" ");
              //wcscat(PP, args);
  
              // Start the process on behalf of the current user 
              BOOL result = CreateProcessAsUserW(hUserToken,
                  PP,
                  NULL,
                  &amp;Security1,
                  &amp;Security2,
                  FALSE,
                  NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE/*| CREATE_NO_WINDOW*/,//CREATE_NO_WINDOW to Hide Console Process 03-10-2018
                  /*lpEnvironment*/NULL,
  
                  //"C:\\ProgramData\\some_dir",
                  NULL,
                  /*NULL,*/
                  &amp;StartupInfo,
                  &amp;processInfo);
  
              if (!result)
              {
                  //log error
                  //char * lpszPath = WideCharToChar(PP);
                  logger-&gt;Log(L"Failed to create process", PP);
                  //LocalFree(lpszPath);
                  DWORD err = GetLastError();
                  logger-&gt;Log(L"GetLastError returned", err);
  
              }
              else
              {
                  *dwProcessId = processInfo.dwProcessId;
                  logger-&gt;Log(L"Created Process", *dwProcessId);
                  //log success
              }
  
              DestroyEnvironmentBlock(lpEnvironment);
  
              CloseHandle(hImpersonationToken);
              CloseHandle(hUserToken);
              CloseHandle(realToken);
  
              RevertToSelf();
          }
  
          WTSFreeMemory(pSession);
  
  
          return S_OK;
      }
  </code></pre>
  
  <p>Procmon screen shots attached below
  Please help.
  Thanks,
  Sagar</p>
  
  <pre><code>[![Pg 1](https://i.stack.imgur.com/CJCrG.png)
  [![Pg 2](https://i.stack.imgur.com/uo8Uw.png)
  [![Pg 3](https://i.stack.imgur.com/G7g12.png)
  [![Pg 4](https://i.stack.imgur.com/6e5w4.png)
  [![Pg 5](https://i.stack.imgur.com/8k2b0.png)
  </code></pre>
  
  <p>I tried the following permutations</p>
  
  <pre><code>Target Process : ATL DLL : Launcher:Result
   64 bit      64 bit     64 bit      Crashes
   64 bit      32 bit     64 bit      Crashes
   32 bit      32 bit     64 bit      Crashes
   32 bit      64 bit     64 bit      Crashes
   32 bit      32 bit     32 bit      OK
   64 bit      32 bit     32 bit      OK
   64 bit      64 bit     32 bit      OK
   32 bit      64 bit     32 bit      OK
  </code></pre>
  
  <p>So it seems that if the launcher process is 64 bit, it always crashes and if it is 32 bit, it always succeeds. What is the difference between a 64 and 32 bit launcher process?</p>