/**
* Program that demonstrates some of the functionality in Windows to
* manipulate the WLAN environment.
*
* @author: Asanga Udugama (adu@comnets.uni-bremen.de)
*
*/

#include "stdafx.h"
#include <windows.h>
#include <conio.h>
#include <atlbase.h>
#include <iostream>
#include <wlanapi.h>

DWORD dClientVersion, dNegotiatedVersion;
HANDLE hClientHandle;
PWLAN_INTERFACE_INFO_LIST pInterfaceList;
DWORD dSelectedInterfaceIndex;
PWLAN_CONNECTION_ATTRIBUTES pCurrentConnInfo;
DWORD       dwSize;

INT iReqestedOp, iContinue;

/**
* Select a network interface function that uses WLAN API
* to get the wireless interface list.
*/
DWORD SelectNetworkInterface()
{
       DWORD rtn;

       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       pInterfaceList = NULL;
       rtn = WlanEnumInterfaces(hClientHandle, NULL, &pInterfaceList);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanEnumInterfaces: %d\n", rtn);
              return rtn;
       }

       _tprintf("List of WLAN Interfaces\n");

       for(pInterfaceList->dwIndex = 0; pInterfaceList->dwIndex < pInterfaceList->dwNumberOfItems; pInterfaceList->dwIndex++)
       {
              CW2T szIfcName(pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].strInterfaceDescription);
              _tprintf("%2d - %s\n", (pInterfaceList->dwIndex + 1), szIfcName);
       }

       dSelectedInterfaceIndex = 11000;
       while(dSelectedInterfaceIndex < 1 || dSelectedInterfaceIndex > pInterfaceList->dwNumberOfItems)
       {
              fflush(stdin);
              dSelectedInterfaceIndex = 11000;
              _tprintf("\n");
              _tprintf("Select the interface by typing the number and pressing enter - ");
              _tscanf_s("%d", &dSelectedInterfaceIndex);
       }

       pInterfaceList->dwIndex = dSelectedInterfaceIndex - 1;

       return rtn;
}

/**
* Shows a list of wireless interfaces using WLAN API.
*
*/
DWORD ListWLANInterfaceswithWLANAPI()
{
       DWORD rtn;

       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       pInterfaceList = NULL;
       rtn = WlanEnumInterfaces(hClientHandle, NULL, &pInterfaceList);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanEnumInterfaces: %d\n", rtn);
              return rtn;
       }

       for(pInterfaceList->dwIndex = 0; pInterfaceList->dwIndex < pInterfaceList->dwNumberOfItems; pInterfaceList->dwIndex++)
       {
              CW2T szIfcName(pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].strInterfaceDescription);
              _tprintf("%2d - %s\n", (pInterfaceList->dwIndex + 1), szIfcName);
       }

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);
       return rtn;
}

/**
* Shows the list of network interfaces using the registry.
*
*/
DWORD ListWLANInterfacesusingRegistry()
{
       LONG rtn, rtn2;
       HKEY hNICListKey, hNICKey;
       INT i;
       TCHAR szKeyName[256];
       DWORD dwSize, dwSize2;
       FILETIME ftFileTime;
       TCHAR szFullKeyName[256];
       TCHAR szDevInfo[256];
       TCHAR szDevDesc[256];
       DWORD dwType;

       rtn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                                          "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards",
                                          0, KEY_READ, &hNICListKey);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in RegOpenKeyEx: %d\n", rtn);
              return rtn;
       }

       dwSize = 256;
       i = 0;
       rtn = RegEnumKeyEx(hNICListKey, i, szKeyName,
                                                 &dwSize, NULL, NULL, NULL,
                                                 &ftFileTime);
       while(rtn == ERROR_SUCCESS)
       {
              _stprintf_s(szFullKeyName, 256,
                     "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\%s",
                     szKeyName);

              rtn2 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKeyName,
0, KEY_READ, &hNICKey);
              if(rtn2 != ERROR_SUCCESS)
              {
                     i++;
                     continue;
              }

              dwType = REG_SZ;
              dwSize2 = 256;
              memset(szDevInfo, 0, 256);
              rtn2 = RegQueryValueEx(hNICKey, "ServiceName", NULL,
                                          &dwType, (BYTE *) szDevInfo, &dwSize2);
              if(rtn2 != ERROR_SUCCESS)
              {
                     i++;
                     continue;
              }

              dwType = REG_SZ;
              dwSize2 = 256;
              memset(szDevDesc, 0, 256);
              rtn = RegQueryValueEx(hNICKey, "Description", NULL,
                                          &dwType, (BYTE *) szDevDesc, &dwSize2);
              if(rtn2 != ERROR_SUCCESS)
              {
                     i++;
                     continue;
              }
              RegCloseKey(hNICKey);

              _tprintf("%2d - %s\n", (i + 1), szDevDesc);

              i++;
              dwSize = 256;
              rtn = RegEnumKeyEx(hNICListKey, i, szKeyName,
                                                 &dwSize, NULL, NULL, NULL,
                                                 &ftFileTime);
       }

       RegCloseKey(hNICListKey);


       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn2;
}

/**
* Show the connected AP info using the WLAN API.
*/
DWORD ShowConnectedAPwithWLANAPI()
{
       DWORD rtn;
       TCHAR szCurrentESSID[256];
       TCHAR szCurrentMACAddressStr[256];
       INT iCurrentRSSI;
       INT iCurrentLinkQuality;

       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       // get connected AP info from WLAN API
       dwSize = 0;
       pCurrentConnInfo = NULL;
       rtn = WlanQueryInterface(hClientHandle,
                                   &pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                   wlan_intf_opcode_current_connection,
                                   NULL,
                                   &dwSize,
                                   (PVOID *) &pCurrentConnInfo,
                                   NULL);
       if(rtn == ERROR_INVALID_STATE)
       {
              // that means not connected to any AP
              rtn = ERROR_SUCCESS;

              if(pCurrentConnInfo != NULL)
              {
                     WlanFreeMemory((PVOID) pCurrentConnInfo);
              }

              // close handle
              WlanCloseHandle(hClientHandle, NULL);

              _tprintf("Not connected to any AP\n");

              return rtn;
       }
       else if(rtn != ERROR_SUCCESS)
       {
              if(pCurrentConnInfo != NULL)
              {
                     WlanFreeMemory((PVOID) pCurrentConnInfo);
              }

              // close handle
              WlanCloseHandle(hClientHandle, NULL);

              _tprintf("Error occured in WlanQueryInterface: %d\n", rtn);

              return rtn;
       }

       CW2T szESSID(pCurrentConnInfo->strProfileName);
       memset(szCurrentESSID, 0, 256);
       memcpy(szCurrentESSID, szESSID, 256);

       memset(szCurrentMACAddressStr, 0, 256);
       _stprintf_s(szCurrentMACAddressStr, 256, "%02x:%02x:%02x:%02x:%02x:%02x",
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[0],
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[1],
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[2],
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[3],
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[4],
              pCurrentConnInfo->wlanAssociationAttributes.dot11Bssid[5]);

       iCurrentRSSI = (pCurrentConnInfo->wlanAssociationAttributes.wlanSignalQuality / 2) - 100;
       iCurrentLinkQuality = pCurrentConnInfo->wlanAssociationAttributes.wlanSignalQuality;

       rtn = ERROR_SUCCESS;

       if(pCurrentConnInfo != NULL)
       {
              WlanFreeMemory((PVOID) pCurrentConnInfo);
       }

       // close handle
       WlanCloseHandle(hClientHandle, NULL);

       _tprintf("Network Name (Profile Name): %s\n", szCurrentESSID);
       _tprintf("AP MAC Address : %s\n", szCurrentMACAddressStr);
       _tprintf("RSSI : %d\n", iCurrentRSSI);
       _tprintf("Link Quality : %d\n", iCurrentLinkQuality);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Show the connected AP info using the NDIS 802.11 IOCTLs.
*/
INT ShowConnectedAPwithNDIS()
{
       INT       rtn;
       TCHAR szCurrentESSID[256];
       TCHAR szCurrentMACAddressStr[256];
       INT iCurrentRSSI;
       INT iCurrentLinkQuality;
       NDIS_802_11_RSSI ndisRSSI;
       NDIS_802_11_SSID ndisESSID;
       NDIS_802_11_MAC_ADDRESS ndisMACAddress;
       WCHAR       wsNICGUIDinString[256];
       char       sNICIDFullPath[256];
       DWORD       dwMemSize;
       ULONG       ulBytesReturned;
       ULONG       ulOIDCode;

       // open handle
       memset(wsNICGUIDinString, 0, 256);
       memset(sNICIDFullPath, 0, 256);
       StringFromGUID2(pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                          wsNICGUIDinString, 256);
       sprintf_s(sNICIDFullPath, "\\\\.\\%S", wsNICGUIDinString);
       hClientHandle = CreateFileA(sNICIDFullPath, GENERIC_READ | GENERIC_WRITE,
                                                                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                                             NULL, OPEN_EXISTING,
                                                                             0, NULL) ;

       if(hClientHandle == INVALID_HANDLE_VALUE)
       {
              _tprintf("Error in CreateFileA\n");
              return 0;
       }

       // call to get connected ESSID
       dwMemSize = sizeof(NDIS_802_11_SSID);
       ulOIDCode = OID_802_11_SSID;
       ulBytesReturned = 0;
       rtn = DeviceIoControl(hClientHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS,
                                                 &ulOIDCode, sizeof(ulOIDCode), (ULONG *) &ndisESSID,
                                                 dwMemSize, &ulBytesReturned, NULL);
       if(rtn == 0)
       {
              _tprintf("Error in DeviceIoControl\n");
              CloseHandle(hClientHandle);
              return rtn;
       }
       memset(szCurrentESSID, 0, 256);
       memcpy(szCurrentESSID, ndisESSID.Ssid, ndisESSID.SsidLength);


       // call to get connected MAC Address
       dwMemSize = sizeof(NDIS_802_11_MAC_ADDRESS);
       ulOIDCode = OID_802_11_BSSID;
       ulBytesReturned = 0;
       rtn = DeviceIoControl(hClientHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS,
                                                 &ulOIDCode, sizeof(ulOIDCode), (ULONG *) &ndisMACAddress,
                                                 dwMemSize, &ulBytesReturned, NULL);
       if(rtn == 0)
       {
              _tprintf("Error in DeviceIoControl\n");
              CloseHandle(hClientHandle);
              return rtn;
       }
       memset(szCurrentMACAddressStr, 0, 256);
       _stprintf_s(szCurrentMACAddressStr, 256, "%02x:%02x:%02x:%02x:%02x:%02x",
              ndisMACAddress[0],
              ndisMACAddress[1],
              ndisMACAddress[2],
              ndisMACAddress[3],
              ndisMACAddress[4],
              ndisMACAddress[5]);

       // call to get RSSI
       ndisRSSI = 0;
       dwMemSize = sizeof(NDIS_802_11_RSSI);
       ulOIDCode = OID_802_11_RSSI;
       ulBytesReturned = 0;
       rtn = DeviceIoControl(hClientHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS,
                                                 &ulOIDCode, sizeof(ulOIDCode), (ULONG *) &ndisRSSI,
                                                 dwMemSize, &ulBytesReturned, NULL);
       if(rtn == 0)
       {
              _tprintf("Error in DeviceIoControl\n");
              CloseHandle(hClientHandle);
              return rtn;
       }

       // close handle
       CloseHandle(hClientHandle);

       iCurrentRSSI = ndisRSSI;
       // MS computes link quality as follows;
       // range 1 to 100, maps rssi from -100 to -50, linear interpolation
       iCurrentLinkQuality = (ndisRSSI + 100) * 2;
       if(iCurrentLinkQuality < 0)
       {
              iCurrentLinkQuality = 0;
       }
       else if(iCurrentLinkQuality > 100)
       {
              iCurrentLinkQuality = 100;
       }

       _tprintf("Network Name (Profile Name): %s\n", szCurrentESSID);
       _tprintf("AP MAC Address : %s\n", szCurrentMACAddressStr);
       _tprintf("RSSI : %d\n", iCurrentRSSI);
       _tprintf("Link Quality : %d\n", iCurrentLinkQuality);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Issue a scan to find the visible APs using the WLAN API.
*/
DWORD ScanwithWLANAPI()
{
       DWORD rtn;

       // open handle for scanning
       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       // send scan commmand
       rtn = WlanScan(hClientHandle,
                                   &pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                   NULL, NULL, NULL);

       // close handle
       WlanCloseHandle(hClientHandle, NULL);

       _tprintf("Scan issued...\n");

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Issue a scan to find the visible APs using the NDIS 802.11 IOCTL.
*
* Note: This function doesn't seem to be working. I will have to figure
* this out, later.
*/
DWORD ScanwithNDIS()
{
       INT rtn;
       WCHAR       wsNICGUIDinString[256];
       char       sNICIDFullPath[256];
       DWORD       dwMemSize;
       ULONG       ulBytesReturned;
       ULONG       ulOIDCode;

       // open handle
       memset(wsNICGUIDinString, 0, 256);
       memset(sNICIDFullPath, 0, 256);
       StringFromGUID2(pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                          wsNICGUIDinString, 256);
       sprintf_s(sNICIDFullPath, "\\\\.\\%S", wsNICGUIDinString);
       //hClientHandle = CreateFileA(sNICIDFullPath, GENERIC_READ | GENERIC_WRITE,
       //                                                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
       //                                                                      NULL, OPEN_EXISTING,
       //                                                                      0, NULL) ;
       hClientHandle = CreateFileA(sNICIDFullPath, GENERIC_READ,
                                                                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                                             NULL, OPEN_EXISTING,
                                                                             0, NULL) ;

       if(hClientHandle == INVALID_HANDLE_VALUE)
       {
              _tprintf("Error in CreateFileA\n");
              return 0;
       }

       // call to get connected ESSID
       dwMemSize = 0;
       ulOIDCode = OID_802_11_BSSID_LIST_SCAN;
       ulOIDCode |= 0x00800000;
       ulBytesReturned = 0;
       rtn = DeviceIoControl(hClientHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS,
                                                 &ulOIDCode, sizeof(ulOIDCode), (ULONG *) NULL,
                                                 dwMemSize, &ulBytesReturned, NULL);
       if(rtn == 0)
       {
                     DWORD errnum = GetLastError();
              _tprintf("Error in DeviceIoControl\n");
              CloseHandle(hClientHandle);
              return rtn;
       }

       // close handle
       CloseHandle(hClientHandle);

       _tprintf("Scan issued...\n");

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Show the list of WLAN networks currently visible. This uses the WLAN API
* and it only shows information by SSIDs and not by BSSIDs.
*
* Only a few pieces of information are printed. The structure
* WLAN_AVAILABLE_NETWORK has more information.
*/
DWORD ShowNetworkListwithWLANAPI()
{
       DWORD rtn;
       PWLAN_AVAILABLE_NETWORK_LIST pNwList;
       PWLAN_AVAILABLE_NETWORK pAvailableNw;
       TCHAR szESSIDStr1[256];
       UINT i, j;

       // open handle for scanning
       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       pNwList = NULL;
       rtn = WlanGetAvailableNetworkList(hClientHandle,
                                   &pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                   WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,
                                   NULL,
                                   &pNwList);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanGetAvailableNetworkList: %d\n", rtn);
              WlanCloseHandle(hClientHandle, NULL);
              if(pNwList != NULL)
              {
                     WlanFreeMemory((PVOID) pNwList);
              }
              return ERROR_SUCCESS;
       }

       _tprintf("\n");
       _tprintf(" SSID (Network) Mode BSSIDs SigQual SecStat AuthAlgo CiphAlgo \n");

       // loop and show networks
       for(i = 0; i < pNwList->dwNumberOfItems; i++)
       {
              // find the location of next element
              j = 0;
              pAvailableNw = pNwList->Network;
              while(j < i)
              {
                     pAvailableNw = (PWLAN_AVAILABLE_NETWORK) (((unsigned char *) pAvailableNw)
                                                        + sizeof(WLAN_AVAILABLE_NETWORK));
                     j++;
              }
              memset(szESSIDStr1, 0, 256);
              memcpy(szESSIDStr1, pAvailableNw->dot11Ssid.ucSSID, pAvailableNw->dot11Ssid.uSSIDLength);
              _tprintf("%24s ", szESSIDStr1);
              if(pAvailableNw->dot11BssType == dot11_BSS_type_infrastructure)
                     _tprintf("Infra ");
              else if(pAvailableNw->dot11BssType == dot11_BSS_type_independent)
                     _tprintf("Ad-hoc ");
              else if(pAvailableNw->dot11BssType == dot11_BSS_type_any)
                     _tprintf("Any ");
              else
                     _tprintf(" ");

              _tprintf("%6d ", pAvailableNw->uNumberOfBssids);
              _tprintf("%7d ", pAvailableNw->wlanSignalQuality);
              if(pAvailableNw->bSecurityEnabled)
                     _tprintf("yes ");
              else
                     _tprintf("no ");

              _tprintf("%8d ", pAvailableNw->dot11DefaultAuthAlgorithm);
              _tprintf("%8d ", pAvailableNw->dot11DefaultCipherAlgorithm);

              _tprintf("\n");
       }

       if(pNwList != NULL)
       {
              WlanFreeMemory((PVOID) pNwList);
       }

       // close handle
       WlanCloseHandle(hClientHandle, NULL);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Shows the list of WLAN APs currently visible. This uses the NDIS
* 802.11 IOCT to retrive this information. Itshows information by
* BSSIDs.
*
* Only a few pieces of information are printed. The structure
* NDIS_WLAN_BSSID has more information.
*/
DWORD ShowNetworkListwithNDIS()
{
       INT              rtn;
       WCHAR       wsNICGUIDinString[256];
       char       sNICIDFullPath[256];
       DWORD       dwMemSize;
       ULONG       ulBytesReturned;
       ULONG       ulOIDCode;
       PNDIS_802_11_BSSID_LIST pNDIS80211BSSIDList;
       PNDIS_WLAN_BSSID       pNDIS80211BSSIDInfo;
       TCHAR szESSIDStr1[256];
       TCHAR szMACAddressStr[256];
       UINT i, j;

       // open handle
       memset(wsNICGUIDinString, 0, 256);
       memset(sNICIDFullPath, 0, 256);
       StringFromGUID2(pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                                          wsNICGUIDinString, 256);
       sprintf_s(sNICIDFullPath, "\\\\.\\%S", wsNICGUIDinString);
       hClientHandle = CreateFileA(sNICIDFullPath, GENERIC_READ,
                                                                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                                             NULL, OPEN_EXISTING,
                                                                             0, NULL) ;

       if(hClientHandle == INVALID_HANDLE_VALUE)
       {
              _tprintf("Error in CreateFileA\n");
              return 0;
       }

       // allocate temporary memory to check the number of
       // AP entries
       dwMemSize = sizeof(NDIS_802_11_BSSID_LIST) + (sizeof(NDIS_WLAN_BSSID) * 24);
       pNDIS80211BSSIDList = (NDIS_802_11_BSSID_LIST *) VirtualAlloc(NULL,
                                                               dwMemSize, MEM_RESERVE | MEM_COMMIT,
                                                               PAGE_READWRITE);
       memset(pNDIS80211BSSIDList, 0, dwMemSize);
       
       // set OID
       ulOIDCode = OID_802_11_BSSID_LIST;
       ulBytesReturned = 0;

       // call get AP list
       rtn = DeviceIoControl(hClientHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS,
                                                 &ulOIDCode, sizeof(ulOIDCode), (ULONG *) pNDIS80211BSSIDList,
                                                 dwMemSize, &ulBytesReturned, NULL);
       if(!(rtn != 0 || (rtn == 0 && GetLastError() == ERROR_MORE_DATA)))
       {
              _tprintf("Error occured in DeviceIoControl OID_802_11_BSSID_LIST: %d\n", rtn);
              // free memory allocation
              VirtualFree(pNDIS80211BSSIDList, dwMemSize,       MEM_RELEASE | MEM_DECOMMIT);
              CloseHandle(hClientHandle);
              return 0;
       }

       _tprintf("\n");
       _tprintf(" SSID (Network) MAC Address RSSI \n");
       // loop and print
       for(i = 0; i < pNDIS80211BSSIDList->NumberOfItems; i++)
       {

              // find the location of next element
              j = 0;
              pNDIS80211BSSIDInfo = pNDIS80211BSSIDList->Bssid;
              while(j < i)
              {
                     pNDIS80211BSSIDInfo = (PNDIS_WLAN_BSSID) (((unsigned char *) pNDIS80211BSSIDInfo)
                                                        + pNDIS80211BSSIDInfo->Length);
                     j++;
              }

              memset(szESSIDStr1, 0, 256);
              memcpy(szESSIDStr1, pNDIS80211BSSIDInfo->Ssid.Ssid, pNDIS80211BSSIDInfo->Ssid.SsidLength);
              _tprintf("%24s ", szESSIDStr1);

              memset(szMACAddressStr, 0, 256);
              _stprintf_s(szMACAddressStr, 256, "%02x:%02x:%02x:%02x:%02x:%02x",
                     pNDIS80211BSSIDInfo->MacAddress[0],
                     pNDIS80211BSSIDInfo->MacAddress[1],
                     pNDIS80211BSSIDInfo->MacAddress[2],
                     pNDIS80211BSSIDInfo->MacAddress[3],
                     pNDIS80211BSSIDInfo->MacAddress[4],
                     pNDIS80211BSSIDInfo->MacAddress[5]);
              _tprintf("%s ", szMACAddressStr);
              _tprintf("%4d ", pNDIS80211BSSIDInfo->Rssi);
              _tprintf("\n");
       }

       VirtualFree(pNDIS80211BSSIDList, dwMemSize,       MEM_RELEASE | MEM_DECOMMIT);
       // close handle
       CloseHandle(hClientHandle);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Initiates a connection to a given WLAN network using the
* WLAN API. The user must create a profile before to connect
* to the given network. A profile is what you create using
* the "Wireless Networks" tab in the properties of the
* wireless interface.
*
*/
DWORD ConnectToNetworkwithWLANAPI()
{
       DWORD rtn;
       TCHAR szEssIDString[256];
       WLAN_CONNECTION_PARAMETERS       sWLANConnParam;

       _tprintf("\n");
       _tprintf("Type the network name (SSID) (a profile must exist)... ");
       _tscanf_s("%s", szEssIDString, 256);
       CT2W lpsXMLProfileName(szEssIDString);

       // open handle for scanning
       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       // set connection parameters
       memset(&sWLANConnParam, 0, sizeof(WLAN_CONNECTION_PARAMETERS));
       sWLANConnParam.wlanConnectionMode = wlan_connection_mode_profile;
       sWLANConnParam.strProfile = lpsXMLProfileName;
       sWLANConnParam.pDot11Ssid = NULL;
       sWLANConnParam.pDesiredBssidList = NULL;
       sWLANConnParam.dot11BssType = dot11_BSS_type_any;
       sWLANConnParam.dwFlags = 0;

       // connect to given AP
       rtn = WlanConnect(hClientHandle,
                            &pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                            &sWLANConnParam,
                            NULL);

       // close handle
       WlanCloseHandle(hClientHandle, NULL);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Show the XML profile of a configured connection profile.
*
*/
DWORD ShowProfileInfowithWLANAPI()
{
       DWORD rtn;
       DWORD dwFlags;
       LPWSTR lpsXMLProfile;
       TCHAR szEssIDString[256];

       _tprintf("\n");
       _tprintf("Type the profile name (usually SSID) ... ");
       _tscanf_s("%s", szEssIDString, 256);
       CT2W lpsXMLProfileName(szEssIDString);

       // open handle for scanning
       dClientVersion = 1;
       dNegotiatedVersion = 0;
       rtn = WlanOpenHandle(dClientVersion, NULL, &dNegotiatedVersion, &hClientHandle);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanOpenHandle: %d\n", rtn);
              return rtn;
       }

       dwFlags = 0;
       lpsXMLProfile = NULL;

       rtn = WlanGetProfile(hClientHandle,
                     &pInterfaceList->InterfaceInfo[pInterfaceList->dwIndex].InterfaceGuid,
                     lpsXMLProfileName,
                     NULL,
                     &lpsXMLProfile,
                     &dwFlags,
                     NULL);
       if(rtn != ERROR_SUCCESS)
       {
              _tprintf("Error occured in WlanGetProfile: %d\n", rtn);
              return rtn;
       }

       CW2T szProfileXML(lpsXMLProfile);
       _tprintf("\n\n");
       _tprintf("%s", szProfileXML);

       _tprintf("\n\n");
       _tprintf("Type 99 to continue ... ");
       _tscanf_s("%d", &iContinue);

       return rtn;
}

/**
* Main function that calls the other functions.
*
*/
int _tmain(int argc, _TCHAR* argv[])
{
       DWORD rtn;

       do
       {

              iReqestedOp = 0;
              _tprintf("\n");
              _tprintf("------------------------------------------------------- \n");
              _tprintf("WLAN Operations ver 0.1 \n");
              _tprintf("Developed by Asanga Udugama (adu@comnets.uni-bremen.de) \n");
              _tprintf("------------------------------------------------------- \n");
              _tprintf("\n");
              _tprintf("Operations \n");

              _tprintf(" 1. List the WLAN interfaces using WLAN API \n");
              _tprintf(" 2. List the network interfaces using the Registry \n");
              _tprintf(" 3. Show connected WLAN network using WLAN API \n");
              _tprintf(" 4. Show connected WLAN network using NDIS \n");
              _tprintf(" 5. Issue a Scan using WLAN API \n");
              _tprintf(" 6. Issue a Scan using NDIS \n");
              _tprintf(" 7. Show visible WLAN networks using WLAN API \n");
              _tprintf(" 8. Show visible WLAN networks using NDIS \n");
              _tprintf(" 9. Connect to network using WLANAPI \n");
              _tprintf("10. Show connection profile information using WLANAPI \n");
              _tprintf("\n");

              _tprintf("99. Quit \n");
              _tprintf("\n");
              _tprintf("Type a number to run the operation ... ");

              _tscanf_s("%d", &iReqestedOp);
              _tprintf("\n\n");

              if(iReqestedOp == 1)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("List the WLAN interfaces using WLAN API \n");
                     _tprintf("------------------------------------------------------- \n");
                     ListWLANInterfaceswithWLANAPI();
              }
              else if(iReqestedOp == 2)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("List the network interfaces using the Registry \n");
                     _tprintf("------------------------------------------------------- \n");
                     ListWLANInterfacesusingRegistry();
              }
              else if(iReqestedOp == 3)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Show connected WLAN network using WLAN API \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ShowConnectedAPwithWLANAPI();
                     }
              }
              else if(iReqestedOp == 4)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Show connected WLAN network using NDIS \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ShowConnectedAPwithNDIS();
                     }
              }
              else if(iReqestedOp == 5)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Issue a Scan using WLAN API \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ScanwithWLANAPI();
                     }
              }
              else if(iReqestedOp == 6)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Issue a Scan using NDIS \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ScanwithNDIS();
                     }
              }
              else if(iReqestedOp == 7)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Show visible WLAN networks using WLAN API \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ShowNetworkListwithWLANAPI();
                     }
              }
              else if(iReqestedOp == 8)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Show visible WLAN networks using NDIS \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ShowNetworkListwithNDIS();
                     }
              }
              else if(iReqestedOp == 9)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Connect to network using WLANAP \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ConnectToNetworkwithWLANAPI();
                     }
              }
              else if(iReqestedOp == 10)
              {
                     _tprintf("------------------------------------------------------- \n");
                     _tprintf("Show connection profile information using WLANAPI \n");
                     _tprintf("------------------------------------------------------- \n");
                     rtn = SelectNetworkInterface();
                     if(rtn == ERROR_SUCCESS)
                     {
                            ShowProfileInfowithWLANAPI();
                     }
              }
              else if(iReqestedOp == 99)
              {
              }
              else
              {
                     _tprintf("You have entered an invalid operation number ... \n\n");
              }
              _tprintf("\n\n");


       } while(iReqestedOp != 99);

       return 0;
}