Programatically Turning the Pocket PC WLAN Adapter On and Off

Here is another frequently requested Pocket PC programming trick. With the wide adoption of WiFi / 802.11x wireless for PDAs, Pocket PC developers very frequently want to programatically turn the wireless LAN adapter on their device on or off. There are various reasons for this, not least of which is the desire to exercise greater control over the power consumption of the wireless radio.

The trick to doing this is our friend the DeviceIoControl API. Basically what you need to do is this:

To power off the WLAN radio: Unbind the wireless adapter, then power it off.
To power on the WLAN radio: Power on the adapter, then bind it.

Here is the code:

// wlanutils.cpp : Defines the entry point for the DLL application.
//

#include
#include
#include
#include
#include
#include "wlanutils.h"

///
//Global definitions

//g_pszAdapterName --> Used for the multisz null terminated adapter string name for the
// IOCTL_NDIS_BIND_ADAPTER and IOCTL_NDIS_UNBIND_ADAPTER ioctls
// By the time this variable is needed, it is in the proper format.
TCHAR* g_pszAdapterName = NULL;
DWORD g_dwAdapterNameLen = 0;
//g_pszDriverName --> Contains the name of the active WLAN driver.
//This value corresponds to the SanDisk SDIO WiFi card.
//The driver name for your device may be different. Look in
//the device registry under HKLM/Drivers for yours.
TCHAR g_pszDriverName[] = TEXT("SDN1:");

//
//Public exported functions
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

int GetRadioState()
{
HANDLE hDriver = NULL;
DWORD dwBytesOut = 0;
CEDEVICE_POWER_STATE ps;
int nPowerState = GET_POWER_STATE_ERROR;

hDriver = ::CreateFile(g_pszDriverName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE != hDriver)
{
BOOL bRes = ::DeviceIoControl(hDriver, IOCTL_POWER_GET, NULL, 0, &ps, sizeof(ps), &dwBytesOut, NULL);
if (bRes) {
nPowerState = ((ps == D4)?GET_POWER_STATE_OFF:GET_POWER_STATE_ON); //Note: This treats all states but off as on, i.e, stanby is considered on
}
::CloseHandle(hDriver);
}
return (nPowerState);
}

//bPowerState paramter is TRUE to turn radio on, FALSE to turn off
BOOL PowerRadio(BOOL bPowerState)
{
HANDLE hNdis = NULL;
HANDLE hDriver = NULL;
BOOL bRes = FALSE;
DWORD dwBytesOut = 0;
DWORD dwError = 0;
CEDEVICE_POWER_STATE ps;

GetAdapterName();

ps = (bPowerState?D0:D4);

if (!bPowerState)
{ //Power off the radio
hNdis = ::CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE != hNdis)
{
bRes = ::DeviceIoControl(hNdis, IOCTL_NDIS_UNBIND_ADAPTER, g_pszAdapterName, g_dwAdapterNameLen, NULL, 0, &dwBytesOut, NULL);
if (bRes)
{
hDriver = ::CreateFile(g_pszDriverName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE != hDriver)
{
bRes = ::DeviceIoControl(hDriver, IOCTL_POWER_SET, NULL, 0, &ps, sizeof(ps), &dwBytesOut, NULL);
}
else bRes = FALSE;
::CloseHandle(hDriver);

}
::CloseHandle(hNdis);
}
}
else
{ //Power on the radio
hDriver = ::CreateFile(g_pszDriverName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE != hDriver)
{
bRes = ::DeviceIoControl(hDriver, IOCTL_POWER_SET, NULL, 0, &ps, sizeof(ps), &dwBytesOut, NULL);
if (bRes)
{
hNdis = ::CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE != hNdis)
{
bRes = ::DeviceIoControl(hNdis, IOCTL_NDIS_BIND_ADAPTER, g_pszAdapterName, g_dwAdapterNameLen, NULL, 0, &dwBytesOut, NULL);
::CloseHandle(hNdis);
}
else bRes = FALSE;
}
::CloseHandle(hDriver);
}
}
return (bRes);
}

///
//Internal functions
void GetAdapterName()
{
DWORD dwError = 0;
DWORD dwSize = 0;
::GetAdaptersInfo(NULL, &dwSize);
IP_ADAPTER_INFO* pInfo = (IP_ADAPTER_INFO*)new char[dwSize];
TCHAR pszAdapterName[MAX_ADAPTER_NAME_LENGTH+4];

if ((dwError = ::GetAdaptersInfo(pInfo, &dwSize)) == NO_ERROR)
{
IP_ADAPTER_INFO* pCurrentAdapter = pInfo;
while (pCurrentAdapter)
{
if (pCurrentAdapter->Type == MIB_IF_TYPE_ETHERNET)
{
MultiByteToWideChar( CP_ACP, 0, pCurrentAdapter->AdapterName, -1, pszAdapterName, sizeof(pszAdapterName) / sizeof(pszAdapterName[0]));
//We assume there is only one ethernet adapter per device
break;
}
pCurrentAdapter = pCurrentAdapter->Next;
}
}
//Add the terminating zeros required by the IOCTL_NDIS_BIND_ADAPTER and IOCTL_NDIS_UNBIND_ADAPTER ioctls
DWORD dwLen = _tcslen(pszAdapterName)*sizeof(TCHAR);
g_dwAdapterNameLen = (_tcslen(pszAdapterName)+3)*sizeof(TCHAR);
//Free previous use of the adapter name string
if (g_pszAdapterName != NULL) {
::LocalFree(g_pszAdapterName);
g_pszAdapterName = NULL;
}
g_pszAdapterName = (TCHAR*)::LocalAlloc(LPTR, g_dwAdapterNameLen);
memmove(g_pszAdapterName, pszAdapterName, dwLen);
delete [] pInfo;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值