如何在Delphi中使用"Native Wifi API" Windows API函数



我试图在delphi上使用Windows API的函数,Windows Wlanapi的函数.dll(Native WIFI API(

无线打开手柄

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

WLAN托管网络查询属性

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

我尝试使用此函数和其他函数数小时,阅读 MSDN 参考和其他站点,但我无法正常工作。

我的尝试

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;

正在尝试翻译这个 API,似乎有很多工作,我只是 delphi 的初学者,我在网上阅读了很多东西,我如何处理这个OpCode参数,似乎是一个带有常量的 C 结构,PWLAN_OPCODE_VALUE_TYPE?

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

你实际上并没有展示你是如何称呼apiWlanOpenHandle的,我认为,这可以解释问题是什么。但是,有一个非常常见的错误很可能使您感到困惑。

考虑 API 的 C 声明:

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

我怀疑给您带来问题的参数是最后两个。让我们考虑一下pdwNegotiatedVersion.这是指向DWORD的指针。由于这是一个 out 参数,因此必须提供指向有效内存的指针。我怀疑您只是在声明一个 PDWORD 类型的变量并传递它。

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

然后WlanOpenHandle该函数取消引用该指针并尝试写入内存。如果您没有给出有效的指针,那么这将失败。

天真的解决方案是将调用代码更改为如下所示:

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

这将起作用,但有一种更清洁的方法。像这样声明 API 导入:

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

类型 DWORDout 参数实际上作为指针传递到您作为函数调用的参数提供的DWORD。然后,可以将调用代码更改为如下所示:

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

请注意,我还添加了一些您确实应该执行的错误检查。

使用 指针声明 Windows API 函数的原因是 C 语言仅支持按值传递参数。它根本没有通过引用传递,即 outvar德尔菲术语。支持按引用传递的语言应尽可能使用它们。

某些 Windows API 函数将可选参数声明为指针。在这种情况下,传递NULL作为指针是发出您不希望传递参数的信号的方式。将这些API转换为Delphi更为复杂。您需要使用指针实现版本,以允许调用方选择不提供参数。但是,为了方便调用方,提供使用 outvar 的重载版本可能会很有帮助。德尔福Windows单元包含许多这样的例子。


至于WlanHostedNetworkQueryProperty,我会这样声明:

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;

我使用了delayed工具,因为这是一个Windows 7及更高版本的API。您可能希望程序在旧版本的Windows上运行,因此需要延迟加载。有关 Delphi 中延迟加载的更多信息,请参阅此答案,尤其是后续链接。

请注意,您链接到的 MSDN 主题中的文档不正确。pWlanOpcodeValueType参数在 MSDN 主题中声明不正确。正确的定义,在wlanpi.h中找到的定义是这样的:

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,

最新更新