📄 opentsrv.cpp
字号:
// opentsrv.cpp : implementation file
//
// This file handles the Open Tserver dialog
//
#include "stdafx.h"
#include "resource.h" // replace with theApp header if needed
#include "opentsrv.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COpenTsrv dialog
COpenTsrv::COpenTsrv(CWnd* pParent /*=NULL*/)
: CDialog(COpenTsrv::IDD, pParent)
{
//{{AFX_DATA_INIT(COpenTsrv)
m_Login = _T("");
m_Password = _T("");
m_Tserver = _T("");
m_DeviceID = _T("");
//}}AFX_DATA_INIT
}
// For non-MFC folks, this is a helper routine for passing data back-and-forth
// from this class to the Open Tserver dialog.
void COpenTsrv::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COpenTsrv)
DDX_Control(pDX, IDC_TSERVERLIST, m_TserverListControl);
DDX_Control(pDX, IDOK, m_OKControl);
DDX_Text(pDX, IDC_LOGIN, m_Login);
DDV_MaxChars(pDX, m_Login, 48);
DDX_Text(pDX, IDC_PASSWORD, m_Password);
DDV_MaxChars(pDX, m_Password, 48);
DDX_CBString(pDX, IDC_TSERVERLIST, m_Tserver);
DDX_Text(pDX, IDC_DEVICEID, m_DeviceID);
DDV_MaxChars(pDX, m_DeviceID, 64);
//}}AFX_DATA_MAP
}
// For non-MFC folks, this map replaces the large "switch" statement found in
// straight C Windows programs. The ON_MESSAGE() lines were added manually.
// Read them as "when a message of type {first argument} is received, call
// the method {second argument}"
BEGIN_MESSAGE_MAP(COpenTsrv, CDialog)
ON_MESSAGE(WM_TSAPIACSCONFIRMATION, OnTsapiAcsConfirmation)
ON_MESSAGE(WM_TSAPICSTACONFIRMATION, OnTsapiCstaConfirmation)
//{{AFX_MSG_MAP(COpenTsrv)
ON_CBN_SELCHANGE(IDC_TSERVERLIST, OnSelchangeTserverlist)
ON_EN_CHANGE(IDC_LOGIN, OnChangeLogin)
ON_EN_CHANGE(IDC_DEVICEID, OnChangeDeviceid)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COpenTsrv message handlers
extern "C"
{
// this callback function is used by the csta dll (via acsEnumServerNames)
// lParam contains a pointer to the combo box on the Open Tserver dialog
// name contains 1 registered Tserver service - put it into the combo box.
Boolean AddToList(char* name, unsigned long lParam)
{
CComboBox* lBox = (CComboBox*)lParam;
return(lBox->AddString(name) >= 0);
}
}
// dialog initialization
BOOL COpenTsrv::OnInitDialog()
{
CDialog::OnInitDialog();
CenterWindow();
// want CSTA-type services
// AddToList() is the callback function
// pass the address of the combo box to be returned in the AddToList() callback
acsEnumServerNames(ST_CSTA, AddToList, (unsigned long)(CComboBox*)&m_TserverListControl);
UpdateData(FALSE);
// must have a Tserver, login and device (password may also be needed, depending on
// the Tserver selected)
m_OKControl.EnableWindow(!m_Tserver.IsEmpty() && !m_Login.IsEmpty() && !m_DeviceID.IsEmpty());
return TRUE; // return TRUE unless you set the focus to a control
}
// for every change to the Login ID field, this method is called
void COpenTsrv::OnChangeLogin()
{
UpdateData(TRUE);
// must have a Tserver, login and device (password may also be needed, depending on
// the Tserver selected)
m_OKControl.EnableWindow(!m_Tserver.IsEmpty() && !m_Login.IsEmpty() && !m_DeviceID.IsEmpty());
}
// as each Tserver in the Tserver combo box is selected, this method is called
void COpenTsrv::OnSelchangeTserverlist()
{
UpdateData(TRUE); // get server name out of the combo box control
// get authorization information for the selected Tserver
ACSAuthInfo_t authInfo;
if(acsQueryAuthInfo((ServerID_t*)(LPCTSTR)m_Tserver, &authInfo) == ACSPOSITIVE_ACK)
{
switch(authInfo.authType)
{
case AUTH_LOGIN_ID_ONLY:
case AUTH_LOGIN_ID_IS_DEFAULT:
case ANY_LOGIN_ID:
// no login or password needed
m_Login = authInfo.authLoginID;
UpdateData(FALSE);
break;
default: // login (and maybe password) are needed
break;
}
}
// must have a Tserver, login and device (password may also be needed, depending on
// the Tserver selected)
m_OKControl.EnableWindow(!m_Tserver.IsEmpty() && !m_Login.IsEmpty() && !m_DeviceID.IsEmpty());
}
// for every change to the Device ID field, this method is called
void COpenTsrv::OnChangeDeviceid()
{
UpdateData(TRUE);
// must have a Tserver, login and device (password may also be needed, depending on
// the Tserver selected)
m_OKControl.EnableWindow(!m_Tserver.IsEmpty() && !m_Login.IsEmpty() && !m_DeviceID.IsEmpty());
}
// If the OK button is pressed, this method is called
void COpenTsrv::OnOK()
{
if(!UpdateData(TRUE))
{
return;
}
// attempt to open a stream to the selected Tserver
ServerID_t advertisingName;
lstrcpy(advertisingName, m_Tserver);
LoginID_t loginID;
lstrcpy(loginID, m_Login);
Passwd_t passwd;
lstrcpy(passwd, m_Password);
AppName_t appname;
lstrcpy(appname, "TSAPI Sample");
Version_t version;
lstrcpy(version, "TS1-2");
// before opening the stream, create the hidden window which will process all
// of the TSAPI events.
m_TsapiWndPtr = new CTsapiWnd;
m_TsapiWndPtr->m_TsapiController = m_TsapiController;
m_TsapiWndPtr->DoCreate();
// The application will generate the invoke IDs.
// Use a pointer to the window here (and for all ACS requests) for the invoke ID -
// this specifies which window applies to this request. The TSAPI window looks at
// the invoke ID of all ACS events and assumes they are window pointers. The event is
// then forwarded to that window.
RetCode_t rc = acsOpenStream(&m_TsapiWndPtr->m_AcsHandle, APP_GEN_ID,
(InvokeID_t)this, ST_CSTA, &advertisingName, &loginID, &passwd, &appname,
ACS_LEVEL1, &version, 10, 5, 50, 5, 0);
if(rc < 0)
{
// failure for some reason, specified in rc as a RetCode_t (defined in acs.h).
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("open stream failed");
return;
}
// no conf events are being processed yet, so don't wait for it yet...
// set up event notification on this acs stream
// all TSAPI events will be sent to the TSAPI window (m_TsapiWndPtr) via the
// WM_TSAPIMSG message.
// The last parameter set to FALSE indicates that the application will handle draining
// the TSAPI event queue from the CSTA dll. TRUE would indicate the dll should send a
// WM_TSAPIMSG per TSAPI event. With FALSE, the dll sends a WM_TSAPIMSG only when the
// TSAPI event queue goes from empty to non-empty. This allows the application to drain
// the TSAPI event queue at its own pace, without overflowing the Windows message queue.
rc = acsEventNotify(m_TsapiWndPtr->m_AcsHandle, m_TsapiWndPtr->GetSafeHwnd(), WM_TSAPIMSG, FALSE);
if(rc < 0)
{
// failure for some reason, specified in rc as a RetCode_t (defined in acs.h).
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("event notify failed");
return;
}
// once the event notify is processed, conf events will come back from the
// TSAPI DLL
}
// This method is called when an ACS Confirmation Event is received that is forwarded to
// this dialog.
LRESULT COpenTsrv::OnTsapiAcsConfirmation(WPARAM wParam, LPARAM lParam)
{
// this dialog should either get an open stream conf event or
// a universal failure event
switch(m_TsapiWndPtr->m_EventBufPtr->eventHeader.eventType)
{
case ACS_OPEN_STREAM_CONF:
// this is what we want...
break;
case ACS_UNIVERSAL_FAILURE_CONF:
// failure for some reason. This could be invalid login/password, no permissions,
// or several other failure codes (listed in acsdefs.h).
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("open stream failed");
return 0;
default:
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("unexpected response to acsOpenStream");
return 0;
}
// now, attempt to put a device monitor on the specified device. No filtering is requested,
// but the PBX may place filtering on the monitor. You will be notified of the filtering
// placed on the monitor in the monitor confirmation event.
CSTAMonitorFilter_t noFilter;
noFilter.call = 0;
noFilter.feature = 0;
noFilter.agent = 0;
noFilter.maintenance = 0;
noFilter.privateFilter = 0;
// create a device record in the TSAPI window for this device. This device record will be
// used to track all calls for this device and is also used to determine which window should
// handle the TSAPI events that are received for each device.
DeviceID_t deviceID;
lstrcpy(deviceID, m_DeviceID);
CTsapiDevice* pTsapi = m_TsapiWndPtr->CreateDeviceRecord(deviceID);
if(!pTsapi)
{
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("no memory for device");
return 0;
}
// For now, process events for this device in this window
pTsapi->SetWndPtr(this);
// Use a pointer to the device record here (and for all CSTA requests) for the invoke ID -
// this specifies which device record applies to this request. The TSAPI window looks at
// the invoke ID of all CSTA CONFIRMATION events and assumes they are device record pointers.
// That record is then used to determine which window should handle events for that device.
// The event is then forwarded to that window.
RetCode_t rc = cstaMonitorDevice(m_TsapiWndPtr->m_AcsHandle,
(InvokeID_t)pTsapi, &deviceID, &noFilter, NULL);
if(rc < 0)
{
// failure for some reason, specified in rc as a RetCode_t (defined in acs.h).
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("monitor device failed");
return 0;
}
return 0;
}
// This method is called when an CSTA Confirmation Event is received that is forwarded to
// this dialog.
LRESULT COpenTsrv::OnTsapiCstaConfirmation(WPARAM wParam, LPARAM lParam)
{
// this dialog should either get a monitor conf event or
// a universal failure event
switch(m_TsapiWndPtr->m_EventBufPtr->eventHeader.eventType)
{
case CSTA_MONITOR_CONF:
// this is what we want...
break;
case CSTA_UNIVERSAL_FAILURE_CONF:
// failure for some reason. failure codes are listed in cstadefs.h.
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("monitor device failed");
return 0;
default:
acsAbortStream(m_TsapiWndPtr->m_AcsHandle, NULL);
delete m_TsapiWndPtr;
m_TsapiWndPtr = 0;
AfxMessageBox("unexpected response to cstaMonitorDevice");
return 0;
}
// The lParam is a device record pointer. Set the monitor cross reference ID for that
// device to the cross reference ID recieved here. The TSAPI window looks at the cross
// reference ID of all CSTA UNSOLICITED events and retrieves the associated device record.
// That record is then used to determine which window should handle events for that device.
// The event is then forwarded to that window.
((CTsapiDevice*)lParam)->SetCrossRefID(m_TsapiWndPtr->m_EventBufPtr->event.cstaConfirmation.u.monitorStart.monitorCrossRefID);
// now the open tserver dialog can be dismissed.
// The calling class is now responsible for the CTsapiWnd memory clean-up
EndDialog(IDOK);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -