前几天接了一个比较老的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);