Example #1
0
        // This code mimics the MSDN defined way to adjust privilege for shutdown
        // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/shutting_down.asp
        private bool GrantShutdownPrivilege()
        {
            bool   grantSuccess  = false;
            IntPtr processToken  = IntPtr.Zero;
            IntPtr processHandle = IntPtr.Zero;

            WindowsApi.TOKEN_PRIVILEGES tokenPrivileges = new WindowsApi.TOKEN_PRIVILEGES();
            long luid      = 0;
            int  returnLen = 0;

            try
            {
                processHandle = WindowsApi.GetCurrentProcess();

                bool result = WindowsApi.OpenProcessToken(processHandle, WindowsApi.TOKEN_ADJUST_PRIVILEGES | WindowsApi.TOKEN_QUERY, ref processToken);

                if (!result)
                {
                    return(grantSuccess);
                }

                WindowsApi.LookupPrivilegeValue(null, WindowsApi.SE_SHUTDOWN_NAME, ref luid);

                tokenPrivileges.PrivilegeCount        = 1;
                tokenPrivileges.Privileges.Luid       = luid;
                tokenPrivileges.Privileges.Attributes = WindowsApi.SE_PRIVILEGE_ENABLED;

                result = WindowsApi.AdjustTokenPrivileges(processToken, false, ref tokenPrivileges, 0, IntPtr.Zero, ref returnLen);

                if (WindowsApi.GetLastError() != 0)
                {
                    throw new Exception("Failed to grant shutdown privilege");
                }

                grantSuccess = true;
            }
            catch (Exception ex)
            {
                LogInstallMessage(EventLogEntryType.Error, m_logMessagePrefix + ex.Message);
            }
            finally
            {
                if (processToken != IntPtr.Zero)
                {
                    WindowsApi.CloseHandle(processToken);
                }
            }

            return(grantSuccess);
        }
Example #2
0
        public static Process CreateProcessAsStandardUser(string fileName, string arguments = "")
        {
            // The following implementation is roughly based on Aaron Margosis' post:
            // http://blogs.msdn.com/aaron_margosis/archive/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app.aspx

            IntPtr hProcessToken      = IntPtr.Zero;
            IntPtr hShellProcess      = IntPtr.Zero;
            IntPtr hShellProcessToken = IntPtr.Zero;
            IntPtr hPrimaryToken      = IntPtr.Zero;

            try
            {
                if (!WindowsApi.OpenProcessToken(WindowsApi.GetCurrentProcess(), WindowsApi.TOKEN_ADJUST_PRIVILEGES, ref hProcessToken))
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                // Enable SeIncreaseQuotaPrivilege in this process.  (This requires administrative privileges.)
                WindowsApi.TOKEN_PRIVILEGES tkp = new WindowsApi.TOKEN_PRIVILEGES();
                long luid      = 0;
                int  returnLen = 0;

                WindowsApi.LookupPrivilegeValue(null, WindowsApi.SE_INCREASE_QUOTA_NAME, ref luid);

                tkp.PrivilegeCount        = 1;
                tkp.Privileges.Luid       = luid;
                tkp.Privileges.Attributes = WindowsApi.SE_PRIVILEGE_ENABLED;

                WindowsApi.AdjustTokenPrivileges(hProcessToken, false, ref tkp, 0, IntPtr.Zero, ref returnLen);
                int dwLastErr = WindowsApi.GetLastError();

                if (dwLastErr != 0)
                {
                    throw new Win32Exception(dwLastErr);
                }

                // Get window handle representing the desktop shell.  This might not work if there is no shell window, or when
                // using a custom shell.  Also note that we're assuming that the shell is not running elevated.
                IntPtr hShellWnd = WindowsApi.GetShellWindow();

                if (hShellWnd == IntPtr.Zero)
                {
                    throw new InvalidOperationException("Unable to locate shell window. System might be using a custom shell.");
                }

                // Get the ID of the desktop shell process.
                uint dwShellPID;

                WindowsApi.GetWindowThreadProcessId(hShellWnd, out dwShellPID);

                if (dwShellPID == 0)
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                // Open the desktop shell process in order to get the process token.
                hShellProcess = WindowsApi.OpenProcess(WindowsApi.ProcessAccessTypes.PROCESS_QUERY_INFORMATION, false, dwShellPID);

                if (hShellProcess == IntPtr.Zero)
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                // Get the process token of the desktop shell.
                if (!WindowsApi.OpenProcessToken(hShellProcess, WindowsApi.TOKEN_DUPLICATE, ref hShellProcessToken))
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                // Duplicate the shell's process token to get a primary token.
                const uint dwTokenRights = WindowsApi.TOKEN_QUERY | WindowsApi.TOKEN_ASSIGN_PRIMARY | WindowsApi.TOKEN_DUPLICATE | WindowsApi.TOKEN_ADJUST_DEFAULT | WindowsApi.TOKEN_ADJUST_SESSIONID;

                if (!WindowsApi.DuplicateTokenEx(hShellProcessToken, dwTokenRights, IntPtr.Zero, WindowsApi.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, WindowsApi.TOKEN_TYPE.TokenPrimary, out hPrimaryToken))
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                // Start the target process with the new token.
                WindowsApi.PROCESS_INFORMATION pi;
                WindowsApi.STARTUPINFO         si = new WindowsApi.STARTUPINFO();

                si.cb = Marshal.SizeOf(si);

                if (!WindowsApi.CreateProcessWithTokenW(hPrimaryToken, 0, null, fileName + " " + arguments, 0, IntPtr.Zero, null, ref si, out pi))
                {
                    throw new Win32Exception(WindowsApi.GetLastError());
                }

                WindowsApi.CloseHandle(pi.hProcess);
                WindowsApi.CloseHandle(pi.hThread);

                return(Process.GetProcessById(pi.ProcessId));
            }
            finally
            {
                if (hProcessToken != IntPtr.Zero)
                {
                    WindowsApi.CloseHandle(hProcessToken);
                }

                if (hShellProcessToken != IntPtr.Zero)
                {
                    WindowsApi.CloseHandle(hShellProcessToken);
                }

                if (hPrimaryToken != IntPtr.Zero)
                {
                    WindowsApi.CloseHandle(hPrimaryToken);
                }

                if (hShellProcess != IntPtr.Zero)
                {
                    WindowsApi.CloseHandle(hShellProcess);
                }
            }
        }