我正在使用德尔福XE2,并试图将我们的usb通信动态链接库升级到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;发布于 2012-06-13 22:22:16
现在的更改是在JVCL中,请使用最新的SVN内容。
基本上,需要修复SetupApi,以便它在x64中使用“填充符”进行对齐。
这已经过测试,并且在这里运行良好。
发布于 2011-11-10 23:29:24
所以,经过大量的努力,我已经把它弄好了。尽管我必须深入研究JVCL SetupApi单元并更改一些结构的变量类型,但最终的修复并不是非常复杂。
repeat
TmpDeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
// showmessage('TSPDeviceInterfaceData: ' + inttostr(SizeOf(TSPDeviceInterfaceData)));
TmpSuccess := SetupDiEnumDeviceInterfaces(TmpDevInfo, nil, TmpDevHidGuid, TmpDevn, TmpDeviceInterfaceData);
if TmpSuccess then
begin
TmpDevData.cbSize := SizeOf(TmpDevData);
// showmessage('TmpDevData: ' + inttostr(tmpdevdata.cbsize));
TmpBytesReturned := 0;
SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, nil, 0, TmpBytesReturned, @TmpDevData);
//showmessage('bytes returned = ' + inttostr(TmpBytesReturned)); // = 170 in 32 bit app
inc(i);
if (TmpBytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
// showmessage('i did this ' + inttostr(i) + ' times');
TmpFunctionClassDeviceData := AllocMem(TmpBytesReturned);
{$ifdef CPUX64}
TmpFunctionClassDeviceData.cbSize := 8;
// showmessage('64 bit compiler used');
{$else}
TmpFunctionClassDeviceData.cbSize := 6;
// showmessage('32 bit compiler used');
{$endif}
// showmessage('TmpFunctionClassDeviceData:' + inttostr(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)));
if SetupDiGetDeviceInterfaceDetail(TmpDevInfo, @TmpDeviceInterfaceData, TmpFunctionClassDeviceData, TmpBytesReturned, TmpBytesReturned, @TmpDevData) then
begin
try
begin
//try to obtain PID and VID information about the HID devices
s := '';
for i := 0 to 999 do
begin
s := s + TmpFunctionClassDeviceData.DevicePath[i];
end;
TmpDeviceHandle := CreateFile(PChar(s),
GENERIC_READ OR GENERIC_WRITE,
FILE_SHARE_READ OR FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0 , 0);
TmpAttributes.Size := Sizeof(TmpAttributes);
// showmessage('TmpAttributes: ' + inttostr(Sizeof(TmpAttributes)));
HidD_GetAttributes(TmpDeviceHandle, TmpAttributes);
// showmessage(inttostr(TmpAttributes.VendorID) + ' ; ' + inttostr(TmpAttributes.ProductID));
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('bob ' + inttostr(GetLastError));
FreeMem(TmpFunctionClassDeviceData);
end;
end;
until not TmpSuccess;有关对SetupAPI.pas的更改,请参阅此处的绝地问题跟踪器条目:http://issuetracker.delphi-jedi.org/view.php?id=5706
如果有人能告诉我为什么在传递给CreateFile之前需要显式地将DevicePath复制到本地字符串中,或者为什么我不能将SizeOf用于TmpFunctionClassDeviceData.cbSize,我将非常感激。
https://stackoverflow.com/questions/8049889
复制相似问题