2011-11-08 79 views
5

私はDelphi XE2を使用しており、usb comms dllを64ビットにアップグレードしようとしています。 JVCL SetupAPIとHidユニットを使用しています。すべてが32ビットコンパイラを使用して完全に動作し、付属のHIDデバイスを見ることができます。 64ビットに切り替えると、私が知っているHIDデバイスが見えなくなります。64ビットアプリケーションでSetupAPIを使用してUSB 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; 

答えて

0

変更は現在JVCLにありますので、最新のSVNコンテンツをご利用ください。

基本的に、x64の「フィラー」をアライメントに使用するようにSetupApiを修正する必要がありました。

これはテスト済みで、ここではうまくいきます。

0

このように、私はこれまで多くの努力を重ねてきました。最終的な修正はあまり複雑ではありませんが、私はJVCL SetupApiユニットを掘り下げて構造の変数タイプを変更しなければなりませんでした。 SetupAPI.pasへの変更については

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; 

は、ここに私のジェダイIssue Trackerのエントリを参照してください。 http://issuetracker.delphi-jedi.org/view.php?id=5706

DevicePathのは、明示的にCreateFileに渡される前に地元の文字列にしてコピーする必要がある、なぜ誰も私を伝えることができた場合、またはTmpFunctionClassDeviceData.cbSizeにSizeOfを使用できない理由は、私は非常に義務づけられています。

+0

> DevicePathのMSは、ここで言うように、明示的に をコピーする必要がある理由: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552343%28v=vs.85%29 .aspx > DevicePath >デバイスインターフェイスパスを含むNULLで終了する文字列。このパスは、CreateFileなどのWin32関数に渡すことができます。 szDevicePath:= PChar(@ TmpFunctionClassDeviceData.DevicePath [0]); は、その値をCreateFileに渡すために使用します。 –

関連する問題