// NetCard.cpp: implementation of the NetCard class.
// This is the copied stuff from Microsoft.
// Calls Wrapi.dll to get Access Point info.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NetCard.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

NetCard::NetCard()
// requires: only one NetCard can be used at one time
// modifies: handle, info 
// effects: Opens the network card, Get initial info.
{
	handle = OpenDevice();
	InitClientInfo(&info);
	GetInfo(handle, &info);
}

NetCard::~NetCard()
{

}


void NetCard::Update()
// Updates the info on info
{
	GetInfo(handle, &info);
}


WRAPIHANDLE NetCard::OpenDevice (void)
// Code blatantly copied from Microsoft
{
	int cnt;
	WRAPIHANDLE hndl;
	WRAPIDEVINFO *list;
	

	// This is to check if we are connected to a wireless or wired network
	// Get Adapter name, info and IP statistics
	PCSTR ret; // CHAR const *
	//char WlanNic[] = "AIRONET PC4800 Wireless LAN Adapter.";
	char WlanNic[] = "Cisco 340 Series Wireless LAN Adapter.";
	// Changed this because having multiple Adapters made things not work.
	IP_ADAPTER_INFO AdapterInfo[5];
	ULONG BufLen = sizeof (AdapterInfo);
	DWORD j = GetAdaptersInfo((PIP_ADAPTER_INFO) AdapterInfo, (PULONG) &BufLen);
	ret = strstr(AdapterInfo->Description,"Wireless");

	if (ret == 0)
	{
	   return(WIRED_NETWORK_HANDLE);
	}

	// Get the list of devices attached to the system
	WrapiGetDeviceList(&list, &cnt);

	// Open the first device in the list
	if(cnt>0){
		print(L"NetCard::OpenDevice - opening %S\n",list[0].Device);
		hndl = WrapiOpenDevice(list[0].Device);
		if (hndl == WRAPI_INVALID_HANDLE)
		{
			return (WRAPI_INVALID_HANDLE);
		}
	} else {
		return (WRAPI_INVALID_HANDLE);
	}

	// return the handle to the calling program
	return (hndl);
}

int NetCard::GetInfo(WRAPIHANDLE hndl,  CLIENTINFO *Client)
// Code blatantly copied from Microsoft
{
	int rb, ret;
	register int i;

	if (hndl == WRAPI_INVALID_HANDLE) {
		static int printmessage = 1;
		if(printmessage){
			print(L"NetCard::GetInfo - invalid handle (most likely the wireless card is unsupported)\n");
			printmessage = 0;
		}
		return -1;
	}
	else { // handle is valid

		// Get system time
		GetLocalTime (&Client->st);

		// Get user name
		DWORD userNameLen = MAX_NAME_LEN;
		//GetUserNameA(Client->UserName, &userNameLen);
//		strncpy (Client->UserName, UserName(), MAX_NAME_LEN-1);
		Client->UserName[MAX_NAME_LEN-1] = 0;

		// Get host name and domain
		FIXED_INFO *NetInfo;
		ULONG NetInfoLen = 2 * sizeof (FIXED_INFO);
		NetInfo = (FIXED_INFO *)malloc(NetInfoLen);
		GetNetworkParams (NetInfo, &NetInfoLen);
		strncpy (Client->MachineName, NetInfo->HostName, MAX_NAME_LEN-1);
		Client->MachineName[MAX_NAME_LEN-1] = 0;

		strncpy (Client->DomainName, NetInfo->DomainName, MAX_DNAME_LEN-1);
		Client->DomainName[MAX_NAME_LEN-1] = 0;
	    free(NetInfo);


		// Get OS version
		Client->Version = GetVersion();
		   
		// Get host IP address
		MIB_IPADDRTABLE *IpAddrTable;
		ULONG TableLen = MAX_NICS * sizeof (MIB_IPADDRTABLE);
		IpAddrTable = (MIB_IPADDRTABLE *)malloc (TableLen);
		GetIpAddrTable(IpAddrTable, &TableLen, TRUE);
		if (IpAddrTable->dwNumEntries != 0)
		{
		   // Convert to aa.bb.cc.dd format
		   DWORD IpAddress = IpAddrTable->table[1].dwAddr;
		   Client->IpAddress[0] = (BYTE) (IpAddress & 0xFF);
		   Client->IpAddress[1] = (BYTE) ((IpAddress >> 8) & 0xFF);
		   Client->IpAddress[2] = (BYTE) ((IpAddress >>16) & 0xFF);
		   Client->IpAddress[3] = (BYTE) ((IpAddress >>24) & 0XFF);
		}
		free (IpAddrTable);


		// Get Adapter name, info and IP statistics
		IP_ADAPTER_INFO AdapterInfo[MAX_NICS];
		ULONG BufLen = sizeof(AdapterInfo);
		MIB_IPSTATS IpStats;
		::ZeroMemory(&AdapterInfo,sizeof(AdapterInfo));
		DWORD dwRes = GetAdaptersInfo(AdapterInfo, (PULONG) &BufLen);
		if ( ERROR_SUCCESS == dwRes )
		{
			int i;
			for(i=0; i<MAX_NICS && !strstr(AdapterInfo[i].Description,"Wireless"); i++)
				;
			if ( i >= MAX_NICS )
				i = 0;
			strncpy (Client->AdapterName, AdapterInfo[i].Description, MAX_ADAPTER_NAME-1);
		}
		else
		{
			strncpy (Client->AdapterName, "UNKNOWN", MAX_ADAPTER_NAME-1);
		}
		Client->AdapterName[MAX_ADAPTER_NAME-1] = 0;

		GetIpStatistics (&IpStats);


		// Process further only if this is a wireless network
		if (hndl != WIRED_NETWORK_HANDLE) {

			// Get the IP address of the AP client is associated with
			STRIDACCESS ridAccess;
			STSTATUS	bufPtr;		   
			ridAccess.BufPtr = (char *)&bufPtr;
			ridAccess.BufLen = sizeof (bufPtr);
			ridAccess.RID = (USHORT)0xFF50;
		
			WrapiIoctl(hndl, OID_X500_READ_RID, &ridAccess, sizeof(bufPtr), &rb);
			for (i = 0; i < 4; i++) 
				Client->ApIpAddress[i] = bufPtr.AccessPointIPAddress[i];

			// Get AP's MAC address
			for (i = 0; i < 6; i++) {
				Client->EtherAddress[i] = (BYTE) bufPtr.au8CurrentBssid[i];
				Client->ApEtherAddress[i] = (BYTE) bufPtr.au8MacAddress[i];
			}

			// Get the network data rate for client
			switch (bufPtr.u16CurrentTxRate) {
			 case 0:
			 default:
				Client->DataRate = (float)0.0;
				break;
			 case 0x0001:
				Client->DataRate = (float)0.5;
				break;
			 case 0x0002:
				Client->DataRate = (float)1.0;
				break;
			 case 0x0004:
				Client->DataRate = (float)2.0;
				break;
			 case 0x000B:
				Client->DataRate = (float)5.5;
				break;
			 case 0x0016:
				Client->DataRate = (float)11.0;
				break;
			}


			// Name of Access Point
			strncpy (Client->ApName, (char *)bufPtr.au8ApName, MAX_NAME_LEN);
			Client->ApName[MAX_NAME_LEN-1] = 0;
			

			// Network SSID
			strncpy (Client->SSID, (char *)bufPtr.SSID, MAX_SNAME_LEN);
			Client->SSID[MAX_SNAME_LEN-1] = 0;

			// Received Signal Stength
			Client->SignalStrength = bufPtr.u16SignalStrength;
			Client->NormalizedSignalStrength = bufPtr.u16NormalizedSignalStrength;

			// Beacon Period
			Client->BeaconPeriod = bufPtr.u16BeaconPeriod;		   

			// Get Statistics and time (hh:mm:ss) since last reset;
			STSTATISTICS stats;
			ret = WrapiIoctl(hndl, OID_X500_GET_STATISTICS, &stats, sizeof(stats), &rb);

			Client->TxBytes = stats.HostTxBytes; 
			Client->RxBytes = stats.HostRxBytes;
			Client->ElapsedSeconds = stats.ElapsedSec;
		} else {
			// zero AP's MAC address
			for (i = 0; i < 6; i++) {
				Client->EtherAddress[i] = 0;
				Client->ApEtherAddress[i] = 0;
			}
		}

#ifdef NOT_WORKING
		   // Get Cummulative Statistics
		   STSTATISTICS CumStats;
		   int CumStatsLen = sizeof (STSTATISTICS);
		   ridAccess.BufPtr = (char *)&CumStats;
		   ridAccess.BufLen = CumStatsLen;
		   ridAccess.RID = (USHORT) 0xFF68;

		   ret = WrapiIoctl(hndl, OID_X500_READ_RID, (unsigned char *)&ridAccess, sizeof(CumStats), &rb); 

		   // Additional Info:
		   STCAPS  stcaps;
		   ret = WrapiIoctl(hndl, OID_X500_GET_CAPS, &stcaps, sizeof(STCAPS), &rb);
#endif
		}
		   // Cleanup
//		   free(list[0].Device);
//	       free(list[0].Make);
//	       free(list[0].Model);
//	       free(list);

		   return 1;
}


// Name:   InitClientInfo
// Purpose 
//
void NetCard::InitClientInfo (CLIENTINFO *Client)
// Code blatantly copied from Microsoft
{
	strcpy (Client->UserName, "Victor");
	strcpy (Client->MachineName, "SAMSON");
	strcpy (Client->DomainName, "domain.name");	
	strcpy (Client->AdapterName, "Aironet");	
	strcpy (Client->ApName,	"Wired Network - No AP");
	strcpy (Client->SSID, "Not Relevant");	
	Client->Version = 0;
	Client->DataRate = 100.0;	
	Client->IpAddress[0] = 0;
	Client->IpAddress[1] = 0;
	Client->IpAddress[2] = 0;
	Client->IpAddress[3] = 0;	
	Client->ApIpAddress[0] = 0;
	Client->ApIpAddress[1] = 0;
	Client->ApIpAddress[2] = 0;
	Client->ApIpAddress[3] = 0;
	Client->EtherAddress[0] = 0;
	Client->EtherAddress[1] = 0; 
	Client->EtherAddress[2] = 0;
	Client->EtherAddress[3] = 0;
	Client->EtherAddress[4] = 0;
	Client->EtherAddress[5] = 0;
	Client->ApEtherAddress[0] = 0;
	Client->ApEtherAddress[1] = 0;
	Client->ApEtherAddress[2] = 0;
	Client->ApEtherAddress[3] = 0;
	Client->ApEtherAddress[4] = 0;
	Client->ApEtherAddress[5] = 0;
	Client->SignalStrength = 0;	
	Client->NormalizedSignalStrength = 0;
	Client->BeaconPeriod = 0;	
	Client->ElapsedSeconds = 0;    
	Client->RxBytes = 0;
	Client->TxBytes = 0;
}

//

// Name:    PrintClientInfo
// Purpuse
//
void NetCard::PrintClientInfo (CLIENTINFO *Client)
// Code blatantly copied from Microsoft
{
	char msg[800];
	char DataRate[30];
	char NetUpTime[100];
	unsigned int days,hours,minutes, seconds; 
		   
	// Set up time for printing (hh :mm:ss);
	seconds = Client->ElapsedSeconds;
	days = seconds / (24 * 3600);
	if (days)
	   seconds -= (days * 24 * 3600);;
	hours = seconds / 3600;
	seconds  -= (hours * 3600);
	minutes = seconds / 60;
	seconds -= (minutes * 60);
	if (days > 1)
	   sprintf(NetUpTime, "%d days, %02d:%02d:%02d (hh:mm:ss)", days, hours, minutes, seconds);
	else if (days)
	   sprintf(NetUpTime, "%d day, %02d:%02d:%02d (hh:mm:ss)", days, hours, minutes, seconds);
	else
	   sprintf(NetUpTime, "%02d:%02d:%02d (hh:mm:ss)", hours, minutes, seconds);


	// Set up data rate for printing
	if (Client->DataRate)
	   sprintf(DataRate, "%3.1f Mbit/sec", Client->DataRate);
	else
	   sprintf(DataRate, "Unknown");
		   

	// Set up Ethernet for printing. Do client's address 
	// followed by AP's address with which the client is associated
	char ApMacAddress[48], NicMacAddress[48];
	sprintf(NicMacAddress, "%02X:%02X:%02X:%02X:%02X:%02X",
					Client->EtherAddress[0],Client->EtherAddress[1],
					Client->EtherAddress[2],Client->EtherAddress[3],
					Client->EtherAddress[4],Client->EtherAddress[5]);
	sprintf(ApMacAddress, "%02X:%02X:%02X:%02X:%02X:%02X",
					Client->ApEtherAddress[0], Client->ApEtherAddress[1],
					Client->ApEtherAddress[2], Client->ApEtherAddress[3],
					Client->ApEtherAddress[4], Client->ApEtherAddress[5]);

	// Prepare string for printing
	char tmp[100];
	sprintf(msg,"Local Time:\t%d:%d:%d, %d//%d//%d\n",
				Client->st.wHour, Client->st.wMinute, 
				Client->st.wSecond,  Client->st.wMonth, 
				Client->st.wDay, Client->st.wYear);
	
	// user name
	sprintf(tmp, "Email:\t\t%s@microsoft.com\n", Client->UserName);
	strcat (msg, tmp);
	
	// host name
	sprintf(tmp, "Machine name:\t%s\n", Client->MachineName);
	strcat (msg, tmp);
	
	// domain name
	sprintf(tmp, "Domain name:\t%s\n", Client->DomainName);
	strcat (msg, tmp);
	
	// OS version
	sprintf(tmp, "Operating System:\tWindows 2000 version %d.%d\n",
				Client->Version & 0x000000FF, 
				Client->Version & 0x0000FF00);
	strcat (msg, tmp);
	
	// Adapter name
	sprintf(tmp, "Network Adapter:\t%s\n", Client->AdapterName);
	strcat (msg, tmp);
	
	// Elapsed time since network has been up
	sprintf(tmp, "Network Uptime:\t%s\n", NetUpTime);
	strcat (msg, tmp);
	
	// network data rate
	sprintf(tmp, "Data Rate:\t%s\n", DataRate);
	strcat (msg, tmp);
	
	// Client's IP address
	sprintf(tmp,"NIC's IP address:\t%d.%d.%d.%d\n",
				 Client->IpAddress[0], Client->IpAddress[1],
				 Client->IpAddress[2], Client->IpAddress[3]);
	strcat (msg, tmp);

	// Client's MAC address
	sprintf(tmp, "NIC's MAC Addr.:\t%s\n", NicMacAddress);
	strcat (msg, tmp);

	// AP's IP address
	sprintf(tmp, "Associated with:\t%d.%d.%d.%d\n",
				 Client->ApIpAddress[0], Client->ApIpAddress[1], 
				 Client->ApIpAddress[2], Client->ApIpAddress[3]);
	strcat (msg, tmp);

	// AP's MAC Address
	sprintf(tmp, "AP's MAC Addr.:\t%s\n", ApMacAddress);
	strcat (msg, tmp);

	// Name of Access Point
	 sprintf(tmp, "AP Name:\t\t%s\n", Client->ApName);
	strcat (msg, tmp);

	// Number of bytes transmitted since last reset
	sprintf(tmp, "Transmitted:\t%d bytes\n",Client->TxBytes); 
	strcat (msg, tmp);

	// Number of bytes received since last reset
	sprintf(tmp, "Received:\t%d bytes\n",Client->RxBytes);
	strcat (msg, tmp);

	// network SSID
	sprintf(tmp, "SSID:\t\t%s\n", Client->SSID);
	strcat (msg, tmp);

	// Snap shot of Signal Strength
	sprintf(tmp, "Signal Strength:\t%d\n", Client->SignalStrength);
	strcat (msg, tmp);
	 sprintf(tmp, "Normalized SS:\t%d\n", Client->NormalizedSignalStrength);
	strcat (msg, tmp);

	// Beacon Period
	sprintf(tmp, "Beacon Period:\tonce every %d msec\n", Client->BeaconPeriod);
	strcat (msg, tmp);
	printf("%s", msg);
}
