windows-nt/Source/XPSP1/NT/enduser/netmeeting/t120/mst120/sap.cpp
2020-09-26 16:20:57 +08:00

487 lines
12 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}