/// <summary> /// Opens a device in the Win32 Namespace. /// </summary> /// <param name="deviceName">The name of the device to open.</param> /// <param name="access">The access needed for the handle.</param> /// <returns>A <see cref="SafeFileHandle"/> to the device.</returns> private static SafeFileHandle OpenWin32Device(string deviceName, uint access, FileShare share, FileOptions options) { //Define the DOS device name for access string dosDeviceName = string.Format(CultureInfo.InvariantCulture, "eraser{0}_{1}", System.Diagnostics.Process.GetCurrentProcess().Id, System.Threading.Thread.CurrentThread.ManagedThreadId); if (!NativeMethods.DefineDosDevice( NativeMethods.DosDeviceDefineFlags.RawTargetPath, dosDeviceName, deviceName)) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } try { //Open the device handle. return(NativeMethods.CreateFile(string.Format(CultureInfo.InvariantCulture, "\\\\.\\{0}", dosDeviceName), access, (uint)share, IntPtr.Zero, (int)FileMode.Open, (uint)options, IntPtr.Zero)); } finally { //Then undefine the DOS device if (!NativeMethods.DefineDosDevice( NativeMethods.DosDeviceDefineFlags.ExactMatchOnRmove | NativeMethods.DosDeviceDefineFlags.RawTargetPath | NativeMethods.DosDeviceDefineFlags.RemoveDefinition, dosDeviceName, deviceName)) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } } }
private SafeFileHandle OpenHandle(FileMode mode, uint access, FileShare share, FileOptions options) { //Sharing mode if ((share & FileShare.Inheritable) != 0) { throw new NotSupportedException("Inheritable handles are not supported."); } //Advanced options if ((options & FileOptions.Asynchronous) != 0) { throw new NotSupportedException("Asynchronous handles are not implemented."); } //Create the handle SafeFileHandle result = NativeMethods.CreateFile(FullName, access, (uint)share, IntPtr.Zero, (uint)mode, (uint)options, IntPtr.Zero); if (result.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); result.Close(); throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); } return(result); }
private SafeFileHandle OpenHandle(uint access, FileShare share, FileOptions options) { //Sharing mode if ((share & FileShare.Inheritable) != 0) { throw new NotSupportedException("Inheritable handles are not supported."); } //Advanced options if ((options & FileOptions.Asynchronous) != 0) { throw new NotSupportedException("Asynchronous handles are not implemented."); } //Create the handle string openPath = VolumeId; if (openPath.Length > 0 && openPath[openPath.Length - 1] == '\\') { openPath = openPath.Remove(openPath.Length - 1); } SafeFileHandle result = NativeMethods.CreateFile(openPath, access, (uint)share, IntPtr.Zero, (uint)FileMode.Open, (uint)options, IntPtr.Zero); //Check that the handle is valid if (result.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); result.Close(); throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); } return(result); }
private SafeFileHandle OpenHandle(uint access, FileShare share, FileOptions options) { //Sharing mode if ((share & FileShare.Inheritable) != 0) { throw new NotSupportedException("Inheritable handles are not supported."); } //Advanced options if ((options & FileOptions.Asynchronous) != 0) { throw new NotSupportedException("Asynchronous handles are not implemented."); } //Create the handle SafeFileHandle result = OpenWin32Device(GetDiskPath(), access, share, options); if (result.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); result.Close(); throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); } return(result); }
/// <summary> /// Gets the actual size of the MFT. /// </summary> /// <param name="volume">The volume to query.</param> /// <returns>The size of the MFT.</returns> public static long GetMftValidSize(VolumeInfo volume) { NativeMethods.NTFS_VOLUME_DATA_BUFFER?volumeData = GetNtfsVolumeData(volume); if (volumeData == null) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } return(volumeData.Value.MftValidDataLength); }
/// <summary> /// Opens a file in the specified mode with read, write, or read/write access, /// the specified sharing option, and other advanced options. /// </summary> /// <param name="mode">A System.IO.FileMode constant specifying the mode /// (for example, Open or Append) in which to open the file.</param> /// <param name="access">A System.IO.FileAccess constant specifying whether /// to open the file with Read, Write, or ReadWrite file access.</param> /// <param name="share">A System.IO.FileShare constant specifying the type /// of access other FileStream objects have to this file.</param> /// <param name="options">The System.IO.FileOptions constant specifying /// the advanced file options to use when opening the file.</param> /// <returns>A System.IO.FileStream object opened with the specified mode, /// access, sharing options, and special file options.</returns> public FileStream Open(FileMode mode, FileAccess access, FileShare share, FileOptions options) { SafeFileHandle handle = OpenHandle(mode, access, share, options); //Check that the handle is valid if (handle.IsInvalid) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } //Return the FileStream return(new FileStream(handle, access)); }
/// <summary> /// Permanently deletes the stream. If this refers to the unnamed stream, all /// alternate data streams are also deleted. /// </summary> public override void Delete() { if (!NativeMethods.DeleteFile(FullName)) { int errorCode = Marshal.GetLastWin32Error(); switch (errorCode) { case Win32ErrorCode.PathNotFound: break; default: throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); } } }
/// <summary> /// Opens a file with read, write, or read/write access, the specified /// sharing option, and other advanced options. /// </summary> /// <param name="mode">A System.IO.FileMode constant specifying the mode /// (for example, Open or Append) in which to open the file.</param> /// <param name="access">A System.IO.FileAccess constant specifying whether /// to open the file with Read, Write, or ReadWrite file access.</param> /// <param name="share">A System.IO.FileShare constant specifying the type /// of access other FileStream objects have to this file.</param> /// <param name="options">The System.IO.FileOptions constant specifying /// the advanced file options to use when opening the file.</param> /// <returns>A System.IO.FileStream object opened with the specified mode, /// access, sharing options, and special file options.</returns> public FileStream Open(FileAccess access, FileShare share, FileOptions options) { SafeFileHandle handle = OpenHandle(access, share, options); //Check that the handle is valid if (handle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); handle.Close(); throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); } //Return the stream return(new PhysicalDriveStream(this, handle, access)); }
/// <summary> /// Destroys all partitioning information on the drive. /// </summary> public void DeleteDriveLayout() { //Open the drive for read/write access using (SafeFileHandle handle = OpenHandle(FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.None)) { //Issue the IOCTL_DISK_DELETE_DRIVE_LAYOUT control code uint returnSize = 0; if (!NativeMethods.DeviceIoControl(handle, NativeMethods.IOCTL_DISK_DELETE_DRIVE_LAYOUT, IntPtr.Zero, 0, IntPtr.Zero, 0, out returnSize, IntPtr.Zero)) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } } }
private void LockVolume() { LengthCache = Length; uint result = 0; for (int i = 0; !NativeMethods.DeviceIoControl(SafeFileHandle, NativeMethods.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out result, IntPtr.Zero); ++i) { if (i > 100) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } System.Threading.Thread.Sleep(100); } IsLocked = true; }
/// <summary> /// Sends the FSCTL_GET_NTFS_VOLUME_DATA control code, returning the resuling /// NTFS_VOLUME_DATA_BUFFER. /// </summary> /// <param name="volume">The volume to query.</param> /// <returns>The NTFS_VOLUME_DATA_BUFFER structure representing the data /// file system structures for the volume, or null if the data could not be /// retrieved.</returns> internal static NativeMethods.NTFS_VOLUME_DATA_BUFFER GetNtfsVolumeData(VolumeInfo volume) { using (FileStream stream = volume.Open(FileAccess.Read, FileShare.ReadWrite, FileOptions.None)) using (SafeFileHandle handle = stream.SafeFileHandle) { uint resultSize = 0; NativeMethods.NTFS_VOLUME_DATA_BUFFER volumeData = new NativeMethods.NTFS_VOLUME_DATA_BUFFER(); if (NativeMethods.DeviceIoControl(handle, NativeMethods.FSCTL_GET_NTFS_VOLUME_DATA, IntPtr.Zero, 0, out volumeData, (uint)Marshal.SizeOf(volumeData), out resultSize, IntPtr.Zero)) { return(volumeData); } throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } }
/// <summary> /// Creates a Volume object from its mountpoint. /// </summary> /// <param name="mountPoint">The path to the mountpoint.</param> /// <returns>The volume object if such a volume exists, or an exception /// is thrown.</returns> public static VolumeInfo FromMountPoint(string mountPoint) { //Verify that the mountpoint given exists; if it doesn't we'll raise //a DirectoryNotFound exception. DirectoryInfo mountpointDir = new DirectoryInfo(mountPoint); if (!mountpointDir.Exists) { throw new DirectoryNotFoundException(); } do { //Ensure that the current path has a trailing backslash string currentDir = mountpointDir.FullName; if (currentDir.Length > 0 && currentDir[currentDir.Length - 1] != '\\') { currentDir += '\\'; } //The path cannot be empty. if (string.IsNullOrEmpty(currentDir)) { throw new DirectoryNotFoundException(); } //Get the type of the drive DriveType driveType = (DriveType)NativeMethods.GetDriveType(currentDir); //We do different things for different kinds of drives. Network drives //will need us to resolve the drive to a UNC path. Local drives will //be resolved to a volume GUID StringBuilder volumeID = new StringBuilder(NativeMethods.MaxPath); if (driveType == DriveType.Network) { //If the current directory is a UNC path, then return the VolumeInfo instance //directly if (currentDir.Substring(0, 2) == "\\\\" && currentDir.IndexOf('\\', 2) != -1) { return(new VolumeInfo(currentDir)); } //Otherwise, resolve the mountpoint to a UNC path uint bufferCapacity = (uint)volumeID.Capacity; uint errorCode = NativeMethods.WNetGetConnection( currentDir.Substring(0, currentDir.Length - 1), volumeID, ref bufferCapacity); switch (errorCode) { case Win32ErrorCode.Success: return(new VolumeInfo(volumeID.ToString() + '\\')); case Win32ErrorCode.BadDevice: //Path is not a network share break; default: throw new Win32Exception((int)errorCode); } } else { //If this is a mountpoint, resolve it before calling //GetVolumeNameForVolumeMountPoint since it will return an error if //the path given is a reparse point, but not a volume reparse point. while (mountpointDir.Exists && (mountpointDir.Attributes & FileAttributes.ReparsePoint) != 0) { currentDir = ExtensionMethods.PathUtil.ResolveReparsePoint(currentDir); //If we get a volume identifier, we need to see if it is the only thing //in the path. If it is, we found our volume GUID and we won't have to //call GetVolumeNameForVolumeMountPoint. if (currentDir.StartsWith("\\??\\Volume{")) { if (currentDir.Length == 49 && currentDir.EndsWith("}\\")) { return(new VolumeInfo(string.Format(CultureInfo.InvariantCulture, "\\\\?\\Volume{{{0}}}\\", currentDir.Substring(11, 36)))); } else { throw new ArgumentException(S._("The path provided includes a " + "reparse point which references another volume.")); } } //Strip the NT namespace bit else { currentDir = currentDir.Substring(4); } mountpointDir = new DirectoryInfo(currentDir); } if (!NativeMethods.GetVolumeNameForVolumeMountPoint(currentDir, volumeID, 50)) { int errorCode = Marshal.GetLastWin32Error(); switch (errorCode) { case Win32ErrorCode.InvalidFunction: case Win32ErrorCode.FileNotFound: case Win32ErrorCode.PathNotFound: case Win32ErrorCode.NotAReparsePoint: break; case Win32ErrorCode.InvalidParameter: //This is a peculiar case: we have a DOS device defined, but it //does not show up in the list of volume GUIDs. I know the ImDisk //Ramdisk drive triggers this, so the only workaround is to //allow DOS device names to be used in VolumeInfo as well. return(new VolumeInfo(new DirectoryInfo(currentDir))); default: throw Win32ErrorCode.GetExceptionForWin32Error( Marshal.GetLastWin32Error()); } } else { return(new VolumeInfo(volumeID.ToString())); } } mountpointDir = mountpointDir.Parent; }while (mountpointDir != null); throw Win32ErrorCode.GetExceptionForWin32Error(Win32ErrorCode.NotAReparsePoint); }
/// <summary> /// Lists all mounted network drives on the current computer. The key is /// the local path, the value is the remote path. /// </summary> private static Dictionary <string, string> GetNetworkDrivesInternal() { Dictionary <string, string> result = new Dictionary <string, string>(); //Open an enumeration handle to list mount points. IntPtr enumHandle; uint errorCode = NativeMethods.WNetOpenEnum(NativeMethods.RESOURCE_CONNECTED, NativeMethods.RESOURCETYPE_DISK, 0, IntPtr.Zero, out enumHandle); if (errorCode != Win32ErrorCode.Success) { throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } try { int resultBufferCount = 32; int resultBufferSize = resultBufferCount * Marshal.SizeOf(typeof(NativeMethods.NETRESOURCE)); IntPtr resultBuffer = Marshal.AllocHGlobal(resultBufferSize); try { for ( ; ;) { uint resultBufferStored = (uint)resultBufferCount; uint resultBufferRequiredSize = (uint)resultBufferSize; errorCode = NativeMethods.WNetEnumResource(enumHandle, ref resultBufferStored, resultBuffer, ref resultBufferRequiredSize); if (errorCode == Win32ErrorCode.NoMoreItems) { break; } else if (errorCode != Win32ErrorCode.Success) { throw new Win32Exception((int)errorCode); } unsafe { //Marshal the memory block to managed structures. byte *pointer = (byte *)resultBuffer.ToPointer(); for (uint i = 0; i < resultBufferStored; ++i, pointer += Marshal.SizeOf(typeof(NativeMethods.NETRESOURCE))) { NativeMethods.NETRESOURCE resource = (NativeMethods.NETRESOURCE)Marshal.PtrToStructure( (IntPtr)pointer, typeof(NativeMethods.NETRESOURCE)); //Skip all UNC paths without a local mount point if (resource.lpLocalName == null) { continue; } //Ensure that the path in the resource structure ends with a trailing //backslash as out volume ID ends with one. if (string.IsNullOrEmpty(resource.lpRemoteName)) { continue; } if (resource.lpRemoteName[resource.lpRemoteName.Length - 1] != '\\') { resource.lpRemoteName += '\\'; } result.Add(resource.lpLocalName, resource.lpRemoteName); } } } } finally { Marshal.FreeHGlobal(resultBuffer); } } finally { NativeMethods.WNetCloseEnum(enumHandle); } return(result); }