예제 #1
0
파일: CustomActions.cs 프로젝트: avs009/gsf
        // 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 static bool GrantShutdownPrivilege(Session session)
        {
            bool grantSuccess = false;
            IntPtr processToken = IntPtr.Zero;
            IntPtr processHandle;
            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 false;

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

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

                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(session, EventLogEntryType.Error, "GrantShutdownPrivilege: " + ex.Message);
            }
            finally
            {
                if (processToken != IntPtr.Zero)
                    WindowsApi.CloseHandle(processToken);
            }

            return grantSuccess;
        }
예제 #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);
            }
        }