Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Last active January 1, 2025 22:54
Show Gist options
  • Save ArtemGr/29a5ce08f468c00d905f6dd49e791a32 to your computer and use it in GitHub Desktop.
Save ArtemGr/29a5ce08f468c00d905f6dd49e791a32 to your computer and use it in GitHub Desktop.
// fomat-macros = "0.3"
// gstuff = {version = "^0.8.20", features = ["crossterm", "fomat-macros", "inlinable_string", "nightly", "re"]}
// scopeguard = "1"
// winapi = {version = "0.3", features = ["wlanapi"]}
#![allow(non_snake_case)]
#![allow(uncommon_codepoints)]
use fomat_macros::fomat;
use gstuff::{fail, log};
use gstuff::re::Re;
use std::mem::MaybeUninit;
use std::ptr::null_mut;
use winapi::ctypes::c_void;
use winapi::shared::wlantypes::dot11_BSS_type_any;
use winapi::um::wlanapi::{self, WlanConnect, WlanCloseHandle, WlanDisconnect};
use wlanapi::{WLAN_AVAILABLE_NETWORK_HAS_PROFILE, WLAN_INTERFACE_INFO_LIST};
use wlanapi::{WLAN_CONNECTION_PARAMETERS, WLAN_AVAILABLE_NETWORK_LIST, WLAN_AVAILABLE_NETWORK_CONNECTED};
use wlanapi::{WlanEnumInterfaces, WlanFreeMemory, WlanGetAvailableNetworkList, WlanOpenHandle};
fn wifi() -> Re<()> {unsafe {
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlanopenhandle
let (mut dwNegotiatedVersion, mut hClientHandle) = (0, null_mut());
let rc = WlanOpenHandle (2, null_mut(), &mut dwNegotiatedVersion, &mut hClientHandle);
let _close = scopeguard::guard ((), |_| {if !hClientHandle.is_null() {WlanCloseHandle (hClientHandle, null_mut());}});
if rc != 0 {fail! ("!WlanOpenHandle")}
if dwNegotiatedVersion < 2 {fail! ([=dwNegotiatedVersion])}
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlanenuminterfaces
let mut waˡ: *mut WLAN_INTERFACE_INFO_LIST = null_mut();
let rc = WlanEnumInterfaces (hClientHandle, null_mut(), &mut waˡ);
let _free = scopeguard::guard ((), |_| {if !waˡ.is_null() {WlanFreeMemory (waˡ as *mut c_void)}});
if rc != 0 {fail! ("!WlanEnumInterfaces")}
for ii in 0 .. (*waˡ).dwNumberOfItems as usize {
let interface = (*waˡ).InterfaceInfo.as_ptr().add (ii);
let description = String::from_utf16_lossy (&(*interface).strInterfaceDescription);
log! ([=description]);
let pInterfaceGuid = &(*interface).InterfaceGuid;
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlangetavailablenetworklist
let mut wnˡ: *mut WLAN_AVAILABLE_NETWORK_LIST = null_mut();
let rc = WlanGetAvailableNetworkList (hClientHandle, pInterfaceGuid, 0, null_mut(), &mut wnˡ);
let _free = scopeguard::guard ((), |_| {if !wnˡ.is_null() {WlanFreeMemory (wnˡ as *mut c_void)}});
if rc != 0 {fail! ("!WlanGetAvailableNetworkList")}
for ni in 0 .. (*wnˡ).dwNumberOfItems as usize {
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/ns-wlanapi-wlan_available_network
let net = (*wnˡ).Network.as_ptr().add (ni);
if (*net).bNetworkConnectable == 0 {continue}
let ssid = String::from_utf8_lossy (&(*net).dot11Ssid.ucSSID);
log! ([=ssid]);
let connected = 0 != (*net).dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED;
let has_profile = 0 != (*net).dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE;
log! ([=(*net).wlanSignalQuality] ", " [=connected] ", " [=has_profile]);
if connected {
log! ("disconnect..");
let rc = WlanDisconnect (hClientHandle, pInterfaceGuid, null_mut());
if rc != 0 {fail! ("!WlanDisconnect")}
break}
if has_profile {
log! ("connect..");
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlanconnect
let mut pa: WLAN_CONNECTION_PARAMETERS = MaybeUninit::zeroed().assume_init();
pa.strProfile = (*net).strProfileName.as_ptr();
pa.dot11BssType = dot11_BSS_type_any;
let rc = WlanConnect (hClientHandle, pInterfaceGuid, &mut pa, null_mut());
if rc != 0 {fail! ("!WlanConnect")}
break}}}
// https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlanscan
Re::Ok(())}}
fn main() {wifi().unwrap()}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment