예제 #1
0
        private static int ExecRequireNonAdmin(IWin32Window parent, string exePath, string args, out IntPtr hProcess)
        {
            int    nError      = NativeConstants.ERROR_SUCCESS;
            string commandLine = "\"" + exePath + "\"" + (args == null ? "" : (" " + args));

            string dir;

            try
            {
                dir = Path.GetDirectoryName(exePath);
            }

            catch (Exception)
            {
                dir = null;
            }

            IntPtr hWndShell          = IntPtr.Zero;
            IntPtr hShellProcess      = IntPtr.Zero;
            IntPtr hShellProcessToken = IntPtr.Zero;
            IntPtr hTokenCopy         = IntPtr.Zero;
            IntPtr bstrExePath        = IntPtr.Zero;
            IntPtr bstrCommandLine    = IntPtr.Zero;
            IntPtr bstrDir            = IntPtr.Zero;

            NativeStructs.PROCESS_INFORMATION procInfo = new NativeStructs.PROCESS_INFORMATION();

            try
            {
                hWndShell = SafeNativeMethods.FindWindowW("Progman", null);
                if (hWndShell == IntPtr.Zero)
                {
                    NativeMethods.ThrowOnWin32Error("FindWindowW() returned NULL");
                }

                uint dwPID;
                uint dwThreadId = SafeNativeMethods.GetWindowThreadProcessId(hWndShell, out dwPID);
                if (0 == dwPID)
                {
                    NativeMethods.ThrowOnWin32Error("GetWindowThreadProcessId returned 0", NativeErrors.ERROR_FILE_NOT_FOUND);
                }

                hShellProcess = NativeMethods.OpenProcess(NativeConstants.PROCESS_QUERY_INFORMATION, false, dwPID);
                if (IntPtr.Zero == hShellProcess)
                {
                    NativeMethods.ThrowOnWin32Error("OpenProcess() returned NULL");
                }

                bool optResult = NativeMethods.OpenProcessToken(
                    hShellProcess,
                    NativeConstants.TOKEN_ASSIGN_PRIMARY | NativeConstants.TOKEN_DUPLICATE | NativeConstants.TOKEN_QUERY,
                    out hShellProcessToken);

                if (!optResult)
                {
                    NativeMethods.ThrowOnWin32Error("OpenProcessToken() returned FALSE");
                }

                bool dteResult = NativeMethods.DuplicateTokenEx(
                    hShellProcessToken,
                    NativeConstants.MAXIMUM_ALLOWED,
                    IntPtr.Zero,
                    NativeConstants.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                    NativeConstants.TOKEN_TYPE.TokenPrimary,
                    out hTokenCopy);

                if (!dteResult)
                {
                    NativeMethods.ThrowOnWin32Error("DuplicateTokenEx() returned FALSE");
                }

                bstrExePath     = Marshal.StringToBSTR(exePath);
                bstrCommandLine = Marshal.StringToBSTR(commandLine);
                bstrDir         = Marshal.StringToBSTR(dir);

                bool cpwtResult = NativeMethods.CreateProcessWithTokenW(
                    hTokenCopy,
                    0,
                    bstrExePath,
                    bstrCommandLine,
                    0,
                    IntPtr.Zero,
                    bstrDir,
                    IntPtr.Zero,
                    out procInfo);

                if (cpwtResult)
                {
                    hProcess          = procInfo.hProcess;
                    procInfo.hProcess = IntPtr.Zero;
                    nError            = NativeConstants.ERROR_SUCCESS;
                }
                else
                {
                    hProcess = IntPtr.Zero;
                    nError   = Marshal.GetLastWin32Error();
                }
            }

            catch (Win32Exception ex)
            {
                Tracing.Ping(ex.ToString());
                nError   = ex.ErrorCode;
                hProcess = IntPtr.Zero;
            }

            finally
            {
                if (bstrExePath != IntPtr.Zero)
                {
                    Marshal.FreeBSTR(bstrExePath);
                    bstrExePath = IntPtr.Zero;
                }

                if (bstrCommandLine != IntPtr.Zero)
                {
                    Marshal.FreeBSTR(bstrCommandLine);
                    bstrCommandLine = IntPtr.Zero;
                }

                if (bstrDir != IntPtr.Zero)
                {
                    Marshal.FreeBSTR(bstrDir);
                    bstrDir = IntPtr.Zero;
                }

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

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

                if (hTokenCopy != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(hTokenCopy);
                    hTokenCopy = IntPtr.Zero;
                }

                if (procInfo.hThread != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(procInfo.hThread);
                    procInfo.hThread = IntPtr.Zero;
                }

                if (procInfo.hProcess != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(procInfo.hProcess);
                    procInfo.hProcess = IntPtr.Zero;
                }
            }

            return(nError);
        }