CreateProcessAsUser() fails with error 193 on Windows Server 2008. RRS feed

  • Question

  • I'm seeing failure of CreateProcessAsUser() with error 193 on windows server 2008. Let me explain what exactly I'm doing.


    I've a service (running as LocalSystem) which invokes a command line C++ program (say util.exe). This C++ program util.exe spawn another process to run a windows program. The util.exe calls CreateProcess() to spawn windows program and calls  LogonUser();CreateProcessAsUser() when domain user credentials are provided. The program, utils.exe, works fine on Windows 2003 (with or without user credentials) and also on Windows 2008 when no user credentials are provided. But, on 2008, with user credentials, CreateProcessAsUser() fails and GetLastError() returns 193.


    I read several articles and tried code from MSDN article- "Starting an Interactive Client Process in C++" (http://msdn.microsoft.com/en-us/library/aa379608(VS.85).aspx) but it is not working, same error 193. This article says that "the process must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges for successful execution of CreateProcessAsUser".


    But as per article "LocalSystem Account" (http://msdn.microsoft.com/en-us/library/ms684190.aspx), SE_ASSIGNPRIMARYTOKEN_NAME is disabled.

    However MSDN article describing CreateProcessAsUser (http://msdn.microsoft.com/en-us/library/ms682429.aspx) stats that LogonUser() can be used to get token and that the SE_ASSIGNPRIMARYTOKEN_NAME privilege is not required.


    In the program (util.exe) when I call LogonUser() and GetTokenInformation(..,TokenSessionID,..) it returns Session ID = 0; Is that expected? The "Starting an Interactive Client Process in C++" article describes how one can assign winsta0 and interactive desktop but would that work from session 0 (session of services on vista).


    All these confuses me and wondering what is the best way to use  CreateProcessAsUser() from service on Vista.

    Wednesday, May 6, 2009 5:51 PM

All replies

  • The best way is to use createprocesswithlogonw() rather than attempting to do it manually.
    Wednesday, May 6, 2009 5:56 PM
  • error code 193 decimal is ERROR_BAD_EXE_FORMAT.  I see this error code when trying to launch something that isn't an executable, or is linked for a greater OS version, is corrupt in some other way.  It could be coming up for other reasons, of course, but are you sure that what you're trying to launch is an executable program?
    Wednesday, May 6, 2009 7:05 PM
  • Andy,

    I read somewhere that createprocesswithlogonw() doesn't work from service on vista. May be due to the fact that services' session is 0. I tried that but didn't work. I need to reproduce it see what error it was failing with.

    MSDN article on CreateProcessWithLogonW  says:
    Windows XP with SP2 and Windows Server 2003:  You cannot call CreateProcessWithLogonW from a process that is running under the LocalSystem account, because the function uses the logon SID in the caller token, and the token for the LocalSystem account does not contain this SID. As an alternative, use the CreateProcessAsUser and LogonUser functions.


    It is a command line windows exe program I'm trying to invoke. The program does work with CreateProcess() when called from serivice.

    One question I've is if I'm invoking non-GUI exe, do I need to worry about windows station and desktop. Why can't I execute in session 0.
    Wednesday, May 6, 2009 11:17 PM
  • Spawn util.exe in logon user session using CreateProcessAsUser(). Give administrative privilages to util.exe using the administrative token.
    In Vista admin user has normal token and high privileged token. So get the linked admin token using TokenLinkedToken and use that for CreateProcessAsUser()

    GetTokenInformation(hToken,TokenLinkedToken,&linkedToken,dwSize, &dwSize)

    Thursday, May 7, 2009 4:42 AM
  • Is RD9595 trying to launch something elevated in a user session? That's not the picture I got.
    Thursday, May 7, 2009 6:46 PM
  • I've been able to investigate the issue further and wondering this new details would help.

    I've omitted some of the details of my program thinking that it is not the cause of the problem. But let me explain my program in full details.

    Actually my services, is a 32-bit application (mysvc.exe) and I'm testing on 64-bit Win2k8 server which is a member of domain. The service spawns a 32-bit application (I called it util.exe). The utils.exe in turn calls CreateProcess() is not user cred. are provided or calls CreateProcessAsUser() if domain\Administrator user ID and Password are provided. The util.exe calls CreateProcess()/CreateProcessAsUser() to spawn a process to execute a 64-bit windows program (e.g. ipconfig.exe). So util.exe does following things.

    1. Call Wow64DisableWow64FsRedirection()
    2. if (user cred NOT provided)
           CreateProcess(..,cmdline,..);   // e.g. ipconfig.exe
        else {
          CreateProcessAsUser(htoken, ..., cmdline, ..)
    3. Wait for For Process to complete
    4. Wow64RevertWow64FsRedirection (OldValue);
    5. return;

    This program is working fine on Win2k3 64-bit server. On Win2k8 64-bit, CreateProcess() works fine but CreateProcessAsUser() fails with 193.

    When I removed line #1 and #4, CreateProcessAsUser() didn't fail but I end up calling 32-bit version of windows program which is not what I want.

    Any idea what is happening here?

    Thursday, May 7, 2009 7:49 PM
  • From Wow64DisableWow64FsRedirection:



    To restore file system redirection, call the Wow64RevertWow64FsRedirection function.

    To compile an application that uses this function, define the _WIN32_WINNT macro as 0x0501 or later. For more information, see Using the Windows Headers.

    Disabling file system redirection affects only operations made by the current thread. Some functions, such as CreateProcessAsUser, do work on another thread which is not affected by the state of file system redirection in the calling thread.

    My theory is that what happens is:
    You call CreateProcessAsUser.  It locates the file you want to run on this non-wow64 fs-redirected thread.
    A new thread is created somewhere in CreateProcessAsUser to do some other work, and this thread is not affected by the WOW redirection.
    Somewhere, there's a problem, the two threads don't agree over something, and ERROR_BAD_EXE_FORMAT gets returned as a result.

    That's my guess, anyway.

    Friday, May 8, 2009 12:17 AM
  • What you said makes sense but only Microsoft can confirm it. What I'm wondering is what has changed in Vista because the code is working fine on Windows 2003.
    Friday, May 8, 2009 4:14 PM
  • I'm not so sure about that.  What path are you passing to CreateProcess, inside util.exe?

    You can make some headway for confirm this theory by grabbing a copy of process monitor from MSDN and watching at filesystem accesses during the failed call.  My guess is you will see both syswow64 and system32 are being inspected.

    Friday, May 8, 2009 6:06 PM
  • One option you might explore is having a 64-bit exe be the one that calls CreateProcessAsUser.

    Friday, May 8, 2009 10:42 PM
  • David,

    That is what I endup doing it. I removed the calls for WOW redirection and compiled my util.exe for 64-bit. That resolved the issue.

    Regarding your earlier comment, I pass the same command line, which is just the exe name, for CreateProcess() and CreateProcessAsUser(). The original code, with wow calls and 32-bit, inovkes 64-bit windows program when CreateProcess() is called.

    Looks like something is different in 2008 that breaks the code. May be UAC.
    Wednesday, May 13, 2009 4:28 PM