2017-01-25 31 views
0

私はWlanGetNetworkBssListを呼び出してデバッグ作業に取り掛かりました。私の最終目標は、リモートサイトでのネットワークの問題のトラブルシューティングに役立つWifiスキャナ/プロファイラツールを構築することです。WlanAPI WlanGetNetworkBssListが無効なデータを返す

WindowsネイティブWifi API(link)とDelphi/Pascalインターフェイスhereは、Windows 10(VCL)のDelphi Berlin 10.1 Update 2を使用しています。

シンプルで粗いテストアプリ(VCL)でAPIの感触を始めて、WlanGetNetworkBssListという問題が発生したので、その問題に焦点を当てた小型のコンソールアプリを作成しました。問題は、コマンドプロンプトで実行中のコンソールアプリでは動作しますが、VCLテストアプリでは動作しません。機能はかなりコピーペースト等価であり、コードサイドバイサイドをステップは、データがWlanGetNetworkBssListコール(pWlanBssList)

質問からの戻りデータを除いて同一であることを示している:コールがであるので外部DLLこれをさらにデバッグしてVCLとコンソールアプリケーションの違いを理解するには、どのような手順が必要ですか?

注:WlanGetNetworkBssListには、特定のSSIDのBSSID(アクセスポイントのMAC)を取得するためにSSIDを提供できる2つの操作モードがあります。 SSIDの代わりにNULLを渡すことで、APIはすべてのAPのBSSIDを返します。 NULLを渡すことは、VLCとコンソールアプリケーションの両方で機能します。特定のSSIDが要求されたときに何が中断しますか。検証後、SSIDデータ構造は両方のアプリケーションで同じですが、返されるデータバッファはVCLアプリケーションでは無効です。どうすればいいの?

コンソールアプリ:VCLアプリの

program CWifiScan; 

{$APPTYPE CONSOLE} 

uses 
    Windows, 
    System.SysUtils, 
    nduWlanAPI, 
    nduWlanTypes; 
const 
    WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = $00000001; 
var 
    hWlan: THandle; 
    guid : TGUID; 
    dwSupportedVersion: DWORD = 0; 
    dwClientVersion: DWORD = 1; 
    i,j     : integer; 
    pInterfaceInfo  : Pndu_WLAN_INTERFACE_INFO; 
    pInterfaceList  : Pndu_WLAN_INTERFACE_INFO_LIST; 
    pAvailableNetworkList : Pndu_WLAN_AVAILABLE_NETWORK_LIST; 

procedure GetBSSIDList(clientHandle : THandle; 
          interfaceGUID : TGUID; 
          pSSID   : Pndu_DOT11_SSID = nil; 
          SSID_Type  : Tndu_DOT11_BSS_Type = dot11_BSS_type_any; 
          SecurityEnabled : BOOL = True); 
var 
    //to check if interface is connected 
    pData   : Pndu_WLAN_INTERFACE_STATE; 
    pdwDataSize : DWORD; 
    isConnected : Boolean; 
    //to get list of BSSids from available APs 
    pWlanBssList : Pndu_WLAN_BSS_LIST; 
    items   : integer; 
    itemIndex  : integer; 
    SSID   : string; 
    MAC   : string; 
begin 
    //check if interface is connected 
    isConnected := False; 
    if WlanQueryInterface(clientHandle, 
         @interfaceGUID, 
         wlan_intf_opcode_interface_state, 
         nil, 
         @pdwDataSize, 
         @pData, 
         nil) = ERROR_SUCCESS then 
    begin 
    isConnected := (pData^ = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected); 
    end; 

    //get the list of BSSids for the provided interface 
    if isConnected then 
    begin 
    if WlanGetNetworkBssList(clientHandle, 
          @interfaceGUID, 
          pSSID, 
          SSID_Type, 
          SecurityEnabled, 
          nil, 
          @pWlanBssList) = ERROR_SUCCESS then 
    begin 
     items := pWlanBssList^.dwNumberOfItems; 
     for itemIndex := 0 to items - 1 do 
     begin 

     SSID := String(PAnsiChar(@pWlanBssList^.wlanBssEntries[itemIndex].dot11Ssid.ucSSID)); 

     MAC := Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x', [ 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[0], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[1], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[2], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[3], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[4], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[5]]); 

     Writeln(''); 
     Writeln('SSID: ................ '+SSID); 
     Writeln('Physical Address: .... '+MAC); 
     end; {for itemIndex} 
     Writeln(#10+#13+'Done.'); 
    end; {WlanGetNetworkBssList succeeds} 

    end; {isConnected} 
end; 

begin 
    hWlan := 0; 

    if WlanOpenHandle(2, nil,@dwSupportedVersion, @hWlan)= ERROR_SUCCESS then 
    begin 
    if WlanEnumInterfaces(hWlan, nil, @pInterfaceList) = ERROR_SUCCESS then 
    begin 
     try 
     for i := 0 to pInterfaceList^.dwNumberOfItems-1 do 
      begin 
      Writeln('Wifi Adapter - '+GUIDToString(pInterfaceList^.InterfaceInfo[i].InterfaceGuid)); 
      Writeln('Scanning: .... '+pInterfaceList^.InterfaceInfo[i].strInterfaceDescription); 
      guid := pInterfaceList^.InterfaceInfo[i].InterfaceGuid; 

      //Get all BSSids for this interface 
      GetBSSIDList(hWlan, guid); 

      if WlanGetAvailableNetworkList(hWlan, 
              @guid, 
              WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES, 
              nil, 
              pAvailableNetworkList) = ERROR_SUCCESS then 
      begin 
       try 
       for j := 0 to pAvailableNetworkList^.dwNumberOfItems - 1 do 
        begin 

        //Get BSSid for this specific SSID 
        GetBSSIDList(hWlan, 
           guid, 
           @pAvailableNetworkList^.Network[j].dot11Ssid, 
           pAvailableNetworkList^.Network[j].dot11BssType, 
           pAvailableNetworkList^.Network[j].bSecurityEnabled); 

        end; 
       finally 
       if pAvailableNetworkList<>nil then 
        WlanFreeMemory(pAvailableNetworkList); 
       end; 
      end; 

      end; 
     finally 
     if pInterfaceList<>nil then 
      WlanFreeMemory(pInterfaceList); 
     end; 
    end; 

    WlanCloseHandle(hWlan, nil); 

    readln; 

    end; 
end. 

関連する部分は、次のとおりと呼ばれている

uses 
    ... nduWlanAPI, nduWlanTypes, nduWinDot11; 


function TForm1.GetBSSID(clientHandle: THandle; 
         interfaceGuid: TGUID; 
         pSSID: Pndu_DOT11_SSID = nil; 
         SSID_Type : Tndu_DOT11_BSS_TYPE = dot11_BSS_type_any; 
         SecurityEnabled: boolean = true): string; 
var 
    //used to determin if the interface is connected 
    pData  : Pndu_WLAN_INTERFACE_STATE; 
    isConnected : boolean; 
    //used to extract a list of BSSIDs for a given interface 
    pWlanBssList : Pndu_WLAN_BSS_LIST; 

    lastError  : DWORD; 
    pdwDataSize : DWORD; 
    items, 
    itemIndex: Integer; 
begin 
    pData := nil; 
    pdwDataSize := 0; 
    isConnected := False; 

    //check if the interface is connected 
    lastError := WlanQueryInterface(clientHandle, 
           @interfaceGuid, 
           wlan_intf_opcode_interface_state, 
           nil, 
           @pdwDataSize, 
           @pData, 
           nil); 
    if (lastError = ERROR_SUCCESS) then 
    begin 
    //isConnected := (Tndu_WLAN_INTERFACE_STATE(pData^.isState) = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected); 
    isConnected := (pData^ = Tndu_WLAN_INTERFACE_STATE.wlan_interface_state_connected); 
    end 
    else 
     DisplayError('Error in WlanQueryInterface() function', lastError); 

    if isConnected then 
    begin 
    pWlanBssList := nil; 

    lastError := WlanGetNetworkBssList(clientHandle, 
             @interfaceGuid, 
             pSSID, 
             SSID_Type, 
             SecurityEnabled, 
             nil, 
             @pWlanBssList); 

    try 

     if (lastError = ERROR_SUCCESS) then 
     begin 

     items := pWlanBssList^.dwNumberOfItems; 
     for itemIndex := 0 to items-1 do 
     begin 

      Result := (Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x', [ 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[0], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[1], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[2], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[3], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[4], 
        pWlanBssList^.wlanBssEntries[itemIndex].dot11Bssid[5]])); 

     end; 
     end 
     else 
     DisplayError('Error in the WlanGetNetworkBssList() function call', lastError); 

    finally 
     if pData<>nil then 
     WlanFreeMemory(pData); 

     if pWlanBssList<>nil then 
     WlanFreeMemory(pWlanBssList); 
    end; 
    end; 
end; 

は次のとおりです。

function TForm1.ScanWifi(): THandle; 
const 
    WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = $00000001; 
var 
    hClient    : THandle; 
    dwVersion   : DWORD; 
    lastError   : DWORD; 
    pInterface   : Pndu_WLAN_INTERFACE_INFO_LIST; 
    i     : Integer; 
    j     : Integer; 
    pAvailableNetworkList: Pndu_WLAN_AVAILABLE_NETWORK_LIST; 
    interfaceGuid  : TGUID; 
    BSSID    : string; 
begin 
    lastError:=WlanOpenHandle(NDU_WLAN_API_VERSION, nil, @dwVersion, @hClient); 
    if lastError<> ERROR_SUCCESS then 
    begin 
    //DisplayError('Error in the WlanOpenHandle() function call', lastError); 
    Result := 0; 
    Exit; 
    end; 

    //L(Format('Requested WLAN interface version [%d], negotiated version [%d]', [NDU_WLAN_API_VERSION, dwVersion])); 
    Result := hClient; 

    try 

     lastError:=WlanEnumInterfaces(hClient, nil, @pInterface); 

     try 
     if lastError<> ERROR_SUCCESS then 
     begin 
      //DisplayError('Errorin the WlanEnumInterfaces() function call', lastError); 
      Exit; 
     end; 

     for i := 0 to pInterface^.dwNumberOfItems - 1 do 
     begin 
      interfaceGuid:= pInterface^.InterfaceInfo[i].InterfaceGuid; 

      lastError:=WlanGetAvailableNetworkList(hClient, 
               @interfaceGuid, 
               WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES, 
               nil, 
               pAvailableNetworkList); 

      try 
      if lastError<> ERROR_SUCCESS then 
      begin 
       //DisplayError('Error WlanGetAvailableNetworkList', lastError); 

       Exit; 
      end 
      else 
      begin 
       for j := 0 to pAvailableNetworkList^.dwNumberOfItems - 1 do 
       Begin 

       BSSID := GetBssid(hClient, 
            interfaceGuid, 
            @pAvailableNetworkList^.Network[j].dot11Ssid, 
            pAvailableNetworkList^.Network[j].dot11BssType, 
            pAvailableNetworkList^.Network[j].bSecurityEnabled 
       ); 

       //FAPList.AddOrSetValue(BSSID,J); 

       end; 
      end; 

      finally 
      if pAvailableNetworkList <> nil then 
       WlanFreeMemory(pAvailableNetworkList); 
      end; 

     end; 
     finally 
     if pInterface <> nil then 
      WlanFreeMemory(pInterface); 
     end; 


    finally 
    WlanCloseHandle(FhClient, nil); 
    end; 

end; 

を2つのアプリケーション間でデータを比較すると、唯一の違いは、ここに見られる結果(pWlanBssList)です(left = console、right = VCL): enter image description here

答えて

2

問題はVCLコードで

SecurityEnabled: boolean = true 

をラインに従っている、ブールの変換ではコンパイラのバグのように見えるあなたは絶対にそれだった

SecurityEnabled: bool = true 
+0

にそれを変更する必要があります。そして、最悪のことは、それがコンソールアプリケーションのBOOLだが、私はVCLアプリケーションのその違いを逃した。コードを見て回ってくれてありがとう。 – lowrider

関連する問題