You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1446 lines
38 KiB
1446 lines
38 KiB
/////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
|
|
//
|
|
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
|
|
//
|
|
// Other brand and product names used herein are trademarks of their respective owners.
|
|
//
|
|
// The entire program and user interface including the structure, sequence, selection,
|
|
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
|
|
// by "1" and "2," and each dialog message are protected by copyrights registered in
|
|
// the United States and by international treaties.
|
|
//
|
|
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
|
|
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
|
|
//
|
|
// Active Voice Corporation
|
|
// Seattle, Washington
|
|
// USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ConfExplorerTreeView.cpp : Implementation of CConfExplorerTreeView
|
|
#include "stdafx.h"
|
|
#include <stdio.h>
|
|
#include "TapiDialer.h"
|
|
#include "CETreeView.h"
|
|
#include "DlgAddCSvr.h"
|
|
#include "DlgAddLoc.h"
|
|
#include "EnumSite.h"
|
|
|
|
#define DEFAULT_REFRESH_INTERVAL 1800000
|
|
|
|
int CALLBACK CETreeCompare( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CConfExplorerTreeView
|
|
|
|
CConfExplorerTreeView::CConfExplorerTreeView()
|
|
{
|
|
m_pIConfExplorer = NULL;
|
|
m_hIml = NULL;
|
|
m_dwRefreshInterval = DEFAULT_REFRESH_INTERVAL;
|
|
}
|
|
|
|
void CConfExplorerTreeView::FinalRelease()
|
|
{
|
|
ATLTRACE(_T(".enter.CConfExplorerTreeView::FinalRelease().\n"));
|
|
|
|
// Destroy the image list
|
|
if ( m_hIml ) ImageList_Destroy( m_hIml );
|
|
put_hWnd( NULL );
|
|
DELETE_CRITLIST(m_lstServers, m_critServerList);
|
|
put_ConfExplorer( NULL );
|
|
|
|
CComObjectRootEx<CComMultiThreadModel>::FinalRelease();
|
|
}
|
|
|
|
void CConfExplorerTreeView::UpdateData( bool bSaveAndValidate )
|
|
{
|
|
// Need the tree view to store the information in the registry
|
|
_ASSERT( IsWindow(m_wndTree.m_hWnd) );
|
|
if ( !IsWindow(m_wndTree.m_hWnd) ) return;
|
|
|
|
// Variable initialization
|
|
USES_CONVERSION;
|
|
int nCount = 0, nLevel = 1;
|
|
CRegKey regKey;
|
|
|
|
TCHAR szReg[MAX_SERVER_SIZE + 100], szSubKey[50], szText[MAX_SERVER_SIZE];
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_KEY, szReg, ARRAYSIZE(szReg) );
|
|
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE( szText );
|
|
tvi.stateMask = TVIS_EXPANDED | TVIS_SELECTED;
|
|
|
|
// Write information to the registry
|
|
if ( bSaveAndValidate )
|
|
{
|
|
// Open and then clean the registry key
|
|
if ( regKey.Open(HKEY_CURRENT_USER, szReg) == ERROR_SUCCESS )
|
|
{
|
|
regKey.RecurseDeleteKey( NULL );
|
|
regKey.Close();
|
|
}
|
|
|
|
// Write out listbox information to registry (include open/closed state of items)
|
|
if ( regKey.Create(HKEY_CURRENT_USER, szReg) == ERROR_SUCCESS )
|
|
{
|
|
// Save dwRefresh interval
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_REFRESHINTERVAL, szReg, ARRAYSIZE(szReg) );
|
|
regKey.SetValue( m_dwRefreshInterval, szReg );
|
|
|
|
HTREEITEM hItemTemp, hItem = TreeView_GetRoot( m_wndTree.m_hWnd );
|
|
while ( hItem )
|
|
{
|
|
tvi.hItem = hItem;
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
|
|
// Write information out to registry && increment the counter
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
|
|
_sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
|
|
_sntprintf( szReg, ARRAYSIZE(szReg), _T("\"%u\",\"%u\",\"%u\",\"%s\""), nLevel, tvi.iImage, tvi.state, tvi.pszText );
|
|
|
|
regKey.SetValue( szReg, szSubKey );
|
|
nCount++;
|
|
|
|
// Enumerate through child items
|
|
hItemTemp = TreeView_GetChild( m_wndTree.m_hWnd, hItem );
|
|
if ( hItemTemp )
|
|
nLevel++;
|
|
else
|
|
hItemTemp = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
|
|
|
|
while ( !hItemTemp && (hItemTemp = TreeView_GetParent(m_wndTree.m_hWnd, hItem)) != NULL )
|
|
{
|
|
nLevel--;
|
|
hItem = hItemTemp;
|
|
hItemTemp = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
|
|
}
|
|
|
|
// Swap with temporary storage
|
|
hItem = hItemTemp;
|
|
}
|
|
|
|
// Close down the registry
|
|
regKey.Close();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Notification for host application of servers being loaded
|
|
CComPtr<IAVGeneralNotification> pAVGen;
|
|
_Module.get_AVGenNot( &pAVGen );
|
|
|
|
if ( regKey.Open(HKEY_CURRENT_USER, szReg, KEY_READ) == ERROR_SUCCESS )
|
|
{
|
|
// Load dwRefresh interval
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_REFRESHINTERVAL, szReg, ARRAYSIZE(szReg) );
|
|
regKey.QueryValue( m_dwRefreshInterval, szReg );
|
|
|
|
// Clear out the listbox and add default item
|
|
TreeView_DeleteAllItems( m_wndTree.m_hWnd );
|
|
::SendMessage( m_wndTree.m_hWnd, WM_SETREDRAW, false, 0 );
|
|
|
|
HTREEITEM hItem;
|
|
HTREEITEM hParent[MAX_TREE_DEPTH] = {0};
|
|
hParent[0] = TVI_ROOT;
|
|
|
|
// Load up info from registry
|
|
int nCount = 0;
|
|
DWORD dwSize;
|
|
TV_INSERTSTRUCT tvis;
|
|
tvis.hInsertAfter = TVI_LAST;
|
|
|
|
HTREEITEM hItemSelected = NULL;
|
|
|
|
do
|
|
{
|
|
// Read registry entry
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
|
|
_sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
|
|
szSubKey[ARRAYSIZE(szSubKey)-1] = _T('\0');
|
|
dwSize = ARRAYSIZE(szReg) - 1;
|
|
if ( (regKey.QueryValue(szReg, szSubKey, &dwSize) != ERROR_SUCCESS) || !dwSize ) break;
|
|
|
|
// Parse registry entry
|
|
GetToken( 1, _T("\","), szReg, szText ); nLevel = min(MAX_TREE_DEPTH - 1, max(1,_ttoi(szText)));
|
|
GetToken( 2, _T("\","), szReg, szText ); tvi.iImage = tvi.iSelectedImage = _ttoi( szText );
|
|
GetToken( 3, _T("\","), szReg, szText ); tvi.state = (UINT) _ttoi( szText );
|
|
GetToken( 4, _T("\","), szReg, szText );
|
|
|
|
// Add item to the list and set expanded if necessary
|
|
tvis.hParent = hParent[nLevel - 1];
|
|
tvis.item = tvi;
|
|
|
|
// Notify host app of server being added.
|
|
if ( pAVGen )
|
|
{
|
|
if ( tvi.iImage == IMAGE_MYNETWORK )
|
|
{
|
|
pAVGen->fire_AddSiteServer( NULL );
|
|
}
|
|
else if ( tvi.iImage == IMAGE_SERVER )
|
|
{
|
|
BSTR bstrTemp = NULL;
|
|
bstrTemp = SysAllocString( T2COLE(tvi.pszText) );
|
|
pAVGen->fire_AddSiteServer( bstrTemp );
|
|
SysFreeString( bstrTemp );
|
|
}
|
|
}
|
|
|
|
hItem = TreeView_InsertItem( m_wndTree.m_hWnd, &tvis );
|
|
if ( hItem && (tvis.item.state & TVIS_SELECTED) )
|
|
hItemSelected = hItem;
|
|
|
|
hParent[nLevel] = hItem;
|
|
} while ( ++nCount );
|
|
|
|
// Redraw the listbox
|
|
::SendMessage( m_wndTree.m_hWnd, WM_SETREDRAW, true, 0 );
|
|
::InvalidateRect(m_wndTree.m_hWnd, NULL, true);
|
|
|
|
// Make the listbox selection
|
|
if ( hItemSelected )
|
|
m_wndTree.PostMessage( TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItemSelected );
|
|
}
|
|
else
|
|
{
|
|
// Just add the default server to the list
|
|
TreeView_DeleteAllItems( m_wndTree.m_hWnd );
|
|
HTREEITEM hFindItem;
|
|
FindOrAddItem( NULL, NULL, true, false, (long **) &hFindItem );
|
|
|
|
// Notify host app of server being added
|
|
if ( pAVGen )
|
|
pAVGen->fire_AddSiteServer( NULL );
|
|
}
|
|
|
|
// Store list of servers
|
|
EnumerateConfServers();
|
|
}
|
|
}
|
|
|
|
HRESULT CConfExplorerTreeView::EnumerateConfServers()
|
|
{
|
|
if ( !IsWindow(m_wndTree.m_hWnd) ) return E_PENDING;
|
|
|
|
USES_CONVERSION;
|
|
BSTR bstrServer = NULL;
|
|
TCHAR szText[MAX_SERVER_SIZE];
|
|
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE(szText);
|
|
|
|
HTREEITEM hItemServer;
|
|
HTREEITEM hItemLocation = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, TreeView_GetRoot(m_wndTree.m_hWnd) );
|
|
|
|
while ( hItemLocation && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) )
|
|
{
|
|
// Skip location entries in list
|
|
if ( tvi.iImage == IMAGE_LOCATION )
|
|
hItemServer = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItemLocation );
|
|
else
|
|
hItemServer = tvi.hItem;
|
|
|
|
// Server names first
|
|
while ( hItemServer && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) && (tvi.iImage != IMAGE_LOCATION) )
|
|
{
|
|
if ( tvi.iImage == IMAGE_MYNETWORK )
|
|
{
|
|
SysFreeString( bstrServer );
|
|
bstrServer = NULL;
|
|
}
|
|
else
|
|
{
|
|
SysReAllocString( &bstrServer, T2COLE(tvi.pszText) );
|
|
}
|
|
|
|
AddConfServer( bstrServer );
|
|
|
|
// Next Server
|
|
hItemServer = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemServer );
|
|
}
|
|
|
|
// Next Location
|
|
hItemLocation = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemLocation );
|
|
}
|
|
|
|
SysFreeString( bstrServer );
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CConfExplorerTreeView::SetServerState( CConfServerDetails* pcsd )
|
|
{
|
|
if ( !IsWindow(m_wndTree.m_hWnd) ) return;
|
|
|
|
USES_CONVERSION;
|
|
BSTR bstrServer = NULL;
|
|
TCHAR szText[MAX_SERVER_SIZE];
|
|
bool bRefreshDetailsView = false;
|
|
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT | TVIF_STATE;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE(szText);
|
|
tvi.stateMask = TVIS_OVERLAYMASK | TVIS_SELECTED;
|
|
|
|
HTREEITEM hItemServer;
|
|
HTREEITEM hItemLocation = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, TreeView_GetRoot(m_wndTree.m_hWnd) );
|
|
|
|
while ( hItemLocation && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) )
|
|
{
|
|
// Skip location entries in list
|
|
if ( tvi.iImage == IMAGE_LOCATION )
|
|
hItemServer = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItemLocation );
|
|
else
|
|
hItemServer = tvi.hItem;
|
|
|
|
// Server names first
|
|
while ( hItemServer && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) && (tvi.iImage != IMAGE_LOCATION) )
|
|
{
|
|
if ( tvi.iImage == IMAGE_MYNETWORK )
|
|
{
|
|
SysFreeString( bstrServer );
|
|
bstrServer = NULL;
|
|
}
|
|
else
|
|
{
|
|
SysReAllocString( &bstrServer, T2COLE(tvi.pszText) );
|
|
}
|
|
|
|
// Set state if necessary
|
|
if ( pcsd->IsSameAs(bstrServer) )
|
|
{
|
|
if ( !bRefreshDetailsView )
|
|
bRefreshDetailsView = (bool) ((tvi.state & TVIS_SELECTED) != 0);
|
|
|
|
TV_ITEM tvTemp = tvi;
|
|
tvTemp.mask = TVIF_STATE | TVIF_HANDLE;
|
|
tvTemp.state = INDEXTOOVERLAYMASK(pcsd->m_nState);
|
|
tvTemp.stateMask = TVIS_OVERLAYMASK;
|
|
|
|
TreeView_SetItem( m_wndTree.m_hWnd, &tvTemp );
|
|
|
|
// Notify Host app of change
|
|
CComPtr<IAVGeneralNotification> pAVGen;
|
|
if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
|
|
pAVGen->fire_NotifySiteServerStateChange( bstrServer, (ServerState) pcsd->m_nState );
|
|
}
|
|
|
|
// Next Server
|
|
hItemServer = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemServer );
|
|
}
|
|
|
|
// Next Location
|
|
hItemLocation = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemLocation );
|
|
}
|
|
|
|
// Clean up
|
|
SysFreeString( bstrServer );
|
|
|
|
// Invalidate the details view if necessary
|
|
if ( bRefreshDetailsView )
|
|
{
|
|
IConfExplorer *pConfExplorer;
|
|
if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
|
|
{
|
|
IConfExplorerDetailsView *pDetails;
|
|
if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
|
|
{
|
|
HWND hWndDetails;
|
|
pDetails->get_hWnd( &hWndDetails );
|
|
pDetails->Release();
|
|
|
|
::InvalidateRect( hWndDetails, NULL, TRUE );
|
|
}
|
|
pConfExplorer->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
CConfServerDetails* CConfExplorerTreeView::FindConfServer( const OLECHAR *lpoleServer )
|
|
{
|
|
// Should be locked prior to entering!
|
|
_ASSERT( m_critServerList.m_sec.LockCount >= 0 );
|
|
|
|
// NOTE must already have crit locked
|
|
CConfServerDetails *pRet = NULL;
|
|
for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
|
|
{
|
|
if ( (*i)->IsSameAs(lpoleServer) )
|
|
{
|
|
pRet = *i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
HRESULT CConfExplorerTreeView::AddConfServer( BSTR bstrServer )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// $CRIT - enter
|
|
m_critServerList.Lock();
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
CConfServerDetails csTemp;
|
|
bool bSetState = false;
|
|
|
|
if ( !pConfServer )
|
|
{
|
|
// Create a new conf server
|
|
pConfServer = new CConfServerDetails;
|
|
if ( pConfServer )
|
|
{
|
|
SysReAllocString( &pConfServer->m_bstrServer, bstrServer );
|
|
|
|
// Add item to the list
|
|
m_lstServers.push_back( pConfServer );
|
|
csTemp = *pConfServer;
|
|
bSetState = true;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Archive if it's already in the list
|
|
pConfServer->m_bArchived = true;
|
|
}
|
|
m_critServerList.Unlock();
|
|
// $CRIT - exit
|
|
|
|
if ( bSetState ) SetServerState( &csTemp );
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CConfExplorerTreeView::ArchiveConfServers()
|
|
{
|
|
CComPtr<IAVGeneralNotification> pAVGen;
|
|
_Module.get_AVGenNot( &pAVGen );
|
|
|
|
// Walk list of conf servers, destroying ones that don't have their archive bit set
|
|
// $CRIT - enter
|
|
m_critServerList.Lock();
|
|
|
|
bool bContinue = true;
|
|
while ( bContinue && !m_lstServers.empty() )
|
|
{
|
|
bContinue = false;
|
|
CONFSERVERLIST::iterator i = m_lstServers.begin();
|
|
do
|
|
{
|
|
// Not to be archived, delete
|
|
if ( !(*i)->m_bArchived )
|
|
{
|
|
#ifdef _DEBUG
|
|
USES_CONVERSION;
|
|
ATLTRACE(_T(".1.CConfExplorerTreeView::ArchiveConfServers() -- removing %s.\n"), OLE2CT((*i)->m_bstrServer) );
|
|
#endif
|
|
// Notification for host application of server being deleted
|
|
if ( pAVGen ) pAVGen->fire_RemoveSiteServer( (*i)->m_bstrServer );
|
|
|
|
delete (*i);
|
|
m_lstServers.erase( i );
|
|
|
|
bContinue = true;
|
|
break;
|
|
}
|
|
|
|
i++; // increment iterator
|
|
} while ( i != m_lstServers.end() );
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
// $CRIT - exit
|
|
}
|
|
|
|
void CConfExplorerTreeView::CleanConfServers()
|
|
{
|
|
// Clear all archive flags on conf servers
|
|
m_critServerList.Lock();
|
|
for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i !=m_lstServers.end(); i++ )
|
|
(*i)->m_bArchived = false;
|
|
m_critServerList.Unlock();
|
|
|
|
EnumerateConfServers();
|
|
ArchiveConfServers();
|
|
}
|
|
|
|
void CConfExplorerTreeView::RemoveServerFromReg( BSTR bstrServer )
|
|
{
|
|
CRegKey regKey;
|
|
|
|
//
|
|
// Get the 'Conference Services' key name
|
|
//
|
|
TCHAR szReg[MAX_SERVER_SIZE + 100];
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_KEY, szReg, ARRAYSIZE(szReg) );
|
|
|
|
//
|
|
// open the registry key name
|
|
//
|
|
if ( regKey.Open(HKEY_CURRENT_USER, szReg) != ERROR_SUCCESS )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Parse the items
|
|
//
|
|
int nCount = 1;
|
|
TCHAR szSubKey[50];
|
|
while( TRUE)
|
|
{
|
|
//
|
|
// Get the item entry name
|
|
//
|
|
LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
|
|
_sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
|
|
szSubKey[ARRAYSIZE(szSubKey)-1] = _T('\0');
|
|
|
|
//
|
|
// Get the key value
|
|
//
|
|
DWORD dwValue = 255;
|
|
TCHAR szValue[256];
|
|
LONG lReturn = regKey.QueryValue( szValue, szSubKey, &dwValue);
|
|
if( lReturn != ERROR_SUCCESS )
|
|
{
|
|
// Don't go further
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Let see if is our server
|
|
//
|
|
|
|
if( wcsstr( szValue, bstrServer) != NULL )
|
|
{
|
|
// We find the server, let's delete it!
|
|
regKey.DeleteValue( szSubKey );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Go to the next entry
|
|
//
|
|
nCount++;
|
|
}
|
|
|
|
//
|
|
// Close the key
|
|
//
|
|
regKey.Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT CConfExplorerTreeView::OnSelChanged( LPNMHDR lpnmHdr )
|
|
{
|
|
CConfServerDetails *pConfServer = NULL;
|
|
CConfServerDetails csTemp;
|
|
|
|
BSTR bstrLocation = NULL, bstrServer = NULL;
|
|
if ( SUCCEEDED(GetSelection(&bstrLocation, &bstrServer)) )
|
|
{
|
|
// Get a copy of the information stored for the server
|
|
m_critServerList.Lock();
|
|
|
|
pConfServer = FindConfServer( bstrServer );
|
|
if ( pConfServer )
|
|
csTemp = *pConfServer;
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
// Clean up
|
|
SysFreeString( bstrLocation );
|
|
SysFreeString( bstrServer );
|
|
}
|
|
|
|
// Set the details list with the information stored for this server location
|
|
IConfExplorer *pConfExplorer;
|
|
if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
|
|
{
|
|
IConfExplorerDetailsView *pDetails;
|
|
if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
|
|
{
|
|
pDetails->UpdateConfList( (long *) &csTemp.m_lstConfs );
|
|
pDetails->Release();
|
|
}
|
|
pConfExplorer->Release();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
LRESULT CConfExplorerTreeView::OnEndLabelEdit( TV_DISPINFO *pInfo )
|
|
{
|
|
if ( !pInfo->item.pszText ) return 0;
|
|
|
|
// Make sure that we're changing the text of something valid
|
|
TCHAR szText[MAX_SERVER_SIZE + 1];
|
|
TV_ITEM tvi;
|
|
tvi.hItem = pInfo->item.hItem;
|
|
tvi.mask = TVIF_IMAGE | TVIF_TEXT | TVIF_STATE;
|
|
tvi.stateMask = TVIS_OVERLAYMASK;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE(szText) - 1;
|
|
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
if ( (tvi.iImage == IMAGE_ROOT) || (tvi.iImage == IMAGE_MYNETWORK) ) return 0;
|
|
|
|
// Make sure the server isn't presently being queried
|
|
if ( (tvi.state >> 8) == SERVER_QUERYING )
|
|
{
|
|
CErrorInfo er( IDS_ER_RENAME_TREEVIEW_ITEM, IDS_ER_RENAME_UNALLOWED_IN_QUERY );
|
|
er.set_hr( E_ABORT );
|
|
return 0;
|
|
}
|
|
|
|
// Make sure that we have something to actually change
|
|
pInfo->item.mask = TVIF_TEXT;
|
|
TreeView_SetItem( m_wndTree.m_hWnd, &pInfo->item );
|
|
|
|
// If the user is renaming a conference server, we need to go out and change the
|
|
// information stored in the ConfDetails object for the server
|
|
if ( tvi.iImage == IMAGE_SERVER )
|
|
{
|
|
USES_CONVERSION;
|
|
m_critServerList.Lock();
|
|
CConfServerDetails *pDetails = FindConfServer( T2COLE(tvi.pszText) );
|
|
if ( pDetails )
|
|
SysReAllocString( &pDetails->m_bstrServer, T2COLE(pInfo->item.pszText) );
|
|
|
|
m_critServerList.Unlock();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// COM interface methods and properties
|
|
//
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::get_ConfExplorer(IConfExplorer **ppVal)
|
|
{
|
|
HRESULT hr = E_PENDING;
|
|
Lock();
|
|
if ( m_pIConfExplorer )
|
|
hr = m_pIConfExplorer->QueryInterface(IID_IConfExplorer, (void **) ppVal );
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::put_ConfExplorer(IConfExplorer * newVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Lock();
|
|
RELEASE( m_pIConfExplorer );
|
|
if ( newVal )
|
|
hr = newVal->QueryInterface( IID_IConfExplorer, (void **) &m_pIConfExplorer );
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::get_hWnd(HWND *pVal)
|
|
{
|
|
*pVal = m_wndTree.m_hWnd;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::put_hWnd(HWND newVal)
|
|
{
|
|
if ( IsWindow(newVal) )
|
|
{
|
|
// Make sure the window isn't already subclassed
|
|
if ( m_wndTree.m_hWnd ) m_wndTree.UnsubclassWindow();
|
|
|
|
// Set up tree view
|
|
if ( m_wndTree.SubclassWindow(newVal) )
|
|
{
|
|
// Hook up link
|
|
m_wndTree.m_pTreeView = this;
|
|
|
|
// Verify that window has proper styles
|
|
::SetWindowLongPtr( m_wndTree.m_hWnd, GWL_STYLE, GetWindowLongPtr(m_wndTree.m_hWnd, GWL_STYLE) |
|
|
TVS_HASLINES |
|
|
TVS_HASBUTTONS |
|
|
TVS_SHOWSELALWAYS |
|
|
TVS_DISABLEDRAGDROP );
|
|
|
|
// Setup image lists for Tree View
|
|
InitImageLists();
|
|
UpdateData( false );
|
|
}
|
|
}
|
|
else if ( IsWindow(m_wndTree.m_hWnd) )
|
|
{
|
|
// Shutdown
|
|
UpdateData( true );
|
|
TreeView_DeleteAllItems( m_wndTree.m_hWnd );
|
|
m_wndTree.UnsubclassWindow();
|
|
m_wndTree.m_pTreeView = NULL;
|
|
m_wndTree.m_hWnd = NULL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::get_dwRefreshInterval(DWORD * pVal)
|
|
{
|
|
*pVal = m_dwRefreshInterval;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::put_dwRefreshInterval(DWORD newVal)
|
|
{
|
|
m_dwRefreshInterval = newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::Select(BSTR bstrName)
|
|
{
|
|
HRESULT hr;
|
|
HTREEITEM hItem;
|
|
if ( SUCCEEDED(hr = FindOrAddItem(NULL, bstrName, false, false, (long **) &hItem)) )
|
|
TreeView_SelectItem( m_wndTree.m_hWnd, hItem );
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::SelectItem(short nSel)
|
|
{
|
|
// TODO: Add your implementation code here
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::Refresh()
|
|
{
|
|
// Load up the conference explorer control
|
|
if ( !m_wndTree.m_hWnd ) return E_PENDING;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::AddLocation(BSTR bstrLocation)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// Show dialog that let's use add a server
|
|
CDlgAddLocation dlg;
|
|
if ( bstrLocation )
|
|
SysReAllocString( &dlg.m_bstrLocation, bstrLocation );
|
|
|
|
if ( dlg.DoModal(_Module.GetParentWnd()) == IDOK )
|
|
{
|
|
// Add items to the tree view
|
|
HTREEITEM hItem;
|
|
hr = FindOrAddItem( dlg.m_bstrLocation, NULL, true, true, (long **) &hItem );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::AddServer( BSTR bstrServer )
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if ( bstrServer && !SysStringLen(bstrServer) ) bstrServer = NULL;
|
|
|
|
// Show dialog that let's use add a server
|
|
CDlgAddConfServer dlg;
|
|
if ( !bstrServer )
|
|
{
|
|
// Only want location from current selection
|
|
GetSelection( &dlg.m_bstrLocation, &dlg.m_bstrServer );
|
|
|
|
// Never set server names
|
|
SysFreeString( dlg.m_bstrServer );
|
|
dlg.m_bstrServer = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Use user supplied parameters
|
|
dlg.m_bstrServer = SysAllocString( bstrServer );
|
|
}
|
|
|
|
if ( dlg.DoModal(_Module.GetParentWnd()) == IDOK )
|
|
{
|
|
TCHAR szFormat[255];
|
|
TCHAR szMessage[255 + MAX_SERVER_SIZE];
|
|
CConfServerDetails *pConfServer = NULL;
|
|
bool bMyNetwork = false;
|
|
|
|
// If the server to add matches "(My Network)" then just ignore it as a duplicate
|
|
::LoadString( _Module.GetResourceInstance(), IDS_DEFAULT_SERVER, szFormat, ARRAYSIZE(szFormat) );
|
|
if ( !_tcsicmp(szFormat, OLE2CT(dlg.m_bstrServer)) )
|
|
{
|
|
bMyNetwork = true;
|
|
}
|
|
else
|
|
{
|
|
m_critServerList.Lock();
|
|
pConfServer = FindConfServer( dlg.m_bstrServer );
|
|
m_critServerList.Unlock();
|
|
}
|
|
|
|
// Does the conference server already exist?
|
|
if ( !bMyNetwork && !pConfServer )
|
|
{
|
|
// Add items to the tree view
|
|
HTREEITEM hItem;
|
|
if ( SUCCEEDED(hr = FindOrAddItem(NULL, dlg.m_bstrServer, true, false, (long **) &hItem)) )
|
|
{
|
|
AddConfServer( dlg.m_bstrServer );
|
|
|
|
// Notify host app of server addition
|
|
CComPtr<IAVGeneralNotification> pAVGen;
|
|
if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
|
|
pAVGen->fire_AddSiteServer( dlg.m_bstrServer );
|
|
|
|
// Publish our information on the server
|
|
CComPtr<IAVTapi> pAVTapi;
|
|
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
|
|
pAVTapi->RegisterUser( true, dlg.m_bstrServer );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Notify user that the server already exists
|
|
::LoadString( _Module.GetResourceInstance(), IDS_CONFEXP_SERVEREXISTS, szFormat, ARRAYSIZE(szFormat) );
|
|
_sntprintf( szMessage, ARRAYSIZE(szMessage), szFormat, OLE2CT(dlg.m_bstrServer) );
|
|
szMessage[ARRAYSIZE(szMessage)-1] = _T('\0');
|
|
|
|
_Module.DoMessageBox( szMessage, MB_OK | MB_ICONINFORMATION, false );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::RemoveServer(BSTR bstrLocation, BSTR bstrName )
|
|
{
|
|
if ( !IsWindow(m_wndTree.m_hWnd) ) return E_FAIL;
|
|
HTREEITEM hItem = NULL;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// if all args NULL that means delete currently selected item
|
|
if ( !bstrLocation && !bstrName )
|
|
{
|
|
hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
|
|
}
|
|
else
|
|
{
|
|
if ( FAILED(FindOrAddItem(bstrLocation, bstrName, false, false, (long **) &hItem)) )
|
|
hItem = NULL;
|
|
}
|
|
|
|
// Have an item to delete?
|
|
if ( hItem && (hItem != TreeView_GetRoot(m_wndTree.m_hWnd)) )
|
|
{
|
|
TCHAR szText[MAX_SERVER_SIZE];
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_IMAGE | TVIF_HANDLE | TVIF_TEXT;
|
|
tvi.hItem = hItem;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE(szText);
|
|
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
if ( tvi.iImage != IMAGE_MYNETWORK )
|
|
{
|
|
TCHAR szFormat[255];
|
|
TCHAR szMessage[255 + MAX_SERVER_SIZE];
|
|
::LoadString( _Module.GetResourceInstance(), IDS_CONFIRM_REMOVE_SERVER, szFormat, ARRAYSIZE(szFormat) );
|
|
_sntprintf( szMessage, ARRAYSIZE(szMessage), szFormat, tvi.pszText );
|
|
|
|
// Confirm
|
|
if ( _Module.DoMessageBox(szMessage, MB_YESNO | MB_ICONQUESTION, false) == IDYES )
|
|
{
|
|
if ( TreeView_DeleteItem(m_wndTree.m_hWnd, hItem) )
|
|
{
|
|
RemoveServerFromReg( bstrName );
|
|
CleanConfServers();
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::FindOrAddItem(BSTR bstrLocation, BSTR bstrServer, BOOL bAddItem, BOOL bLocationOnly, long **pphItem)
|
|
{
|
|
#undef FETCH_STRING
|
|
#define FETCH_STRING( _IDS_ ) \
|
|
LoadString( _Module.GetResourceInstance(), _IDS_, szJunk, ARRAYSIZE(szJunk) ); \
|
|
SysReAllocString( &bstrItemText, T2COLE(szJunk) );
|
|
|
|
if ( !IsWindow(m_wndTree.m_hWnd) ) return E_FAIL;
|
|
|
|
HRESULT hr = S_OK;
|
|
_ASSERT( pphItem );
|
|
*pphItem = NULL;
|
|
|
|
USES_CONVERSION;
|
|
TCHAR szText[MAX_SERVER_SIZE], szJunk[MAX_SERVER_SIZE];
|
|
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE( szText );
|
|
tvi.stateMask = TVIS_EXPANDED;
|
|
|
|
TV_INSERTSTRUCT tvis;
|
|
tvis.hParent = TVI_ROOT;
|
|
tvis.hInsertAfter = TVI_SORT;
|
|
|
|
HTREEITEM hItem = TreeView_GetRoot( m_wndTree.m_hWnd );
|
|
|
|
BSTR bstrItemText = NULL;
|
|
int nImage;
|
|
int nEnd = (bLocationOnly) ? IMAGE_LOCATION : IMAGE_SERVER;
|
|
|
|
for ( int i = 0; i <= nEnd; i++ )
|
|
{
|
|
// Pick the string based on how deep in the search we are
|
|
nImage = i;
|
|
|
|
switch ( i )
|
|
{
|
|
case IMAGE_ROOT: FETCH_STRING( IDS_CONFSERV_ROOT ); break;
|
|
case IMAGE_LOCATION: SysReAllocString( &bstrItemText, bstrLocation ); break;
|
|
|
|
case IMAGE_SERVER:
|
|
if ( bstrServer )
|
|
{
|
|
SysReAllocString( &bstrItemText, bstrServer );
|
|
}
|
|
else
|
|
{
|
|
FETCH_STRING( IDS_DEFAULT_SERVER );
|
|
nImage = IMAGE_MYNETWORK;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( bstrItemText )
|
|
{
|
|
while ( hItem )
|
|
{
|
|
tvi.hItem = hItem;
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
|
|
// Found item
|
|
if ( !_tcsicmp(OLE2CT(bstrItemText), tvi.pszText) )
|
|
break;
|
|
|
|
hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
|
|
}
|
|
|
|
// If no item is found, should we add one?
|
|
if ( !hItem )
|
|
{
|
|
if ( bAddItem )
|
|
{
|
|
_tcscpy( tvi.pszText, OLE2CT(bstrItemText) );
|
|
tvi.iSelectedImage = tvi.iImage = nImage;
|
|
tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE;
|
|
tvis.item = tvi;
|
|
hItem = TreeView_InsertItem( m_wndTree.m_hWnd, &tvis );
|
|
if ( hItem )
|
|
TreeView_SelectItem( m_wndTree.m_hWnd, hItem );
|
|
}
|
|
else
|
|
{
|
|
// No item found and can't add
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set up parent information
|
|
if ( hItem )
|
|
{
|
|
*pphItem = (long *) hItem; // return value
|
|
tvis.hParent = hItem;
|
|
hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItem );
|
|
}
|
|
|
|
SysFreeString( bstrItemText );
|
|
bstrItemText = NULL;
|
|
}
|
|
}
|
|
|
|
// Clean-up
|
|
SysFreeString( bstrItemText );
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::GetSelection(BSTR * pbstrLocation, BSTR * pbstrServer)
|
|
{
|
|
// Initialize [in,out] parameters
|
|
*pbstrLocation = *pbstrServer = NULL;
|
|
|
|
HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
|
|
if ( !hItem ) return E_PENDING;
|
|
|
|
USES_CONVERSION;
|
|
HRESULT hr = E_FAIL;
|
|
TCHAR szText[MAX_SERVER_SIZE];
|
|
TV_ITEM tvi;
|
|
tvi.mask = TVIF_TEXT | TVIF_IMAGE;
|
|
tvi.pszText = szText;
|
|
tvi.cchTextMax = ARRAYSIZE( szText );
|
|
tvi.hItem = hItem;
|
|
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
switch ( tvi.iImage)
|
|
{
|
|
case IMAGE_MYNETWORK:
|
|
// This is the default (NULL, NULL, NULL)
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case IMAGE_SERVER:
|
|
hr = S_OK;
|
|
*pbstrServer = SysAllocString( T2COLE(tvi.pszText) );
|
|
// drop out here if we don't have a parent item
|
|
if ( (tvi.hItem = TreeView_GetParent(m_wndTree.m_hWnd, tvi.hItem)) == NULL )
|
|
break;
|
|
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
|
|
case IMAGE_LOCATION:
|
|
// Don't return root item itself
|
|
if ( tvi.hItem != TreeView_GetRoot(m_wndTree.m_hWnd) )
|
|
*pbstrLocation = SysAllocString( T2COLE(tvi.pszText) );
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CConfExplorerTreeView::InitImageLists()
|
|
{
|
|
if ( m_hIml || !IsWindow(m_wndTree.m_hWnd) ) return;
|
|
|
|
// Normal
|
|
if ( (m_hIml = ImageList_LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_LST_CONFSERV), 16, 9, RGB(255, 0, 255))) != NULL )
|
|
{
|
|
// Overlay images for various states
|
|
for ( int i = 1; i < 4; i++ )
|
|
ImageList_SetOverlayImage( m_hIml, 5 + i, i );
|
|
|
|
TreeView_SetImageList( m_wndTree.m_hWnd, m_hIml, TVSIL_NORMAL );
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::CanRemoveServer()
|
|
{
|
|
if ( IsWindow(m_wndTree.m_hWnd) )
|
|
{
|
|
HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
|
|
if ( hItem && (hItem != TreeView_GetRoot(m_wndTree.m_hWnd)) )
|
|
{
|
|
TV_ITEM tvi = {0};
|
|
tvi.mask = TVIF_HANDLE | TVIF_IMAGE;
|
|
tvi.hItem = hItem;
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
if ( tvi.iImage != IMAGE_MYNETWORK )
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::ForceConfServerForEnum( BSTR bstrServer )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
m_critServerList.Lock();
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
CConfServerDetails csTemp;
|
|
|
|
if ( pConfServer && (pConfServer->m_nState != SERVER_QUERYING) )
|
|
{
|
|
pConfServer->m_nState = SERVER_UNKNOWN;
|
|
pConfServer->m_dwTickCount = 0;
|
|
DELETE_LIST( pConfServer->m_lstConfs );
|
|
DELETE_LIST( pConfServer->m_lstPersons );
|
|
|
|
csTemp.CopyLocalProperties( *pConfServer );
|
|
hr = S_OK;
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
// Repaint if succeeded
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
SetServerState( &csTemp );
|
|
if ( IsWindow(m_wndTree.m_hWnd) ) m_wndTree.RedrawWindow();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::GetConfServerForEnum(BSTR * pbstrServer )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CConfServerDetails *pConfServer = NULL;
|
|
CConfServerDetails csTemp;
|
|
|
|
m_critServerList.Lock();
|
|
for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
|
|
{
|
|
if ( ((*i)->m_nState != SERVER_QUERYING) &&
|
|
(!(*i)->m_dwTickCount || ((GetTickCount() - (*i)->m_dwTickCount) > m_dwRefreshInterval)) )
|
|
{
|
|
if ( !pConfServer || ((GetTickCount() - pConfServer->m_dwTickCount) < (GetTickCount() - (*i)->m_dwTickCount)) )
|
|
pConfServer = *i;
|
|
}
|
|
}
|
|
|
|
// This is the conference server that is most in need of updating
|
|
if ( pConfServer )
|
|
{
|
|
*pbstrServer = SysAllocString( pConfServer->m_bstrServer );
|
|
pConfServer->m_nState = SERVER_QUERYING;
|
|
|
|
csTemp = *pConfServer;
|
|
hr = S_OK;
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
if ( SUCCEEDED(hr) ) SetServerState( &csTemp );
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::SetConfServerForEnum(BSTR bstrServer, long *pList, long *pListPersons, DWORD dwTicks, BOOL bUpdate)
|
|
{
|
|
m_critServerList.Lock();
|
|
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
CConfServerDetails csTemp;
|
|
bool bSetState = false;
|
|
|
|
if ( pConfServer )
|
|
{
|
|
pConfServer->m_dwTickCount = dwTicks;
|
|
DELETE_LIST( pConfServer->m_lstConfs );
|
|
DELETE_LIST( pConfServer->m_lstPersons );
|
|
|
|
if ( pList )
|
|
{
|
|
///////////////////////////////////////////
|
|
// Add all of the conference servers
|
|
{
|
|
CONFDETAILSLIST::iterator i, iEnd = ((CONFDETAILSLIST *) pList)->end();
|
|
for ( i = ((CONFDETAILSLIST *) pList)->begin(); i != iEnd; i++ )
|
|
{
|
|
CConfDetails *pDetails = new CConfDetails;
|
|
if ( pDetails )
|
|
{
|
|
*pDetails = *(*i);
|
|
pConfServer->m_lstConfs.push_back( pDetails );
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////
|
|
// Add all of the people
|
|
{
|
|
if ( pListPersons )
|
|
{
|
|
PERSONDETAILSLIST::iterator i, iEnd = ((PERSONDETAILSLIST *) pListPersons)->end();
|
|
for ( i = ((PERSONDETAILSLIST *) pListPersons)->begin(); i != iEnd; i++ )
|
|
{
|
|
CPersonDetails *pDetails = new CPersonDetails;
|
|
if ( pDetails )
|
|
{
|
|
*pDetails = *(*i);
|
|
pConfServer->m_lstPersons.push_back( pDetails );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pConfServer->m_nState = SERVER_OK;
|
|
}
|
|
else
|
|
{
|
|
// Server connection broken
|
|
pConfServer->m_nState = SERVER_NOT_RESPONDING;
|
|
}
|
|
|
|
csTemp = *pConfServer;
|
|
bSetState = true;
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
// Force update of list if selected
|
|
if ( bSetState ) SetServerState( &csTemp );
|
|
|
|
if ( bUpdate )
|
|
{
|
|
IConfExplorer *pConfExplorer;
|
|
if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
|
|
{
|
|
BSTR bstrMyLocation = NULL, bstrMyServer = NULL;
|
|
if ( SUCCEEDED(GetSelection(&bstrMyLocation, &bstrMyServer)) )
|
|
{
|
|
if ( csTemp.IsSameAs(bstrMyServer) )
|
|
{
|
|
IConfExplorerDetailsView *pDetails;
|
|
if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
|
|
{
|
|
pDetails->UpdateConfList( (long *) &csTemp.m_lstConfs );
|
|
pDetails->Release();
|
|
}
|
|
}
|
|
|
|
SysFreeString( bstrMyLocation );
|
|
SysFreeString( bstrMyServer );
|
|
}
|
|
pConfExplorer->Release();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::BuildJoinConfList(long * pList, VARIANT_BOOL bAllConfs )
|
|
{
|
|
_ASSERT( pList );
|
|
|
|
m_critServerList.Lock();
|
|
for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
|
|
(*i)->BuildJoinConfList( (CONFDETAILSLIST *) pList, bAllConfs );
|
|
m_critServerList.Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::get_nServerState(ServerState * pVal)
|
|
{
|
|
// default return value
|
|
*pVal = SERVER_INVALID;
|
|
|
|
HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
|
|
if ( hItem )
|
|
{
|
|
TV_ITEM tvi;
|
|
tvi.hItem = hItem;
|
|
tvi.mask = TVIF_HANDLE | TVIF_STATE | TVIF_IMAGE;
|
|
tvi.stateMask = TVIS_OVERLAYMASK;
|
|
|
|
TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
|
|
|
|
switch ( tvi.iImage )
|
|
{
|
|
case IMAGE_SERVER:
|
|
case IMAGE_MYNETWORK:
|
|
switch ( tvi.state >> 8 )
|
|
{
|
|
case 0: *pVal = SERVER_OK; break;
|
|
case 1: *pVal = SERVER_UNKNOWN; break;
|
|
case 2: *pVal = SERVER_NOT_RESPONDING; break;
|
|
case 3: *pVal = SERVER_QUERYING; break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::BuildJoinConfListText(long * pList, BSTR bstrText)
|
|
{
|
|
_ASSERT( pList );
|
|
|
|
m_critServerList.Lock();
|
|
for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
|
|
(*i)->BuildJoinConfList( (CONFDETAILSLIST *) pList, bstrText );
|
|
m_critServerList.Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::RenameServer()
|
|
{
|
|
HTREEITEM hItem;
|
|
hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
|
|
if ( hItem )
|
|
TreeView_EditLabel( m_wndTree.m_hWnd, hItem );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::RemoveConference(BSTR bstrServer, BSTR bstrName)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
m_critServerList.Lock();
|
|
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
if ( pConfServer )
|
|
{
|
|
if ( SUCCEEDED(hr = pConfServer->RemoveConference(bstrName)) )
|
|
{
|
|
IConfExplorer *pConfExplorer;
|
|
if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
|
|
{
|
|
IConfExplorerDetailsView *pDetails;
|
|
if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
|
|
{
|
|
pDetails->UpdateConfList( (long *) &pConfServer->m_lstConfs );
|
|
pDetails->Release();
|
|
}
|
|
pConfExplorer->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::AddPerson(BSTR bstrServer, ITDirectoryObject * pDirObj)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
int nCount = 0;
|
|
bool bRetry;
|
|
bool bSuccess = false;
|
|
|
|
// Spin in loop waiting to add person to the conference
|
|
do
|
|
{
|
|
bRetry = false;
|
|
m_critServerList.Lock();
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
if ( pConfServer )
|
|
{
|
|
if ( pConfServer->m_nState == SERVER_QUERYING )
|
|
{
|
|
ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- sleeping, server being queried.\n"));
|
|
bRetry = true;
|
|
}
|
|
else if ( SUCCEEDED(hr = pConfServer->AddPerson(bstrServer, pDirObj)) )
|
|
{
|
|
ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- adding to list.\n"));
|
|
bSuccess = true;
|
|
}
|
|
}
|
|
m_critServerList.Unlock();
|
|
|
|
// Sleep while we're waiting
|
|
if ( bRetry )
|
|
Sleep( 3000 );
|
|
|
|
} while ( bRetry && (++nCount < 20) );
|
|
ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- safely out of spin loop.\n"));
|
|
|
|
// Notification for host application of servers being loaded
|
|
if ( bSuccess )
|
|
{
|
|
CComPtr<IAVGeneralNotification> pAVGen;
|
|
_Module.get_AVGenNot( &pAVGen );
|
|
if ( pAVGen )
|
|
pAVGen->fire_AddUser( NULL, NULL, NULL );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::AddConference(BSTR bstrServer, ITDirectoryObject * pDirObj)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
m_critServerList.Lock();
|
|
|
|
CConfServerDetails *pConfServer = FindConfServer( bstrServer );
|
|
if ( pConfServer )
|
|
{
|
|
if ( SUCCEEDED(hr = pConfServer->AddConference(bstrServer, pDirObj)) )
|
|
{
|
|
IConfExplorer *pConfExplorer;
|
|
if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
|
|
{
|
|
IConfExplorerDetailsView *pDetails;
|
|
if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
|
|
{
|
|
pDetails->UpdateConfList( (long *) &pConfServer->m_lstConfs );
|
|
pDetails->Release();
|
|
}
|
|
pConfExplorer->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_critServerList.Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CConfExplorerTreeView::EnumSiteServer(BSTR bstrName, IEnumSiteServer * * ppEnum)
|
|
{
|
|
// First make a copy of what we have for the server
|
|
CConfServerDetails *pConfServer = NULL;
|
|
CConfServerDetails csTemp;
|
|
|
|
m_critServerList.Lock();
|
|
pConfServer = FindConfServer( bstrName );
|
|
if ( pConfServer )
|
|
csTemp = *pConfServer;
|
|
m_critServerList.Unlock();
|
|
|
|
// Bad server name
|
|
if ( !pConfServer )
|
|
{
|
|
#ifdef _DEBUG
|
|
USES_CONVERSION;
|
|
ATLTRACE(_T(".warning.CConfExplorerTreeView::EnumSiteServer(%s) name not found in list.\n"), OLE2CT(bstrName) );
|
|
#endif
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Make a copy of everything...
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
*ppEnum = new CComObject<CEnumSiteServer>;
|
|
if ( *ppEnum )
|
|
hr = (*ppEnum)->BuildList( (long *) &csTemp.m_lstPersons );
|
|
|
|
return hr;
|
|
}
|
|
|