【问题标题】:How to use "Native Wifi API" Windows API functions with Delphi如何在 Delphi 中使用“Native Wifi API”Windows API 函数
【发布时间】:2012-02-18 23:00:27
【问题描述】:

我正在尝试在 delphi 上使用来自 Windows API 的函数,用于 Windows Wlanapi.dll(本机 WIFI API)的函数

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

我尝试使用这个功能和其他几个小时,阅读 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参数,似乎带有常量和 PWLAN_OPCODE_VALUE_TYPE 的 C 结构?

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

【问题讨论】:

标签: delphi winapi dll wlanapi


【解决方案1】:

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

考虑 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';

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

某些 Windows API 函数具有声明为指针的可选参数。在这种情况下,将NULL 作为指针传递是表示您不希望传递参数的方式。将这些 API 转换为 Delphi 更为复杂。您需要使用指针实现一个版本,以允许调用者选择不提供参数。但是为了方便调用者,提供一个使用outvar 的重载版本会很有帮助。 Delphi 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 中延迟加载的更多信息,请参阅this answer,尤其是后续链接。

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

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,

【讨论】:

  • 谢谢,我写这篇文章是为了帮助我vitim.us/test/Convert_C_to_Delphi.htm 这并不能神奇地解决整个问题,只是减少了我的工作量。
  • 我还有一个问题,也许你能帮帮我,这个另一个函数msdn.microsoft.com/en-us/library/windows/desktop/…,我如何处理这个不是默认类型的参数,这个typedef C Struct。我可以声明为记录吗?
  • 我没有看到结构,只有 2 个枚举。在 wlanapi.h 中查找值。通过安装对此类工作必不可少的 Windows SDK 来获取。
  • 非常感谢,在您的帮助下,我几乎翻译了一半的标题!
猜你喜欢
  • 1970-01-01
  • 2019-08-02
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多