Click here to Skip to main content
15,886,798 members
Articles / Mobile Apps / Windows Mobile

Wifi scanner + custom MFC controls

Rate me:
Please Sign up or sign in to vote.
4.78/5 (29 votes)
30 Jul 2007CPOL16 min read 234.2K   10.2K   146  
A Wifi scanner with custom slider, tab control, buttons and checkboxes
#include "WifiPeek.h"

//////////////////////////////////////////////////////////////////////////
CWifiPeek::CWifiPeek()
{
	m_hNDUIO=NULL;
	InitializeCriticalSection(&m_Lock);
	OpenDriver();
}

//////////////////////////////////////////////////////////////////////////
CWifiPeek::~CWifiPeek()
{
	if(m_hNDUIO != NULL)
	{
		CloseDriver();
	}
	DeleteCriticalSection(&m_Lock);
}

//////////////////////////////////////////////////////////////////////////
//get list of usable adapters
bool CWifiPeek::GetAdapters(LPWSTR pDest, DWORD &dwBufSizeBytes)
{
HANDLE hFile;
BYTE Buffer[2048];
void *pvBuf;
WCHAR TmpBuf[1024];
WCHAR *pszOut;
DWORD dwRet;
bool retval;

	if(pDest == NULL || dwBufSizeBytes < sizeof(WCHAR))
	{
		dwBufSizeBytes=0;
		return false;
	}

	EnterCriticalSection(&m_Lock);
	retval=false;
	//open NDIS driver
	hFile=CreateFile(L"NDS0:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		pvBuf=(void *)(&Buffer[0]);
		dwRet=sizeof(Buffer);
		if(DeviceIoControl(hFile, IOCTL_NDIS_GET_ADAPTER_NAMES, NULL, 0, pvBuf, sizeof(Buffer), &dwRet, NULL))
		{
			//adapter list ok.
			LPWSTR pszStr;
			dwRet=0;
			pszOut=TmpBuf;

			//no string classes used, so no MFC or ATL dependency.
			for(pszStr=(LPWSTR)pvBuf; *pszStr; pszStr+=wcslen(pszStr)+1)
			{
				//check if adapter name is ok, skip infrared, gprs, ActiveSync etc.
				if(wcsicmp(pszStr, L"ASYNCMAC1") && \
					wcsicmp(pszStr, L"IRSIR1") && \
					wcsicmp(pszStr, L"L2TP1") && \
					wcsicmp(pszStr, L"PPTP1") && \
					wcsicmp(pszStr, L"RNDISFN1") && \
					wcsicmp(pszStr, L"WWAN1") && \
					wcsicmp(pszStr, L"XSC1_IRDA1"))
				{						
					//not the first adapter?
					if(pszOut != TmpBuf)
					{
						//append separator
						wcscat(pszOut, L",");
						pszOut++;
						dwRet+=sizeof(WCHAR);
					}
					wcscpy(pszOut, pszStr);
					pszOut+=wcslen(pszStr);
					dwRet+=sizeof(WCHAR) * wcslen(pszStr);
				}
			}
			//return required buffer size anyway
			dwBufSizeBytes=dwRet;

			//if buffer large enough, copy adapter names
			if(dwBufSizeBytes >= dwRet)
			{
				wcsncpy(pDest, TmpBuf, dwRet);
				retval=true;
			}
			//otherwise will return false
			//..
		}
		CloseHandle(hFile);
	}
	LeaveCriticalSection(&m_Lock);
	return retval;
}

//////////////////////////////////////////////////////////////////////////
//open the NDISUIO driver
bool CWifiPeek::OpenDriver()
{
HANDLE hDev;

	//already opened?
	if(m_hNDUIO != NULL)
	{
		return true;
	}

	hDev=CreateFile(NDISUIO_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, INVALID_HANDLE_VALUE);
	if(hDev == INVALID_HANDLE_VALUE)
	{
		return false;
	}
	else
	{
		m_hNDUIO=hDev;
		return true;
	}
}

//////////////////////////////////////////////////////////////////////////
//at the end, close NDISUIO handle
void CWifiPeek::CloseDriver()
{
	CloseHandle(m_hNDUIO);
	m_hNDUIO=NULL;
}

//////////////////////////////////////////////////////////////////////////
//initiate station scanning
bool CWifiPeek::RefreshBSSIDs(LPWSTR pAdapter)
{
NDISUIO_SET_OID nso;
DWORD dwBytesRet;
bool retval;

	EnterCriticalSection(&m_Lock);
	nso.ptcDeviceName = pAdapter;
	nso.Oid = OID_802_11_BSSID_LIST_SCAN;

	dwBytesRet=0;
	if(!DeviceIoControl(m_hNDUIO, IOCTL_NDISUIO_SET_OID_VALUE, (void *)&nso, sizeof(NDISUIO_SET_OID), NULL, 0, &dwBytesRet, NULL))
	{
		retval=false;
	}
	else
	{
		retval=true;
	}
	LeaveCriticalSection(&m_Lock);
	return retval;
}

//////////////////////////////////////////////////////////////////////////
//get a list of currently visible stations
bool CWifiPeek::GetBBSIDs(LPWSTR pAdapter, struct BSSIDInfo *pDest, DWORD &dwBufSizeBytes, DWORD &dwReturnedItems)
{
PNDISUIO_QUERY_OID pNQO;
DWORD dwBytesRet;
BYTE Buffer[8192], *pByte;
PNDIS_802_11_BSSID_LIST pList;
int i;

	if(pDest == NULL)
	{
		dwReturnedItems=0;
		return false;
	}

	EnterCriticalSection(&m_Lock);	
	pNQO=(PNDISUIO_QUERY_OID)Buffer;

	pNQO->ptcDeviceName = pAdapter;
	pNQO->Oid=OID_802_11_BSSID_LIST;

	// Run query
	dwBytesRet = 0;
	if(!DeviceIoControl(m_hNDUIO, IOCTL_NDISUIO_QUERY_OID_VALUE, (void *)pNQO, 8192, (void *)pNQO, 8192, &dwBytesRet, NULL))
	{
		GetLastError();
		LeaveCriticalSection(&m_Lock);
		return false;
	}

	pList=(PNDIS_802_11_BSSID_LIST)&pNQO->Data;
	dwReturnedItems=pList->NumberOfItems;

	//first item in array
	PNDIS_WLAN_BSSID pItem=pList->Bssid;

	for(i=0; i<pList->NumberOfItems; i++)
	{
		memcpy(pDest[i].BSSID, pItem->MacAddress, sizeof(pItem->MacAddress));
		mbstowcs(pDest[i].SSID, (char *)pItem->Ssid.Ssid, sizeof(pItem->Ssid.Ssid));
		pDest[i].RSSI=pItem->Rssi;
		if(pItem->Configuration.DSConfig > 14)
		{
			pDest[i].Channel=(pItem->Configuration.DSConfig - 2407000) / 5000;
		}
		else
		{
			pDest[i].Channel=pItem->Configuration.DSConfig;
		}
		pDest[i].Auth=pItem->Privacy;
		pDest[i].Infastructure=pItem->InfrastructureMode;

		//some pointer magic...actually pItem->Length was not sizeof(NDIS_WLAN_BSSID)
		//so use returned length
		pByte=(BYTE *)pItem;
		pByte+=pItem->Length;
		pItem=(PNDIS_WLAN_BSSID)pByte;
	}//for

	LeaveCriticalSection(&m_Lock);
	return true;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Hungary Hungary
I'm a 29-year old software developer. I began programming on a ZX Spectrum many years ago. I've programmed a number of high level languages (Basic, Pascal, C/C++, Java, Php, Perl, C#). I also like reverse-engineering and assembler programming.
I'm interested in handheld devices programming, especially Windows Mobile devices.

Comments and Discussions