using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Win_API { public static class NativeMethods { // The following GitHub link was very helpful in understanding how some of the WinApi calls work together, as well as // for certain const values like DIGCF_PRESENT. https://github.com/mikeobrien/HidLibrary/tree/dc9026067dd0c511574c8ce726682ece4f45939e //https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi //https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/introduction-to-hid-concepts public const uint GENERIC_READ = 0x80000000; public const uint GENERIC_WRITE = 0x40000000; public const int FILE_FLAG_OVERLAPPED = 0x40000000; public const int FILE_ATTRIBUTE_NORMAL = 0x128; public const short DIGCF_PRESENT = 0x2; public const short DIGCF_DEVICEINTERFACE = 0x10; public const int DIGCF_ALLCLASSES = 0x4; public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); /// /// Zero prevents other processes from opening a file or device if they request delete, read, or write access. /// public enum FileShareMode { Zero = 0x00000000, FILE_SHARE_DELETE = 0x00000004, FILE_SHARE_READ = 0x00000001, FILE_SHARE_WRITE = 0x00000002 } public struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; public bool bInheritHandle; } [DllImport("kernel32.dll")] public static extern bool CancelIo(IntPtr hFile); [DllImport("kernel32.dll")] public static extern IntPtr CreateFileA( string lpFileName, uint dwDesiredAccess, int dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32.dll")] public static extern bool ReadFile( IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, [In] ref System.Threading.NativeOverlapped lpOverlapped); [DllImport("kernel32.dll")] public static extern bool WriteFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, [In] ref System.Threading.NativeOverlapped lpOverlapped); [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr hHandle); /// /// The caller of this function must delete the returned device information set when it is no longer needed by calling SetupDiDestroyDeviceInfoList. /// /// /// /// [DllImport("Setupapi.dll")] public static extern IntPtr SetupDiCreateDeviceInfoList(Guid Guid, IntPtr HwndParent); [DllImport("setupapi.dll")] public static extern bool SetupDiCreateDeviceInfo(IntPtr DeviceInfoSet, string DeviceName, Guid ClassGuid, string DeviceDescription, uint CreationFlags, IntPtr DeviceInfoData); [DllImport("setupapi.dll")] public static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData); [DllImport("setupapi.dll")] public static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, Guid InterfaceClassGuid, uint MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData); [DllImport("setupapi.dll")] public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, ref uint RequiredSize, IntPtr DeviceInfoData); [DllImport("setupapi.dll")] public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, ref uint RequiredSize, IntPtr DeviceInfoData); [DllImport("setupapi.dll")] public static extern bool SetupDiGetClassDevs(Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, uint Flags); [DllImport("setupapi.dll")] public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); /// /// HidD_GetAttributes returns TRUE if succeeds; otherwise, it returns FALSE. /// /// /// /// [DllImport("hid.dll")] public static extern bool HidD_GetAttributes(IntPtr HidDeviceObject, HIDD_ATTRIBUTES Attributes); /// /// [out] Pointer to a caller-allocated GUID buffer that the routine uses to return the device interface GUID for HIDClass devices. /// /// [DllImport("hid.dll")] public static extern void HidD_GetHidGuid(out Guid HidGuid); [DllImport("hid.dll")] public static extern bool HidD_GetIndexString(IntPtr HidDeviceObject, ulong StringIndex, out string Buffer, ulong BufferLength); /// /// The maximum possible number of characters in an embedded string is device specific. For USB devices, the maximum string length is 126 wide characters (not including the terminating NULL character). /// If the supplied buffer is not <= 4093 bytes(2^12 – 3) the call may fail(depending on the underlying protocol, HID/Bluetooth/SPI) with error code ERROR_GEN_FAILURE(0x0000001f). /// /// /// /// /// bool [DllImport("hid.dll")] public static extern bool HidD_GetManufacturerString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength); /// /// HidD_GetPhysicalDescriptor returns TRUE if it succeeds; otherwise, it returns FALSE. Use GetLastError to get extended error information. /// /// /// /// /// [DllImport("hid.dll")] public static extern bool HidD_GetPhysicalDescriptor(IntPtr HidDeviceObject, out string Buffer, [In] ulong BufferLength); [DllImport("hid.dll")] public static extern bool HidD_GetPreparsedData(IntPtr HidDeviceObject, out HID_COLLECTION_INFORMATION PreparsedData); /// /// The supplied buffer must be <= 4093 bytes (2^12 – 3). /// /// /// /// /// [DllImport("hid.dll")] public static extern bool HidD_GetProductString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength); [DllImport("hid.dll")] public static extern bool HidD_GetSerialNumberString(IntPtr HidDeviceObject, out string Buffer, ulong BufferLength); [DllImport("hid.dll")] public static extern bool HidD_GetNumInputBuffers(IntPtr HidDeviceObject, out ulong NumberBuffers); [DllImport("hid.dll")] public static extern bool HidD_SetNumInputBuffers(IntPtr HidDeviceObject, ulong NumberBuffers); /// /// A caller of HidD_GetAttributes, uses this structure to obtain a device's vendor information. /// Before using a HIDD_ATTRIBUTES structure with HIDClass support routines, the caller must set the Size member. /// public struct HIDD_ATTRIBUTES { public ulong Size; public ushort VendorID; public ushort ProductID; public ushort VersionNumber; } public struct HID_COLLECTION_INFORMATION { public ulong DescriptorSize; public bool Polled; public char[] Reserved1; public ushort VendorID; public ushort ProductID; public ushort VersionNumber; } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVICE_INTERFACE_DATA { public uint cbSize; public Guid InterfaceClassGuid; public uint Flags; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_DATA { public uint cbSize; public Guid ClassGuid; public uint DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVICE_INTERFACE_DETAIL_DATA { public uint cbSize; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string DevicePath; } public static SECURITY_ATTRIBUTES InitWithDefaultAttributes() { SECURITY_ATTRIBUTES attributes = new SECURITY_ATTRIBUTES { bInheritHandle = false, lpSecurityDescriptor = IntPtr.Zero }; attributes.nLength = Marshal.SizeOf(attributes); return attributes; } public static IntPtr CreateNonManagedBuffer(byte[] buffer) { return Marshal.AllocHGlobal(buffer.Length); } public static byte[] CopyUnManagedBufferToManagedBuffer(IntPtr unManagedBuffer, int bytesRead) { var buffer = new byte[] { }; Marshal.Copy(unManagedBuffer, buffer, 0, bytesRead); return buffer; } public static void DisposeNonManagedObject(IntPtr nonManagedObj) { Marshal.FreeHGlobal(nonManagedObj); } } }