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

Vit*_*.us 4 delphi dll winapi wlanapi

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

WlanOpenHandle

DWORD WINAPI WlanOpenHandle(
  __in        DWORD dwClientVersion,
  __reserved  PVOID pReserved,
  __out       PDWORD pdwNegotiatedVersion,
  __out       PHANDLE phClientHandle
);
Run Code Online (Sandbox Code Playgroud)

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
);
Run Code Online (Sandbox Code Playgroud)

我试图使用这些功能和其他人几个小时,阅读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;
Run Code Online (Sandbox Code Playgroud)

我正在尝试翻译这个API,似乎做了很多工作,我只是delphi的初学者,我在网上看了很多东西,我怎么处理这个OpCode参数,似乎是一个带有常量的C Struct,和PWLAN_OPCODE_VALUE_TYPE?

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

Dav*_*nan 14

你实际上没有告诉你如何调用apiWlanOpenHandle,我认为,这将解释问题是什么.然而,有一个非常常见的错误,很可能是让你困惑的错误.

考虑API的C声明:

DWORD WINAPI WlanOpenHandle(
  __in        DWORD dwClientVersion,
  __reserved  PVOID pReserved,
  __out       PDWORD pdwNegotiatedVersion,
  __out       PHANDLE phClientHandle
);
Run Code Online (Sandbox Code Playgroud)

我怀疑引起你问题的参数是最后两个.让我们考虑一下pdwNegotiatedVersion.这是指向a的指针DWORD.因为这是一个out参数,所以必须提供指向有效内存的指针.我怀疑你只是声明一个类型的变量PDWORD并传递它.

var
  NegotiatedVersionPtr: PDWORD;
begin
  WlanOpenHandle(...., NegotiatedVersionPtr, ...);
Run Code Online (Sandbox Code Playgroud)

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

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

var
  NegotiatedVersion: DWORD;
  NegotiatedVersionPtr: PDWORD;
begin
  NegotiatedVersionPtr := @NegotiatedVersion;
  WlanOpenHandle(...., NegotiatedVersionPtr, ...);
Run Code Online (Sandbox Code Playgroud)

这将有效,但有一个更清洁的方式.像这样声明API导入:

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

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
Run Code Online (Sandbox Code Playgroud)

请注意,我还添加了一些您应该做的错误检查.

使用指针声明Windows API函数的原因是C语言仅支持按值传递的参数.它只是没有传递引用,即out或者var用Delphi术语.支持pass-by-reference的语言应尽可能使用它们.

某些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;
Run Code Online (Sandbox Code Playgroud)

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

请注意,您链接到的MSDN主题中的文档不正确.pWlanOpcodeValueTypeMSDN主题中的参数声明不正确.正确的定义,可以找到的wlanpi.h是:

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,
Run Code Online (Sandbox Code Playgroud)