⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 michellecti.cpp

📁 使用CT-C开发的一个CTI软电话系统,ActiveX形式的,仅供参考
💻 CPP
字号:
// MichelleCTI.cpp : Implementation of CMichelleCTI
#include "stdafx.h"
#include "ctcv4.h"
#include "KVPair.h"
#include "KVList.h"
#include "CTIEvent.h"
#include "MichelleCTI.h"
#include "DirectoryNumber.h"

DECLARE_CASTER(CCTIEvent, ICTIEvent)
DECLARE_CREATOR(CCTIEvent, ICTIEvent)
DECLARE_CASTER(CDirectoryNumber, IDirectoryNumber)
DECLARE_CREATOR(CDirectoryNumber, IDirectoryNumber)

//THE NETWORK TYPE
#define NT_NetBIOS_NetBEUI 0
#define NT_TCPIP			NT_NetBIOS_NetBEUI+1
#define NT_DECnet			NT_NetBIOS_NetBEUI+2
#define NT_NetBIOS_TCPIP	NT_NetBIOS_NetBEUI+3
#define NT_NAMED_PIPE		NT_NetBIOS_NetBEUI+4
#define NT_SPX				NT_NetBIOS_NetBEUI+5


HWND h_gPumpWnd=NULL;  // the main window handle that process all message from cti and dn
HINSTANCE h_gInstance=NULL;  // The dll instance handle

BSTR C2B(char* pStr,int nBufLen)
{
	BSTR ret=NULL;
	int nLen=MultiByteToWideChar(CP_ACP,0,pStr,-1,NULL,0);
	if (nLen>0)
	{
		OLECHAR* pBstr=new OLECHAR[nLen];
		if (pBstr)
		{
			nLen=MultiByteToWideChar(CP_ACP,0,pStr,-1,pBstr,nLen);
			if (nLen>0)
			{
				ret=SysAllocString(pBstr);
			}
			delete pBstr;
		}
	}
	return ret;
}

BOOL B2C(BSTR bStr,char* pStr,int nBufLen)
{
	BOOL bRet=FALSE;
	memset(pStr,0,nBufLen);
	int nLen=WideCharToMultiByte(CP_ACP,0,bStr,-1,pStr,nBufLen,NULL,NULL);
	if (nLen>0)
		bRet=TRUE;
	return bRet;
}

// The main message process function for the pump window,
// it process all messages from cti and dns, the fire some of them to VB 
static LRESULT CALLBACK PumpWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	//redo, to fire event and 
	//msg: the message type
	//wParam: the class pointer
	//lParam: the data buffer pointer
	CCTIEvent *pCEvent;
	ICTIEvent *pIEvent;
	CMichelleCTI *pCTI;
	CDirectoryNumber *pDN;

	switch (msg)
	{
	case UM_FATALERROR: //  Never process this routin
		pCTI = (CMichelleCTI *)wParam;
		if (pCTI)
		{
			pCTI->FatalError();
			//fire this evnet out
			if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent)))
			{
				pCEvent->FillEvent(NULL); //NULL means that this is EventServerDisconnected
				pCTI->Fire_Event(pIEvent);
				pIEvent->Release();
			} else 
			{
				pCTI->Fire_Event(NULL);
			}
		}
		//Release data buffer
		if (lParam)
		{
			delete (ctcEventData*)lParam;
		}
		break;
	case UM_CTIEVENT: //process the cti message
		pCTI = (CMichelleCTI *)wParam;
		if (pCTI)
		{
			if(!pCTI->DefaultHandler()) 
			{
				//fire this evnet out
				if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent)))
				{
					pCEvent->FillEvent((ctcEventData*)lParam); //NULL means that this is EventServerDisconnected
					pCTI->Fire_Event(pIEvent);
					pIEvent->Release();
				} else 
				{
					pCTI->Fire_Event(NULL);
				}
			}
		}

		//Release data buffer
		if (lParam)
		{
			delete (ctcEventData*)lParam;
		}
		break;
	case UM_DNEVENT://process the dn message
		pDN = (CDirectoryNumber *)wParam;
		if (pDN)
		{
//			if(!pDN->DefaultHandler((ctcEventData*)lParam))
			{
				if(SUCCEEDED(CreateClass(&pCEvent, &pIEvent))) 
				{
					pCEvent->FillEvent((ctcEventData*)lParam); //NULL means that this is EventServerDisconnected
					pDN->Fire_Event(pIEvent);
					pIEvent->Release();
				} else 
				{
					pDN->Fire_Event(NULL);
				}
			}
		}
		//Release data buffer
		if (lParam)
		{
			delete (ctcEventData*)lParam;
		}
		break;
	default:// the windows message
		return (DefWindowProc(hwnd, msg, wParam, lParam));
	}
	return 0L;
}

BOOL GlobalStartup(HINSTANCE hInstance)
{
	h_gInstance=hInstance;
	//Create the main message process window
	BOOL bRet=FALSE;
	WNDCLASS wc;
	wc.style = 0;
	wc.lpfnWndProc = PumpWndProc;
	wc.cbClsExtra = wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = NULL;
	wc.hCursor = NULL;
	wc.hbrBackground = NULL;
	wc.lpszMenuName = NULL;
	wc.lpszClassName = _T("Michelle_CTI_MsgProcess_Window");
	if(RegisterClass(&wc))
	{
		h_gPumpWnd = CreateWindow(wc.lpszClassName, NULL,
			WS_DISABLED, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
		bRet=TRUE;
	}

	return bRet;
}

void GlobalCleanup()
{
	if (h_gPumpWnd)
		DestroyWindow(h_gPumpWnd);

	return;
}

void CMichelleCTI::ClearAPIInfo()
{
	m_lErrCode=0;
	m_ErrType=ET_USER;
	m_ErrMsg="";
}

void CMichelleCTI::CleanDNList()
{
	EnterCriticalSection(&m_csList);
	DNLIST::iterator p;
	for (p=m_dnlist.begin();p!=m_dnlist.end();++p)
	{
		UnregisterDN(*p);
	}
	m_dnlist.clear();
	LeaveCriticalSection(&m_csList);
}


void CMichelleCTI::FatalError()
{
	return;
}

LPDN CMichelleCTI::SearchRegisterdDN(char* dn)
{
	return NULL;
}
BOOL CMichelleCTI::DefaultHandler()
{
	// must fire the ctilink message
	// if error, fire ctidislink
	// else not fire
	return TRUE;
}

STDMETHODIMP CMichelleCTI::get_Initialized(BOOL *pVal)
{
	*pVal=(strlen(m_strServerName)>0);
	return S_OK;
}

STDMETHODIMP CMichelleCTI::get_ErrType(ERRORTYPES *pVal)
{
	*pVal=m_ErrType;
	return S_OK;
}

STDMETHODIMP CMichelleCTI::get_ErrCode(long *pVal)
{
	*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;
}


//initialize the cti server for dns' login
STDMETHODIMP_(BOOL) CMichelleCTI::Initialize(PBXTYPES pbxtype, BSTR server, int port, BSTR name, BSTR pass)
{
//PARAMETERS:
	// pbxtype: 
	// server:  the server name
	// port:  the network type
	// name: logicalIdentifier
	memset(&m_strServerName,0,sizeof(m_strServerName));
	memset(&m_strLogicalIdentifier,0,sizeof(m_strLogicalIdentifier));
	memset(&m_strNetType,0,sizeof(m_strNetType));
	m_dnlist.clear();
	ClearAPIInfo();


	BOOL bRet=FALSE;
	try
	{
		if (B2C(server,m_strServerName,sizeof(m_strServerName))&&
			B2C(name,m_strLogicalIdentifier,sizeof(m_strLogicalIdentifier)))
		{
			switch (port)
			{
			case NT_NetBIOS_NetBEUI:
				strcpy(m_strNetType,"ncacn_nb_nb");
				break;
			case NT_TCPIP:
				strcpy(m_strNetType,"ncacn_ip_tcp");
				break;
			case NT_DECnet:
				strcpy(m_strNetType,"ncacn_dnet_nsp");
				break;
			case NT_NetBIOS_TCPIP:
				strcpy(m_strNetType,"ncacn_nb_tcp");
				break;
			case NT_NAMED_PIPE:
				strcpy(m_strNetType,"ncacn_np");
				break;
			case NT_SPX:
				strcpy(m_strNetType,"ncacn_spx");
				break;
			default:
				strcpy(m_strNetType,"ncacn_ip_tcp");
			}
			bRet=TRUE;
		}else
		{
			m_ErrType=ET_USER;
			m_ErrMsg="Cti initialize failed.";
			m_lErrCode=-1;
		}

	}catch(...)
	{
		m_ErrType=ET_USER;
		m_ErrMsg="Cti initialize failed.";
		m_lErrCode=-1;
	}
	return bRet;
}

STDMETHODIMP_(void) CMichelleCTI::Uninitialize()
{
	ClearAPIInfo();
	CleanDNList();

	memset(&m_strServerName,0,sizeof(m_strServerName));
	memset(&m_strLogicalIdentifier,0,sizeof(m_strLogicalIdentifier));
	memset(&m_strNetType,0,sizeof(m_strNetType));
	
	return;
}

STDMETHODIMP_(LPDN) CMichelleCTI::RegisterDN(BSTR dn, ADDRTYPES type, BSTR acdpos)
{
	//parameters:
	//dn:  the directory number
	//type:  the ctcAssignData.DeviceType
	ClearAPIInfo();

	CDirectoryNumber *pExDN = NULL, *pPosDN = NULL;
	IDirectoryNumber *iExDN = NULL, *iPosDN = NULL;

	char dnBuf[ctcMaxDnLen]={0};
	char acdposBuf[ctcMaxDnLen]={0};

	if (B2C(dn,dnBuf,ctcMaxDnLen))
	{
		if (SearchRegisterdDN(dnBuf)==NULL)
		{// This dn can be registered
			if(SUCCEEDED(CreateClass(&pExDN, &iExDN))) 
			{
				ctcChanId chanelID;
				struct ctcAssignData assignData={0};
				assignData.APIversion=ctcK_CurrentVersion;
				strcpy((char*)assignData.deviceDN,dnBuf);
				switch(type)
				{
				case AT_DN:
				case AT_Position:
					assignData.deviceType=ctcK_Dn;
					break;
				default:
					assignData.deviceType=-1;
					break;
				}

				DWORD dwStatus=ctcAssign(&chanelID,
										   &assignData,
										   m_strServerName,
										   m_strLogicalIdentifier,
										   m_strNetType);
				if (ctcSuccess==dwStatus)
				{
					dwStatus=ctcSetMonitor(chanelID, ctcK_On);
					if (ctcSuccess==dwStatus)
					{
						if (pExDN->Initialize(dnBuf,chanelID,type,this))
						{
							iExDN->AddRef();
							EnterCriticalSection(&m_csList);
							m_dnlist.push_back(pExDN);
							LeaveCriticalSection(&m_csList);

							if(acdpos) 
							{
								iPosDN = RegisterDN(acdpos, AT_Position, NULL);
								if(iPosDN) 
								{
									pPosDN = I2C(iPosDN);
									ATLASSERT(pPosDN);
									pExDN->m_posDN = pPosDN;
									pPosDN->m_extDN = pExDN;
								} 
								else
								{
									EnterCriticalSection(&m_csList);
									m_dnlist.remove(pExDN);
									LeaveCriticalSection(&m_csList);
									UnregisterDN(iExDN);
									iExDN->Release();
									iExDN = NULL;
								}
							}
						}else
						{
							m_lErrCode=CTC_DN_INITIALIZE_FAIL;
							m_ErrType=ET_USER;
							m_ErrMsg="DN initialize failed.";
							iExDN->Release();
							iExDN = NULL;
						}
					}else
					{
						m_lErrCode=dwStatus;
						m_ErrMsg="set monitor on failed";
						m_ErrType=ET_USER;
					}
				}else
				{
					m_lErrCode=dwStatus;
					m_ErrMsg="ctcAssign failed.";
					m_ErrType=ET_USER;
				}
			}
		}else
		{//This dn has been registerd
			m_lErrCode=CTC_DN_REGISTERED;
			m_ErrType=ET_USER;
			m_ErrMsg="This DN can't be registered twince.";
		}
	}
	return iExDN;
}

STDMETHODIMP_(void) CMichelleCTI::UnregisterDN(LPDN dn)
{
	ClearAPIInfo();
	CDirectoryNumber *pDN = I2C(dn);
	if (!dn || !pDN) return;
	if(pDN->m_posDN)
	{
		UnregisterDN(pDN->m_posDN);
		pDN->m_posDN=NULL;
	}
	EnterCriticalSection(&m_csList);
	m_dnlist.remove(pDN);
	LeaveCriticalSection(&m_csList);
	ctcChanId chanelID=pDN->m_channelId;

	ctcSetMonitor(chanelID, ctcK_Off);
	ctcDeassign(chanelID);

	pDN->Uninitialize();
	pDN->Release();
	return ;
}

STDMETHODIMP_(BOOL) CMichelleCTI::Init(BSTR server, int port)
{
	BOOL bRet=FALSE;
	return bRet;
}

STDMETHODIMP_(void) CMichelleCTI::Uninit()
{
	return ;
}

STDMETHODIMP_(void) CMichelleCTI::Login(BSTR AgentID)
{
	return ;
}

STDMETHODIMP_(void) CMichelleCTI::ReportStatus(BSTR AgentID, AGENTSTATES AgentState)
{
	return ;
}

STDMETHODIMP_(void) CMichelleCTI::ReportConfirm(BOOL confirm)
{
	return ;
}

STDMETHODIMP_(void) CMichelleCTI::ReportResult(BSTR ReqID, BOOL result, BSTR reason)
{
	return ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -