예제 #1
0
        /// <summary>
        /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365194(v=vs.85).aspx" />
        /// </summary>
        public VOLUME_DISK_EXTENTS VolumeGetVolumeDiskExtents()
        {
            // Fetch in increments of 32 bytes, as one extent (the most common case) is one extent pr. volume.
            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.VolumeGetVolumeDiskExtents, 32);

            // Build the VOLUME_DISK_EXTENTS structure
            VOLUME_DISK_EXTENTS res = new VOLUME_DISK_EXTENTS();

            res.NumberOfDiskExtents = BitConverter.ToUInt32(data, 0);
            res.Extents             = new DISK_EXTENT[res.NumberOfDiskExtents];

            using (UnmanagedMemory dataPtr = new UnmanagedMemory(data))
            {
                // TODO: This code needs to be tested for volumes with more than one extent.
                for (int i = 0; i < res.NumberOfDiskExtents; i++)
                {
                    IntPtr      currentDataPtr = new IntPtr(dataPtr.Handle.ToInt64() + 8 + i * MarshalHelper.SizeOf <DISK_EXTENT>());
                    DISK_EXTENT extent         = currentDataPtr.ToStructure <DISK_EXTENT>();

                    res.Extents[i] = extent;
                }
            }

            return(res);
        }
        //StorageCheckVerify
        //StorageCheckVerify2
        //StorageMediaRemoval

        public STORAGE_DEVICE_DESCRIPTOR_PARSED StorageGetDeviceProperty()
        {
            STORAGE_PROPERTY_QUERY query = new STORAGE_PROPERTY_QUERY();

            query.QueryType  = STORAGE_QUERY_TYPE.PropertyStandardQuery;
            query.PropertyId = STORAGE_PROPERTY_ID.StorageDeviceProperty;

            byte[] res = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.StorageQueryProperty, query);
            STORAGE_DEVICE_DESCRIPTOR descriptor = Utils.ByteArrayToStruct <STORAGE_DEVICE_DESCRIPTOR>(res, 0);

            STORAGE_DEVICE_DESCRIPTOR_PARSED returnValue = new STORAGE_DEVICE_DESCRIPTOR_PARSED();

            returnValue.Version               = descriptor.Version;
            returnValue.Size                  = descriptor.Size;
            returnValue.DeviceType            = descriptor.DeviceType;
            returnValue.DeviceTypeModifier    = descriptor.DeviceTypeModifier;
            returnValue.RemovableMedia        = descriptor.RemovableMedia;
            returnValue.CommandQueueing       = descriptor.CommandQueueing;
            returnValue.VendorIdOffset        = descriptor.VendorIdOffset;
            returnValue.ProductIdOffset       = descriptor.ProductIdOffset;
            returnValue.ProductRevisionOffset = descriptor.ProductRevisionOffset;
            returnValue.SerialNumberOffset    = descriptor.SerialNumberOffset;
            returnValue.BusType               = descriptor.BusType;
            returnValue.RawPropertiesLength   = descriptor.RawPropertiesLength;
            returnValue.RawDeviceProperties   = descriptor.RawDeviceProperties;
            returnValue.SerialNumber          = Utils.ReadNullTerminatedAsciiString(res, (int)descriptor.SerialNumberOffset);

            return(returnValue);
        }
        //FsctlSetEncryption
        //FsctlSetObjectId
        //FsctlSetObjectIdExtended
        //FsctlSetReparsePoint

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364596(v=vs.85).aspx"/></summary>
        public void FileSystemSetSparseFile(bool setSparse)
        {
            FILE_SET_SPARSE_BUFFER input = new FILE_SET_SPARSE_BUFFER();

            input.SetSparse = setSparse;

            DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlSetSparse, input);
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364597(v=vs.85).aspx"/></summary>
        public void FileSystemSetZeroData(long fileOffset, long length)
        {
            FILE_ZERO_DATA_INFORMATION input = new FILE_ZERO_DATA_INFORMATION();

            input.FileOffset      = fileOffset;
            input.BeyondFinalZero = fileOffset + length;

            DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlSetZeroData, input);
        }
예제 #5
0
        //FsctlAllowExtendedDasdIo
        //FsctlCreateOrGetObjectId
        //FsctlDeleteObjectId
        //FsctlDeleteReparsePoint
        //FsctlDismountVolume
        //FsctlDumpPropertyData
        //FsctlEnableUpgrade
        //FsctlEncryptionFsctlIo

        //FsctlExtendVolume

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364565(v=vs.85).aspx"/></summary>
        public FileSystemStats[] FileSystemGetStatistics()
        {
            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.FsctlFileSystemGetStatistics, 512);

            FileSystemStats[] res;

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                IntPtr currentDataPtr = mem;

                FILESYSTEM_STATISTICS firstStats = (FILESYSTEM_STATISTICS)Marshal.PtrToStructure(currentDataPtr, typeof(FILESYSTEM_STATISTICS));

                int fsStatsSize = Marshal.SizeOf(typeof(FILESYSTEM_STATISTICS));

                int elementSize = (int)firstStats.SizeOfCompleteStructure;
                int procCount   = data.Length / elementSize;

                res = new FileSystemStats[procCount];

                for (int i = 0; i < procCount; i++)
                {
                    res[i]       = new FileSystemStats();
                    res[i].Stats = (FILESYSTEM_STATISTICS)Marshal.PtrToStructure(currentDataPtr, typeof(FILESYSTEM_STATISTICS));

                    switch (res[i].Stats.FileSystemType)
                    {
                    case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_NTFS:
                        NTFS_STATISTICS ntfsStats = (NTFS_STATISTICS)Marshal.PtrToStructure(currentDataPtr + fsStatsSize, typeof(NTFS_STATISTICS));

                        res[i].FSStats = ntfsStats;

                        break;

                    case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_FAT:
                        FAT_STATISTICS fatStats = (FAT_STATISTICS)Marshal.PtrToStructure(currentDataPtr + fsStatsSize, typeof(FAT_STATISTICS));

                        res[i].FSStats = fatStats;
                        break;

                    case FILESYSTEM_STATISTICS_TYPE.FILESYSTEM_STATISTICS_TYPE_EXFAT:
                        EXFAT_STATISTICS exFatStats = (EXFAT_STATISTICS)Marshal.PtrToStructure(currentDataPtr + fsStatsSize, typeof(EXFAT_STATISTICS));

                        res[i].FSStats = exFatStats;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    currentDataPtr += elementSize;
                }
            }

            return(res);
        }
        //FsctlHsmData
        //FsctlHsmMsg
        //FsctlInvalidateVolumes
        //FsctlIsPathnameValid
        //FsctlIsVolumeDirty
        //FsctlIsVolumeMounted
        //FsctlLockVolume
        //FsctlMarkAsSystemHive
        //FsctlMarkHandle
        //FsctlMarkVolumeDirty

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/aa364577(v=vs.85).aspx"/></summary>
        public void FileSystemMoveFile(IntPtr fileHandle, ulong startingVcn, ulong startingLcn, uint clusterCount)
        {
            MOVE_FILE_DATA input = new MOVE_FILE_DATA();

            input.FileHandle   = fileHandle;
            input.StartingVcn  = startingVcn;
            input.StartingLcn  = startingLcn;
            input.ClusterCount = clusterCount;

            DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlMoveFile, input);
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364563(v=vs.85).aspx"/></summary>
        public IUSN_RECORD[] FileSystemEnumUsnData()
        {
            ulong     nextUsn   = 0;
            const int chunkSize = 1 * 1024 * 1024;      // 1 MB chunks

            List <IUSN_RECORD> res = new List <IUSN_RECORD>();

            using (UnmanagedMemory mem = new UnmanagedMemory(chunkSize))
            {
                do
                {
                    MFT_ENUM_DATA_V0 input = new MFT_ENUM_DATA_V0();
                    input.StartFileReferenceNumber = nextUsn;
                    input.LowUsn  = long.MinValue;
                    input.HighUsn = long.MaxValue;

                    int    errorCode;
                    byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlEnumUsnData, chunkSize, input, out errorCode);
                    Marshal.Copy(data, 0, mem, data.Length);

                    if (errorCode != 0)
                    {
                        // Exit when theres no more to do
                        break;
                    }

                    nextUsn = BitConverter.ToUInt64(data, 0);

                    int dataOffset = 8;

                    while (dataOffset < data.Length)
                    {
                        int         length;
                        IUSN_RECORD rec = ParseUsnRecord(mem, dataOffset, out length);

                        if (length <= 0)
                        {
                            break;
                        }

                        res.Add(rec);

                        // Move to next record
                        dataOffset += length;
                    }

                    // Fetch next chunk
                } while (true);
            }

            return(res.ToArray());
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364573(v=vs.85).aspx"/></summary>
        public VOLUME_BITMAP_BUFFER FileSystemGetVolumeBitmap(ulong startingLcn = 0)
        {
            STARTING_LCN_INPUT_BUFFER startingLcnStruct = new STARTING_LCN_INPUT_BUFFER();

            startingLcnStruct.StartingLcn = startingLcn;

            // Fetch 128 bytes (this includes the size parameter of the VOLUME_BITMAP_BUFFER structure.
            int lastError;

            byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlGetVolumeBitmap, 128, startingLcnStruct, out lastError);

            // Is there more data? (Most often there is).
            if (lastError == 234)
            {
                // Parse length attribute (2'nd 64-bit attribute)
                uint newLength = (uint)BitConverter.ToUInt64(data, 8);

                // Length: Clusters / 8 + 2x 64 bit numbers
                newLength = (uint)Math.Ceiling(newLength / 8d) + 2 * 8;

                data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlGetVolumeBitmap, newLength, startingLcnStruct, out lastError);
            }

            // Ensure the last call to InvokeIoControl succeeded.
            if (lastError != 0)
            {
                throw new Win32Exception(lastError, "Couldn't invoke FileSystemGetVolumeBitmap. LastError: " + Utils.GetWin32ErrorMessage(lastError));
            }

            // Build the VOLUME_BITMAP_BUFFER structure.
            VOLUME_BITMAP_BUFFER res = new VOLUME_BITMAP_BUFFER();

            res.StartingLcn = BitConverter.ToUInt64(data, 0);
            res.BitmapSize  = BitConverter.ToUInt64(data, sizeof(UInt64));

            res.Buffer = new BitArray((int)res.BitmapSize);

            for (int i = 0; i < res.Buffer.Length; i++)
            {
                int  dataByteIndex = sizeof(UInt64) * 2 + i / 8;
                byte dataByte      = data[dataByteIndex];

                int byteIdx = i % 8;

                res.Buffer[i] = ((dataByte >> byteIdx) & 1) == 1;
            }

            return(res);
        }
        /// <summary>
        /// No reference
        /// </summary>
        public List <string> QueryDosVolumePaths(string deviceName)
        {
            int byteCount = Encoding.Unicode.GetByteCount(deviceName);

            byte[] tmp = new byte[sizeof(ushort) + byteCount];

            tmp[0] = (byte)(byteCount & 0xFF);
            tmp[1] = (byte)((byteCount >> 8) & 0xFF);

            Encoding.Unicode.GetBytes(deviceName, 0, deviceName.Length, tmp, 2);

            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.MountmgrQueryDosVolumePaths, tmp, 64, (uint)tmp.Length);

            return(new List <string>(Utils.ReadUnicodeStringArray(data, sizeof(uint))));
        }
        //DiskSetPartitionInfo
        //DiskSetPartitionInfoEx

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365173(v=vs.85).aspx"/></summary>
        public DRIVE_LAYOUT_INFORMATION DiskGetDriveLayout()
        {
            DRIVE_LAYOUT_INFORMATION_INTERNAL data = DeviceIoControlHelper.InvokeIoControl <DRIVE_LAYOUT_INFORMATION_INTERNAL>(Handle, IOControlCode.DiskGetDriveLayout);

            DRIVE_LAYOUT_INFORMATION res = new DRIVE_LAYOUT_INFORMATION();

            res.PartitionCount = data.PartitionCount;
            res.Signature      = data.Signature;
            res.PartitionEntry = new PARTITION_INFORMATION[res.PartitionCount];

            for (int i = 0; i < res.PartitionCount; i++)
            {
                res.PartitionEntry[i] = data.PartitionEntry[i];
            }

            return(res);
        }
        //FsctlGetHfsInformation

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/aa364568(v=vs.85).aspx"/></summary>
        public NTFS_FILE_RECORD_OUTPUT_BUFFER FileSystemGetNtfsFileRecord(ulong fileId)
        {
            NTFS_FILE_RECORD_INPUT_BUFFER input = new NTFS_FILE_RECORD_INPUT_BUFFER();

            input.FileReferenceNumber = fileId;

            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.FsctlGetNtfsFileRecord, input, 1024);    // NTFS File records are in 1K chunks

            NTFS_FILE_RECORD_OUTPUT_BUFFER res = new NTFS_FILE_RECORD_OUTPUT_BUFFER();

            res.FileReferenceNumber = BitConverter.ToUInt64(data, 0);
            res.FileRecordLength    = BitConverter.ToUInt32(data, 8);

            res.FileRecordBuffer = new byte[res.FileRecordLength];
            Array.Copy(data, 8 + 4, res.FileRecordBuffer, 0, (int)res.FileRecordLength);

            return(res);
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365174(v=vs.85).aspx"/></summary>
        public DRIVE_LAYOUT_INFORMATION_EX DiskGetDriveLayoutEx()
        {
            DRIVE_LAYOUT_INFORMATION_EX_INTERNAL data = DeviceIoControlHelper.InvokeIoControl <DRIVE_LAYOUT_INFORMATION_EX_INTERNAL>(Handle, IOControlCode.DiskGetDriveLayoutEx);

            DRIVE_LAYOUT_INFORMATION_EX res = new DRIVE_LAYOUT_INFORMATION_EX();

            res.PartitionStyle         = data.PartitionStyle;
            res.PartitionCount         = data.PartitionCount;
            res.DriveLayoutInformaiton = data.DriveLayoutInformaiton;
            res.PartitionEntry         = new PARTITION_INFORMATION_EX[res.PartitionCount];

            for (int i = 0; i < res.PartitionCount; i++)
            {
                res.PartitionEntry[i] = data.PartitionEntry[i];
            }

            return(res);
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365171(v=vs.85).aspx"/></summary>
        public DISK_GEOMETRY_EX DiskGetDriveGeometryEx()
        {
            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.DiskGetDriveGeometryEx, 256);

            DISK_GEOMETRY_EX res;

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                res.Geometry = (DISK_GEOMETRY)Marshal.PtrToStructure(mem, typeof(DISK_GEOMETRY));
                res.DiskSize = BitConverter.ToInt64(data, Marshal.SizeOf(typeof(DISK_GEOMETRY)));

                IntPtr tmpPtr = mem.Handle + Marshal.SizeOf(typeof(DISK_GEOMETRY)) + sizeof(long);
                res.PartitionInformation = (DISK_PARTITION_INFO)Marshal.PtrToStructure(tmpPtr, typeof(DISK_PARTITION_INFO));

                tmpPtr           += res.PartitionInformation.SizeOfPartitionInfo;
                res.DiskInt13Info = (DISK_EX_INT13_INFO)Marshal.PtrToStructure(tmpPtr, typeof(DISK_EX_INT13_INFO));
            }

            return(res);
        }
예제 #14
0
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365171(v=vs.85).aspx"/></summary>
        public DISK_GEOMETRY_EX DiskGetDriveGeometryEx()
        {
            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.DiskGetDriveGeometryEx, 256);

            DISK_GEOMETRY_EX res;

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                res.Geometry = mem.Handle.ToStructure <DISK_GEOMETRY>();
                res.DiskSize = BitConverter.ToInt64(data, (int)MarshalHelper.SizeOf <DISK_GEOMETRY>());

                IntPtr tmpPtr = new IntPtr(mem.Handle.ToInt64() + MarshalHelper.SizeOf <DISK_GEOMETRY>() + sizeof(long));
                res.PartitionInformation = tmpPtr.ToStructure <DISK_PARTITION_INFO>();

                tmpPtr            = new IntPtr(tmpPtr.ToInt64() + res.PartitionInformation.SizeOfPartitionInfo);
                res.DiskInt13Info = tmpPtr.ToStructure <DISK_EX_INT13_INFO>();
            }

            return(res);
        }
        /// <summary><see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364586(v=vs.85).aspx"/></summary>
        public IUSN_RECORD[] FileSystemReadUsnJournal(long volumeJournalId, UsnJournalReasonMask reasonMask, USN firstUsn, int bytesToWaitFor = 0, int timeout = 0)
        {
            READ_USN_JOURNAL_DATA_V0 input = new READ_USN_JOURNAL_DATA_V0();

            input.StartUsn       = firstUsn;
            input.UsnJournalId   = volumeJournalId;
            input.ReasonMask     = reasonMask;
            input.BytesToWaitFor = bytesToWaitFor;
            input.Timeout        = timeout;

            int errorCode;

            byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlReadUsnJournal, 1024 * 1024, input, out errorCode);

            List <IUSN_RECORD> res = new List <IUSN_RECORD>();

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                int dataOffset = 8;

                while (dataOffset < data.Length)
                {
                    int         length;
                    IUSN_RECORD rec = ParseUsnRecord(mem, dataOffset, out length);

                    if (length <= 0)
                    {
                        break;
                    }

                    res.Add(rec);

                    // Move to next record
                    dataOffset += length;
                }
            }

            return(res.ToArray());
        }
        //FsctlNssControl
        //FsctlNssRcontrol
        //FsctlOpBatchAckClosePending
        //FsctlOplockBreakAckNo2
        //FsctlOplockBreakAcknowledge
        //FsctlOplockBreakNotify

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364582(v=vs.85).aspx"/></summary>
        public FILE_ALLOCATED_RANGE_BUFFER[] FileSystemQueryAllocatedRanges(long offset, long length)
        {
            FILE_ALLOCATED_RANGE_BUFFER input = new FILE_ALLOCATED_RANGE_BUFFER();

            input.FileOffset = offset;
            input.Length     = offset + length;

            byte[] res = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.FsctlQueryAllocatedRanges, input, 512);

            int singleSize = (int)MarshalHelper.SizeOf <FILE_ALLOCATED_RANGE_BUFFER>();
            List <FILE_ALLOCATED_RANGE_BUFFER> ranges = new List <FILE_ALLOCATED_RANGE_BUFFER>();

            for (int i = 0; i < res.Length; i += singleSize)
            {
                FILE_ALLOCATED_RANGE_BUFFER single = new FILE_ALLOCATED_RANGE_BUFFER();
                single.FileOffset = BitConverter.ToInt64(res, i);
                single.Length     = BitConverter.ToInt64(res, i + 8);

                ranges.Add(single);
            }

            return(ranges.ToArray());
        }
        /// <summary>
        /// <see cref="http://msdn.microsoft.com/en-us/library/windows/hardware/ff560474(v=vs.85).aspx" />
        /// </summary>
        public List <MountPoint> MountQueryPoints()
        {
            MOUNTMGR_MOUNT_POINT input = new MOUNTMGR_MOUNT_POINT();

            byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.MountmgrQueryPoints, input, 512);

            uint mountPoints            = BitConverter.ToUInt32(data, sizeof(uint));
            uint sizeOfMountPointStruct = MarshalHelper.SizeOf <MOUNTMGR_MOUNT_POINT>();

            List <MountPoint> result = new List <MountPoint>();

            using (UnmanagedMemory mem = new UnmanagedMemory(data))
            {
                IntPtr offset = new IntPtr(mem.Handle.ToInt64() + sizeof(uint) * 2);

                for (int i = 0; i < mountPoints; i++)
                {
                    MOUNTMGR_MOUNT_POINT strct = offset.ToStructure <MOUNTMGR_MOUNT_POINT>();

                    MountPoint point = new MountPoint();

                    point.SymbolicLinkName = Encoding.Unicode.GetString(data, (int)strct.SymbolicLinkNameOffset, strct.SymbolicLinkNameLength);
                    point.DeviceName       = Encoding.Unicode.GetString(data, (int)strct.DeviceNameOffset, strct.DeviceNameLength);

                    byte[] idBytes = new byte[strct.UniqueIdLength];
                    Array.Copy(data, (int)strct.UniqueIdOffset, idBytes, 0, idBytes.Length);
                    point.UniqueId = idBytes;

                    result.Add(point);

                    // Advance one
                    offset = new IntPtr(offset.ToInt64() + sizeOfMountPointStruct);
                }
            }

            return(result);
        }
        //FsctlQueryFatBpb
        //FsctlQueryRetrievalPointers
        //FsctlQueryOnDiskVolumeInfo

        //FsctlReadPropertyData
        //FsctlReadRawEncrypted
        //FsctlRecallFile
        //FsctlRequestBatchOplock
        //FsctlRequestFilterOplock
        //FsctlRequestOplockLevel1
        //FsctlRequestOplockLevel2
        //FsctlSecurityIdCheck

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364592(v=vs.85).aspx"/></summary>
        public void FileSystemSetCompression(COMPRESSION_FORMAT level)
        {
            DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlSetCompression, (ushort)level);
        }
예제 #19
0
 /// <summary>
 /// Used to f.ex. close CD Rom trays
 /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363414(v=vs.85).aspx" />
 /// </summary>
 public bool StorageLoadMedia()
 {
     return(DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.StorageLoadMedia));
 }
        //DiskSetDriveLayout
        //DiskSetDriveLayoutEx
        //DiskVerify
        //DiskFormatTracks
        //DiskReassignBlocks
        //DiskPerformance
        //DiskIsWritable
        //DiskLogging
        //DiskFormatTracksEx
        //DiskHistogramStructure
        //DiskHistogramData
        //DiskHistogramReset
        //DiskRequestStructure
        //DiskRequestData
        //DiskControllerNumber

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/hardware/ff566202(v=vs.85).aspx"/></summary>
        public GETVERSIONINPARAMS DiskGetSmartVersion()
        {
            return(DeviceIoControlHelper.InvokeIoControl <GETVERSIONINPARAMS>(Handle, IOControlCode.DiskSmartGetVersion));
        }
        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/dd405526(v=vs.85).aspx"/></summary>
        /// <remarks>
        ///     Does not correcly handle all cases of this method!. Especially regarding compressed/encrypted and/or sparse files in NTFS.
        ///     Consider yourself warned.
        /// </remarks>
        public FileExtentInfo[] FileSystemGetRetrievalPointers()
        {
            STARTING_VCN_INPUT_BUFFER input = new STARTING_VCN_INPUT_BUFFER();

            input.StartingVcn = 0;

            List <FileExtentInfo> extents = new List <FileExtentInfo>();

            uint chunkSize        = 1024;
            uint singleExtentSize = MarshalHelper.SizeOf <RETRIEVAL_POINTERS_EXTENT>();

            int lastError;

            do
            {
                byte[] data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.FsctlGetRetrievalPointers, chunkSize, input, out lastError);

                RETRIEVAL_POINTERS_BUFFER output = new RETRIEVAL_POINTERS_BUFFER();
                output.ExtentCount = BitConverter.ToUInt32(data, 0);
                output.StartingVcn = BitConverter.ToUInt64(data, sizeof(ulong));

                output.Extents = new RETRIEVAL_POINTERS_EXTENT[output.ExtentCount];

                // Parse extents
                int extentsSize = (int)(output.ExtentCount * singleExtentSize);
                using (var dataPtr = new UnmanagedMemory(extentsSize))
                {
                    Marshal.Copy(data, sizeof(ulong) + sizeof(ulong), dataPtr, extentsSize);

                    for (ulong i = 0; i < output.ExtentCount; i++)
                    {
                        IntPtr currentPtr = new IntPtr(dataPtr.Handle.ToInt64() + (int)(singleExtentSize * i));
                        output.Extents[i] = currentPtr.ToStructure <RETRIEVAL_POINTERS_EXTENT>();
                    }
                }

                // Make extents more readable
                for (ulong i = 0; i < output.ExtentCount; i++)
                {
                    ulong startVcn = i == 0
                        ? output.StartingVcn
                        : output.Extents[i - 1].NextVcn;

                    ulong size = output.Extents[i].NextVcn - startVcn;

                    FileExtentInfo extent = new FileExtentInfo();
                    extent.Size = size;
                    extent.Vcn  = startVcn;
                    extent.Lcn  = output.Extents[i].Lcn;

                    extents.Add(extent);
                }

                if (lastError == 38)
                {
                    // End of file reached
                    break;
                }

                // Prep the start point for the next call
                input.StartingVcn = output.Extents[output.ExtentCount - 1].NextVcn;
            } while (lastError == 234);

            return(extents.ToArray());
        }
        //FsctlFindFilesBySid

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364567(v=vs.85).aspx"/></summary>
        public COMPRESSION_FORMAT FileSystemGetCompression()
        {
            return((COMPRESSION_FORMAT)DeviceIoControlHelper.InvokeIoControl <ushort>(Handle, IOControlCode.FsctlGetCompression));
        }
        //DiskSmartSendDriveCommand
        //DiskSmartRcvDriveData
        //DiskUpdateDriveSize
        //DiskGrowPartition

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365165(v=vs.85).aspx"/></summary>
        public DISK_CACHE_INFORMATION DiskGetCacheInformation()
        {
            return(DeviceIoControlHelper.InvokeIoControl <DISK_CACHE_INFORMATION>(Handle, IOControlCode.DiskGetCacheInformation));
        }
        //DiskSetCacheInformation
        //DiskDeleteDriveLayout
        //DiskFormatDrive
        //DiskSenseDevice
        //DiskCheckVerify
        //DiskMediaRemoval
        //DiskEjectMedia
        //DiskLoadMedia
        //DiskReserve
        //DiskRelease
        //DiskFindNewDevices
        //DiskCreateDisk

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365178(v=vs.85).aspx"/></summary>
        public long DiskGetLengthInfo()
        {
            return(DeviceIoControlHelper.InvokeIoControl <GET_LENGTH_INFORMATION>(Handle, IOControlCode.DiskGetLengthInfo).Length);
        }
 /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/hh706681(v=vs.85).aspx"/></summary>
 public GET_DISK_ATTRIBUTES DiskGetDiskAttributes()
 {
     return(DeviceIoControlHelper.InvokeIoControl <GET_DISK_ATTRIBUTES>(Handle, IOControlCode.DiskGetDiskAttributes));
 }
 /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365180(v=vs.85).aspx"/></summary>
 public PARTITION_INFORMATION_EX DiskGetPartitionInfoEx()
 {
     return(DeviceIoControlHelper.InvokeIoControl <PARTITION_INFORMATION_EX>(Handle, IOControlCode.DiskGetPartitionInfoEx));
 }
        /// <summary><see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364583(v=vs.85).aspx"/></summary>
        public USN_JOURNAL_DATA_V0 FileSystemQueryUsnJournal()
        {
            USN_JOURNAL_DATA_V0 res = DeviceIoControlHelper.InvokeIoControl <USN_JOURNAL_DATA_V0>(Handle, IOControlCode.FsctlQueryUsnJournal);

            return(res);
        }
 /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364569(v=vs.85).aspx"/></summary>
 public NTFS_VOLUME_DATA_BUFFER FileSystemGetNtfsVolumeData()
 {
     return(DeviceIoControlHelper.InvokeIoControl <NTFS_VOLUME_DATA_BUFFER>(Handle, IOControlCode.FsctlGetNtfsVolumeData));
 }
        //FsctlGetObjectId
        //FsctlGetReparsePoint

        /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/dd405526(v=vs.85).aspx"/></summary>
        public RETRIEVAL_POINTER_BASE FileSystemGetRetrievalPointerBase()
        {
            return(DeviceIoControlHelper.InvokeIoControl <RETRIEVAL_POINTER_BASE>(Handle, IOControlCode.FsctlGetRetrievalPointerBase));
        }
 /// <summary><see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365169(v=vs.85).aspx"/></summary>
 public DISK_GEOMETRY DiskGetDriveGeometry()
 {
     return(DeviceIoControlHelper.InvokeIoControl <DISK_GEOMETRY>(Handle, IOControlCode.DiskGetDriveGeometry));
 }