Exemple #1
0
        public IntPtr OpenHan(uint dwDesiredAccess, int pid)
        {
            var args = new object[3];

            args[0] = dwDesiredAccess;
            args[1] = false;
            args[2] = pid;
            return((IntPtr)OpenHandle.Invoke(null, args));
        }
Exemple #2
0
        /// <summary>
        /// Returns the ADSes of the given file, forcing open handles to the files closed
        /// if necessary.
        /// </summary>
        /// <param name="file">The file to look for ADSes.</param>
        /// <param name="attempts">The number of tries to close open handles. Abort after a
        /// large number of tries (currently 10 attempts)</param>
        /// <returns>The list of ADSes the file contains.</returns>
        private static StreamInfo[] GetPathADSes(FileInfo file, ref int attempts)
        {
            try
            {
                return(file.GetADSes().ToArray());
            }
            catch (FileNotFoundException)
            {
                return(new StreamInfo[0]);
            }
            catch (SharingViolationException)
            {
                //The system cannot open the file, try to force the file handle to close.
                if (!Host.Instance.Settings.ForceUnlockLockedFiles)
                {
                    throw;
                }

                //Retry closing the file 10 times. If we can't do that, we should abort
                //since we may not be able to get the process information of processes
                //running with higher privileges.
                if (OpenHandle.Close(file.FullName).Count == 0 && ++attempts <= 10)
                {
                    return(GetPathADSes(file, ref attempts));
                }
                else
                {
                    throw;
                }
            }
            catch (UnauthorizedAccessException e)
            {
                //The system cannot read the file, assume no ADSes for lack of
                //more information.
                Logger.Log(e.Message, LogLevel.Error);
            }

            return(new StreamInfo[0]);
        }
Exemple #3
0
        /// <summary>
        /// Obfuscates the file name and file attributes of the given file.
        /// </summary>
        /// <param name="info">The file to obfuscate.</param>
        private void ObfuscateFileSystemInfoName(FileSystemInfo info)
        {
            //If the file/directory doesn't exist, pass.
            if (!info.Exists)
            {
                return;
            }

            //Reset the file attributes to non-content indexed so indexing
            //services will not lock the file.
            try
            {
                info.Attributes = FileAttributes.NotContentIndexed;
            }
            catch (ArgumentException e)
            {
                //This is an undocumented exception: when the path we are setting
                //cannot be accessed (ERROR_ACCESS_DENIED is returned) an
                //ArgumentException is raised (no idea why!)
                throw new UnauthorizedAccessException(e.Message, e);
            }

            //Rename the file a few times to erase the entry from the file system
            //table.
            for (int i = 0, tries = 0; i < FileNameErasePasses; ++tries)
            {
                //Generate a new file name for the file/directory.
                string newPath = GenerateRandomFileName(info.GetParent(), info.Name.Length);

                try
                {
                    ResetFileTimes(info);

                    //Try to rename the file. If it fails, it is probably due to another
                    //process locking the file. Defer, then rename again.
                    info.MoveTo(newPath);
                    ++i;
                }
                catch (IOException e)
                {
                    switch (System.Runtime.InteropServices.Marshal.GetLastWin32Error())
                    {
                    case Win32ErrorCode.AccessDenied:
                        throw new UnauthorizedAccessException(S._("The file {0} could not " +
                                                                  "be erased because the file's permissions prevent access to the file.",
                                                                  info.FullName));

                    case Win32ErrorCode.SharingViolation:
                        //If after FilenameEraseTries the file is still locked, some program is
                        //definitely using the file; throw an exception.
                        if (tries > FileNameEraseTries)
                        {
                            //Try to force the handle closed.
                            if (tries > FileNameEraseTries + 1 ||
                                !Host.Instance.Settings.ForceUnlockLockedFiles)
                            {
                                throw new IOException(S._("The file {0} is currently in use " +
                                                          "and cannot be removed.", info.FullName), e);
                            }

                            //Either we could not close all instances, or we already tried twice. Report
                            //the error.
                            string processes = string.Empty;
                            {
                                StringBuilder processStr = new StringBuilder();
                                foreach (OpenHandle handle in OpenHandle.Close(info.FullName))
                                {
                                    try
                                    {
                                        processStr.AppendFormat(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "{0}, ", handle.Process.MainModule.FileName);
                                    }
                                    catch (System.ComponentModel.Win32Exception)
                                    {
                                        processStr.AppendFormat(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "Process ID {0}, ", handle.Process.Id);
                                    }
                                }

                                if (processStr.Length > 2)
                                {
                                    processes = processStr.ToString().Remove(processStr.Length - 2).Trim();
                                }
                                else
                                {
                                    processes = S._("(unknown)");
                                }
                            }

                            throw new SharingViolationException(S._(
                                                                    "Could not force closure of file \"{0}\" {1}", info.FullName,
                                                                    S._("(locked by {0})", processes)));
                        }

                        //Let the process locking the file release the lock
                        Thread.Sleep(100);
                        break;

                    case Win32ErrorCode.DiskFull:
                        //If the disk is full, we can't do anything except manually deleting
                        //the file, break out of this loop.
                        i = FileNameEraseTries;
                        break;

                    default:
                        throw;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Attempts to erase a stream, trying to close all open handles if a process has
        /// a lock on the file.
        /// </summary>
        /// <param name="fsManager">The file system provider used to erase the stream.</param>
        /// <param name="method">The erasure method to use to erase the stream.</param>
        /// <param name="info">The stream to erase.</param>
        /// <param name="callback">The erasure progress callback.</param>
        private void TryEraseStream(IFileSystem fsManager, IErasureMethod method, StreamInfo info,
                                    ErasureMethodProgressFunction callback)
        {
            for (int i = 0; ; ++i)
            {
                try
                {
                    //Make sure the file does not have any attributes which may affect
                    //the erasure process
                    if ((info.Attributes & FileAttributes.Compressed) != 0 ||
                        (info.Attributes & FileAttributes.Encrypted) != 0 ||
                        (info.Attributes & FileAttributes.SparseFile) != 0)
                    {
                        //Log the error
                        Logger.Log(S._("The file {0} could not be erased because the file was " +
                                       "either compressed, encrypted or a sparse file.", info.FullName),
                                   LogLevel.Error);
                        return;
                    }

                    //Do not erase reparse points, as they will cause other references to the file
                    //to be to garbage.
                    if ((info.Attributes & FileAttributes.ReparsePoint) == 0)
                    {
                        fsManager.EraseFileSystemObject(info, method, callback);
                    }
                    else
                    {
                        Logger.Log(S._("The file {0} is a hard link or a symbolic link thus the " +
                                       "contents of the file was not erased.", info.FullName), LogLevel.Notice);
                    }
                    return;
                }
                catch (FileNotFoundException)
                {
                    Logger.Log(S._("The file {0} was not erased because it was " +
                                   "deleted before it could be erased.", info.FullName), LogLevel.Information);
                }
                catch (DirectoryNotFoundException)
                {
                    Logger.Log(S._("The file {0} was not erased because the containing " +
                                   "directory was deleted before it could be erased.", info.FullName),
                               LogLevel.Information);
                }
                catch (SharingViolationException)
                {
                    if (!Host.Instance.Settings.ForceUnlockLockedFiles)
                    {
                        throw;
                    }

                    //Try closing all open handles. If it succeeds, we can run the erase again.
                    //To prevent Eraser from deadlocking, we will only attempt this once. Some
                    //programs may be aggressive and keep a handle open in a tight loop.
                    List <OpenHandle> remainingHandles = OpenHandle.Close(info.FullName);
                    if (i == 0 && remainingHandles.Count == 0)
                    {
                        continue;
                    }

                    //Either we could not close all instances, or we already tried twice. Report
                    //the error.
                    string processes = string.Empty;
                    {
                        StringBuilder processStr = new StringBuilder();
                        foreach (OpenHandle handle in remainingHandles)
                        {
                            try
                            {
                                processStr.AppendFormat(
                                    System.Globalization.CultureInfo.InvariantCulture,
                                    "{0}, ", handle.Process.MainModule.FileName);
                            }
                            catch (System.ComponentModel.Win32Exception)
                            {
                                processStr.AppendFormat(
                                    System.Globalization.CultureInfo.InvariantCulture,
                                    "Process ID {0}, ", handle.Process.Id);
                            }
                        }

                        if (processStr.Length > 2)
                        {
                            processes = processStr.ToString().Remove(processStr.Length - 2).Trim();
                        }
                        else
                        {
                            processes = S._("(unknown)");
                        }
                    }

                    throw new SharingViolationException(S._(
                                                            "Could not force closure of file \"{0}\" {1}", info.FileName,
                                                            S._("(locked by {0})", processes)));
                }
            }
        }