示例#1
0
 /// <summary>
 /// IOCTL_ATA_PASS_THROUGH IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_ata_pass_through )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <param name="Header"></param>
 /// <param name="Data"></param>
 /// <returns></returns>
 public static bool AtaPassThroughIdentifyDevice(this IoControl IoControl, out IAtaPassThroughEx <IdentifyDevice> value, out uint ReturnBytes)
 {
     if (IntPtr.Size == 4)
     {
         var ptr = new StructPtr <AtaPassThroughEx32WithIdentifyDevice>(new AtaPassThroughEx32WithIdentifyDevice(
                                                                            AtaFlags: AtaFlags.DataIn | AtaFlags.NoMultiple,
                                                                            TimeOutValue: 3,
                                                                            Feature: 0,
                                                                            Cylinder: 0,
                                                                            Command: 0xEC
                                                                            ));
         var result = IoControl.AtaPassThrough(ptr, out ReturnBytes);
         value = ptr.Get();
         return(result);
     }
     else if (IntPtr.Size == 8)
     {
         var ptr = new StructPtr <AtaPassThroughExWithIdentifyDevice>(new AtaPassThroughExWithIdentifyDevice(
                                                                          AtaFlags: AtaFlags.DataIn | AtaFlags.NoMultiple,
                                                                          TimeOutValue: 3,
                                                                          Feature: 0,
                                                                          Cylinder: 0,
                                                                          Command: 0xEC
                                                                          ));
         var result = IoControl.AtaPassThrough(ptr, out ReturnBytes);
         value = ptr.Get();
         return(result);
     }
     throw new NotSupportedException();
 }
示例#2
0
        public void SmartGetVersionTest(IoControl IoControl)
        {
            var result = IoControl.SmartGetVersion(out var Version);

            Trace.WriteLine($"{nameof(result)}:{result}");
            Trace.WriteLine(Version);
        }
示例#3
0
 /// <summary>
 /// IOCTL_VOLUME_OFFLINE IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddvol/ni-ntddvol-ioctl_volume_offline )
 /// </summary>
 /// <param name="IoControl"></param>
 public static void VolumeOffline(this IoControl IoControl)
 {
     if (!IoControl.DeviceIoControl(IOControlCode.VolumeOffline, out var _))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
 }
 public void StorageGetMediaTypesTest(IoControl IoControl)
 {
     foreach (var MediaType in IoControl.StorageGetMediaTypes())
     {
         Trace.WriteLine(MediaType);
     }
 }
示例#5
0
 /// <summary>
 /// IOCTL_ATA_PASS_THROUGH IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_ata_pass_through )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <param name="Header"></param>
 /// <param name="Data"></param>
 /// <returns></returns>
 public static bool AtaPassThroughSmartData(this IoControl IoControl, out IAtaPassThroughEx <SmartData> value, out uint ReturnBytes)
 {
     if (IntPtr.Size == 4)
     {
         var request = new AtaPassThroughEx32WithSmartData(
             AtaFlags: AtaFlags.DataIn | AtaFlags.NoMultiple,
             TimeOutValue: 3,
             Feature: 0xd0,
             Cylinder: 0xc24f,
             Command: 0xb0
             );
         System.Diagnostics.Debug.Assert(request.DataTransferLength == 512, "データが不正");
         var ptr    = new StructPtr <AtaPassThroughEx32WithSmartData>(request);
         var result = IoControl.AtaPassThrough(ptr, out ReturnBytes);
         value = ptr.Get();
         return(result);
     }
     else if (IntPtr.Size == 8)
     {
         var request = new AtaPassThroughExWithSmartData(
             AtaFlags: AtaFlags.DataIn | AtaFlags.NoMultiple,
             TimeOutValue: 3,
             Feature: 0xd0,
             Cylinder: 0xc24f,
             Command: 0xb0
             );
         System.Diagnostics.Debug.Assert(request.DataTransferLength == 512, "データが不正");
         var ptr    = new StructPtr <AtaPassThroughExWithSmartData>(request);
         var result = IoControl.AtaPassThrough(ptr, out ReturnBytes);
         value = ptr.Get();
         return(result);
     }
     throw new NotSupportedException();
 }
示例#6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="IoControl"></param>
 /// <param name="AtaFlags"></param>
 /// <param name="PathId"></param>
 /// <param name="TargetId"></param>
 /// <param name="Lun"></param>
 /// <param name="ReservedAsUchar"></param>
 /// <param name="TimeOutValue"></param>
 /// <param name="ReservedAsUlong"></param>
 /// <param name="Feature"></param>
 /// <param name="SectorCouont"></param>
 /// <param name="SectorNumber"></param>
 /// <param name="Cylinder"></param>
 /// <param name="DeviceHead"></param>
 /// <param name="Command"></param>
 /// <param name="Reserved"></param>
 /// <param name="DataSize"></param>
 /// <returns></returns>
 public static (IAtaPassThroughEx Header, byte[] Data) AtaPassThrough(this IoControl IoControl, AtaFlags AtaFlags, byte PathId = default, byte TargetId = default, byte Lun = default, byte ReservedAsUchar = default, uint TimeOutValue = default, uint ReservedAsUlong = default, ushort Feature = default, ushort SectorCouont = default, ushort SectorNumber = default, uint Cylinder = default, byte DeviceHead = default, byte Command = default, ushort Reserved = default, uint DataSize = default)
 {
     if (!AtaPassThrough(IoControl,
                         Header: out var Header,
                         Data: out var Data,
                         AtaFlags: AtaFlags,
                         PathId: PathId,
                         TargetId: TargetId,
                         Lun: Lun,
                         ReservedAsUchar: ReservedAsUchar,
                         TimeOutValue: TimeOutValue,
                         ReservedAsUlong: ReservedAsUlong,
                         Feature: Feature,
                         SectorCouont: SectorCouont,
                         SectorNumber: SectorNumber,
                         Cylinder: Cylinder,
                         DeviceHead: DeviceHead,
                         Command: Command,
                         Reserved: Reserved,
                         DataSize: DataSize))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(Header, Data);
 }
示例#7
0
        /// <summary>
        /// IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddvol/ni-ntddvol-ioctl_volume_get_volume_disk_extents )
        /// </summary>
        /// <param name="IoControl"></param>
        /// <param name="extent"></param>
        public static bool VolumeGetVolumeDiskExtents(this IoControl IoControl, out VolumeDiskExtent extent, out uint ReturnBytes)
        {
            var Size   = (uint)Marshal.SizeOf(typeof(VolumeDiskExtent));
            var OutPtr = Marshal.AllocCoTaskMem((int)Size);

            using (Disposable.Create(() => Marshal.FreeCoTaskMem(OutPtr)))
            {
                var get_volume_disk_result = IoControl.DeviceIoControlOutOnly(IOControlCode.VolumeGetVolumeDiskExtents, OutPtr, Size, out ReturnBytes);
                extent = new VolumeDiskExtent(OutPtr, ReturnBytes);
                if (get_volume_disk_result && extent.NumberOfDiskExtents == 1)
                {
                    return(get_volume_disk_result);
                }
                if (extent.NumberOfDiskExtents == 0 || extent.NumberOfDiskExtents == (uint)extent.Extents.Length)
                {
                    return(get_volume_disk_result);
                }
            }
            Size   = (uint)(Marshal.SizeOf(typeof(VolumeDiskExtent)) + Marshal.SizeOf(typeof(DiskExtent)) * (extent.NumberOfDiskExtents - 1));
            OutPtr = Marshal.AllocCoTaskMem((int)Size);
            using (Disposable.Create(() => Marshal.FreeCoTaskMem(OutPtr)))
            {
                var devide_ioc_result = IoControl.DeviceIoControlOutOnly(IOControlCode.VolumeGetVolumeDiskExtents, OutPtr, Size, out ReturnBytes);
                extent = new VolumeDiskExtent(OutPtr, ReturnBytes);
                return(devide_ioc_result);
            }
        }
示例#8
0
 /// <summary>
 /// IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddvol/ni-ntddvol-ioctl_volume_get_volume_disk_extents )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static VolumeDiskExtent VolumeGetVolumeDiskExtents(this IoControl IoControl)
 {
     if (!VolumeGetVolumeDiskExtents(IoControl, out var extent, out var ReturnBytes) && ReturnBytes == 0)
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(extent);
 }
示例#9
0
 /// <summary>
 /// IOCTL_SCSI_GET_INQUIRY_DATA IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_scsi_get_inquiry_data )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static ScsiAdapterBusInfo ScsiGetInquiryData(this IoControl IoControl)
 {
     if (!IoControl.ScsiGetInquiryData(out var info))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(info);
 }
示例#10
0
 public static IdentifyDevice ScsiMiniportIdentify(this IoControl IoControl, byte TargetId)
 {
     if (!IoControl.ScsiMiniportIdentify(TargetId, out var IdentifyDevice))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(IdentifyDevice);
 }
示例#11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="IoControl"></param>
 /// <param name="AtaFlags"></param>
 /// <param name="PathId"></param>
 /// <param name="TargetId"></param>
 /// <param name="Lun"></param>
 /// <param name="ReservedAsUchar"></param>
 /// <param name="TimeOutValue"></param>
 /// <param name="ReservedAsUlong"></param>
 /// <param name="DataTransferLength"></param>
 /// <param name="DataBuffer"></param>
 /// <param name="Feature"></param>
 /// <param name="SectorCouont"></param>
 /// <param name="SectorNumber"></param>
 /// <param name="Cylinder"></param>
 /// <param name="DeviceHead"></param>
 /// <param name="Command"></param>
 /// <param name="Reserved"></param>
 /// <returns></returns>
 public static AtaPassThroughDirect AtaPassThroughDirect(this IoControl IoControl, AtaFlags AtaFlags = default, byte PathId = default, byte TargetId = default, byte Lun = default, byte ReservedAsUchar = default, uint TimeOutValue = default, uint ReservedAsUlong = default, uint DataTransferLength = default, IntPtr DataBuffer = default, ushort Feature = default, ushort SectorCouont = default, ushort SectorNumber = default, uint Cylinder = default, byte DeviceHead = default, byte Command = default, ushort Reserved = default)
 {
     if (!AtaPassThroughDirect(IoControl, out var Header, AtaFlags, PathId, TargetId, Lun, ReservedAsUchar, TimeOutValue, ReservedAsUlong, DataTransferLength, DataBuffer, Feature, SectorCouont, SectorNumber, Cylinder, DeviceHead, Command, Reserved))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(Header);
 }
示例#12
0
        /// <summary>
        /// IOCTL_SCSI_GET_INQUIRY_DATA IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_scsi_get_inquiry_data )
        /// </summary>
        /// <param name="IoControl"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        public static bool ScsiGetInquiryData(this IoControl IoControl, out ScsiAdapterBusInfo info)
        {
            var data   = new DataUtils.AnySizeStruct <ScsiAdapterBusInfo>();
            var result = IoControl.DeviceIoControlOutOnly(IOControlCode.ScsiGetInquiryData, data, out var ReturnBytes);

            info = data.Get();
            return(result);
        }
示例#13
0
 public static IAtaPassThroughEx AtaPassThroughCheckPowerMode(this IoControl IoControl)
 {
     if (!IoControl.AtaPassThroughCheckPowerMode(out var result, out var ReturnBytes))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(result);
 }
示例#14
0
        /// <summary>
        /// IOCTL_ATA_PASS_THROUGH IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_ata_pass_through )
        /// </summary>
        /// <param name="IoControl"></param>
        /// <returns></returns>

        public static IAtaPassThroughEx <SmartData> AtaPassThroughSmartData(this IoControl IoControl)
        {
            if (!IoControl.AtaPassThroughSmartData(out var result, out var ReturnBytes))
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            return(result);
        }
示例#15
0
 public static PartitionInformationEx DiskGetPartitionInfoEx(this IoControl IoControl)
 {
     if (!DiskGetPartitionInfoEx(IoControl, out var partition, out var ReturnBytes) && ReturnBytes > 0)
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(partition);
 }
示例#16
0
 /// <summary>
 /// IOCTL_SCSI_GET_ADDRESS IOCTL ( https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_scsi_get_address )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static ScsiAddress ScsiGetAddress(this IoControl IoControl)
 {
     if (!ScsiGetAddress(IoControl, out var address))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(address);
 }
示例#17
0
 /// <summary>
 /// IOCTL_STORAGE_GET_DEVICE_NUMBER_EX IOCTL
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static StorageDeviceNumberEx StorageGetDeviceNumberEx(this IoControl IoControl)
 {
     if (!StorageGetDeviceNumberEx(IoControl, out var number, out var ReturnBytes) && ReturnBytes == 0)
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(number);
 }
示例#18
0
 /// <summary>
 /// IOCTL_DISK_GET_CACHE_INFORMATION IOCTL ( https://docs.microsoft.com/en-us/windows/desktop/api/WinIoCtl/ni-winioctl-ioctl_disk_get_cache_information )
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static DiskCacheInformation DiskGetCacheInformation(this IoControl IoControl)
 {
     if (!DiskGetCacheInformation(IoControl, out var information))
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(information);
 }
示例#19
0
 /// <summary>
 /// IOCTL_STORAGE_GET_HOTPLUG_INFO IOCTL
 /// </summary>
 /// <param name="IoControl"></param>
 /// <returns></returns>
 public static StorageHotplugInfo StorageGetHotplugInfo(this IoControl IoControl)
 {
     if (!StorageGetHotplugInfo(IoControl, out var info, out var ReturnBytes) && ReturnBytes == 0)
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(info);
 }
示例#20
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="IoControl"></param>
 /// <param name="PropertyId"></param>
 /// <param name="QueryType"></param>
 /// <param name="AdditionalParameters"></param>
 /// <returns></returns>
 public static IStorageDescriptor StorageQueryProperty(this IoControl IoControl, StoragePropertyId PropertyId, StorageQueryType QueryType = default, params byte[] AdditionalParameters)
 {
     if (!StorageQueryProperty(IoControl, PropertyId, QueryType, AdditionalParameters, out var descriptor, out var ReturnBytes) && ReturnBytes == 0)
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
     return(descriptor);
 }
示例#21
0
        /// <summary>
        /// FSCTL_DISMOUNT_VOLUME control code ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa364562.aspx )
        /// </summary>
        /// <param name="IoControl"></param>
        public static void FsctlDismountVolume(this IoControl IoControl)
        {
            var result = IoControl.DeviceIoControl(IOControlCode.FsctlDismountVolume, out var _);

            if (!result)
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
        }
示例#22
0
        /// <summary>
        /// IOCTL_VOLUME_QUERY_VOLUME_NUMBER IOCTL
        /// </summary>
        /// <param name="IoControl"></param>
        /// <param name="number"></param>
        public static void VolumeQueryVolumeNumber(this IoControl IoControl, out VolumeNumber number)
        {
            var result = IoControl.DeviceIoControlOutOnly(IOControlCode.VolumeQueryVolumeNumber, out number, out var ReturnBytes);

            if (!result)
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
        }
示例#23
0
        public void FsctlIsVolumeMountedTest(IoControl IoControl, bool?result)
        {
            var _result = IoControl.FsctlIsVolumeMounted();

            Trace.WriteLine(_result);
            if (result is bool Result)
            {
                Assert.AreEqual(Result, _result);
            }
        }
示例#24
0
        public void QuitView()
        {
            //サーボ終了処理
            SvControl.Close();

            //I/O終了処理
            IoControl.Close();
            //生成したスレッドの終了(フラグを立てる)
            _threadStop = 1;
        }
示例#25
0
 public void DiskGetDriveGeometryTest(IoControl IoControl)
 {
     if (IoControl.DiskGetDriveGeometry() is DiskGeometry DiskGeometry)
     {
         Trace.WriteLine(DiskGeometry);
     }
     else
     {
         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     }
 }
示例#26
0
 public void NewIoControlTest(string Path, FileAccess FileAccess = default, FileShare FileShare = default, FileMode CreationDisposition = default, FileFlagAndAttributes FlagAndAttributes = default)
 {
     using (var IoControl = new IoControl(Path, FileAccess, FileShare, CreationDisposition, FlagAndAttributes))
     {
         if (IoControl.IsInvalid)
         {
             Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
         }
         Trace.WriteLine(IoControl);
     }
 }
示例#27
0
 public async Task DiskGetDriveGeometryAsyncTest(IoControl IoControl)
 {
     using (var Source = new CancellationTokenSource(TimeSpan.FromSeconds(1)))
         if (await IoControl.DiskGetDriveGeometryAsync(Source.Token) is DiskGeometry DiskGeometry)
         {
             Trace.WriteLine(DiskGeometry);
         }
         else
         {
             Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
         }
 }
示例#28
0
        private static bool VolumeIs(IoControl IoControl, IOControlCode IOControlCode, params uint[] NotErrorCodes)
        {
            var result = IoControl.DeviceIoControl(IOControlCode, out var _);

            if (!result)
            {
                var win32error = Marshal.GetHRForLastWin32Error();
                if (!NotErrorCodes.Any(ErrorCode => unchecked ((uint)win32error) == ErrorCode))
                {
                    Marshal.ThrowExceptionForHR(win32error);
                }
            }
            return(result);
        }
示例#29
0
        /// <summary>
        /// IOCTL_VOLUME_QUERY_FAILOVER_SET IOCTL
        /// </summary>
        /// <param name="IoControl"></param>
        /// <param name="set"></param>
        public static void VolumeQueryFailoverSet(this IoControl IoControl, out VolumeFailoverSet set)
        {
            const int ERROR_INSUFFICIENT_BUFFER = 122;
            const int ERROR_MORE_DATA           = 234;
            var       Size   = (uint)Marshal.SizeOf(typeof(VolumeFailoverSet));
            var       OutPtr = Marshal.AllocCoTaskMem((int)Size);

            using (Disposable.Create(() => Marshal.FreeCoTaskMem(OutPtr)))
            {
                var get_volume_disk_result = IoControl.DeviceIoControlOutOnly(IOControlCode.VolumeGetVolumeDiskExtents, OutPtr, Size, out var ReturnBytes);
                var query_size_error       = Marshal.GetHRForLastWin32Error();
                System.Diagnostics.Trace.WriteLine($"{nameof(get_volume_disk_result)}:{get_volume_disk_result}");
                System.Diagnostics.Trace.WriteLine($"{nameof(ReturnBytes)}:{ReturnBytes}");
                System.Diagnostics.Trace.WriteLine($"{nameof(query_size_error)}:0x{unchecked((uint)query_size_error):X8}");
                set = (VolumeFailoverSet)Marshal.PtrToStructure(OutPtr, typeof(VolumeFailoverSet));
                System.Diagnostics.Trace.WriteLine($"{nameof(set.NumberOfDisks)}:{set.NumberOfDisks}");
                if (get_volume_disk_result && set.NumberOfDisks == 0)
                {
                    set.DiskNumbers = new uint[0];
                    return;
                }
                if (get_volume_disk_result && set.NumberOfDisks == 1)
                {
                    return;
                }
                if (query_size_error != ERROR_INSUFFICIENT_BUFFER && query_size_error != ERROR_MORE_DATA)
                {
                    Marshal.ThrowExceptionForHR(query_size_error);
                    return;
                }
            }
            Size   = (uint)(Marshal.SizeOf(typeof(VolumeFailoverSet)) + sizeof(uint) * (set.NumberOfDisks - 1));
            OutPtr = Marshal.AllocCoTaskMem((int)Size);
            using (Disposable.Create(() => Marshal.FreeCoTaskMem(OutPtr)))
            {
                var devide_ioc_result = IoControl.DeviceIoControlOutOnly(IOControlCode.VolumeGetVolumeDiskExtents, OutPtr, Size, out var ReturnBytes);
                if (!devide_ioc_result)
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }
                set = (VolumeFailoverSet)Marshal.PtrToStructure(OutPtr, typeof(VolumeFailoverSet));
                var ExtentsPtr = IntPtr.Add(OutPtr, Marshal.OffsetOf <VolumeFailoverSet>(nameof(VolumeFailoverSet.DiskNumbers)).ToInt32());
                var ExtentSize = Marshal.SizeOf(typeof(DiskExtent));
                set.DiskNumbers = Enumerable
                                  .Range(0, (int)set.NumberOfDisks)
                                  .Select(index => (uint)Marshal.PtrToStructure(IntPtr.Add(ExtentsPtr, ExtentSize * index), typeof(uint)))
                                  .ToArray();
                return;
            }
        }
示例#30
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="IoControl"></param>
        /// <param name="PropertyId"></param>
        /// <param name="QueryType"></param>
        /// <param name="AdditionalParameters"></param>
        /// <param name="descriptor"></param>
        /// <param name="ReturnBytes"></param>
        /// <returns></returns>
        public static bool StorageQueryProperty(this IoControl IoControl, StoragePropertyId PropertyId, StorageQueryType QueryType, byte[] AdditionalParameters, out IStorageDescriptor descriptor, out uint ReturnBytes)
        {
            var genericType = PropertyId.GetDestType() ?? typeof(StorageDescriptor);

            var query    = new StoragePropertyQuery(PropertyId, QueryType, AdditionalParameters);
            var argument = new object[] { IoControl, query, null, null };
            var result   = (bool)typeof(MassStorageExtensions)
                           .GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)
                           .FirstOrDefault(mi => mi.Name == nameof(StorageQueryProperty) && mi.IsGenericMethodDefinition)
                           .MakeGenericMethod(genericType)
                           .Invoke(null, argument);

            descriptor  = (IStorageDescriptor)argument[2];
            ReturnBytes = (uint)argument[3];
            return(result);
        }