CCHAN.CPP

//**************************************************************************** 
// Module: NMUI.EXE
// File: CCHAT.CPP
// Content: INmChannel Routines
//
//
// Copyright (c) Microsoft Corporation 1995-1997
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//****************************************************************************


#include "precomp.h"

COBLIST * g_pListChannel = (COBLIST *) NULL;
COBLIST * g_pListChannelNotify = (COBLIST *) NULL;

INmFt * g_pFt = NULL;
INmChannelAppShare * g_pChannelShare = NULL;


//****************************************************************************
//
// HRESULT HookChannel(INmChannel * pChannel)
//
// Hook into notification callback for the channel
//
//****************************************************************************

HRESULT HookChannel(INmChannel * pChannel)
{
HRESULT hr;
CChannelNotify * pNotify;

ULONG uch;
pChannel->GetNmch(&uch);
TRACE_MSG("[%08X] - Channel=[%s] Added", pChannel, GetNmchSz(uch));

ASSERT(NULL != pChannel);
pChannel->AddRef();
AddNode(pChannel, &g_pListChannel);

pNotify = new CChannelNotify();
if (pNotify == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
hr = pNotify->Connect(pChannel);
if (FAILED(hr))
{
WARN_MSG("CConfNotify Failed (%s)", GetHrSz(hr));
pNotify->Release();
}
else
{
OBJECT_MSG("Conference Connection point established successfully");
AddNode(pNotify, &g_pListChannelNotify);
}
}

if (SUCCEEDED(hr))
{
ULONG uch;
if (SUCCEEDED(pChannel->GetNmch(&uch)))
{
switch (uch)
{
case NMCH_SHARE:
{
if (NULL != g_pChannelShare)
{
WARN_MSG("Replacing App Sharing Channel");
g_pChannelShare->Release();
g_pChannelShare = NULL;
}
hr = pChannel->QueryInterface(IID_INmChannelAppShare, (void **)&g_pChannelShare);
if (FAILED(hr))
{
ERROR_MSG("HookData:Unable to get Data Channel");
}
break;
}
case NMCH_DATA:
HookData(pChannel);
break;
default:
break;
}
}
}

return hr;
}


//****************************************************************************
//
// VOID UnHookChannel(INmChannel * pChannel)
//
//****************************************************************************

VOID UnHookChannel(INmChannel * pChannel)
{
POSITION pos;
POSITION posSav;
IUnknown * pUnk = pChannel;

ULONG uch;
pChannel->GetNmch(&uch);
TRACE_MSG("[%08X] - Channel=[%s] Removed", pChannel, GetNmchSz(uch));

// Search for the notify object responsible for this channel
ASSERT(NULL != g_pListChannelNotify);
for (pos = g_pListChannelNotify->GetHeadPosition(); NULL != pos; )
{
posSav = pos;
CChannelNotify * pNotify = (CChannelNotify *) g_pListChannelNotify->GetNext(pos);
ASSERT(NULL != pNotify);

if (S_OK == pChannel->IsSameAs((INmChannel *) pNotify->GetPunk()))
{
g_pListChannelNotify->RemoveAt(posSav);
pNotify->Disconnect();
pNotify->Release();
break;
}
}

// Search for the channel in the list
ASSERT(NULL != g_pListChannel);
for (pos = g_pListChannel->GetHeadPosition(); NULL != pos; )
{
posSav = pos;
if (S_OK == pChannel->IsSameAs((INmChannel *) g_pListChannel->GetNext(pos)))
{
g_pListChannel->RemoveAt(posSav);
pChannel->Release();
break;
}
}

OBJECT_MSG("Channel connection point removed");
}


//****************************************************************************
//
// VOID UpdateChannelState(INmChannel * pChannel)
//
//****************************************************************************

VOID UpdateChannelState(INmChannel * pChannel)
{
HRESULT hr;
ULONG nmch;
BOOL fActive;
ULONG cMember;

hr = pChannel->GetNmch(&nmch);
if (FAILED(hr))
{
return;
}
fActive = S_OK == pChannel->IsActive();
pChannel->GetMemberCount(&cMember);
TRACE_MSG("%s channel %08X is %s with %d members", GetNmchSz(nmch), pChannel,
fActive ? TEXT("Active") : TEXT("Inactive"), cMember);

switch (nmch)
{
case NMCH_DATA:
{
INmChannelData * pChannelData;
hr = pChannel->QueryInterface(IID_INmChannelData, (void **)&pChannelData);
if (FAILED(hr))
return;
if (pChannelData != g_pChannelData)
{
WARN_MSG("second data channel?");
}
SetMenuCheck(IDM_CHANNEL_DATA, fActive);
pChannelData->Release();
break;
}
case NMCH_AUDIO:
case NMCH_VIDEO:
break;
case NMCH_SHARE:
{
if (fActive)
break;

if (NULL == g_pChannelShare)
break;
g_pChannelShare->Release();
g_pChannelShare = NULL;
break;
}
break;
default:
break;
}
}


//****************************************************************************
//
// VOID FreeChannels(void)
//
//****************************************************************************

VOID FreeChannels(void)
{
// Release all notify
if (NULL != g_pListChannelNotify)
{
while (!g_pListChannelNotify->IsEmpty())
{
CChannelNotify * pNotify = (CChannelNotify *) g_pListChannelNotify->RemoveHead();
ASSERT(NULL != pNotify);
OBJECT_MSG("[%08X] channel notify released", pNotify);
pNotify->Disconnect();
pNotify->Release();
}
}

if (NULL != g_pListChannel)
{
while (!g_pListChannel->IsEmpty())
{
INmChannel * pChannel = (INmChannel *) g_pListChannel->RemoveHead();
ASSERT(NULL != pChannel);
OBJECT_MSG("[%08X] channel released", pChannel);
pChannel->Release();
}
}
}


//****************************************************************************
//
// CLASS CChannelNotify
//
//****************************************************************************

CChannelNotify::CChannelNotify() : RefCount(), CNotify()
{
OBJECT_MSG("CChannelNotify created");
}

CChannelNotify::~CChannelNotify()
{
OBJECT_MSG("CChannelNotify destroyed");
}


//****************************************************************************
//
// Methods from IUnknown
//
//****************************************************************************

ULONG STDMETHODCALLTYPE CChannelNotify::AddRef(void)
{
return RefCount::AddRef();
}


ULONG STDMETHODCALLTYPE CChannelNotify::Release(void)
{
return RefCount::Release();
}

HRESULT STDMETHODCALLTYPE CChannelNotify::QueryInterface(REFIID riid, PVOID *ppvObject)
{
HRESULT hr = S_OK;

if (riid == IID_IUnknown)
{
*ppvObject = (IUnknown *)this;
OBJECT_MSG("CChannelNotify::QueryInterface(): Returning IUnknown.");
}
else if (riid == IID_INmChannelNotify)
{
*ppvObject = (INmChannelNotify *)this;
OBJECT_MSG("CChannelNotify::QueryInterface(): Returning INmChannelNotify.");
}
else
{
hr = E_NOINTERFACE;
*ppvObject = NULL;
OBJECT_MSG("CChannelNotify::QueryInterface(): Called on unknown interface.");
}

if (S_OK == hr)
{
AddRef();
}

return hr;
}


//****************************************************************************
//
// Methods from ICNotify
//
//****************************************************************************

HRESULT STDMETHODCALLTYPE CChannelNotify::Connect(IUnknown *pUnk)
{
return CNotify::Connect(pUnk, IID_INmChannelNotify, (IUnknown *)this);
}

HRESULT STDMETHODCALLTYPE CChannelNotify::Disconnect(void)
{
return CNotify::Disconnect();
}


//****************************************************************************
//
// Methods from IConfNotify
//
//****************************************************************************

HRESULT STDMETHODCALLTYPE CChannelNotify::NmUI(CONFN uNotify)
{
NOTIFY_MSG("CChannelNotify::NmUI uNotify=%08X, pChannel=%08X", uNotify, CNotify::GetPunk());
return S_OK;
}


HRESULT STDMETHODCALLTYPE CChannelNotify::MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pMember)
{
NOTIFY_MSG("CChannelNotify::MemberChanged uNotify=%d pMember=%08X, pChannel=%08X", uNotify, pMember, CNotify::GetPunk());

PUSER pUser = PUserFromINmMember(pMember);
if (NULL != pUser)
{
UpdateUserChannel(pUser, (INmChannel *) (CNotify::GetPunk()), uNotify);
}

return S_OK;
}


//****************************************************************************
//
// VOID SendFile(INmMember * pMember)
//
//****************************************************************************

VOID SendFile(INmMember * pMember)
{
PUSER pUser = PUserLocal();
if (NULL == pUser)
{
return;
}

if (NULL == pUser->m_pChannelFt)
{
return;
}

INmFt * pFt;
BSTRING bstrFileName(gPref.pszFileName);
HRESULT hr = pUser->m_pChannelFt->SendFile(&pFt, pMember, bstrFileName, 0);
if (SUCCEEDED(hr))
{
FreeFt();
g_pFt = pFt;
}
}


//****************************************************************************
//
// VOID DoFtCancel(void)
//
//****************************************************************************

VOID DoFtCancel(void)
{
if (NULL == g_pFt)
return;

HRESULT hr = g_pFt->Cancel();
}


//****************************************************************************
//
// VOID FreeFt(void)
//
//****************************************************************************

VOID FreeFt(void)
{
if (NULL != g_pFt)
{
g_pFt->Release();
g_pFt = NULL;
}
}


//****************************************************************************
//
// VOID FreeAs(void)
//
//****************************************************************************

VOID FreeAs(void)
{
if (NULL != g_pChannelShare)
{
g_pChannelShare->Release();
g_pChannelShare = NULL;
}
}