How to use the Native Wifi API with Windows API with Delphi

I am trying to use a function from the Windows API in 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 have been trying to use these features and others for several hours reading MSDN links and other sites, but I just can't get it to work.

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, it seems a lot of work, and I'm just new to delphi, I read a lot on the Internet, how do I work with this OpCode parameter, it 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

+4
source share
1 answer

In fact, you did not show what you called apiWlanOpenHandle , which, I think, would explain what the problem is. However, there is one very common mistake that is most likely confusing.

Consider the C API declaration:

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

The parameters that I suspect are causing problems are the last. Consider pdwNegotiatedVersion . This is a pointer to a DWORD . Since this is an out parameter, you must point to a pointer to the actual memory. I suspect you are simply declaring a variable of type PDWORD and passing it.

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

The WlanOpenHandle function then de-references this pointer and tries to write to memory. If you did not specify the correct pointer, this will not be done.

The naive solution is to change the calling code in this way:

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

This will work, but there is a cleaner way. Declare the import of the API as follows:

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

The out parameter of the DWORD type is actually passed as a pointer to the DWORD , which you pass as an argument to the function call. Then you can change the calling code this way:

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

Please note that I also added some error checking that you really should do.

The reason the Windows API function is declared using pointers is because C only supports passing parameters by value. It simply does not have a link passing, i.e. out or var in terms of Delphi. Languages ​​that support link passing should use them whenever they can.

Some Windows API functions have optional parameters declared as pointers. When this happens, pass NULL , because a pointer is a way to indicate that you do not want to pass a parameter. Translating these APIs into Delphi is more complicated. You need to implement the version using pointers to allow subscribers to refuse to submit the parameter. But it may be useful to provide an overloaded version that uses out or var for the convenience of the caller. The Delphi Windows block contains many such examples.


As for WlanHostedNetworkQueryProperty , I would declare it as follows:

 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 used the delayed tool because it is an API for Windows 7 and above. You probably want your program to run on older versions of Windows, and so additional download is required. For more information on loading delays in Delphi, see this answer and, in particular, further links.

Please note that the documentation in the MSDN topic you are linking to is incorrect. The pWlanOpcodeValueType parameter pWlanOpcodeValueType incorrectly specified in the MSDN topic. The correct definition, which can be found in wlanpi.h , is:

 __out PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType, 
+12
source

Source: https://habr.com/ru/post/1397234/


All Articles