在 64 位应用程序中使用 SetupAPI 枚举 USB HID 设备
我正在使用 Delphi XE2 并尝试将我们的 usb comms dll 升级到 64 位。我们使用 JVCL SetupAPI 和 Hid 单元。使用 32 位编译器一切正常,并且可以看到我连接的 HID 设备。我切换到 64 位后,再也看不到任何我所知道的已连接的 HID 设备。
我遇到过有人提到需要针对 64 位调整某些数据结构的大小(请参阅 https:// /forums.embarcadero.com/thread.jspa?messageID=408473#408473)这有帮助,但我现在正式难住了。
目前我的代码返回从 SetupDiGetDeviceInterfaceDetail 函数读取的 0 字节。注释掉的 SizeOf() 适用于 32 位,但不适用于 64 位。
任何帮助将不胜感激。
repeat
TmpDeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
TmpDeviceInterfaceData.cbSize := 32; // SizeOf(TmpDeviceInterfaceData);
TmpSuccess := SetupDiEnumDeviceInterfaces(TmpDevInfo, nil, TmpDevHidGuid, TmpDevn, TmpDeviceInterfaceData);
if TmpSuccess then
begin
TmpDevData.cbSize := 32; //SizeOf(TmpDevData);
showmessage(inttostr(tmpdevdata.cbsize));
TmpBytesReturned := 0;
SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, nil, 0, TmpBytesReturned, @TmpDevData);
showmessage('bytes returned = ' + inttostr(TmpBytesReturned));
if (TmpBytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
// showmessage('hello');
TmpFunctionClassDeviceData := AllocMem(TmpBytesReturned);
TmpFunctionClassDeviceData.cbSize := sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
TmpFunctionClassDeviceData.cbSize := 8;
// showmessage(inttostr(TmpFunctionClassDeviceData.cbSize));
if SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, TmpFunctionClassDeviceData, TmpBytesReturned, TmpBytesReturned, @TmpDevData) then
begin
// showmessage('here');
try
begin
//try to obtain PID and VID information about the HID devices
TmpDeviceHandle := CreateFile(@TmpFunctionClassDeviceData.DevicePath,
GENERIC_READ OR GENERIC_WRITE,
FILE_SHARE_READ OR FILE_SHARE_WRITE,
NIL, OPEN_EXISTING, 0 , 0);
TmpAttributes.Size := Sizeof(TmpAttributes);
HidD_GetAttributes(TmpDeviceHandle, TmpAttributes);
If (vid = TmpAttributes.VendorID) then
begin
PIDlistStr := PIDlistStr + Inttostr(TmpAttributes.ProductID) + ',';
end ;
if TmpDeviceHandle <> INVALID_HANDLE_VALUE then
begin
CloseHandle(TmpDeviceHandle);
TmpAttributes.ProductID := 0;
TmpAttributes.VendorID := 0;
end;
TmpDeviceHandle := INVALID_HANDLE_VALUE;
end
except
// ignore device if unreadable
end;
Inc(TmpDevn);
end
else
showmessage('error in SetupDiGetDeviceInterfaceDetails');
FreeMem(TmpFunctionClassDeviceData);
end;
end;
until not TmpSuccess;
I am using Delphi XE2 and attempting to upgrade our usb comms dll to 64 bit. We're using the JVCL SetupAPI and Hid units. All works perfectly using 32 bit compiler and can see my attached HID device. I switch to 64 bit and I can no longer see any of the HID devices that I know are attached.
I have come across people mentioning the need to resize some of the data structures differently for 64 bit (see https://forums.embarcadero.com/thread.jspa?messageID=408473#408473) and this has helped but I am now officially stumped.
Currently my code is returning 0 bytes read from the SetupDiGetDeviceInterfaceDetail function. The commented out SizeOf() were working for 32 bit but not for 64 bit.
Any help would be much appreciated.
repeat
TmpDeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
TmpDeviceInterfaceData.cbSize := 32; // SizeOf(TmpDeviceInterfaceData);
TmpSuccess := SetupDiEnumDeviceInterfaces(TmpDevInfo, nil, TmpDevHidGuid, TmpDevn, TmpDeviceInterfaceData);
if TmpSuccess then
begin
TmpDevData.cbSize := 32; //SizeOf(TmpDevData);
showmessage(inttostr(tmpdevdata.cbsize));
TmpBytesReturned := 0;
SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, nil, 0, TmpBytesReturned, @TmpDevData);
showmessage('bytes returned = ' + inttostr(TmpBytesReturned));
if (TmpBytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
// showmessage('hello');
TmpFunctionClassDeviceData := AllocMem(TmpBytesReturned);
TmpFunctionClassDeviceData.cbSize := sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
TmpFunctionClassDeviceData.cbSize := 8;
// showmessage(inttostr(TmpFunctionClassDeviceData.cbSize));
if SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, TmpFunctionClassDeviceData, TmpBytesReturned, TmpBytesReturned, @TmpDevData) then
begin
// showmessage('here');
try
begin
//try to obtain PID and VID information about the HID devices
TmpDeviceHandle := CreateFile(@TmpFunctionClassDeviceData.DevicePath,
GENERIC_READ OR GENERIC_WRITE,
FILE_SHARE_READ OR FILE_SHARE_WRITE,
NIL, OPEN_EXISTING, 0 , 0);
TmpAttributes.Size := Sizeof(TmpAttributes);
HidD_GetAttributes(TmpDeviceHandle, TmpAttributes);
If (vid = TmpAttributes.VendorID) then
begin
PIDlistStr := PIDlistStr + Inttostr(TmpAttributes.ProductID) + ',';
end ;
if TmpDeviceHandle <> INVALID_HANDLE_VALUE then
begin
CloseHandle(TmpDeviceHandle);
TmpAttributes.ProductID := 0;
TmpAttributes.VendorID := 0;
end;
TmpDeviceHandle := INVALID_HANDLE_VALUE;
end
except
// ignore device if unreadable
end;
Inc(TmpDevn);
end
else
showmessage('error in SetupDiGetDeviceInterfaceDetails');
FreeMem(TmpFunctionClassDeviceData);
end;
end;
until not TmpSuccess;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
现在更改在JVCL中,请使用最新的SVN内容。
基本上,需要修复 SetupApi,以便它使用 x64 中的“填充程序”进行对齐。
这已经过测试并且在这里运行良好。
The changes now are in the JVCL, please use the latest SVN content.
Basically, there was a need to fix SetupApi so that it uses a "filler" in x64 for alignment.
This has been tested and works well here.
因此,经过艰苦的努力,我已经完成了这项工作。最终的修复并不太复杂,尽管我确实必须深入研究 JVCL SetupApi 单元并更改某些结构的变量类型。
有关对 SetupAPI.pas 的更改,请参阅我的 jedi 问题跟踪器条目:http:// issuestracker.delphi-jedi.org/view.php?id=5706
如果有人可以告诉我为什么在传递给 CreateFile 之前需要将 DevicePath 显式复制到本地字符串中,或者为什么我不能使用SizeOf 为 TmpFunctionClassDeviceData.cbSize,我将非常感激。
So, after much hard work I have got this working. The eventual fix is not overly complicated, although I did have to delve in to the JVCL SetupApi unit and change some structure's variable types.
For the changes to SetupAPI.pas see my jedi issue tracker entry here: http://issuetracker.delphi-jedi.org/view.php?id=5706
If anyone can tell me why the DevicePath needs to be explicitly copied in to a local string before being passed to CreateFile, or why I can't use SizeOf for TmpFunctionClassDeviceData.cbSize, I would be much obliged.