2011-11-08 8 views
5

में SetupAPI का उपयोग कर यूएसबी छिपाई उपकरणों का आकलन करना मैं डेल्फी एक्सई 2 का उपयोग कर रहा हूं और हमारे यूएसबी कॉमर्स डीएल को 64 बिट में अपग्रेड करने का प्रयास कर रहा हूं। हम जेवीसीएल सेटअपअप और छुपा इकाइयों का उपयोग कर रहे हैं। सभी 32 बिट कंपाइलर का पूरी तरह से काम करते हैं और मेरे संलग्न एचआईडी डिवाइस देख सकते हैं। मैं 64 बिट पर स्विच करता हूं और अब मैं किसी भी छिपाई डिवाइस को नहीं देख सकता जो मुझे पता है।64 बिट ऐप

मैं 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 में हैं, कृपया नवीनतम एसवीएन सामग्री का उपयोग करें।

असल में, SetupApi को ठीक करने की आवश्यकता थी ताकि यह संरेखण के लिए x64 में "filler" का उपयोग कर सके।

यह परीक्षण किया गया है और यहां अच्छी तरह से काम करता है।

0

तो, बहुत मेहनत के बाद मुझे यह काम मिल गया है। अंतिम फिक्स अत्यधिक जटिल नहीं है, हालांकि मुझे 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

किसी को भी मुझे बता सकते हैं तो क्यों DevicePath स्पष्ट CreateFile करने के लिए पारित किया जा रहा से पहले एक स्थानीय स्ट्रिंग के लिए में नकल करने की आवश्यकता है , या मैं TmpFunctionClassDeviceData.cbSize के लिए SizeOf का उपयोग क्यों नहीं कर सकता, मैं बहुत बाध्य होगा।

+0

> क्यों DevicePath स्पष्ट एमएस के रूप में कॉपी किया जा करने की जरूरत है यहाँ का कहना है: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552343%28v=vs.85%29 .aspx > डिवाइसपाथ > एक पूर्ण-समाप्त स्ट्रिंग जिसमें डिवाइस इंटरफ़ेस पथ होता है। यह पथ Win32 फ़ंक्शंस जैसे CreateFile को पास किया जा सकता है। szDevicePath: = पीसीहर (@ TmpFunctionClassDeviceData.DevicePath [0]); CreateFile को पास करने के लिए उस मान का उपयोग करें। –