www.pudn.com > lucent_softphone.rar > MichelleCTI.cpp


// MichelleCTI.cpp : Implementation of CMichelleCTI 
#include "stdafx.h" 
#include "LucentCti.h" 
#include "KVPair.h" 
#include "KVList.h" 
#include "CTIEvent.h" 
#include "MichelleCTI.h" 
 
#include  
#define szLogPath "c:\\LUCENTLOG" // the log file path 
#define EVENT_BUF_LEN 800 // the lucent event bufer default length 
 
/////////////////////////////////////////////////////////////////////////////// 
//Area for global functions 
HINSTANCE CMichelleCTI::m_hInstance=NULL; 
HWND CMichelleCTI::m_hSynWnd=NULL; 
HANDLE CMichelleCTI::m_hPumpTrd=NULL; 
UINT CMichelleCTI::m_dwPumpId=0; 
 
DECLARE_CASTER(CDirectoryNumber, IDirectoryNumber) 
DECLARE_CREATOR(CCTIEvent, ICTIEvent) 
DECLARE_CREATOR(CDirectoryNumber, IDirectoryNumber) 
 
//write log 
void WriteLog(char* pData) 
{ 
#ifdef _WRITELOG 
	time_t  now; 
	time(&now); 
	tm nowTime=*localtime(&now); 
 
	char logfile[1024]={0}; 
	sprintf(logfile,"%s\\LucentCTILog%02d_%02d_%04d.log",szLogPath,nowTime.tm_mon+1,nowTime.tm_mday,nowTime.tm_year+1900); 
	HANDLE hLogFile=CreateFile(logfile,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 
	if (hLogFile==INVALID_HANDLE_VALUE) 
	{ 
		if (!CreateDirectory(szLogPath,NULL)) 
			return; 
		else 
			hLogFile=CreateFile(logfile,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 
	} 
	if (hLogFile!=INVALID_HANDLE_VALUE) 
	{ 
		SetFilePointer(hLogFile,NULL,NULL,FILE_END); 
		sprintf(logfile,"%2d:%2d:%2d Message:%s\r\n",nowTime.tm_hour,nowTime.tm_min,nowTime.tm_sec,pData); 
		DWORD dw; 
		WriteFile(hLogFile,logfile,strlen(logfile),&dw,NULL); 
		 
		CloseHandle(hLogFile); 
	} 
 
#endif 
} 
 
// the pump thread, all lucent api must post message to me at first, then 
//		I'll send this message to the synchronic window 
DWORD PumpThread (HWND hSynWnd) 
{ 
	CoInitialize(NULL); 
	MSG msg; 
	while (GetMessage(&msg,NULL,0,0)) 
	{ 
		if (IsWindow(hSynWnd)) 
		if (!SendMessage(hSynWnd,msg.message,msg.wParam,msg.lParam)) 
			Sleep(100); 
	} 
	CoUninitialize(); 
	return 0; 
} 
 
//the registried lucent stream monitor function.Get all message here 
//void WINAPI monitorStream(CMichelleCTI* pCti) 
void WINAPI monitorStream(unsigned long p) 
{ // the stream event process event 
	CMichelleCTI* pCti=(CMichelleCTI*)p; 
	//PostThreadMessage regulation: 
	//msg: um_cti or um_dn_csta or um_dn_att or um_apifailed 
	//wParam: cti class or dn class 
	//lParam: evnet pointer 
	if (pCti) 
	{ 
		byte*  eventBuf=new byte[EVENT_BUF_LEN]; 
		if (eventBuf==NULL) 
			return; 
		unsigned short nEventBufLen=EVENT_BUF_LEN; 
		ATTPrivateData_t* data=new ATTPrivateData_t; // the private data 
		if (data) 
		{ 
			 
			data->length=ATT_MAX_PRIVATE_DATA; 
			CSTAEvent_t* cstaEvent=NULL; // the csta event 
			ATTEvent_t* attEvent=NULL; // the att event 
			unsigned short nNumEvent=0; // the event queue 's member account 
 
			RetCode_t ret=acsGetEventPoll(pCti->m_serverHandle,eventBuf,&nEventBufLen, 
											(PrivateData_t*)data,&nNumEvent); 
			if (ret!=0) 
			{ 
				if (ACSERR_NOMESSAGE==ret) 
				{//There is no message,ok 
					return; 
				}else if (ACSERR_UBUFSMALL==ret) 
				{//The buffer is too small 
					delete eventBuf; 
					eventBuf=new byte[ nEventBufLen]; 
					if (!eventBuf) 
					{ 
						PostThreadMessage(pCti->m_dwPumpId,UM_APIFAILED,(WPARAM)pCti,0); 
						WriteLog("event buffer too small, realloc failed."); 
					} 
					//try to get the event again 
					ret=acsGetEventPoll(pCti->m_serverHandle,eventBuf,&nEventBufLen, 
											(PrivateData_t*)data,&nNumEvent); 
					if (ret!=0) 
					{ 
						PostThreadMessage(pCti->m_dwPumpId,UM_APIFAILED,(WPARAM)pCti,0); 
						WriteLog("get event twince, but all failed."); 
					} 
				}else 
				{ 
					PostThreadMessage(pCti->m_dwPumpId,UM_APIFAILED,(WPARAM)pCti,0); 
					WriteLog("get event failed."); 
				} 
			}else 
			{// ok, we get a csta event 
				cstaEvent=(CSTAEvent_t*)eventBuf; 
			} 
 
			if (cstaEvent) 
			{ 
				dnevent* pEvent=NULL; 
				//now process the csta event 
				switch(cstaEvent->eventHeader.eventClass) 
				{ 
				case ACSCONFIRMATION: 
					// the acs api confirmation 
					switch (cstaEvent->eventHeader.eventType) 
					{ 
					case ACS_OPEN_STREAM_CONF: 
					case ACS_CLOSE_STREAM_CONF: 
						//acs ok 
						PostThreadMessage(pCti->m_dwPumpId,UM_CTI,(WPARAM)pCti,cstaEvent->eventHeader.eventType); 
						break; 
					case ACS_UNIVERSAL_FAILURE_CONF: 
						//failure confirm 
						if (pCti->m_iDn) 
						{// This message must be post to dn if the dn has been registered 
							pEvent=new dnevent(cstaEvent,NULL); 
							if (pEvent) 
							{ 
								 PostThreadMessage(pCti->m_dwPumpId,UM_DN,(WPARAM)pCti->m_iDn,(LPARAM)pEvent); 
								 eventBuf=NULL; 
								 cstaEvent=NULL; 
							} 
						}else 
						{ 
							pCti->m_lErrCode=cstaEvent->event.cstaConfirmation.u.universalFailure.error; 
							pCti->m_errType=ET_LUCENT_CONF; 
							PostThreadMessage(pCti->m_dwPumpId,UM_CTI,(WPARAM)pCti,UM_APIFAILED); 
							char pTemp[100]={0}; 
							wsprintf(pTemp,"ACS_UNIVERSAL_FAILURE_CONF error code:%d(cti)",pCti->m_lErrCode); 
							WriteLog(pTemp); 
						} 
						break; 
					default: 
						//PostThreadMessage(pCti->m_dwPumpId,UM_CTI,(WPARAM)pCti,UM_APIFAILED); 
						WriteLog("Get an unknown ascconfirmation event."); 
						break; 
					} 
					break; 
				case ACSUNSOLICITED: 
					if (pCti->m_iDn) 
					{// This message must be post to dn if the dn has been registered 
						pEvent=new dnevent(cstaEvent,NULL); 
						if (pEvent) 
						{ 
							 PostThreadMessage(pCti->m_dwPumpId,UM_DN,(WPARAM)pCti->m_iDn,(LPARAM)pEvent); 
							 eventBuf=NULL; 
							 cstaEvent=NULL; 
						} 
					}else  
					{//send to cti object 
						pCti->m_lErrCode=cstaEvent->event.acsUnsolicited.u.failureEvent.error; 
						pCti->m_errType=ET_LUCENT_CONF; 
						pCti->m_ErrMsg="Get an acsunsolicited event."; 
						PostThreadMessage(pCti->m_dwPumpId,UM_CTI,(WPARAM)pCti,UM_APIFAILED); 
						char pTemp[100]={0}; 
						wsprintf(pTemp,"ACSUNSOLICITED error code:%d(cti)",pCti->m_lErrCode); 
						WriteLog(pTemp); 
					} 
					break; 
				case CSTACONFIRMATION: 
					//the csta api confirmation 
					pEvent=new dnevent(cstaEvent,NULL); 
					if (pEvent) 
					{ 
						 PostThreadMessage(pCti->m_dwPumpId,UM_DN,(WPARAM)pCti->m_iDn,(LPARAM)pEvent); 
						 eventBuf=NULL; 
						 cstaEvent=NULL; 
					} 
					break; 
				case CSTAUNSOLICITED: 
					//post the csta message 
					switch (cstaEvent->eventHeader.eventType) 
					{ 
					case CSTA_DELIVERED: 
						//post the att event 
						if (data->length>0) 
						{//contains private data,send ATTEvent 
							attEvent=new ATTEvent_t; 
							//this buffer will be processed and deleted in future 
							if (attEvent) 
							{ 
								ret=attPrivateData(data,attEvent); 
								if (ret!=0) 
								{ 
									delete attEvent; 
									attEvent=NULL; 
								} 
							} 
						} 
						break; 
					default: 
						break; 
					} 
					pEvent=new dnevent(cstaEvent,attEvent); 
					if (pEvent) 
					{ 
						PostThreadMessage(pCti->m_dwPumpId,UM_DN,(WPARAM)pCti->m_iDn,(LPARAM)pEvent); 
						eventBuf=NULL; 
						cstaEvent=NULL; 
					}else 
					{ 
						delete attEvent; 
						attEvent=NULL; 
					} 
					eventBuf=NULL; 
					cstaEvent=NULL; 
					break; 
				}//switch(cstaEvent->eventHeader.eventClass) 
			} 
			// before exit, clear buffer 
			if (eventBuf) 
			{ 
				delete eventBuf; 
				eventBuf=NULL; 
				cstaEvent=NULL; 
			} 
			//call fun again to process event 
			if (nNumEvent>1) 
				monitorStream((unsigned long)pCti); 
		} 
	} 
	return; 
} 
 
// the synchronic window message process function. All message will be processed here 
LRESULT CALLBACK SynchronicWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{// the synchronic window message dispatcher 
	CCTIEvent *pCEvent; 
	ICTIEvent *pIEvent; 
	CMichelleCTI* pCti=NULL; 
	CDirectoryNumber* pDn=NULL; 
 
	CSTAEvent_t* cstaEvent=NULL; 
	dnevent* pEvent=NULL; 
 
	switch(msg) 
	{ 
	case UM_APIFAILED: 
		if (wParam!=0) 
		{ 
			pCti=(CMichelleCTI*)wParam; 
			if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent)))  
			{ 
				pCEvent->m_GenesysEvent=EVT_Error; 
				pCti->Fire_Event(pIEvent); 
				pIEvent->Release(); 
			} else  
			{ 
				pCti->Fire_Event(NULL); 
			} 
		} 
		break; 
	case UM_CTI: 
		if (wParam!=0) 
		{ 
			pCti=(CMichelleCTI*)wParam; 
			if (!pCti->DefaultHandler(lParam))//event name 
			{ 
				if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent)))  
				{ 
					switch(lParam) 
					{ 
					case UM_APIFAILED: 
						pCEvent->m_GenesysEvent=EVT_Error; 
						break; 
					case ACS_OPEN_STREAM_CONF: 
						pCEvent->m_GenesysEvent=EVT_LinkConnected; 
						break; 
/////////////MARK by rick --begin 
//					case ACS_CLOSE_STREAM_CONF: 
//						pCEvent->m_GenesysEvent=EVT_LinkDisconnected; 
//						break; 
 
/////////////MARK --end 
					} 
					pCti->Fire_Event(pIEvent); 
					pIEvent->Release(); 
				} else  
				{ 
					pCti->Fire_Event(NULL); 
				} 
			} 
		} 
		break; 
	case UM_DN: 
		if (wParam!=0) 
		{ 
			pDn = I2C((IDirectoryNumber*)wParam); 
			pEvent=(dnevent*) lParam; 
			if (!pDn->DefaultHandler(pEvent)) 
			{ 
				if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent)))  
				{ 
						pCEvent->SetEvent(pEvent); 
						pDn->Fire_Event(pIEvent); 
						pIEvent->Release(); 
				} else  
				{ 
					pCti->Fire_Event(NULL); 
				} 
				delete pEvent; 
			} 
			lParam=0; // the dnevent has been deleted 
		} 
		if (wParam==0 && lParam!=0)  
			delete ((dnevent*) lParam); 
		break; 
 
	default: 
		return(DefWindowProc(hwnd, msg, wParam, lParam)); 
	} 
	return (0l); 
} 
 
BOOL GlobalStartup(HINSTANCE hInstance) 
{ 
	BOOL ret=FALSE; 
	if (hInstance) 
	{ 
		CMichelleCTI::m_hInstance=hInstance; 
		//Create the message synchronic window 
			WNDCLASS wc; 
		wc.style = 0; 
		wc.lpfnWndProc = SynchronicWndProc; 
		wc.cbClsExtra = wc.cbWndExtra = 0; 
		wc.hInstance = hInstance; 
		wc.hIcon = NULL; 
		wc.hCursor = NULL; 
		wc.hbrBackground = NULL; 
		wc.lpszMenuName = NULL; 
		wc.lpszClassName = _T("LUCENT_CTI_SYN_WND"); 
		CMichelleCTI::m_hSynWnd=NULL; 
		if(RegisterClass(&wc)) 
			CMichelleCTI::m_hSynWnd = CreateWindow(wc.lpszClassName, NULL, 
				WS_DISABLED, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); 
		if (CMichelleCTI::m_hSynWnd) 
		{ 
			CMichelleCTI::m_hPumpTrd=(HANDLE)_beginthreadex(NULL,0,(ALT_LPTHREAD_START_ROUTINE)PumpThread, 
													CMichelleCTI::m_hSynWnd,0, 
													&CMichelleCTI::m_dwPumpId); 
			if (CMichelleCTI::m_hPumpTrd) 
				ret=TRUE; 
		} 
	} 
	return ret; 
} 
 
void GlobalCleanup() 
{ 
	if (CMichelleCTI::m_hSynWnd) 
	{ 
		DestroyWindow(CMichelleCTI::m_hSynWnd); 
		CMichelleCTI::m_hSynWnd=NULL; 
	} 
	 
	if (CMichelleCTI::m_hPumpTrd && CMichelleCTI::m_dwPumpId) 
	{ 
		PostThreadMessage(CMichelleCTI::m_dwPumpId,WM_QUIT,0,0); 
 
		while (WaitForSingleObject(CMichelleCTI::m_hPumpTrd,100)==WAIT_TIMEOUT) 
		{ 
			MSG msg; 
			if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) 
			{ 
				TranslateMessage(&msg); 
				DispatchMessage(&msg); 
			} 
		} 
		CloseHandle(CMichelleCTI::m_hPumpTrd ); 
	} 
	return; 
} 
 
// change the bstring to ansi string 
BOOL B2C(BSTR bStr,char* pBuf,int nBufLen) 
{ 
	BOOL ret=FALSE; 
	if (pBuf && nBufLen>0) 
	{ 
		if (bStr) 
		{ 
			int nLen=WideCharToMultiByte(CP_ACP,0,bStr,-1,NULL,0,NULL,NULL); 
			if (nLen<=nBufLen) 
			{ 
				if (WideCharToMultiByte(CP_ACP,0,bStr,-1,pBuf,nBufLen,NULL,NULL)>0) 
					ret=TRUE; 
			} 
		}else 
		{// the BSTR is a null string 
			memset(pBuf,0,nBufLen); 
			ret=TRUE; 
		} 
	} 
	return ret; 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CMichelleCTI 
BOOL CMichelleCTI::DefaultHandler(long cstaEvent) 
{ 
	BOOL notFire=TRUE; 
	switch (cstaEvent) 
	{ 
	case UM_APIFAILED: 
	case ACS_OPEN_STREAM_CONF: 
	case ACS_CLOSE_STREAM_CONF: 
		notFire=FALSE; 
		break; 
	} 
    while (!PostMessage(NULL,UM_CMDMSG,cstaEvent,0)) 
		Sleep(100); 
	if (!notFire)  
		ReplyMessage(0l); 
	return notFire; 
} 
 
STDMETHODIMP CMichelleCTI::get_Initialized(BOOL *pVal) 
{ 
	// TODO: Add your implementation code here 
	*pVal=m_serverHandle!=0; 
	return S_OK; 
} 
 
STDMETHODIMP_(BOOL) CMichelleCTI::Initialize(PBXTYPES pbxtype, BSTR server, int port, BSTR name, BSTR pass) 
{ 
	// TODO: Add your implementation code here 
	BOOL bRet=FALSE; 
	if (B2C(server,m_serverId,sizeof(m_serverId))  
			&& B2C(name,m_loginId,sizeof (m_loginId)) 
			&& B2C(pass,m_pwdId,sizeof (m_pwdId))) 
	{ 
 
		AppName_t appName={0}; 
		strcpy(appName,"Lucent cti dll"); 
		Version_t version={0}; 
		strcpy(version,"TS1-2"); 
		InvokeIDType_t invokeType=APP_GEN_ID; 
		StreamType_t streamType=ST_CSTA; 
		Level_t level=ACS_LEVEL1; //This param is ignored 
 
		// set the private data version 
		ATTPrivateData_t OpenData; 
		strcpy(OpenData.vendor,"VERSION"); 
//		strcpy(&OpenData.data[1],"AT&T Definity G3#6"); 
		OpenData.data[0]=PRIVATE_DATA_ENCODING; 
		attMakeVersionString("6",&OpenData.data[1]); 
		OpenData.length=strlen(&OpenData.data[1])+2; 
 
		//error prepaired 
		m_lErrCode=0; 
		m_errType=ET_NOERROR; 
		RetCode_t ret; 
		char pTemp[300]; 
		wsprintf(pTemp,"acsOpenStream: user:%s,pwd:%s",m_loginId,m_pwdId); 
		WriteLog(pTemp); 
		try 
		{ 
			ret=acsOpenStream(&m_serverHandle,invokeType,m_invokeId,streamType, 
										&m_serverId,&m_loginId,&m_pwdId,&appName,level,&version, 
										5,//send queue size 
										5,//additional packet buffer 
										20,//receive queue size 
										5,//additional packet buffer 
										(PrivateData_t*)&OpenData/*private data*/); 
		}catch(...) 
		{ 
			ret=LUCENT_UNKNOWN; 
			m_errType=ET_LUCENT; 
			m_ErrMsg="acsOpenStream failed by unknown error."; 
		} 
		if (ret<0) 
		{//ERROR 
			m_errType=ET_LUCENT; 
			m_lErrCode=ret; 
			m_ErrMsg="acsOpenStream return failed."; 
		}else 
		{//OK 
			m_lErrCode=ERR_INI; 
			//Regist the message process function 
			ret=acsSetESR(m_serverHandle,monitorStream,(unsigned long)this,TRUE); 
			if (ret>=0) 
			{ 
				BOOL bQuit=FALSE; 
				//waiting for the acs confirmation's arrival 
				MSG msg; 
				while (GetMessage(&msg,NULL,0,0)) 
				{ 
					if (msg.message==UM_CMDMSG && msg.hwnd==NULL) 
					{ 
						switch(msg.wParam) 
						{ 
						case ACS_OPEN_STREAM_CONF: 
							bRet=TRUE; 
							bQuit=TRUE; 
							break; 
						case UM_APIFAILED: 
							if (m_lErrCode==ERR_INI) 
							{ 
								m_errType=ET_LUCENT; 
								m_lErrCode=LUCENT_UNKNOWN; 
								m_ErrMsg="acsSetESR failed."; 
							} 
							bQuit=TRUE; 
							break; 
						default: 
							break; 
						} 
						if (bQuit) 
							break; 
					} 
				} 
			}else 
			{ 
				m_errType=ET_LUCENT; 
				m_lErrCode=ret; 
			} 
		} 
	}else 
	{ 
		m_errType=ET_USER; 
		m_lErrCode=LUCENT_INVALID_PARAM; 
		m_ErrMsg="Specified an error parameter."; 
	} 
 
	if (!bRet) 
	{ 
		char tep[300]={0}; 
		wsprintf((char*)&tep,"error:%s,code:%d.",m_ErrMsg.c_str(),m_lErrCode); 
		WriteLog((char*)&tep); 
	} 
	return bRet; 
} 
 
STDMETHODIMP_(void) CMichelleCTI::Uninitialize() 
{ 
	// TODO: Add your implementation code here 
	//IF {m_iDn} do 
	BOOL bRet=FALSE; 
	if (m_iDn) UnregisterDN(NULL); 
//	acsAbortStream(m_serverHandle,NULL); 
	WriteLog("acsCloseStream service."); 
	m_lErrCode=ERR_INI; 
	RetCode_t ret=acsCloseStream(m_serverHandle,m_invokeId,NULL); 
	if (ret==ACSPOSITIVE_ACK) 
	{ 
		MSG msg; 
		while (GetMessage(&msg,NULL,0,0)) 
		{ 
			if (msg.message==UM_CMDMSG) 
			{ 
				if (msg.wParam==UM_APIFAILED) 
				{ 
					if (m_lErrCode!=ERR_INI) 
					{ 
						m_errType=ET_LUCENT; 
						m_lErrCode=LUCENT_UNKNOWN; 
						m_ErrMsg="acsCloseStream unknown error."; 
					}  
					break; 
				}else if (msg.wParam==ACS_CLOSE_STREAM_CONF) 
				{ 
					bRet=TRUE; 
					break; 
				} 
			} 
		} 
	}else 
	{ 
		m_errType=ET_LUCENT; 
		m_lErrCode=ret; 
		m_ErrMsg="acsCloseStream return error."; 
	} 
	if (!bRet) 
	{ 
		char tep[300]={0}; 
		wsprintf((char*)&tep,"error:%s,code:%d.",m_ErrMsg.c_str(),m_lErrCode); 
		WriteLog((char*)&tep); 
	} 
	return; 
} 
 
STDMETHODIMP_(IDirectoryNumber*) CMichelleCTI::RegisterDN(BSTR dn, ADDRTYPES type, BSTR acdpos) 
{ 
	if (type==AT_DN || type==AT_Unknown) 
	{ 
		CDirectoryNumber *pExtDN = NULL; 
		IDirectoryNumber *iExtDN = NULL; 
		HRESULT hRes = CreateClass(&pExtDN, &iExtDN); 
		if(SUCCEEDED(hRes))  
		{ 
			m_iDn=iExtDN; 
			m_iDn->AddRef(); 
			if (!pExtDN->Initialize(dn,m_serverHandle,m_invokeId+1)) 
			{ 
				m_iDn->Release(); 
				m_iDn=NULL; 
				m_errType=ET_USER; 
				m_lErrCode=LUCNET_DNINI_ERR; 
			} 
	//		iExtDN->Release(); 
			iExtDN=NULL; 
		}else 
		{ 
			m_errType=ET_COM; 
			m_lErrCode=hRes; 
			m_ErrMsg="Create a com instance failed."; 
		} 
	}else 
	{ 
		m_errType=ET_USER; 
		m_lErrCode=LUCENT_ADDRESSTYPE_ERR; 
		m_ErrMsg="Sepcified an error parameter."; 
	} 
	if (m_iDn==NULL) 
	{ 
		char tep[300]={0}; 
		wsprintf((char*)tep,"error:%s,code:%d",m_ErrMsg.c_str(),m_lErrCode); 
	} 
	return m_iDn; 
} 
 
STDMETHODIMP_(void) CMichelleCTI::UnregisterDN(LPDN dn) 
{ 
	// TODO: Add your implementation code here 
	if (m_iDn) 
	{ 
		CDirectoryNumber* pExtDn=I2C(m_iDn); 
		pExtDn->Uninitialize(); 
//		long n=m_iDn->AddRef(); 
		m_iDn->Release(); 
		m_iDn=NULL; 
	} 
 
} 
 
 
STDMETHODIMP CMichelleCTI::get_ErrType(ERRORTYPES *pVal) 
{ 
	// TODO: Add your implementation code here 
	*pVal=m_errType; 
	return S_OK; 
} 
 
STDMETHODIMP CMichelleCTI::get_ErrCode(long *pVal) 
{ 
	// TODO: Add your implementation code here 
	*pVal=m_lErrCode; 
	return S_OK; 
} 
 
STDMETHODIMP CMichelleCTI::get_ErrMsg(BSTR *pVal) 
{ 
	// TODO: Add your implementation code here 
	*pVal=C2B(m_ErrMsg.c_str()); 
	return S_OK; 
} 
 
STDMETHODIMP_(BOOL) CMichelleCTI::Init(BSTR server, int port) 
{ 
	ATLASSERT(FALSE); 
	return TRUE; 
} 
STDMETHODIMP_(void) CMichelleCTI::Login(BSTR AgentID) 
{ 
	ATLASSERT(FALSE); 
	return ; 
} 
STDMETHODIMP_(void) CMichelleCTI::ReportConfirm(BOOL confirm) 
{ 
	ATLASSERT(FALSE); 
	return ; 
} 
STDMETHODIMP_(void) CMichelleCTI::ReportResult(BSTR ReqID, BOOL result, BSTR reason) 
{ 
	ATLASSERT(FALSE); 
	return ; 
} 
STDMETHODIMP_(void) CMichelleCTI::ReportStatus(BSTR AgentID, AGENTSTATES AgentState) 
{ 
	ATLASSERT(FALSE); 
	return ; 
} 
STDMETHODIMP_(void) CMichelleCTI::Uninit() 
{ 
	ATLASSERT(FALSE); 
	return ; 
}