source: trunk/eraser/Eraser.Util/NtfsApi.cs @ 2198

Revision 2198, 2.9 KB checked in by lowjoel, 4 years ago (diff)

Fixed UnauthorizedAccessException? when erasing files from an NTFS volume under Windows 7. Fixes regression in r2189

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using Microsoft.Win32.SafeHandles;
26using System.Runtime.InteropServices;
27using System.IO;
28
29namespace Eraser.Util
30{
31    public static class NtfsApi
32    {
33        /// <summary>
34        /// Gets the actual size of the MFT.
35        /// </summary>
36        /// <param name="volume">The volume to query.</param>
37        /// <returns>The size of the MFT.</returns>
38        public static long GetMftValidSize(VolumeInfo volume)
39        {
40            NativeMethods.NTFS_VOLUME_DATA_BUFFER? volumeData = GetNtfsVolumeData(volume);
41            if (volumeData == null)
42                throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
43
44            return volumeData.Value.MftValidDataLength;
45        }
46
47        /// <summary>
48        /// Gets the size of one MFT record segment.
49        /// </summary>
50        /// <param name="volume">The volume to query.</param>
51        /// <returns>The size of one MFT record segment.</returns>
52        public static long GetMftRecordSegmentSize(VolumeInfo volume)
53        {
54            try
55            {
56                return GetNtfsVolumeData(volume).BytesPerFileRecordSegment;
57            }
58            catch (UnauthorizedAccessException)
59            {
60                return Math.Min(volume.ClusterSize, 1024);
61            }
62        }
63
64        /// <summary>
65        /// Sends the FSCTL_GET_NTFS_VOLUME_DATA control code, returning the resuling
66        /// NTFS_VOLUME_DATA_BUFFER.
67        /// </summary>
68        /// <param name="volume">The volume to query.</param>
69        /// <returns>The NTFS_VOLUME_DATA_BUFFER structure representing the data
70        /// file system structures for the volume, or null if the data could not be
71        /// retrieved.</returns>
72        internal static NativeMethods.NTFS_VOLUME_DATA_BUFFER GetNtfsVolumeData(VolumeInfo volume)
73        {
74            using (FileStream stream = volume.Open(FileAccess.Read, FileShare.ReadWrite,
75                FileOptions.None))
76            using (SafeFileHandle handle = stream.SafeFileHandle)
77            {
78                uint resultSize = 0;
79                NativeMethods.NTFS_VOLUME_DATA_BUFFER volumeData =
80                    new NativeMethods.NTFS_VOLUME_DATA_BUFFER();
81                if (NativeMethods.DeviceIoControl(handle,
82                    NativeMethods.FSCTL_GET_NTFS_VOLUME_DATA, IntPtr.Zero, 0, out volumeData,
83                    (uint)Marshal.SizeOf(volumeData), out resultSize, IntPtr.Zero))
84                {
85                    return volumeData;
86                }
87
88                throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
89            }
90        }
91    }
92}
Note: See TracBrowser for help on using the repository browser.