www.pudn.com > xltsm.rar > SendSM.cpp


#include "StdAfx.h" 
#include "smei.h" 
#include "smset.h" 
#include "SendSM.h" 
 
extern char szIcpNbr[]; 
extern char szCorpId[]; 
 
typedef struct tagSUBMITINFO { 
	long lRelatedMO;			//对应的MO标识,为0表示由SP发起的 
	LPCSTR lpcszFromMobile;		//发送方,可以是服务号码+用户定义标识,最长不超过19位 
	LPCSTR lpcszToMobile;		//接受该短消息的手机号 
	LPCSTR lpcszServiceType;	//业务代码,由sp定义 
	int nFeeType;				//计费类型 
	int nFeeCode;				//该条短消息的收费值;单位为分 
	int nPriority;				//优先级0-9,从低到高 
	LPCSTR lpcszFeeMobile;		//收费的手机号码,为NULL或"",则表示不指定 
	LPCSTR lpcszExpireTime;		//短消息寿命的终止时间;"yymmddhhmmsstnnp";"tnnp"取固定值"032+" 
	LPCSTR lpcszScheduleTime;	//定时发送时间 
	int nMessageLength;			//短消息长度 
	LPCSTR lpcszMsgContent;		//短消息内容 
} SUBMITINFO, * PSUBMITINFO, FAR * LPSUBMITINFO; 
 
BOOL bInitOK = FALSE; 
BOOL bLoginOK = FALSE; 
 
static BOOL bStop = FALSE; 
 
void MoveTitle() 
{ 
	char szChar[3], szTitle[80]; 
 
	memset(szTitle, 0, sizeof(szTitle)); 
	GetConsoleTitle(szTitle, sizeof(szTitle)); 
 
	memcpy(szChar, szTitle, 2); 
	szChar[2] = '\0'; 
 
	memmove(szTitle, szTitle + sizeof(unsigned short), strlen(szTitle + sizeof(unsigned short)) + 1); 
 
	strcat(szTitle, szChar); 
 
	SetConsoleTitle(szTitle); 
} 
 
void ProcRawMsgID(LPCSTR lpcszRawMsgID, LPSTR lpszMsgID, int cbMsgID) 
{ 
	_ASSERT(cbMsgID >= 21); 
	memset(lpszMsgID, 0, cbMsgID); 
	for (int i = 0; i < 10; i ++) sprintf(lpszMsgID + strlen(lpszMsgID), "%02X", 0xFF & lpcszRawMsgID[i]); 
} 
 
 
void LoggingDeliveryInfo(DELIVERRESP& dr) 
{ 
	CString strError; 
	CString msg, sql; 
 
	if (dr.nIsReply) { 
		// 收到状态报告 
		//printf("\n移动状态报告:%s\n", dr.sMsgContent); 
		return; 
	} 
	 
	_ASSERT (dr.nMsgLen <= 116); 
 
	// 将信息拷入msg中,以便处理,因为dr.lpcszMsgContent不一定以\0结尾 
	try { 
		LPSTR p = msg.GetBuffer(dr.nMsgLen + 1); 
		memcpy(p, dr.sMsgContent, dr.nMsgLen); 
		p[dr.nMsgLen] = '\0'; 
		msg.ReleaseBuffer(); 
	} catch(CMemoryException*){ 
		FatalAppExit(0, "内存不足,无法创建缓冲区。"); 
	} 
 
	// 将 ' 变成 ''  
	msg.Replace("'", "\x3"); 
	msg.Replace("\x3", "''"); 
 
	CMyDatabase db; 
 
	printf("\n收到%s发到%s信息(ID:%s):%s", dr.sSrcTermID, dr.sDestTermID, dr.sServiceID, msg); 
	if (MakeSureDBConnected(db, strError)){ 
		sql.Format(	"EXECUTE ismr_sp_delivery \r\n" 
					"	@FROMMOBILE = '%s',  \r\n" 
					"	@TOMOBILE = '%s', \r\n" 
					"	@ICPNUMBER = '%s', \r\n" 
					"	@MSGLEVEL = %d, \r\n" 
					"	@MESSAGE = '%s' \r\n", 
					dr.sSrcTermID,  
					dr.sDestTermID,  
					dr.sServiceID, 
					dr.nMsgLevel, 
					msg); 
		if (db.ExecuteSQLEx(strError, sql) != -1){ 
			printf("\n登记成功。"); 
			strError = ""; 
		} 
	} 
 
	if (!strError.IsEmpty()){ 
		printf("\n登记失败,因为数据库错误:%s\n", strError); 
		LogError(".sql", "sqlError", "/* SQL */\n%s\n/* ERROR: %s */", sql, strError); 
	} 
 
	return; 
} 
 
int cngpSubmit(SUBMITINFO &submit, char* szMsgID, int lenMsgID, char szSrcTermId[21 + 1]) 
{ 
	int nPhsFeeType = -1; 
	int nMsgFormat = MSG_FORMAT_ASCII; 
	int nResult = 0; 
	int nNeedReply = 1;	// 0=不要求,1=要求 
	int nSubType = 2;	// 短消息子类型(0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发,其他保留) 
	int nFeeUserType = 0; 
	char szFeeType[3], szFeeCode[7]; 
	char szRawMsgID[11]; 
 
	_ASSERT (strlen(szIcpNbr) + strlen(submit.lpcszFromMobile) <= 19); 
	sprintf(szSrcTermId, "%s%s", szIcpNbr, submit.lpcszFromMobile); 
 
	if (!submit.lpcszFeeMobile) submit.lpcszFeeMobile = ""; 
	if (*submit.lpcszFeeMobile) nFeeUserType = 3; 
 
	switch(submit.nFeeType){ 
	case 1: 
		nPhsFeeType = 0; // 转化成PHS的FeeType 
		if (!submit.lRelatedMO){ 
			// 由SP发起的MT 
			nSubType = 3; // 订阅下发 
			nFeeUserType = 2; // 对SP计费 
		} else { 
			// 由MO发起的MT 
			nSubType = 2; // 点播下发 
		} 
		break; 
	case 2: 
		nPhsFeeType = 1; // 转化成PHS的FeeType 
		if (!submit.lRelatedMO){ 
			// 由SP发起的MT 
			nSubType = 3; // 订阅下发 
		} else { 
			// 由MO发起的MT 
			nSubType = 2; // 点播下发 
		} 
		break; 
	case 3: // 包月扣费请求 
		nPhsFeeType = 4;	// 扣费请求 
		nSubType = 3;			// 订阅下发 
		break; 
	default: 
		return SP_ERROR_INVALID_FEETYPE; 
	} 
 
	for (unsigned i = 0; i < strlen(submit.lpcszMsgContent); i ++){ 
		if ((unsigned char)submit.lpcszMsgContent[i] > 0x80){ 
			nMsgFormat = MSG_FORMAT_GB; 
		} 
	} 
 
	_ASSERT (nPhsFeeType >= 0 && nPhsFeeType <= 4); 
	sprintf(szFeeType, "%02d", nPhsFeeType); 
 
	_ASSERT (submit.nFeeCode >= 0 && submit.nFeeType <= 999999); 
	sprintf(szFeeCode, "%06d", submit.nFeeCode); 
 
	/* 
	printf("\nSP企业代码:  %s", szCorpId); 
	printf("\n短消息子类型:%d (0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发)", nSubType); 
	printf("\n确认报告:%d(0=不要求,1=要求)", nNeedReply); 
	printf("\n信息级别:%d(0=最低,1=正常,2=紧急,3=十分紧急)", submit.nPriority); 
	printf("\n业务类型:%s", submit.lpcszServiceType); 
	printf("\n资费类别:%s", szFeeType); 
	printf("\n计费用户类型:%d", nFeeUserType); 
	printf("\n资费代码:%s", szFeeCode); 
	printf("\n信息格式:%d", nMsgFormat); 
	printf("\n存活有效期:%s", submit.lpcszExpireTime); 
	printf("\n定时发送时间:%s", submit.lpcszScheduleTime); 
	printf("\n源发方号码:%s", szSrcTermId); 
	printf("\n被计费用户的号码:%s", submit.lpcszFeeMobile); 
	printf("\n接收方的手机号码:%s", submit.lpcszToMobile); 
	printf("\n短信长度:%d", submit.nMessageLength); 
	printf("\n短信内容:%s", submit.lpcszMsgContent); 
	*/ 
 
	nResult = _CNGPSubmit(szCorpId,		// SP企业代码 
		  nSubType,					// 短消息子类型(0=取消订阅,1=订阅或点播请求,2=点播下发,3=订阅下发,其他保留) 
		  nNeedReply,				// 是否要求返回状态报告:(0=不要求,1=要求) 
		  submit.nPriority,			// 信息级别(0=最低优先级,1=正常,2=紧急,3=十分紧急) 
		  submit.lpcszServiceType,	// 业务类型,最长10字节 
		  szFeeType,				// 资费类别,最长2字节(01-免费 02-按条 03-包月) 
		  nFeeUserType,				// 计费用户类型字段,0:对目的终端计费;1:对源终端计费;2:对SP计费; 3:表示本字段无效,对谁计费参见Fee_terminal_id字段。 
		  szFeeCode,				// 资费代码(以分为单位) ,最长6字节 
		  nMsgFormat,				// 信息格式 
		  submit.lpcszExpireTime,	// 存活有效期 
		  submit.lpcszScheduleTime,	// 定时发送时间 
		  szSrcTermId,				// 源发方的手机号码或ICP服务编号(特服号+用户自定义标识) 
		  submit.lpcszFeeMobile,	// 被计费用户的号码(如本字节填空,则表示本字段无效,对谁计费参见Fee_UserType字段。本字段与Fee_UserType字段互斥),最长21 bytes。 
		  1,						// 给多少个用户发 
		  submit.lpcszToMobile,		// 接收方的手机号码	 
		  submit.nMessageLength,	// 短信长度 
		  submit.lpcszMsgContent,	// 短信内容 
		  0,						// 协议类型 0-缺省 
		  (unsigned char*)szRawMsgID);				// 用来取得MSGID (接收返回的短信标识) 
 
	memset(szMsgID, 0, lenMsgID); 
	ProcRawMsgID(szRawMsgID, szMsgID, lenMsgID); 
		   
	return nResult; 
} 
 
// 返回页数,返回0表示页数太多,返回-1表示内存不足,要求释放aMsgPtr[i]内容 
int SplitMessage(wchar_t* lpwMsg, int nWordCnt, wchar_t* aMsgPtr[], int nMsgPtr) 
{ 
	int nTotal = 0; 
	LPWSTR lpwBuffer; 
 
	// 将所有指针置 NULL 
	memset(aMsgPtr, 0, nMsgPtr * sizeof(LPWSTR)); 
 
	if (nWordCnt <= 59){ 
		// 中文和英文都可以一屏发送,故没有问题 
		lpwBuffer = new WCHAR[1 + nWordCnt]; 
		if (lpwBuffer == NULL) return -1; 
		lpwBuffer[0] = nWordCnt; 
		memcpy(&lpwBuffer[1], lpwMsg, nWordCnt * sizeof(WCHAR)); 
		aMsgPtr[0] = lpwBuffer; 
		return 1; 
	} 
	if (nWordCnt <= 112){ 
		// 只有英文与数字或半角符号可以一屏发送,故判断 
		for (int i = 0; i < nWordCnt; i ++){ 
			if (lpwMsg[i] > 0xFF) break; 
		} 
		if (i >= nWordCnt){ 
			// 全是英文与数字或半角符号 
			lpwBuffer = new WCHAR[nWordCnt + 1]; 
			if (lpwBuffer == NULL)  return -1; 
			lpwBuffer[0] = nWordCnt; 
			memcpy(&lpwBuffer[1], lpwMsg, nWordCnt * sizeof(WCHAR)); 
			aMsgPtr[0] = lpwBuffer; 
			return 1; 
		} 
	} 
 
	// 以下必须分屏显示 
	int nPageBytes = 112 - 8; 
	int nStart = 0; 
	int nLen = 0; 
	for (int i = 0; i < nWordCnt; i ++){ 
		// 判断加上本字符是否超屏 
		if ((nLen == nPageBytes) || (lpwMsg[i] > 0xFF && nLen + 1 > 59 - 8)){ 
			// 超过或到达一屏,则拷贝本屏 
			lpwBuffer = new WCHAR[1 + nLen + 8]; 
			if (lpwBuffer == NULL){ 
				for (int i = 0; i < nTotal; i++) delete aMsgPtr[i]; 
				return -1; 
			} 
			lpwBuffer[0] = nLen + 8; 
			memcpy(&lpwBuffer[1], "(\0i\0/\0n\0)\0\0\0", 5 * sizeof(WCHAR)); 
			lpwBuffer[2] = (nTotal + 1) + '0'; 
			memcpy(&lpwBuffer[1 + 5], lpwMsg + nStart, nLen * sizeof(WCHAR)); 
			memcpy(&lpwBuffer[1 + 5 + nLen], ".\0.\0.\0\0\0", 3 * sizeof(WCHAR)); 
			aMsgPtr[nTotal++] = lpwBuffer; 
			if (nTotal >= 10){ 
				for (int i = 0; i < nTotal; i++) delete aMsgPtr[i]; 
				return 0; 
			} 
			// 重新设置有关初始,开始下一轮 
			nPageBytes = 112 - 8; 
			nStart += nLen; 
			nLen = 0; 
		} 
		// 判断当前字符是否为汉字,是则调整页长度 
		if (lpwMsg[i] > 0xFF) nPageBytes = 70 - 8; 
		// 并计数 
		nLen ++; 
	} 
 
	if (nLen > 0){ 
		lpwBuffer = new WCHAR[1 + nLen + 8]; 
		if (lpwBuffer == NULL){ 
			for (int i = 0; i < nTotal; i++) delete aMsgPtr[i]; 
			return -1; 
		} 
		lpwBuffer[0] = nLen + 8; 
		memcpy(&lpwBuffer[1], "(\0i\0/\0n\0)\0\0\0", 5 * sizeof(WCHAR)); 
		lpwBuffer[2] = (nTotal + 1) + '0'; 
		memcpy(&lpwBuffer[1 + 5], lpwMsg + nStart, nLen * sizeof(WCHAR)); 
		memcpy(&lpwBuffer[1 + 5 + nLen], ".\0.\0.\0\0\0", 3 * sizeof(WCHAR)); 
		aMsgPtr[nTotal++] = lpwBuffer; 
		if (nTotal >= 10){ 
			for (int i = 0; i < nTotal; i++) delete aMsgPtr[i]; 
			return 0; 
		} 
	} 
 
	for (i = 0; i < nTotal; i ++){ 
		aMsgPtr[i][4] = nTotal + '0'; 
	} 
 
	return nTotal; 
} 
 
long LoggingSubmitInfo(CMyDatabase& db, SUBMITINFO& submit, int index) 
{ 
	CString strError; 
	char sql[512]; // 196 + 10 + 21 + 21 + 10 + 10 + 10 + 10 + 16 + 16 + 10 + 161 
	CString msg; 
 
	_ASSERT(index <= 9); 
	_ASSERT(submit.nMessageLength <= 116); 
 
	// 将信息拷入msg中,以便处理,因为submit.lpcszMsgContent不一定以\0结尾 
	try { 
		LPSTR p = msg.GetBuffer(submit.nMessageLength + 1); 
		memcpy(p, submit.lpcszMsgContent, submit.nMessageLength); 
		p[submit.nMessageLength] = '\0'; 
		msg.ReleaseBuffer(); 
	} catch(CMemoryException*){ 
		FatalAppExit(0, "内存不足,无法创建缓冲区。"); 
	} 
 
	// 将 ' 变成 ''  
	msg.Replace("'", "\x3"); 
	msg.Replace("\x3", "''"); 
 
	long idTimeID = -1; 
 
	if (MakeSureDBConnected(db, strError)){ 
		CMyDataSet ds(&db); 
 
		sprintf(sql, "SELECT MAX(TIMEID) FROM SMS_SUBMIT WHERE TOMOBILE = '%s' ", submit.lpcszToMobile); 
		ds.Open(sql); 
		if (ds.m_nSQLCode == -1){ 
			strError = ds.GetSQLErrText(); 
		} else { 
			_ASSERT (ds.m_nSQLCode != 100); 
			idTimeID = ds[0][0]; 
			idTimeID += 1; 
			sprintf(sql, "INSERT INTO SMS_SUBMIT (TIMEID, FROMMOBILE, TOMOBILE, SERVICETYPE, FEETYPE, FEECODE, PRIORITY, EXPIRETIME, SCHEDULETIME, MSGLENGTH, MSGCONTENT) " 
						 "VALUES (%ld, '%s', '%s', '%s', %d, %d, %d, '%s', '%s', %d, '%s')",  
						idTimeID, submit.lpcszFromMobile,	submit.lpcszToMobile, submit.lpcszServiceType,  
						submit.nFeeType, submit.nFeeCode, submit.nPriority,	submit.lpcszExpireTime,  
						submit.lpcszScheduleTime, msg.GetLength(), msg); 
			if (db.ExecuteSQLEx(strError, sql) != -1) strError = ""; 
		} 
	}  
 
	if (!strError.IsEmpty()){ 
		printf("\n数据库错误:%s\n", strError); 
		LogError(".sql", "sqlError", "/* SQL */\n%s\n/* ERROR: %s */", sql, strError); 
	} 
 
	return idTimeID; 
} 
 
void UpdateSubmitInfo(CMyDatabase& db, long lRecordNo, const char *lpcszToMobile, const char *lpcszSrcTermId, bool bStatus, LPCTSTR lpcszMsgID) 
{ 
	CString strError; 
	char sql[256]; 
 
	sprintf(sql, "UPDATE SMS_SUBMIT SET STATUS = %d, FROMMOBILE='%s', MSGID='%s' WHERE TIMEID = %ld AND TOMOBILE = '%s' ",  
		(int)bStatus, lpcszSrcTermId, lpcszMsgID, lRecordNo, lpcszToMobile); 
 
	if (MakeSureDBConnected(db, strError)){ 
		if (db.ExecuteSQLEx(strError, sql) != -1){ 
			strError = ""; 
			if (db.GetExecRowCount() != 1){ 
				strError = "更改状态失败,找不到要修改的记录。"; 
			} 
		} 
	}  
 
	if (!strError.IsEmpty()){ 
		printf("\n无法更改ID为 %ld (接收号码为 %s )的数据 - 错误信息:%s\n", lRecordNo, lpcszToMobile, strError); 
		LogError(".sql", "sqlError", "/* SQL */\n%s\n/* ERROR: %s */", sql, strError); 
	} 
 
	return; 
} 
 
bool SubmitSM ( 
	const char * lpcszRecvMobile,	// 接收方的手机号 
	const char * lpcszServiceType,	// 业务类别 
	const char * lpcszSendMobile,	// 源发方号码 
	int nFeeType,					// 计费类型 (1-免费 2-按条 3-包月) 
	int	nFeeValue,					// 计费费用(单位:分) 
	int nPriority,					// 信息级别(0=最低优先级,1=正常,2=紧急,3=十分紧急) 
	const char * lpcszFeeMobile,	// 收费的手机号 
	int nMsgLen,					// 短信长度 
	char * lpszMsgTxt,				// 短信内容 
	int *pnErrorCode)				// 用来取错误码 
{ 
	CMyDatabase db; 
	const char *aType[] = { "CMCCTEST", "BZEDU", "BZQX", "BZHELP", "EDUJXT", "EDUZLYX", "EDUTJKB", "EDUYJJC", "EDUZXDY", "EDUKJGX", "EDUXTSW" }; 
	int nTypeCnt = sizeof(aType)/sizeof(aType[0]); 
	LPWSTR lpwMsgContent = NULL; 
	int nUcs2MsgLen = 0; 
	LPWSTR aMsgPtr[10]; 
	char Message[161]; 
	int i, nSendCount = 0; 
	long lRecordNo; 
	char szMsgID[21 + 1]; 
 
	// 去掉要发送的信息文本中无效的字符 
	for(i = 0; i < nMsgLen; i ++){ 
		switch(lpszMsgTxt[i]){ 
		case '\x3': lpszMsgTxt[i] = '\x20'; break; 
		case '\x4': lpszMsgTxt[i] = '\r'; break; 
		case '\x5': lpszMsgTxt[i] = '\n'; break; 
		case '\x6': lpszMsgTxt[i] = '\t'; break; 
		} 
	} 
 
	// 检查参数合法性 
	if (strlen(lpcszRecvMobile) < 7){ 
		printf("\n接收方手机号码(%s)长度不对,至少7位。\n", lpcszRecvMobile); 
		return false; 
	} 
 
	if (memcmp(lpcszRecvMobile, "13", 2) == 0){ 
		printf("\n接收方小灵通号码(%s)不对,不应以13开头。\n", lpcszRecvMobile); 
		return false; 
	} 
 
	// 下面就可以判断lpcszRecvMobile[2]来决定是联通还是移动  
	bool bValid = false; 
	for (i = 0; i < nTypeCnt && !bValid; i ++){ 
		int nOffset = 0; 
		if (lpcszServiceType[0] == '+' || lpcszServiceType[0] == '-') nOffset = 1; 
		if (!strcmp(aType[i], lpcszServiceType + nOffset)) bValid = true; 
	} 
 
	if (!bValid){ 
		printf("\n业务类型(%s)非法。\n", lpcszServiceType); 
		return false; 
	} 
 
	if (strlen(lpcszSendMobile) > 11){ 
		printf("\n源发方号码(%s)长度不对,应不超过11位,可为手机号码或其它标识。\n", lpcszSendMobile); 
		return false; 
	} 
 
	switch(nFeeType){ 
	case 1: 
		if (nFeeValue != 0){ 
			printf("\n计费费用值(%06d)不对,应为0。\n", nFeeValue); 
			return false; 
		} 
		break; 
	case 2: 
		if (nFeeValue <= 0 || nFeeValue > 200){ 
			printf("\n计费费用值(%06d)不对,应为1到200元,按条计费每条最高不超过2元。\n", nFeeValue); 
			return false; 
		} 
		break; 
	case 3: 
		if (nFeeValue <= 0 || nFeeValue > 3000){ 
			printf("\n计费费用值(%06d)不对,应为1到3000元,包月计费每月最高不超过30元。\n", nFeeValue); 
			return false; 
		} 
		break; 
	default: 
		printf("\n计费类型(%02d)不对,应为1、2、3,其中1为免费(包月用户下发信息使用)、2为按条收费(用于按条计费用户)、3为包月扣费包。\n", nFeeType); 
		return false; 
	} 
 
	if (nPriority < 0 || nPriority > 3){ 
		printf("\n短信优先级(%d)不对,应为0到9。\n", nPriority); 
		return false; 
	} 
 
	// 将要发送的信息进行处理,变成 MSG_FORMAT_UCS2 格式 
	lpwMsgContent = new WCHAR[nMsgLen + 1]; 
	if (lpwMsgContent == NULL){ 
		printf("\n没有内存转换数据。\n"); 
		return false; 
	} 
 
	memset(lpwMsgContent, 0, (nMsgLen + 1) * sizeof(WCHAR)); 
	nUcs2MsgLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszMsgTxt, nMsgLen, lpwMsgContent, nMsgLen); 
	if (nUcs2MsgLen <= 0){ 
		delete []lpwMsgContent; 
		printf("\n转换数据失败。\n"); 
		return false; 
	} 
 
	nSendCount = SplitMessage(lpwMsgContent, nUcs2MsgLen, aMsgPtr, 10); 
 
	delete []lpwMsgContent; 
 
	switch(nSendCount){ 
	case 0: 
		printf("\n要发送的信息太长,已达10页。\n"); 
		return false; 
	case -1: 
		printf("\n没有内存转换数据。\n"); 
		return false; 
	} 
 
	SUBMITINFO submit; 
 
	submit.lpcszFromMobile	= lpcszSendMobile; 
	submit.lpcszToMobile	= lpcszRecvMobile; 
	submit.lpcszServiceType	= lpcszServiceType; 
	submit.nFeeType			= nFeeType; 
	submit.nFeeCode			= nFeeValue; 
	submit.nPriority		= nPriority; 
	submit.lpcszExpireTime  = ""; 
	submit.lpcszScheduleTime= ""; 
	submit.lpcszFeeMobile   = lpcszFeeMobile; 
 
	bool bReturn = true; 
	char szSrcNumber[21 + 1]; 
	for (i = 0; i < nSendCount && bReturn; i ++){ 
 
		// 将UNICODE转成MULTIBYTE 
		submit.nMessageLength = WideCharToMultiByte(CP_ACP, 0, &aMsgPtr[i][1], aMsgPtr[i][0], Message, sizeof(Message), NULL, NULL); 
		Message[submit.nMessageLength] = 0; 
		submit.lpcszMsgContent	= Message; 
 
		printf("\n发送:%s\n", Message); 
 
		lRecordNo = LoggingSubmitInfo(db, submit, i); 
		if (lRecordNo < 0){ 
			*pnErrorCode = -1; 
			bReturn = false; 
			break; 
		} 
				 
		// 发送它们 
		printf("\n通过网通短信网关发送短信给%s...", lpcszRecvMobile); 
		int nResult = cngpSubmit(submit, szMsgID, sizeof(szMsgID), szSrcNumber); 
		if (nResult != 0){ 
			printf("失败!\n错误码为%d。\n", *pnErrorCode); 
			bReturn = false; 
		} else { 
			printf("成功!\n接方手机号为网通用户:%s MSGID: %s\n", lpcszRecvMobile, szMsgID); 
		} 
 
		UpdateSubmitInfo(db, lRecordNo, submit.lpcszToMobile, szSrcNumber, bReturn, szMsgID); 
	} 
 
	for (i = 0; i < nSendCount; i ++){ 
		if (aMsgPtr[i]){ 
			delete aMsgPtr[i]; 
		} 
	} 
 
	return bReturn; 
} 
 
BOOL ProcDelivery(int nTimeOut) 
{ 
	char rawmsgid[10]; 
    unsigned char byProValue; 
    char sRecvTime[34 + 1];  
	char raworgmsgid[10]; 
    char sSubmitdate[34 + 1]; 
    char sDonedate[34 + 1]; 
    char sStatus[21 + 1]; 
    int  iDeliverAckResult = 1; 
	DELIVERRESP dr; 
 
	memset(&dr, 0, sizeof(dr)); 
	dr.uSize = sizeof(dr); 
 
	Sleep(nTimeOut); 
 
	if (_GetCNGPDeliverSM( 
			rawmsgid, 
            (unsigned char*)&dr.nMsgFormat, 
            sRecvTime, 
            dr.sSrcTermID, 
            dr.sDestTermID, 
            (unsigned char*)&dr.nMsgLen, 
            dr.sMsgContent, 
            (unsigned char*)&byProValue, 
            (unsigned char*)&dr.nIsReply, 
            raworgmsgid, 
            sSubmitdate,          
            sDonedate, 
            sStatus, 
            iDeliverAckResult) != 0) return FALSE; 
	ProcRawMsgID(rawmsgid, dr.sMsgID, sizeof(dr.sMsgID)); 
 
	char *p = strstr(dr.sDestTermID, szIcpNbr); 
	if (p != NULL){ 
		if (p != dr.sDestTermID){ 
			memmove(dr.sDestTermID, p, strlen(p) + 1); // 多拷一个0 
		} 
	} 
 
	if (dr.nMsgLen < 0 || dr.nMsgLen >= sizeof(dr.sMsgContent)){ 
		printf("\n错误:无效的MSGLEN。"); 
		return TRUE; 
	} 
 
	dr.sMsgContent[dr.nMsgLen] = '\0'; 
 
	if (!dr.nIsReply){ 
		printf("\nDELIVER: MID:%s FMT:%d FRM: %s TO: %s LEN: %d>%s", dr.sMsgID, dr.nMsgFormat, dr.sSrcTermID, dr.sDestTermID, dr.nMsgLen, dr.sMsgContent); 
	} else { 
		char orgmsgid[21 + 1]; 
		char stat[21]; 
		ProcRawMsgID(raworgmsgid, orgmsgid, sizeof(orgmsgid)); 
		char *p = strstr(dr.sMsgContent, "stat:"); 
		if (p != NULL){ 
			p += 5; 
			if (sscanf(p, "%20s", stat) != 1){ 
				memset(stat, 0, sizeof(stat)); 
			} 
			printf("\nREPORT: MID:%s FMT:%d FRM: %s TO: %s>原始消息标识:%s 状态:%s", dr.sMsgID, dr.nMsgFormat, dr.sSrcTermID, dr.sDestTermID, orgmsgid, stat); 
		} 
	} 
 
	printf("\n"); 
 
	// 2003-12-20 前加,用来给客户端返回特服号码 
	_ASSERT(strlen(szIcpNbr) > 0); 
	strcpy(dr.sServiceID, szIcpNbr); 
 
	LoggingDeliveryInfo(dr); // 网通 
 
	return TRUE; 
}