diff --git a/DeviceIOControlLib/DeviceIOControlLib.csproj b/DeviceIOControlLib/DeviceIOControlLib.csproj
index 48e3b3f..ffbb04e 100644
--- a/DeviceIOControlLib/DeviceIOControlLib.csproj
+++ b/DeviceIOControlLib/DeviceIOControlLib.csproj
@@ -1,19 +1,10 @@
- netstandard1.3;netstandard2.0
+ net8.0-windows;net9.0-windows;net10.0-windows
Library to interact with Windows' DeviceIoControl method
Win32 DeviceIoControl
+ True
-
-
-
-
-
-
-
-
-
-
diff --git a/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_EX_INTERNAL.cs b/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_EX_INTERNAL.cs
index 8c538d5..38ecb9f 100644
--- a/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_EX_INTERNAL.cs
+++ b/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_EX_INTERNAL.cs
@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using DeviceIOControlLib.Objects.Enums;
@@ -10,7 +11,5 @@ internal struct DRIVE_LAYOUT_INFORMATION_EX_INTERNAL
public PartitionStyle PartitionStyle;
public int PartitionCount;
public DRIVE_LAYOUT_INFORMATION_UNION DriveLayoutInformaiton;
- [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 128)]
- public PARTITION_INFORMATION_EX[] PartitionEntry;
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_INTERNAL.cs b/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_INTERNAL.cs
index 07b4027..fc60465 100644
--- a/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_INTERNAL.cs
+++ b/DeviceIOControlLib/Objects/Disk/DRIVE_LAYOUT_INFORMATION_INTERNAL.cs
@@ -7,7 +7,5 @@ internal struct DRIVE_LAYOUT_INFORMATION_INTERNAL
{
public int PartitionCount;
public uint Signature;
- [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 128)]
- public PARTITION_INFORMATION[] PartitionEntry;
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Disk/GETVERSIONINPARAMS.cs b/DeviceIOControlLib/Objects/Disk/GETVERSIONINPARAMS.cs
index adbb9ee..0664aeb 100644
--- a/DeviceIOControlLib/Objects/Disk/GETVERSIONINPARAMS.cs
+++ b/DeviceIOControlLib/Objects/Disk/GETVERSIONINPARAMS.cs
@@ -3,14 +3,13 @@
namespace DeviceIOControlLib.Objects.Disk
{
[StructLayout(LayoutKind.Sequential)]
- public struct GETVERSIONINPARAMS
+ public unsafe struct GETVERSIONINPARAMS
{
public byte bVersion;
public byte bRevision;
public byte bReserved;
public byte bIDEDeviceMap;
public ulong fCapabilities;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
- public ulong[] dwReserved;
+ public fixed ulong dwReserved[4];
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Disk/PARTITION_INFORMATION_GPT.cs b/DeviceIOControlLib/Objects/Disk/PARTITION_INFORMATION_GPT.cs
index 6ac7373..69a5a4f 100644
--- a/DeviceIOControlLib/Objects/Disk/PARTITION_INFORMATION_GPT.cs
+++ b/DeviceIOControlLib/Objects/Disk/PARTITION_INFORMATION_GPT.cs
@@ -5,7 +5,7 @@
namespace DeviceIOControlLib.Objects.Disk
{
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct PARTITION_INFORMATION_GPT
+ public unsafe struct PARTITION_INFORMATION_GPT
{
[FieldOffset(0)]
public Guid PartitionType;
@@ -15,7 +15,6 @@ public struct PARTITION_INFORMATION_GPT
[MarshalAs(UnmanagedType.U8)]
public EFIPartitionAttributes Attributes;
[FieldOffset(40)]
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
- public string Name;
+ public fixed char Name[36];
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR.cs b/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR.cs
index 2dbc5bd..4912bf8 100644
--- a/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR.cs
+++ b/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR.cs
@@ -3,7 +3,7 @@
namespace DeviceIOControlLib.Objects.Storage
{
[StructLayout(LayoutKind.Sequential)]
- public struct STORAGE_DEVICE_DESCRIPTOR
+ public unsafe struct STORAGE_DEVICE_DESCRIPTOR
{
public uint Version;
public uint Size;
@@ -20,6 +20,6 @@ public struct STORAGE_DEVICE_DESCRIPTOR
public STORAGE_BUS_TYPE BusType;
public uint RawPropertiesLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x16)]
- public byte[] RawDeviceProperties;
+ public fixed byte RawDeviceProperties[0x16];
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR_PARSED.cs b/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR_PARSED.cs
index 4112135..e05ca1d 100644
--- a/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR_PARSED.cs
+++ b/DeviceIOControlLib/Objects/Storage/STORAGE_DEVICE_DESCRIPTOR_PARSED.cs
@@ -3,7 +3,7 @@
namespace DeviceIOControlLib.Objects.Storage
{
[StructLayout(LayoutKind.Sequential)]
- public struct STORAGE_DEVICE_DESCRIPTOR_PARSED
+ public unsafe struct STORAGE_DEVICE_DESCRIPTOR_PARSED
{
public uint Version;
public uint Size;
@@ -20,7 +20,7 @@ public struct STORAGE_DEVICE_DESCRIPTOR_PARSED
public STORAGE_BUS_TYPE BusType;
public uint RawPropertiesLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x16)]
- public byte[] RawDeviceProperties;
+ public fixed byte RawDeviceProperties[0x16];
public string SerialNumber;
public string VendorId;
public string ProductId;
diff --git a/DeviceIOControlLib/Objects/Storage/STORAGE_PROPERTY_QUERY.cs b/DeviceIOControlLib/Objects/Storage/STORAGE_PROPERTY_QUERY.cs
index 4a45790..3051222 100644
--- a/DeviceIOControlLib/Objects/Storage/STORAGE_PROPERTY_QUERY.cs
+++ b/DeviceIOControlLib/Objects/Storage/STORAGE_PROPERTY_QUERY.cs
@@ -3,10 +3,10 @@
namespace DeviceIOControlLib.Objects.Storage
{
[StructLayout(LayoutKind.Sequential)]
- public struct STORAGE_PROPERTY_QUERY
+ public unsafe struct STORAGE_PROPERTY_QUERY
{
public STORAGE_PROPERTY_ID PropertyId;
public STORAGE_QUERY_TYPE QueryType;
- public byte[] AdditionalParameters;
+ public byte* AdditionalParameters;
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Usn/USN_RECORD_V2.cs b/DeviceIOControlLib/Objects/Usn/USN_RECORD_V2.cs
index 448b356..cba221b 100644
--- a/DeviceIOControlLib/Objects/Usn/USN_RECORD_V2.cs
+++ b/DeviceIOControlLib/Objects/Usn/USN_RECORD_V2.cs
@@ -4,7 +4,7 @@
namespace DeviceIOControlLib.Objects.Usn
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct USN_RECORD_V2 : IUSN_RECORD
+ public unsafe struct USN_RECORD_V2 : IUSN_RECORD
{
private uint _recordLength;
private ushort _majorVersion;
@@ -19,8 +19,7 @@ public struct USN_RECORD_V2 : IUSN_RECORD
private FileAttributes _fileAttributes;
private ushort _fileNameLength;
private ushort _fileNameOffset;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
- private string _fileName;
+ private fixed char _fileName[1];
public uint RecordLength
{
@@ -89,8 +88,20 @@ public ushort FileNameOffset
}
public string FileName
{
- get { return _fileName; }
- set { _fileName = value; }
+ get
+ {
+ fixed(char* fileNamePtr = _fileName)
+ {
+ return new string(fileNamePtr, 0, 1);
+ }
+ }
+ set
+ {
+ fixed(char * fileNamePtr = _fileName)
+ {
+ fileNamePtr[0] = value[0];
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Objects/Usn/USN_RECORD_V3.cs b/DeviceIOControlLib/Objects/Usn/USN_RECORD_V3.cs
index 3937f09..ca12dc8 100644
--- a/DeviceIOControlLib/Objects/Usn/USN_RECORD_V3.cs
+++ b/DeviceIOControlLib/Objects/Usn/USN_RECORD_V3.cs
@@ -1,18 +1,17 @@
+using System;
using System.Runtime.InteropServices;
using DeviceIOControlLib.Objects.Enums;
namespace DeviceIOControlLib.Objects.Usn
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct USN_RECORD_V3 : IUSN_RECORD
+ public unsafe struct USN_RECORD_V3 : IUSN_RECORD
{
internal uint _recordLength;
internal ushort _majorVersion;
internal ushort _minorVersion;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public byte[] _fileReferenceNumber;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
- public byte[] _parentFileReferenceNumber;
+ public fixed byte _fileReferenceNumber[16];
+ public fixed byte _parentFileReferenceNumber[16];
public long _usn;
public ulong _timeStamp;
public UsnJournalReasonMask _reason;
@@ -21,8 +20,7 @@ public struct USN_RECORD_V3 : IUSN_RECORD
public FileAttributes _fileAttributes;
public ushort _fileNameLength;
public ushort _fileNameOffset;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
- public string _fileName;
+ public fixed char _fileName[1];
public uint RecordLength
{
@@ -41,13 +39,48 @@ public ushort MinorVersion
}
public byte[] FileReferenceNumber
{
- get { return _fileReferenceNumber; }
- set { _fileReferenceNumber = value; }
+ get
+ {
+ byte[] fileReferenceNumber = new byte[16];
+ fixed (byte* fileReferenceNumberDst = fileReferenceNumber)
+ fixed (byte* fileReferenceNumberSrc = _fileReferenceNumber)
+ {
+ Buffer.MemoryCopy(fileReferenceNumberSrc, fileReferenceNumberDst, 16, 16);
+ }
+
+ return fileReferenceNumber;
+ }
+ set
+ {
+ fixed (byte* fileReferenceNumberDst = _fileReferenceNumber)
+ fixed (byte* fileReferenceNumberSrc = value)
+ {
+ Buffer.MemoryCopy(fileReferenceNumberSrc, fileReferenceNumberDst, 16, 16);
+ }
+ }
}
+
public byte[] ParentFileReferenceNumber
{
- get { return _parentFileReferenceNumber; }
- set { _parentFileReferenceNumber = value; }
+ get
+ {
+ byte[] parentFileReferenceNumber = new byte[16];
+ fixed (byte* parentFileReferenceNumberDst = parentFileReferenceNumber)
+ fixed (byte* parentFileReferenceNumberSrc = _parentFileReferenceNumber)
+ {
+ Buffer.MemoryCopy(parentFileReferenceNumberSrc, parentFileReferenceNumberDst, 16, 16);
+ }
+
+ return parentFileReferenceNumber;
+ }
+ set
+ {
+ fixed (byte* parentFileReferenceNumberDst = _parentFileReferenceNumber)
+ fixed (byte* parentFileReferenceNumberSrc = value)
+ {
+ Buffer.MemoryCopy(parentFileReferenceNumberSrc, parentFileReferenceNumberDst, 16, 16);
+ }
+ }
}
public USN Usn
{
@@ -91,8 +124,20 @@ public ushort FileNameOffset
}
public string FileName
{
- get { return _fileName; }
- set { _fileName = value; }
+ get
+ {
+ fixed (char* fileNamePtr = _fileName)
+ {
+ return new string(fileNamePtr, 0, 1);
+ }
+ }
+ set
+ {
+ fixed (char* fileNamePtr = _fileName)
+ {
+ fileNamePtr[0] = value[0];
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Utilities/MarshalHelper.cs b/DeviceIOControlLib/Utilities/MarshalHelper.cs
index d9a21d1..ea8f191 100644
--- a/DeviceIOControlLib/Utilities/MarshalHelper.cs
+++ b/DeviceIOControlLib/Utilities/MarshalHelper.cs
@@ -5,22 +5,14 @@ namespace DeviceIOControlLib.Utilities
{
internal static class MarshalHelper
{
- public static T ToStructure(this IntPtr ptr)
+ public static unsafe T ToStructure(this IntPtr ptr) where T : unmanaged
{
-#if NETCORE
- return Marshal.PtrToStructure(ptr);
-#else
- return (T)Marshal.PtrToStructure(ptr, typeof(T));
-#endif
+ return *(T*)ptr.ToPointer();
}
- public static uint SizeOf()
+ public static unsafe uint SizeOf() where T : unmanaged
{
-#if NETCORE
- return (uint)Marshal.SizeOf();
-#else
- return (uint)Marshal.SizeOf(typeof(T));
-#endif
+ return (uint)sizeof(T);
}
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Utilities/Utils.cs b/DeviceIOControlLib/Utilities/Utils.cs
index 301f03c..bbd72d0 100644
--- a/DeviceIOControlLib/Utilities/Utils.cs
+++ b/DeviceIOControlLib/Utilities/Utils.cs
@@ -12,7 +12,7 @@ public static string GetWin32ErrorMessage(int errorCode)
return new Win32Exception(errorCode).Message;
}
- public static T ByteArrayToStruct(byte[] data, int index) where T : struct
+ public static T ByteArrayToStruct(byte[] data, int index) where T : unmanaged
{
using (UnmanagedMemory mem = new UnmanagedMemory(data.Length - index))
{
diff --git a/DeviceIOControlLib/Wrapper/DeviceIoControlHelper.cs b/DeviceIOControlLib/Wrapper/DeviceIoControlHelper.cs
index 993158f..683d556 100644
--- a/DeviceIOControlLib/Wrapper/DeviceIoControlHelper.cs
+++ b/DeviceIOControlLib/Wrapper/DeviceIoControlHelper.cs
@@ -7,29 +7,16 @@
namespace DeviceIOControlLib.Wrapper
{
- public static class DeviceIoControlHelper
+ public static partial class DeviceIoControlHelper
{
- [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- private static extern bool DeviceIoControl(
- SafeFileHandle hDevice,
- IOControlCode IoControlCode,
- [MarshalAs(UnmanagedType.AsAny)]
- [In] object InBuffer,
- uint nInBufferSize,
- [MarshalAs(UnmanagedType.AsAny)]
- [Out] object OutBuffer,
- uint nOutBufferSize,
- ref uint pBytesReturned,
- [In] IntPtr Overlapped
- );
-
- [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- private static extern bool DeviceIoControl(
+ [LibraryImport("Kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static partial bool DeviceIoControl(
SafeFileHandle hDevice,
IOControlCode ioControlCode,
- byte[] inBuffer,
+ IntPtr inBuffer,
uint nInBufferSize,
- byte[] outBuffer,
+ IntPtr outBuffer,
uint nOutBufferSize,
ref uint pBytesReturned,
IntPtr overlapped
@@ -43,18 +30,22 @@ public static bool InvokeIoControl(SafeFileHandle handle, IOControlCode controlC
{
uint returnedBytes = 0;
- return DeviceIoControl(handle, controlCode, null, 0, null, 0, ref returnedBytes, IntPtr.Zero);
+ return DeviceIoControl(handle, controlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, ref returnedBytes, IntPtr.Zero);
}
///
/// Invoke DeviceIOControl with no input, and retrieve the output in the form of a byte array.
///
- public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength)
+ public unsafe static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength)
{
+ bool success;
uint returnedBytes = 0;
byte[] output = new byte[outputLength];
- bool success = DeviceIoControl(handle, controlCode, null, 0, output, outputLength, ref returnedBytes, IntPtr.Zero);
+ fixed (byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, IntPtr.Zero, 0, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
if (!success)
{
@@ -68,12 +59,16 @@ public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode contro
///
/// Invoke DeviceIOControl with no input, and retrieve the output in the form of a byte array. Lets the caller handle the errorcode (if any).
///
- public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength, out int errorCode)
+ public unsafe static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength, out int errorCode)
{
+ bool success;
uint returnedBytes = 0;
byte[] output = new byte[outputLength];
- bool success = DeviceIoControl(handle, controlCode, null, 0, output, outputLength, ref returnedBytes, IntPtr.Zero);
+ fixed (byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, IntPtr.Zero, 0, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
errorCode = 0;
@@ -86,13 +81,14 @@ public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode contro
///
/// Invoke DeviceIOControl with no input, and retrieve the output in the form of an object of type T.
///
- public static T InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode)
+ public unsafe static T InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode)
+ where T : unmanaged
{
uint returnedBytes = 0;
- object output = default(T);
+ T output = default;
uint outputSize = MarshalHelper.SizeOf();
- bool success = DeviceIoControl(handle, controlCode, null, 0, output, outputSize, ref returnedBytes, IntPtr.Zero);
+ bool success = DeviceIoControl(handle, controlCode, IntPtr.Zero, 0, new IntPtr(&output), outputSize, ref returnedBytes, IntPtr.Zero);
if (!success)
{
@@ -100,21 +96,23 @@ public static T InvokeIoControl(SafeFileHandle handle, IOControlCode controlC
throw new Win32Exception(lastError, "Couldn't invoke DeviceIoControl for " + controlCode + ". LastError: " + Utils.GetWin32ErrorMessage(lastError));
}
- return (T)output;
+ return output;
}
///
/// Invoke DeviceIOControl with input of type V, and retrieve the output in the form of an object of type T.
///
- public static T InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, V input)
+ public unsafe static T InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, V input)
+ where T : unmanaged
+ where V : unmanaged
{
uint returnedBytes = 0;
- object output = default(T);
+ T output = default;
uint outputSize = MarshalHelper.SizeOf();
uint inputSize = MarshalHelper.SizeOf();
- bool success = DeviceIoControl(handle, controlCode, input, inputSize, output, outputSize, ref returnedBytes, IntPtr.Zero);
+ bool success = DeviceIoControl(handle, controlCode, new IntPtr(&input), inputSize, new IntPtr(&output), outputSize, ref returnedBytes, IntPtr.Zero);
if (!success)
{
@@ -122,18 +120,19 @@ public static T InvokeIoControl(SafeFileHandle handle, IOControlCode contr
throw new Win32Exception(lastError, "Couldn't invoke DeviceIoControl for " + controlCode + ". LastError: " + Utils.GetWin32ErrorMessage(lastError));
}
- return (T)output;
+ return output;
}
///
/// Invoke DeviceIOControl with input of type V, and retrieves no output.
///
- public static void InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, V input)
+ public unsafe static void InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, V input)
+ where V : unmanaged
{
uint returnedBytes = 0;
uint inputSize = MarshalHelper.SizeOf();
- bool success = DeviceIoControl(handle, controlCode, input, inputSize, null, 0, ref returnedBytes, IntPtr.Zero);
+ bool success = DeviceIoControl(handle, controlCode, new IntPtr(&input), inputSize, IntPtr.Zero, 0, ref returnedBytes, IntPtr.Zero);
if (!success)
{
@@ -145,15 +144,20 @@ public static void InvokeIoControl(SafeFileHandle handle, IOControlCode contr
///
/// Calls InvokeIoControl with the specified input, returning a byte array. It allows the caller to handle errors.
///
- public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength, V input, out int errorCode)
+ public unsafe static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode controlCode, uint outputLength, V input, out int errorCode)
+ where V : unmanaged
{
+ bool success;
uint returnedBytes = 0;
uint inputSize = MarshalHelper.SizeOf();
errorCode = 0;
- byte[] output = new byte[outputLength];
- bool success = DeviceIoControl(handle, controlCode, input, inputSize, output, outputLength, ref returnedBytes, IntPtr.Zero);
+ byte[] output = new byte[outputLength];
+ fixed (byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, new IntPtr(&input), inputSize, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
if (!success)
{
@@ -166,16 +170,21 @@ public static byte[] InvokeIoControl(SafeFileHandle handle, IOControlCode con
///
/// Repeatedly invokes InvokeIoControl, as long as it gets return code 234 ("More data available") from the method.
///
- public static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControlCode controlCode, uint increment = 128)
+ public unsafe static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControlCode controlCode, uint increment = 128)
{
uint returnedBytes = 0;
uint outputLength = increment;
+ byte[] output = new byte[outputLength];
+
do
{
- byte[] output = new byte[outputLength];
- bool success = DeviceIoControl(handle, controlCode, null, 0, output, outputLength, ref returnedBytes, IntPtr.Zero);
+ bool success;
+ fixed(byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, IntPtr.Zero, 0, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
if (!success)
{
@@ -205,7 +214,8 @@ public static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControl
///
/// Repeatedly invokes InvokeIoControl with the specified input, as long as it gets return code 234 ("More data available") from the method.
///
- public static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControlCode controlCode, V input, uint increment = 128, uint inputSizeOverride = 0)
+ public unsafe static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControlCode controlCode, V input, uint increment = 128, uint inputSizeOverride = 0)
+ where V : unmanaged
{
uint returnedBytes = 0;
@@ -221,10 +231,15 @@ public static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOCont
inputSize = MarshalHelper.SizeOf();
}
+ byte[] output = new byte[outputLength];
+
do
{
- byte[] output = new byte[outputLength];
- bool success = DeviceIoControl(handle, controlCode, input, inputSize, output, outputLength, ref returnedBytes, IntPtr.Zero);
+ bool success;
+ fixed(byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, new IntPtr(&input), inputSize, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
if (!success)
{
@@ -251,5 +266,50 @@ public static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOCont
} while (true);
}
+ ///
+ /// Repeatedly invokes InvokeIoControl with the specified input, as long as it gets return code 234 ("More data available") from the method.
+ ///
+ public unsafe static byte[] InvokeIoControlUnknownSize(SafeFileHandle handle, IOControlCode controlCode, byte[] input, uint increment = 128)
+ {
+ uint returnedBytes = 0;
+
+ uint inputSize = (uint)input.Length;
+ uint outputLength = increment;
+
+ byte[] output = new byte[outputLength];
+
+ do
+ {
+ bool success;
+ fixed (byte* inputPtr = input)
+ fixed (byte* outputPtr = output)
+ {
+ success = DeviceIoControl(handle, controlCode, new IntPtr(inputPtr), inputSize, new IntPtr(outputPtr), outputLength, ref returnedBytes, IntPtr.Zero);
+ }
+
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+
+ if (lastError == 234)
+ {
+ // More data
+ outputLength += increment;
+ continue;
+ }
+
+ throw new Win32Exception(lastError, "Couldn't invoke DeviceIoControl for " + controlCode + ". LastError: " + Utils.GetWin32ErrorMessage(lastError));
+ }
+
+ // Return the result
+ if (output.Length == returnedBytes)
+ return output;
+
+ byte[] res = new byte[returnedBytes];
+ Array.Copy(output, res, (int)returnedBytes);
+
+ return res;
+ } while (true);
+ }
}
}
\ No newline at end of file
diff --git a/DeviceIOControlLib/Wrapper/DiskDeviceWrapper.cs b/DeviceIOControlLib/Wrapper/DiskDeviceWrapper.cs
index 496f253..cbf6055 100644
--- a/DeviceIOControlLib/Wrapper/DiskDeviceWrapper.cs
+++ b/DeviceIOControlLib/Wrapper/DiskDeviceWrapper.cs
@@ -57,9 +57,16 @@ public PARTITION_INFORMATION_EX DiskGetPartitionInfoEx()
//DiskSetPartitionInfoEx
///
- public DRIVE_LAYOUT_INFORMATION DiskGetDriveLayout()
+ public unsafe DRIVE_LAYOUT_INFORMATION DiskGetDriveLayout()
{
- DRIVE_LAYOUT_INFORMATION_INTERNAL data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.DiskGetDriveLayout);
+ byte[] outputBytes = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.DiskGetDriveLayoutEx,
+ (uint)sizeof(DRIVE_LAYOUT_INFORMATION_INTERNAL) + 128 * (uint)sizeof(PARTITION_INFORMATION));
+
+ DRIVE_LAYOUT_INFORMATION_INTERNAL data;
+ fixed (byte* outputPtr = outputBytes)
+ {
+ data = MarshalHelper.ToStructure(new IntPtr(outputPtr));
+ }
DRIVE_LAYOUT_INFORMATION res = new DRIVE_LAYOUT_INFORMATION();
@@ -67,16 +74,28 @@ public DRIVE_LAYOUT_INFORMATION DiskGetDriveLayout()
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];
+ fixed (byte* outputPtr = outputBytes)
+ {
+ PARTITION_INFORMATION* partitionPtr = (PARTITION_INFORMATION*)
+ (outputPtr + sizeof(DRIVE_LAYOUT_INFORMATION_INTERNAL));
+ for (int i = 0; i < res.PartitionCount; i++)
+ res.PartitionEntry[i] = *partitionPtr++;
+ }
return res;
}
///
- public DRIVE_LAYOUT_INFORMATION_EX DiskGetDriveLayoutEx()
+ public unsafe DRIVE_LAYOUT_INFORMATION_EX DiskGetDriveLayoutEx()
{
- DRIVE_LAYOUT_INFORMATION_EX_INTERNAL data = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.DiskGetDriveLayoutEx);
+ byte[] outputBytes = DeviceIoControlHelper.InvokeIoControl(Handle, IOControlCode.DiskGetDriveLayoutEx,
+ (uint)sizeof(DRIVE_LAYOUT_INFORMATION_EX_INTERNAL) + 128 * (uint)sizeof(PARTITION_INFORMATION_EX));
+
+ DRIVE_LAYOUT_INFORMATION_EX_INTERNAL data;
+ fixed (byte* outputPtr = outputBytes)
+ {
+ data = MarshalHelper.ToStructure(new IntPtr(outputPtr));
+ }
DRIVE_LAYOUT_INFORMATION_EX res = new DRIVE_LAYOUT_INFORMATION_EX();
@@ -85,8 +104,13 @@ public DRIVE_LAYOUT_INFORMATION_EX DiskGetDriveLayoutEx()
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];
+ fixed(byte* outputPtr = outputBytes)
+ {
+ PARTITION_INFORMATION_EX* partitionPtr = (PARTITION_INFORMATION_EX*)
+ (outputPtr + sizeof(DRIVE_LAYOUT_INFORMATION_EX_INTERNAL));
+ for (int i = 0; i < res.PartitionCount; i++)
+ res.PartitionEntry[i] = *partitionPtr++;
+ }
return res;
}
diff --git a/DeviceIOControlLib/Wrapper/MountManagerWrapper.cs b/DeviceIOControlLib/Wrapper/MountManagerWrapper.cs
index 2f217f1..819b514 100644
--- a/DeviceIOControlLib/Wrapper/MountManagerWrapper.cs
+++ b/DeviceIOControlLib/Wrapper/MountManagerWrapper.cs
@@ -69,7 +69,7 @@ public List QueryDosVolumePaths(string deviceName)
Encoding.Unicode.GetBytes(deviceName, 0, deviceName.Length, tmp, 2);
- byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.MountmgrQueryDosVolumePaths, tmp, 64, (uint)tmp.Length);
+ byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.MountmgrQueryDosVolumePaths, tmp, 64);
return new List(Utils.ReadUnicodeStringArray(data, sizeof(uint)));
}
diff --git a/DeviceIOControlLib/Wrapper/StorageDeviceWrapper.cs b/DeviceIOControlLib/Wrapper/StorageDeviceWrapper.cs
index 2b2e83b..5634ffe 100644
--- a/DeviceIOControlLib/Wrapper/StorageDeviceWrapper.cs
+++ b/DeviceIOControlLib/Wrapper/StorageDeviceWrapper.cs
@@ -2,6 +2,8 @@
using DeviceIOControlLib.Objects.Storage;
using DeviceIOControlLib.Utilities;
using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
namespace DeviceIOControlLib.Wrapper
{
@@ -17,7 +19,7 @@ public StorageDeviceWrapper(SafeFileHandle handle, bool ownsHandle = false)
//StorageCheckVerify2
//StorageMediaRemoval
- public STORAGE_DEVICE_DESCRIPTOR_PARSED StorageGetDeviceProperty()
+ public unsafe STORAGE_DEVICE_DESCRIPTOR_PARSED StorageGetDeviceProperty()
{
STORAGE_PROPERTY_QUERY query = new STORAGE_PROPERTY_QUERY();
query.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery;
@@ -40,7 +42,7 @@ public STORAGE_DEVICE_DESCRIPTOR_PARSED StorageGetDeviceProperty()
returnValue.SerialNumberOffset = descriptor.SerialNumberOffset;
returnValue.BusType = descriptor.BusType;
returnValue.RawPropertiesLength = descriptor.RawPropertiesLength;
- returnValue.RawDeviceProperties = descriptor.RawDeviceProperties;
+ Buffer.MemoryCopy(descriptor.RawDeviceProperties, returnValue.RawDeviceProperties, 0x16, 0x16);
if (descriptor.SerialNumberOffset > 0)
returnValue.SerialNumber = Utils.ReadNullTerminatedAsciiString(res, (int)descriptor.SerialNumberOffset);