C# 读写USB X64

前几天接了一个比较老的USB读写dll,发现是X86的,但最新的软件框架需要X64,所以需要升级该USB的dll。

使用dnspy反编译获取代码(还好是c#写的,支持反编译)

直接上改完的代码:

public class TiUsbHidIO
    {
        // Token: 0x06000001 RID: 1
        [DllImport("kernel32.dll")]
        private static extern IntPtr GlobalLock(IntPtr hMem);

        // Token: 0x06000002 RID: 2
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GlobalUnlock(IntPtr hMem);

        // Token: 0x06000003 RID: 3
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, uint lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, uint hTemplateFile);

        // Token: 0x06000004 RID: 4
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool WriteFile(SafeFileHandle hFile, IntPtr HidOut, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr overlaped);

        // Token: 0x06000005 RID: 5
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool ReadFile(SafeFileHandle hFile, IntPtr HidIn, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

        // Token: 0x06000006 RID: 6
        [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, int Enumerator, int hwndParent, uint Flags);

        // Token: 0x06000007 RID: 7
        [DllImport("setupapi.dll", SetLastError = true)]
        public static extern bool SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, int DeviceInfoData, ref Guid InterfaceClassGuid, uint MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);

        // Token: 0x06000008 RID: 8
        [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr hDevInfo, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData, uint deviceInterfaceDetailDataSize, ref uint requiredSize, out SP_DEVINFO_DATA deviceInfoData);

        // Token: 0x06000009 RID: 9
        [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
        public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

        // Token: 0x0600000A RID: 10 RVA: 0x00002050 File Offset: 0x00000250
        public bool Open(ushort VendorID, ushort ProductID, ushort Interface)
        {
            Guid guid = new Guid("4D1E55B2-F16F-11CF-88CB-001111000030");
            uint num = 0u;
            uint num2 = 0u;
            this.VID = "VID_" + VendorID.ToString("X4");
            this.PID = "PID_" + ProductID.ToString("X4");
            this.MI = "MI_" + Interface.ToString("X2");
            if (this.handle != null)
            {
                this.handle.Close();
                this.handle = null;
            }
            this.IsOpen = false;
            IntPtr intPtr = SetupDiGetClassDevs(ref guid, 0, 0, 18u); //这里的18u是我们公司的专属硬件,可以百度改成其他类型的
            if (intPtr.ToInt64() == -1)
            {
                string message = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                this.ErrorMessage = "Setup Di Class Failed: " + message;
            }
            else
            {
                SP_DEVICE_INTERFACE_DATA sp_DEVICE_INTERFACE_DATA = default(SP_DEVICE_INTERFACE_DATA);
                uint cblength1 = (uint)Marshal.SizeOf(sp_DEVICE_INTERFACE_DATA);
                sp_DEVICE_INTERFACE_DATA.cbSize = cblength1;
                SP_DEVINFO_DATA sp_DEVINFO_DATA = default(SP_DEVINFO_DATA);
                uint cblength2 = (uint)Marshal.SizeOf(sp_DEVINFO_DATA);
                sp_DEVINFO_DATA.cbSize = cblength2;
                //SP_DEVICE_INTERFACE_DETAIL_DATA sp_DEVICE_INTERFACE_DETAIL_DATA = default(SP_DEVICE_INTERFACE_DETAIL_DATA);
                while (SetupDiEnumDeviceInterfaces(intPtr, 0, ref guid, num, ref sp_DEVICE_INTERFACE_DATA))
                {
                    num += 1u;
                    if (!SetupDiGetDeviceInterfaceDetail(intPtr, ref sp_DEVICE_INTERFACE_DATA, IntPtr.Zero, 0u, ref num2, out sp_DEVINFO_DATA) && 122 != Marshal.GetLastWin32Error())
                    {
                        this.ErrorMessage = "Setup Di Class Failed!\nSetup Get Device Interface Detail\nProbe for buffer size!";
                        break;
                    }
                    uint num3 = num2;

                    IntPtr intPtr2 = Marshal.AllocHGlobal((int)num3);
                    if (IntPtr.Size == 8)
                        Marshal.WriteInt32(intPtr2, 6 + Marshal.SystemDefaultCharSize);
                    else
                        Marshal.WriteInt32(intPtr2, 4 + Marshal.SystemDefaultCharSize);
                    //sp_DEVINFO_DATA.cbSize = 8;
                    if (!SetupDiGetDeviceInterfaceDetail(intPtr, ref sp_DEVICE_INTERFACE_DATA, intPtr2, num3, ref num2, out sp_DEVINFO_DATA))
                    {
                        Marshal.FreeHGlobal(intPtr2);
                        string message2 = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                        this.ErrorMessage = "Setup Detail!";
                        break;
                    }
                    string text = new string(((SP_DEVICE_INTERFACE_DETAIL_DATA)Marshal.PtrToStructure(intPtr2, typeof(SP_DEVICE_INTERFACE_DETAIL_DATA))).DeviceName, 0, (int)(num3 - 6u >> 1));
                    Marshal.FreeHGlobal(intPtr2);
                    text = text.ToUpper();
                    if (text.Contains(this.VID) && text.Contains(this.PID) && text.Contains(this.MI))
                    {
                        this.handle = CreateFile(text, 3221225472u, 0u, 0u, 3u, 0u, 0u);
                        if (this.handle.IsInvalid)
                        {
                            this.handle.Close();
                            this.handle = null;
                            string message3 = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                            this.ErrorMessage = "Createfile error: " + message3;
                            break;
                        }
                        this.ProjectorControlOut.data = new byte[65];
                        this.ProjectorControlIn.data = new byte[65];
                        this.IsOpen = true;
                        break;
                    }
                }
                //int errCode = Marshal.GetLastWin32Error();
                //System.Windows.Forms.MessageBox.Show(errCode.ToString());
                //System.Windows.Forms.MessageBox.Show(GetSysErrMsg(errCode));
            }
            SetupDiDestroyDeviceInfoList(intPtr);
            return this.IsOpen;
        }

        [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
        public extern static int FormatMessage(int flag, ref IntPtr source, int msgid, int langid, ref string buf, int size, ref IntPtr args);
        /// <summary>
        /// 获取系统错误信息描述
        /// </summary>
        /// <param name="errCode">系统错误码</param>
        /// <returns></returns>
        public static string GetSysErrMsg(int errCode)
        {
            IntPtr tempptr = IntPtr.Zero;
            string msg = null;
            FormatMessage(0x1300, ref tempptr, errCode, 0, ref msg, 255, ref tempptr);
            return msg;
        }

        // Token: 0x0600000B RID: 11 RVA: 0x00002308 File Offset: 0x00000508
        public void Close()
        {
            if (this.handle != null)
            {
                this.handle.Close();
            }
        }

        // Token: 0x0600000C RID: 12 RVA: 0x00002320 File Offset: 0x00000520
        public bool WriteThenRead(ushort cmd, byte[] writeData, ushort length, int msecTimeout, out byte[] readData)
        {
            uint num = 0u;
            uint num2 = 0u;
            readData = new byte[1];
            if (this.handle == null)
            {
                Array.Resize<byte>(ref readData, 0);
                return false;
            }
            byte seq = (byte)cmd;
            this.ProjectorControlOut.reportid = 0;
            this.ProjectorControlOut.flags = 192;
            this.ProjectorControlOut.seq = seq;
            this.ProjectorControlOut.length = (ushort)(length + 2);
            this.ProjectorControlOut.cmd = cmd;
            for (int i = 0; i < (int)length; i++)
            {
                this.ProjectorControlOut.data[i] = writeData[i];
            }
            for (int j = (int)length; j < 65; j++)
            {
                this.ProjectorControlOut.data[j] = 0;
            }
            IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(this.ProjectorControlOut));
            Marshal.StructureToPtr(this.ProjectorControlOut, intPtr, false);
            WriteFile(this.handle, intPtr, 65u, out num, IntPtr.Zero);
            Thread.Sleep(msecTimeout);
            ReadFile(this.handle, intPtr, 65u, out num2, IntPtr.Zero);
            this.ProjectorControlIn = (PROJECTORHIDSTRUCTIN)Marshal.PtrToStructure(intPtr, typeof(PROJECTORHIDSTRUCTIN));
            Array.Resize<byte>(ref readData, (int)this.ProjectorControlIn.length);
            for (int k = 0; k < readData.Length; k++)
            {
                readData[k] = this.ProjectorControlIn.data[k];
            }
            Marshal.FreeHGlobal(intPtr);
            if (this.ProjectorControlOut.seq != this.ProjectorControlIn.seq)
            {
                this.ErrorMessage = "Error: Projector Communications Sequence # mismatch!";
                return false;
            }
            return true;
        }

        // Token: 0x0600000D RID: 13 RVA: 0x000024B0 File Offset: 0x000006B0
        public bool Write(ushort cmd, byte[] writeData, ushort length)
        {
            uint num = 0u;
            if (this.handle == null)
            {
                return false;
            }
            byte seq = (byte)cmd;
            this.ProjectorControlOut.reportid = 0;
            this.ProjectorControlOut.flags = 0;
            this.ProjectorControlOut.seq = seq;
            this.ProjectorControlOut.length = (ushort)(length + 2);
            this.ProjectorControlOut.cmd = cmd;
            for (int i = 0; i < (int)length; i++)
            {
                this.ProjectorControlOut.data[i] = writeData[i];
            }
            IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(this.ProjectorControlOut));
            Marshal.StructureToPtr(this.ProjectorControlOut, intPtr, false);
            WriteFile(this.handle, intPtr, 65u, out num, IntPtr.Zero);
            Marshal.FreeHGlobal(intPtr);
            return true;
        }

        // Token: 0x04000001 RID: 1
        private const byte HIDREPORTID = 0;

        // Token: 0x04000002 RID: 2
        private const byte NOREPLY = 0;

        // Token: 0x04000003 RID: 3
        private const byte REPLY = 64;

        // Token: 0x04000004 RID: 4
        private const byte DESTPROJECTOR = 0;

        // Token: 0x04000005 RID: 5
        private const byte HIDWRITE = 0;

        // Token: 0x04000006 RID: 6
        private const byte HIDREAD = 128;

        // Token: 0x04000007 RID: 7
        private const byte HIDNACK = 32;

        // Token: 0x04000008 RID: 8
        private const uint GENERIC_READ = 2147483648u;

        // Token: 0x04000009 RID: 9
        private const uint GENERIC_WRITE = 1073741824u;

        // Token: 0x0400000A RID: 10
        private const uint READWRITE = 3221225472u;

        // Token: 0x0400000B RID: 11
        public SafeFileHandle handle;

        // Token: 0x0400000C RID: 12
        public string VID = "VID_0451";

        // Token: 0x0400000D RID: 13
        public string PID = "PID_4421";

        // Token: 0x0400000E RID: 14
        public string MI = "MI_00";

        // Token: 0x0400000F RID: 15
        public string ErrorMessage;

        // Token: 0x04000010 RID: 16
        public bool IsOpen;

        // Token: 0x04000011 RID: 17
        private PROJECTORHIDSTRUCTOUT ProjectorControlOut;

        // Token: 0x04000012 RID: 18
        private PROJECTORHIDSTRUCTIN ProjectorControlIn;

        // Token: 0x02000003 RID: 3
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
        public struct SP_DEVICE_INTERFACE_DETAIL_DATA
        {
            // Token: 0x04000013 RID: 19
            public uint cbsize;

            // Token: 0x04000014 RID: 20
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] DeviceName;
        }

        // Token: 0x02000004 RID: 4
        //X64重新修改长度 ----在X64下长度应为32
        public struct SP_DEVICE_INTERFACE_DATA
        {
            // Token: 0x04000015 RID: 21
            public uint cbSize;

            // Token: 0x04000016 RID: 22
            public Guid InterfaceClassGuid;

            // Token: 0x04000017 RID: 23
            public int FLAGS;

            // Token: 0x04000018 RID: 24
            public long Reserved;
        }

        // Token: 0x02000005 RID: 5
        public struct SP_DEVINFO_DATA
        {
            // Token: 0x04000019 RID: 25
            public uint cbSize;

            // Token: 0x0400001A RID: 26
            public Guid ClassGuid;

            // Token: 0x0400001B RID: 27
            public uint DevInst;

            // Token: 0x0400001C RID: 28
            public IntPtr Reserved;
        }

        // Token: 0x02000006 RID: 6
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct PROJECTORHIDSTRUCTIN
        {
            // Token: 0x0400001D RID: 29
            public byte reportid;

            // Token: 0x0400001E RID: 30
            public byte flags;

            // Token: 0x0400001F RID: 31
            public byte seq;

            // Token: 0x04000020 RID: 32
            public ushort length;

            // Token: 0x04000021 RID: 33
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65)]
            public byte[] data;
        }

        // Token: 0x02000007 RID: 7
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct PROJECTORHIDSTRUCTOUT
        {
            // Token: 0x04000022 RID: 34
            public byte reportid;

            // Token: 0x04000023 RID: 35
            public byte flags;

            // Token: 0x04000024 RID: 36
            public byte seq;

            // Token: 0x04000025 RID: 37
            public ushort length;

            // Token: 0x04000026 RID: 38
            public ushort cmd;

            // Token: 0x04000027 RID: 39
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65)]
            public byte[] data;
        }
    }

解决方案:

1,使用SetupDiGetClassDevs会报system.overflowException算数运算符溢出。

这个是由于直接引用老版dll(x86)内存不一致导致。

2,SetupDiEnumDeviceInterfaces一致返回false

SP_DEVICE_INTERFACE_DATA 该数据结构在X86长度为28,在X64应该改为32位

将public int Reserved 改为:public long Reserved;

因为int 4字节,long8字节正好32位

public struct SP_DEVICE_INTERFACE_DATA
        {
            // Token: 0x04000015 RID: 21
            public uint cbSize;

            // Token: 0x04000016 RID: 22
            public Guid InterfaceClassGuid;

            // Token: 0x04000017 RID: 23
            public int FLAGS;

            // Token: 0x04000018 RID: 24
            public long Reserved;
        }

3,SetupDiGetDeviceInterfaceDetail返回false

这个是因为intptr在X86是4字节,在X64是8字节。

在分配内存时,X64需要分配8长度,X86需要分配6字节。

if (IntPtr.Size == 8)
                        Marshal.WriteInt32(intPtr2, 6 + Marshal.SystemDefaultCharSize);
                    else
                        Marshal.WriteInt32(intPtr2, 4 + Marshal.SystemDefaultCharSize);

参考文章:https://stackoom.com/question/eRBj/%E5%9C%A8-%E4%BD%8D%E5%92%8C-%E4%BD%8D%E8%BF%90%E8%A1%8C%E6%97%B6%E4%B8%AD%E7%BC%96%E7%BB%84%E5%8A%A8%E6%80%81%E7%BB%93%E6%9E%84

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值