Domanda

Sto cercando di utilizzare una funzione di Windows API su Delphi, funzioni per Windows wlanapi.dll (API WiFi nativo)

Wlanopenhandle

DWORD WINAPI WlanOpenHandle(
  __in        DWORD dwClientVersion,
  __reserved  PVOID pReserved,
  __out       PDWORD pdwNegotiatedVersion,
  __out       PHANDLE phClientHandle
);

WlanhostednetworkQueryProperty

DWORD WINAPI WlanHostedNetworkQueryProperty(
  __in        HANDLE hClientHandle,
  __in        WLAN_HOSTED_NETWORK_OPCODE OpCode,
  __out       PDWORD pdwDataSize,
  __out       PVOID *ppvData,
  __out       PWLAN_OPCODE_VALUE_TYPE *pWlanOpcodeValueType,
  __reserved  PVOID pvReserved
);

Sto cercando di usare queste funzioni e altre per ore, leggendo i riferimenti MSDN e altri siti, ma non riesco proprio a farlo funzionare.

Il mio tentativo

type

  TWlanOpenHandle = function(  dwClientVersion:DWORD;
                               pReserved:Pointer;
                               pdwNegotiatedVersion:PDWORD;
                               phClientHandle:PHANDLE
                            ):DWORD; stdcall;

  function apiWlanOpenHandle(  dwClientVersion:DWORD;
                               pReserved:Pointer;
                               pdwNegotiatedVersion:PDWORD;
                               phClientHandle:PHANDLE
                      ):DWORD;


implementation

function apiWlanOpenHandle ( dwClientVersion:DWORD;  pReserved:Pointer; pdwNegotiatedVersion:PDWORD; phClientHandle:PHANDLE ):DWORD;
var
  WlanOpenHandle: TWlanOpenHandle;
  DLL: Cardinal;
begin
  DLL:=LoadLibrary('Wlanapi.dll');
  WlanOpenHandle := GetProcAddress(DLL, 'WlanOpenHandle');
  if Assigned(WlanOpenHandle) then
  begin
      WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, phClientHandle);
  end
  else begin
      ShowMessage('Function not found');
  end;
end;

Sto cercando di tradurre questa API, sembra un sacco di lavoro e sono solo un principiante a Delphi, ho letto un sacco di cose sul web, come faccio a gestire questo OpCode Parametro, sembra una struttura C con costanti e pwlan_opcode_value_type?

http://msdn.microsoft.com/en-us/library/windows/desktop/dd439502(v=vs.85).aspx

È stato utile?

Soluzione

In realtà non hai mostrato come hai chiamato apiWlanOpenHandle Il che, credo, spiegherebbe qual è il problema. Tuttavia, c'è un errore molto comune che è molto probabilmente ciò che ti sta confondendo.

Considera la dichiarazione C dell'API:

DWORD WINAPI WlanOpenHandle(
  __in        DWORD dwClientVersion,
  __reserved  PVOID pReserved,
  __out       PDWORD pdwNegotiatedVersion,
  __out       PHANDLE phClientHandle
);

I parametri che sospetto ti stiano causando problemi sono gli ultimi due. Lasciaci considerare pdwNegotiatedVersion. Questo è un puntatore a un DWORD. Poiché questo è un parametro Out, è necessario fornire un puntatore alla memoria valida. Sospetto che tu stia solo dichiarando una variabile di tipo PDWORD e passando quello.

var
  NegotiatedVersionPtr: PDWORD;
begin
  WlanOpenHandle(...., NegotiatedVersionPtr, ...);

La funzione WlanOpenHandle Quindi differenze quel puntatore e cerca di scrivere alla memoria. Se non hai dato un puntatore valido, questo fallirà.

La soluzione ingenua è cambiare il codice chiamante per assomigliare a questo:

var
  NegotiatedVersion: DWORD;
  NegotiatedVersionPtr: PDWORD;
begin
  NegotiatedVersionPtr := @NegotiatedVersion;
  WlanOpenHandle(...., NegotiatedVersionPtr, ...);

Funzionerà ma c'è un modo molto più pulito. Dichiarare l'importazione dell'API in questo modo:

function WlanOpenHandle(
    dwClientVersion: DWORD;
    pReserved: Pointer;
    out NegotiatedVersion: DWORD;
    out ClientHandle: THandle
): DWORD; stdcall; external 'Wlanapi.dll';

Un out parametro di tipo DWORD è effettivamente passato come puntatore al DWORD che fornisci come argomento alla chiamata della funzione. Puoi quindi modificare il tuo codice di chiamata per assomigliare a questo:

var
  ReturnValue: DWORD;
  NegotiatedVersion: DWORD;
  ClientHandle: THandle;
begin
  ReturnValue := WlanOpenHandle(2, nil, NegotiatedVersion, ClientHandle);
  if ReturnValue<>ERROR_SUCCESS then
    //respond to error

Nota che ho anche aggiunto un controllo degli errori che dovresti davvero fare.

Il motivo per cui la funzione API di Windows viene dichiarata usando i puntatori è che la lingua C supporta solo i parametri che passano per valore. Semplicemente non ha pass per riferimento, cioè out o var In termini di Delphi. Le lingue che supportano il passaggio pass-by-reference dovrebbero farne uso quando possono.

Alcune funzioni API di Windows hanno parametri opzionali dichiarati come puntatori. Quando questo è il caso che passa NULL Poiché il puntatore è il modo per segnalare che non si desidera passare un parametro. Tradurre quelle API in Delphi è più complesso. È necessario implementare una versione utilizzando i puntatori per consentire ai chiamanti di rinunciare alla fornitura del parametro. Ma può essere utile fornire una versione sovraccarica che utilizza out o var per comodità al chiamante. Il Delphi Windows L'unità contiene molti di questi esempi.


Quanto a WlanHostedNetworkQueryProperty, Lo dichiarerei così:

const
  // WLAN_HOSTED_NETWORK_OPCODE constants
  wlan_hosted_network_opcode_connection_settings = 0;
  wlan_hosted_network_opcode_security_settings   = 1;
  wlan_hosted_network_opcode_station_profile     = 2;
  wlan_hosted_network_opcode_enable              = 3;

  // WLAN_OPCODE_VALUE_TYPE constants
  wlan_opcode_value_type_query_only          = 0;
  wlan_opcode_value_type_set_by_group_policy = 1;
  wlan_opcode_value_type_set_by_user         = 2;
  wlan_opcode_value_type_invalid             = 3;


function WlanHostedNetworkQueryProperty(
  hClientHandle: THandle;
  OpCode: Integer;
  out DataSize: DWORD;
  out Data: Pointer;
  out WlanOpcodeValueType: Integer;
  Reserved: Pointer
): DWORD; external 'Wlanapi.dll' delayed;

Ho usato il delayed struttura perché si tratta di un'API di Windows 7 e UP. Presumibilmente vorrai che il tuo programma venga eseguito sulle versioni precedenti di Windows e quindi è necessario il caricamento del ritardo. Per ulteriori informazioni sul caricamento del ritardo in Delphi, vedere questa risposta, e in particolare i collegamenti successivi.

Si noti che la documentazione nell'argomento MSDN a cui si collega non è corretta. Il pWlanOpcodeValueType Il parametro è dichiarato erroneamente nell'argomento MSDN. La definizione corretta, quella che si trova in wlanpi.h è questo:

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top