Calling CreateProcessAsUser() from service

According to some MS documents (e.g. http://www.microsoft.com/whdc/system/vista/services.mspx), it should be possible to use CreateProcessAsUser() API in a Vista service to create a process in user session. I am trying to achive this, but the function returns error code 1307 (ERROR_INVALID_OWNER) = "This security ID may not be assigned as the owner of this object."

Does it work for somebody Many thanks in advance.


Answer this question

Calling CreateProcessAsUser() from service

  • bitbonk

    [Ganeshm wrote]

    Mine was the same senerio, calling CreateProcessAsUser from service.

    I followed the steps given by you, and it really worked for me thanks

    HANDLE hTokenNew = NULL, hTokenDup = NULL;
    HMODULE hmod = LoadLibrary("kernel32.dll");

    ...

    Hi !

    Could you tell me what sort of libraries did you included to make this piece of code working When I pasted it in VS a lot of errors occured...

    For sure there were libraries:      WtsApi32.h, windows.h and variables  declarations     STARTUPINFO si;            PROCESS_INFORMATION pi;,

    but others I cannot guess...

    Creating process , using this function is very important for me, so I'd be grateful for an answer... :)





  • Kitty Butler

    The TS session in which the process is started will be based on the session id of the token passed to CreateProcessAsUser. If the token is for an interactive logged on user, it should already have the correct session id.

    The windowstation/desktop can be specified in the STARTUPINFO structure. "Winsta0\Default" is the default user's desktop.



  • Gordonn

    Is CreateEnvironmentBlock() necessary

  • Dennis Mulder - dennismulder.net

    The call was in windbg, I used DebugBreak() to get into step by step. (Somehow I couldn't use OutputDebugStringA() to display using DbgView.exe).
    When I use Remote Desktop to debug, the session id is 3, however WTSQueryUserToken() failed with the same error 1008.

  • Dmitry Pavlov

    Did you use start windbg.exe in session 0 and make the service interactive
    Dbgview has to run in the same session as the process being traced...
    Windbg doesn't have this restriction by the way. You can debug/attach accross session boundary and use it as dbgview.

    MSDN with regards to WTSQueryUserToken:

    ERROR_NO_TOKEN
    1008
    The token query is for a session in which no user is logged-on. This occurs, for example, when the session is in the idle state.

    Was a user logged on in session 3 at the time of the call



  • Raoul_BennetH

    Somehow on Vista, when I call WTSGetActiveConsoleSessionId(), I got session 0 and pass this session id to WTSQueryUserToken() and I got error 1008 (An attempt was made to reference a token that does not exist). The above calls were from a localsystem and the login user was current on. Why I got the error message
  • prasindo

    There's a small mistake in this code:

    WTSQueryUserToken(dwSessionId, &hToken);
    DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);

    The output of the WTSQueryUserToken (i.e. hToken) should become the first parameter to DuplicateTokenEx but it's not in this case.
    Note that the token duplication is not really necessary because WTSQueryUserToken yields a primary token already.



  • Sai A

    123 is ERROR_INVALID_NAME ("The filename, directory name, or volume label syntax is incorrect"). Check the command line / exe path you are passing it. Also, keep in mind that Local System does not have privileges to access network paths, and does not have the mapped drives that a user might have.
  • Mark See

    Mine was the same senerio, calling CreateProcessAsUser from service.

    I followed the steps given by you, and it really worked for me thanks

    HANDLE hTokenNew = NULL, hTokenDup = NULL;
    HMODULE hmod = LoadLibrary("kernel32.dll");
    WTSGETACTIVECONSOLESESSIONID lpfnWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress(hmod,"WTSGetActiveConsoleSessionId");
    DWORD dwSessionId = lpfnWTSGetActiveConsoleSessionId();
    WTSQueryUserToken(dwSessionId, &hToken);
    DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);
    //
    WriteToLog("Calling lpfnCreateEnvironmentBlock");
    ZeroMemory( &si, sizeof( STARTUPINFO ) );
    si.cb = sizeof( STARTUPINFO );
    si.lpDesktop = "winsta0\\default";


    LPVOID pEnv = NULL;
    DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    HMODULE hModule = LoadLibrary("Userenv.dll");
    if(hModule )
    {
    LPFN_CreateEnvironmentBlock lpfnCreateEnvironmentBlock = (LPFN_CreateEnvironmentBlock)GetProcAddress( hModule, "CreateEnvironmentBlock" );
    if( lpfnCreateEnvironmentBlock != NULL )
    {
    if(lpfnCreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
    {
    WriteToLog("CreateEnvironmentBlock Ok");
    dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
    }
    else
    {
    pEnv = NULL;
    }
    }
    }
    //
    ZeroMemory( &pi,sizeof(pi));

    if ( !CreateProcessAsUser(
    hTokenDup,
    NULL,
    ( char * )pszCmd,
    NULL,
    NULL,
    FALSE,
    dwCreationFlag,
    pEnv,
    NULL,
    &si,
    &pi
    ) )
    {

    goto RESTORE;
    }



  • Joo Park

    The same code works for us on Vista as on XP, etc. The service is running as the Local System.

    1. use WTSGetActiveConsoleSessionId to get the ID of the current active Windows session at the console (i.e. the machine keyboard and display, as opposed to WTS sessions).

    2. use WTSQueryUserToken to get the token for that session.

    3. use DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary, &hTokenDup) to duplicate that token.

    4. use CreateEnvironmentBlock to create an environment that you will be passing to the process.

    5. use CreateProcessAsUser with the duplicated token and the created environment. Actually, we use CreateProcessAsUserW, since the A version had some sort of bug on some older systems.

    6. Don't forget to CloseHandle on the various tokens, etc, and to DestroyEnvironmentBlock the environment.


  • S_A_S

    WTSQueryUserToken with 0 as the session id will always fail on Vista, because no user ever logs on in that session anymore.
    WTSGetActiveConsoleSessionId() returning 0 may happen under some rare circumstances.
    Is there anything special about the moment when you call that API



  • kiran1234

    I am doing basically the same thing, but I get "CreateProcessAsUser failed with 123"

    I have tried everything I cn think of with no luck



  • fya

    Any way I am able to launch process (using CreateProcessAsUser) but it is getting launch in another desktop

    i.e., is Session0, this is the place where my service is running. I am not able to launch in Session1 (users desktop).

    I am trying to get some help from

    http://weblogs.asp.net/kennykerr/archive/2006/09/29/Windows-Vista-for-Developers-_1320_-Part-4-_1320_-User-Account-Control.aspx

    may this help you. If you could, let me know.

    Thanks



  • Jeffrey Brown

    Only if you want the process to have an environment.
  • Calling CreateProcessAsUser() from service