locked
Elevated application trying to spawn non-elevated application RRS feed

  • Question

  • This has been asked a number of times and there's alot of information on the subject -- unfortunately, the information does not include the error that I'm reaching.

    Situation:
    User Application running in Manifest Required Elevated mode would like to spawn another application at standard user mode privlidges.

    I have the code completed and working (at least I assume so) but I run into a problem:
    "Error 1300: Not all privileges or groups referenced are assigned to the caller"

     

            LookupPrivilegeValueW(null, SE_INCREASE_QUOTA_NAME, out tkp.Privileges[0].Luid);
            tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            AdjustTokenPrivileges(hProcessToken, false, ref tkp, 0, new IntPtr(0), new IntPtr(0));
            int dwLastErr = Marshal.GetLastWin32Error();
            CloseHandle(hProcessToken);
            if (ERROR_SUCCESS != dwLastErr)
    
    AdjustTokenPriv is firing that error.

    The user is an administrator on a windows 7 machine. the user is elevating the process by accepting the UAC dialog when presented. The application is signed but is in program files directory. Is the ability to AdjustTokenPrivileges not part of the power an Administrator has?

    If not, how do I go about getting this work-around to work -- without the boot loader idea. The reason why I ask this is because the boot loader is planed development and I would like to get a temporary fix out first.

     

    Thanks

    BlD

     

     

    Thursday, October 28, 2010 7:10 PM

All replies

  • In the event that processing continues, the application *is not* elevated. It seems that only

    AdjustTokenPrivileges

    Requires some extra account priv that are not normally part of the administrative group.

     

    Thursday, October 28, 2010 7:42 PM
  • This is not the right way to do things.  There are a number of really complex questions here that probably aren't documented, like what sort of magic you need to do on the process to make it look like a normal UAC process, what you need to do to ensure the child process can't be used for ill against the parent... or, more importantly, what user the 'de-elevated' process needs to run as.  For example, if I am a standard user, and I run your application (doing an 'over-the-shoulder' elevation to my admin account), what user is the 'de-elevated' process going to be running as?

    You could pester explorer, and determine who it is running as... which will work fine until you remember that not everyone uses explorer for their desktop shell.  It may also be the case that the user really was trying to run your application as another user, and your attempt to de-elevate may directly contradict the user's intent.

    The right way to 'de-elevate' is not to do so at all.  What you probably really want to do is have an 'asInvoker' 'launcher' process go ahead and launch your main requireAdministrator application. When you need to spawn an unprivileged worker, talk to the launcher process over a pipe or what-have-you and tell it to launch the 'unprivileged' process.

    This isn't some hack solution; if you debug a few installers updated in the past few years you'll see most are doing something of this sort to do their 'Launch Now!' thing at the end of installation.

    • Proposed as answer by David T. Hunt Thursday, October 28, 2010 8:26 PM
    • Unproposed as answer by BlndLeadingDef Thursday, October 28, 2010 8:30 PM
    Thursday, October 28, 2010 8:26 PM
  • David,

    I appreciate that you took the time to write me a reply, I also appreciate that you took the time to read this post I really do. Please don't take this the obvious wrong way but the solution you provided is not an answer to the question. Unfortunately I can't say the whole story, I can't even say more than what I have said, but currently the question boils down to:

    Why does AdjustTokenPrivileges throw an error 1300: Not all privileges or groups referenced are assigned to the caller, when executed on an admin account, through an elevated process, which is signed and specifically requiring requestAdministrator in the manifest.

    Please do not take my post as an arrogant shut down. I understand completely this is a hack, I further understand there's another way to do it. I *also* have read in numerous posts why launchers are almost necessary but right now, the answer I see is not how to best do it, or how to create a work-around, or why it's bad, but -- it's to find out why an account that should be god-like, isn't.

    Thanks for reading, and I appreciate the support and time you are offering me,
    BlD

    Thursday, October 28, 2010 8:35 PM
  • The example doesn't show you checking the return values from these functions, but I will trust that you are not using GetLastError() to check to see if the function is returning success/failure.

    Are you passing the right flags to OpenProcessToken?

    Friday, October 29, 2010 2:36 AM
  • My apologies, I had grabbed the whole block and I thought that it was posted alltogether.

     

        LookupPrivilegeValueW(null
    
    , SE_INCREASE_QUOTA_NAME, out
    
     tkp.Privileges[0].Luid);
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hProcessToken, false
    
    , ref
    
     tkp, 0, new
    
     IntPtr(0), new
    
     IntPtr(0));
        int
    
     dwLastErr = Marshal.GetLastWin32Error();
        CloseHandle(hProcessToken);
        if
    
     (ERROR_SUCCESS != dwLastErr)
        {
         if
    
     (dwLastErr != 1300)
          throw
    
     new
    
     Win32Exception(dwLastErr);
        }
    

     

    Please ignore the blatant dodging of error 1300. Each reference to an extern sets GetLastError, therefore I can assume that any error that may have been thrown by LookupPrivilegeValueW would be overwritten by AdjustTokenPrivilidge.

    Edit:
    I would like to say through-out the debugging, I did not receive any errors thrown by LookupPrivilegeValueW.

    Friday, October 29, 2010 1:37 PM
  • I'll restate directly: are you checking the return value on AdjustTokenPrivileges?

    Secondly, what flags are you passing to OpenProcessToken?

    Friday, October 29, 2010 3:21 PM
  • To answer your first question: Yes.

    As demonstrated by the previous forum-butchered code example:

            int dwLastErr = Marshal.GetLastWin32Error();
            CloseHandle(hProcessToken);
            if (ERROR_SUCCESS != dwLastErr)
            {
              if (dwLastErr != 1300)
                throw new Win32Exception(dwLastErr);
            }
    

     

     

    To answer your second question: I'm sending in the TOKEN_ADJUST_PRIVILEGES flag.

    if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES, out hProcessToken))
          {
            throw new Win32Exception(Marshal.GetLastWin32Error());
          }
    

     

     

     

     

    Friday, October 29, 2010 3:41 PM
  • The call you have above for AdjustTokenPrivileges doesn't have you checking the return value, it has you using GetLastError() to determine if the API succeeded or failed (which is not the correct way to do things.)
    To wit, not every API sets ERROR_SUCCESS when it works, so you could potentially be seeing that result from an API that AdjustTokenPrivileges is calling, or it could be left over from an even earlier call.
    Friday, October 29, 2010 4:47 PM
  • That is an excellent point. I did not check the return value. The current return values are:
    Call to LookupPrivilegeValueW = true;
    Call to AdjustTokenPrivileges = true;

    dwLastErr still equates to 1300; But that value is only set to 1300 after AdjustTokenPrivileges is called. 

    Even though AdjustTokenPrivileges returned true, it still sets an error, is this an acceptable case?
    What, if anything, does that mean?

     

    Friday, October 29, 2010 6:31 PM