#include "StdAfx.h"
#include <GobiApi.h>
#include "GobiApiWds.h"
#include "FuncList.h"
#include "StatusCtrl.h"
#include "GobiConnectionMgmtAPI.h"
#include "SwiWwanCmApi.h"
#include "winsock2.h"
#include "ws2tcpip.h"

// Function names
#define FUNC_GetIPAddress				L"GetIPAddress"
#define FUNC_GetIPAddressLTE            L"GetIPAddressLTE"
#define FUNC_GetIPConfiguration			L"GetIPConfiguration"
#define FUNC_GetPacketStatus			L"GetPacketStatus"
#define FUNC_GetByteTotals				L"GetByteTotals"
#define FUNC_GetDataBearerTechnology	L"GetDataBearerTechnology"
#define FUNC_GetSwiCurrentDataBearerTech	L"SwiGetCurrentDataBearerTechnology"
#define FUNC_GetDormancyState			L"GetDormancyState"
#define FUNC_GetConnectionRate			L"GetConnectionRate"
#define FUNC_GetDefaultProfile			L"GetDefaultProfile"
#define FUNC_GetDefaultProfileLTE       L"GetDefaultProfileLTE"
#define FUNC_GetDefaultIPv6Profile      L"GetDefaultIPv6Profile"
#define FUNC_SetDefaultProfile          L"SetDefaultProfile"
#define FUNC_SetDefaultIPv6Profile      L"SetDefaultIPv6Profile"
#define FUNC_SetDataBearerCallback		L"SetDataBearerCallback"
#define FUNC_SwiSetCurrentDataBearerCallback	L"SwiSetCurrentDataBearerCallback"
#define FUNC_SetDormancyStatusCallback	L"SetDormancyStatusCallback"
#define FUNC_SetByteTotalsCallback		L"SetByteTotalsCallback"
#define FUNC_SetMobileIPStatusCallback	L"SetMobileIPStatusCallback"
#define FUNC_StartDataSession2			L"StartDataSession2"
#define FUNC_StartDataSessionLTE        L"StartDataSessionLTE"
#define FUNC_StopDataSession			L"StopDataSession"
#define FUNC_GetSessionState    		L"GetSessionState"
#define FUNC_GetSessionDuration    		L"GetSessionDuration"
#define FUNC_SetSessionStateCallback	L"SetSessionStateCallback"
#define FUNC_GetAutoconnect         	L"GetAutoconnect"
#define FUNC_SetAutoconnect         	L"SetAutoconnect"
#define FUNC_SetMobileIp				L"SetMobileIP"
#define FUNC_GetMobileIp				L"GetMobileIP"
#define FUNC_SetActiveMobileIpProfile	L"SetActiveMobileIPProfile"
#define FUNC_GetActiveMobileIpProfile	L"GetActiveMobileIPProfile"
#define FUNC_SetMobileIpProfile			L"SetMobileIPProfile" 
#define FUNC_GetMobileIpProfile			L"GetMobileIPProfile"
#define FUNC_GetMobileIpProfile2		L"GetMobileIPProfile2"
#define FUNC_SetMobileIpParameters		L"SetMobileIPParameters"
#define FUNC_GetMobileIpParameters		L"GetMobileIPParameters"
#define FUNC_GetLastMobileIpError		L"GetLastMobileIPError"
#define FUNC_SwiGoDormant				L"SwiGoDormant"
#define FUNC_GetEnhancedAutoconnect		L"GetEnhancedAutoconnect"
#define FUNC_SetEnhancedAutoconnect		L"SetEnhancedAutoconnect"
#define FUNC_GetDNSSettings				L"GetDNSSettings"
#define FUNC_SetDNSSettings				L"SetDNSSettings"
#define FUNC_GetDNSIPv6Settings         L"GetDNSIPv6Settings"
#define FUNC_SetDNSIPv6Settings         L"SetDNSIPv6Settings"
#define FUNC_SwiGetApn					L"SwiGetApn"

// Parameter names
#define PARAM_Technology				L"Technology"
#define PARAM_PrimaryDns				L"PrimaryDns"
#define PARAM_SecondaryDns				L"SecondaryDns"
#define PARAM_PrimaryDnsIPv6            L"PrimaryDnsIPv6"
#define PARAM_SecondaryDnsIPv6          L"SecondaryDnsIPv6"
#define PARAM_PrimaryNbns				L"PrimaryNbns"
#define PARAM_SecondaryNbns				L"SecondaryNbns"
#define PARAM_ApnName					L"ApnName"
#define PARAM_IpAddress					L"IpAddress"
#define PARAM_IpAddressIPv6             L"IpAddressIPv6"
#define PARAM_Authentication			L"Authentication"
#define PARAM_Username					L"Username"
#define PARAM_Password					L"Password"
#define PARAM_SessionId					L"SessionId"
#define PARAM_FailureReason				L"FailureReason"
#define PARAM_Interval  				L"Interval(sec)"
#define PARAM_SessionId					L"SessionId"
#define PARAM_ProfileType				L"ProfileType"
#define PARAM_PDPType                   L"PDPType"
#define PARAM_ProfileName               L"ProfileName"
#define PARAM_MipMode		            L"Mode"
#define PARAM_SPC						L"SPC"
#define PARAM_Index						L"Index"
#define PARAM_Enabled					L"Enabled"
#define PARAM_Address					L"Address"
#define PARAM_PrimaryHA					L"PrimaryHA"
#define PARAM_SecondaryHA				L"SecondaryHA"
#define PARAM_RevTunneling				L"RevTunneling"
#define PARAM_NAI						L"NAI"
#define PARAM_HASPI						L"HASPI"
#define PARAM_AAASPI					L"AAASPI"
#define PARAM_MNHA						L"MNHA"
#define PARAM_MNAAA						L"MNAAA"
#define PARAM_RetryLimit				L"RetryLimit"
#define PARAM_RetryInterval				L"RetryInterval"
#define PARAM_ReRetryPeriod				L"ReRetryPeriod"
#define PARAM_ReRegTraffic				L"ReRegTraffic"
#define PARAM_HAAuthenticator			L"HAAuthenticator"
#define PARAM_HA2002bis					L"HA2002bis"
#define PARAM_EnableAutoconnect			L"EnableAutoconnect"
#define PARAM_Enable					L"Enable"
#define PARAM_SetRoamAutoconnect		L"RoamAutoconnect"

// variable used to coordinate start/stop network connection actions
static ULONG sessionID = 0;

CParamList CGobiApiWds::m_sStartDataSession;
CParamList CGobiApiWds::m_sEnableAutoconnect;
CParamList CGobiApiWds::m_sSetByteTotalCallback;
CParamList CGobiApiWds::m_sStopDataSession;
CParamList CGobiApiWds::m_sSetDefaultProfile;
CParamList CGobiApiWds::m_sSetMobileIp;
CParamList CGobiApiWds::m_sSetActiveMobileIpProfile;
CParamList CGobiApiWds::m_sSetMobileIpProfile;
CParamList CGobiApiWds::m_sGetMobileIpProfile;
CParamList CGobiApiWds::m_sGetMobileIpProfile2;
CParamList CGobiApiWds::m_sSetMobileIpParameters;
CParamList CGobiApiWds::m_sSetMobileIpStatusCallback;
CParamList CGobiApiWds::m_sSetSessionStateCallback;
CParamList CGobiApiWds::m_sSetDormacyStatusCallback;
CParamList CGobiApiWds::m_sSetDataBearerCallback;
CParamList CGobiApiWds::m_sSwiSetCurrentDataBearerCallback;
CParamList CGobiApiWds::m_sSetEnhancedAutoconnect;
CParamList CGobiApiWds::m_sSetDNSSettings;
CParamList CGobiApiWds::m_sSetDNSIPv6Settings;
CParamList CGobiApiWds::m_sSetDefaultIPv6Profile;
CParamList CGobiApiWds::m_sSwiGetApn;

const TableFuncEntry CGobiApiWds::m_TableFunc[] = 
{
	{FUNC_GetSessionState,				FuncGetSessionState},
	{FUNC_StartDataSession2,			FuncStartDataSession2, &m_sStartDataSession},
    {FUNC_StartDataSessionLTE,          FuncStartDataSessionLTE, &m_sStartDataSession},
	{FUNC_StopDataSession,				FuncStopDataSession, &m_sStopDataSession},
	{FUNC_GetIPAddress,					FuncGetIPAddress},
    {FUNC_GetIPAddressLTE,              FuncGetIPAddressLTE},
	{FUNC_GetIPConfiguration,			FuncGetIPConfiguration},
	{FUNC_GetPacketStatus,				FuncGetPacketStatus},
	{FUNC_GetByteTotals,				FuncGetByteTotals},
	{FUNC_GetDataBearerTechnology,		FuncGetDataBearerTechnology},
	{FUNC_GetSwiCurrentDataBearerTech,	FuncSwiGetCurrentDataBearerTechnology},
	{FUNC_GetDormancyState,				FuncGetDormancyState},
	{FUNC_GetConnectionRate,			FuncGetConnectionRate},
	{FUNC_GetDefaultProfile,			FuncGetDefaultProfile},
    {FUNC_GetDefaultProfileLTE,         FuncGetDefaultProfileLTE},
    {FUNC_GetDefaultIPv6Profile,        FuncGetDefaultIPv6Profile},
	{FUNC_SetDefaultProfile,			FuncSetDefaultProfile, &m_sSetDefaultProfile},
    {FUNC_SetDefaultIPv6Profile,        FuncSetDefaultIPv6Profile, &m_sSetDefaultIPv6Profile},
	{FUNC_GetSessionDuration,			FuncGetSessionDuration},
	{FUNC_GetAutoconnect,				FuncGetAutoconnect},
	{FUNC_SetAutoconnect,				FuncSetAutoconnect, &m_sEnableAutoconnect},
	{FUNC_SetMobileIp,					FuncSetMobileIp, &m_sSetMobileIp },
	{FUNC_GetMobileIp,					FuncGetMobileIp},
	{FUNC_SetActiveMobileIpProfile,		FuncSetActiveMobileIpProfile, &m_sSetActiveMobileIpProfile },
	{FUNC_GetActiveMobileIpProfile,		FuncGetActiveMobileIpProfile},
	{FUNC_SetMobileIpProfile,			FuncSetMobileIpProfile, &m_sSetMobileIpProfile }, 
	{FUNC_GetMobileIpProfile,			FuncGetMobileIpProfile, &m_sGetMobileIpProfile },
	{FUNC_GetMobileIpProfile2,			FuncGetMobileIpProfile2, &m_sGetMobileIpProfile2 },
	{FUNC_SetMobileIpParameters,		FuncSetMobileIpParameters, &m_sSetMobileIpParameters },
	{FUNC_GetMobileIpParameters,		FuncGetMobileIpParameters },
	{FUNC_GetLastMobileIpError,			FuncGetLastMobileIpError },
	{FUNC_SetDataBearerCallback,		FuncSetDataBearerCallback, &m_sSetDataBearerCallback},
	{FUNC_SwiSetCurrentDataBearerCallback,		FuncSwiSetCurrentDataBearerCallback, &m_sSwiSetCurrentDataBearerCallback},
	{FUNC_SetDormancyStatusCallback,	FuncSetDormancyStatusCallback, &m_sSetDormacyStatusCallback},
	{FUNC_SetByteTotalsCallback,		FuncSetByteTotalsCallback, &m_sSetByteTotalCallback},
	{FUNC_SetMobileIPStatusCallback,	FuncSetMobileIPStatusCallback, &m_sSetMobileIpStatusCallback},
	{FUNC_SetSessionStateCallback,		FuncSetSessionStateCallback, &m_sSetSessionStateCallback},
	{FUNC_SwiGoDormant,					FuncSwiGoDormant},
	{FUNC_GetEnhancedAutoconnect,		FuncGetEnhancedAutoconnect},
	{FUNC_SetEnhancedAutoconnect,		FuncSetEnhancedAutoconnect, &m_sSetEnhancedAutoconnect},
	{FUNC_GetDNSSettings,				FuncGetDNSSettings},
	{FUNC_SetDNSSettings,				FuncSetDNSSettings, &m_sSetDNSSettings},
    {FUNC_GetDNSIPv6Settings,           FuncGetDNSIPv6Settings},
    {FUNC_SetDNSIPv6Settings,           FuncSetDNSIPv6Settings, &m_sSetDNSIPv6Settings},
	{FUNC_SwiGetApn,					FuncSwiGetApn, &m_sSwiGetApn},
	{FUNC_EndOfList}
};

CGobiApiWds::CGobiApiWds(HMODULE hQCDll)
{
	// Initialize the QC Dll pointer
	m_hQCDll = hQCDll;

	// Define StartDataSession configurable parameters
	m_sStartDataSession.Add(PARAM_ApnName, L"internet.com");
	m_sStartDataSession.Add(PARAM_Username, L"wapuser1");
	m_sStartDataSession.Add(PARAM_Password, L"wap");
	m_sStartDataSession.Add(PARAM_Technology, L"1");
	m_sStartDataSession.Add(PARAM_Authentication, L"0");
	m_sStartDataSession.Add(PARAM_IpAddress, L"0");
	m_sStartDataSession.Add(PARAM_PrimaryDns, L"0");
	m_sStartDataSession.Add(PARAM_SecondaryDns, L"0");
	m_sStartDataSession.Add(PARAM_PrimaryNbns, L"0");
	m_sStartDataSession.Add(PARAM_SecondaryNbns, L"0");

	// Define SetByteTotalCallback configurable parameters
	m_sSetByteTotalCallback.Add(PARAM_Interval, L"20");
	m_sSetByteTotalCallback.Add(PARAM_Enable, L"1");

	// Define StopDataSession configurable parameters
	m_sStopDataSession.Add(PARAM_SessionId, L"0");

	// Define SetDefaultProfile configurable parameters
	m_sSetDefaultProfile.Add(PARAM_ProfileName, L"Rogers");
	m_sSetDefaultProfile.Add(PARAM_ProfileType, L"0");
	m_sSetDefaultProfile.Add(PARAM_PDPType, L"0");
	m_sSetDefaultProfile.Add(PARAM_IpAddress, L"0");
	m_sSetDefaultProfile.Add(PARAM_PrimaryDns, L"0");
	m_sSetDefaultProfile.Add(PARAM_SecondaryDns, L"0");
	m_sSetDefaultProfile.Add(PARAM_ApnName, L"internet.com");
	m_sSetDefaultProfile.Add(PARAM_Authentication, L"0");
	m_sSetDefaultProfile.Add(PARAM_Username, L"wapuser1");
	m_sSetDefaultProfile.Add(PARAM_Password, L"wap");

    // Define SetDefaultIPv6Profile configurable parameters
    m_sSetDefaultIPv6Profile.Add( PARAM_ProfileType, L"0" );
    m_sSetDefaultIPv6Profile.Add( PARAM_IpAddressIPv6, L"0:0:0:0:0:0:0:0" );
    m_sSetDefaultIPv6Profile.Add(PARAM_PrimaryDnsIPv6, L"0:0:0:0:0:0:0:0");
    m_sSetDefaultIPv6Profile.Add(PARAM_SecondaryDnsIPv6, L"0:0:0:0:0:0:0:0");

	// Define SetMobileIp configurable parameters
	m_sSetMobileIp.Add(PARAM_MipMode, L"0");

	// Define SetActiveMobileIpProfile configurable parameters
	m_sSetActiveMobileIpProfile.Add(PARAM_SPC, L"123456");
	m_sSetActiveMobileIpProfile.Add(PARAM_Index, L"1");

	// Define SetMobileIpProfile configurable parameters
	m_sSetMobileIpProfile.Add(PARAM_SPC, L"000000");
	m_sSetMobileIpProfile.Add(PARAM_Index, L"1");
	m_sSetMobileIpProfile.Add(PARAM_Enabled, L"0");
	m_sSetMobileIpProfile.Add(PARAM_Address, L"0");
	m_sSetMobileIpProfile.Add(PARAM_PrimaryHA, L"0");
	m_sSetMobileIpProfile.Add(PARAM_SecondaryHA, L"0");
	m_sSetMobileIpProfile.Add(PARAM_RevTunneling, L"0");
	m_sSetMobileIpProfile.Add(PARAM_NAI, L"NAISTRING");
	m_sSetMobileIpProfile.Add(PARAM_HASPI, L"1");
	m_sSetMobileIpProfile.Add(PARAM_AAASPI, L"2");
	m_sSetMobileIpProfile.Add(PARAM_MNHA, L"abcdefg");
	m_sSetMobileIpProfile.Add(PARAM_MNAAA, L"hijklmnop");

	// Define GetMobileIpProfile configurable parameters
	m_sGetMobileIpProfile.Add(PARAM_Index, L"0");

	// Define GetMobileIpProfile2 configurable parameters
	m_sGetMobileIpProfile2.Add(PARAM_Index, L"0");

	// Define SetMobileIpParameters configurable parameters
	m_sSetMobileIpParameters.Add(PARAM_SPC, L"000000");
	m_sSetMobileIpParameters.Add(PARAM_MipMode, L"0");
	m_sSetMobileIpParameters.Add(PARAM_RetryLimit, L"0");
	m_sSetMobileIpParameters.Add(PARAM_RetryInterval, L"0");
	m_sSetMobileIpParameters.Add(PARAM_ReRetryPeriod, L"0");
	m_sSetMobileIpParameters.Add(PARAM_ReRegTraffic, L"0");
	m_sSetMobileIpParameters.Add(PARAM_HAAuthenticator, L"0");
	m_sSetMobileIpParameters.Add(PARAM_HA2002bis, L"0");

	// Define configurable parameters for EnableAutoconnect
	m_sEnableAutoconnect.Add(PARAM_EnableAutoconnect, L"0");

	// Define configurable parameters for callbacks
	m_sSetMobileIpStatusCallback.Add(PARAM_Enable, L"1");
	m_sSetSessionStateCallback.Add(PARAM_Enable, L"1");
	m_sSetDormacyStatusCallback.Add(PARAM_Enable, L"1");
	m_sSetDataBearerCallback.Add(PARAM_Enable, L"1");
	m_sSwiSetCurrentDataBearerCallback.Add(PARAM_Enable, L"1");

	// Define configurable parameters for SetEnhancedAutoconnect
	m_sSetEnhancedAutoconnect.Add(PARAM_EnableAutoconnect, L"0");
	m_sSetEnhancedAutoconnect.Add(PARAM_SetRoamAutoconnect, L"0");

	// Define configurable parameters for SetDNSSettings
	m_sSetDNSSettings.Add(PARAM_PrimaryDns, L"0");
	m_sSetDNSSettings.Add(PARAM_SecondaryDns, L"0");

    // Define configurable parameters for SetDNSIPv6Settings
    m_sSetDNSIPv6Settings.Add(PARAM_PrimaryDnsIPv6, L"0:0:0:0:0:0:0:0");
    m_sSetDNSIPv6Settings.Add(PARAM_SecondaryDnsIPv6, L"0:0:0:0:0:0:0:0");

	// Define configurable parameters for SwiGetApn
	m_sSwiGetApn.Add(PARAM_ProfileType, L"0");
	m_sSwiGetApn.Add(PARAM_Index, L"3");
}

CGobiApiWds::~CGobiApiWds(void)
{
}

BOOL CGobiApiWds::GetAvailFuncList(CFuncList* pFuncList)
{
	TBD_FUNCTION(CGobiApiWds::GetAvailFuncList);

	int iIndex = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		pFuncList->Add(L"Wireless Data", m_TableFunc[iIndex].szFuncName, m_TableFunc[iIndex].pParamList);
		TBD_OUTPUT(TBDCT_INFO, TBDOL_INFORMATION, m_TableFunc[iIndex].szFuncName);
		iIndex++;
	}

	return TRUE;
}

UINT CGobiApiWds::ExecuteFunctions(CFuncList* pFuncList, UINT &nTotalExec)
{
	TBD_FUNCTION(CGobiApiWds::Execute);

	int iIndex = 0;
	m_nNumErrors = 0;
	nTotalExec = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		if (pFuncList->Find(m_TableFunc[iIndex].szFuncName))
		{
			// Get list of parameters
			CParamList sParams;
			pFuncList->GetFuncParams(m_TableFunc[iIndex].szFuncName, sParams);

			// execute function
			if (!m_TableFunc[iIndex].pFunc(&sParams))
				// increment error counter
				m_nNumErrors++;

			// increment total functions executed
			nTotalExec++;
		}

		iIndex++;
	}

	return m_nNumErrors;
}

BOOL CGobiApiWds::FuncGetSessionState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetSessionState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG currentLinkStatus = 0;

	// call Sierra interface
	ULONG nRet = GetSessionState( &currentLinkStatus );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(currentLinkStatus)
		{
		case 0x01:
			strTemp.Format(L"Current Link Status: Disconnected [0x%04x]", currentLinkStatus);
			break;
		case 0x02:
			strTemp.Format(L"Current Link Status: Connected [0x%04x]", currentLinkStatus);
			break;
		case 0x03:
			strTemp.Format(L"Current Link Status: Suspended [0x%04x]", currentLinkStatus);
			break;
		case 0x04:
			strTemp.Format(L"Current Link Status: Authenicating [0x%04x]", currentLinkStatus);
			break;
		default:			
			strTemp.Format(L"Current Link Status: 0x%04x", currentLinkStatus);
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETSESSIONSTATE) (ULONG*);

		// get pointer to function
		LPFN_GETSESSIONSTATE pFn = (LPFN_GETSESSIONSTATE)GetProcAddress_W(m_hQCDll, FUNC_GetSessionState);

		// execute function
		if (pFn)
		{
			ULONG QcSessionState = 0;

			ULONG nQcRet = pFn(&QcSessionState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcSessionState != currentLinkStatus)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}
BOOL CGobiApiWds::FuncStartDataSession2(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncStartDataSession2", STATUSMSG_Send);

	BOOL bRet = FALSE;
	const UINT nMaxStrLen = 0xFF;

	ULONG Technology = 1; 
	ULONG PrimaryDNS = 0;
	ULONG SecondaryDNS = 0; 
	ULONG PrimaryNBNS = 0;
	ULONG SecondaryNBNS = 0; 
	CHAR APNName[nMaxStrLen] = "internet.com";
	ULONG IPAddress = 0;
	ULONG Authentication = 0; 
	CHAR Username[nMaxStrLen] = "wapuser"; 
	CHAR Password[nMaxStrLen] = "wap";
	ULONG FailureReason = 0;

	if (pParams)
	{
		// copy user specified parameters
		CHAR szIpAddress[MAX_PATH] = "";
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ApnName), -1, APNName, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Username), -1, Username, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Password), -1, Password, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_IpAddress), -1, szIpAddress, nMaxStrLen, 0, 0);
		IPAddress		= ntohl(inet_addr(szIpAddress));
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_PrimaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
		PrimaryDNS		= ntohl(inet_addr(szIpAddress));
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SecondaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
		SecondaryDNS	= ntohl(inet_addr(szIpAddress));
		Authentication	= _ttoi(pParams->GetValue(PARAM_Authentication));
		PrimaryDNS		= _ttoi(pParams->GetValue(PARAM_PrimaryDns));
		Technology		= _ttoi(pParams->GetValue(PARAM_Technology));
	}

	ULONG nRet = StartDataSession2( 
					&Technology, 
					&PrimaryDNS, 
					&SecondaryDNS, 
					&PrimaryNBNS, 
					&SecondaryNBNS, 
					&APNName[0], 
					&IPAddress, 
					&Authentication, 
					&Username[0], 
					&Password[0],
					&sessionID,
					&FailureReason );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Session ID: %d", sessionID);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}
	else
	{
		strTemp.Format(L"FailureReason: %d", FailureReason);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
	}

	return bRet;
}

BOOL CGobiApiWds::FuncStartDataSessionLTE(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncStartDataSessionLTE", STATUSMSG_Send);

	BOOL bRet = FALSE;
	const UINT nMaxStrLen = 0xFF;

	ULONG Technology = 1; 
	ULONG PrimaryDNSv4 = 0;
	ULONG SecondaryDNSv4 = 0; 
	ULONG PrimaryNBNSv4 = 0;
	ULONG SecondaryNBNSv4 = 0; 
	CHAR APNName[nMaxStrLen] = "internet.com";
	ULONG IPAddressv4 = 0;
	ULONG Authentication = 0; 
	CHAR Username[nMaxStrLen] = "wapuser"; 
	CHAR Password[nMaxStrLen] = "wap";
	ULONG FailureReason = 0;

	if (pParams)
	{
		// copy user specified parameters
		CHAR szIpAddress[MAX_PATH] = "";
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ApnName), -1, APNName, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Username), -1, Username, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Password), -1, Password, nMaxStrLen, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_IpAddress), -1, szIpAddress, nMaxStrLen, 0, 0);
		IPAddressv4		= ntohl(inet_addr(szIpAddress));
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_PrimaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
		PrimaryDNSv4		= ntohl(inet_addr(szIpAddress));
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SecondaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
		SecondaryDNSv4	= ntohl(inet_addr(szIpAddress));
		Authentication	= _ttoi(pParams->GetValue(PARAM_Authentication));
//		PrimaryDNS		= _ttoi(pParams->GetValue(PARAM_PrimaryDns));
		Technology		= _ttoi(pParams->GetValue(PARAM_Technology));
	}

	ULONG nRet = StartDataSessionLTE( 
					&Technology, 
					&PrimaryDNSv4, 
					&SecondaryDNSv4, 
					&PrimaryNBNSv4, 
					&SecondaryNBNSv4,
                    NULL,
                    NULL,
					&APNName[0], 
					&IPAddressv4, 
                    NULL,
					&Authentication, 
					&Username[0], 
					&Password[0],
					&sessionID,
					&FailureReason );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Session ID: %d", sessionID);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}
	else
	{
		strTemp.Format(L"FailureReason: %d", FailureReason);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
	}

	return bRet;
}

BOOL CGobiApiWds::FuncStopDataSession(CParamList* pParams)
{
	ADDSTATUS(L"FuncStopDataSession", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG nRet = StopDataSession( _ttoi(pParams->GetValue(PARAM_SessionId)));

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		bRet = TRUE;
	}

	return bRet;
}
BOOL CGobiApiWds::FuncGetIPAddress(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetIPAddress", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG IPAddress = 0;

	// call Sierra interface
	ULONG nRet = GetIPAddress( &IPAddress );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"IP Address: %d.%d.%d.%d", (IPAddress & 0xFF000000)>> 24, (IPAddress & 0x00FF0000) >> 16, (IPAddress & 0x0000FF00) >> 8, IPAddress & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETIPADDRESS) (ULONG*);

		// get pointer to function
		LPFN_GETIPADDRESS pFn = (LPFN_GETIPADDRESS)GetProcAddress_W(m_hQCDll, FUNC_GetIPAddress);

		// execute function
		if (pFn)
		{
			ULONG QcIPAddress = 0;

			ULONG nQcRet = pFn(&QcIPAddress);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcIPAddress != IPAddress)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetIPAddressLTE(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetIPAddressLTE", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG IPv4Address = 0;
    USHORT IPv6Address[8] = {0};
    BYTE IPv6AddressPrefixLen = 0;

	// call Sierra interface
	ULONG nRet = GetIPAddressLTE( &IPv4Address, &IPv6Address[0], &IPv6AddressPrefixLen );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"IPv4 Address: %d.%d.%d.%d", (IPv4Address & 0xFF000000)>> 24, (IPv4Address & 0x00FF0000) >> 16, (IPv4Address & 0x0000FF00) >> 8, IPv4Address & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
        strTemp.Format(L"IPv6 Address: %X.%X.%X.%X.%X.%X.%X.%X", 
            htons(IPv6Address[0]), htons(IPv6Address[1]), htons(IPv6Address[2]), htons(IPv6Address[3]),
            htons(IPv6Address[4]), htons(IPv6Address[5]), htons(IPv6Address[6]), htons(IPv6Address[7]));
        ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
        strTemp.Format(L"IPv6 Address Prefix Length: %d-bit", IPv6AddressPrefixLen);
        ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetIPConfiguration(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetIPConfiguration", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG IPAddress = 0;
	ULONG GatewayAddress = 0;
	ULONG SubnetMask = 0;
	ULONG PrimaryDnsAddress = 0;
	ULONG SecondaryDnsAddress = 0;

	// call Sierra interface
	ULONG nRet = GetIPConfiguration( &IPAddress, &GatewayAddress, &SubnetMask, &PrimaryDnsAddress, &SecondaryDnsAddress );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"IP Address: %d.%d.%d.%d", (IPAddress & 0xFF000000)>> 24, (IPAddress & 0x00FF0000) >> 16, (IPAddress & 0x0000FF00) >> 8, IPAddress & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Gateway Address: %d.%d.%d.%d", (GatewayAddress & 0xFF000000)>> 24, (GatewayAddress & 0x00FF0000) >> 16, (GatewayAddress & 0x0000FF00) >> 8, GatewayAddress & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Subnet Mask: %d.%d.%d.%d", (SubnetMask & 0xFF000000)>> 24, (SubnetMask & 0x00FF0000) >> 16, (SubnetMask & 0x0000FF00) >> 8, SubnetMask & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Primary DNS Address: %d.%d.%d.%d", (PrimaryDnsAddress & 0xFF000000)>> 24, (PrimaryDnsAddress & 0x00FF0000) >> 16, (PrimaryDnsAddress & 0x0000FF00) >> 8, PrimaryDnsAddress & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Secondary DNS Address: %d.%d.%d.%d", (SecondaryDnsAddress & 0xFF000000)>> 24, (SecondaryDnsAddress & 0x00FF0000) >> 16, (SecondaryDnsAddress & 0x0000FF00) >> 8, SecondaryDnsAddress & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
    // There is no equivalent QC function so skip.
	return bRet;
}

BOOL CGobiApiWds::FuncGetPacketStatus(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetPacketStatus", STATUSMSG_Send);

	BOOL bRet = FALSE;

	typedef struct 
	{
		ULONG TXPacketSuccesses;
		ULONG RXPacketSuccesses;
		ULONG TXPacketErrors;
		ULONG RXPacketErrors; 
		ULONG TXPacketOverflows; 
		ULONG RXPacketOverflows;
	} STRUCT_GetPacketStatus;

	STRUCT_GetPacketStatus sParam;
	// clear structure
	memset(&sParam, 0, sizeof(STRUCT_GetPacketStatus));

	// call Sierra interface
	ULONG nRet = GetPacketStatus( &sParam.TXPacketSuccesses, &sParam.RXPacketSuccesses, &sParam.TXPacketErrors, &sParam.RXPacketErrors, &sParam.TXPacketOverflows, &sParam.RXPacketOverflows );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Okay Packets: TX[%d] RX[%d]", sParam.TXPacketSuccesses, sParam.RXPacketSuccesses);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Error Packets: TX[%d] RX[%d]", sParam.TXPacketErrors, sParam.RXPacketErrors);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Overflow Packets: TX[%d] RX[%d]", sParam.TXPacketOverflows, sParam.RXPacketOverflows);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETPKTSTATUS) (ULONG*, ULONG*, ULONG*, ULONG*, ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETPKTSTATUS pFn = (LPFN_GETPKTSTATUS)GetProcAddress_W(m_hQCDll, FUNC_GetPacketStatus);

		// execute function
		if (pFn)
		{
			STRUCT_GetPacketStatus sQcParam;
			// clear structure
			memset(&sQcParam, 0, sizeof(STRUCT_GetPacketStatus));

			ULONG nQcRet = pFn(&sQcParam.TXPacketSuccesses, &sQcParam.RXPacketSuccesses, &sQcParam.TXPacketErrors, &sQcParam.RXPacketErrors, &sQcParam.TXPacketOverflows, &sQcParam.RXPacketOverflows);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				// can't expect byte counts to remain the same for both of these calls
				strTemp.Format(L"Comparing: Okay Packets: TX/RX  SWI[%d/%d] QCom[%d/%d]", sParam.TXPacketSuccesses, sParam.RXPacketSuccesses, sQcParam.TXPacketSuccesses, sQcParam.RXPacketSuccesses);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
				strTemp.Format(L"Comparing: Error Packets: TX/RX  SWI[%d/%d] QCom[%d/%d]", sParam.TXPacketErrors, sParam.RXPacketErrors, sQcParam.TXPacketErrors, sQcParam.RXPacketErrors);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
				strTemp.Format(L"Comparing: Overflow Packets: TX/RX  SWI[%d/%d] QCom[%d/%d]", sParam.TXPacketOverflows, sParam.RXPacketOverflows, sQcParam.TXPacketOverflows, sQcParam.RXPacketOverflows);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetByteTotals(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetByteTotals", STATUSMSG_Send);

	BOOL bRet = FALSE;

	typedef struct 
	{
		ULONGLONG TXPacket;
		ULONGLONG RXPacket;
	} STRUCT_GetByteTotals;

	STRUCT_GetByteTotals sParam;
	// clear structure
	memset(&sParam, 0, sizeof(STRUCT_GetByteTotals));

	// call Sierra interface
	ULONG nRet = GetByteTotals( &sParam.TXPacket, &sParam.RXPacket );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Byte Totals: TX[%I64d] RX[%I64d]", sParam.TXPacket, sParam.RXPacket);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETBYTETOTALS) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETBYTETOTALS pFn = (LPFN_GETBYTETOTALS)GetProcAddress_W(m_hQCDll, FUNC_GetByteTotals);

		// execute function
		if (pFn)
		{
			STRUCT_GetByteTotals sQcParam;
			// clear structure
			memset(&sQcParam, 0, sizeof(STRUCT_GetByteTotals));

			ULONG nQcRet = pFn((ULONG *)&sQcParam.TXPacket, (ULONG *)&sQcParam.RXPacket);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				strTemp.Format(L"Comparing: Byte Totals: TX/RX SWI[%I64d/%I64d] QCOM[%I64d/%I64d]", sParam.TXPacket, sParam.RXPacket, sQcParam.TXPacket, sQcParam.RXPacket);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetDataBearerTechnology(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDataBearerTechnology", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG dataStatus = 0;

	// call Sierra interface
	ULONG nRet = GetDataBearerTechnology( &dataStatus );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(dataStatus)
		{
		case 0x01:
			strTemp.Format(L"Data Bearer: CDMA 1xRTT [%d]", dataStatus );
			break;
		case 0x02:
			strTemp.Format(L"Data Bearer: CDMA 1xEV-DO [%d]", dataStatus );
			break;
		case 0x03:
			strTemp.Format(L"Data Bearer: GPRS [%d]", dataStatus );
			break;
		case 0x04:
			strTemp.Format(L"Data Bearer: WCDMA [%d]", dataStatus );
			break;
		case 0x05:
			strTemp.Format(L"Data Bearer: CDMA 1xEV-DO RevA [%d]", dataStatus );
			break;
		case 0x06:
			strTemp.Format(L"Data Bearer: EDGE [%d]", dataStatus );
			break;
		case 0x07:
			strTemp.Format(L"Data Bearer: HSDPA DL, WCDMA UL [%d]", dataStatus );
			break;
		case 0x08:
			strTemp.Format(L"Data Bearer: WCDMA DL, HSUPA UL [%d]", dataStatus );
			break;
		case 0x09:
			strTemp.Format(L"Data Bearer: HSDPA DL, HSUPA UL [%d]", dataStatus );
			break;
		default:
			strTemp.Format(L"Data Bearer: CDMA 1xRTT [%d]", dataStatus );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDATABEARER) (ULONG*);

		// get pointer to function
		LPFN_GETDATABEARER pFn = (LPFN_GETDATABEARER)GetProcAddress_W(m_hQCDll, FUNC_GetDataBearerTechnology);

		// execute function
		if (pFn)
		{
			ULONG qcDataStatus = 0;

			ULONG nQcRet = pFn(&qcDataStatus);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(qcDataStatus != dataStatus)
			{
				strTemp.Format(L"Comparing: qcDataStatus: %d  dataStatus: %d", qcDataStatus, dataStatus);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = TRUE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncSwiGetCurrentDataBearerTechnology(CParamList* pParams /*= NULL*/)
{
	UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncSwiGetCurrentDataBearerTechnology", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG NetworkType = 0;
	ULONG RatMask = 0;
	ULONG SoMask = 0;

	// call Sierra interface
	ULONG nRet = SwiGetCurrentDataBearerTechnology( &NetworkType, &RatMask, &SoMask );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(NetworkType)
		{
		case 0x00:
			strTemp.Format(L"NetworkType: 0x%02x - UNKNOWN", NetworkType );
			break;
		case 0x01:
			strTemp.Format(L"NetworkType: 0x%02x - 3GPP2", NetworkType );
			break;
		case 0x02:
			strTemp.Format(L"NetworkType: 0x%02x - 3GPP", NetworkType );
			break;
		default:
			strTemp.Format(L"NetworkType: 0x%02x", NetworkType );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		switch(RatMask)
		{
		case 0x00:
			strTemp.Format(L"RatMask: 0x%02x - DO NOT CARE", RatMask );
			break;
		default:
			strTemp.Format(L"RatMask: 0x%02x", RatMask );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		switch(SoMask)
		{
		case 0x00:
			strTemp.Format(L"SoMask: 0x%02x - DO NOT CARE", SoMask );
			break;
		default:
			strTemp.Format(L"SoMask: 0x%02x", SoMask );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = TRUE;
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetDormancyState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDormancyState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG dataStatus = 0;

	// call Sierra interface
	ULONG nRet = GetDormancyState( &dataStatus );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(dataStatus)
		{
		case 0x01:
			strTemp.Format(L"Dormancy Status: Traffic Channel Dormant [%d]", dataStatus );
			break;
		case 0x02:
			strTemp.Format(L"Dormancy Status: Traffic Channel Active [%d]", dataStatus );
			break;
		default:
			strTemp.Format(L"Dormancy Status: [%d]", dataStatus );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDORMANCYSTATUS) (ULONG*);

		// get pointer to function
		LPFN_GETDORMANCYSTATUS pFn = (LPFN_GETDORMANCYSTATUS)GetProcAddress_W(m_hQCDll, FUNC_GetDormancyState);

		// execute function
		if (pFn)
		{
			ULONG qcDataStatus = 0;

			ULONG nQcRet = pFn(&qcDataStatus);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(qcDataStatus != dataStatus)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetConnectionRate(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetConnectionRate", STATUSMSG_Send);

	BOOL bRet = FALSE;

	typedef struct 
	{
		ULONG CurrentTxRate;
		ULONG CurrentRxRate;
		ULONG MaxTxRate;
		ULONG MaxRxRate;
	} STRUCT_GetConnectionRate;

	STRUCT_GetConnectionRate sParam;
	// clear structure
	memset(&sParam, 0, sizeof(STRUCT_GetConnectionRate));

	// call Sierra interface
	ULONG nRet = GetConnectionRate(&sParam.CurrentTxRate, &sParam.CurrentRxRate, &sParam.MaxTxRate, &sParam.MaxRxRate);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Current Rate: Tx[%d] Rx[%d]", sParam.CurrentTxRate, sParam.CurrentRxRate );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"MAX Rate: Tx[%d] Rx[%d]", sParam.MaxTxRate, sParam.MaxRxRate );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETCONNECTIONRATE) (ULONG*, ULONG*, ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETCONNECTIONRATE pFn = (LPFN_GETCONNECTIONRATE)GetProcAddress_W(m_hQCDll, FUNC_GetConnectionRate);

		// execute function
		if (pFn)
		{
			STRUCT_GetConnectionRate sQcParam;
			// clear structure
			memset(&sQcParam, 0, sizeof(STRUCT_GetConnectionRate));

			ULONG nQcRet = pFn(&sQcParam.CurrentTxRate, &sQcParam.CurrentRxRate, &sQcParam.MaxTxRate, &sQcParam.MaxRxRate);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetConnectionRate)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}
BOOL CGobiApiWds::FuncGetAutoconnect(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetAutoconnect", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG setting = 0;

	// call Sierra interface
	ULONG nRet = GetAutoconnect( &setting );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(setting)
		{
		case 0x00:
			strTemp.Format(L"AutoConnect: Disabled [%d]", setting );
			break;
		case 0x01:
			strTemp.Format(L"AutoConnect: Enabled [%d]", setting  );
			break;
		default:
			strTemp.Format(L"AutoConnect: [%d]", setting );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETAUTOCONNECT) (ULONG*);

		// get pointer to function
		LPFN_GETAUTOCONNECT pFn = (LPFN_GETAUTOCONNECT)GetProcAddress_W(m_hQCDll, FUNC_GetAutoconnect);

		// execute function
		if (pFn)
		{
			ULONG qcSetting = 0;

			ULONG nQcRet = pFn(&qcSetting);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(qcSetting != setting)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}
BOOL CGobiApiWds::FuncSetAutoconnect(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetAutoconnect", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG nSetting = _ttoi(pParams->GetValue(PARAM_EnableAutoconnect));

	// call Sierra interface
	ULONG nRet = SetAutoconnect(nSetting);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = TRUE;

	// Query state with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_SETAUTOCONNECT) (ULONG);

		// get pointer to function
		LPFN_SETAUTOCONNECT pFn = (LPFN_SETAUTOCONNECT)GetProcAddress_W(m_hQCDll, FUNC_SetAutoconnect);

		// execute function
		if (pFn)
		{
			LONG nQcRet = pFn(nSetting);

			if (nQcRet != 0)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}
BOOL CGobiApiWds::FuncSetMobileIp(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetMobileIp", STATUSMSG_Send);
	BOOL bRet = FALSE;
	ULONG mode;

	mode = _ttoi(pParams->GetValue(PARAM_MipMode));

	// call Sierra interface
	ULONG nRet = SetMobileIP(mode);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = true;

	return(bRet);
}
BOOL CGobiApiWds::FuncGetMobileIp(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetMobileIp", STATUSMSG_Send);
	BOOL bRet = FALSE;
	ULONG mode;

	// call Sierra interface
	ULONG nRet = GetMobileIP(&mode);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"MIP mode: %d", mode  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = true;
	}

	return(bRet);
}
BOOL CGobiApiWds::FuncSetMobileIpProfile(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ADDSTATUS(L"FuncSetMobileIpProfile", STATUSMSG_Send);
	BOOL bRet = FALSE;
	CHAR SPC[nMaxStrLen] = "";
	BYTE index;
	BYTE enabled;
	ULONG address;
	ULONG primaryHA;
	ULONG secondaryHA;
	BYTE revTunneling;
	CHAR NAI[nMaxStrLen] = "";
	ULONG HASPI;
	ULONG AAASPI;
	CHAR MNHA[nMaxStrLen] = "";
	CHAR MNAAA[nMaxStrLen] = "";
	CHAR szIpAddress[nMaxStrLen] = "";
    


	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SPC), -1, SPC, nMaxStrLen, 0, 0);
	index = (BYTE)_ttoi(pParams->GetValue(PARAM_Index));
	enabled = (BYTE)_ttoi(pParams->GetValue(PARAM_Enabled));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Address), -1, szIpAddress, nMaxStrLen, 0, 0);
	address =  ntohl(inet_addr(szIpAddress));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_PrimaryHA), -1, szIpAddress, nMaxStrLen, 0, 0);
	primaryHA = ntohl(inet_addr(szIpAddress));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SecondaryHA), -1, szIpAddress, nMaxStrLen, 0, 0);
	secondaryHA = ntohl(inet_addr(szIpAddress));
	revTunneling = (BYTE)_ttoi(pParams->GetValue(PARAM_RevTunneling));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_NAI), -1, NAI, nMaxStrLen, 0, 0);
	HASPI = _ttoi(pParams->GetValue(PARAM_HASPI));
	AAASPI = _ttoi(pParams->GetValue(PARAM_AAASPI));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_MNHA), -1, MNHA, nMaxStrLen, 0, 0);
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_MNAAA), -1, MNAAA, nMaxStrLen, 0, 0);

	// call Sierra interface
	ULONG nRet = SetMobileIPProfile(SPC, 
			index, 
			&enabled, 
			&address, 
			&primaryHA, 
			&secondaryHA, 
			&revTunneling,
			NAI, 
			&HASPI,	
			&AAASPI, 
			MNHA, 
			MNAAA);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		bRet = true;
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncGetMobileIpProfile(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ADDSTATUS(L"FuncGetMobileIpProfile", STATUSMSG_Send);
	BOOL bRet = FALSE;

	struct STRUCT_GetMobileIpProfile
	{
		BYTE index;
		BYTE enabled;
		ULONG address;
		ULONG primaryHA;
		ULONG secondaryHA;
		BYTE revTunneling;
		CHAR NAI[nMaxStrLen];
		ULONG HASPI;
		ULONG AAASPI;
	};

	STRUCT_GetMobileIpProfile sParam;
	memset(&sParam, 0, sizeof(STRUCT_GetMobileIpProfile));

	sParam.index = (BYTE)_ttoi(pParams->GetValue(PARAM_Index));

	// call Sierra interface
	ULONG nRet = GetMobileIPProfile(sParam.index, 
									&sParam.enabled, 
									&sParam.address, 
									&sParam.primaryHA, 
									&sParam.secondaryHA, 
									&sParam.revTunneling, 
									nMaxStrLen, 
									sParam.NAI,
									&sParam.HASPI, 
									&sParam.AAASPI);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"index: %d", sParam.index  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"enabled: %d", sParam.enabled  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"address: %d.%d.%d.%d", (sParam.address & 0xFF000000)>> 24, (sParam.address & 0x00FF0000) >> 16, (sParam.address & 0x0000FF00) >> 8, sParam.address & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"primaryHA: %d.%d.%d.%d", (sParam.primaryHA & 0xFF000000)>> 24, (sParam.primaryHA & 0x00FF0000) >> 16, (sParam.primaryHA & 0x0000FF00) >> 8, sParam.primaryHA & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"secondaryHA: %d.%d.%d.%d", (sParam.secondaryHA & 0xFF000000)>> 24, (sParam.secondaryHA & 0x00FF0000) >> 16, (sParam.secondaryHA & 0x0000FF00) >> 8, sParam.secondaryHA & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"revTunneling: %d", sParam.revTunneling  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		WCHAR strNai[nMaxStrLen] = L"";
		MultiByteToWideChar(CP_ACP, 0, sParam.NAI, nMaxStrLen, strNai, nMaxStrLen);
		strTemp.Format(L"NAI: %s", strNai);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"HASPI: %i", sParam.HASPI  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"AAASPI: %i", sParam.AAASPI  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = true;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETMOBILEIPPROFILE) (BYTE, BYTE*, ULONG*, ULONG*, ULONG*, BYTE*, BYTE, CHAR*, ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETMOBILEIPPROFILE pFn = (LPFN_GETMOBILEIPPROFILE)GetProcAddress_W(m_hQCDll, FUNC_GetMobileIpProfile);

		// execute function
		if (pFn)
		{
			STRUCT_GetMobileIpProfile sQcParam;
			memset(&sQcParam, 0, sizeof(STRUCT_GetMobileIpProfile));

			sQcParam.index = sParam.index;

			ULONG nQcRet = pFn(sQcParam.index, 
							  &sQcParam.enabled, 
							  &sQcParam.address, 
							  &sQcParam.primaryHA, 
							  &sQcParam.secondaryHA, 
							  &sQcParam.revTunneling, 
							  nMaxStrLen, 
							  sQcParam.NAI,
							  &sQcParam.HASPI, 
							  &sQcParam.AAASPI);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetMobileIpProfile)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncGetMobileIpProfile2(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ADDSTATUS(L"FuncGetMobileIpProfile2", STATUSMSG_Send);
	BOOL bRet = FALSE;

	struct STRUCT_GetMobileIpProfile2
	{
		BYTE index;
		BYTE enabled;
		ULONG address;
		ULONG primaryHA;
		ULONG secondaryHA;
		BYTE revTunneling;
		CHAR NAI[nMaxStrLen];
		ULONG HASPI;
		ULONG AAASPI;
		ULONG HAKEYSTATE;
		ULONG AAAKEYSTATE;
	};

	STRUCT_GetMobileIpProfile2 sParam;
	memset(&sParam, 0, sizeof(STRUCT_GetMobileIpProfile2));

	sParam.index = (BYTE)_ttoi(pParams->GetValue(PARAM_Index));

	// call Sierra interface
	ULONG nRet = GetMobileIPProfile2(sParam.index, 
									&sParam.enabled, 
									&sParam.address, 
									&sParam.primaryHA, 
									&sParam.secondaryHA, 
									&sParam.revTunneling, 
									nMaxStrLen, 
									sParam.NAI,
									&sParam.HASPI, 
									&sParam.AAASPI,
									&sParam.HAKEYSTATE, 
									&sParam.AAAKEYSTATE);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"index: %d", sParam.index  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"enabled: %d", sParam.enabled  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"address: %d.%d.%d.%d", (sParam.address & 0xFF000000)>> 24, (sParam.address & 0x00FF0000) >> 16, (sParam.address & 0x0000FF00) >> 8, sParam.address & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"primaryHA: %d.%d.%d.%d", (sParam.primaryHA & 0xFF000000)>> 24, (sParam.primaryHA & 0x00FF0000) >> 16, (sParam.primaryHA & 0x0000FF00) >> 8, sParam.primaryHA & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		// display IP address
		strTemp.Format(L"secondaryHA: %d.%d.%d.%d", (sParam.secondaryHA & 0xFF000000)>> 24, (sParam.secondaryHA & 0x00FF0000) >> 16, (sParam.secondaryHA & 0x0000FF00) >> 8, sParam.secondaryHA & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"revTunneling: %d", sParam.revTunneling  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		WCHAR strNai[nMaxStrLen] = L"";
		MultiByteToWideChar(CP_ACP, 0, sParam.NAI, nMaxStrLen, strNai, nMaxStrLen);
		strTemp.Format(L"NAI: %s", strNai);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"HASPI: %i", sParam.HASPI  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"AAASPI: %i", sParam.AAASPI  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"HA KEY STATE: %i", sParam.HAKEYSTATE  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"AAA KEY STATE: %i", sParam.AAAKEYSTATE );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = true;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETMOBILEIPPROFILE2) (BYTE, BYTE*, ULONG*, ULONG*, ULONG*, BYTE*, BYTE, CHAR*, ULONG*, ULONG*, ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETMOBILEIPPROFILE2 pFn = (LPFN_GETMOBILEIPPROFILE2)GetProcAddress_W(m_hQCDll, FUNC_GetMobileIpProfile2);

		// execute function
		if (pFn)
		{
			STRUCT_GetMobileIpProfile2 sQcParam;
			memset(&sQcParam, 0, sizeof(STRUCT_GetMobileIpProfile2));

			sQcParam.index = sParam.index;

			ULONG nQcRet = pFn(sQcParam.index, 
							  &sQcParam.enabled, 
							  &sQcParam.address, 
							  &sQcParam.primaryHA, 
							  &sQcParam.secondaryHA, 
							  &sQcParam.revTunneling, 
							  nMaxStrLen, 
							  sQcParam.NAI,
							  &sQcParam.HASPI, 
							  &sQcParam.AAASPI,
							  &sQcParam.HAKEYSTATE, 
							  &sQcParam.AAAKEYSTATE);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetMobileIpProfile2)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncSetActiveMobileIpProfile(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ADDSTATUS(L"FuncSetActiveMobileIpProfile", STATUSMSG_Send);
	BOOL bRet = FALSE;
	CHAR SPC[nMaxStrLen] = "";
	BYTE index;

	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SPC), -1, SPC, nMaxStrLen, 0, 0);
	index = (BYTE)_ttoi(pParams->GetValue(PARAM_Index));

	// call Sierra interface
	ULONG nRet = SetActiveMobileIPProfile(SPC, index);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		bRet = true;
	}

	return(bRet);
}
BOOL CGobiApiWds::FuncGetActiveMobileIpProfile(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetActiveMobileIpProfile", STATUSMSG_Send);
	BOOL bRet = FALSE;
	BYTE index;

	// call Sierra interface
	ULONG nRet = GetActiveMobileIPProfile(&index);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"index: %d", index  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = true;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETACTIVEMOBILEIPPROFILE) (BYTE*);

		// get pointer to function
		LPFN_GETACTIVEMOBILEIPPROFILE pFn = (LPFN_GETACTIVEMOBILEIPPROFILE)GetProcAddress_W(m_hQCDll, FUNC_GetActiveMobileIpProfile);

		// execute function
		if (pFn)
		{
			BYTE QcIndex = 0;

			ULONG nQcRet = pFn(&QcIndex);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(index != QcIndex)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return(bRet);
}
BOOL CGobiApiWds::FuncSetMobileIpParameters(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ADDSTATUS(L"FuncSetMobileIpParameters", STATUSMSG_Send);
	BOOL bRet = FALSE;
	ULONG mode;
	CHAR SPC[nMaxStrLen] = "";
	BYTE retryLimit;
	BYTE retryInterval;
	BYTE reRegPeriod;
	BYTE reRegTraffic;
	BYTE HAAuthenticator;
	BYTE HA2002bis;

	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SPC), -1, SPC, nMaxStrLen, 0, 0);
	mode = _ttoi(pParams->GetValue(PARAM_MipMode));
	retryLimit = (BYTE)_ttoi(pParams->GetValue(PARAM_RetryLimit));
	retryInterval = (BYTE)_ttoi(pParams->GetValue(PARAM_RetryInterval));
	reRegPeriod = (BYTE)_ttoi(pParams->GetValue(PARAM_ReRetryPeriod));
	reRegTraffic = (BYTE)_ttoi(pParams->GetValue(PARAM_ReRegTraffic));
	HAAuthenticator = (BYTE)_ttoi(pParams->GetValue(PARAM_HAAuthenticator));
	HA2002bis = (BYTE)_ttoi(pParams->GetValue(PARAM_HA2002bis));

	// call Sierra interface
	ULONG nRet = SetMobileIPParameters(SPC, &mode, &retryLimit, 
		&retryInterval, &reRegPeriod, &reRegTraffic, &HAAuthenticator, &HA2002bis );

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		bRet = true;
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncGetMobileIpParameters(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetMobileIpParameters", STATUSMSG_Send);
	BOOL bRet = FALSE;

	struct STRUCT_GetMobileIpParameters
	{
		ULONG mode;
		BYTE retryLimit;
		BYTE retryInterval;
		BYTE reRegPeriod;
		BYTE reRegTraffic;
		BYTE HAAuthenticator;
		BYTE HA2002bis;
	};
	
	STRUCT_GetMobileIpParameters sParam;
	memset(&sParam, 0, sizeof(STRUCT_GetMobileIpParameters));

	// call Sierra interface
	ULONG nRet = GetMobileIPParameters(&sParam.mode, 
									   &sParam.retryLimit, 
									   &sParam.retryInterval, 
									   &sParam.reRegPeriod, 
									   &sParam.reRegTraffic,
									   &sParam.HAAuthenticator, 
									   &sParam.HA2002bis);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"mode: %d", sParam.mode  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"retryLimit: %d", sParam.retryLimit  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"retryInterval: %d", sParam.retryInterval  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"reRegPeriod: %d", sParam.reRegPeriod  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"reRegTraffic: %d", sParam.reRegTraffic  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"HAAuthenticator: %d", sParam.HAAuthenticator  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"HA2002bis: %d", sParam.HA2002bis  );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = true;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETMOBILEIPARAMETERS) (ULONG*, BYTE*, BYTE*, BYTE*, BYTE*, BYTE*, BYTE*);

		// get pointer to function
		LPFN_GETMOBILEIPARAMETERS pFn = (LPFN_GETMOBILEIPARAMETERS)GetProcAddress_W(m_hQCDll, FUNC_GetMobileIpParameters);

		// execute function
		if (pFn)
		{
			STRUCT_GetMobileIpParameters sQcParam;
			memset(&sQcParam, 0, sizeof(STRUCT_GetMobileIpParameters));

			ULONG nQcRet = pFn(&sQcParam.mode, 
							  &sQcParam.retryLimit, 
							  &sQcParam.retryInterval, 
							  &sQcParam.reRegPeriod, 
							  &sQcParam.reRegTraffic,
							  &sQcParam.HAAuthenticator, 
							  &sQcParam.HA2002bis);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetMobileIpParameters)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncGetLastMobileIpError(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetLastMobileIpError", STATUSMSG_Send);
	BOOL bRet = FALSE;
	ULONG nError;

	// call Sierra interface
	ULONG nRet = GetLastMobileIPError(&nError);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"error: %d", nError);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		bRet = true;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETLASTMOBILEIPERROR) (ULONG*);

		// get pointer to function
		LPFN_GETLASTMOBILEIPERROR pFn = (LPFN_GETLASTMOBILEIPERROR)GetProcAddress_W(m_hQCDll, FUNC_GetLastMobileIpError);

		// execute function
		if (pFn)
		{
			ULONG QcError = 0;

			ULONG nQcRet = pFn(&QcError);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(nError != QcError)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return(bRet);
}

BOOL CGobiApiWds::FuncGetDefaultProfile(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDefaultProfile", STATUSMSG_Send);

	BOOL bRet = FALSE;
	const BYTE MAX_ProfileName = 0xFF;
	const BYTE MAX_ApnName = 0xFF;
	const BYTE MAX_UserName = 0xFF;

	typedef struct 
	{
		ULONG	PDPType; 
		ULONG	IpAddress;
		ULONG	PrimaryDNS;
		ULONG	SecondaryDNS;
		ULONG	Authentication; 
		CHAR	profileName[MAX_ProfileName];
		CHAR	APNName[MAX_ApnName]; 
		CHAR	Username[MAX_UserName];
	} STRUCT_GetDefaultProfile;

	STRUCT_GetDefaultProfile sParam;
	// clear structure
	memset(&sParam, 0, sizeof(STRUCT_GetDefaultProfile));

	// call Sierra interface
	ULONG nRet = GetDefaultProfile(0x00, &sParam.PDPType, &sParam.IpAddress, &sParam.PrimaryDNS, &sParam.SecondaryDNS, &sParam.Authentication, MAX_ProfileName, sParam.profileName, MAX_ApnName, sParam.APNName, MAX_UserName, sParam.Username);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"PDP Type: %d", sParam.PDPType );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"IPADDRESS: %x", sParam.IpAddress);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"DNS: Primary[%x] Secondary[%x]", sParam.PrimaryDNS, sParam.SecondaryDNS);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Authentication: %x", sParam.Authentication);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		WCHAR szStringU[MAX_ProfileName] = L"";

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.profileName, MAX_ProfileName, szStringU, MAX_ProfileName) == MAX_ProfileName)
		{
			strTemp.Format(L"ProfileName: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.APNName, MAX_ApnName, szStringU, MAX_ApnName) == MAX_ApnName)
		{
			strTemp.Format(L"ProfileApn: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.Username, MAX_UserName, szStringU, MAX_UserName) == MAX_UserName)
		{
			strTemp.Format(L"ProfileUserName: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}
		
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDEFAULTPROFILE) (ULONG, ULONG*, ULONG*, ULONG*, ULONG*, ULONG*, BYTE, CHAR*, BYTE, CHAR*, BYTE, CHAR*);

		// get pointer to function
		LPFN_GETDEFAULTPROFILE pFn = (LPFN_GETDEFAULTPROFILE)GetProcAddress_W(m_hQCDll, FUNC_GetDefaultProfile);

		// execute function
		if (pFn)
		{
			STRUCT_GetDefaultProfile sQcParam;
			// clear structure
			memset(&sQcParam, 0, sizeof(STRUCT_GetDefaultProfile));

			ULONG nQcRet = pFn(0x00, &sQcParam.PDPType, &sQcParam.IpAddress, &sQcParam.PrimaryDNS, &sQcParam.SecondaryDNS, &sQcParam.Authentication, MAX_ProfileName, &sQcParam.profileName[0], MAX_ApnName, &sQcParam.APNName[0], MAX_UserName, &sQcParam.Username[0]);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetDefaultProfile)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetDefaultIPv6Profile(CParamList * pParams /* = NULL */)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDefaultIPv6Profile", STATUSMSG_Send);

	BOOL bRet = FALSE;

    typedef struct
    {
        USHORT IpAddress[8];
        USHORT PrimaryDNS[8];
        USHORT SecondaryDNS[8];
    } STRUCT_GetDefaultIPv6Profile;

    STRUCT_GetDefaultIPv6Profile sParam;
    memset( &sParam, 0, sizeof(STRUCT_GetDefaultIPv6Profile) );

    ULONG nRet = GetDefaultIPv6Profile( 0, 
                                        &sParam.IpAddress[0],
                                        &sParam.PrimaryDNS[0],
                                        &sParam.SecondaryDNS[0] );

    // display output in GUI
	CString strTemp;
	strTemp.Format( L"Result: %04d", nRet );
	ADDSTATUS( strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error );

    if (!nRet)
    {
#ifndef UNDER_CE
        // Display IP address
        IN6_ADDR addr_ipv6;
        TCHAR a[64] = {0};
        memcpy( &addr_ipv6.u.Word[0], &sParam.IpAddress[0], sizeof(USHORT) * 8 );
        InetNtop( AF_INET6, &addr_ipv6, a, 64 );
        strTemp.Format( L"IPv6 address: %s", a );
        ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

        // Display DNS addresses
        memcpy( &addr_ipv6.u.Word[0], &sParam.PrimaryDNS[0], sizeof(USHORT) * 8 );
        InetNtop( AF_INET6, &addr_ipv6, a, 64 );
        strTemp.Format( L"Primary IPv6 DNS: %s", a );
        ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

        memcpy( &addr_ipv6.u.Word[0], &sParam.SecondaryDNS[0], sizeof(USHORT) * 8 );
        InetNtop( AF_INET6, &addr_ipv6, a, 64 );
        strTemp.Format( L"Secondary IPv6 DNS: %s", a );
        ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );
#endif
        bRet = TRUE;
    }

    // Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDEFAULTIPV6PROFILE) (ULONG, USHORT*, USHORT*, USHORT*);

		// get pointer to function
		LPFN_GETDEFAULTIPV6PROFILE pFn = (LPFN_GETDEFAULTIPV6PROFILE)GetProcAddress_W( m_hQCDll, FUNC_GetDefaultIPv6Profile );

		// execute function
		if (pFn)
		{
			STRUCT_GetDefaultIPv6Profile sQcParam;
			// clear structure
			memset( &sQcParam, 0, sizeof(STRUCT_GetDefaultIPv6Profile) );

			ULONG nQcRet = pFn( 0x00, &sQcParam.IpAddress[0], &sQcParam.PrimaryDNS[0], &sQcParam.SecondaryDNS[0] );

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp( &sQcParam, &sParam, sizeof(STRUCT_GetDefaultIPv6Profile) ))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

    return bRet;
}

BOOL CGobiApiWds::FuncGetDefaultProfileLTE(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
    BOOL bRet = FALSE;
/*	ADDSTATUS(L"FuncGetDefaultProfileLTE", STATUSMSG_Send);

	const BYTE MAX_ProfileName = 0xFF;
	const BYTE MAX_ApnName = 0xFF;
	const BYTE MAX_UserName = 0xFF;
    const BYTE MAX_IPV6 = 0x8;

	typedef struct 
	{
		ULONG	PDPType; 
		ULONG	IpAddressv4;
		ULONG	PrimaryDNSv4;
		ULONG	SecondaryDNSv4;
        USHORT  IpAddressv6[MAX_IPV6];
        USHORT  PrimaryDNSv6[MAX_IPV6];
        USHORT  SecondaryDNSv6[MAX_IPV6];
		ULONG	Authentication; 
		CHAR	profileName[MAX_ProfileName];
		CHAR	APNName[MAX_ApnName]; 
		CHAR	Username[MAX_UserName];
	} STRUCT_GetDefaultProfileLTE;

	STRUCT_GetDefaultProfileLTE sParam;
	// clear structure
	memset(&sParam, 0, sizeof(STRUCT_GetDefaultProfileLTE));

	// call Sierra interface
	ULONG nRet = GetDefaultProfileLTE(0x00, &sParam.PDPType, &sParam.IpAddressv4, &sParam.PrimaryDNSv4, &sParam.SecondaryDNSv4,
        &sParam.IpAddressv6[0], &sParam.PrimaryDNSv6[0], &sParam.SecondaryDNSv6[0], &sParam.Authentication, 
        MAX_ProfileName, sParam.profileName, MAX_ApnName, sParam.APNName, MAX_UserName, sParam.Username);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"PDP Type: %d", sParam.PDPType );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"IPADDRESSv4: %x", sParam.IpAddressv4);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"DNSv4: Primary[%x] Secondary[%x]", sParam.PrimaryDNSv4, sParam.SecondaryDNSv4);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
        strTemp.Format(L"IPADDRESSv6: %x", sParam.IpAddressv6);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"DNSv6: Primary[%x] Secondary[%x]", sParam.PrimaryDNSv6, sParam.SecondaryDNSv6);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		strTemp.Format(L"Authentication: %x", sParam.Authentication);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		WCHAR szStringU[MAX_ProfileName] = L"";

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.profileName, MAX_ProfileName, szStringU, MAX_ProfileName) == MAX_ProfileName)
		{
			strTemp.Format(L"ProfileName: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.APNName, MAX_ApnName, szStringU, MAX_ApnName) == MAX_ApnName)
		{
			strTemp.Format(L"ProfileApn: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, sParam.Username, MAX_UserName, szStringU, MAX_UserName) == MAX_UserName)
		{
			strTemp.Format(L"ProfileUserName: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}
		
		bRet = TRUE;
	}
*/
	// Compare with QC DLL
/*	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDEFAULTPROFILE) (ULONG, ULONG*, ULONG*, ULONG*, ULONG*, ULONG*, BYTE, CHAR*, BYTE, CHAR*, BYTE, CHAR*);

		// get pointer to function
		LPFN_GETDEFAULTPROFILE pFn = (LPFN_GETDEFAULTPROFILE)GetProcAddress_W(m_hQCDll, FUNC_GetDefaultProfile);

		// execute function
		if (pFn)
		{
			STRUCT_GetDefaultProfileLTE sQcParam;
			// clear structure
			memset(&sQcParam, 0, sizeof(STRUCT_GetDefaultProfileLTE));

			ULONG nQcRet = pFn(0x00, &sQcParam.PDPType, &sQcParam.IpAddress, &sQcParam.PrimaryDNS, &sQcParam.SecondaryDNS, &sQcParam.Authentication, MAX_ProfileName, &sQcParam.profileName[0], MAX_ApnName, &sQcParam.APNName[0], MAX_UserName, &sQcParam.Username[0]);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if(0 != memcmp(&sQcParam, &sParam, sizeof(STRUCT_GetDefaultProfile)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}
*/
    return bRet;
}

BOOL CGobiApiWds::FuncSetDefaultProfile(CParamList* pParams /*= NULL*/)
{
	const UINT nMaxStrLen = 0xFF;
	ULONG ProfileType = 0; 
	ULONG PDPType = 0;
	ULONG PrimaryDNS = 0;
	ULONG SecondaryDNS = 0; 
	CHAR APNName[nMaxStrLen] = "internet.com";
	ULONG IPAddress = 0;
	CHAR szIpAddress[nMaxStrLen] = "";
	ULONG Authentication = 0; 
	CHAR Username[nMaxStrLen] = "wapuser"; 
	CHAR Password[nMaxStrLen] = "wap";
	CHAR Name[nMaxStrLen] = "Rogers";

	ADDSTATUS(L"FuncSetDefaultProfile", STATUSMSG_Send);
	BOOL bRet = FALSE;

	ProfileType		= _ttoi(pParams->GetValue(PARAM_ProfileType));
	PDPType			= _ttoi(pParams->GetValue(PARAM_PDPType));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_IpAddress), -1, szIpAddress, nMaxStrLen, 0, 0);
	IPAddress		= ntohl(inet_addr(szIpAddress));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_PrimaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
    PrimaryDNS		= ntohl(inet_addr(szIpAddress));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SecondaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
	SecondaryDNS	= ntohl(inet_addr(szIpAddress));
	Authentication	= _ttoi(pParams->GetValue(PARAM_Authentication));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ProfileName), -1, Name, nMaxStrLen, 0, 0);
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Username), -1, Username, nMaxStrLen, 0, 0);
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_Password), -1, Password, nMaxStrLen, 0, 0);
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ApnName), -1, APNName, nMaxStrLen, 0, 0);

	// call Sierra interface
	ULONG nRet = SetDefaultProfile(
		ProfileType, 
		&PDPType, 
		&IPAddress, 
		&PrimaryDNS, 
		&SecondaryDNS, 
		&Authentication, 
		Name, 
		APNName, 
		Username, 
		Password);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = TRUE;

	return bRet;
}

BOOL CGobiApiWds::FuncSetDefaultIPv6Profile( CParamList * pParams /* = NULL */ )
{
    ADDSTATUS( L"FuncSetDefaultIPv6Profile", STATUSMSG_Send );

    BOOL bRet = FALSE;

    if (!pParams)
    {
        return bRet;
    }

#ifndef UNDER_CE
    ULONG ProfileType = _ttoi(pParams->GetValue(PARAM_ProfileType));
    USHORT IPAddressIPv6[8] = {0};
    USHORT PrimaryDNSIPv6[8] = {0};
    USHORT SecondaryDNSIPv6[8] = {0};
    IN6_ADDR addr_ipv6;

    memset( &addr_ipv6, 0, sizeof(IN6_ADDR) );
    CString strAdd = pParams->GetValue( PARAM_IpAddressIPv6 );
    InetPton( AF_INET6, strAdd.GetBuffer(), &addr_ipv6 );
    memcpy( &IPAddressIPv6[0], &addr_ipv6.u.Word[0], sizeof(USHORT) * 8 );
        
    strAdd = pParams->GetValue( PARAM_PrimaryDnsIPv6 );
    InetPton( AF_INET6, strAdd.GetBuffer(), &addr_ipv6 );
    memcpy( &PrimaryDNSIPv6[0], &addr_ipv6.u.Word[0], sizeof(USHORT) * 8 );

    strAdd = pParams->GetValue( PARAM_SecondaryDnsIPv6 );
    InetPton( AF_INET6, strAdd.GetBuffer(), &addr_ipv6 );
    memcpy( &SecondaryDNSIPv6[0], &addr_ipv6.u.Word[0], sizeof(USHORT) * 8 );

    ULONG nRet = SetDefaultIPv6Profile( ProfileType, IPAddressIPv6, PrimaryDNSIPv6, SecondaryDNSIPv6 );

    // display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = TRUE;

#else
	ADDSTATUS(L"Not supported on WinCE", STATUSMSG_Error);
#endif

    return bRet;
}

BOOL CGobiApiWds::FuncGetSessionDuration(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetSessionDuration", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONGLONG callDuration = 0;

	// call Sierra interface
	ULONG nRet = GetSessionDuration(&callDuration); 

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		strTemp.Format(L"Call Duration(msec): %I64d", callDuration );
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETCALLDURATION) (ULONGLONG*);

		// get pointer to function
		LPFN_GETCALLDURATION pFn = (LPFN_GETCALLDURATION)GetProcAddress_W(m_hQCDll, FUNC_GetSessionDuration);

		// execute function
		if (pFn)
		{
			ULONGLONG QcSessionDuration = 0;

			ULONG nQcRet = pFn(&QcSessionDuration);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				strTemp.Format(L"Session Duration[milliseconds]: SWI[%I64d] Qualcomm[%I64d]", callDuration, QcSessionDuration);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}
// WDS callback functions
static void SWICALLBACK SessionStateCallback(ULONG sessionState, ULONG endReason )
{
	ADDSTATUS(L"SessionStateCallback", STATUSMSG_Receive);
	CString strTemp;

	switch(sessionState)
	{
	case 0x01:
		switch(endReason)
		{
		case 1:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: Unspecified[%d]", sessionState, endReason);
			break;
		case 2:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: ClientEnded[%d]", sessionState, endReason);
			break;
		case 3:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: NoService[%d]", sessionState, endReason);
			break;
		case 4:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: Fade[%d]", sessionState, endReason);
			break;
		case 5:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: RelNormal[%d]", sessionState, endReason);
			break;
		case 6:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: AccInProg[%d]", sessionState, endReason);
			break;
		case 7:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: AccFail[%d]", sessionState, endReason);
			break;
		case 8:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: RedirOrHandoff[%d]", sessionState, endReason);
			break;
		default:
			strTemp.Format(L"Notification - State: Disconnected[%d]  End Reason: [%d]", sessionState, endReason);
			break;
		}
		break;
	case 0x02:
		strTemp.Format(L"Notification - State: Connected[%d]  End Reason %d", sessionState, endReason);
		break;
	case 0x03:
		strTemp.Format(L"Notification - State: Suspended[%d]  End Reason %d", sessionState, endReason);
		break;
	case 0x04:
		strTemp.Format(L"Notification - State: Authenicating[%d]  End Reason %d", sessionState, endReason);
		break;
	default:
		strTemp.Format(L"Notification - State: [%d]  End Reason %d", sessionState, endReason);
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

static void SWICALLBACK DataBearerCallback(ULONG dataBearer )
{
	ADDSTATUS(L"DataBearerCallback", STATUSMSG_Receive);
	CString strTemp;
	switch(dataBearer)
	{
	case 0x01:
		strTemp.Format(L"Notification - Data Bearer: CDMA 1xRTT [%d]", dataBearer );
		break;
	case 0x02:
		strTemp.Format(L"Notification - Data Bearer: CDMA 1xEV-DO [%d]", dataBearer );
		break;
	case 0x03:
		strTemp.Format(L"Notification - Data Bearer: GPRS [%d]", dataBearer );
		break;
	case 0x04:
		strTemp.Format(L"Notifiation - Data Bearer: WCDMA [%d]", dataBearer );
		break;
	case 0x05:
		strTemp.Format(L"Notification - Data Bearer: CDMA 1xEV-DO RevA [%d]", dataBearer );
		break;
	case 0x06:
		strTemp.Format(L"Notification - Data Bearer: EDGE [%d]", dataBearer );
		break;
	case 0x07:
		strTemp.Format(L"Notification - Data Bearer: HSDPA DL, WCDMA UL [%d]", dataBearer );
		break;
	case 0x08:
		strTemp.Format(L"Notification - Data Bearer: WCDMA DL, HSUPA UL [%d]", dataBearer );
		break;
	case 0x09:
		strTemp.Format(L"Notification - Data Bearer: HSDPA DL, HSUPA UL [%d]", dataBearer );
		break;
	default:
		strTemp.Format(L"Notifiation - Data Bearer: CDMA 1xRTT [%d]", dataBearer );
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

static void SWICALLBACK CurrentDataBearerCallback(ULONG NetworkType, ULONG RatMask, ULONG SoMask )
{
	ADDSTATUS(L"CurrentDataBearerCallback", STATUSMSG_Receive);
	CString strTemp;
	switch(NetworkType)
	{
	case 0x00:
		strTemp.Format(L"NetworkType: 0x%02x - UNKNOWN", NetworkType );
		break;
	case 0x01:
		strTemp.Format(L"NetworkType: 0x%02x - 3GPP2", NetworkType );
		break;
	case 0x02:
		strTemp.Format(L"NetworkType: 0x%02x - 3GPP", NetworkType );
		break;
	default:
		strTemp.Format(L"NetworkType: 0x%02x", NetworkType );
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	switch(RatMask)
	{
	case 0x00:
		strTemp.Format(L"RatMask: 0x%02x - DO NOT CARE", RatMask );
		break;
	default:
		strTemp.Format(L"RatMask: 0x%02x", RatMask );
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	switch(SoMask)
	{
	case 0x00:
		strTemp.Format(L"SoMask: 0x%02x - DO NOT CARE", SoMask );
		break;
	default:
		strTemp.Format(L"SoMask: 0x%02x", SoMask );
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Receive);  
}

static void SWICALLBACK DormancyStatusCallback(ULONG dormancyStatus )
{
	ADDSTATUS(L"DormancyStatusCallback", STATUSMSG_Receive);
	CString strTemp;
	switch(dormancyStatus)
	{
	case 0x01:
		strTemp.Format(L"Notification - Dormancy Status: Traffic Channel Dormant [%d]", dormancyStatus );
		break;
	case 0x02:
		strTemp.Format(L"Notification - Dormancy Status: Traffic Channel Active [%d]", dormancyStatus );
		break;
	default:
		strTemp.Format(L"Notification - Dormancy Status: [%d]", dormancyStatus );
		break;
	}
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

static void SWICALLBACK ByteTotalsCallback(ULONGLONG totalBytesTX, ULONGLONG totalBytesRX )
{
	ADDSTATUS(L"ByteTotalsCallback", STATUSMSG_Receive);
	CString strTemp;
	strTemp.Format(L"Notification - Byte Totals: tx[%I64d] rx[%I64d]", totalBytesTX, totalBytesRX);
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

static void SWICALLBACK MobileIPStatusCallback(ULONG mipStatus )
{
	ADDSTATUS(L"MobileIPStatusCallback", STATUSMSG_Receive);
	CString strTemp;
	strTemp.Format(L"Notification - MIP status: %04d", mipStatus);
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

BOOL CGobiApiWds::FuncSetSessionStateCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetSessionStateCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetSessionStateCallback(SessionStateCallback);
	}
	else
	{
		ret = SetSessionStateCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSetDataBearerCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetDataBearerCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetDataBearerCallback(DataBearerCallback);
	}
	else
	{
		ret = SetDataBearerCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSwiSetCurrentDataBearerCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSwiSetCurrentDataBearerCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SwiSetCurrentDataBearerCallback(CurrentDataBearerCallback);
	}
	else
	{
		ret = SwiSetCurrentDataBearerCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSetDormancyStatusCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetDormancyStatusCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetDormancyStatusCallback(DormancyStatusCallback);
	}
	else
	{
		ret = SetDormancyStatusCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSetByteTotalsCallback(CParamList* pParams)
{
	ADDSTATUS(L"FuncSetByteTotalsCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetByteTotalsCallback(ByteTotalsCallback, (BYTE)_ttoi(pParams->GetValue(PARAM_Interval)));
	}
	else
	{
		ret = SetByteTotalsCallback(NULL, 0);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSetMobileIPStatusCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetMobileIPStatusCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetMobileIPStatusCallback(MobileIPStatusCallback);
	}
	else
	{
		ret = SetMobileIPStatusCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

BOOL CGobiApiWds::FuncSwiGoDormant(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncSwiGoDormant", STATUSMSG_Send);

	ULONG ret = SwiGoDormant();
	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);

	return ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);
}

BOOL CGobiApiWds::FuncGetEnhancedAutoconnect(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetEnhancedAutoconnect", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG setting = 0;
	ULONG RoamSetting = 0;

	// call Sierra interface
	ULONG nRet = GetEnhancedAutoconnect(&setting, &RoamSetting);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
	{
		switch(setting)
		{
		case 0x00:
			strTemp.Format(L"AutoConnect: Disabled [%d]", setting );
			break;
		case 0x01:
			strTemp.Format(L"AutoConnect: Enabled [%d]", setting  );
			break;
		case 0x02:
			strTemp.Format(L"AutoConnect: Paused [%d] (resume on power cycle)", setting  );
			break;
		default:
			strTemp.Format(L"AutoConnect: [%d]", setting );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		switch(RoamSetting)
		{
		case 0x00:
			strTemp.Format(L"AutoConnect Roaming: Always allowed [%d]", RoamSetting );
			break;
		case 0x01:
			strTemp.Format(L"AutoConnect Roaming: while in home service area only [%d]", RoamSetting  );
			break;
		default:
			strTemp.Format(L"AutoConnect Roaming: [%d]", RoamSetting );
			break;
		}
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETENHANCEDAUTOCONNECT) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETENHANCEDAUTOCONNECT pFn = (LPFN_GETENHANCEDAUTOCONNECT)GetProcAddress_W(m_hQCDll, FUNC_GetEnhancedAutoconnect);

		// execute function
		if (pFn)
		{
			ULONG qcSetting = 0;
			ULONG qcRoamSetting = 0;

			ULONG nQcRet = pFn(&qcSetting, &qcRoamSetting);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if((qcSetting != setting)||(qcRoamSetting != RoamSetting))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncSetEnhancedAutoconnect(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetEnhancedAutoconnect", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG nSetting = _ttoi(pParams->GetValue(PARAM_EnableAutoconnect));
	ULONG nRoamingSetting = _ttoi(pParams->GetValue(PARAM_SetRoamAutoconnect));

	// call Sierra interface
	ULONG nRet = SetEnhancedAutoconnect(nSetting, &nRoamingSetting);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = TRUE;

	// Query state with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_SETENHANCEDAUTOCONNECT) (ULONG, ULONG*);

		// get pointer to function
		LPFN_SETENHANCEDAUTOCONNECT pFn = (LPFN_SETENHANCEDAUTOCONNECT)GetProcAddress_W(m_hQCDll, FUNC_SetEnhancedAutoconnect);

		// execute function
		if (pFn)
		{

			LONG nQcRet = pFn(nSetting, &nRoamingSetting);

			if (nQcRet != 0)
			{
				strTemp.Format(L"QC returned status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}


BOOL CGobiApiWds::FuncGetDNSSettings(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDNSSettings", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG	PrimaryDNS = 0;
	ULONG	SecondaryDNS = 0;

	// call Sierra interface
	ULONG nRet = GetDNSSettings(&PrimaryDNS, &SecondaryDNS);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
    {
		// display IP address
		strTemp.Format(L"PrimaryDNS: %d.%d.%d.%d", (PrimaryDNS & 0xFF000000)>> 24, (PrimaryDNS & 0x00FF0000) >> 16, (PrimaryDNS & 0x0000FF00) >> 8, PrimaryDNS & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

		strTemp.Format(L"SecondaryDNS: %d.%d.%d.%d", (SecondaryDNS & 0xFF000000)>> 24, (SecondaryDNS & 0x00FF0000) >> 16, (SecondaryDNS & 0x0000FF00) >> 8, SecondaryDNS & 0x000000FF);
		ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		bRet = TRUE;
    }   

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_GETDNSSETTINGS) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETDNSSETTINGS pFn = (LPFN_GETDNSSETTINGS)GetProcAddress_W(m_hQCDll, FUNC_GetDNSSettings);

		// execute function
		if (pFn)
		{
			ULONG qcPrimaryDNS = 0;
			ULONG qcSecondaryDNS = 0;

			ULONG nQcRet = pFn(&qcPrimaryDNS, &qcSecondaryDNS);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if((qcPrimaryDNS != PrimaryDNS)||(qcSecondaryDNS != SecondaryDNS))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}



BOOL CGobiApiWds::FuncSetDNSSettings(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncSetDNSSettings", STATUSMSG_Send);

	const UINT nMaxStrLen = 0xFF;
	BOOL bRet = FALSE;
	ULONG	PrimaryDNS = 0;
	ULONG	SecondaryDNS = 0;
	CHAR szIpAddress[nMaxStrLen] = "";

	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_PrimaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
	PrimaryDNS  = ntohl(inet_addr(szIpAddress));
	WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_SecondaryDns), -1, szIpAddress, nMaxStrLen, 0, 0);
	SecondaryDNS  = ntohl(inet_addr(szIpAddress));

	// call Sierra interface
	ULONG nRet = SetDNSSettings(&PrimaryDNS, &SecondaryDNS);

	// display output in GUI
	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);
	ADDSTATUS(strTemp,(nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);

	if (!nRet)
		bRet = TRUE;

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICALLBACK*LPFN_SETDNSSETTINGS) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_SETDNSSETTINGS pFn = (LPFN_SETDNSSETTINGS)GetProcAddress_W(m_hQCDll, FUNC_SetDNSSettings);

		// execute function
		if (pFn)
		{
			ULONG qcPrimaryDNS = 0;
			ULONG qcSecondaryDNS = 0;

			ULONG nQcRet = pFn(&qcPrimaryDNS, &qcSecondaryDNS);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if((qcPrimaryDNS != PrimaryDNS)||(qcSecondaryDNS != SecondaryDNS))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiWds::FuncGetDNSIPv6Settings(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetDNSIPv6Settings", STATUSMSG_Send);

	BOOL bRet = FALSE;
    USHORT  PrimaryDNSIPv6[8] = {0};
    USHORT	SecondaryDNSIPv6[8] = {0};

    // Call Sierra Interface
    ULONG nRet = GetDNSIPv6Settings( &PrimaryDNSIPv6[0], &SecondaryDNSIPv6[0] );

    // Display the output in GUI
    CString strTemp;
    strTemp.Format( L"Result: %04d", nRet );
    ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

    if (!nRet)
    {
#ifndef UNDER_CE
        // Display DNS addresses
        IN6_ADDR addr_ipv6;
        TCHAR a[64] = {0};
        memcpy( &addr_ipv6.u.Word[0], &PrimaryDNSIPv6[0], sizeof(USHORT) * 8 );
        InetNtop( AF_INET6, &addr_ipv6, a, 64 );

        strTemp.Format( L"Primary IPv6 DNS: %s", a );

        ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

        memset( a, 0, sizeof(TCHAR) * 64 );
        memcpy( &addr_ipv6.u.Word[0], &SecondaryDNSIPv6[0], sizeof(USHORT) * 8 );
        InetNtop( AF_INET6, &addr_ipv6, a, 64 );

        strTemp.Format( L"Secondary IPv6 DNS: %s", a );
        ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );
#endif
        bRet = TRUE;
    }

    // Compare with QC DLL
    if (m_hQCDll)
    {
        // Function prototype
        typedef ULONG (SWICALLBACK * LPFN_GETDNSIPv6SETTINGS)(USHORT *, USHORT *);

        // Get pointer to function
        LPFN_GETDNSIPv6SETTINGS pFn = (LPFN_GETDNSIPv6SETTINGS)GetProcAddress_W( m_hQCDll, FUNC_GetDNSIPv6Settings );

        // Execute function
        if (pFn)
        {
            USHORT qcPrimaryDNSIPv6[8] = {0};
            USHORT qcSecondaryDNSIPv6[8] = {0};

            ULONG nqcRet = pFn( &qcPrimaryDNSIPv6[0], &qcSecondaryDNSIPv6[0] );

            if (nqcRet != nRet)
            {
                strTemp.Format( L"QC returned a different status code: %04d", nqcRet );
                ADDSTATUS( strTemp, STATUSMSG_Error );
                bRet = FALSE;
            }
            else if ((memcmp( &qcPrimaryDNSIPv6[0], &PrimaryDNSIPv6[0], sizeof(USHORT) * 8 ) != 0) ||
                     (memcpy( &qcSecondaryDNSIPv6[0], &SecondaryDNSIPv6[0], sizeof(USHORT) * 8 ) != 0))
            {
                ADDSTATUS( L"Response differes from QC DLL", STATUSMSG_Error );
                bRet = FALSE;
            }
            else
            {
                ADDSTATUS( L"Response matches QC DLL", STATUSMSG_Status );
                bRet = TRUE;
            }
        }
    }

    return bRet;
}

BOOL CGobiApiWds::FuncSetDNSIPv6Settings(CParamList* pParams /*= NULL*/)
{
    ADDSTATUS( L"FuncSetDNSIPv6Settings", STATUSMSG_Send );

    BOOL bRet = FALSE;

#ifndef UNDER_CE
    USHORT PrimaryDNSIPv6[8] = {0};
    USHORT SecondaryDNSIPv6[8] = {0};
    IN6_ADDR addr_ipv6;

    memset( &addr_ipv6, 0, sizeof(IN6_ADDR) );
    CString strAdd = pParams->GetValue( PARAM_PrimaryDnsIPv6 );
    InetPton( AF_INET6, strAdd.GetBuffer(), &addr_ipv6 );
    memcpy( &PrimaryDNSIPv6[0], &addr_ipv6.u.Word[0], sizeof(USHORT) * 8 );

    strAdd = pParams->GetValue( PARAM_SecondaryDnsIPv6 );
    InetPton( AF_INET6, strAdd.GetBuffer(), &addr_ipv6 );
    memcpy( &SecondaryDNSIPv6[0], &addr_ipv6.u.Word[0], sizeof(USHORT) * 8 );

    // Call Sierra interface
    ULONG nRet = SetDNSIPv6Settings( &PrimaryDNSIPv6[0], &SecondaryDNSIPv6[0] );

    // Display the output in GUI
    CString strTemp;
    strTemp.Format( L"Result: %04d", nRet );
    ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

    if (!nRet)
    {
        bRet = TRUE;
    }

    // Compare with QC DLL
    if (m_hQCDll)
    {
        // Function prototype
        typedef ULONG (SWICALLBACK * LPFN_SETDNSIPv6SETTINGS)(USHORT *, USHORT *);

        // Get pointer to function
        LPFN_SETDNSIPv6SETTINGS pFn = (LPFN_SETDNSIPv6SETTINGS)GetProcAddress_W( m_hQCDll, FUNC_SetDNSIPv6Settings );

        // Execute function
        if (pFn)
        {
            USHORT qcPrimaryDNSIPv6[8] = {0};
            USHORT qcSecondaryDNSIPv6[8] = {0};

            memcpy( &qcPrimaryDNSIPv6[0], &PrimaryDNSIPv6[0], sizeof(USHORT) * 8 );
            memcpy( &qcSecondaryDNSIPv6[0], &SecondaryDNSIPv6[0], sizeof(USHORT) * 8 );

            ULONG nqcRet = pFn( &qcPrimaryDNSIPv6[0], &qcSecondaryDNSIPv6[0] );

            if (nqcRet != nRet)
            {
                strTemp.Format( L"QC returned a different status code: %04d", nqcRet );
                ADDSTATUS( strTemp, STATUSMSG_Error );
                bRet = FALSE;
            }
            else
            {
                ADDSTATUS( L"Response matches QC DLL", STATUSMSG_Status );
                bRet = TRUE;
            }
        }
    }

#else
	UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS( L"not supported on WinCE", STATUSMSG_Error );
#endif

    return bRet;
}

BOOL CGobiApiWds::FuncSwiGetApn(CParamList* pParams /*= NULL*/)
{
	UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncSwiGetCdmaApn", STATUSMSG_Send);

	BOOL bRet = FALSE;

	const BYTE MAX_ApnName = 0xFF;
	CHAR szApnName[MAX_ApnName] = "";

	CString strType = pParams->GetValue(PARAM_ProfileType);
	CString strIndex = pParams->GetValue(PARAM_Index);

	BYTE nType = _ttoi(strType);
	BYTE nIndex = _ttoi(strIndex);

	// Call Sierra Interface
	ULONG nRet = SwiGetApn( nType, nIndex, MAX_ApnName, szApnName);

	// Display the output in GUI
	CString strTemp;
	strTemp.Format( L"Result: %04d", nRet );
	ADDSTATUS( strTemp, (nRet == 0) ? STATUSMSG_Receive : STATUSMSG_Error );

	if (!nRet)
	{
		WCHAR szStringU[MAX_ApnName] = L"";

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, szApnName, MAX_ApnName, szStringU, MAX_ApnName) == MAX_ApnName)
		{
			strTemp.Format(L"APN: %s", szStringU);
			ADDSTATUS(strTemp, (nRet==0)?STATUSMSG_Receive:STATUSMSG_Error);
		}

		bRet = TRUE;
	}

	return bRet;
}