windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/t120app.cpp
2020-09-26 16:20:57 +08:00

1744 lines
51 KiB
C++
Raw 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"
#include "t120app.h"
BOOL InitAppletSDK(void)
{
CheckStructCompatible();
return TRUE;
}
void CleanupAppletSDK(void)
{
}
void CALLBACK T120AppletSessionCallback
(
T120AppletSessionMsg *pMsg
)
{
CNmAppletSession *pSession = (CNmAppletSession *) pMsg->pSessionContext;
if (NULL != pSession)
{
pSession->T120Callback(pMsg);
}
}
void CALLBACK T120AppletCallback
(
T120AppletMsg *pMsg
)
{
CNmAppletObj *pApplet = (CNmAppletObj *) pMsg->pAppletContext;
if (NULL != pApplet)
{
pApplet->T120Callback(pMsg);
}
}
//////////////////////////////////////////////////
//
// CNmAppletSession
//
CNmAppletSession::CNmAppletSession
(
CNmAppletObj *pApplet,
IT120AppletSession *pSession,
BOOL fAutoJoin
)
:
m_cRef(1),
m_pApplet(pApplet),
m_pT120SessReq(NULL),
m_pT120Session(pSession),
m_pNotify(NULL),
m_fAutoJoin(fAutoJoin)
{
m_pApplet->AddRef();
pSession->Advise(T120AppletSessionCallback, m_pApplet, this);
}
CNmAppletSession::~CNmAppletSession(void)
{
ASSERT(0 == m_cRef);
m_pApplet->Release();
if (NULL != m_pT120Session)
{
m_pT120Session->ReleaseInterface();
m_pT120Session = NULL;
}
}
//////////////////////////////////////////////////
//
// IUnknown @ CNmAppletSession
//
HRESULT CNmAppletSession::QueryInterface
(
REFIID riid,
void **ppv
)
{
if (NULL != ppv)
{
*ppv = NULL;
if (riid == IID_IAppletSession || riid == IID_IUnknown)
{
*ppv = (IAppletSession *) this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
return E_POINTER;
}
ULONG CNmAppletSession::AddRef(void)
{
::InterlockedIncrement(&m_cRef);
return (ULONG) m_cRef;
}
ULONG CNmAppletSession::Release(void)
{
ASSERT(m_cRef > 0);
if (::InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return (ULONG) m_cRef;
}
//////////////////////////////////////////////////
//
// Basic Info @ CNmAppletSession
//
HRESULT CNmAppletSession::GetConfID
(
AppletConfID *pnConfID
)
{
if (NULL != m_pT120Session)
{
*pnConfID = m_pT120Session->GetConfID();
return S_OK;
}
return APPLET_E_NO_SERVICE;
}
HRESULT CNmAppletSession::IsThisNodeTopProvider
(
BOOL *pfTopProvider
)
{
if (NULL != m_pT120Session)
{
*pfTopProvider = m_pT120Session->IsThisNodeTopProvider();
return S_OK;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Join Conference @ CNmAppletSession
//
HRESULT CNmAppletSession::Join
(
AppletSessionRequest *pRequest
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
if (NULL == m_pT120SessReq)
{
m_pT120SessReq = ::AllocateJoinSessionRequest(pRequest);
if (NULL != m_pT120SessReq)
{
T120Error rc = m_pT120Session->Join(m_pT120SessReq);
ASSERT(T120_NO_ERROR == rc);
if (T120_NO_ERROR == rc)
{
return S_OK;
}
::FreeJoinSessionRequest(m_pT120SessReq);
m_pT120SessReq = NULL;
return APPLET_E_SERVICE_FAIL;
}
return APPLET_E_INVALID_JOIN_REQUEST;
}
return APPLET_E_ALREADY_JOIN;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
HRESULT CNmAppletSession::Leave(void)
{
if (NULL != m_pT120Session)
{
if (m_fAutoJoin)
{
m_pT120Session->Leave();
m_fAutoJoin = FALSE;
return S_OK;
}
else
if (NULL != m_pT120SessReq)
{
m_pT120Session->Leave();
::FreeJoinSessionRequest(m_pT120SessReq);
m_pT120SessReq = NULL;
return S_OK;
}
return APPLET_E_NOT_JOINED;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Send Data @ CNmAppletSession
//
HRESULT CNmAppletSession::SendData
(
BOOL fUniformSend,
AppletChannelID nChannelID,
AppletPriority ePriority,
ULONG cbBufSize,
BYTE *pBuffer // size_is(cbBufSize)
)
{
if (NULL != m_pT120Session)
{
if (cbBufSize && NULL != pBuffer)
{
T120Error rc = m_pT120Session->SendData(
fUniformSend ? UNIFORM_SEND_DATA : NORMAL_SEND_DATA,
nChannelID,
ePriority,
pBuffer,
cbBufSize,
APP_ALLOCATION);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return E_INVALIDARG;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Invoke Applet @ CNmAppletSession
//
HRESULT CNmAppletSession::InvokeApplet
(
AppletRequestTag *pnReqTag,
AppletProtocolEntity *pAPE,
ULONG cNodes,
AppletNodeID aNodeIDs[] // size_is(cNodes)
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
if (NULL != pAPE && NULL != pnReqTag)
{
// set up node list
GCCSimpleNodeList NodeList;
NodeList.cNodes = cNodes;
NodeList.aNodeIDs = aNodeIDs;
// set up ape list
GCCAppProtEntityList APEList;
APEList.cApes = 1;
APEList.apApes = (T120APE **) &pAPE;
T120Error rc = m_pT120Session->InvokeApplet(&APEList, &NodeList, pnReqTag);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return E_POINTER;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
//////////////////////////////////////////////////
//
// Inquiry @ CNmAppletSession
//
HRESULT CNmAppletSession::InquireRoster
(
AppletSessionKey *pSessionKey
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
T120Error rc = m_pT120Session->InquireRoster((T120SessionKey *) pSessionKey);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
//////////////////////////////////////////////////
//
// Registry Services @ CNmAppletSession
//
HRESULT CNmAppletSession::RegistryRequest
(
AppletRegistryRequest *pRequest
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
T120RegistryRequest reg_req;
::AppletRegistryRequestToT120One(pRequest, &reg_req);
T120Error rc = m_pT120Session->RegistryRequest(&reg_req);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
//////////////////////////////////////////////////
//
// Channel Services @ CNmAppletSession
//
HRESULT CNmAppletSession::ChannelRequest
(
AppletChannelRequest *pRequest
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
T120Error rc = m_pT120Session->ChannelRequest((T120ChannelRequest *) pRequest);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
//////////////////////////////////////////////////
//
// Token Services @ CNmAppletSession
//
HRESULT CNmAppletSession::TokenRequest
(
AppletTokenRequest *pRequest
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Session)
{
T120Error rc = m_pT120Session->TokenRequest((T120TokenRequest *) pRequest);
ASSERT(T120_NO_ERROR == rc);
return (T120_NO_ERROR == rc) ? S_OK : APPLET_E_SERVICE_FAIL;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
//////////////////////////////////////////////////
//
// Notification @ CNmAppletSession
//
HRESULT CNmAppletSession::Advise
(
IAppletSessionNotify *pNotify,
DWORD *pdwCookie
)
{
if (NULL != m_pT120Session)
{
if (NULL == m_pNotify)
{
if (NULL != pNotify && NULL != pdwCookie)
{
pNotify->AddRef();
m_pNotify = pNotify;
m_pSessionObj = this;
*pdwCookie = 1;
return S_OK;
}
return E_POINTER;
}
return APPLET_E_ALREADY_ADVISED;
}
return APPLET_E_NO_SERVICE;
}
HRESULT CNmAppletSession::UnAdvise
(
DWORD dwCookie
)
{
if (NULL != m_pT120Session)
{
if (NULL != m_pNotify)
{
if (dwCookie == 1 && m_pSessionObj == this)
{
m_pNotify->Release();
m_pNotify = NULL;
return S_OK;
}
return APPLET_E_INVALID_COOKIE;
}
return APPLET_E_NOT_ADVISED;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// T120 Applet Session Callback @ CNmAppletSession
//
void CNmAppletSession::T120Callback
(
T120AppletSessionMsg *pMsg
)
{
HRESULT hrNotify;
HRESULT hrResult;
IAppletSession *pAppletSession;
T120ChannelID *aChannelIDs;
AppletOctetString ostr;
AppletRegistryCommand eRegistryCommand;
AppletTokenCommand eTokenCommand;
AppletRegistryItem RegItem;
AppletRegistryItem *pRegItem;
AppletRegistryEntryOwner EntryOwner;
if (NULL != m_pNotify)
{
switch (pMsg->eMsgType)
{
//
// Join Session
//
case T120_JOIN_SESSION_CONFIRM:
hrResult = APPLET_E_SERVICE_FAIL;
pAppletSession = NULL;
aChannelIDs = NULL;
if (T120_RESULT_SUCCESSFUL == pMsg->JoinSessionConfirm.eResult &&
T120_NO_ERROR == pMsg->JoinSessionConfirm.eError)
{
hrResult = S_OK;
if (pMsg->JoinSessionConfirm.cResourceReqs)
{
aChannelIDs = new T120ChannelID[pMsg->JoinSessionConfirm.cResourceReqs];
if (NULL != aChannelIDs)
{
for (ULONG i = 0; i < pMsg->JoinSessionConfirm.cResourceReqs; i++)
{
aChannelIDs[i] = pMsg->JoinSessionConfirm.aResourceReqs[i].nChannelID;
}
}
else
{
ASSERT(NULL != aChannelIDs);
hrResult = E_OUTOFMEMORY;
}
}
}
if (S_OK == hrResult)
{
hrNotify = m_pNotify->JoinSessionConfirm(
hrResult,
pMsg->JoinSessionConfirm.uidMyself,
pMsg->JoinSessionConfirm.nidMyself,
pMsg->JoinSessionConfirm.sidMyself,
pMsg->JoinSessionConfirm.eidMyself,
pMsg->JoinSessionConfirm.cResourceReqs,
aChannelIDs);
ASSERT(SUCCEEDED(hrNotify));
}
else
{
hrNotify = m_pNotify->JoinSessionConfirm(hrResult, 0, 0, 0, 0, 0, NULL);
ASSERT(SUCCEEDED(hrNotify));
}
delete [] aChannelIDs;
break;
//
// Detach User
//
case MCS_DETACH_USER_INDICATION:
hrNotify = m_pNotify->LeaveSessionIndication(::GetAppletReason(pMsg->DetachUserInd.eReason),
pMsg->DetachUserInd.nUserID);
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Send Data
//
case MCS_SEND_DATA_INDICATION:
case MCS_UNIFORM_SEND_DATA_INDICATION:
ostr.cbStrSize = pMsg->SendDataInd.user_data.length;
ostr.pbValue = pMsg->SendDataInd.user_data.value;
hrNotify = m_pNotify->SendDataIndication(MCS_UNIFORM_SEND_DATA_INDICATION == pMsg->eMsgType,
pMsg->SendDataInd.initiator,
pMsg->SendDataInd.channel_id,
(AppletPriority) pMsg->SendDataInd.data_priority,
ostr);
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Roster
//
case GCC_APP_ROSTER_REPORT_INDICATION:
hrNotify = m_pNotify->RosterReportIndication((ULONG) pMsg->AppRosterReportInd.cRosters,
(AppletRoster **) pMsg->AppRosterReportInd.apAppRosters);
ASSERT(SUCCEEDED(hrNotify));
break;
case GCC_APP_ROSTER_INQUIRE_CONFIRM:
hrNotify = m_pNotify->InquireRosterConfirm(::GetHrResult(pMsg->AppRosterInquireConfirm.nResult),
(ULONG) pMsg->AppRosterInquireConfirm.cRosters,
(AppletRoster **) pMsg->AppRosterInquireConfirm.apAppRosters);
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Applet Invoke
//
case GCC_APPLICATION_INVOKE_CONFIRM:
hrNotify = m_pNotify->InvokeAppletConfirm(pMsg->AppInvokeConfirm.nReqTag,
::GetHrResult(pMsg->AppInvokeConfirm.nResult));
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Registry
//
case GCC_REGISTER_CHANNEL_CONFIRM:
eRegistryCommand = APPLET_REGISTER_CHANNEL;
RegistryCommon_1:
if (NULL != pMsg->RegistryConfirm.pRegItem)
{
pRegItem = (AppletRegistryItem *) pMsg->RegistryConfirm.pRegItem;
}
else
{
::ZeroMemory(&RegItem, sizeof(RegItem));
pRegItem = &RegItem;
}
hrNotify = m_pNotify->RegistryConfirm(eRegistryCommand,
::GetHrResult(pMsg->RegistryConfirm.nResult),
(AppletRegistryKey *) pMsg->RegistryConfirm.pRegKey,
pRegItem,
(AppletRegistryEntryOwner *) &pMsg->RegistryConfirm.EntryOwner,
pMsg->RegistryConfirm.eRights);
ASSERT(SUCCEEDED(hrNotify));
break;
case GCC_ASSIGN_TOKEN_CONFIRM:
eRegistryCommand = APPLET_ASSIGN_TOKEN;
goto RegistryCommon_1;
case GCC_SET_PARAMETER_CONFIRM:
eRegistryCommand = APPLET_SET_PARAMETER;
goto RegistryCommon_1;
case GCC_RETRIEVE_ENTRY_CONFIRM:
hrResult = ::GetHrResult(pMsg->RegistryConfirm.nResult);
if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult)
{
if (NULL != pMsg->RegistryConfirm.pRegItem)
{
pRegItem = (AppletRegistryItem *) pMsg->RegistryConfirm.pRegItem;
}
else
{
::ZeroMemory(&RegItem, sizeof(RegItem));
pRegItem = &RegItem;
}
hrNotify = m_pNotify->RegistryConfirm(APPLET_RETRIEVE_ENTRY,
hrResult,
(AppletRegistryKey *) pMsg->RegistryConfirm.pRegKey,
pRegItem,
(AppletRegistryEntryOwner *) &pMsg->RegistryConfirm.EntryOwner,
pMsg->RegistryConfirm.eRights);
ASSERT(SUCCEEDED(hrNotify));
}
else
{
::ZeroMemory(&RegItem, sizeof(RegItem));
::ZeroMemory(&EntryOwner, sizeof(EntryOwner));
hrNotify = m_pNotify->RegistryConfirm(APPLET_RETRIEVE_ENTRY,
hrResult,
(AppletRegistryKey *) pMsg->RegistryConfirm.pRegKey,
&RegItem,
&EntryOwner,
APPLET_NO_MODIFICATION_RIGHTS_SPECIFIED);
ASSERT(SUCCEEDED(hrNotify));
}
break;
case GCC_DELETE_ENTRY_CONFIRM:
hrResult = ::GetHrResult(pMsg->RegistryConfirm.nResult);
if (GCC_RESULT_INDEX_ALREADY_OWNED == pMsg->RegistryConfirm.nResult)
{
if (NULL != pMsg->RegistryConfirm.pRegItem)
{
pRegItem = (AppletRegistryItem *) pMsg->RegistryConfirm.pRegItem;
}
else
{
::ZeroMemory(&RegItem, sizeof(RegItem));
pRegItem = &RegItem;
}
hrNotify = m_pNotify->RegistryConfirm(APPLET_DELETE_ENTRY,
hrResult,
(AppletRegistryKey *) pMsg->RegistryConfirm.pRegKey,
pRegItem,
(AppletRegistryEntryOwner *) &pMsg->RegistryConfirm.EntryOwner,
pMsg->RegistryConfirm.eRights);
ASSERT(SUCCEEDED(hrNotify));
}
else
{
::ZeroMemory(&RegItem, sizeof(RegItem));
::ZeroMemory(&EntryOwner, sizeof(EntryOwner));
hrNotify = m_pNotify->RegistryConfirm(APPLET_DELETE_ENTRY,
hrResult,
(AppletRegistryKey *) pMsg->RegistryConfirm.pRegKey,
&RegItem,
&EntryOwner,
APPLET_NO_MODIFICATION_RIGHTS_SPECIFIED);
ASSERT(SUCCEEDED(hrNotify));
}
break;
case GCC_ALLOCATE_HANDLE_CONFIRM:
hrNotify = m_pNotify->AllocateHandleConfirm(::GetHrResult(pMsg->RegAllocHandleConfirm.nResult),
pMsg->RegAllocHandleConfirm.nFirstHandle,
pMsg->RegAllocHandleConfirm.cHandles);
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Channel
//
case MCS_CHANNEL_JOIN_CONFIRM:
hrNotify = m_pNotify->ChannelConfirm(APPLET_JOIN_CHANNEL,
::GetHrResult(pMsg->ChannelConfirm.eResult),
pMsg->ChannelConfirm.nChannelID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_CHANNEL_CONVENE_CONFIRM:
hrNotify = m_pNotify->ChannelConfirm(APPLET_CONVENE_CHANNEL,
::GetHrResult(pMsg->ChannelConfirm.eResult),
pMsg->ChannelConfirm.nChannelID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_CHANNEL_LEAVE_INDICATION:
hrNotify = m_pNotify->ChannelIndication(APPLET_LEAVE_CHANNEL,
pMsg->ChannelInd.nChannelID,
::GetAppletReason(pMsg->ChannelInd.eReason),
0);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_CHANNEL_DISBAND_INDICATION:
hrNotify = m_pNotify->ChannelIndication(APPLET_DISBAND_CHANNEL,
pMsg->ChannelInd.nChannelID,
::GetAppletReason(pMsg->ChannelInd.eReason),
0);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_CHANNEL_ADMIT_INDICATION:
hrNotify = m_pNotify->ChannelIndication(APPLET_ADMIT_CHANNEL,
pMsg->ChannelInd.nChannelID,
APPLET_R_UNSPECIFIED,
pMsg->ChannelInd.nManagerID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_CHANNEL_EXPEL_INDICATION:
hrNotify = m_pNotify->ChannelIndication(APPLET_EXPEL_CHANNEL,
pMsg->ChannelInd.nChannelID,
::GetAppletReason(pMsg->ChannelInd.eReason),
0);
ASSERT(SUCCEEDED(hrNotify));
break;
//
// Token
//
case MCS_TOKEN_GRAB_CONFIRM:
eTokenCommand = APPLET_GRAB_TOKEN;
Token_Common_1:
hrNotify = m_pNotify->TokenConfirm(eTokenCommand,
::GetHrResult(pMsg->TokenConfirm.eResult),
pMsg->TokenConfirm.nTokenID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_TOKEN_INHIBIT_CONFIRM:
eTokenCommand = APPLET_INHIBIT_TOKEN;
goto Token_Common_1;
case MCS_TOKEN_GIVE_CONFIRM:
eTokenCommand = APPLET_GIVE_TOKEN;
goto Token_Common_1;
case MCS_TOKEN_RELEASE_CONFIRM:
eTokenCommand = APPLET_RELEASE_TOKEN;
goto Token_Common_1;
case MCS_TOKEN_TEST_CONFIRM:
hrNotify = m_pNotify->TestTokenConfirm(pMsg->TokenConfirm.nTokenID,
pMsg->TokenConfirm.eTokenStatus);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_TOKEN_GIVE_INDICATION:
hrNotify = m_pNotify->TokenIndication(APPLET_GIVE_TOKEN,
APPLET_R_UNSPECIFIED,
pMsg->TokenInd.nTokenID,
pMsg->TokenInd.nUserID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_TOKEN_PLEASE_INDICATION:
hrNotify = m_pNotify->TokenIndication(APPLET_PLEASE_TOKEN,
APPLET_R_UNSPECIFIED,
pMsg->TokenInd.nTokenID,
pMsg->TokenInd.nUserID);
ASSERT(SUCCEEDED(hrNotify));
break;
case MCS_TOKEN_RELEASE_INDICATION:
hrNotify = m_pNotify->TokenIndication(APPLET_RELEASE_TOKEN,
::GetAppletReason(pMsg->TokenInd.eReason),
pMsg->TokenInd.nTokenID,
0);
ASSERT(SUCCEEDED(hrNotify));
break;
} // switch
} // if
}
HRESULT GetHrResult(T120Result rc)
{
HRESULT hrResult;
switch (rc)
{
case T120_RESULT_SUCCESSFUL:
hrResult = S_OK;
break;
case GCC_RESULT_ENTRY_ALREADY_EXISTS:
hrResult = APPLET_E_ENTRY_ALREADY_EXISTS;
break;
case GCC_RESULT_ENTRY_DOES_NOT_EXIST:
hrResult = APPLET_E_ENTRY_DOES_NOT_EXIST;
break;
case GCC_RESULT_INDEX_ALREADY_OWNED:
hrResult = APPLET_E_NOT_OWNER;
break;
default:
hrResult = APPLET_E_SERVICE_FAIL;
break;
}
return hrResult;
}
AppletReason GetAppletReason(T120Reason rc)
{
AppletReason eAppletReason;
switch (rc)
{
case REASON_USER_REQUESTED:
eAppletReason = APPLET_R_USER_REJECTED;
break;
case REASON_DOMAIN_DISCONNECTED:
case REASON_PROVIDER_INITIATED:
eAppletReason = APPLET_R_CONFERENCE_GONE;
break;
case REASON_TOKEN_PURGED:
case REASON_CHANNEL_PURGED:
eAppletReason = APPLET_R_RESOURCE_PURGED;
break;
default:
eAppletReason = APPLET_R_UNSPECIFIED;
break;
}
return eAppletReason;
}
//////////////////////////////////////////////////
//
// CNmAppletObj
//
CNmAppletObj::CNmAppletObj(void)
:
m_cRef(0),
m_pT120Applet(NULL),
m_pT120AutoJoinReq(NULL),
m_pNotify(NULL),
m_nPendingConfID(0)
{
}
CNmAppletObj::~CNmAppletObj(void)
{
ASSERT(0 == m_cRef);
if (NULL != m_pT120Applet)
{
m_pT120Applet->ReleaseInterface();
m_pT120Applet = NULL;
}
::FreeJoinSessionRequest(m_pT120AutoJoinReq);
}
HRESULT CNmAppletObj::Initialize(void)
{
T120Error rc = ::T120_CreateAppletSAP(&m_pT120Applet);
if (T120_NO_ERROR == rc)
{
m_pT120Applet->Advise(T120AppletCallback, this);
return S_OK;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Auto Join @ CNmAppletObj
//
HRESULT CNmAppletObj::RegisterAutoJoin
(
AppletSessionRequest *pRequest
)
{
if (NULL != m_pNotify)
{
if (NULL != m_pT120Applet)
{
if (NULL != pRequest)
{
if (NULL == m_pT120AutoJoinReq)
{
m_pT120AutoJoinReq = ::AllocateJoinSessionRequest(pRequest);
if (NULL != m_pT120AutoJoinReq)
{
T120Error rc = m_pT120Applet->RegisterAutoJoin(m_pT120AutoJoinReq);
ASSERT(T120_NO_ERROR == rc);
if (T120_NO_ERROR == rc)
{
return S_OK;
}
::FreeJoinSessionRequest(m_pT120AutoJoinReq);
m_pT120AutoJoinReq = NULL;
return APPLET_E_SERVICE_FAIL;
}
return APPLET_E_INVALID_JOIN_REQUEST;
}
return APPLET_E_ALREADY_REGISTERED;
}
return E_POINTER;
}
return APPLET_E_NO_SERVICE;
}
return APPLET_E_NOT_ADVISED;
}
HRESULT CNmAppletObj::UnregisterAutoJoin(void)
{
if (NULL != m_pT120Applet)
{
if (NULL != m_pT120AutoJoinReq)
{
m_pT120Applet->UnregisterAutoJoin();
::FreeJoinSessionRequest(m_pT120AutoJoinReq);
m_pT120AutoJoinReq = NULL;
return S_OK;
}
return APPLET_E_NOT_REGISTERED;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Session @ CNmAppletObj
//
HRESULT CNmAppletObj::CreateSession
(
IAppletSession **ppSession,
AppletConfID nConfID
)
{
if (NULL != m_pT120Applet)
{
if (NULL != ppSession)
{
*ppSession = NULL;
if (nConfID)
{
IT120AppletSession *pT120Session = NULL;
T120Error rc = m_pT120Applet->CreateSession(&pT120Session, nConfID);
if (T120_NO_ERROR == rc)
{
*ppSession = (IAppletSession *) new CNmAppletSession(this, pT120Session);
if (NULL != *ppSession)
{
return S_OK;
}
pT120Session->ReleaseInterface();
return E_OUTOFMEMORY;
}
return APPLET_E_SERVICE_FAIL;
}
return APPLET_E_INVALID_CONFERENCE;
}
return E_POINTER;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// Notification @ CNmAppletObj
//
HRESULT CNmAppletObj::Advise
(
IAppletNotify *pNotify,
DWORD *pdwCookie
)
{
if (NULL != m_pT120Applet)
{
if (NULL == m_pNotify)
{
if (NULL != pNotify && NULL != pdwCookie)
{
pNotify->AddRef();
m_pNotify = pNotify;
m_pAppletObj = this;
*pdwCookie = 1;
if (m_nPendingConfID)
{
m_pNotify->PermitToJoinSessionIndication(m_nPendingConfID, TRUE);
m_nPendingConfID = 0;
}
return S_OK;
}
return E_POINTER;
}
return APPLET_E_ALREADY_ADVISED;
}
return APPLET_E_NO_SERVICE;
}
HRESULT CNmAppletObj::UnAdvise
(
DWORD dwCookie
)
{
if (NULL != m_pT120Applet)
{
if (NULL != m_pNotify)
{
if (dwCookie == 1 && m_pAppletObj == this)
{
m_pNotify->Release();
m_pNotify = NULL;
return S_OK;
}
return APPLET_E_INVALID_COOKIE;
}
return APPLET_E_NOT_ADVISED;
}
return APPLET_E_NO_SERVICE;
}
//////////////////////////////////////////////////
//
// T120 Applet @ CNmAppletObj
//
void CNmAppletObj::T120Callback
(
T120AppletMsg *pMsg
)
{
HRESULT hrNotify;
HRESULT hrResult;
IAppletSession *pAppletSession;
T120ChannelID *aChannelIDs;
if (NULL != m_pNotify)
{
switch (pMsg->eMsgType)
{
case GCC_PERMIT_TO_ENROLL_INDICATION:
ASSERT(0 == m_nPendingConfID);
hrNotify = m_pNotify->PermitToJoinSessionIndication(
pMsg->PermitToEnrollInd.nConfID,
pMsg->PermitToEnrollInd.fPermissionGranted);
ASSERT(SUCCEEDED(hrNotify));
break;
case T120_JOIN_SESSION_CONFIRM:
hrResult = APPLET_E_SERVICE_FAIL;
pAppletSession = NULL;
aChannelIDs = NULL;
if (T120_RESULT_SUCCESSFUL == pMsg->AutoJoinSessionInd.eResult &&
T120_NO_ERROR == pMsg->AutoJoinSessionInd.eError)
{
hrResult = S_OK;
if (pMsg->AutoJoinSessionInd.cResourceReqs)
{
aChannelIDs = new T120ChannelID[pMsg->AutoJoinSessionInd.cResourceReqs];
if (NULL != aChannelIDs)
{
for (ULONG i = 0; i < pMsg->AutoJoinSessionInd.cResourceReqs; i++)
{
aChannelIDs[i] = pMsg->AutoJoinSessionInd.aResourceReqs[i].nChannelID;
}
}
else
{
ASSERT(NULL != aChannelIDs);
hrResult = E_OUTOFMEMORY;
}
}
if (S_OK == hrResult)
{
ASSERT(NULL != pMsg->AutoJoinSessionInd.pIAppletSession);
pAppletSession = new CNmAppletSession(this, pMsg->AutoJoinSessionInd.pIAppletSession, TRUE);
ASSERT(NULL != pAppletSession);
hrResult = (NULL != pAppletSession) ? S_OK : E_OUTOFMEMORY;
}
}
if (S_OK == hrResult)
{
hrNotify = m_pNotify->AutoJoinSessionIndication(
pAppletSession,
hrResult,
pMsg->AutoJoinSessionInd.uidMyself,
pMsg->AutoJoinSessionInd.nidMyself,
pMsg->AutoJoinSessionInd.sidMyself,
pMsg->AutoJoinSessionInd.eidMyself,
pMsg->AutoJoinSessionInd.cResourceReqs,
aChannelIDs);
ASSERT(SUCCEEDED(hrNotify));
}
else
{
hrNotify = m_pNotify->AutoJoinSessionIndication(NULL, hrResult, 0, 0, 0, 0, 0, NULL);
ASSERT(SUCCEEDED(hrNotify));
if (NULL != pMsg->AutoJoinSessionInd.pIAppletSession)
{
pMsg->AutoJoinSessionInd.pIAppletSession->ReleaseInterface();
}
}
delete [] aChannelIDs;
break;
} // switch
}
else
{
// free memory for unwanted message
if (T120_JOIN_SESSION_CONFIRM == pMsg->eMsgType &&
T120_RESULT_SUCCESSFUL == pMsg->AutoJoinSessionInd.eResult &&
T120_NO_ERROR == pMsg->AutoJoinSessionInd.eError)
{
if (NULL != pMsg->AutoJoinSessionInd.pIAppletSession)
{
pMsg->AutoJoinSessionInd.pIAppletSession->ReleaseInterface();
}
}
else
if (GCC_PERMIT_TO_ENROLL_INDICATION == pMsg->eMsgType)
{
if (pMsg->PermitToEnrollInd.fPermissionGranted)
{
m_nPendingConfID = pMsg->PermitToEnrollInd.nConfID;
}
else
{
if (m_nPendingConfID == pMsg->PermitToEnrollInd.nConfID)
{
m_nPendingConfID = 0;
}
}
}
}
}
//////////////////////////////////////////////////
//
// Join Session Request
//
T120JoinSessionRequest * AllocateJoinSessionRequest
(
AppletSessionRequest *pAppletRequest
)
{
T120JoinSessionRequest *pT120One = new T120JoinSessionRequest;
if (NULL != pT120One)
{
::ZeroMemory(pT120One, sizeof(*pT120One));
ULONG i;
pT120One->dwAttachmentFlags = ATTACHMENT_DISCONNECT_IN_DATA_LOSS;
if (! ::DuplicateSessionKey(&pT120One->SessionKey, (T120SessionKey *) &pAppletRequest->SessionKey))
{
goto MyError;
}
pT120One->fConductingCapable = FALSE;
pT120One->nStartupChannelType = pAppletRequest->nStartupChannelType;
if (::ConvertNonCollapsedCaps(&pT120One->apNonCollapsedCaps,
pAppletRequest->apNonCollapsedCaps,
pAppletRequest->cNonCollapsedCaps))
{
pT120One->cNonCollapsedCaps = pAppletRequest->cNonCollapsedCaps;
}
else
{
goto MyError;
}
if (::ConvertCollapsedCaps(&pT120One->apCollapsedCaps,
pAppletRequest->apCollapsedCaps,
pAppletRequest->cCollapsedCaps))
{
pT120One->cCollapsedCaps = pAppletRequest->cCollapsedCaps;
}
else
{
goto MyError;
}
if (0 != (pT120One->cStaticChannels = pAppletRequest->cStaticChannels))
{
pT120One->aStaticChannels = new T120ChannelID[pT120One->cStaticChannels];
if (NULL != pT120One->aStaticChannels)
{
::CopyMemory(pT120One->aStaticChannels,
pAppletRequest->aStaticChannels,
pT120One->cStaticChannels * sizeof(T120ChannelID));
}
else
{
goto MyError;
}
}
if (0 != (pT120One->cResourceReqs = pAppletRequest->cDynamicChannels))
{
if (NULL != (pT120One->aResourceReqs = new T120ResourceRequest[pT120One->cResourceReqs]))
{
::ZeroMemory(pT120One->aResourceReqs, pT120One->cResourceReqs * sizeof(T120ResourceRequest));
for (i = 0; i < pT120One->cResourceReqs; i++)
{
pT120One->aResourceReqs[i].eCommand = APPLET_JOIN_DYNAMIC_CHANNEL;
if (! ::DuplicateRegistryKey(&pT120One->aResourceReqs[i].RegKey,
(T120RegistryKey *) &pAppletRequest->aChannelRegistryKeys[i]))
{
goto MyError;
}
}
}
else
{
goto MyError;
}
}
return pT120One;
}
MyError:
::FreeJoinSessionRequest(pT120One);
return NULL;
}
void FreeJoinSessionRequest
(
T120JoinSessionRequest *pT120One
)
{
if (NULL != pT120One)
{
::FreeSessionKey(&pT120One->SessionKey);
::FreeNonCollapsedCaps(pT120One->apNonCollapsedCaps, pT120One->cNonCollapsedCaps);
::FreeCollapsedCaps(pT120One->apCollapsedCaps, pT120One->cCollapsedCaps);
if (pT120One->cStaticChannels)
{
delete [] pT120One->aStaticChannels;
}
if (pT120One->cResourceReqs)
{
for (ULONG i = 0; i < pT120One->cResourceReqs; i++)
{
::FreeRegistryKey(&pT120One->aResourceReqs[i].RegKey);
}
delete [] pT120One->aResourceReqs;
}
delete pT120One;
}
}
BOOL ConvertCollapsedCaps(T120AppCap ***papDst, AppletCapability **apSrc, ULONG cItems)
{
if (cItems)
{
T120AppCap **arr_ptr;
ULONG cbTotalSize = cItems * (sizeof(T120AppCap*) + sizeof(T120AppCap));
if (NULL != (arr_ptr = (T120AppCap**) new BYTE[cbTotalSize]))
{
::ZeroMemory(arr_ptr, cbTotalSize);
T120AppCap *arr_obj = (T120AppCap *) (arr_ptr + cItems);
for (ULONG i = 0; i < cItems; i++)
{
arr_ptr[i] = &arr_obj[i];
if (! ::DuplicateCollapsedCap(arr_ptr[i], (T120AppCap *) apSrc[i]))
{
::FreeCollapsedCaps(arr_ptr, cItems);
return FALSE;
}
}
}
*papDst = arr_ptr;
return (NULL != arr_ptr);
}
*papDst = NULL;
return TRUE;
}
void FreeCollapsedCaps(T120AppCap **apDst, ULONG cItems)
{
if (cItems && NULL != apDst)
{
T120AppCap **arr_ptr = apDst;
T120AppCap *arr_obj = (T120AppCap *) (arr_ptr + cItems);
for (ULONG i = 0; i < cItems; i++)
{
::FreeCollapsedCap(&arr_obj[i]);
}
delete [] (LPBYTE) arr_ptr;
}
}
BOOL DuplicateCollapsedCap(T120AppCap *pDst, T120AppCap *pSrc)
{
pDst->number_of_entities = pSrc->number_of_entities;
pDst->capability_class = pSrc->capability_class; // no memory allocation
return ::DuplicateCapID(&pDst->capability_id, &pSrc->capability_id);
}
void FreeCollapsedCap(T120AppCap *pDst)
{
::FreeCapID(&pDst->capability_id);
}
BOOL DuplicateCapID(T120CapID *pDst, T120CapID *pSrc)
{
pDst->capability_id_type = pSrc->capability_id_type;
switch (pDst->capability_id_type)
{
case GCC_STANDARD_CAPABILITY:
pDst->standard_capability = pSrc->standard_capability;
return TRUE;
case GCC_NON_STANDARD_CAPABILITY:
return ::DuplicateObjectKey(&pDst->non_standard_capability, &pSrc->non_standard_capability);
}
return FALSE;
}
void FreeCapID(T120CapID *pDst)
{
switch (pDst->capability_id_type)
{
case GCC_NON_STANDARD_CAPABILITY:
::FreeObjectKey(&pDst->non_standard_capability);
break;
}
}
BOOL ConvertNonCollapsedCaps(T120NonCollCap ***papDst, AppletCapability2 **apSrc, ULONG cItems)
{
if (cItems)
{
T120NonCollCap **arr_ptr;
ULONG cbTotalSize = cItems * (sizeof(T120NonCollCap*) + sizeof(T120NonCollCap));
if (NULL != (arr_ptr = (T120NonCollCap**) new BYTE[cbTotalSize]))
{
::ZeroMemory(arr_ptr, cbTotalSize);
T120NonCollCap *arr_obj = (T120NonCollCap *) (arr_ptr + cItems);
for (ULONG i = 0; i < cItems; i++)
{
arr_ptr[i] = &arr_obj[i];
if (! ::DuplicateNonCollapsedCap(arr_ptr[i], (T120NonCollCap *) apSrc[i]))
{
::FreeNonCollapsedCaps(arr_ptr, cItems);
return FALSE;
}
}
}
*papDst = arr_ptr;
return (NULL != arr_ptr);
}
*papDst = NULL;
return TRUE;
}
void FreeNonCollapsedCaps(T120NonCollCap **apDst, ULONG cItems)
{
if (cItems && NULL != apDst)
{
T120NonCollCap **arr_ptr = apDst;
T120NonCollCap *arr_obj = (T120NonCollCap *) (arr_ptr + cItems);
for (ULONG i = 0; i < cItems; i++)
{
::FreeNonCollapsedCap(&arr_obj[i]);
}
delete [] (LPBYTE) arr_ptr;
}
}
BOOL DuplicateNonCollapsedCap(T120NonCollCap *pDst, T120NonCollCap *pSrc)
{
if (::DuplicateCapID(&pDst->capability_id, &pSrc->capability_id))
{
if (NULL == pSrc->application_data)
{
return TRUE;
}
if (NULL != (pDst->application_data = new OSTR))
{
return ::DuplicateOSTR(pDst->application_data, pSrc->application_data);
}
}
return FALSE;
}
void FreeNonCollapsedCap(T120NonCollCap *pDst)
{
::FreeCapID(&pDst->capability_id);
if (NULL != pDst->application_data)
{
::FreeOSTR(pDst->application_data);
delete pDst->application_data;
}
}
BOOL DuplicateRegistryKey(T120RegistryKey *pDst, T120RegistryKey *pSrc)
{
if (::DuplicateSessionKey(&pDst->session_key, &pSrc->session_key))
{
return ::DuplicateOSTR(&pDst->resource_id, &pSrc->resource_id);
}
return FALSE;
}
void FreeRegistryKey(T120RegistryKey *pDst)
{
::FreeSessionKey(&pDst->session_key);
::FreeOSTR(&pDst->resource_id);
}
BOOL DuplicateSessionKey(T120SessionKey *pDst, T120SessionKey *pSrc)
{
pDst->session_id = pSrc->session_id;
return ::DuplicateObjectKey(&pDst->application_protocol_key, &pSrc->application_protocol_key);
}
void FreeSessionKey(T120SessionKey *pDst)
{
::FreeObjectKey(&pDst->application_protocol_key);
}
BOOL DuplicateObjectKey(T120ObjectKey *pDst, T120ObjectKey *pSrc)
{
pDst->key_type = pSrc->key_type;
switch (pDst->key_type)
{
case GCC_OBJECT_KEY:
pDst->object_id.long_string_length = pSrc->object_id.long_string_length;
if (pSrc->object_id.long_string_length && NULL != pSrc->object_id.long_string)
{
if (NULL != (pDst->object_id.long_string = new ULONG[pDst->object_id.long_string_length]))
{
::CopyMemory(pDst->object_id.long_string,
pSrc->object_id.long_string,
pDst->object_id.long_string_length * sizeof(ULONG));
return TRUE;
}
}
break;
case GCC_H221_NONSTANDARD_KEY:
return ::DuplicateOSTR(&pDst->h221_non_standard_id, &pSrc->h221_non_standard_id);
}
return FALSE;
}
void FreeObjectKey(T120ObjectKey *pDst)
{
switch (pDst->key_type)
{
case GCC_OBJECT_KEY:
if (pDst->object_id.long_string_length)
{
delete [] pDst->object_id.long_string;
}
break;
case GCC_H221_NONSTANDARD_KEY:
::FreeOSTR(&pDst->h221_non_standard_id);
break;
}
}
BOOL DuplicateOSTR(OSTR *pDst, OSTR *pSrc)
{
if (pSrc->length && NULL != pSrc->value)
{
pDst->length = pSrc->length;
if (NULL != (pDst->value = new BYTE[pDst->length]))
{
::CopyMemory(pDst->value, pSrc->value, pDst->length);
return TRUE;
}
}
return FALSE;
}
void FreeOSTR(OSTR *pDst)
{
if (pDst->length)
{
delete [] pDst->value;
}
}
//////////////////////////////////////////////////
//
// Conversion
//
void AppletRegistryRequestToT120One
(
AppletRegistryRequest *pAppletRequest,
T120RegistryRequest *pT120One
)
{
pT120One->eCommand = pAppletRequest->eCommand;
pT120One->pRegistryKey = (T120RegistryKey *) &pAppletRequest->RegistryKey;
switch (pT120One->eCommand)
{
case APPLET_REGISTER_CHANNEL:
pT120One->nChannelID = pAppletRequest->nChannelID;
break;
case APPLET_SET_PARAMETER:
pT120One->Param.postrValue = (OSTR *) &pAppletRequest->ostrParamValue;
pT120One->Param.eModifyRights = pAppletRequest->eParamModifyRights;
break;
case APPLET_ALLOCATE_HANDLE:
pT120One->cHandles = pAppletRequest->cHandles;
break;
case APPLET_RETRIEVE_ENTRY:
case APPLET_DELETE_ENTRY:
case APPLET_ASSIGN_TOKEN:
case APPLET_MONITOR:
default:
break;
}
}
#ifdef _DEBUG
void CheckStructCompatible(void)
{
ASSERT(sizeof(AppletOctetString) == sizeof(OSTR));
ASSERT(FIELD_OFFSET(AppletOctetString, cbStrSize) == FIELD_OFFSET(OSTR, length));
ASSERT(FIELD_OFFSET(AppletOctetString, pbValue) == FIELD_OFFSET(OSTR, value));
ASSERT(sizeof(AppletLongString) == sizeof(T120LongString));
ASSERT(FIELD_OFFSET(AppletLongString, nStrLen) == FIELD_OFFSET(T120LongString, long_string_length));
ASSERT(FIELD_OFFSET(AppletLongString, pnValue) == FIELD_OFFSET(T120LongString, long_string));
ASSERT(sizeof(AppletObjectKey) == sizeof(T120ObjectKey));
ASSERT(FIELD_OFFSET(AppletObjectKey, eType) == FIELD_OFFSET(T120ObjectKey, key_type));
ASSERT(FIELD_OFFSET(AppletObjectKey, lstrObjectID) == FIELD_OFFSET(T120ObjectKey, object_id));
ASSERT(FIELD_OFFSET(AppletObjectKey, ostrH221NonStdID) == FIELD_OFFSET(T120ObjectKey, h221_non_standard_id));
ASSERT(sizeof(AppletSessionKey) == sizeof(T120SessionKey));
ASSERT(FIELD_OFFSET(AppletSessionKey, AppletProtocolKey) == FIELD_OFFSET(T120SessionKey, application_protocol_key));
ASSERT(FIELD_OFFSET(AppletSessionKey, nSessionID) == FIELD_OFFSET(T120SessionKey, session_id));
ASSERT(sizeof(AppletRegistryKey) == sizeof(T120RegistryKey));
ASSERT(FIELD_OFFSET(AppletRegistryKey, SessionKey) == FIELD_OFFSET(T120RegistryKey, session_key));
ASSERT(FIELD_OFFSET(AppletRegistryKey, ostrResourceID) == FIELD_OFFSET(T120RegistryKey, resource_id));
ASSERT(sizeof(AppletRegistryItem) == sizeof(T120RegistryItem));
ASSERT(FIELD_OFFSET(AppletRegistryItem, ItemType) == FIELD_OFFSET(T120RegistryItem, item_type));
ASSERT(FIELD_OFFSET(AppletRegistryItem, nChannelID) == FIELD_OFFSET(T120RegistryItem, channel_id));
ASSERT(FIELD_OFFSET(AppletRegistryItem, nTokenID) == FIELD_OFFSET(T120RegistryItem, token_id));
ASSERT(FIELD_OFFSET(AppletRegistryItem, ostrParamValue) == FIELD_OFFSET(T120RegistryItem, parameter));
ASSERT(sizeof(AppletRegistryEntryOwner) == sizeof(T120RegistryEntryOwner));
ASSERT(FIELD_OFFSET(AppletRegistryEntryOwner, fEntryOwned) == FIELD_OFFSET(T120RegistryEntryOwner, entry_is_owned));
ASSERT(FIELD_OFFSET(AppletRegistryEntryOwner, nOwnerNodeID) == FIELD_OFFSET(T120RegistryEntryOwner, owner_node_id));
ASSERT(FIELD_OFFSET(AppletRegistryEntryOwner, nOwnerEntityID) == FIELD_OFFSET(T120RegistryEntryOwner, owner_entity_id));
ASSERT(sizeof(AppletCapabilityID) == sizeof(T120CapID));
ASSERT(FIELD_OFFSET(AppletCapabilityID, eType) == FIELD_OFFSET(T120CapID, capability_id_type));
ASSERT(FIELD_OFFSET(AppletCapabilityID, nNonStdCap) == FIELD_OFFSET(T120CapID, non_standard_capability));
ASSERT(FIELD_OFFSET(AppletCapabilityID, nStdCap) == FIELD_OFFSET(T120CapID, standard_capability));
ASSERT(sizeof(AppletCapability) == sizeof(T120AppCap));
ASSERT(FIELD_OFFSET(AppletCapability, CapID) == FIELD_OFFSET(T120AppCap, capability_id));
ASSERT(FIELD_OFFSET(AppletCapability, CapClass) == FIELD_OFFSET(T120AppCap, capability_class));
ASSERT(FIELD_OFFSET(AppletCapability, cEntities) == FIELD_OFFSET(T120AppCap, number_of_entities));
ASSERT(sizeof(AppletCapability2) == sizeof(T120NonCollCap));
ASSERT(FIELD_OFFSET(AppletCapability2, CapID) == FIELD_OFFSET(T120NonCollCap, capability_id));
ASSERT(FIELD_OFFSET(AppletCapability2, pCapData) == FIELD_OFFSET(T120NonCollCap, application_data));
ASSERT(sizeof(AppletProtocolEntity) == sizeof(T120APE)); // array of structs vs array of pointers
ASSERT(FIELD_OFFSET(AppletProtocolEntity, SessionKey) == FIELD_OFFSET(T120APE, session_key));
ASSERT(FIELD_OFFSET(AppletProtocolEntity, eStartupChannelType) == FIELD_OFFSET(T120APE, startup_channel_type));
ASSERT(FIELD_OFFSET(AppletProtocolEntity, fMustBeInvoked) == FIELD_OFFSET(T120APE, must_be_invoked));
ASSERT(FIELD_OFFSET(AppletProtocolEntity, cExpectedCapabilities) == FIELD_OFFSET(T120APE, number_of_expected_capabilities));
ASSERT(FIELD_OFFSET(AppletProtocolEntity, apExpectedCapabilities) == FIELD_OFFSET(T120APE, expected_capabilities_list));
ASSERT(sizeof(AppletRecord) == sizeof(T120AppRecord)); // array of structs vs array of pointers
ASSERT(FIELD_OFFSET(AppletRecord, nNodeID) == FIELD_OFFSET(T120AppRecord, node_id));
ASSERT(FIELD_OFFSET(AppletRecord, nEntityID) == FIELD_OFFSET(T120AppRecord, entity_id));
ASSERT(FIELD_OFFSET(AppletRecord, fEnrolledActively) == FIELD_OFFSET(T120AppRecord, is_enrolled_actively));
ASSERT(FIELD_OFFSET(AppletRecord, fConductingCapable) == FIELD_OFFSET(T120AppRecord, is_conducting_capable));
ASSERT(FIELD_OFFSET(AppletRecord, eStartupChannelType) == FIELD_OFFSET(T120AppRecord, startup_channel_type));
ASSERT(FIELD_OFFSET(AppletRecord, nAppletUserID) == FIELD_OFFSET(T120AppRecord, application_user_id));
ASSERT(FIELD_OFFSET(AppletRecord, cCapabilities) == FIELD_OFFSET(T120AppRecord, number_of_non_collapsed_caps));
ASSERT(FIELD_OFFSET(AppletRecord, apCapabilities) == FIELD_OFFSET(T120AppRecord, non_collapsed_caps_list));
ASSERT(sizeof(AppletRoster) == sizeof(T120AppRoster)); // array of structs vs array of pointers
ASSERT(FIELD_OFFSET(AppletRoster, SessionKey) == FIELD_OFFSET(T120AppRoster, session_key));
ASSERT(FIELD_OFFSET(AppletRoster, fRosterChanged) == FIELD_OFFSET(T120AppRoster, application_roster_was_changed));
ASSERT(FIELD_OFFSET(AppletRoster, nInstanceNumber) == FIELD_OFFSET(T120AppRoster, instance_number));
ASSERT(FIELD_OFFSET(AppletRoster, fNodesAdded) == FIELD_OFFSET(T120AppRoster, nodes_were_added));
ASSERT(FIELD_OFFSET(AppletRoster, fNodesRemoved) == FIELD_OFFSET(T120AppRoster, nodes_were_removed));
ASSERT(FIELD_OFFSET(AppletRoster, fCapabilitiesChanged) == FIELD_OFFSET(T120AppRoster, capabilities_were_changed));
ASSERT(FIELD_OFFSET(AppletRoster, cRecords) == FIELD_OFFSET(T120AppRoster, number_of_records));
ASSERT(FIELD_OFFSET(AppletRoster, apAppletRecords) == FIELD_OFFSET(T120AppRoster, application_record_list));
ASSERT(FIELD_OFFSET(AppletRoster, cCapabilities) == FIELD_OFFSET(T120AppRoster, number_of_capabilities));
ASSERT(FIELD_OFFSET(AppletRoster, apCapabilities) == FIELD_OFFSET(T120AppRoster, capabilities_list));
ASSERT(sizeof(AppletChannelRequest) == sizeof(T120ChannelRequest));
ASSERT(FIELD_OFFSET(AppletChannelRequest, eCommand) == FIELD_OFFSET(T120ChannelRequest, eCommand));
ASSERT(FIELD_OFFSET(AppletChannelRequest, nChannelID) == FIELD_OFFSET(T120ChannelRequest, nChannelID));
ASSERT(FIELD_OFFSET(AppletChannelRequest, cUsers) == FIELD_OFFSET(T120ChannelRequest, cUsers));
ASSERT(FIELD_OFFSET(AppletChannelRequest, aUsers) == FIELD_OFFSET(T120ChannelRequest, aUsers));
ASSERT(sizeof(AppletTokenRequest) == sizeof(T120TokenRequest));
ASSERT(FIELD_OFFSET(AppletTokenRequest, eCommand) == FIELD_OFFSET(T120TokenRequest, eCommand));
ASSERT(FIELD_OFFSET(AppletTokenRequest, nTokenID) == FIELD_OFFSET(T120TokenRequest, nTokenID));
ASSERT(FIELD_OFFSET(AppletTokenRequest, uidGiveTo) == FIELD_OFFSET(T120TokenRequest, uidGiveTo));
ASSERT(FIELD_OFFSET(AppletTokenRequest, hrGiveResponse) == FIELD_OFFSET(T120TokenRequest, eGiveResponse));
}
#endif // _DEBUG