Beispiel #1
0
 public static extern bool DeviceIoControl(SafeFileHandle hVol
                                           , int controlCode
                                           , IntPtr inBuffer
                                           , int inBufferSize
                                           , ref DiskExtents outBuffer
                                           , int outBufferSize
                                           , ref int bytesReturned
                                           , IntPtr overlapped);
Beispiel #2
0
 public static extern bool DeviceIoControl(
     IntPtr hDevice,
     UInt32 dwIoControlCode,
     IntPtr lpInBuffer,
     Int32 nInBufferSize,
     ref DiskExtents lpOutBuffer,
     Int32 nOutBufferSize,
     out int lpBytesReturned,
     IntPtr lpOverlapped);
Beispiel #3
0
        public void Dispose()
        {
            try
            {
                var de1           = new DiskExtents();
                var bytesReturned = 0;
                if (!DeviceIoControl(diskHandle, DeviceIoControlCode.FSCTL_UNLOCK_VOLUME, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "FSCTL_LOCK_VOLUME");
                }

                //fileStream.Dispose();
                diskHandle.Dispose();
            }
            catch (Exception e)
            {
                if (!e.Message.StartsWith("External component has thrown an exception."))
                {
                    throw;
                }
            }
        }
Beispiel #4
0
        // A Volume could be on many physical drives.
        // Returns a list of string containing each physical drive the volume uses.
        // For CD Drives with no disc in it will return an empty list.
        private List <string> GetPhysicalDriveStrings(DriveInfo driveInfo)
        {
            SafeFileHandle sfh            = null;
            List <string>  physicalDrives = new List <string>(1);
            string         path           = "\\\\.\\" + driveInfo.RootDirectory.ToString().TrimEnd('\\');

            try
            {
                sfh = NativeMethods.CreateFile(path, 0, FileShareRead | Filesharewrite, IntPtr.Zero, OpenExisting, 0, IntPtr.Zero);

                int         bytesReturned  = 0;
                DiskExtents de1            = new DiskExtents();
                int         numDiskExtents = 0;
                bool        result         = NativeMethods.DeviceIoControl(sfh
                                                                           , IoctlVolumeGetVolumeDiskExtents
                                                                           , IntPtr.Zero
                                                                           , 0
                                                                           , ref de1
                                                                           , Marshal.SizeOf(de1)
                                                                           , ref bytesReturned, IntPtr.Zero);
                DiskExtents de1Cast = (DiskExtents)de1;
                if (result == true)
                {
                    // there was only one disk extent. So the volume lies on 1 physical drive.
                    physicalDrives.Add("\\\\.\\PhysicalDrive" + de1Cast.first.DiskNumber.ToString());
                    return(physicalDrives);
                }
                if (Marshal.GetLastWin32Error() == IncorrectFunction)
                {
                    // The drive is removable and removed, like a CDRom with nothing in it.
                    return(physicalDrives);
                }
                if (Marshal.GetLastWin32Error() == MoreDataIsAvailable)
                {
                    // This drive is part of a mirror or volume - handle it below.
                }
                else if (Marshal.GetLastWin32Error() != ErrorInsufficientBuffer)
                {
                    throw new Win32Exception();
                }
                // Houston, we have a spanner. The volume is on multiple disks.
                // Untested...
                // We need a blob of memory for the DISK_EXTENTS structure, and all the DISK_EXTENTS

                int    blobSize = Marshal.SizeOf(typeof(DiskExtents)) + (de1Cast.numberOfExtents - 1) * Marshal.SizeOf(typeof(DiskExtent));
                IntPtr pBlob    = Marshal.AllocHGlobal(blobSize);
                result = NativeMethods.DeviceIoControl(sfh, IoctlVolumeGetVolumeDiskExtents, IntPtr.Zero, 0, pBlob, blobSize, ref bytesReturned, IntPtr.Zero);
                if (result == false)
                {
                    throw new Win32Exception();
                }
                // Read them out one at a time.
                IntPtr pNext = new IntPtr(pBlob.ToInt64() + 8);
                // is this always ok on 64 bit OSes? ToInt64?
                for (int i = 0; i <= de1Cast.numberOfExtents - 1; i++)
                {
                    DiskExtent diskExtentN = (DiskExtent)Marshal.PtrToStructure(pNext, typeof(DiskExtent));
                    physicalDrives.Add("\\\\.\\PhysicalDrive" + diskExtentN.DiskNumber.ToString());
                    pNext = new IntPtr(pNext.ToInt32() + Marshal.SizeOf(typeof(DiskExtent)));
                }
                return(physicalDrives);
            }
            finally
            {
                if (sfh != null)
                {
                    if (sfh.IsInvalid == false)
                    {
                        sfh.Close();
                    }
                    sfh.Dispose();
                }
            }
        }
Beispiel #5
0
        public SDManagement(String RootDir)
        {
            var de1           = new DiskExtents();
            var bytesReturned = 0;

            try
            {
                driveLetter = RootDir;
                var path = @"\\.\" + driveLetter;
                using (var sfh = CreateFile(path, EFileAccess.GenericRead | EFileAccess.GenericWrite, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, 0, IntPtr.Zero))
                {
                    if (sfh.IsInvalid)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), "Handle.IsInvalid");
                    }

                    using (new FileStream(sfh, FileAccess.Read))
                    {
                        if (DeviceIoControl(sfh, DeviceIoControlCode.IoctlVolumeGetVolumeDiskExtents, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero))
                        {
                            SDPhysicalName = @"\\.\PhysicalDrive" + de1.first.DiskNumber.ToString(CultureInfo.InvariantCulture);

                            var dg1 = new DISK_GEOMETRY();
                            if (!DeviceIoControl(sfh, DeviceIoControlCode.IOCTL_DISK_GET_DRIVE_GEOMETRY, IntPtr.Zero, 0, ref dg1, Marshal.SizeOf(dg1), ref bytesReturned, IntPtr.Zero))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error(), "IOCTL_DISK_GET_DRIVE_GEOMETRY");
                            }
                            SDSize = dg1.DiskSize;
                            if (!DeviceIoControl(sfh, DeviceIoControlCode.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error(), "FSCTL_LOCK_VOLUME");
                            }
                            if (!DeviceIoControl(sfh, DeviceIoControlCode.FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error(), "FSCTL_DISMOUNT_VOLUME");
                            }
                            //if (IsWinVistaOrHigher())
                            {
                                deviceName = GetDeviceName(driveLetter);
                                if (!String.IsNullOrEmpty(deviceName) && !DefineDosDevice(EParam.DDD_RAW_TARGET_PATH | EParam.DDD_REMOVE_DEFINITION | EParam.DDD_EXACT_MATCH_ON_REMOVE, driveLetter, deviceName))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error(), "DefineDosDevice");
                                }
                            }
                        }
                        var lerror = Marshal.GetLastWin32Error();

                        if (lerror != 0)
                        {
                            if (lerror == 1)
                            {
                                throw new Win32Exception(lerror, String.Format(@"IncorrectFunction The drive ""{0}"" is removable and removed, like a CDRom with nothing in it.)", driveLetter));
                            }
                            if (lerror == 122)
                            {
                                throw new Win32Exception(lerror, "ErrorInsufficientBuffer");
                            }
                            throw new NotSupportedException("Multiple Disc Volume");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (!e.Message.StartsWith("External component has thrown an exception."))
                {
                    throw;
                }
            }

            diskHandle = CreateFile(SDPhysicalName, EFileAccess.GenericRead | EFileAccess.GenericWrite, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.Device | EFileAttributes.NoBuffering | EFileAttributes.Write_Through, IntPtr.Zero);
            if (diskHandle.IsInvalid)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Handle.IsInvalid");
            }
            if (!DeviceIoControl(diskHandle, DeviceIoControlCode.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "FSCTL_LOCK_VOLUME");
            }
            fileStream = new FileStream(diskHandle, FileAccess.ReadWrite);
        }