Пример #1
0
    void _Schedule()
    {
        var s = _FormatCL(3); if (s == null)
        {
            return;
        }
        var    user   = Environment.UserName;
        string folder = @"Au\" + user /*App.Model.WorkspaceName*/,
               name   = App.Model.CurrentFile.DisplayName;

        try {
            if (!WinTaskScheduler.TaskExists(folder, name))
            {
                WinTaskScheduler.CreateTaskWithoutTriggers(folder, name,
                                                           uacInfo.isAdmin ? UacIL.High : UacIL.Medium,
                                                           process.thisExePath, s, author: user);
            }
            WinTaskScheduler.EditTask(folder, name);
        }
        catch (UnauthorizedAccessException) when(!uacInfo.isAdmin)
        {
            dialog.showError("Failed", "Restart this program as administrator.", owner: this);
        }
        catch (Exception e1) { dialog.showError("Failed", e1.ToStringWithoutStack(), owner: this); }

        //never mind: non-admin process can't create folders and tasks.
        //	But somehow can do it in the QM2 tasks folder.
        //	Now I don't know how to set folder security permissions.
    }
Пример #2
0
 static bool _RestartAsAdmin(string[] args)
 {
     if (Debugger.IsAttached)
     {
         return(false);                            //very fast
     }
     try {
         //int pid =
         WinTaskScheduler.RunTask("Au",
                                  AFolders.ThisAppBS.Eqi(@"Q:\app\Au\_\") ? "_Au.Editor" : "Au.Editor", //run Q:\app\Au\_\Au.CL.exe or <installed path>\Au.CL.exe
                                  true, args);
         //Api.AllowSetForegroundWindow(pid); //fails and has no sense, because it's Au.CL.exe running as SYSTEM
     }
     catch (Exception ex) {        //probably this program is not installed (no scheduled task)
         AOutput.QM2.Write(ex);
         return(false);
     }
     return(true);
 }
Пример #3
0
        /// <summary>
        /// Starts UAC Medium integrity level (IL) process from this admin process.
        /// </summary>
        /// <param name="need">Which field to set in <b>Result</b>.</param>
        /// <exception cref="AuException">Failed.</exception>
        /// <remarks>
        /// Actually the process will have the same IL and user session as the shell process (normally explorer).
        /// Fails if there is no shell process (API GetShellWindow fails) for more than 2 s from calling this func.
        /// Asserts and fails if this is not admin/system process. Caller should at first call <see cref="uacInfo.isAdmin"/> or <see cref="uacInfo.IntegrityLevel"/>.
        /// </remarks>
        internal Result StartUserIL(Result.Need need = 0)
        {
            if (s_userToken == null)
            {
                Debug.Assert(uacInfo.isAdmin);                 //else cannot set privilege
                if (!SecurityUtil.SetPrivilege("SeIncreaseQuotaPrivilege", true))
                {
                    goto ge;
                }

                //perf.first();
#if false //works, but slow, eg 60 ms, even if we don't create task everytime
                var s = $"\"{folders.ThisAppBS}{(osVersion.is32BitProcess ? "32" : "64")}\\AuCpp.dll\",Cpp_RunDll";
                WinTaskScheduler.CreateTaskToRunProgramOnDemand("Au", "rundll32", false, folders.System + "rundll32.exe", s);
                //WinTaskScheduler.CreateTaskToRunProgramOnDemand("Au", "rundll32", false, folders.System + "notepad.exe"); //slow too
                //perf.next();
                int pid = WinTaskScheduler.RunTask("Au", "rundll32");
                //perf.next();
                //print.it(pid);
                var hUserProcess = Handle_.OpenProcess(pid);
                //print.it((IntPtr)hUserProcess);
                if (hUserProcess.Is0)
                {
                    goto ge;
                }
#else
                bool retry = false;
g1:
                var w = Api.GetShellWindow();
                if (w.Is0)                   //if Explorer process killed or crashed, wait until it restarts
                {
                    if (!wait.forCondition(2, () => !Api.GetShellWindow().Is0))
                    {
                        throw new AuException($"*start process '{_exe}' as user. There is no shell process.");
                    }
                    500.ms();
                    w = Api.GetShellWindow();
                }

                var hUserProcess = Handle_.OpenProcess(w);
                if (hUserProcess.Is0)
                {
                    if (retry)
                    {
                        goto ge;
                    }
                    retry = true; 500.ms(); goto g1;
                }

                //two other ways:
                //1. Enum processes and find one that has Medium IL. Unreliable, eg its token may be modified.
                //2. Start a service process. Let it start a Medium IL process like in QM2. Because LocalSystem can get token with WTSQueryUserToken.
                //tested: does not work with GetTokenInformation(TokenLinkedToken). Even if would work, in non-admin session it is wrong token.
#endif
                //perf.nw();

                using (hUserProcess) {
                    if (Api.OpenProcessToken(hUserProcess, Api.TOKEN_DUPLICATE, out Handle_ hShellToken))
                    {
                        using (hShellToken) {
                            const uint access = Api.TOKEN_QUERY | Api.TOKEN_ASSIGN_PRIMARY | Api.TOKEN_DUPLICATE | Api.TOKEN_ADJUST_DEFAULT | Api.TOKEN_ADJUST_SESSIONID;
                            if (Api.DuplicateTokenEx(hShellToken, access, null, Api.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, Api.TOKEN_TYPE.TokenPrimary, out var userToken))
                            {
                                s_userToken = new SafeAccessTokenHandle(userToken);
                            }
                        }
                    }
                }
                if (s_userToken == null)
                {
                    goto ge;
                }
            }

            bool suspended = need == Result.Need.NetProcess && !_NetProcessObject.IsFast, resetSuspendedFlag = false;
            if (suspended && 0 == (flags & Api.CREATE_SUSPENDED))
            {
                flags |= Api.CREATE_SUSPENDED; resetSuspendedFlag = true;
            }
            bool ok = Api.CreateProcessWithTokenW(s_userToken.DangerousGetHandle(), 0, null, cl, flags, envVar, curDir, si, out var pi);
            if (resetSuspendedFlag)
            {
                flags &= ~Api.CREATE_SUSPENDED;
            }
            if (!ok)
            {
                goto ge;
            }
            return(new Result(pi, need, suspended));

            ge : throw new AuException(0, $"*start process '{_exe}' as user");
        }