From b151b82e0697ddf90f3570c19165a138f345522e Mon Sep 17 00:00:00 2001 From: dahall Date: Thu, 18 Feb 2021 14:25:21 -0700 Subject: [PATCH] Added parameter attributes and DeviceIoControl overload that takes no input or output params. --- PInvoke/Kernel32/IoApiSet.cs | 131 ++++++++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/PInvoke/Kernel32/IoApiSet.cs b/PInvoke/Kernel32/IoApiSet.cs index a77e0ea0..de8029cc 100644 --- a/PInvoke/Kernel32/IoApiSet.cs +++ b/PInvoke/Kernel32/IoApiSet.cs @@ -291,7 +291,8 @@ namespace Vanara.PInvoke // HANDLE WINAPI CreateIoCompletionPort( _In_ HANDLE FileHandle, _In_opt_ HANDLE ExistingCompletionPort, _In_ ULONG_PTR CompletionKey, _In_ DWORD NumberOfConcurrentThreads ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("IoAPI.h", MSDNShortId = "40cb47fc-7b15-47f6-bee2-2611d4686053")] - public static extern HANDLE CreateIoCompletionPort([In] HANDLE FileHandle, [In, Optional] HANDLE ExistingCompletionPort, UIntPtr CompletionKey, uint NumberOfConcurrentThreads); + public static extern HANDLE CreateIoCompletionPort([In] HANDLE FileHandle, [In, Optional] HANDLE ExistingCompletionPort, + UIntPtr CompletionKey, uint NumberOfConcurrentThreads); /// This macro is used to create a unique system I/O control code (IOCTL). /// @@ -472,8 +473,9 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] - public static extern bool DeviceIoControl(HFILE hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, - uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); + public static extern bool DeviceIoControl(HFILE hDevice, uint dwIoControlCode, [In, Optional] IntPtr lpInBuffer, + [In, Optional] uint nInBufferSize, [Out, Optional] IntPtr lpOutBuffer, [In, Optional] uint nOutBufferSize, + out uint lpBytesReturned, [In, Out, Optional] IntPtr lpOverlapped); /// /// Sends a control code directly to a specified device driver, causing the corresponding device to perform the corresponding operation. @@ -571,8 +573,25 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] - public static extern unsafe bool DeviceIoControl(HFILE hDevice, uint dwIoControlCode, byte* lpInBuffer, uint nInBufferSize, byte* lpOutBuffer, - uint nOutBufferSize, out uint lpBytesReturned, NativeOverlapped* lpOverlapped); + public static extern unsafe bool DeviceIoControl(HFILE hDevice, uint dwIoControlCode, [In, Optional] byte* lpInBuffer, + [In, Optional] uint nInBufferSize, [Out, Optional] byte* lpOutBuffer, [In, Optional] uint nOutBufferSize, + out uint lpBytesReturned, [In, Out, Optional] NativeOverlapped* lpOverlapped); + + /// + /// Sends a control code directly to a specified device driver, causing the corresponding device to perform the corresponding operation. + /// + /// + /// A handle to the device on which the operation is to be performed. The device is typically a volume, directory, file, or stream. + /// To retrieve a device handle, use the CreateFile function. For more information, see Remarks. + /// + /// + /// The control code for the operation. This value identifies the specific operation to be performed and the type of device on which + /// to perform it. + /// + /// true if successful. + [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] + public static bool DeviceIoControl(HFILE hDev, uint ioControlCode) => + DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, out _, IntPtr.Zero); /// /// Sends a control code directly to a specified device driver, causing the corresponding device to perform the corresponding operation. @@ -597,12 +616,15 @@ namespace Vanara.PInvoke [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] public static bool DeviceIoControl(HFILE hDev, uint ioControlCode, TIn inVal, out TOut outVal) where TIn : struct where TOut : struct { - using (SafeHGlobalHandle ptrIn = SafeHGlobalHandle.CreateFromStructure(inVal), ptrOut = SafeHGlobalHandle.CreateFromStructure()) + using SafeHGlobalHandle ptrIn = SafeHGlobalHandle.CreateFromStructure(inVal), ptrOut = SafeHGlobalHandle.CreateFromStructure(); + var ret = DeviceIoControl(hDev, ioControlCode, ptrIn, ptrIn.Size, ptrOut, ptrOut.Size, out var bRet, IntPtr.Zero); + if (!ret && Win32Error.GetLastError() == Win32Error.ERROR_INSUFFICIENT_BUFFER) { - var ret = DeviceIoControl(hDev, ioControlCode, (IntPtr)ptrIn, (uint)ptrIn.Size, (IntPtr)ptrOut, (uint)ptrOut.Size, out var bRet, IntPtr.Zero); - outVal = ptrOut.ToStructure(); - return ret; + ptrOut.Size = bRet; + ret = DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, ptrOut, ptrOut.Size, out bRet, IntPtr.Zero); } + outVal = ret ? ptrOut.ToStructure() : default; + return ret; } /// @@ -624,12 +646,15 @@ namespace Vanara.PInvoke [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] public static bool DeviceIoControl(HFILE hDev, uint ioControlCode, out TOut outVal) where TOut : struct { - using (var ptrOut = SafeHGlobalHandle.CreateFromStructure()) + using var ptrOut = SafeHGlobalHandle.CreateFromStructure(); + var ret = DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, ptrOut, ptrOut.Size, out var bRet, IntPtr.Zero); + if (!ret && Win32Error.GetLastError() == Win32Error.ERROR_INSUFFICIENT_BUFFER) { - var ret = DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, (IntPtr)ptrOut, (uint)ptrOut.Size, out var bRet, IntPtr.Zero); - outVal = ptrOut.ToStructure(); - return ret; + ptrOut.Size = bRet; + ret = DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, ptrOut, ptrOut.Size, out bRet, IntPtr.Zero); } + outVal = ret ? ptrOut.ToStructure() : default; + return ret; } /// @@ -651,10 +676,8 @@ namespace Vanara.PInvoke [PInvokeData("Winbase.h", MSDNShortId = "aa363216")] public static bool DeviceIoControl(HFILE hDev, uint ioControlCode, TIn inVal) where TIn : struct { - using (var ptrIn = SafeHGlobalHandle.CreateFromStructure(inVal)) - { - return DeviceIoControl(hDev, ioControlCode, (IntPtr)ptrIn, (uint)ptrIn.Size, IntPtr.Zero, 0, out var bRet, IntPtr.Zero); - } + using var ptrIn = SafeHGlobalHandle.CreateFromStructure(inVal); + return DeviceIoControl(hDev, ioControlCode, ptrIn, ptrIn.Size, IntPtr.Zero, 0, out _, IntPtr.Zero); } /// Ends the asynchronous call to BeginDeviceIoControl<TIn, TOut>(HFILE, uint, TIn?, TOut?, AsyncCallback). @@ -950,7 +973,8 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("IoAPI.h", MSDNShortId = "aa365458")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern unsafe bool PostQueuedCompletionStatus([In] HANDLE CompletionPort, uint dwNumberOfBytesTransferred, UIntPtr dwCompletionKey, NativeOverlapped* lpOverlapped); + public static extern unsafe bool PostQueuedCompletionStatus([In] HANDLE CompletionPort, uint dwNumberOfBytesTransferred, + UIntPtr dwCompletionKey, [In, Optional] NativeOverlapped* lpOverlapped); /// Posts an I/O completion packet to an I/O completion port. /// A handle to an I/O completion port to which the I/O completion packet is to be posted. @@ -972,7 +996,8 @@ namespace Vanara.PInvoke [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("IoAPI.h", MSDNShortId = "aa365458")] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PostQueuedCompletionStatus([In] HANDLE CompletionPort, uint dwNumberOfBytesTransferred, [Optional] UIntPtr dwCompletionKey, [Optional] IntPtr lpOverlapped); + public static extern bool PostQueuedCompletionStatus([In] HANDLE CompletionPort, uint dwNumberOfBytesTransferred, + UIntPtr dwCompletionKey, [In, Optional] IntPtr lpOverlapped); private static unsafe IAsyncResult BeginDeviceIoControl(HFILE hDevice, uint dwIoControlCode, byte[] buffer, AsyncCallback userCallback, object userState) where TIn : struct where TOut : struct => BeginDeviceIoControl(hDevice, dwIoControlCode, buffer, userCallback, userState); @@ -992,11 +1017,9 @@ namespace Vanara.PInvoke private static T MemRead(byte[] buffer, ref int startIndex) where T : struct { - using (var pin = new PinnedObject(buffer, startIndex)) - { - startIndex += Marshal.SizeOf(typeof(T)); - return ((IntPtr)pin).ToStructure(); - } + using var pin = new PinnedObject(buffer, startIndex); + startIndex += Marshal.SizeOf(typeof(T)); + return ((IntPtr)pin).ToStructure(); } private static int MemWrite(byte[] buffer, T value, int startIndex = 0) where T : struct @@ -1009,52 +1032,44 @@ namespace Vanara.PInvoke private static byte[] Pack(TIn? inVal, TOut? outVal) where TIn : struct where TOut : struct { - using (var ms = new MemoryStream()) - using (var wtr = new BinaryWriter(ms)) - { - wtr.Write(inVal.HasValue ? Marshal.SizeOf(typeof(TIn)) : 0); - wtr.Write(outVal.HasValue ? Marshal.SizeOf(typeof(TOut)) : 0); - if (inVal.HasValue) wtr.Write(inVal.Value); - if (outVal.HasValue) wtr.Write(outVal.Value); - return ms.ToArray(); - } + using var ms = new MemoryStream(); + using var wtr = new BinaryWriter(ms); + wtr.Write(inVal.HasValue ? Marshal.SizeOf(typeof(TIn)) : 0); + wtr.Write(outVal.HasValue ? Marshal.SizeOf(typeof(TOut)) : 0); + if (inVal.HasValue) wtr.Write(inVal.Value); + if (outVal.HasValue) wtr.Write(outVal.Value); + return ms.ToArray(); } private static byte[] Pack(byte[] inputBuffer, byte[] outputBuffer) { - using (var ms = new MemoryStream()) - using (var wtr = new BinaryWriter(ms)) - { - wtr.Write(inputBuffer != null ? inputBuffer.Length : 0); - wtr.Write(outputBuffer != null ? outputBuffer.Length : 0); - if (inputBuffer != null && inputBuffer.Length > 0) - wtr.Write(inputBuffer); - if (outputBuffer != null && outputBuffer.Length > 0) - wtr.Write(outputBuffer); - return ms.ToArray(); - } + using var ms = new MemoryStream(); + using var wtr = new BinaryWriter(ms); + wtr.Write(inputBuffer != null ? inputBuffer.Length : 0); + wtr.Write(outputBuffer != null ? outputBuffer.Length : 0); + if (inputBuffer != null && inputBuffer.Length > 0) + wtr.Write(inputBuffer); + if (outputBuffer != null && outputBuffer.Length > 0) + wtr.Write(outputBuffer); + return ms.ToArray(); } private static Tuple Unpack(byte[] buffer) where TIn : struct where TOut : struct { - using (var ms = new MemoryStream(buffer)) - using (var rdr = new BinaryReader(ms)) - { - var inLen = rdr.ReadInt32(); - var outLen = rdr.ReadInt32(); - return new Tuple(inLen > 0 ? rdr.Read() : (TIn?)null, outLen > 0 ? rdr.Read() : (TOut?)null); - } + using var ms = new MemoryStream(buffer); + using var rdr = new BinaryReader(ms); + var inLen = rdr.ReadInt32(); + var outLen = rdr.ReadInt32(); + return new Tuple(inLen > 0 ? rdr.Read() : (TIn?)null, outLen > 0 ? rdr.Read() : (TOut?)null); } private static Tuple Unpack(byte[] buffer) { - using (var ms = new MemoryStream(buffer)) - using (var rdr = new BinaryReader(ms)) - { - var inLen = rdr.ReadInt32(); - var outLen = rdr.ReadInt32(); - return new Tuple(rdr.ReadBytes(inLen), rdr.ReadBytes(outLen)); - } + using var ms = new MemoryStream(buffer); + using var rdr = new BinaryReader(ms); + var inLen = rdr.ReadInt32(); + var outLen = rdr.ReadInt32(); + return new Tuple(rdr.ReadBytes(inLen), rdr.ReadBytes(outLen)); } /// Contains the information returned by a call to the GetQueuedCompletionStatusEx function.