コード例 #1
0
        /// <summary>
        /// Creates a file stream with the given filename that is deleted when either the
        /// stream is closed, or the application is terminated.
        /// </summary>
        /// <remarks>
        /// If the file already exists, it is overwritten without any error (CREATE_ALWAYS).
        /// </remarks>
        /// <param name="fileName">The full path to the file to create.</param>
        /// <returns>A Stream with read and write access.</returns>
        public static FileStream CreateTempFile(string fileName)
        {
            IntPtr hFile = SafeNativeMethods.CreateFileW(
                fileName,
                NativeConstants.GENERIC_READ | NativeConstants.GENERIC_WRITE,
                NativeConstants.FILE_SHARE_READ,
                IntPtr.Zero,
                NativeConstants.CREATE_ALWAYS,
                NativeConstants.FILE_ATTRIBUTE_TEMPORARY |
                NativeConstants.FILE_FLAG_DELETE_ON_CLOSE |
                NativeConstants.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
                IntPtr.Zero);

            if (hFile == NativeConstants.INVALID_HANDLE_VALUE)
            {
                NativeMethods.ThrowOnWin32Error("CreateFileW returned INVALID_HANDLE_VALUE");
            }

            SafeFileHandle sfhFile = new SafeFileHandle(hFile, true);
            FileStream     stream;

            try
            {
                stream = new FileStream(sfhFile, FileAccess.ReadWrite);
            }

            catch (Exception)
            {
                SafeNativeMethods.CloseHandle(hFile);
                hFile = IntPtr.Zero;
                throw;
            }

            return(stream);
        }
コード例 #2
0
        /// <summary>
        /// Opens the requested directory in the shell's file/folder browser.
        /// </summary>
        /// <param name="parent">The window that is currently in the foreground.</param>
        /// <param name="folderPath">The folder to open.</param>
        /// <remarks>
        /// This UI is presented modelessly, in another process, and in the foreground.
        /// Error handling and messaging (error dialogs) will be handled by the shell,
        /// and these errors will not be communicated to the caller of this method.
        /// </remarks>
        public static void BrowseFolder(IWin32Window parent, string folderPath)
        {
            NativeStructs.SHELLEXECUTEINFO sei = new NativeStructs.SHELLEXECUTEINFO();

            sei.cbSize = (uint)Marshal.SizeOf(typeof(NativeStructs.SHELLEXECUTEINFO));
            sei.fMask  = NativeConstants.SEE_MASK_NO_CONSOLE;
            sei.lpVerb = "open";
            sei.lpFile = folderPath;
            sei.nShow  = NativeConstants.SW_SHOWNORMAL;
            sei.hwnd   = parent.Handle;

            bool bResult = NativeMethods.ShellExecuteExW(ref sei);

            if (bResult)
            {
                if (sei.hProcess != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(sei.hProcess);
                    sei.hProcess = IntPtr.Zero;
                }
            }
            else
            {
                NativeMethods.ThrowOnWin32Error("ShellExecuteW returned FALSE");
            }

            GC.KeepAlive(parent);
        }
コード例 #3
0
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                UnregisterWindow();
            }

            if (this.hFileMapping != IntPtr.Zero)
            {
                SafeNativeMethods.CloseHandle(this.hFileMapping);
                this.hFileMapping = IntPtr.Zero;
            }
        }
コード例 #4
0
        private static bool EnableCompression(string filePath)
        {
            IntPtr hFile = IntPtr.Zero;

            try
            {
                hFile = SafeNativeMethods.CreateFileW(
                    filePath,
                    NativeConstants.GENERIC_READ | NativeConstants.GENERIC_WRITE,
                    NativeConstants.FILE_SHARE_READ | NativeConstants.FILE_SHARE_WRITE | NativeConstants.FILE_SHARE_DELETE,
                    IntPtr.Zero,
                    NativeConstants.OPEN_EXISTING,
                    NativeConstants.FILE_FLAG_BACKUP_SEMANTICS,
                    IntPtr.Zero);

                if (hFile == NativeConstants.INVALID_HANDLE_VALUE)
                {
                    int dwError = Marshal.GetLastWin32Error();
                    return(false);
                }

                ushort cType   = NativeConstants.COMPRESSION_FORMAT_DEFAULT;
                uint   dwBytes = 0;
                bool   bResult;

                unsafe
                {
                    bResult = NativeMethods.DeviceIoControl(
                        hFile,
                        NativeConstants.FSCTL_SET_COMPRESSION,
                        new IntPtr(&cType),
                        sizeof(ushort),
                        IntPtr.Zero,
                        0,
                        ref dwBytes,
                        IntPtr.Zero);
                }

                return(bResult);
            }

            finally
            {
                if (hFile != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(hFile);
                    hFile = IntPtr.Zero;
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Opens a file for streaming. This stream should be read from or written
        /// to sequentially for best performance. Random I/O is still permissible,
        /// but may not perform as well.
        /// This file is created in such a way that is it NOT indexed by the system's
        /// file indexer (e.g., Windows Desktop Search).
        /// </summary>
        /// <param name="fileName">The file to open.</param>
        /// <returns>A Stream object that may be used to read from or write to the file, depending on the fileMode parameter.</returns>
        public static FileStream OpenStreamingFile(string fileName, FileAccess fileAccess)
        {
            uint dwDesiredAccess;
            uint dwCreationDisposition;

            switch (fileAccess)
            {
            case FileAccess.Read:
                dwDesiredAccess       = NativeConstants.GENERIC_READ;
                dwCreationDisposition = NativeConstants.OPEN_EXISTING;
                break;

            case FileAccess.ReadWrite:
                dwDesiredAccess       = NativeConstants.GENERIC_READ | NativeConstants.GENERIC_WRITE;
                dwCreationDisposition = NativeConstants.OPEN_ALWAYS;
                break;

            case FileAccess.Write:
                dwDesiredAccess       = NativeConstants.GENERIC_WRITE;
                dwCreationDisposition = NativeConstants.CREATE_NEW;
                break;

            default:
                throw new InvalidEnumArgumentException();
            }

            uint dwFlagsAndAttributes =
                NativeConstants.FILE_ATTRIBUTE_TEMPORARY |
                NativeConstants.FILE_FLAG_SEQUENTIAL_SCAN |
                NativeConstants.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;

            IntPtr hFile = SafeNativeMethods.CreateFileW(
                fileName,
                dwDesiredAccess,
                NativeConstants.FILE_SHARE_READ,
                IntPtr.Zero,
                dwCreationDisposition,
                dwFlagsAndAttributes,
                IntPtr.Zero);

            if (hFile == NativeConstants.INVALID_HANDLE_VALUE)
            {
                NativeMethods.ThrowOnWin32Error("CreateFileW returned INVALID_HANDLE_VALUE");
            }

            FileStream stream;

            try
            {
                SafeFileHandle sfh = new SafeFileHandle(hFile, true);
                stream = new FileStream(sfh, fileAccess, 512, false);
            }

            catch
            {
                SafeNativeMethods.CloseHandle(hFile);
                hFile = IntPtr.Zero;
                throw;
            }

            return(stream);
        }
コード例 #6
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);
        }
コード例 #7
0
        /// <summary>
        /// Uses the shell to execute the command. This method must only be used by Paint.NET
        /// and not by plugins.
        /// </summary>
        /// <param name="parent">
        /// The window that is currently in the foreground. This may be null if requireAdmin
        /// is false and the executable that exePath refers to is not marked (e.g. via a
        /// manifest) as requiring administrator privilege.
        /// </param>
        /// <param name="exePath">
        /// The path to the executable to launch.
        /// </param>
        /// <param name="args">
        /// The command-line arguments for the executable.
        /// </param>
        /// <param name="execPrivilege">
        /// The privileges to execute the new process with.
        /// If the executable is already marked as requiring administrator privilege
        /// (e.g. via a "requiresAdministrator" UAC manifest), this parameter should be
        /// set to AsInvokerOrAsManifest.
        /// </param>
        /// <remarks>
        /// If administrator privilege is required, a consent UI may be displayed asking the
        /// user to approve the action. A parent window must be provided in this case so that
        /// the consent UI will know where to position itself. Administrator privilege is
        /// required if execPrivilege is set to RequireAdmin, or if the executable being launched
        /// has a manifest declaring that it requires this privilege and if the operating
        /// system recognizes the manifest.
        /// </remarks>
        /// <exception cref="ArgumentException">
        /// execPrivilege was RequireAdmin, but parent was null.
        /// </exception>
        /// <exception cref="SecurityException">
        /// execPrivilege was RequireAdmin, but the user does not have this privilege, nor do they
        /// have the ability to acquire or elevate to obtain this privilege.
        /// </exception>
        /// <exception cref="Win32Exception">
        /// There was an error launching the program.
        /// </exception>
        public static void Execute(
            IWin32Window parent,
            string exePath,
            string args,
            ExecutePrivilege execPrivilege,
            ExecuteWaitType execWaitType)
        {
            if (exePath == null)
            {
                throw new ArgumentNullException("exePath");
            }

            if (execPrivilege == ExecutePrivilege.RequireAdmin && parent == null)
            {
                throw new ArgumentException("If requireAdmin is true, a parent window must be provided");
            }

            // If this action requires admin privilege, but the user does not have this
            // privilege and is not capable of acquiring this privilege, then we will
            // throw an exception.
            if (execPrivilege == ExecutePrivilege.RequireAdmin &&
                !Security.IsAdministrator &&
                !Security.CanElevateToAdministrator)
            {
                throw new SecurityException("Executable requires administrator privilege, but user is not an administrator and cannot elevate");
            }

            ExecuteHandOff executeHandOff = null;

            switch (execPrivilege)
            {
            case ExecutePrivilege.AsInvokerOrAsManifest:
                executeHandOff = new ExecuteHandOff(ExecAsInvokerOrAsManifest);
                break;

            case ExecutePrivilege.RequireAdmin:
                executeHandOff = new ExecuteHandOff(ExecRequireAdmin);
                break;

            case ExecutePrivilege.RequireNonAdminIfPossible:
                if (Security.CanLaunchNonAdminProcess)
                {
                    executeHandOff = new ExecuteHandOff(ExecRequireNonAdmin);
                }
                else
                {
                    executeHandOff = new ExecuteHandOff(ExecAsInvokerOrAsManifest);
                }
                break;

            default:
                throw new InvalidEnumArgumentException("ExecutePrivilege");
            }

            string updateMonitorExePath = null;

            if (execWaitType == ExecuteWaitType.RelaunchPdnOnExit)
            {
                RelaunchPdnHelperPart1(out updateMonitorExePath);
            }

            IntPtr hProcess = IntPtr.Zero;
            int    nResult  = executeHandOff(parent, exePath, args, out hProcess);

            if (nResult == NativeConstants.ERROR_SUCCESS)
            {
                if (execWaitType == ExecuteWaitType.WaitForExit)
                {
                    SafeNativeMethods.WaitForSingleObject(hProcess, NativeConstants.INFINITE);
                }
                else if (execWaitType == ExecuteWaitType.RelaunchPdnOnExit)
                {
                    bool bResult2 = SafeNativeMethods.SetHandleInformation(
                        hProcess,
                        NativeConstants.HANDLE_FLAG_INHERIT,
                        NativeConstants.HANDLE_FLAG_INHERIT);

                    RelaunchPdnHelperPart2(updateMonitorExePath, hProcess);

                    // Ensure that we don't close the process handle right away in the next few lines of code.
                    // It must be inherited by the child process. Yes, this is technically a leak but we are
                    // planning to terminate in just a moment anyway.
                    hProcess = IntPtr.Zero;
                }
                else if (execWaitType == ExecuteWaitType.ReturnImmediately)
                {
                }

                if (hProcess != IntPtr.Zero)
                {
                    SafeNativeMethods.CloseHandle(hProcess);
                    hProcess = IntPtr.Zero;
                }
            }
            else
            {
                if (nResult == NativeConstants.ERROR_CANCELLED ||
                    nResult == NativeConstants.ERROR_TIMEOUT)
                {
                    // no problem
                }
                else
                {
                    NativeMethods.ThrowOnWin32Error("ExecuteHandoff failed", nResult);
                }

                if (updateMonitorExePath != null)
                {
                    try
                    {
                        File.Delete(updateMonitorExePath);
                    }

                    catch (Exception)
                    {
                    }

                    updateMonitorExePath = null;
                }
            }

            GC.KeepAlive(parent);
        }