📄 tsapi.cpp
字号:
// Tsapi.cpp : interface to TSAPI Tserver.
//
// This file handles the hidden TSAPI window
//
#include "stdafx.h"
#include "windowsx.h"
#include "Tsapi.h"
#include "utilities.h"
#include "global.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// First, there are the CTsapiDevice methods.
//
// This class is referenced by the TSAPI window class (CTsapiWnd).
// It handles:
// 1. tracking of the window that handles the TSAPI events for each device known
// by the CTsapiWnd
// 3. tracking of the monitor cross reference ID for the current monitoring session
// for each device known by the CTsapiWnd
// 2. tracking of all of the calls and connections for each device known by the
// CTsapiWnd
//
// Note that this sample only implements 1 device tracking. The CTsapiWnd here can
// only track a single device and this memory is hard-coded.
// Note that this sample hard-codes the number of calls and connections that the
// device can support.
CTsapiDevice::CTsapiDevice()
{
m_MonitorCrossRefID = 0;
m_pWnd = 0;
for(int i=0; i<MAX_CALLS_AT_DEVICE; i++)
{
// an empty call ID indicates a free entry
for(int j=0; j<MAX_DEVICES_IN_CALL; j++)
{
m_ConnIDList[i][j].callID = 0;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CTsapiWnd object
CTsapiWnd theTsapiWnd;
// For non-MFC folks, this map replaces the large "switch" statement found in
// straight C Windows programs. The ON_MESSAGE() line can be read as
// "when a message of type {first argument} is recieved, call
// the method {second argument}"
BEGIN_MESSAGE_MAP(CTsapiWnd, CWnd)
ON_MESSAGE(WM_TSAPIMSG, OnTsapiMsg)
END_MESSAGE_MAP()
CTsapiWnd::CTsapiWnd()
{
m_AcsHandle = 0;
m_EventBufPtr = (CSTAEvent_t*)&m_EventBuf;
m_EventBufSize = sizeof(CSTAEvent_t);
m_AttPrivateData.length = sizeof(m_AttPrivateData.data);
}
CTsapiWnd::~CTsapiWnd()
{
// free any allocated memory
if(m_EventBufPtr != (CSTAEvent_t*)&m_EventBuf)
{
GlobalFreePtr(m_EventBufPtr);
}
// terminate the stream connection
if(m_AcsHandle)
{
acsAbortStream(m_AcsHandle, 0);
}
}
// public interface to the private CreateEx() method
void CTsapiWnd::DoCreate()
{
CreateEx(0, AfxRegisterWndClass(CS_GLOBALCLASS), "", 0, 0, 0, 0, 0, 0, 0);
}
// This method is called when a TSAPI message (WM_TSAPIMSG) is received.
// The WM_TSAPIMSG is just a notification that there is a message waiting in the
// CSTA DLL. Use acsGetEventPoll() to retrieve the actual message.
//
// If the static buffer is too small for the message, dynamically allocate a buffer
// that is big enough. Debug tracing should be used to fine tune the size of the
// static buffer such that a dynamic buffer doesn't need to be created every time.
// The event is then forwarded to the appropriate window.
// If there are more events waiting (numEvents > 0), then post ourselves another
// WM_TSAPIMSG. This is done instead of a while(numEvents >0) loop to allow for
// processing of other windows events and to allow for the TSAPI event to process-to-
// completion
LRESULT CTsapiWnd::OnTsapiMsg(WPARAM wParam, LPARAM lParam)
{
static char func[]="CTsapiWnd::OnTsapiMsg";
RetCode_t rc;
unsigned short numEvents;
//AfxMessageBox("Event received");
// free any previously allocated memory before continuing
if(m_EventBufPtr && (m_EventBufPtr != (CSTAEvent_t*)&m_EventBuf))
{
GlobalFreePtr(m_EventBufPtr);
m_EventBufPtr = (CSTAEvent_t*)&m_EventBuf;
}
// attempt to retrieve the event from the CSTA DLL
m_EventBufSize = sizeof(m_EventBuf);
// rc = acsGetEventPoll(m_AcsHandle, &m_EventBuf, &m_EventBufSize, 0, &numEvents);
m_AttPrivateData.length = 0;
rc = acsGetEventPoll(
m_AcsHandle, // the handle returned by acsOpenStream()
m_EventBufPtr, // a pointer to the event buffer which will be filled by this call
&m_EventBufSize, // a pointer to the size of the above event buffer
(PrivateData_t*) &m_AttPrivateData, // a pointer to the private data buffer which will be filled by this call
&numEvents // a pointer to the number of events left in the queue
);
if(rc != 0)
{
// check if rc indicates no messages to get - that is ok
if(rc == ACSERR_NOMESSAGE)
{
return 0;
}
else if(rc == ACSERR_UBUFSMALL) // static buffer too small - allocate larger one
{
// space required is in the return parameter
m_EventBufPtr = (CSTAEvent_t*)GlobalAllocPtr(GHND, m_EventBufSize);
if(!m_EventBufPtr)
{
m_TsapiController->PostMessage(WM_TSAPIFAILURE, rc, 0);
return (LRESULT)rc;
}
CString reqStr;
reqStr.Format( "acsGetEventPoll(acsHandle=%d eventBufSize=%d) 2", m_AcsHandle, m_EventBufSize );
// try to get the event out of the queue again, into the newly allocated memory
rc = acsGetEventPoll(m_AcsHandle, m_EventBufPtr, &m_EventBufSize, (PrivateData_t*) &m_AttPrivateData, &numEvents);
DBG1_OUT( func, "%s rc=%d numEvents=%d eventBufSize=%d", reqStr.GetString(), rc, ( rc == 0 ? numEvents : 0 ), ( rc == ACSERR_UBUFSMALL ? m_EventBufSize : 0 ) );
if(rc != 0)
{
// not you can do here...
// free the allocated memory
GlobalFreePtr(m_EventBufPtr);
m_EventBufPtr = 0;
m_TsapiController->PostMessage(WM_TSAPIFAILURE, rc, 0);
return (LRESULT)rc;
}
}
else
{
// not much you can do here...
m_TsapiController->PostMessage(WM_TSAPIFAILURE, rc, 0);
return (LRESULT)rc;
}
}
else
{
m_EventBufPtr = (CSTAEvent_t*)&m_EventBuf;
}
// at this point acsGetEventPoll() got an event
// now lets figure out what to do with the event
// until we determine otherwise, lets assume that this event does NOT contain private data
m_AttEvent.eventType = 0;
// handle each class of events slightly differently
switch(m_EventBufPtr->eventHeader.eventClass)
{
case ACSUNSOLICITED:
{
// ACS Unsolicited events are all handled by the TSAPI controller - the
// window that wants to be responsible for memory clean-up and stream failure
// handling. Forward all of these events to the controller.
// this is a sendmessage(), not a postmessage() because the operation has to
// process to completion - or at least until the event buffer is not needed
CWnd* pWnd = (CWnd*)m_EventBufPtr->event.acsConfirmation.invokeID;
if(::IsWindow(pWnd->m_hWnd))
{
pWnd->SendMessage(WM_TSAPIACSUNSOLICITED, 0, 0);
// m_TsapiController->SendMessage(WM_TSAPIACSUNSOLICITED, 0, 0);
}
break;
}
case ACSCONFIRMATION:
{
// ACS Confirmation events are all handled by the window that is passed in via
// the invoke ID. Forward all of these events to that window.
// get CWnd pointer out of invokeID, send message
CWnd* pWnd = (CWnd*)m_EventBufPtr->event.acsConfirmation.invokeID;
if(::IsWindow(pWnd->m_hWnd))
{
// this is a sendmessage(), not a postmessage() because the operation has to
// process to completion - or at least until the event buffer is not needed
pWnd->SendMessage(WM_TSAPIACSCONFIRMATION, 0, 0);
}
break;
}
case CSTACONFIRMATION:
{
CWnd* pWnd = (CWnd*)m_EventBufPtr->event.acsConfirmation.invokeID;
if(::IsWindow(pWnd->m_hWnd))
{
if(m_AttPrivateData.length > 0)
{
if (attPrivateData( &m_AttPrivateData, &m_AttEvent ) != ACSPOSITIVE_ACK) {
// we are unable to get private data. still send confirmation
m_TsapiController->SendMessage(WM_TSAPICSTACONFIRMATION, 0, 0);
} else
m_TsapiController->SendMessage(WM_TSAPICSTACONFIRMATION, 0, 0);
} else
m_TsapiController->SendMessage(WM_TSAPICSTACONFIRMATION, 0, 0);
}
break;
}
case CSTAUNSOLICITED:
{
// CSTA Unsolicited events are all handled by the window that is associated with
// the device whose monitor cross reference ID matches the one received in this
// event. Forward all of these events to that window.
// get CTsapiDevice pointer by looking for a matching monitor cross reference ID
//m_EventBufPtr->event.cstaUnsolicited.monitorCrossRefId;
// get the CWnd pointer out of CTsapiDevice and make sure the window is still there
CWnd* pWnd = (CWnd*)m_EventBufPtr->event.acsConfirmation.invokeID;
// pWnd->SendMessage(WM_TSAPICSTAUNSOLICITED, 0, 0);
m_TsapiController->SendMessage(WM_TSAPICSTAUNSOLICITED, 0, 0);
break;
}
case CSTAREQUEST:
if (attPrivateData( &m_AttPrivateData, &m_AttEvent ) != ACSPOSITIVE_ACK) {
/* Decoding error */
printf(" Decoding failed\n");
} else {
printf("Decoding successful\n");
m_TsapiController->SendMessage(WM_TSAPICSTAREQUEST, 0, 0);
}
break;
default:
break;
}
// If there are additional TSAPI events to process, post ourselves another message.
if(numEvents > 0)
{
PostMessage(WM_TSAPIMSG, 0, 0);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -