www.pudn.com > SMS.rar > MobileControl.cpp


// MobileControl.cpp: implementation of the CMobileControl class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "MobileControl.h" 
 
#ifndef _SMS_DISABLE 
 
// Callgle 短信帮助信息 
#define CALLGLE_HELP_INFO1 "\ 
##\n\ 
[{for example}]:\n\ 
#101,102#Hello!\n\ 
" 
 
#define CALLGLE_HELP_INFO2 "\ 
###[GroupName1,2, ...]#\n\ 
[{for example}]:\n\ 
##Bulletin#PerDept,MarketDept#Hello!\n\ 
" 
 
// 是否是电话号码字符 
#define IS_PHONE_CHAR(ch) (((ch)>=_T('0') && (ch)<=_T('9')) || (ch)==_T('*') || (ch)==_T('#') || (ch)==_T('+')) 
// 
// 获取正确的电话号码字符串 
// 如:输入"+12ab*d#()982", 输出"+12*#982" 
// ret : 处理后字符串长度 
// 
int GetRightPhoneNOString ( IN OUT TCHAR* szPhoneNO, TCHAR cExtra=_T('\0') ) 
{ 
	if ( !szPhoneNO ) return 0; 
	int nLen = lstrlen ( szPhoneNO ); 
	int count = 0; 
	for ( int i=0; iThreadProc_Mobile(); 
	pMobileControl->ClearSendQueue (); 
	return bRet; 
} 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CMobileControl::CMobileControl() 
	: m_Proc_ReceivedSMS ( NULL ) 
	, m_wParam ( NULL ) 
	, m_lParam ( NULL ) 
	, m_hEvt_TerminateSys ( NULL ) 
	, m_hThread_Mobile ( NULL ) 
	, m_bRunAsServer ( FALSE ) 
	, m_bRecvSMSEnable ( FALSE ) 
	, m_eRunState ( ENUM_RunState_Start ) 
	, m_InitializeInterfaceInterval ( INITIALIZE_INTERFACE_INTERVAL ) 
	, m_nComNO_UserDefine ( 0 ) 
	, m_eMobileStatus ( ENUM_ERROR_TYPE_INVALID_DATA ) 
	, m_eMobileStatus_Real ( ENUM_ERROR_TYPE_INVALID_DATA ) 
	, m_Proc_HandleMobileStatusChange ( NULL ) 
	, m_paraHandleMobileStatusChange ( 0 ) 
	, m_pdwSentSMSCount ( NULL ) 
	, m_pMobileParameter ( NULL ) 
	, m_bMustRegistered ( TRUE ) 
{ 
	m_hEvt_SMSSendQueue = NULL; 
	m_Ary_SMS_SendQueue.SetSize ( 0, 10*sizeof(t_SMS_SendQueue) ); 
	m_csSMSHead = _T("SMS:\n"); 
	m_csSMSTail = _T("\nSent by chrys"); 
 
	HwDbgLog ( L_DEBUG, _T("CMobileControl 构造完成") ); 
} 
 
CMobileControl::~CMobileControl() 
{ 
	RestoreRecvSMSNotifyMode (); 
	ChangeMobileStatus ( ENUM_ERROR_TYPE_NoneMobile ); 
	if ( m_hEvt_TerminateSys ) 
		::SetEvent ( m_hEvt_TerminateSys ); 
	WaitForThreadEnd ( &m_hThread_Mobile ); 
 
	m_CSFor_SMSSendQueue.Lock (); 
	m_Ary_SMS_SendQueue.RemoveAll(); 
	m_CSFor_SMSSendQueue.Unlock (); 
	m_Ary_MobileNOHead.RemoveAll (); 
 
	// 关闭事件对象 
	if ( m_hEvt_SMSSendQueue && m_hEvt_SMSSendQueue != INVALID_HANDLE_VALUE ) 
		::CloseHandle ( m_hEvt_SMSSendQueue ); 
	m_hEvt_SMSSendQueue = NULL; 
	Log ( L_VERBOSE, _T("Mobile module be uninit") ); 
} 
 
BOOL CMobileControl::Init ( 
		BOOL bRunAsServer,			// 是否当作服务器运行 
		BOOL bRecvSMSEnable,		// 是否允许自动收取手机短信 
		HANDLE hEvt_TerminateSys, 
		int nComNO, 
		int nBaudRate 
) 
{ 
	if ( m_hThread_Mobile && m_hThread_Mobile != INVALID_HANDLE_VALUE ) 
	{ 
		return TRUE; 
	} 
 
	m_hEvt_TerminateSys = hEvt_TerminateSys; 
	ASSERT ( m_hEvt_TerminateSys && m_hEvt_TerminateSys != INVALID_HANDLE_VALUE ); 
 
	m_bRunAsServer = bRunAsServer; 
	m_bRecvSMSEnable = bRecvSMSEnable; 
	CHwMobile::SetModulePara ( nComNO, nBaudRate ); 
	m_nComNO_UserDefine = nComNO; 
	m_eRunState = ENUM_RunState_Init; 
 
	// 做服务器运行时就创建一个手机工作线程 
	if ( m_bRunAsServer ) 
	{ 
		if ( !m_hEvt_SMSSendQueue ) 
		{ 
			m_hEvt_SMSSendQueue = ::CreateEvent ( NULL, FALSE, FALSE, NULL ); 
			if ( !m_hEvt_SMSSendQueue || m_hEvt_SMSSendQueue == INVALID_HANDLE_VALUE ) 
				return FALSE; 
		} 
		if ( !m_hThread_Mobile ) 
		{ 
			m_hThread_Mobile = ::CreateThread ( NULL, 0, ::ThreadProc_Mobile, this, 0, NULL ); 
			if ( !m_hThread_Mobile || m_hThread_Mobile == INVALID_HANDLE_VALUE ) 
				return FALSE; 
		} 
		else 
		{ 
			::ResumeThread ( m_hThread_Mobile ); 
		} 
	} 
	else 
	{ 
		return InitMobileControl (); 
	} 
	 
	return TRUE; 
} 
 
// 
// 初始化手机模块 
// 
BOOL CMobileControl::InitMobileControl () 
{ 
	static DWORD dwStartTime = 0; 
	if ( !TimeIntervalArrived ( dwStartTime, m_InitializeInterfaceInterval ) ) 
	{ 
		return FALSE; 
	} 
#ifndef _DEBUG 
	m_InitializeInterfaceInterval += INITIALIZE_INTERFACE_INTERVAL; 
	if ( m_InitializeInterfaceInterval > 30 ) 
		m_InitializeInterfaceInterval = 30; 
#endif 
 
	BOOL bRet = FALSE; 
	int nComNO = 0; 
	for ( int i=0; i<3; i++ ) 
	{ 
		if ( InitMobileModule ( nComNO ) ) 
		{ 
			bRet = TRUE; 
			break; 
		} 
		if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 100 ) == WAIT_OBJECT_0 ) 
		{ 
			return FALSE; 
		} 
	} 
 
	if ( m_bInitMobileLastRes != bRet ) 
	{		 
		if ( bRet ) 
		{ 
			Log ( L_VERBOSE | L_OUT_UI, _T("Initialize mobile module [COM%d] successfully"), nComNO ); 
		} 
		else 
		{ 
			Log ( L_WARNING | L_OUT_UI, _T("Initialize mobile module failed") ); 
		} 
		m_bInitMobileLastRes = bRet; 
	} 
 
	if ( bRet ) 
	{ 
		if ( !m_pMobileParameter || lstrlen(m_pMobileParameter->szLocalCountryCode) < 1 || lstrlen(m_pMobileParameter->szLocalAreaCode) < 1 ) 
		{ 
			Log ( L_WARNING | L_OUT_UI, _T("Please set country code") ); 
			ChangeMobileStatus ( ENUM_ERROR_TYPE_ConfigNotRight ); 
		} 
		else 
		{ 
			ChangeMobileStatus ( ENUM_ERROR_TYPE_SUCCESS ); 
		} 
	} 
	else 
	{ 
		ChangeMobileStatus ( ENUM_ERROR_TYPE_NotInitialized ); 
	} 
 
	return bRet; 
} 
 
// 
// 只做初始化手机模块的操作 
// 
BOOL CMobileControl::InitMobileModule ( int &nComNO ) 
{ 
	BOOL bRet = FALSE; 
	nComNO = 0; 
	// 指定一个串口 
	if ( m_nComNO_UserDefine >= 1 && m_nComNO_UserDefine <= MAX_COM_NO ) 
	{ 
		nComNO = m_nComNO_UserDefine; 
		bRet = InitMobileOneCOM ( nComNO ); 
	} 
	// 自动 
	else 
	{ 
		for ( nComNO = 1; nComNO <= MAX_COM_NO; nComNO ++ ) 
		{ 
			if ( InitMobileOneCOM ( nComNO ) ) 
			{ 
				bRet = TRUE; 
				break; 
			} 
			if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 ) 
				return FALSE; 
		} 
	} 
 
	return bRet; 
} 
 
// 
// 用一个串口初始化手机模块 
// 
BOOL CMobileControl::InitMobileOneCOM ( int nComNO ) 
{ 
	SetModulePara ( nComNO ); 
	if ( CHwMobile::Init () ) 
	{ 
		if ( m_bMustRegistered ) 
		{ 
			BOOL bIsRegistered = FALSE; 
			for ( int i=0; i<3; i++ ) 
			{ 
				if ( GSMModuleIsRegistered () ) 
				{ 
					bIsRegistered = TRUE; 
					break; 
				} 
				if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 3*1000 ) == WAIT_OBJECT_0 ) 
					return FALSE; 
			} 
			if ( !bIsRegistered ) 
			{ 
				Log ( L_ERROR | L_OUT_UI, _T("Please use [HOWA] mobile module") ); 
				return FALSE; 
			} 
		} 
 
		ShowGSMModuleInfo (); 
		if ( !GetSMSCNO () ) 
		{ 
			Log ( L_ERROR | L_OUT_UI, _T("Get SMSC Failed") ); 
			if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 5*1000 ) == WAIT_OBJECT_0 ) 
				return FALSE; 
		} 
		else 
		{ 
			// 将手机中收到的短信全部读出来 
			ReadExistSMSInMobile (); 
			return TRUE; 
		} 
	} 
 
	CloseCOM (); 
	return FALSE; 
} 
 
// 
// 手机工作线程 
// 
BOOL CMobileControl::ThreadProc_Mobile() 
{ 
	// 等待线程执行通知 
	if ( m_EvtThreadCanRun && m_EvtThreadCanRun != INVALID_HANDLE_VALUE ) 
	{ 
		HANDLE EvtAry[] = { m_EvtThreadCanRun, m_hEvt_TerminateSys }; 
		if ( ::WaitForMultipleObjects ( COUNT(EvtAry), EvtAry, FALSE, INFINITE ) - WAIT_OBJECT_0 == 1 ) 
			return FALSE; 
	} 
 
	int nRet = 0; 
	for ( ;; ) 
	{ 
		if ( m_eMobileStatus != ENUM_ERROR_TYPE_MobileDisable ) 
		{ 
			switch ( m_eRunState ) 
			{ 
			case ENUM_RunState_Start: 
				{ 
					m_eRunState = ENUM_RunState_Init; 
					break; 
				} 
			case ENUM_RunState_Init: 
				{ 
					// 初始化手机模块 
					if ( InitMobileControl () ) 
					{ 
						m_eRunState = ENUM_RunState_Runing; 
					} 
					else 
					{ 
						if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, INITIALIZE_INTERFACE_INTERVAL*1000 ) == WAIT_OBJECT_0 ) 
							return TRUE; 
					} 
					break; 
				} 
			case ENUM_RunState_Runing: 
				{ 
					nRet = Runing (); 
					if ( nRet == 1 )	// 系统要终止 
						return TRUE; 
					break; 
				} 
			default: 
				return FALSE; 
			} 
		} 
		else if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 3000 ) == WAIT_OBJECT_0 ) 
		{ 
			return FALSE; 
		} 
	} 
 
	return TRUE; 
} 
 
// 
// 正在运行 
// return : ----------------------------------------------------- 
//		1	-	系统要终止 
//		0	-	运行出错,需要重新来过 
// 
int CMobileControl::Runing() 
{ 
	ASSERT ( m_hEvt_TerminateSys ); 
	HANDLE hEvtAry[] = { m_hEvt_TerminateSys, m_hEvt_SMSSendQueue }; 
	for ( ;; ) 
	{ 
		DWORD dwRet = ::WaitForMultipleObjects ( COUNT(hEvtAry), hEvtAry, FALSE, MOBILE_THREAD_SLEEP_TIME ); 
		if ( m_eMobileStatus != ENUM_ERROR_TYPE_MobileDisable ) 
		{ 
			switch ( dwRet - WAIT_OBJECT_0 ) 
			{ 
				// 系统要终止咯 
			case 0: 
				{ 
					return 1; 
				} 
				// 请求发送手机短信 
			case 1: 
				{ 
					SendSMSQueue (); 
					break; 
				} 
				// 定时时间 
			default: 
				{ 
					ReadNewSMS (); 
					break; 
				} 
			} 
		} 
 
		if ( m_eRunState != ENUM_RunState_Runing ) 
		{ 
			break; 
		} 
	} 
 
	return 0; 
} 
 
// 
// 发送短信,过长的短信处理:这个函数处理成多条短信; 
// 
ENUM_ERROR_TYPE CMobileControl::SendSMS ( 
		ENUM_MOBILESMSTYPE eMobileSMSType, 
		LPCTSTR lpszReceiverMobileNO,					// 接收者手机号 
		char* szSMSContent_Byte,						// 单字节短信内容 
		DWORD dwSMSSenderID_Sender/*=INVALID_SMSSenderID*/,	// 发送者的 PM 号码 
		FUNC_SendSMSEnd Proc_SendSMSEnd/*=NULL*/,		// 发送完成时通过该回调函数来通知请求者 
		WPARAM wParam/*=NULL*/, 
		LPARAM lParam/*=NULL*/ 
) 
{ 
#ifndef _DEBUG 
	ENUM_ERROR_TYPE eMobileStatus = GetMobileStatus(); 
	if ( eMobileStatus != ENUM_ERROR_TYPE_SUCCESS ) 
		return eMobileStatus; 
#endif 
 
	// 超过最大SIM卡发送短信条数 
	if ( m_pMobileParameter && m_pdwSentSMSCount && m_pMobileParameter->dwSMSCountPerSIM > 0 && 
		*m_pdwSentSMSCount >= m_pMobileParameter->dwSMSCountPerSIM ) 
	{ 
		return ENUM_ERROR_TYPE_OverSMSCountPerSIM; 
	} 
 
//	int nRetTemp = IsMobileNO ( lpszReceiverMobileNO ); 
//	CString csTemp = SimplifyMobileNO ( lpszReceiverMobileNO ); 
	CString csReceiverMobileNO = GET_SAFE_STRING( lpszReceiverMobileNO ); 
	BOOL bInternationalMobileNO = TRUE; 
	ENUM_ERROR_TYPE eErrorType = ENUM_ERROR_TYPE_SUCCESS; 
	if ( ENUM_ERROR_TYPE_SUCCESS != StandardMobileNO ( csReceiverMobileNO, &bInternationalMobileNO ) ) 
	{ 
		Log ( L_WARNING, _T("Standard MobileNO failed") ); 
	} 
 
	// 发送短信前做分条处理 
	ASSERT ( szSMSContent_Byte && strlen(szSMSContent_Byte) > 0 ); 
 
	CStringArray *pAryStr = PartMessengerOrSMSText ( GetCompatibleString(szSMSContent_Byte,FALSE), 0, TRUE, NULL, NULL ); 
	if ( !pAryStr ) return ENUM_ERROR_TYPE_PARAMETER; 
 
	for ( int i=0; iGetSize(); i++ ) 
	{ 
		CString csTextOne = pAryStr->GetAt ( i ); 
		csTextOne.TrimLeft(); csTextOne.TrimRight(); 
		ENUM_ERROR_TYPE eErrorTypeTemp = SendOnePartSMS ( eMobileSMSType, csReceiverMobileNO, bInternationalMobileNO,  
			CMultiByteString(csTextOne).GetBuffer(), dwSMSSenderID_Sender, Proc_SendSMSEnd, wParam, lParam ); 
		if ( eErrorTypeTemp != ENUM_ERROR_TYPE_SUCCESS ) 
		{ 
			eErrorType = eErrorTypeTemp; 
		} 
	} 
	pAryStr->RemoveAll(); 
	delete pAryStr; 
	return eErrorType; 
} 
 
ENUM_ERROR_TYPE CMobileControl::InfillSMParam (  
		OUT SM_PARAM &SmParam, 
		IN CString csReceiverMobileNO	// 接收者手机号 
	) 
{ 
	memset ( &SmParam, 0, sizeof(SM_PARAM) ); 
	if ( !m_nInitOK ) return ENUM_ERROR_TYPE_NoneMobile; 
	GetSMSCNO (); 
	if ( m_csSMSC.GetLength() <= MIN_MOBILENO_LENGTH ) 
	{ 
		Log ( L_ERROR, _T("SMSC Error, Cancel send SMS to [%s]"), csReceiverMobileNO  ); 
		return ENUM_ERROR_TYPE_ConfigNotRight; 
	} 
	CString csSMSC = m_csSMSC; 
	// 填充短消息结构 
	StandardMobileNOHead ( csSMSC ); 
	CMultiByteString ( csSMSC, STRING_IS_SOFTCODE, SmParam.SCA, sizeof(SmParam.SCA) ); 
	CMultiByteString ( csReceiverMobileNO, STRING_IS_SOFTCODE, SmParam.TPA, sizeof(SmParam.TPA) ); 
	SmParam.TP_PID = 0; 
 
	return ENUM_ERROR_TYPE_SUCCESS; 
} 
// 
// 发送短信,过长的短信,这个模块不会处理,请在调用前先处理 
// 
ENUM_ERROR_TYPE CMobileControl::SendOnePartSMS ( 
		ENUM_MOBILESMSTYPE eMobileSMSType, 
		LPCTSTR lpszReceiverMobileNO,					// 接收者手机号 
		BOOL bInternationalMobileNO, 
		char* szSMSContent_Byte,						// 单字节短信内容 
		DWORD dwSMSSenderID_Sender/*=INVALID_SMSSenderID*/,	// 发送者的 PM 号码 
		FUNC_SendSMSEnd Proc_SendSMSEnd/*=NULL*/,		// 发送完成时通过该回调函数来通知请求者 
		WPARAM wParam/*=NULL*/, 
		LPARAM lParam/*=NULL*/ 
) 
{ 
	if ( !szSMSContent_Byte || strlen(szSMSContent_Byte) <= 0 ) 
		return ENUM_ERROR_TYPE_INVALID_DATA; 
 
	// 完全相同(短信内容和接收者手机号相同)的短信在 SAME_SMS_INTERVAL_TIMELONG 秒内不允许发送 
	// 防止短信炸弹,也防止 UDP 通信时收到重发的短信包 
#ifndef _DEBUG 
	static CString csReceiverMobileNO_Last, csSMSContent_Last; 
	static time_t tTimeLast = 0; 
	if ( csReceiverMobileNO_Last == lpszReceiverMobileNO && 
		csSMSContent_Last == szSMSContent_Byte ) 
	{ 
		if ( difftime ( time(NULL), tTimeLast ) < SAME_SMS_INTERVAL_TIMELONG ) 
		{ 
			return ENUM_ERROR_TYPE_RepeatedRequest; 
		} 
	} 
	csReceiverMobileNO_Last = GET_SAFE_STRING ( lpszReceiverMobileNO ); 
	csSMSContent_Last = GET_SAFE_STRING ( szSMSContent_Byte ); 
	tTimeLast = time(NULL); 
#endif 
 
	// 队列是否满了? 
	m_CSFor_SMSSendQueue.Lock (); 
	if ( m_Ary_SMS_SendQueue.GetSize() > MAX_SMSQUEUE_NUM ) 
	{ 
		m_CSFor_SMSSendQueue.Unlock (); 
		return ENUM_ERROR_TYPE_BufferQueueFill; 
	} 
	m_CSFor_SMSSendQueue.Unlock (); 
 
	// 创建一个队列节点 
	t_SMS_SendQueue SMS_SendQueue; 
	memset ( &SMS_SendQueue, 0, sizeof(t_SMS_SendQueue) ); 
	SMS_SendQueue.dwSMSSenderID_Sender = dwSMSSenderID_Sender; 
	SMS_SendQueue.Proc_SendSMSEnd = Proc_SendSMSEnd; 
	SMS_SendQueue.wParam = wParam; 
	SMS_SendQueue.lParam = lParam; 
	SMS_SendQueue.eMobileSMSType = eMobileSMSType; 
	ENUM_ERROR_TYPE eErrorType = InfillSMParam ( SMS_SendQueue.sm, GET_SAFE_STRING(lpszReceiverMobileNO) ); 
	 
	strncpy ( SMS_SendQueue.sm.TP_UD_Byte, szSMSContent_Byte, COUNT(SMS_SendQueue.sm.TP_UD_Byte) ); 
	SMS_SendQueue.sm.bInternationalMobileNO = bInternationalMobileNO; 
 
	if ( eErrorType != ENUM_ERROR_TYPE_SUCCESS ) 
		return eErrorType; 
 
	// 做服务器运行时,将要发送的短信包添加到队列中 
	BOOL bRes = TRUE; 
	if ( m_bRunAsServer ) 
	{ 
		m_CSFor_SMSSendQueue.Lock (); 
		m_Ary_SMS_SendQueue.Add ( SMS_SendQueue ); 
		m_CSFor_SMSSendQueue.Unlock (); 
		 
		// 然后通知手机工作线程 
		ASSERT ( m_hEvt_SMSSendQueue && m_hEvt_SMSSendQueue != INVALID_HANDLE_VALUE ); 
		::SetEvent ( m_hEvt_SMSSendQueue ); 
	} 
	// 单机版时直接发送短信 
	else 
	{ 
		bRes = SendOneSMSQueue ( SMS_SendQueue ); 
	} 
 
	return ( bRes ? ENUM_ERROR_TYPE_SUCCESS : ENUM_ERROR_TYPE_SendSMSFailed ); 
} 
 
// 
// 发送短信队列里的短信 
// 
BOOL CMobileControl::SendSMSQueue () 
{ 
	ASSERT ( m_bRunAsServer ); 
	// 发送队列里的一条短消息 
	m_CSFor_SMSSendQueue.Lock (); 
	if ( m_Ary_SMS_SendQueue.GetSize() <= 0 ) 
	{ 
		m_CSFor_SMSSendQueue.Unlock (); 
		return TRUE; 
	} 
	t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 ); 
	t_SMS_SendQueue SMS_SendQueue; 
	memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) ); 
	m_Ary_SMS_SendQueue.RemoveAt ( 0 ); 
	m_CSFor_SMSSendQueue.Unlock (); 
	 
	BOOL bRes = SendOneSMSQueue ( SMS_SendQueue ); 
	 
	// 系统要退出了 
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 ) 
		return TRUE; 
	else 
	{ 
		m_CSFor_SMSSendQueue.Lock (); 
		// 还有短信需要发送 
		if ( m_Ary_SMS_SendQueue.GetSize() > 0 ) 
		{ 
			::SetEvent ( m_hEvt_SMSSendQueue ); 
		} 
		m_CSFor_SMSSendQueue.Unlock (); 
	} 
 
	return TRUE; 
} 
 
BOOL CMobileControl::AppTextToSMSContent ( SM_PARAM &sm, LPCTSTR lpszAppText, int &nFreeCharNum, BOOL bAddToHead ) 
{ 
	ASSERT ( lpszAppText ); 
	int nAppTextTotalCharNum = 0; 
	ParseSMSContentAttr ( CMultiByteString(lpszAppText).GetBuffer(), &nAppTextTotalCharNum ); 
	if ( nAppTextTotalCharNum < nFreeCharNum ) 
	{ 
		CString csTD_UD_Byte = GetCompatibleString(sm.TP_UD_Byte,FALSE); 
		if ( bAddToHead ) csTD_UD_Byte.Insert ( 0, lpszAppText ); 
		else csTD_UD_Byte += lpszAppText; 
		CMultiByteString ( csTD_UD_Byte, STRING_IS_SOFTCODE, sm.TP_UD_Byte, sizeof(sm.TP_UD_Byte) ); 
		nFreeCharNum -= nAppTextTotalCharNum; 
		return TRUE; 
	} 
 
	return FALSE; 
} 
 
 
BOOL CMobileControl::SendOneSMSQueue ( t_SMS_SendQueue &SMS_SendQueue ) 
{ 
	ASSERT ( m_nInitOK ); 
	ASSERT ( m_pMobileParameter ); 
	ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE ); 
	// 系统要退出了 
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 ) 
	{ 
		if ( SMS_SendQueue.Proc_SendSMSEnd ) 
		{ 
			SMS_SendQueue.Proc_SendSMSEnd ( ENUM_ERROR_TYPE_SysTerminate, 
				&SMS_SendQueue.sm, SMS_SendQueue.wParam, SMS_SendQueue.lParam ); 
		} 
		return FALSE; 
	} 
 
	int nTotalCharNum = 0, nFreeCharNum = 0, nTP_DCS = 0; 
	int nOneSMSByteCount = ParseSMSContentAttr ( SMS_SendQueue.sm.TP_UD_Byte, 
		&nTotalCharNum, &nFreeCharNum, &nTP_DCS ); 
	SMS_SendQueue.sm.TP_DCS = nTP_DCS; 
	ASSERT ( nFreeCharNum >= 0 ); 
	CString csSMSContent; 
 
	// 发送以“#howa!#”开头的短信,不附加短信头和尾 
	if ( strstr(SMS_SendQueue.sm.TP_UD_Byte,"#howa!#") == SMS_SendQueue.sm.TP_UD_Byte ) 
	{ 
		Log ( L_VERBOSE, _T("Not append SMS head and tail") ); 
		char TP_UD_Byte_Temp[ONE_SMS_TEXT_LENGTH+1] = {0}; 
		memset ( SMS_SendQueue.sm.TP_UD_Byte, 0, sizeof(SMS_SendQueue.sm.TP_UD_Byte) ); 
		strcpy ( TP_UD_Byte_Temp, &SMS_SendQueue.sm.TP_UD_Byte[7] ); 
		strcpy ( SMS_SendQueue.sm.TP_UD_Byte, TP_UD_Byte_Temp ); 
		csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE); 
	} 
	// 附加短信“#760815# [短信内容] Sent by "callgle" ” 
	else 
	{ 
		csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE); 
		if ( AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSTail, nFreeCharNum, FALSE ) ) 
		{ 
			AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSHead, nFreeCharNum, TRUE ); 
		} 
	} 
 
	BOOL bRet = FALSE; 
	CStringArray StrAry_MobileNO; 
	ASSERT ( m_pMobileParameter ); 
	bRet = SendOneSMSPkt ( &(SMS_SendQueue.sm) ); 
	StrAry_MobileNO.Add ( SimplifyMobileNO(GetCompatibleString(SMS_SendQueue.sm.TPA,FALSE)) ); 
 
	if ( SMS_SendQueue.Proc_SendSMSEnd ) 
	{ 
		SMS_SendQueue.Proc_SendSMSEnd ( bRet?ENUM_ERROR_TYPE_SUCCESS:ENUM_ERROR_TYPE_SendSMSFailed,  
			&(SMS_SendQueue.sm), SMS_SendQueue.wParam, SMS_SendQueue.lParam ); 
	} 
	if ( bRet && m_pdwSentSMSCount ) 
	{ 
		(*m_pdwSentSMSCount) ++; 
	} 
	// 将发送完的短信保存到数据库 
	for ( int i=0; iSaveSMSToHistoryRecord ( 
			SMS_SendQueue.dwSMSSenderID_Sender, 
			StrAry_MobileNO.GetAt(i), 
			SMS_SendQueue.eMobileSMSType, 
			ENUM_SMSOrientation_Send, 
			(bRet?ENUM_BOOL_TRUE:ENUM_BOOL_FALSE), 
			NULL, 
			csSMSContent );*/	//u 
	} 
 
	return bRet; 
} 
 
void CMobileControl::ClearSendQueue () 
{ 
	// 还有短信需要发送 
	while ( TRUE ) 
	{ 
		m_CSFor_SMSSendQueue.Lock (); 
		if ( m_Ary_SMS_SendQueue.GetSize() <= 0 ) 
		{ 
			m_CSFor_SMSSendQueue.Unlock (); 
			break; 
		} 
		 
		t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 ); 
		t_SMS_SendQueue SMS_SendQueue; 
		memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) ); 
		m_Ary_SMS_SendQueue.RemoveAt ( 0 ); 
		m_CSFor_SMSSendQueue.Unlock (); 
 
		SendOneSMSQueue ( SMS_SendQueue ); 
	} 
} 
 
BOOL CMobileControl::HandleRecvSMS(SM_PARAM *pSMRecv) 
{ 
	ASSERT ( pSMRecv ); 
	if ( GetMobileStatus() == ENUM_ERROR_TYPE_MobileDisable ) 
	{ 
		Log ( L_WARNING, _T("Discard recevied SMS [%s : %s], because Mobile mobule disable"), 
			GetCompatibleString(pSMRecv->TPA,FALSE), GetCompatibleString(pSMRecv->TP_UD_Byte,FALSE) ); 
		return FALSE; 
	} 
 
	if ( !CHwMobile::HandleRecvSMS ( pSMRecv ) ) 
		return FALSE; 
 
	CString csTemp = SimplifyMobileNO ( GetCompatibleString(pSMRecv->TPA,FALSE) ); 
	CMultiByteString ( csTemp, STRING_IS_SOFTCODE, pSMRecv->TPA, sizeof(pSMRecv->TPA) ); 
	ASSERT ( m_Proc_ReceivedSMS ); 
	return m_Proc_ReceivedSMS ( pSMRecv, m_wParam, m_lParam ); 
} 
 
// 
// 读最新收到的短信 
// 
BOOL CMobileControl::ReadNewSMS () 
{ 
	if ( !m_bRecvSMSEnable ) return TRUE; 
	if ( HANDLE_IS_VALID(m_hEvt_IsBusy) && 
		::WaitForSingleObject(m_hEvt_IsBusy,0)==WAIT_OBJECT_0 ) 
		return TRUE; 
 
	ASSERT ( m_nInitOK ); 
	// 系统要退出了 
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 ) 
		return TRUE; 
 
	ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE ); 
	if ( !QueryDeviceExist () ) 
	{ 
		return FALSE; 
	} 
 
	// 收短信通知 
	return gsmReadMessageContent ( "+CMT:" ); 
} 
 
// 
// 读取手机中已经存在的所有短信 
// 
BOOL CMobileControl::ReadExistSMSInMobile() 
{ 
	if ( !m_bRecvSMSEnable ) return TRUE; 
	if ( Write ( "AT+CMGL=4\r" ) < 1 ) 
		return FALSE; 
	if ( !WaitForDataToRead ( 2, 5*WAIT_DATA_TIMEOUT ) ) 
		return FALSE; 
	return gsmReadMessageContent ( "+CMGL:" ); 
} 
 
// 
// 读取手机所有电话本。 
// 注意:及时删除返回的指针 
// 
t_Ary_PhoneBook* CMobileControl::ReadPhoneBook() 
{ 
	t_Ary_PhoneBook *pAry_PhoneBook = new t_Ary_PhoneBook; 
	if ( !pAry_PhoneBook ) 
	{ 
		::AfxThrowMemoryException (); 
		return NULL; 
	} 
	pAry_PhoneBook->SetSize ( 0, 10*sizeof(t_PhoneBook) ); 
 
	if ( !gsmReadPhoneBook ( _T("SM"), pAry_PhoneBook ) ) 
		return pAry_PhoneBook; 
	if ( !gsmReadPhoneBook ( _T("ME"), pAry_PhoneBook ) ) 
		return pAry_PhoneBook; 
 
	return pAry_PhoneBook; 
} 
 
LPCTSTR CMobileControl::GetObjectName() 
{ 
	return _T("Mobile control module"); 
} 
 
// 
// 检测字符串 lpszStr 的是否以字符串 lpszHead1 或 lpszHead2 或 lpszHead3 开头 
// 
LPCTSTR CMobileControl::CheckHeadStr ( LPCTSTR lpszStr, LPCTSTR lpszHead1, LPCTSTR lpszHead2, LPCTSTR lpszHead3 ) 
{ 
	if ( !lpszStr || !lpszHead1 || lstrlen(lpszStr) <= 0 ) 
		return NULL; 
	if ( strstr_hw ( lpszStr, lpszHead1 ) == lpszStr ) 
		return lpszHead1; 
	if ( lpszHead2 && strstr_hw ( lpszStr, lpszHead2 ) == lpszStr ) 
		return lpszHead2; 
	if ( lpszHead3 && strstr_hw ( lpszStr, lpszHead3 ) == lpszStr ) 
		return lpszHead3; 
 
	return NULL; 
} 
 
// 
// 根据 Callgle 手机短信协议解析收到的短信 
// return : ----------------------------------------------------------- 
//		1											:	成功 
//		其他数据									:	发生错误 
//		-2											:	在本函数处理已经结束,不需要再处理 
// 注意: 
//		要及时删除 *ppStrAry_GroupName_Recver 和 *ppStrAry_SMSSenderID_Recver 指针 
// 
int CMobileControl::ParseSMSRecved (  
		IN LPCTSTR lpszSMSContent, 
		IN LPCTSTR lpszSenderMobileNO, 
		OUT CStringArray **ppStrAry_GroupName_Recver, 
		// 接收短信者名字或PM帐号,如果是输入控制命令时,这里存放了操作指令和控制命令 
		OUT CStringArray **ppStrAry_SMSSenderID_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize, 
		BOOL &bRequireEchoSMS, 
		LPCTSTR lpszSendTime 
	) 
{ 
	m_csPartString = _T(""); 
	bRequireEchoSMS = FALSE; 
	// 无效的短信内容,所以我也返回一个无效的消息类型 
	if ( !lpszSMSContent || lstrlen(lpszSMSContent) < 2 ) 
		return -1; 
 
	int nRet = -1; 
	ENUM_MOBILESMSTYPE eMobileSMSType = ENUM_MOBILESMSTYPE_Invalid; 
	CString csSMSContent = GET_SAFE_STRING ( lpszSMSContent ); 
	CString csSMSContent_Org = csSMSContent; 
	BOOL bMultiSplitSMS = FALSE; 
	// 以三个'?'开头的短信表示该短信是分多次发送过来的,需要将前面的三个'?'去掉 
	if ( csSMSContent.GetLength() > 3 && csSMSContent.GetAt(0)=='?' && 
		csSMSContent.GetAt(1)=='?' && csSMSContent.GetAt(2)=='?' ) 
	{ 
		bMultiSplitSMS = TRUE; 
		while ( !csSMSContent.IsEmpty() && csSMSContent.GetAt(0) == '?' ) 
			csSMSContent.Delete ( 0, 1 ); 
		csSMSContent_Org = csSMSContent; 
		if ( !m_csMultiSplitSMSHead.IsEmpty() && !CheckHeadStr ( csSMSContent, _T("#"), _T("#"), _T("…") ) ) 
			csSMSContent.Insert ( 0, m_csMultiSplitSMSHead ); 
	} 
	else 
	{ 
		m_csMultiSplitSMSHead = ""; 
	} 
	 
	// 非普通短信,而是一个控制命令,处理后的控制命令保存在 “tchSMSContent” 中 
	LPCTSTR pStr = CheckHeadStr ( csSMSContent, _T("%"), _T("%"), _T("") ); 
	if ( pStr ) 
	{ 
		m_csPartString = pStr; 
		nRet = HandleSMSCtrlCode ( csSMSContent, ppStrAry_SMSSenderID_Recver, tchSMSContent, nSMSContentSize ); 
		eMobileSMSType = ENUM_MOBILESMSTYPE_CtrlCmd; 
	} 
	// 普通的短信 
	else 
	{ 
		LPCTSTR pSMSContent = csSMSContent.GetBuffer(0); 
		// 是否需要回应 
		if ( pStr = CheckHeadStr ( pSMSContent, _T("#!"), _T("#!"), _T("…") ) ) 
		{ 
			pSMSContent += lstrlen ( pStr ); 
			bRequireEchoSMS = TRUE; 
		} 
 
		nRet = HandleSMSCommon ( pSMSContent, lpszSenderMobileNO, ppStrAry_GroupName_Recver,  
			ppStrAry_SMSSenderID_Recver, tchSMSContent, nSMSContentSize, eMobileSMSType ); 
	} 
 
	if ( bMultiSplitSMS ) 
	{ 
		CString csMultiSplitSMSHead = csSMSContent.Left ( csSMSContent_Org.GetLength() - (int)lstrlen(tchSMSContent) ); 
		if ( !csMultiSplitSMSHead.IsEmpty () ) 
		{ 
			m_csMultiSplitSMSHead = csMultiSplitSMSHead; 
		} 
	} 
 
	DWORD dwSMSSenderID = 0; 
	if ( ppStrAry_SMSSenderID_Recver && *ppStrAry_SMSSenderID_Recver && (*ppStrAry_SMSSenderID_Recver)->GetSize() > 0 ) 
	{ 
		dwSMSSenderID = atoi(CMultiByteString((*ppStrAry_SMSSenderID_Recver)->GetAt ( 0 )).GetBuffer()); 
	} 
 
	// 将收到的短信保存起来 
	/* 
	if ( m_pHwMysql_PMMsg ) 
	{ 
		m_pHwMysql_PMMsg->SaveSMSToHistoryRecord ( 
			dwSMSSenderID, 
			lpszSenderMobileNO, 
			eMobileSMSType, 
			ENUM_SMSOrientation_Recv, 
			ENUM_BOOL_TRUE, 
			lpszSendTime, 
			csSMSContent_Org ); 
	} 
	*/	//u 
 
	return nRet; 
} 
 
// 
// 处理普通短信 
// 
int CMobileControl::HandleSMSCommon (  
		IN LPCTSTR lpszSMSContent, 
		IN LPCTSTR lpszSenderMobileNO, 
		OUT CStringArray **ppStrAry_GroupName_Recver, 
		OUT CStringArray **ppStrAry_SMSSenderID_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize, 
		ENUM_MOBILESMSTYPE &eMobileSMSType 
	) 
{ 
	m_csPartString = _T(""); 
	eMobileSMSType = ENUM_MOBILESMSTYPE_Invalid; 
	 
	// 第一个字符是不是“#”或者“#”或者繁体的“#” 
	LPCTSTR pStr = CheckHeadStr ( lpszSMSContent, _T("#"), _T("#"), _T("…") ); 
	if	( pStr ) 
	{ 
		m_csPartString = pStr; 
		pStr = CheckHeadStr ( lpszSMSContent+m_csPartString.GetLength(), _T("#"), _T("#"), _T("…") ); 
		// 连续两个“#”表示群发短信(发送给多人) 
		if ( pStr ) 
		{ 
			m_csPartString = pStr; 
			eMobileSMSType = ENUM_MOBILESMSTYPE_ClusterAD; 
			return HandleSMSMultiRecver ( lpszSMSContent, lpszSenderMobileNO, ppStrAry_GroupName_Recver,  
				tchSMSContent, nSMSContentSize ); 
		} 
		else 
		{ 
			CString csTemp = lpszSMSContent+m_csPartString.GetLength(); 
			csTemp = csTemp.Left ( 4 ); 
			// 寻求帮助 
			if	( 
					( csTemp.GetLength() > 0 ) 
					&& 
					( 
						CheckHeadStr ( csTemp, _T("?"), _T("?"), _T("") ) 
						|| 
						csTemp.CompareNoCase ( _T("help") ) ==0 
					) 
				) 
			{ 
				eMobileSMSType = ENUM_MOBILESMSTYPE_Personal; 
				SendSMS ( ENUM_MOBILESMSTYPE_SysAutoSent, lpszSenderMobileNO, CALLGLE_HELP_INFO1 ); 
				SendSMS ( ENUM_MOBILESMSTYPE_SysAutoSent, lpszSenderMobileNO, CALLGLE_HELP_INFO2 ); 
				return -2; 
			} 
		} 
	} 
	 
	// 个人短信(私聊) 
	eMobileSMSType = ENUM_MOBILESMSTYPE_Personal; 
	return HandleSMSSingleRecver ( lpszSMSContent, lpszSenderMobileNO, ppStrAry_SMSSenderID_Recver, 
		tchSMSContent, nSMSContentSize ); 
} 
 
// 
// 把处理到只剩下“接收者(群组编号或PM帐号或用户名)”和“短信本身”的短信交给这个函数处理 
// 
BOOL CMobileControl::ParseRecverAndContent ( 
		TCHAR *pHandlePos, 
		OUT CStringArray **ppStrAry_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize 
	) 
{ 
	ASSERT ( pHandlePos ); 
	if ( *pHandlePos == _T('\0') ) return FALSE; 
	pHandlePos = strstr_hw ( pHandlePos, m_csPartString ); 
	if ( !pHandlePos ) return FALSE; 
	pHandlePos += m_csPartString.GetLength();	// 跳过 “#” 
	CString csHandleRemain = pHandlePos; 
	CString csSMSContent = csHandleRemain; 
	int nFindPos = csHandleRemain.Find ( m_csPartString, 0 ); 
	if ( nFindPos >= 0 ) 
	{ 
		CString csRecver = csHandleRemain.Left ( nFindPos ); 
		csSMSContent = csHandleRemain.Mid ( nFindPos+m_csPartString.GetLength() ); 
		ASSERT ( ppStrAry_Recver ); 
		*ppStrAry_Recver = new CStringArray; 
		if ( !(*ppStrAry_Recver) ) 
			return FALSE; 
		CStringArray StrAry; 
		PartStringAndAddToStrAry ( csRecver.GetBuffer(0), StrAry, GROUP_NAME_ILLEGAL ); 
		StrAry.RemoveAll (); 
	} 
 
	// 获取短信内容本身 
	lstrcpyn ( tchSMSContent, csSMSContent, nSMSContentSize ); 
	tchSMSContent[nSMSContentSize-1] = _T('\0'); 
 
	return TRUE; 
} 
 
// 
// 处理群发短信 
// 
int CMobileControl::HandleSMSMultiRecver ( 
		IN LPCTSTR lpszSMSContent, 
		IN LPCTSTR lpszSenderMobileNO, 
		OUT CStringArray **ppStrAry_GroupName_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize 
	) 
{ 
	ASSERT ( lpszSMSContent && lstrlen(lpszSMSContent) > 0 ); 
	ASSERT ( nSMSContentSize > 0 ); 
	if ( !m_pMobileParameter ) return FALSE; 
	ASSERT_ADDRESS ( tchSMSContent, nSMSContentSize ); 
	TCHAR* pHandlePos = (TCHAR*)lpszSMSContent; 
	int nSMSContentLen = lstrlen(lpszSMSContent); 
	int nRet = -1; 
	// 跳过前面的俩“#”号 
	pHandlePos += 2*m_csPartString.GetLength(); 
	// 获取接收群组编号 
	if ( !ParseRecverAndContent ( pHandlePos, ppStrAry_GroupName_Recver, tchSMSContent, nSMSContentSize ) ) 
		return -1; 
 
	return 1; 
} 
 
// 
// 处理个人短信 
// 
int CMobileControl::HandleSMSSingleRecver ( 
		IN LPCTSTR lpszSMSContent, 
		IN LPCTSTR lpszSenderMobileNO, 
		OUT CStringArray **ppStrAry_SMSSenderID_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize 
	) 
{ 
	ASSERT ( lpszSMSContent && lstrlen(lpszSMSContent) > 0 ); 
	ASSERT_ADDRESS ( tchSMSContent, nSMSContentSize ); 
	ASSERT ( m_pMobileParameter ); 
	// 发送给指定的用户 
	LPCTSTR pStr = CheckHeadStr ( lpszSMSContent, _T("#"), _T("#"), _T("…") ); 
	if ( pStr ) 
	{ 
		m_csPartString = pStr; 
		// 获取接收者PM帐号 
		ParseRecverAndContent ( (TCHAR*)lpszSMSContent, ppStrAry_SMSSenderID_Recver, tchSMSContent, nSMSContentSize ); 
	} 
 
	// 无 callgle 短信脚本,发送给短信服务者 
	if ( !ppStrAry_SMSSenderID_Recver || !(*ppStrAry_SMSSenderID_Recver) || (*ppStrAry_SMSSenderID_Recver)->GetSize() < 1 ) 
	{ 
		lstrcpyn ( tchSMSContent, lpszSMSContent, nSMSContentSize ); 
		tchSMSContent [nSMSContentSize-1] = _T('\0'); 
		if ( !(*ppStrAry_SMSSenderID_Recver) ) 
		{ 
			(*ppStrAry_SMSSenderID_Recver) = new CStringArray; 
		} 
		if ( *ppStrAry_SMSSenderID_Recver && (*ppStrAry_SMSSenderID_Recver)->GetSize() < 1 ) 
		{ 
			//u 
		} 
	} 
 
	return 1; 
} 
 
// 
// 处理控制代码的短信 
// 
int CMobileControl::HandleSMSCtrlCode (  
		IN LPCTSTR lpszSMSContent, 
		OUT CStringArray **ppStrAry_SMSSenderID_Recver, 
		OUT TCHAR *tchSMSContent, 
		int nSMSContentSize 
	) 
{ 
	ASSERT ( lpszSMSContent && lstrlen(lpszSMSContent) > 0 ); 
	ASSERT_ADDRESS ( tchSMSContent, nSMSContentSize ); 
	LPCTSTR pStart = lpszSMSContent + m_csPartString.GetLength(); 
	if ( pStart[0] == _T('\0') ) 
		return -1; 
	LPCTSTR pEnd = strstr_hw ( pStart, m_csPartString ); 
	if ( !pEnd ) pEnd = pStart + lstrlen(pStart); 
	int nCtrlCodeLen = (int)((ULONGLONG)pEnd - (ULONGLONG)pStart); 
	if ( nCtrlCodeLen < 1 ) return -1; 
	nCtrlCodeLen = MIN ( nCtrlCodeLen, nSMSContentSize ); 
	memcpy ( tchSMSContent, pStart, nCtrlCodeLen ); 
	tchSMSContent[nCtrlCodeLen] = _T('\0'); 
 
	ASSERT ( ppStrAry_SMSSenderID_Recver ); 
	*ppStrAry_SMSSenderID_Recver = new CStringArray; 
	if ( !(*ppStrAry_SMSSenderID_Recver) ) 
		return -1; 
	if ( PartDigitOrSpecifyCharAndAddToStrAry ( tchSMSContent, **ppStrAry_SMSSenderID_Recver, _T("*#") ) < 2 ) 
		return -1; 
 
	return 1; 
} 
 
int CMobileControl::HandleCOMRW(int nRet) 
{ 
	if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 ) 
		return -3; 
 
	// COM got way 
	if	( nRet < 0 ) 
	{ 
		m_eRunState = ENUM_RunState_Init; 
		ChangeMobileStatus ( ENUM_ERROR_TYPE_NoneMobile ); 
	} 
	return CHwMobile::HandleCOMRW ( nRet ); 
} 
 
LRESULT CMobileControl::ChangeMobileStatus( ENUM_ERROR_TYPE eMobileStatus_New ) 
{ 
	ENUM_ERROR_TYPE eMobileStatus_Old = GetMobileStatus(); 
	 
	if ( eMobileStatus_Old == eMobileStatus_New ) 
		return FALSE; 
 
	// 新状态不是禁用也不是启用时,应该属于手机实际的状态了 
	if ( eMobileStatus_New != ENUM_ERROR_TYPE_MobileDisable && eMobileStatus_New != ENUM_ERROR_TYPE_MobileEnable ) 
	{ 
		m_eMobileStatus_Real = eMobileStatus_New; 
	} 
 
	// 模块被禁用了,只有收到启用码才处理后面的动作,否则直接返回。 
	if ( eMobileStatus_Old == ENUM_ERROR_TYPE_MobileDisable && eMobileStatus_New != ENUM_ERROR_TYPE_MobileEnable ) 
	{ 
		return FALSE; 
	} 
 
	// 模块被启用了,应该将真实的状态当作当前的手机状态 
	if ( eMobileStatus_New == ENUM_ERROR_TYPE_MobileEnable ) 
	{ 
		eMobileStatus_New = m_eMobileStatus_Real; 
	} 
	 
	m_CSFor_MobileStatus.Lock (); 
	m_eMobileStatus = eMobileStatus_New; 
	m_CSFor_MobileStatus.Unlock (); 
 
	LRESULT lRes = TRUE; 
	if ( m_Proc_HandleMobileStatusChange ) 
	{ 
		lRes = m_Proc_HandleMobileStatusChange ( eMobileStatus_Old, eMobileStatus_New ); 
	} 
	else 
	{ 
		Log ( L_VERBOSE, _T("Mobile status change to [%s]"), g_pErrorTypeDesc[eMobileStatus_New] ); 
	} 
	return lRes; 
} 
 
ENUM_ERROR_TYPE CMobileControl::GetMobileStatus () 
{ 
	ENUM_ERROR_TYPE eMobileStatus; 
	m_CSFor_MobileStatus.Lock (); 
	eMobileStatus = m_eMobileStatus; 
	m_CSFor_MobileStatus.Unlock (); 
	return eMobileStatus; 
} 
 
BOOL CMobileControl::SMSEnable(BOOL bEnable) 
{ 
	// 启用手机短信 
	if ( bEnable ) 
	{ 
		ChangeMobileStatus ( ENUM_ERROR_TYPE_MobileEnable ); 
		m_InitializeInterfaceInterval = INITIALIZE_INTERFACE_INTERVAL; 
	} 
	// 禁用手机短信 
	else 
	{ 
		Log ( L_NORMAL | L_OUT_UI, _T("Disable ") ); 
		ChangeMobileStatus ( ENUM_ERROR_TYPE_MobileDisable ); 
	} 
 
	return TRUE; 
} 
 
BOOL CMobileControl::GetLocalCodeHead ( CString &csLocalCountryCode, CString &csLocalAreaCode ) 
{ 
	if ( m_pMobileParameter ) 
	{ 
		csLocalCountryCode = m_pMobileParameter->szLocalCountryCode; 
		csLocalAreaCode = m_pMobileParameter->szLocalAreaCode; 
		csLocalCountryCode.Replace ( _T("+"), _T("00") ); 
		csLocalAreaCode.Replace ( _T("+"), _T("00") ); 
		if ( !csLocalCountryCode.IsEmpty() && !csLocalAreaCode.IsEmpty() ) 
			return TRUE; 
	} 
 
	return FALSE; 
} 
 
// 
// 输入的号码是否为手机号码,如果是,那返回他的字头出现在数组 m_Ary_MobileNOHead 中的位置,如果 
// 不是就返回-1;不管国内号码还是国外号码,本函数都会处理它 
// 
// return : ---------------------------------------------------------------------------------------------- 
//		>=0		-	是手机号码,字头在数组中的位置 
//		-1		-	不是手机号码 
// 
int CMobileControl::IsMobileNO ( LPCTSTR lpszPhoneNO, OUT t_MobileNOHead *pMobileNOHead/*=NULL*/, OUT CString *pShortMobileNO/*=NULL*/ ) 
{ 
	if ( !lpszPhoneNO ) return -1; 
	CString csPhoneNO = lpszPhoneNO; 
	csPhoneNO.Replace ( _T("+"), _T("00") ); 
	if ( csPhoneNO.GetLength() < 1 ) return -1; 
	CString csLocalCountryCode, csLocalAreaCode; 
	if ( !GetLocalCodeHead ( csLocalCountryCode, csLocalAreaCode ) ) 
		return -1; 
 
	// 分析国家代码和区号 
	CString csCountryCode, csAreaCode; 
	BOOL bHaveCountryCode = ( csPhoneNO.Find ( _T("00"), 0 ) == 0 ); 
	int nRetLen = FindFromMobileNOHeadAry ( csPhoneNO, csCountryCode, csAreaCode ); 
	CString csShortMobileNO; 
	if ( nRetLen > 0 ) csShortMobileNO = csPhoneNO.Mid ( nRetLen ); 
	else csShortMobileNO = csPhoneNO; 
	int nRet = -1; 
 
	for ( int i=0; i 0 && 
						csCountryCode == MobileNOHead.szCountryCode 
					) 
					|| 
					// 电话号码中没有国家代码,且 MobileNOHead 中也没有国家代码或者就是本国的国家代码 
					( 
						!bHaveCountryCode && csCountryCode.GetLength() == 0 && 
						( lstrlen(MobileNOHead.szCountryCode) == 0 || csLocalCountryCode == MobileNOHead.szCountryCode ) 
					) 
				) 
				&& 
				// 区号 
				( 
					// 电话号码中有区号,且和 MobileNOHead 中的区号相等 
					( 
						csAreaCode.GetLength() > 0 && 
						( csAreaCode == MobileNOHead.szAreaCode ) 
					) 
					|| 
					// 电话号码中没有区号,且 MobileNOHead 中也没有区号或者就是本地的区号 
					( 
						csAreaCode.GetLength() == 0 && 
						( lstrlen(MobileNOHead.szAreaCode) == 0 || csLocalAreaCode == MobileNOHead.szAreaCode ) 
					) 
				) 
				&& 
				// 手机字头 
				( 
					CompareNOHead ( csShortMobileNO, MobileNOHead.szMobileNoHead, (lstrlen(MobileNOHead.szAreaCode)==0 || 
						SWITCH_IS_FLAG ( SMS_MobileNO_Format_AreaCode, MobileNOHead.dwMobileNOFormat )), TRUE ) > 0 
				) 
			) 
		{ 
			if ( pMobileNOHead ) memcpy ( pMobileNOHead, &MobileNOHead, sizeof(t_MobileNOHead) ); 
			nRet = i; 
			StandardShortMobileNO ( csShortMobileNO, MobileNOHead.szMobileNoHead ); 
			break; 
		} 
	} 
 
	if ( pShortMobileNO ) *pShortMobileNO = csShortMobileNO; 
	return nRet; 
} 
 
// 
// 从 m_Ary_MobileNOHead 字头列表中找,手机号码 lpszPhoneNO 的国家代码或区号 
// return : ---------------------------------------------------------------------------------- 
//		> 0		-	号码头(国家代码+区号)的长度 
//		<= 0	-	没有号码头 
// 
int CMobileControl::FindFromMobileNOHeadAry ( 
		LPCTSTR lpszPhoneNO, 
		CString &csCountryCode, 
		CString &csAreaCode 
	) 
{ 
	if ( !lpszPhoneNO ) return -1; 
	int nMobileNOLen = (int)lstrlen(lpszPhoneNO); 
	if ( nMobileNOLen < 1 ) return -1; 
	int nCountryCodeLen = 0, nAreaCodeLen = 0, nPrepositiveNOLen = 0; 
	int nCountryCodeLen_Ret = 0, nAreaCodeLen_Ret = 0, nPrepositiveNOLen_Ret = 0; 
	for ( int i=0; i 0 && nMobileNOLen > nPrepositiveNOLen_Ret && strstr_hw(p,MobileNOHead.szPrepositiveNO) == p ) 
		{ 
			nPrepositiveNOLen = nPrepositiveNOLen_Ret; 
			p += nPrepositiveNOLen; 
		} 
 
		// 找国家代码 
		if ( lstrlen(MobileNOHead.szCountryCode) > 0 ) 
		{ 
			nCountryCodeLen_Ret = CompareNOHead ( p, MobileNOHead.szCountryCode, TRUE, TRUE ); 
			if ( nCountryCodeLen_Ret > 0 && lstrlen(p+nCountryCodeLen_Ret)>=MIN_MOBILENO_LENGTH ) 
			{ 
				nCountryCodeLen = nCountryCodeLen_Ret; 
 
				csCountryCode = MobileNOHead.szCountryCode; 
				p += nCountryCodeLen_Ret; 
			} 
		} 
 
		// 找区号 
		if ( lstrlen(MobileNOHead.szAreaCode) > 0 ) 
		{ 
			nAreaCodeLen_Ret = CompareNOHead ( p, MobileNOHead.szAreaCode, nCountryCodeLen_Ret>0, nCountryCodeLen_Ret>0 ); 
			if ( nAreaCodeLen_Ret > 0 && lstrlen(p+nAreaCodeLen_Ret)>=MIN_MOBILENO_LENGTH  ) 
			{ 
				nAreaCodeLen = nAreaCodeLen_Ret; 
				nCountryCodeLen = nCountryCodeLen_Ret; 
 
				csCountryCode = MobileNOHead.szCountryCode; 
				csAreaCode = MobileNOHead.szAreaCode; 
				p += nAreaCodeLen_Ret; 
				break; 
			} 
		} 
	} 
 
	return ( nPrepositiveNOLen + nCountryCodeLen + nAreaCodeLen ); 
} 
 
// 
// 比较俩号码,是否 lpszPhoneNO 是以 lpszPhoneNOHead 做字头的号码,并自动跳过号码前的“0” 
// return : ----------------------------------------------------------------------------------------- 
//		> 0		-	TRUE, lpszPhoneNO 中多少个字符为字头 
//		= 0		-	FALSE 
// 
int CMobileControl::CompareNOHead(LPCTSTR lpszPhoneNO, LPCTSTR lpszPhoneNOHead, BOOL bIgnoreHeadZero_PhoneNO, BOOL bIgnoreHeadZero_PhoneNOHead) 
{ 
	if ( !lpszPhoneNO || lstrlen(lpszPhoneNO) < 1 ) return 0; 
	if ( !lpszPhoneNOHead || lstrlen(lpszPhoneNOHead) < 1 ) return 0; 
	if ( strstr_hw ( lpszPhoneNO, lpszPhoneNOHead ) == lpszPhoneNO ) 
		return (int)lstrlen(lpszPhoneNOHead); 
 
	// 台湾的手机号码以“0”开头,来电显示有时又收不到这个“0”,所有手机字头跳过这个“0”再来比对 
	// 大陆手机是以“13”开头,但长途漫游之后的来电显示会变成“013”,所以应该跳过来电显示的第一个“0”再比对 
	CString csPhoneNO = lpszPhoneNO; 
	CString csPhoneNOHead = lpszPhoneNOHead; 
	int nPhoneNODeleZeroNum = 0; 
	if ( bIgnoreHeadZero_PhoneNO ) 
	{ 
		while ( csPhoneNO.GetLength() > 0 && csPhoneNO.GetAt (0) == '0' ) 
		{ 
			csPhoneNO.Delete ( 0 ); 
			nPhoneNODeleZeroNum ++; 
		} 
	} 
 
	if ( bIgnoreHeadZero_PhoneNOHead ) 
	{ 
		while ( csPhoneNOHead.GetLength() > 0 && csPhoneNOHead.GetAt (0) == '0' ) 
			csPhoneNOHead.Delete ( 0 ); 
	} 
 
	if ( csPhoneNO.Find ( csPhoneNOHead, 0 ) == 0 ) 
		return ( csPhoneNOHead.GetLength() + nPhoneNODeleZeroNum ); 
 
	return 0; 
} 
 
// 
// 配置 国家代码、手机字头等参数 
// 
void CMobileControl::ConfigParameter ( t_Ary_MobileNOHead *pAry_MobileNOHead ) 
{ 
	if ( pAry_MobileNOHead ) 
	{ 
		m_Ary_MobileNOHead.Append ( *pAry_MobileNOHead ); 
	} 
} 
 
// 
// 获取精简的手机号码 ( 不带任何国家代码的手机号码 ) 
// 
CString CMobileControl::SimplifyMobileNO ( LPCTSTR lpszMobileNO ) 
{ 
	CString csMobileNO = GET_SAFE_STRING ( lpszMobileNO ); 
	CString csSimplifyMobileNO; 
	if ( StandardMobileNO ( csMobileNO, NULL, &csSimplifyMobileNO ) != ENUM_ERROR_TYPE_SUCCESS ) 
		csSimplifyMobileNO = GET_SAFE_STRING ( lpszMobileNO ); 
 
	return csSimplifyMobileNO; 
} 
 
// 
// 标准化干净的手机号码 
// 
void CMobileControl::StandardShortMobileNO ( IN OUT CString &csShortMobileNO, IN LPCTSTR lpszMobileNOHead ) 
{ 
	CString csMobileNOHead = GET_SAFE_STRING(lpszMobileNOHead); 
	// 手机字头从号码的第二位开始出现,且号码是以‘0’开头,那么这个多余的‘0’应该去掉 
	if ( csMobileNOHead.GetLength() > 0 && csShortMobileNO.Find ( csMobileNOHead, 0 ) == 1 && 
		csShortMobileNO.GetAt(0) == '0' ) 
	{ 
		csShortMobileNO.Delete ( 0 ); 
	} 
	// 有些国家的手机字头以‘0’开头(如:台湾是“09”开头),有时来电显示会丢掉前面的‘0’,所以应该把丢掉的‘0’补上 
	if ( csMobileNOHead.GetLength() >= 2 && csMobileNOHead.GetAt(0) == '0' && csShortMobileNO.GetAt(0) != '0' && 
		csShortMobileNO.GetAt(0) == csMobileNOHead.GetAt(1) ) 
	{ 
		csShortMobileNO.Insert ( 0, '0' ); 
	} 
} 
 
// 
// 标准化手机号码,国外的号码只处理字头,国内的号码会处理国家代码区号等,而且也会处理前置号码 
// 
ENUM_ERROR_TYPE CMobileControl::StandardMobileNO ( CString &csMobileNO, BOOL *pbInternationalMobileNO/*=NULL*/, CString *pSimplifyMobileNO/*=NULL*/ ) 
{ 
	if ( pbInternationalMobileNO ) *pbInternationalMobileNO = FALSE; 
	if ( pSimplifyMobileNO ) *pSimplifyMobileNO = ""; 
 
	CString csMobileNORes, csShortPhoneNO, csLocalCountryCode, csLocalAreaCode, csPrepositiveNO, csMobileNOHead; 
	t_MobileNOHead MobileNOHead = {0}; 
 
	// 取得合法的电话号码数字 
	CString csHandleMobileNO = csMobileNO; 
	GetRightPhoneNOString ( csHandleMobileNO.GetBuffer(0) ); 
	csHandleMobileNO.ReleaseBuffer (); 
	if ( csHandleMobileNO.GetLength() < 1 ) 
		return ENUM_ERROR_TYPE_INVALID_DATA; 
	csHandleMobileNO.Replace ( _T("+"), _T("00") ); 
	 
	if ( !GetLocalCodeHead ( csLocalCountryCode, csLocalAreaCode ) ) 
		return ENUM_ERROR_TYPE_ConfigNotRight; 
	 
	// 手机号码为国外的号码,只需对号码进行简单地处理,且不对手机字头进行判断 
	if ( csHandleMobileNO.GetAt(0)=='0' && csHandleMobileNO.GetAt(1)=='0' && 
		csHandleMobileNO.Find ( csLocalCountryCode, 0 ) != 0 ) 
	{ 
		if ( pbInternationalMobileNO ) *pbInternationalMobileNO = TRUE; 
		if ( pSimplifyMobileNO ) *pSimplifyMobileNO = csHandleMobileNO; 
		StandardMobileNOHead ( csMobileNO ); 
		return ENUM_ERROR_TYPE_SUCCESS; 
	} 
	 
	// 根据字头来判断该号码是否为手机号码 
	if ( IsMobileNO ( csHandleMobileNO, &MobileNOHead, &csShortPhoneNO ) < 0 ) 
		return ENUM_ERROR_TYPE_IsNotMobileNO; 
	csMobileNOHead = MobileNOHead.szMobileNoHead; 
	StandardShortMobileNO ( csShortPhoneNO, csMobileNOHead ); 
	csPrepositiveNO = MobileNOHead.szPrepositiveNO; 
 
	// 按照手机号码格式来组建一个标准的手机号码 
	CString csCountryCode = MobileNOHead.szCountryCode; 
	CString csAreaCode = MobileNOHead.szAreaCode; 
	if ( csPrepositiveNO.GetLength() > 0 ) 
	{ 
		csMobileNORes += csPrepositiveNO;		// 前置号码 
	} 
	if ( MobileNOHead.dwMobileNOFormat & SMS_MobileNO_Format_CountryCode ) 
	{ 
		if ( csCountryCode.GetLength() < 1 ) csCountryCode = csLocalCountryCode; 
		StandardMobileNOHead ( csCountryCode ); 
		csMobileNORes += csCountryCode;			// 添加国家代码 
		while ( csAreaCode.GetLength() > 0 && csAreaCode.GetAt(0) == '0' ) 
			csAreaCode.Delete ( 0 );			// 由于要添加国家代码,所以区号前面的“0”应该去掉 
		if ( pbInternationalMobileNO ) *pbInternationalMobileNO = TRUE; 
		if ( pSimplifyMobileNO && csLocalCountryCode != MobileNOHead.szCountryCode ) 
			*pSimplifyMobileNO += MobileNOHead.szCountryCode; 
	} 
	if ( MobileNOHead.dwMobileNOFormat & SMS_MobileNO_Format_AreaCode ) 
	{ 
		if ( csAreaCode.GetLength() < 1 ) 
		{ 
			csAreaCode = csLocalAreaCode; 
			if ( csMobileNORes.GetLength() > 0 ) 
			{ 
				while ( csAreaCode.GetLength() > 0 && csAreaCode.GetAt(0) == '0' ) 
					csAreaCode.Delete ( 0 ); 
			} 
		} 
		csMobileNORes += csAreaCode;			// 添加区号 
		if ( pSimplifyMobileNO && (pSimplifyMobileNO->GetLength() > 0 || csLocalAreaCode != MobileNOHead.szAreaCode) ) 
			*pSimplifyMobileNO += MobileNOHead.szAreaCode; 
	} 
 
	CString csNoneZeroPhoneNO = csShortPhoneNO; 
	while ( csNoneZeroPhoneNO.GetLength() > 0 && csNoneZeroPhoneNO.GetAt(0) == '0' ) 
		csNoneZeroPhoneNO.Delete ( 0 ); 
	if ( csMobileNORes.GetLength() > 0 ) 
		csMobileNORes += csNoneZeroPhoneNO; 
	else 
		csMobileNORes = csShortPhoneNO; 
 
	if ( pSimplifyMobileNO ) 
	{ 
		if ( pSimplifyMobileNO->GetLength() > 0 ) 
			*pSimplifyMobileNO += csNoneZeroPhoneNO; 
		else 
			*pSimplifyMobileNO = csShortPhoneNO; 
	} 
 
 
	TRACE ( _T("标准化手机号码 ( %s ) 为 ( %s )\n"), csMobileNO, csMobileNORes ); 
	csMobileNO = csMobileNORes; 
	return ENUM_ERROR_TYPE_SUCCESS; 
} 
 
// 
// 标准化手机号码头,把 '+'、"00" 去掉 
// 
ENUM_ERROR_TYPE CMobileControl::StandardMobileNOHead ( CString &csMobileNOHead ) 
{ 
	if ( csMobileNOHead.GetLength() < 3 ) 
		return ENUM_ERROR_TYPE_IsNotMobileNO; 
 
	csMobileNOHead.Remove ( _T('+') ); 
	if ( csMobileNOHead.Find ( _T("00"), 0 ) == 0 ) 
	{ 
		csMobileNOHead.Delete ( 0, 2 ); 
	} 
	if ( csMobileNOHead.GetLength() < 1 ) 
		return ENUM_ERROR_TYPE_IsNotMobileNO; 
 
	return ENUM_ERROR_TYPE_SUCCESS; 
} 
 
void CMobileControl::GetRegisterPhoneBookInfo ( CStringArray &StrAry_PhoneNO, CStringArray &StrAry_Name ) 
{ 
	StrAry_PhoneNO.Add ( _T("111") ); StrAry_Name.Add ( _T("HOWASZ") ); 
	StrAry_PhoneNO.Add ( _T("222") ); StrAry_Name.Add ( _T("HOWAFAX") ); 
	StrAry_PhoneNO.Add ( _T("333") ); StrAry_Name.Add ( _T("CHRYS") ); 
} 
 
// 
// 短信模块是否已注册过了,查看本机电话本里是否含有以下几条电话纪录: 
// 
BOOL CMobileControl::GSMModuleIsRegistered() 
{ 
	t_Ary_PhoneBook Ary_PhoneBook; 
	CString csPhoneBook = _T("ME"); 
	Ary_PhoneBook.SetSize ( 0, 10*sizeof(t_PhoneBook) ); 
	if ( !gsmReadPhoneBook ( csPhoneBook, &Ary_PhoneBook ) ) 
	{ 
		Log ( L_WARNING, _T("Read phone book [%s] failed"), csPhoneBook ); 
		return FALSE; 
	} 
 
	CStringArray StrAry_PhoneNO, StrAry_Name; 
	GetRegisterPhoneBookInfo ( StrAry_PhoneNO, StrAry_Name ); 
	CStringArray StrAry_PhoneNO_ME, StrAry_Name_ME; 
	ASSERT ( StrAry_PhoneNO.GetSize() == StrAry_Name.GetSize() ); 
	for ( int i=0; i 1 && csPhoneNO.GetLength () > 1 ); 
		if ( !InsertPhoneBook ( csName, csPhoneNO, NULL ) ) 
		{ 
			return 0; 
		} 
	} 
 
	return 1; 
} 
 
// 
// 注册短信模块,给本机电话本里添加以下几条电话纪录: 
// return : ---------------------------------------------------- 
//		0	-	失败 
//		1	-	成功 
//		2	-	还没注册 
// 
int CMobileControl::UnregisterGSMModule() 
{ 
	CString csPhoneBook = _T("ME"); 
	if ( !gsmSelectPhoneBook ( csPhoneBook ) ) 
		return 0; 
 
	CStringArray StrAry_PhoneNO, StrAry_Name; 
	GetRegisterPhoneBookInfo ( StrAry_PhoneNO, StrAry_Name ); 
	ASSERT ( StrAry_PhoneNO.GetSize() == StrAry_Name.GetSize() ); 
	for ( int i=1; i<=3*StrAry_PhoneNO.GetSize(); i++ ) 
	{ 
		if ( !gsmDeleteOneRecordFromPhoneBook ( i ) ) 
		{ 
			return 0; 
		} 
	} 
 
	return 1; 
} 
 
#endif