如何在Delphi中使用“Native Wifi API”Windows API函数(How to use “Native Wifi API” Windows API functions with D

编程入门 行业动态 更新时间:2024-10-25 15:20:25
如何在Delphi中使用“Native Wifi API”Windows API函数(How to use “Native Wifi API” Windows API functions with Delphi)

我试图从Windows API上使用delphi函数,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参数,看起来OpCode一个带有常量的C结构,和PWLAN_OPCODE_VALUE_TYPE?

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

Im trying to use a function from Windows API on delphi, 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 );

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.

My attempt

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;

I'm trying to translate this API, seems a lot of work, and I'm just a beginner in delphi, 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=vs.85).aspx

最满意答案

你实际上并没有展示你如何调用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语言仅支持按值传递参数。 它根本没有传递引用,即德尔斐条件中的out或var 。 支持通过引用的语言应尽可能使用它们。

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

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

__out PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType,

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.

Consider the C declaration of the API:

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

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

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

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

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.

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.

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.


As for WlanHostedNetworkQueryProperty, I would declare it like this:

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;

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 Delphi, see this answer, and particularly the onward links.

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,

更多推荐

本文发布于:2023-07-19 01:06:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1169717.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   如何在   Native   Delphi   Wifi

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!