如何使用“本机Wifi API” Windows API功能与Delphi [英] How to use "Native Wifi API" Windows API functions with Delphi

查看:234
本文介绍了如何使用“本机Wifi API” Windows API功能与Delphi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Delphi上使用Windows API的功能,Windows Wlanapi.dll(Native WIFI API)的功能

Im trying to use a function from Windows API on delp functions for Windows Wlanapi.dll (Native 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参考和其他站点,但我只是不能得到这个工作。

I trying to use this functions and others for hours, reading the MSDN references and others sites, but I just can't get this working.

我的尝试

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?

I'm trying to translate this API, seems a lot of work, and I'm just a beginner in delp I read a lot of stuff on the web, how do I deal with this OpCode parameter, seems a C Struct with constants, and PWLAN_OPCODE_VALUE_TYPE?

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

推荐答案

您没有真正显示您如何调用 apiWlanOpenHandle ,我认为这将解释问题。但是,有一个很常见的错误很可能是令你困惑的。

You didn't actually show how you called apiWlanOpenHandle which would, I think, explain what the problem is. However, there's one very common mistake that is most likely what is confusing you.

考虑API的C声明:

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

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

The parameters that I suspect are causing you problems are the final two. Let us consider pdwNegotiatedVersion. This is a pointer to a DWORD. Because this is an out parameter you must supply a pointer to valid memory. I suspect you are just declaring a variable of type PDWORD and passing that.

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

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

The function WlanOpenHandle then de-references that pointer and tries to write to the memory. If you have not given a valid pointer then this will fail.

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

The naive solution is to change the calling code to look like this:

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

这将工作,但有一个更清洁的方式。声明API导入如下:

This will work but there is a much cleaner way. Declare the API import like this:

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

out $ c> DWORD 实际上作为一个指针传递给您作为函数调用参数的 DWORD 。你可以改变你的电话代码看起来像这样:

An out parameter of type DWORD is actually passed as a pointer to the DWORD that you supply as the argument to the function call. You can then change your calling code to look like this:

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

注意我还添加了一些您真正应该做的错误检查。

Note that I have also added some error checking which you really ought to be doing.

使用指针声明Windows API函数的原因是C语言仅支持参数通过价值。在Delphi中,它根本没有通过引用,即 out var 。支持传递参考的语言应该可以使用它们。

The reason that the Windows API function is declared using pointers is that the C language only supports parameter passing by value. It simply does not have pass-by-reference, i.e. out or var in Delphi terms. Languages that do support pass-by-reference should make use of them when they can.

某些Windows API函数具有声明为指针的可选参数。当这是通过 NULL 的情况,因为指针是表示您不希望传递参数的方式。将这些API转换为Delphi更为复杂。您需要使用指针实现一个版本,以允许呼叫者选择不提供参数。但是,为方便呼叫者,提供使用 out var 的重载版本是有帮助的。 Delphi Windows 单元包含许多此类示例。

Some Windows API functions have optional parameters declared as pointers. When this is the case passing NULL as the pointer is the way to signal that you do not wish to pass a parameter. Translating those APIs to Delphi is more complex. You need to implement a version using pointers to allow callers to opt-out of supplying the parameter. But it can be helpful to supply an overloaded version that uses out or var for convenience to the caller. The Delphi Windows unit contains many such examples.

至于 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;

我使用了延迟的是Windows 7和更高版本的API。您可能希望程序运行在旧版本的Windows上,因此需要延迟加载。有关Delphi中延迟加载的更多信息,请参阅此答案,特别是前面的链接。

I have used the delayed facility because this is a Windows 7 and up API. You will presumably want your program to run on older versions of Windows and so delay loading is needed. For more information on delay loading in Delp see this answer, and particularly the onward links.

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

Note that the documentation in the MSDN topic to which you link is incorrect. The pWlanOpcodeValueType parameter is declared incorrectly in the MSDN topic. The correct definition, the one to be found in wlanpi.h is this:

__out    PWLAN_OPCODE_VALUE_TYPE     pWlanOpcodeValueType,

这篇关于如何使用“本机Wifi API” Windows API功能与Delphi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆