Cómo usar las funciones de la API de Windows de "API WiFi" con Delphi "
Pregunta
Estoy tratando de usar una función de la API de Windows en Delphi, funciones para Windows wlanapi.dll (API WiFi nativa)
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
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,