487 lines
12 KiB
C++
487 lines
12 KiB
C++
|
#include "precomp.h"
|
|||
|
DEBUG_FILEZONE(ZONE_T120_SAP);
|
|||
|
/*
|
|||
|
* sap.cpp
|
|||
|
*
|
|||
|
* Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
|
|||
|
*
|
|||
|
* Abstract:
|
|||
|
* This is the implementation file for the class CBaseSap. This class is an
|
|||
|
* abstract base class for objects that act as Service Access Points (SAPs)
|
|||
|
* to external applications or the node controller.
|
|||
|
*
|
|||
|
* This class has two main responsibilities. First, it handles many of the
|
|||
|
* administrative tasks that are common to all types of SAPs. These
|
|||
|
* include handling command target registration responsibilities and
|
|||
|
* managing the message queue. It also handles all of the primitives that
|
|||
|
* are common between the Control SAP (CControlSAP class) and Application
|
|||
|
* SAPs (CAppSap class).
|
|||
|
*
|
|||
|
* Protected Member Functions:
|
|||
|
* AddToMessageQueue
|
|||
|
* This routine is used to place messages into the queue of messages
|
|||
|
* to be sent to applications or the node controller.
|
|||
|
* CreateDataToBeDeleted
|
|||
|
* This routine is used to create a structure which holds message data
|
|||
|
* to be delivered to applications or the node controller.
|
|||
|
* CopyDataToGCCMessage
|
|||
|
* This routine is used to fill in the messages to be delivered to
|
|||
|
* applications or the node controller with the necessary data.
|
|||
|
* FreeCallbackMessage
|
|||
|
* This is a virtual function which is used to free up any data which
|
|||
|
* was allocated in order to send a callback message. This function
|
|||
|
* is overloaded in CControlSAP to free messages which were sent to the
|
|||
|
* node controller. It is overloaded in CAppSap to free messages sent
|
|||
|
* to applications.
|
|||
|
*
|
|||
|
* Caveats:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Author:
|
|||
|
* blp
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#include "ms_util.h"
|
|||
|
#include "sap.h"
|
|||
|
#include "conf.h"
|
|||
|
#include "gcontrol.h"
|
|||
|
#include "ernccm.hpp"
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* The node controller SAP handle is always 0.
|
|||
|
*/
|
|||
|
#define NODE_CONTROLLER_SAP_HANDLE 0
|
|||
|
|
|||
|
LRESULT CALLBACK SapNotifyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|||
|
extern HINSTANCE g_hDllInst;
|
|||
|
extern char g_szGCCWndClassName[24];
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* CBaseSap::CBaseSap()
|
|||
|
*
|
|||
|
* Public Function Description
|
|||
|
* This is the CBaseSap constructor. The hash list used to hold command
|
|||
|
* target objects is initialized by this constructor.
|
|||
|
*/
|
|||
|
#ifdef SHIP_BUILD
|
|||
|
CBaseSap::CBaseSap(void)
|
|||
|
:
|
|||
|
CRefCount(),
|
|||
|
#else
|
|||
|
CBaseSap::CBaseSap(DWORD dwStampID)
|
|||
|
:
|
|||
|
CRefCount(dwStampID),
|
|||
|
#endif
|
|||
|
m_nReqTag(GCC_INVALID_TAG)
|
|||
|
{
|
|||
|
//
|
|||
|
// LONCHANC: We have to create the hidden window first
|
|||
|
// because we may need to post PermissionToEnrollIndication
|
|||
|
// to this window for Chat and File Transfer.
|
|||
|
//
|
|||
|
|
|||
|
ASSERT(g_szGCCWndClassName[0] == 'G' &&
|
|||
|
g_szGCCWndClassName[1] == 'C' &&
|
|||
|
g_szGCCWndClassName[2] == 'C');
|
|||
|
//
|
|||
|
// Create a hidden window for confirm and indication.
|
|||
|
// CAppSap or CControlSAP should check for the value of m_hwndNotify.
|
|||
|
//
|
|||
|
m_hwndNotify = CreateWindowA(g_szGCCWndClassName, NULL, WS_POPUP,
|
|||
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|||
|
NULL, NULL, g_hDllInst, NULL);
|
|||
|
|
|||
|
ASSERT(NULL != m_hwndNotify);
|
|||
|
}
|
|||
|
|
|||
|
CBaseSap::~CBaseSap(void)
|
|||
|
{
|
|||
|
//
|
|||
|
// Destroy window and unregister window class
|
|||
|
//
|
|||
|
if (NULL != m_hwndNotify)
|
|||
|
{
|
|||
|
::DestroyWindow(m_hwndNotify);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL CBaseSap::IsThisNodeTopProvider(GCCConfID nConfID)
|
|||
|
{
|
|||
|
BOOL fRet;
|
|||
|
CConf *pConf;
|
|||
|
if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
fRet = pConf->IsConfTopProvider();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
fRet = FALSE;
|
|||
|
}
|
|||
|
return fRet;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GCCNodeID CBaseSap::GetTopProvider(GCCConfID nConfID)
|
|||
|
{
|
|||
|
GCCNodeID uRet;
|
|||
|
CConf *pConf;
|
|||
|
if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
uRet = pConf->GetTopProvider();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
uRet = 0;
|
|||
|
}
|
|||
|
return uRet;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* ConfRosterInquire()
|
|||
|
*
|
|||
|
* Public Function Description
|
|||
|
* This routine is used to retrieve the conference roster. This function
|
|||
|
* just passes this request to the controller via an owner callback. The
|
|||
|
* conference roster is delivered to the requesting command target object
|
|||
|
* in a Conference Roster inquire confirm.
|
|||
|
*/
|
|||
|
GCCError CBaseSap::
|
|||
|
ConfRosterInquire(GCCConfID nConfID, GCCAppSapMsgEx **ppMsgEx)
|
|||
|
{
|
|||
|
GCCError rc;
|
|||
|
CConf *pConf;
|
|||
|
|
|||
|
if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
rc = pConf->ConfRosterInquireRequest(this, ppMsgEx);
|
|||
|
if (GCC_NO_ERROR != rc)
|
|||
|
{
|
|||
|
ERROR_OUT(("CBaseSap::ConfRosterInquire: can't inquire app roster, rc=%u", (UINT) rc));
|
|||
|
// goto MyExit;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WARNING_OUT(("CBaseSap::ConfRosterInquire: invalid conf ID=%u", (UINT) nConfID));
|
|||
|
rc = GCC_INVALID_CONFERENCE;
|
|||
|
}
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* GCCError AppRosterInquire()
|
|||
|
*
|
|||
|
* Public Function Description
|
|||
|
* This routine is used to retrieve a list of application rosters. This
|
|||
|
* function just passes this request to the controller via an owner
|
|||
|
* callback. This list is delivered to the requesting SAP through an
|
|||
|
* Application Roster inquire confirm message.
|
|||
|
*/
|
|||
|
GCCError CBaseSap::
|
|||
|
AppRosterInquire(GCCConfID nConfID,
|
|||
|
GCCSessionKey *pSessionKey,
|
|||
|
GCCAppSapMsgEx **ppMsgEx) // nonzero for sync operation
|
|||
|
|
|||
|
{
|
|||
|
GCCError rc;
|
|||
|
CConf *pConf;
|
|||
|
|
|||
|
if (NULL == (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
WARNING_OUT(("CBaseSap::AppRosterInquire: invalid conf ID=%u", (UINT) nConfID));
|
|||
|
rc = GCC_INVALID_CONFERENCE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CAppRosterMsg *pAppRosterMsg;
|
|||
|
rc = pConf->AppRosterInquireRequest(pSessionKey, &pAppRosterMsg);
|
|||
|
if (GCC_NO_ERROR == rc)
|
|||
|
{
|
|||
|
AppRosterInquireConfirm(nConfID, pAppRosterMsg, GCC_RESULT_SUCCESSFUL, ppMsgEx);
|
|||
|
pAppRosterMsg->Release();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ERROR_OUT(("CBaseSap::AppRosterInquire: can't inquire app roster, rc=%u", (UINT) rc));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* ConductorInquire()
|
|||
|
*
|
|||
|
* Public Function Description
|
|||
|
* This routine is called in order to retrieve conductorship information.
|
|||
|
* The conductorship information is returned in the confirm.
|
|||
|
*
|
|||
|
*/
|
|||
|
GCCError CBaseSap::ConductorInquire(GCCConfID nConfID)
|
|||
|
{
|
|||
|
GCCError rc;
|
|||
|
CConf *pConf;
|
|||
|
|
|||
|
/*
|
|||
|
** Make sure the conference exists in the internal list before forwarding
|
|||
|
** the call on to the conference object.
|
|||
|
*/
|
|||
|
if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
rc = pConf->ConductorInquireRequest(this);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rc = GCC_INVALID_CONFERENCE;
|
|||
|
}
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* AppInvoke()
|
|||
|
*
|
|||
|
* Public Function Description
|
|||
|
* This routine is called in order to invoke other applications at remote
|
|||
|
* nodes. The request is passed on to the appropriate Conference objects.
|
|||
|
*/
|
|||
|
GCCError CBaseSap::
|
|||
|
AppInvoke(GCCConfID nConfID,
|
|||
|
GCCAppProtEntityList *pApeList,
|
|||
|
GCCSimpleNodeList *pNodeList,
|
|||
|
GCCRequestTag *pnReqTag)
|
|||
|
{
|
|||
|
GCCError rc = GCC_NO_ERROR;
|
|||
|
CInvokeSpecifierListContainer *invoke_list;
|
|||
|
UINT i;
|
|||
|
CConf *pConf;
|
|||
|
|
|||
|
DebugEntry(CBaseSap::AppInvoke);
|
|||
|
|
|||
|
if (NULL == pApeList || NULL == pNodeList || NULL == pnReqTag)
|
|||
|
{
|
|||
|
rc = GCC_INVALID_PARAMETER;
|
|||
|
goto MyExit;
|
|||
|
}
|
|||
|
|
|||
|
*pnReqTag = GenerateRequestTag();
|
|||
|
|
|||
|
if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
|
|||
|
{
|
|||
|
if (pApeList->cApes != 0)
|
|||
|
{
|
|||
|
/*
|
|||
|
** Create an object which is used to hold the list of application
|
|||
|
** invoke specifiers.
|
|||
|
*/
|
|||
|
DBG_SAVE_FILE_LINE
|
|||
|
invoke_list = new CInvokeSpecifierListContainer(
|
|||
|
pApeList->cApes,
|
|||
|
pApeList->apApes,
|
|||
|
&rc);
|
|||
|
if ((invoke_list != NULL) && (rc == GCC_NO_ERROR))
|
|||
|
{
|
|||
|
/*
|
|||
|
** Here we must check the destination node list for invalid
|
|||
|
** node IDs.
|
|||
|
*/
|
|||
|
for (i = 0; i < pNodeList->cNodes; i++)
|
|||
|
{
|
|||
|
if (pNodeList->aNodeIDs[i] < MINIMUM_USER_ID_VALUE)
|
|||
|
{
|
|||
|
rc = GCC_INVALID_MCS_USER_ID;
|
|||
|
goto MyExit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
** If no error has occurred, send the request on to the
|
|||
|
** command target (conference) object.
|
|||
|
*/
|
|||
|
rc = pConf->AppInvokeRequest(invoke_list, pNodeList, this, *pnReqTag);
|
|||
|
|
|||
|
/*
|
|||
|
** Free here instead of delete in case the object
|
|||
|
** must persist.
|
|||
|
*/
|
|||
|
invoke_list->Release();
|
|||
|
}
|
|||
|
else if (invoke_list == NULL)
|
|||
|
{
|
|||
|
ERROR_OUT(("CBaseSap::AppInvoke: Error creating new AppInvokeSpecList"));
|
|||
|
rc = GCC_ALLOCATION_FAILURE;
|
|||
|
// goto MyExit;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
invoke_list->Release();
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rc = GCC_BAD_NUMBER_OF_APES;
|
|||
|
// goto MyExit;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rc = GCC_INVALID_CONFERENCE;
|
|||
|
// goto MyExit;
|
|||
|
}
|
|||
|
|
|||
|
MyExit:
|
|||
|
|
|||
|
DebugExitINT(CBaseSap::AppInvoke, rc);
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
GCCRequestTag CBaseSap::GenerateRequestTag(void)
|
|||
|
{
|
|||
|
GCCRequestTag nNewReqTag;
|
|||
|
|
|||
|
ASSERT(sizeof(GCCRequestTag) == sizeof(LONG));
|
|||
|
|
|||
|
nNewReqTag = ++m_nReqTag;
|
|||
|
if (GCC_INVALID_TAG == nNewReqTag)
|
|||
|
{
|
|||
|
nNewReqTag = ++m_nReqTag;
|
|||
|
}
|
|||
|
|
|||
|
// we only take the lower word
|
|||
|
return (nNewReqTag & 0x0000FFFFL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// SapNotifyWndProc() is used to notify the sap clients (app in app sap,
|
|||
|
// node controller in control sap) in their respective thread.
|
|||
|
// The window handle is in CSap::m_hwndNotify.
|
|||
|
//
|
|||
|
LRESULT CALLBACK
|
|||
|
SapNotifyWndProc
|
|||
|
(
|
|||
|
HWND hwnd,
|
|||
|
UINT uMsg,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam
|
|||
|
)
|
|||
|
{
|
|||
|
LRESULT wnd_rc = 0;
|
|||
|
|
|||
|
if (CSAPMSG_BASE <= uMsg && uMsg < CSAPCONFIRM_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
ASSERT(CSAPMSG_BASE + MSG_RANGE == CSAPCONFIRM_BASE);
|
|||
|
if (uMsg < CSAPMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
if (((CControlSAP *) lParam) == g_pControlSap)
|
|||
|
{
|
|||
|
g_pControlSap->NotifyProc((GCCCtrlSapMsgEx *) wParam);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WARNING_OUT(("SapNotifyWndProc: invalid control sap, uMsg=%u, lParam=0x%p, g_pControlSap=0x%p",
|
|||
|
uMsg, lParam, g_pControlSap));
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ASSERT(CSAPCONFIRM_BASE <= uMsg && uMsg < CSAPCONFIRM_BASE + MSG_RANGE);
|
|||
|
if (NULL != g_pControlSap)
|
|||
|
{
|
|||
|
g_pControlSap->WndMsgHandler(uMsg, wParam, lParam);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WARNING_OUT(("SapNotifyWndProc: invalid control sap, uMsg=%u, wParam=0x%x, lParam=0x%x",
|
|||
|
uMsg, (UINT) wParam, (UINT) lParam));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
if (ASAPMSG_BASE <= uMsg && uMsg < ASAPMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
ASSERT(uMsg == ASAPMSG_BASE + (UINT) ((GCCAppSapMsgEx *) wParam)->Msg.eMsgType);
|
|||
|
((CAppSap *) lParam)->NotifyProc((GCCAppSapMsgEx *) wParam);
|
|||
|
}
|
|||
|
else
|
|||
|
if (CONFMSG_BASE <= uMsg && uMsg < CONFMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
::EnterCriticalSection(&g_csGCCProvider);
|
|||
|
if (NULL != ((CConf *) lParam))
|
|||
|
{
|
|||
|
((CConf *) lParam)->WndMsgHandler(uMsg);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ERROR_OUT(("SapNotifyWndProc: invalid conf object, uMsg=%u, lParam=0x%x",
|
|||
|
uMsg, (UINT) lParam));
|
|||
|
}
|
|||
|
::LeaveCriticalSection(&g_csGCCProvider);
|
|||
|
}
|
|||
|
else
|
|||
|
if (GCTRLMSG_BASE <= uMsg && uMsg < GCTRLMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
::EnterCriticalSection(&g_csGCCProvider);
|
|||
|
if (((GCCController *) lParam) == g_pGCCController)
|
|||
|
{
|
|||
|
g_pGCCController->WndMsgHandler(uMsg);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WARNING_OUT(("SapNotifyWndProc: invalid gcc controller, uMsg=%u, lParam=0x%p, g_pGCCController=0x%p",
|
|||
|
uMsg, lParam, g_pGCCController));
|
|||
|
}
|
|||
|
::LeaveCriticalSection(&g_csGCCProvider);
|
|||
|
}
|
|||
|
else
|
|||
|
if (MCTRLMSG_BASE <= uMsg && uMsg < MCTRLMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
void CALLBACK MCSCallBackProcedure (UINT, LPARAM, PVoid);
|
|||
|
MCSCallBackProcedure (uMsg - MCTRLMSG_BASE, lParam, NULL);
|
|||
|
/*
|
|||
|
* If the msg contains user data, we need to unlock the
|
|||
|
* memory with it.
|
|||
|
*/
|
|||
|
UnlockMemory ((PMemory) wParam);
|
|||
|
}
|
|||
|
else
|
|||
|
if (NCMSG_BASE <= uMsg && uMsg < NCMSG_BASE + MSG_RANGE)
|
|||
|
{
|
|||
|
if (((DCRNCConferenceManager *) wParam) == g_pNCConfMgr)
|
|||
|
{
|
|||
|
g_pNCConfMgr->WndMsgHandler(uMsg, lParam);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WARNING_OUT(("SapNotifyWndProc: invalid NC ConfMgr, uMsg=%u, lParam=0x%p, g_pNCConfMgr=0x%p",
|
|||
|
uMsg, lParam, g_pNCConfMgr));
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
switch (uMsg)
|
|||
|
{
|
|||
|
case WM_CLOSE:
|
|||
|
DestroyWindow(hwnd);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return wnd_rc;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|