Sorry, I don't have any code to show. That might make this question a candidate for Programmers, but they don't have language specific areas here and I am seeking a Delphi solution, so I will ask here. I hope that that is acceptable.
Basically, I want to auto-launch my VPN whenever WiFi becomes connected. How would I detect that? Google, it seems, is not my friend in this matter.
The required WinApi calls are not implemented in Delphi - you have to define and call them yourself. In this case, the relevant functions are :
WlanOpenHandle (MSDN)
WlanRegisterNotification (MSDN)
WLAN_NOTIFICATION_SOURCE structure (MSDN)
You would define these as :
const
wlanapi = 'wlanapi.dll';
WLAN_NOTIFICATION_SOURCE_ACM = $00000008;
type
GUID = TGUID;
HANDLE = THandle;
PWLanNotificationData = ^TWLanNotificationData;
TWLanNotificationData = record
NotificationSource: DWORD;
NotificationCode: DWORD;
InterfaceGuid: GUID;
dwDataSize: DWORD;
pData: PVOID;
end;
TWLanNotificationCallback = procedure(data: PWLanNotificationData; context: PVOID); stdcall;
function WlanOpenHandle(dwClientVersion: DWORD; pReserved: PVOID;
out pdwNegotiatedVersion: DWORD; out phClientHandle: HANDLE): DWORD; stdcall;
external wlanapi name 'WlanOpenHandle';
function WlanRegisterNotification(hClientHandle: HANDLE; dwNotifSource: DWORD;
bIgnoreDuplicate: BOOL; funcCallback: TWLanNotificationCallback; pCallbackContext: PVOID;
pReserved: PVOID; out pdwPrevNotifSource: DWORD): DWORD; stdcall;
external wlanapi name 'WlanRegisterNotification';
And call them as :
// Define a callback procedure to handle the notifications
// You can supply a context pointer to any user information the callback
// may require (pointer to object, etc)
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
// ShowMessage(IntToStr(data^.NotificationCode)); etc...
end;
// Register for notification
procedure TForm1.FormCreate(Sender: TObject);
var
negotiatedVer : DWORD;
prevSource : DWORD
begin
if WlanOpenHandle(2, nil, negotiatedVer, FHandle) <> ERROR_SUCCESS then begin
// handle error...
end;
// check negotiatedVersion if needed
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
nil,
nil,
prevSource) <> ERROR_SUCCESS then begin
end;
This registers you for WLAN notifications. Your callback function will execute upon receiving notifications and the nature of the notification can be found in the TWlanNotificationData
structure passed to that method.
You should also un-register for notifications when no longer needed. I've only implemented rudimentary error checking here. The details for the various error codes can be found in the referenced MSDN documentation.
A (partial) list of ACM notifications :
const
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED = $00000001;
//Autoconfiguration is enabled.
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED = $00000002;
//Autoconfiguration is disabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED = $00000003;
//Background scans are enabled.
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED = $00000004;
//Background scans are disabled.
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE = $00000005;
//The BSS type for an interface has changed.
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE = $00000006;
//The power setting for an interface has changed.
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE = $00000007;
//A scan for networks has completed.
WLAN_NOTIFICATION_ACM_SCAN_FAIL = $00000008;
//A scan for connectable networks failed.
WLAN_NOTIFICATION_ACM_CONNECTION_START = $00000009;
//A connection has started to a network in range.
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE = $0000000a;
//A connection has completed.
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL = $0000000b;
//A connection attempt has failed.
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE = $0000000c;
//A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL = $0000000d;
//A wireless LAN interface is been added to or enabled on the local computer.
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL = $0000000e;
//A wireless LAN interface has been removed or disabled on the local computer.
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE = $0000000f;
//A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE = $00000010;
//A profile name has changed, either through group policy or by calls to Native Wifi functions.
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED = $00000011;
//All profiles were exhausted in an attempt to autoconnect.
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE = $00000012;
//The wireless service cannot find any connectable network after a scan.
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE = $00000013;
//The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect .
WLAN_NOTIFICATION_ACM_DISCONNECTING = $00000014;
//The wireless service is disconnecting from a connectable network.
WLAN_NOTIFICATION_ACM_DISCONNECTED = $00000015;
//The wireless service has disconnected from a connectable network.
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE = $00000016;
//A state change has occurred for an adhoc network.
Second example callback with more detail :
procedure OnWlanNotify(data : PWLanNotificationData; context : PVOID); stdcall;
begin
case data^.NotificationCode of
WLAN_NOTIFICATION_ACM_AUTOCONF_ENABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is enabled.');
WLAN_NOTIFICATION_ACM_AUTOCONF_DISABLED :
TForm1(context^).Memo1.Lines.Add('Autoconfiguration is disabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_ENABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are enabled.');
WLAN_NOTIFICATION_ACM_BACKGROUND_SCAN_DISABLED :
TForm1(context^).Memo1.Lines.Add('Background scans are disabled.');
WLAN_NOTIFICATION_ACM_BSS_TYPE_CHANGE :
TForm1(context^).Memo1.Lines.Add('The BSS type for an interface has changed.');
WLAN_NOTIFICATION_ACM_POWER_SETTING_CHANGE :
TForm1(context^).Memo1.Lines.Add('The power setting for an interface has changed.');
WLAN_NOTIFICATION_ACM_SCAN_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A scan for networks has completed.');
WLAN_NOTIFICATION_ACM_SCAN_FAIL :
TForm1(context^).Memo1.Lines.Add('A scan for connectable networks failed.');
WLAN_NOTIFICATION_ACM_CONNECTION_START :
TForm1(context^).Memo1.Lines.Add('A connection has started to a network in range.');
WLAN_NOTIFICATION_ACM_CONNECTION_COMPLETE :
TForm1(context^).Memo1.Lines.Add('A connection has completed.');
WLAN_NOTIFICATION_ACM_CONNECTION_ATTEMPT_FAIL :
TForm1(context^).Memo1.Lines.Add('A connection attempt has failed.');
WLAN_NOTIFICATION_ACM_FILTER_LIST_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in the filter list has occurred, either through group policy or a call to the WlanSetFilterList function.');
WLAN_NOTIFICATION_ACM_INTERFACE_ARRIVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface is been added to or enabled on the local computer.');
WLAN_NOTIFICATION_ACM_INTERFACE_REMOVAL :
TForm1(context^).Memo1.Lines.Add('A wireless LAN interface has been removed or disabled on the local computer.');
WLAN_NOTIFICATION_ACM_PROFILE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A change in a profile or the profile list has occurred, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILE_NAME_CHANGE :
TForm1(context^).Memo1.Lines.Add('A profile name has changed, either through group policy or by calls to Native Wifi functions.');
WLAN_NOTIFICATION_ACM_PROFILES_EXHAUSTED :
TForm1(context^).Memo1.Lines.Add('All profiles were exhausted in an attempt to autoconnect.');
WLAN_NOTIFICATION_ACM_NETWORK_NOT_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service cannot find any connectable network after a scan.');
WLAN_NOTIFICATION_ACM_NETWORK_AVAILABLE :
TForm1(context^).Memo1.Lines.Add('The wireless service found a connectable network after a scan, the interface was in the disconnected state, and there is no compatible auto-connect profile that the wireless service can use to connect.');
WLAN_NOTIFICATION_ACM_DISCONNECTING :
TForm1(context^).Memo1.Lines.Add('The wireless service is disconnecting from a connectable network.');
WLAN_NOTIFICATION_ACM_DISCONNECTED :
TForm1(context^).Memo1.Lines.Add('The wireless service has disconnected from a connectable network.');
WLAN_NOTIFICATION_ACM_ADHOC_NETWORK_STATE_CHANGE :
TForm1(context^).Memo1.Lines.Add('A state change has occurred for an adhoc network.');
end;
end;
In the above example, a pointer to Form1
was passed in the user context parameter. This is passed back in the callback, allowing you to access that data from within the method.
if WlanRegisterNotification(FHandle,
WLAN_NOTIFICATION_SOURCE_ACM,
LongBool(true),
@OnWlanNotify,
@Form1, // Pass in form pointer
nil,
prevSource) <> ERROR_SUCCESS then begin
// handle error
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With