0

I am trying to start a process with CreateProcessAsUser and works fine BUT in case a command line arguments is present the function fails and the last error is set to ERROR_UNKNOWN_REVISION.

I have tried multiple combinations for command line with no luck.

Here is the code

    var CMD_ARGS = Environment.GetCommandLineArgs();

        string FILE_NAME = EntryPoint.PRCOESS_FILE_NAME;
        string WORKING_DIRECTORY = EntryPoint.PROCESS_DIRECTORY;
        string ARGUMENTS = CMD_ARGS.Skip(1).Aggregate((first,next)=> ' ' + first + ' ' + next);

        IntPtr USER_TOKEN = IntPtr.Zero;
        IntPtr ENVIRONMENT=IntPtr.Zero;

        try
        {
            var consoleSession = Kernel32.WTSGetActiveConsoleSessionId();
            if (consoleSession == 0xFFFFFFFF)
                return;

            if (!Wtsapi32.WTSQueryUserToken(consoleSession, out USER_TOKEN))
                throw new Win32Exception();

            if (!Userenv.CreateEnvironmentBlock(out ENVIRONMENT, USER_TOKEN, true))
                throw new Win32Exception();                   

            //initialize structures
            SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
            sa.nLength = Marshal.SizeOf(sa);

            //initialize startup
            STARTUPINFO si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);

            //initialize process info
            var PROCESS_INFO = new PROCESS_INFORMATION();

            int dwCreationFlags = NORMAL_PRIORITY_CLASS | (int)(PROCESS_CREATE_FLAG.CREATE_NEW_CONSOLE | PROCESS_CREATE_FLAG.CREATE_UNICODE_ENVIRONMENT);

            if (!AdvApi32.CreateProcessAsUser(USER_TOKEN,
                FILE_NAME,
                ARGUMENTS,
                ref sa,
                ref sa,
                true,
                dwCreationFlags,
                ENVIRONMENT,
                WORKING_DIRECTORY,
                ref si,
                out PROCESS_INFO))
                throw new Win32Exception();

            if (PROCESS_INFO.hThread != IntPtr.Zero)
            {
                ClientProcessId = PROCESS_INFO.dwProcessId;
                ClientSessionId = consoleSession;
                Trace.WriteLine($"{PROCESS_INFO.dwProcessId}");
            }
        }
        catch(Exception ex)
        {
            throw;
        }
        finally
        {
            Userenv.DestroyEnvironmentBlock(ENVIRONMENT);
            Kernel32.CloseHandle(USER_TOKEN);
        }
NullReference
  • 862
  • 1
  • 11
  • 27
  • Out of curiosity, why are you doing this with p/invoke instead of using the `Process` class with the `runas` verb? – Ron Beyer Apr 19 '18 at 14:51
  • Yes, i am starting a process from a service. – NullReference Apr 19 '18 at 14:56
  • for what you use `sa` ? pass 0 here (instead `ref sa`) – RbMm Apr 19 '18 at 15:00
  • i have set the sa to null , still same behavior :( – NullReference Apr 19 '18 at 15:04
  • if you use *lpApplicationName* the *lpCommandLine* not play any role at all. not parsed. it can be any valid string or 0. and you never got error here. `ERROR_UNKNOWN_REVISION` related to invalid security descriptor revision faster of all. it in `sa` and i dont know, are it init to 0 in your code (not understand *c#*) – RbMm Apr 19 '18 at 15:07
  • https://stackoverflow.com/a/20984942/17034 – Hans Passant Apr 19 '18 at 15:19
  • @RbMm Indeed changing function signature and passing Intptr.Zero instead of null helped to get rid of the error. Thanks! Still i cant manage to start a process with command line. What i pass is lpApplicationName to be equal to full path to application and lpCommandLine to my command line parameters. Msdn : If both lpApplicationName and lpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. Do i need to take any extra care with the command line args? – NullReference Apr 19 '18 at 15:37
  • if `lpApplicationName` not 0, `lpCommandLine` can be any valid string or 0 - it not interpreted by system in this case. – RbMm Apr 19 '18 at 16:50
  • 1
    @RbMm: That's incorrect. Both parameters are used, and the system passes the command line to the target application, even if *lpApplicationName* is used. The command line is passed as-is. The convention to pass the application name as the first command line argument needs to be established by the calling application (if the target application requires this). If you do need to pass command line arguments, however, you usually do not pass a value through *lpApplicationName* (although you can). – IInspectable Apr 19 '18 at 17:57
  • @IInspectable - look like you not understand me - i say that if *lpApplicationName* is used - the *lpCommandLine* **not interpreted (or parsed)** by system. so it can be any valid string (even read only in this case) or 0 pointer – RbMm Apr 19 '18 at 18:00
  • 1
    @RbMm: That is true, although it doesn't much help the OP. If they need to pass command line arguments, it's easier to not pass a value for *lpApplicationName* at all. – IInspectable Apr 19 '18 at 18:12
  • @IInspectable - i say that command line arguments can not give `ERROR_UNKNOWN_REVISION` error. the reason of error, how i view, in uninitialized `sa` (which can be 0 ) – RbMm Apr 19 '18 at 18:17
  • I managed to resolve the problem by passing lpCommandLine as StringBuilder instead of the string. Thanks for your help! – NullReference Apr 20 '18 at 09:48

0 Answers0