Delphi 2012 XE2 x64平台实现HID设备操作

Delphi 2012 XE2 开始支持x64位平台,现有的32位的DELPHI程序需要移植到x64平台下。下面是这次工作的记录。

直接把32位的工程编译成64位后,没有报错,但是执行SetupDiEnumDeviceInterfaces接口的时候总是返回false,使用GetLastError发现错误码是1784(提供给请求操作的用户缓冲区无效。 ),这个接口的C定义是

SetupDiEnumDeviceInterfaces(
__in HDEVINFO DeviceInfoSet,
__in_opt PSP_DEVINFO_DATA DeviceInfoData,
__in CONST GUID *InterfaceClassGuid,
__in DWORD MemberIndex,
__out PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
);



检查了一下代码发现我在调用这个接口的时候只传入了DeviceInterfaceData这个参数,应该是这个参数x64和x86的平台下有差异。查看PSP_DEVINFO_DATA的定义。

typedef struct _SP_DEVICE_INTERFACE_DATA {
 DWORD cbSize;
 GUID  InterfaceClassGuid;
 DWORD Flags;
 ULONG_PTR Reserved;
} SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;



按照接口的定义,在传入参数的时候需要先设置cbSize的大小。网上GOOGLE了一下XE2的64位和32位数据类型基本没有变化,但是VC是有变化的。
GUID应该是不管哪个平台下都应该是16bytes。
使用VS2005写了一个程序把DWORD,GUID,ULONG_PTR都sizeof了一下,确定这些数据类型在x64下的长度。

DWORD 4bytes
GUID  16bytes
ULONG_PTR 8bytes

所以SP_DEVICE_INTERFACE_DATA在64位下的大小应该是32bytes。之前在DELPHI程序中对SP_DEVICE_INTERFACE_DATA的定义是

SP_DEVICE_INTERFACE_DATA = record
 cbSize:Longword;
 InterfaceClassGuid:GUID;
 Flags:Longword;
 Reserved:Longword;
 end;



在XE2 x64平台下Longword仍然是4bytes,所以Reserved就应该用一个8字节的无符号数,去CSDN上问了一下用了UINT64代替。
修改为

SP_DEVICE_INTERFACE_DATA = record
 cbSize:Longword;
 InterfaceClassGuid:GUID;
 Flags:Longword;
 Reserved:UInt64;
 end;



重新编译了一下DELPHI工程,SetupDiEnumDeviceInterfaces接口执行正确,但是发现后面SetupDiGetDeviceInterfaceDetail接口执行又出现问题。

查了一下MSDN发现接口的第三个参数设置有需要注意的
If this parameter is specified, the caller must set DeviceInterfaceDetailData.cbSize to sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) before calling this function. The cbSize member always contains the size of the fixed part of the data structure, not a size reflecting the variable-length string at the end.
cbSize不能直接SizeOf整个长度,直接赋值8就OK了。

重新编译,就全部OK了。。

你可能感兴趣的:(Windows编程,程序员)