Pregunta

Estoy tratando de usar una función de la API de Windows en Delphi, funciones para Windows wlanapi.dll (API WiFi nativa)

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
);

Intento usar estas funciones y otras durante horas, leyendo las referencias de MSDN y otros sitios, pero no puedo hacer que esto funcione.

Mi intento

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;

Estoy tratando de traducir esta API, parece mucho trabajo, y solo soy un principiante en Delphi, leo muchas cosas en la web, ¿cómo lato con esto? OpCode parámetro, parece una estructura C con constantes y pwlan_opcode_value_type?

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

¿Fue útil?

Solución

En realidad no mostraste cómo llamaste apiWlanOpenHandle Lo que creo que explicaría cuál es el problema. Sin embargo, hay un error muy común que probablemente sea lo que te confunde.

Considere la Declaración C de la API:

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

Los parámetros que sospecho que te están causando problemas son los dos últimos. Dejenos considerar pdwNegotiatedVersion. Este es un puntero a un DWORD. Debido a que este es un parámetro de salida, debe suministrar un puntero a la memoria válida. Sospecho que solo estás declarando una variable de tipo PDWORD Y pasando eso.

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

La función WlanOpenHandle Luego, las referencias de su puntero e intentan escribir en la memoria. Si no ha dado un puntero válido, esto fallará.

La solución ingenua es cambiar el código de llamadas para que se vea así:

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

Esto funcionará, pero hay una manera mucho más limpia. Declare la importación de la API así:

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

Un out Parámetro de tipo DWORD en realidad se pasa como un puntero al DWORD que proporciona como argumento a la llamada de función. Luego puede cambiar su código de llamada para que se vea así:

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

Tenga en cuenta que también he agregado algunas verificaciones de errores que realmente debería estar haciendo.

La razón por la que la función API de Windows se declara utilizando punteros es que el lenguaje C solo admite el paso de los parámetros por valor. Simplemente no tiene pases por referencia, es decir out o var en términos de Delphi. Los idiomas que admiten pasar por referencia deben usarlos cuando puedan.

Algunas funciones de la API de Windows tienen parámetros opcionales declarados como punteros. Cuando este es el caso pasando NULL Como el puntero es la forma de señalar que no desea pasar un parámetro. Traducir esas API a Delphi es más compleja. Debe implementar una versión utilizando punteros para permitir que las personas que llamen opten por suministrar el parámetro. Pero puede ser útil proporcionar una versión sobrecargada que use out o var por conveniencia para la persona que llama. El Delphi Windows La unidad contiene muchos de estos ejemplos.


Como para WlanHostedNetworkQueryProperty, Lo declararía así:

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;

He usado el delayed Instalación porque esta es una API de Windows 7 y UP. Presumiblemente, querrá que su programa se ejecute en versiones anteriores de Windows y, por lo tanto, se necesita retrasar la carga. Para obtener más información sobre la carga de retraso en Delphi, consulte esta respuesta, y particularmente los enlaces hacia adelante.

Tenga en cuenta que la documentación en el tema MSDN al que enlace es incorrecta. los pWlanOpcodeValueType El parámetro se declara incorrectamente en el tema MSDN. La definición correcta, la que se encuentra en wlanpi.h Es esto:

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top