#include "StdAfx.h"
#include "GobiApiDev.h"
#include "FuncList.h"
#include "StatusCtrl.h"
#include <GobiAPI.h>
#include "GobiConnectionMgmtAPI.h"
#include "SwiWwanCmApi.h"
#include "ApiHelperGobi.h"

const UINT LENGTH_DeviceId = 256;
const UINT LENGTH_DeviceKey = 16;

#define FUNC_Start							L"Find and connect to device"
#define FUNC_QCWWAN2kEnumerateDevices		L"QCWWAN2kEnumerateDevices"
#define FUNC_QCWWANConnect					L"QCWWANConnect"
#define FUNC_QCWWAN2kConnect				L"QCWWAN2kConnect"
#define FUNC_QCWWANDisconnect				L"QCWWANDisconnect"
#define FUNC_QCWWANGetConnectedDeviceID		L"QCWWANGetConnectedDeviceID"
#define FUNC_QCWWAN2kGetConnectedDeviceID	L"QCWWAN2kGetConnectedDeviceID"
#define FUNC_SwiSetDeviceRemovalCallback	L"SwiSetDeviceRemovalCallback"
#define FUNC_InvokeApiCrash					L"InvokeApiCrash"

#define PARAM_DeviceId		L"DeviceID"
#define PARAM_DeviceKey		L"DeviceKey"
#define PARAM_Enable		L"Enable"
#define PARAM_CrashMethod	L"CrashMethod"

CParamList CGobiApiDev::m_sQCWWAN2kConnect;
CParamList CGobiApiDev::m_sSetDeviceRemovalCallback;
CParamList CGobiApiDev::m_sInvokeApiCrash;

const TableFuncEntry CGobiApiDev::m_TableFunc[] = 
{
	{FUNC_Start,						FuncStart},
	{FUNC_QCWWAN2kEnumerateDevices,		FuncQCWWAN2kEnumerateDevices},
	{FUNC_QCWWANConnect,				FuncQCWWANConnect},
	{FUNC_QCWWAN2kConnect,				FuncQCWWAN2kConnect,				&m_sQCWWAN2kConnect},
	{FUNC_QCWWANDisconnect,				FuncQCWWANDisconnect},
	{FUNC_QCWWANGetConnectedDeviceID,	FuncQCWWANGetConnectedDeviceID},
	{FUNC_QCWWAN2kGetConnectedDeviceID, FuncQCWWAN2kGetConnectedDeviceID},
	{FUNC_SwiSetDeviceRemovalCallback,	FuncSwiSetDeviceRemovalCallback,	&m_sSetDeviceRemovalCallback},
	{FUNC_InvokeApiCrash,				FuncInvokeApiCrash,					&m_sInvokeApiCrash},
	{FUNC_EndOfList}
};

CGobiApiDev::CGobiApiDev(HMODULE hQCDll)
{
	// Initialize the Qualcomm Dll pointer
	m_hQCDll = hQCDll;

	// Define Set SMS Wake configurable parameters
	m_sQCWWAN2kConnect.Add(PARAM_DeviceId, L"0");
	m_sQCWWAN2kConnect.Add(PARAM_DeviceKey, L"0");
	m_sSetDeviceRemovalCallback.Add(PARAM_Enable, L"1");
	m_sInvokeApiCrash.Add(PARAM_CrashMethod, L"0");
}

CGobiApiDev::~CGobiApiDev(void)
{
}

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

	int iIndex = 0;

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

	return TRUE;
}

UINT CGobiApiDev::ExecuteFunctions(CFuncList* pFuncList, UINT &nTotalExec)
{
	TBD_FUNCTION(CGobiApiDev::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;
}

#ifndef UNDER_CE
BOOL CGobiApiDev::FuncStart(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncStart", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	CString strTemp;
	BOOL bRet = FALSE;

	// enumerate list of available devices
	const UINT MAX_DeviceList = 3;

	typedef struct STRUCT_DeviceArrayElement
	{
		CHAR szDeviceId[LENGTH_DeviceId];
		CHAR szDeviceKey[LENGTH_DeviceKey];
	} TYPE_DEVICEARRAYELEMENT;

	TYPE_DEVICEARRAYELEMENT sDeviceList[MAX_DeviceList];
	memset(&sDeviceList, 0, sizeof(sDeviceList));
	BYTE nDeviceListSize = MAX_DeviceList;

	ADDSTATUS(L"Getting list of available devices", STATUSMSG_Send);
	ULONG nRet = QCWWAN2kEnumerateDevices(&nDeviceListSize, (BYTE*)&sDeviceList);

	if (!nRet)
	{
		if (!nDeviceListSize)
		{
			ADDSTATUS(L"No devices found", STATUSMSG_Send);
			bRet = TRUE;
		}
		else
		{
			ADDSTATUS(L"Selecting first available device", STATUSMSG_Send);
			nRet = QCWWAN2kConnect(sDeviceList[0].szDeviceId, sDeviceList[0].szDeviceKey);

			if (!nRet)
			{
				ADDSTATUS(L"Registering device removal callback", STATUSMSG_Send);
				nRet = SwiSetDeviceRemovalCallback(CApiHelperGobi::DeviceRemovalCallback);

				if (!nRet)
					bRet = TRUE;
				else
				{
					strTemp.Format(L"SwiSetDeviceRemovalCallback failed: %04d", nRet);
					ADDSTATUS(strTemp, STATUSMSG_Error);
				}
			}
			else
			{
				strTemp.Format(L"QCWWAN2kConnect failed: %04d", nRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
			}
		}
	}	
	else
	{
		strTemp.Format(L"QCWWAN2kEnumerateDevices failed: %04d", nRet);
		ADDSTATUS(strTemp, STATUSMSG_Error);
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		ADDSTATUS(L"Initialzing QC DLL", STATUSMSG_Send);
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_QCWWAN2KENERMATEDEVICES) (BYTE*, BYTE*);

		// get pointer to function
		LPFN_QCWWAN2KENERMATEDEVICES pFn = (LPFN_QCWWAN2KENERMATEDEVICES)GetProcAddress_W(m_hQCDll, FUNC_QCWWAN2kEnumerateDevices);

		// execute function
		if (pFn)
		{
			TYPE_DEVICEARRAYELEMENT sQcDeviceList[MAX_DeviceList];
			memset(&sQcDeviceList, 0, sizeof(sQcDeviceList));
			BYTE nQcDeviceListSize = MAX_DeviceList;

			ADDSTATUS(L"Getting list of available devices", STATUSMSG_Send);
			ULONG nQcRet = pFn(&nQcDeviceListSize, (BYTE*)&sQcDeviceList);

			if (!nQcRet)
			{
				if (!nQcDeviceListSize)
				{
					ADDSTATUS(L"QC DLL did not find any devices", STATUSMSG_Send);

					if (nQcRet != nRet)
					{
						ADDSTATUS(L"Qualcomm DLL returned a different return code", STATUSMSG_Error);
						bRet = FALSE;
					}
					else
					{
						ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
						bRet = TRUE;
					}
				}
				else
				{
					// function prototype
					typedef ULONG (SWICMAPI*LPFN_QCWWAN2kConnect) (CHAR*, CHAR*);

					// get pointer to function
					LPFN_QCWWAN2kConnect pFn = (LPFN_QCWWAN2kConnect)GetProcAddress_W(m_hQCDll, FUNC_QCWWAN2kConnect);

					// execute function
					if (pFn)
					{
						ADDSTATUS(L"Selecting first available device", STATUSMSG_Send);
						nQcRet = pFn(sQcDeviceList[0].szDeviceId, sQcDeviceList[0].szDeviceKey);

						if (nQcRet != nRet)
						{
							ADDSTATUS(L"Qualcomm DLL returned a different return code", STATUSMSG_Error);
							bRet = FALSE;
						}
						else
						{
							ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
							bRet = TRUE;
						}
					}
				}
			}
		}
	}

	return bRet;
}
#else
BOOL CGobiApiDev::FuncStart(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncStart", STATUSMSG_Send);

	CString strTemp;
	BOOL bRet = FALSE;

	ADDSTATUS(L"Connecting to device device", STATUSMSG_Send);
	ULONG nRet = QCWWANConnect();

	if (!nRet)
	{
		ADDSTATUS(L"Registering device removal callback", STATUSMSG_Send);
		nRet = SwiSetDeviceRemovalCallback(CApiHelperGobi::DeviceRemovalCallback);

		if (!nRet)
			bRet = TRUE;
		else
		{
			strTemp.Format(L"SwiSetDeviceRemovalCallback failed: %04d", nRet);
			ADDSTATUS(strTemp, STATUSMSG_Error);
		}
	}
	else
	{
		strTemp.Format(L"QCWWANConnect failed: %04d", nRet);
		ADDSTATUS(strTemp, STATUSMSG_Error);
	}

	return bRet;
}
#endif

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

	BOOL bRet = FALSE;
	const UINT MAX_DEVICE_LIST_SIZE	= 5;

	typedef struct STRUCT_DeviceArrayElement
	{
		CHAR szDeviceId[LENGTH_DeviceId];
		CHAR szDeviceKey[LENGTH_DeviceKey];
	} TYPE_DEVICEARRAYELEMENT;
	
	TYPE_DEVICEARRAYELEMENT sDeviceList[MAX_DEVICE_LIST_SIZE];
	memset(&sDeviceList, 0, sizeof(sDeviceList));
	BYTE nDeviceListSize = MAX_DEVICE_LIST_SIZE;

	ULONG nRet = QCWWAN2kEnumerateDevices(&nDeviceListSize, (BYTE*)&sDeviceList);

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

	if (!nRet)
	{
		strTemp.Format(L"Number of devices: %i", nDeviceListSize);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		
		TCHAR szStringU[LENGTH_DeviceId+1] = L"";

		for (int i=0; i<nDeviceListSize; i++)
		{
			// convert to UNICODE so we can display it
			if (MultiByteToWideChar(CP_ACP, 0, sDeviceList[i].szDeviceId, LENGTH_DeviceId, szStringU, LENGTH_DeviceId) == LENGTH_DeviceId)
			{
				strTemp.Format(L"DeviceId: %s", szStringU);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
			}

			// convert to UNICODE so we can display it
			if (MultiByteToWideChar(CP_ACP, 0, sDeviceList[i].szDeviceKey, LENGTH_DeviceId, szStringU, LENGTH_DeviceId) == LENGTH_DeviceId)
			{
				strTemp.Format(L"DeviceKey: %s", szStringU);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
			}
		}

		bRet = TRUE;
	}

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

		// get pointer to function
		LPFN_QCWWAN2KENERMATEDEVICES pFn = (LPFN_QCWWAN2KENERMATEDEVICES)GetProcAddress_W(m_hQCDll, FUNC_QCWWAN2kEnumerateDevices);

		// execute function
		if (pFn)
		{
			TYPE_DEVICEARRAYELEMENT sQcDeviceList[MAX_DEVICE_LIST_SIZE];
			memset(&sQcDeviceList, 0, sizeof(sQcDeviceList));
			BYTE nQcDeviceListSize = MAX_DEVICE_LIST_SIZE;

			ULONG nQcRet = pFn(&nQcDeviceListSize, (BYTE*)&sQcDeviceList);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if ((nQcDeviceListSize != nDeviceListSize) || (0 != memcmp(sQcDeviceList, sDeviceList, sizeof(sQcDeviceList))))
			{
				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 CGobiApiDev::FuncQCWWANConnect(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncQCWWANConnect", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;

	ULONG nRet = QCWWANConnect();

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

	if (!nRet)
	{
		bRet = TRUE;
	}

	if (m_hQCDll)
	{
		// Get pointer to QCWWANConnect function and call it
		ULONG nQcRet = GetProcAddress_W(m_hQCDll, L"QCWWANConnect")();

		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 Qualcomm DLL", STATUSMSG_Status);
			bRet = TRUE;
		}
	}

	return bRet;
}

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

	CHAR szDeviceId[LENGTH_DeviceId];
	CHAR szDeviceKey[LENGTH_DeviceKey];

	// Get user selected parameters
	if (pParams)
	{
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_DeviceId), -1, szDeviceId, LENGTH_DeviceId, 0, 0);
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_DeviceKey), -1, szDeviceKey, LENGTH_DeviceKey, 0, 0);
	}

	ULONG nRet = QCWWAN2kConnect(szDeviceId, szDeviceKey);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);


	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_QCWWAN2kConnect) (CHAR*, CHAR*);

		// get pointer to function
		LPFN_QCWWAN2kConnect pFn = (LPFN_QCWWAN2kConnect)GetProcAddress_W(m_hQCDll, FUNC_QCWWAN2kConnect);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(szDeviceId, szDeviceKey);

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

	return (nRet == 0)?TRUE:FALSE;
}

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

	BOOL bRet = FALSE;

	ULONG nRet = QCWWANDisconnect();

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

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Un-initialize Qualcomm API
	if (m_hQCDll)
	{
		ADDSTATUS(L"Un-initializing QC DLL", STATUSMSG_Send);
		ULONG nQcRet = GetProcAddress_W(m_hQCDll, L"QCWWANDisconnect")();

		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 Qualcomm DLL", STATUSMSG_Status);
			bRet = TRUE;
		}
	}

	return bRet;
}

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

	BOOL bRet = FALSE;
	const ULONG MAX_StringLength = 0xFF;
	CHAR szDeviceId[MAX_StringLength] = "";

	ULONG nRet = QCWWANGetConnectedDeviceID(MAX_StringLength, szDeviceId);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	// Get connected device ID
	if (!nRet)
	{
		TCHAR szStringU[MAX_StringLength] = L"";

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, szDeviceId, MAX_StringLength, szStringU, MAX_StringLength) == MAX_StringLength)
		{
			CString strTemp;
			strTemp.Format(L"DeviceId: %s", szStringU);
			ADDSTATUS(strTemp, STATUSMSG_Receive);
		}

		bRet = TRUE;
	}

	if (m_hQCDll)
	{
		// QCWWANGetConnectedDeviceID function prototype
		typedef ULONG (__stdcall * PFNQCWWANGETCONNECTEDDEVICEID)(ULONG , CHAR*);

		// Get pointer to QCWWANGetConnectedDeviceID
		PFNQCWWANGETCONNECTEDDEVICEID pFn = (PFNQCWWANGETCONNECTEDDEVICEID)GetProcAddress_W(m_hQCDll, L"QCWWANGetConnectedDeviceID");

		if (pFn)
		{
			CHAR szQcDeviceId[MAX_StringLength] = "";

			// Call QCWWANGetConnectedDeviceID
			ULONG nQcRet = pFn(MAX_StringLength, szQcDeviceId);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (0 != memcmp(&szDeviceId, &szQcDeviceId, MAX_StringLength))
			{
				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 CGobiApiDev::FuncQCWWAN2kGetConnectedDeviceID(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncQCWWAN2kGetConnectedDeviceID", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;
	CHAR szDeviceId[LENGTH_DeviceId] = "";
	CHAR szDeviceKey[LENGTH_DeviceKey] = "";

	ULONG nRet = QCWWAN2kGetConnectedDeviceID(LENGTH_DeviceId, szDeviceId, LENGTH_DeviceKey, szDeviceKey);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	// Get connected device ID
	if (!nRet)
	{
		TCHAR szStringU[LENGTH_DeviceId] = L"";

		// convert to UNICODE so we can display it
		if (MultiByteToWideChar(CP_ACP, 0, szDeviceId, LENGTH_DeviceId, szStringU, LENGTH_DeviceId) == LENGTH_DeviceId)
		{
			CString strTemp;
			strTemp.Format(L"DeviceId: %s", szStringU);
			ADDSTATUS(strTemp, STATUSMSG_Receive);
		}
		if (MultiByteToWideChar(CP_ACP, 0, szDeviceKey, LENGTH_DeviceKey, szStringU, LENGTH_DeviceId) == LENGTH_DeviceKey)
		{
			CString strTemp;
			strTemp.Format(L"DeviceKey: %s", szStringU);
			ADDSTATUS(strTemp, STATUSMSG_Receive);
		}

		bRet = TRUE;
	}

	if (m_hQCDll)
	{
		// QCWWANGetConnectedDeviceID function prototype
		typedef ULONG (__stdcall * PFNQCWWANGETCONNECTEDDEVICEID)(ULONG , CHAR*, ULONG, CHAR*);

		// Get pointer to QCWWANGetConnectedDeviceID
		PFNQCWWANGETCONNECTEDDEVICEID pFn = (PFNQCWWANGETCONNECTEDDEVICEID)GetProcAddress_W(m_hQCDll, L"QCWWAN2kGetConnectedDeviceID");

		if (pFn)
		{
			CHAR szQcDeviceId[LENGTH_DeviceId] = "";
			CHAR szQcDeviceKey[LENGTH_DeviceKey] = "";

			// Call QCWWANGetConnectedDeviceID
			ULONG nQcRet = pFn(LENGTH_DeviceId, szQcDeviceId, LENGTH_DeviceKey, szQcDeviceKey);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (0 != memcmp(&szDeviceId, &szQcDeviceId, LENGTH_DeviceId))
			{
				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 CGobiApiDev::FuncSwiSetDeviceRemovalCallback(CParamList* pParams /* = NULL */)
{
	ADDSTATUS(L"FuncSwiSetDeviceRemovalCallback", STATUSMSG_Send);

	// Register for device removal notification
	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SwiSetDeviceRemovalCallback(CApiHelperGobi::DeviceRemovalCallback);
	}
	else
	{
		ret = SwiSetDeviceRemovalCallback(NULL);
	}

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

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


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

	ULONG nRet = InvokeApiCrash(_ttoi(pParams->GetValue(PARAM_CrashMethod)));

	CString strTemp;
	strTemp.Format(L"Result: %04d", nRet);

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