4

我试图在 delphi 上使用 Windows API 中的函数,Windows Wlanapi.dll 的函数(本机 WIFI API)

WLANOpenHandle

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

WlanHostedNetworkQuery 属性

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 Struct,和 PWLAN_OPCODE_VALUE_TYPE?

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

4

1 回答 1

14

您实际上并没有展示您如何调用apiWlanOpenHandlewhich 我认为可以解释问题所在。但是,有一个非常常见的错误很可能让您感到困惑。

考虑 API 的 C 声明:

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

我怀疑导致您出现问题的参数是最后两个。让我们考虑一下pdwNegotiatedVersion。这是一个指向DWORD. 因为这是一个输出参数,所以您必须提供一个指向有效内存的指针。我怀疑你只是在声明一个类型的变量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';

out类型参数DWORD实际上是作为指向您作为参数提供给函数调用的指针传递的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在 Delphi 术语中。支持传递引用的语言应该尽可能使用它们。

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


至于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,
于 2012-02-18T23:19:22.230 回答