Leaked source code of windows server 2003
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

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. // ConfExplorerTreeView.cpp : Implementation of CConfExplorerTreeView
  23. #include "stdafx.h"
  24. #include <stdio.h>
  25. #include "TapiDialer.h"
  26. #include "CETreeView.h"
  27. #include "DlgAddCSvr.h"
  28. #include "DlgAddLoc.h"
  29. #include "EnumSite.h"
  30. #define DEFAULT_REFRESH_INTERVAL 1800000
  31. int CALLBACK CETreeCompare( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  32. {
  33. return 0;
  34. }
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CConfExplorerTreeView
  37. CConfExplorerTreeView::CConfExplorerTreeView()
  38. {
  39. m_pIConfExplorer = NULL;
  40. m_hIml = NULL;
  41. m_dwRefreshInterval = DEFAULT_REFRESH_INTERVAL;
  42. }
  43. void CConfExplorerTreeView::FinalRelease()
  44. {
  45. ATLTRACE(_T(".enter.CConfExplorerTreeView::FinalRelease().\n"));
  46. // Destroy the image list
  47. if ( m_hIml ) ImageList_Destroy( m_hIml );
  48. put_hWnd( NULL );
  49. DELETE_CRITLIST(m_lstServers, m_critServerList);
  50. put_ConfExplorer( NULL );
  51. CComObjectRootEx<CComMultiThreadModel>::FinalRelease();
  52. }
  53. void CConfExplorerTreeView::UpdateData( bool bSaveAndValidate )
  54. {
  55. // Need the tree view to store the information in the registry
  56. _ASSERT( IsWindow(m_wndTree.m_hWnd) );
  57. if ( !IsWindow(m_wndTree.m_hWnd) ) return;
  58. // Variable initialization
  59. USES_CONVERSION;
  60. int nCount = 0, nLevel = 1;
  61. CRegKey regKey;
  62. TCHAR szReg[MAX_SERVER_SIZE + 100], szSubKey[50], szText[MAX_SERVER_SIZE];
  63. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_KEY, szReg, ARRAYSIZE(szReg) );
  64. TV_ITEM tvi = {0};
  65. tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  66. tvi.pszText = szText;
  67. tvi.cchTextMax = ARRAYSIZE( szText );
  68. tvi.stateMask = TVIS_EXPANDED | TVIS_SELECTED;
  69. // Write information to the registry
  70. if ( bSaveAndValidate )
  71. {
  72. // Open and then clean the registry key
  73. if ( regKey.Open(HKEY_CURRENT_USER, szReg) == ERROR_SUCCESS )
  74. {
  75. regKey.RecurseDeleteKey( NULL );
  76. regKey.Close();
  77. }
  78. // Write out listbox information to registry (include open/closed state of items)
  79. if ( regKey.Create(HKEY_CURRENT_USER, szReg) == ERROR_SUCCESS )
  80. {
  81. // Save dwRefresh interval
  82. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_REFRESHINTERVAL, szReg, ARRAYSIZE(szReg) );
  83. regKey.SetValue( m_dwRefreshInterval, szReg );
  84. HTREEITEM hItemTemp, hItem = TreeView_GetRoot( m_wndTree.m_hWnd );
  85. while ( hItem )
  86. {
  87. tvi.hItem = hItem;
  88. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  89. // Write information out to registry && increment the counter
  90. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
  91. _sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
  92. _sntprintf( szReg, ARRAYSIZE(szReg), _T("\"%u\",\"%u\",\"%u\",\"%s\""), nLevel, tvi.iImage, tvi.state, tvi.pszText );
  93. regKey.SetValue( szReg, szSubKey );
  94. nCount++;
  95. // Enumerate through child items
  96. hItemTemp = TreeView_GetChild( m_wndTree.m_hWnd, hItem );
  97. if ( hItemTemp )
  98. nLevel++;
  99. else
  100. hItemTemp = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
  101. while ( !hItemTemp && (hItemTemp = TreeView_GetParent(m_wndTree.m_hWnd, hItem)) != NULL )
  102. {
  103. nLevel--;
  104. hItem = hItemTemp;
  105. hItemTemp = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
  106. }
  107. // Swap with temporary storage
  108. hItem = hItemTemp;
  109. }
  110. // Close down the registry
  111. regKey.Close();
  112. }
  113. }
  114. else
  115. {
  116. // Notification for host application of servers being loaded
  117. CComPtr<IAVGeneralNotification> pAVGen;
  118. _Module.get_AVGenNot( &pAVGen );
  119. if ( regKey.Open(HKEY_CURRENT_USER, szReg, KEY_READ) == ERROR_SUCCESS )
  120. {
  121. // Load dwRefresh interval
  122. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_REFRESHINTERVAL, szReg, ARRAYSIZE(szReg) );
  123. regKey.QueryValue( m_dwRefreshInterval, szReg );
  124. // Clear out the listbox and add default item
  125. TreeView_DeleteAllItems( m_wndTree.m_hWnd );
  126. ::SendMessage( m_wndTree.m_hWnd, WM_SETREDRAW, false, 0 );
  127. HTREEITEM hItem;
  128. HTREEITEM hParent[MAX_TREE_DEPTH] = {0};
  129. hParent[0] = TVI_ROOT;
  130. // Load up info from registry
  131. int nCount = 0;
  132. DWORD dwSize;
  133. TV_INSERTSTRUCT tvis;
  134. tvis.hInsertAfter = TVI_LAST;
  135. HTREEITEM hItemSelected = NULL;
  136. do
  137. {
  138. // Read registry entry
  139. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
  140. _sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
  141. szSubKey[ARRAYSIZE(szSubKey)-1] = _T('\0');
  142. dwSize = ARRAYSIZE(szReg) - 1;
  143. if ( (regKey.QueryValue(szReg, szSubKey, &dwSize) != ERROR_SUCCESS) || !dwSize ) break;
  144. // Parse registry entry
  145. GetToken( 1, _T("\","), szReg, szText ); nLevel = min(MAX_TREE_DEPTH - 1, max(1,_ttoi(szText)));
  146. GetToken( 2, _T("\","), szReg, szText ); tvi.iImage = tvi.iSelectedImage = _ttoi( szText );
  147. GetToken( 3, _T("\","), szReg, szText ); tvi.state = (UINT) _ttoi( szText );
  148. GetToken( 4, _T("\","), szReg, szText );
  149. // Add item to the list and set expanded if necessary
  150. tvis.hParent = hParent[nLevel - 1];
  151. tvis.item = tvi;
  152. // Notify host app of server being added.
  153. if ( pAVGen )
  154. {
  155. if ( tvi.iImage == IMAGE_MYNETWORK )
  156. {
  157. pAVGen->fire_AddSiteServer( NULL );
  158. }
  159. else if ( tvi.iImage == IMAGE_SERVER )
  160. {
  161. BSTR bstrTemp = NULL;
  162. bstrTemp = SysAllocString( T2COLE(tvi.pszText) );
  163. pAVGen->fire_AddSiteServer( bstrTemp );
  164. SysFreeString( bstrTemp );
  165. }
  166. }
  167. hItem = TreeView_InsertItem( m_wndTree.m_hWnd, &tvis );
  168. if ( hItem && (tvis.item.state & TVIS_SELECTED) )
  169. hItemSelected = hItem;
  170. hParent[nLevel] = hItem;
  171. } while ( ++nCount );
  172. // Redraw the listbox
  173. ::SendMessage( m_wndTree.m_hWnd, WM_SETREDRAW, true, 0 );
  174. ::InvalidateRect(m_wndTree.m_hWnd, NULL, true);
  175. // Make the listbox selection
  176. if ( hItemSelected )
  177. m_wndTree.PostMessage( TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItemSelected );
  178. }
  179. else
  180. {
  181. // Just add the default server to the list
  182. TreeView_DeleteAllItems( m_wndTree.m_hWnd );
  183. HTREEITEM hFindItem;
  184. FindOrAddItem( NULL, NULL, true, false, (long **) &hFindItem );
  185. // Notify host app of server being added
  186. if ( pAVGen )
  187. pAVGen->fire_AddSiteServer( NULL );
  188. }
  189. // Store list of servers
  190. EnumerateConfServers();
  191. }
  192. }
  193. HRESULT CConfExplorerTreeView::EnumerateConfServers()
  194. {
  195. if ( !IsWindow(m_wndTree.m_hWnd) ) return E_PENDING;
  196. USES_CONVERSION;
  197. BSTR bstrServer = NULL;
  198. TCHAR szText[MAX_SERVER_SIZE];
  199. TV_ITEM tvi = {0};
  200. tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT;
  201. tvi.pszText = szText;
  202. tvi.cchTextMax = ARRAYSIZE(szText);
  203. HTREEITEM hItemServer;
  204. HTREEITEM hItemLocation = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, TreeView_GetRoot(m_wndTree.m_hWnd) );
  205. while ( hItemLocation && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) )
  206. {
  207. // Skip location entries in list
  208. if ( tvi.iImage == IMAGE_LOCATION )
  209. hItemServer = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItemLocation );
  210. else
  211. hItemServer = tvi.hItem;
  212. // Server names first
  213. while ( hItemServer && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) && (tvi.iImage != IMAGE_LOCATION) )
  214. {
  215. if ( tvi.iImage == IMAGE_MYNETWORK )
  216. {
  217. SysFreeString( bstrServer );
  218. bstrServer = NULL;
  219. }
  220. else
  221. {
  222. SysReAllocString( &bstrServer, T2COLE(tvi.pszText) );
  223. }
  224. AddConfServer( bstrServer );
  225. // Next Server
  226. hItemServer = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemServer );
  227. }
  228. // Next Location
  229. hItemLocation = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemLocation );
  230. }
  231. SysFreeString( bstrServer );
  232. return S_OK;
  233. }
  234. void CConfExplorerTreeView::SetServerState( CConfServerDetails* pcsd )
  235. {
  236. if ( !IsWindow(m_wndTree.m_hWnd) ) return;
  237. USES_CONVERSION;
  238. BSTR bstrServer = NULL;
  239. TCHAR szText[MAX_SERVER_SIZE];
  240. bool bRefreshDetailsView = false;
  241. TV_ITEM tvi = {0};
  242. tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT | TVIF_STATE;
  243. tvi.pszText = szText;
  244. tvi.cchTextMax = ARRAYSIZE(szText);
  245. tvi.stateMask = TVIS_OVERLAYMASK | TVIS_SELECTED;
  246. HTREEITEM hItemServer;
  247. HTREEITEM hItemLocation = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, TreeView_GetRoot(m_wndTree.m_hWnd) );
  248. while ( hItemLocation && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) )
  249. {
  250. // Skip location entries in list
  251. if ( tvi.iImage == IMAGE_LOCATION )
  252. hItemServer = tvi.hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItemLocation );
  253. else
  254. hItemServer = tvi.hItem;
  255. // Server names first
  256. while ( hItemServer && TreeView_GetItem(m_wndTree.m_hWnd, &tvi) && (tvi.iImage != IMAGE_LOCATION) )
  257. {
  258. if ( tvi.iImage == IMAGE_MYNETWORK )
  259. {
  260. SysFreeString( bstrServer );
  261. bstrServer = NULL;
  262. }
  263. else
  264. {
  265. SysReAllocString( &bstrServer, T2COLE(tvi.pszText) );
  266. }
  267. // Set state if necessary
  268. if ( pcsd->IsSameAs(bstrServer) )
  269. {
  270. if ( !bRefreshDetailsView )
  271. bRefreshDetailsView = (bool) ((tvi.state & TVIS_SELECTED) != 0);
  272. TV_ITEM tvTemp = tvi;
  273. tvTemp.mask = TVIF_STATE | TVIF_HANDLE;
  274. tvTemp.state = INDEXTOOVERLAYMASK(pcsd->m_nState);
  275. tvTemp.stateMask = TVIS_OVERLAYMASK;
  276. TreeView_SetItem( m_wndTree.m_hWnd, &tvTemp );
  277. // Notify Host app of change
  278. CComPtr<IAVGeneralNotification> pAVGen;
  279. if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
  280. pAVGen->fire_NotifySiteServerStateChange( bstrServer, (ServerState) pcsd->m_nState );
  281. }
  282. // Next Server
  283. hItemServer = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemServer );
  284. }
  285. // Next Location
  286. hItemLocation = tvi.hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItemLocation );
  287. }
  288. // Clean up
  289. SysFreeString( bstrServer );
  290. // Invalidate the details view if necessary
  291. if ( bRefreshDetailsView )
  292. {
  293. IConfExplorer *pConfExplorer;
  294. if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
  295. {
  296. IConfExplorerDetailsView *pDetails;
  297. if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
  298. {
  299. HWND hWndDetails;
  300. pDetails->get_hWnd( &hWndDetails );
  301. pDetails->Release();
  302. ::InvalidateRect( hWndDetails, NULL, TRUE );
  303. }
  304. pConfExplorer->Release();
  305. }
  306. }
  307. }
  308. CConfServerDetails* CConfExplorerTreeView::FindConfServer( const OLECHAR *lpoleServer )
  309. {
  310. // Should be locked prior to entering!
  311. _ASSERT( m_critServerList.m_sec.LockCount >= 0 );
  312. // NOTE must already have crit locked
  313. CConfServerDetails *pRet = NULL;
  314. for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
  315. {
  316. if ( (*i)->IsSameAs(lpoleServer) )
  317. {
  318. pRet = *i;
  319. break;
  320. }
  321. }
  322. return pRet;
  323. }
  324. HRESULT CConfExplorerTreeView::AddConfServer( BSTR bstrServer )
  325. {
  326. HRESULT hr = S_OK;
  327. // $CRIT - enter
  328. m_critServerList.Lock();
  329. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  330. CConfServerDetails csTemp;
  331. bool bSetState = false;
  332. if ( !pConfServer )
  333. {
  334. // Create a new conf server
  335. pConfServer = new CConfServerDetails;
  336. if ( pConfServer )
  337. {
  338. SysReAllocString( &pConfServer->m_bstrServer, bstrServer );
  339. // Add item to the list
  340. m_lstServers.push_back( pConfServer );
  341. csTemp = *pConfServer;
  342. bSetState = true;
  343. }
  344. else
  345. {
  346. hr = E_OUTOFMEMORY;
  347. }
  348. }
  349. else
  350. {
  351. // Archive if it's already in the list
  352. pConfServer->m_bArchived = true;
  353. }
  354. m_critServerList.Unlock();
  355. // $CRIT - exit
  356. if ( bSetState ) SetServerState( &csTemp );
  357. return hr;
  358. }
  359. void CConfExplorerTreeView::ArchiveConfServers()
  360. {
  361. CComPtr<IAVGeneralNotification> pAVGen;
  362. _Module.get_AVGenNot( &pAVGen );
  363. // Walk list of conf servers, destroying ones that don't have their archive bit set
  364. // $CRIT - enter
  365. m_critServerList.Lock();
  366. bool bContinue = true;
  367. while ( bContinue && !m_lstServers.empty() )
  368. {
  369. bContinue = false;
  370. CONFSERVERLIST::iterator i = m_lstServers.begin();
  371. do
  372. {
  373. // Not to be archived, delete
  374. if ( !(*i)->m_bArchived )
  375. {
  376. #ifdef _DEBUG
  377. USES_CONVERSION;
  378. ATLTRACE(_T(".1.CConfExplorerTreeView::ArchiveConfServers() -- removing %s.\n"), OLE2CT((*i)->m_bstrServer) );
  379. #endif
  380. // Notification for host application of server being deleted
  381. if ( pAVGen ) pAVGen->fire_RemoveSiteServer( (*i)->m_bstrServer );
  382. delete (*i);
  383. m_lstServers.erase( i );
  384. bContinue = true;
  385. break;
  386. }
  387. i++; // increment iterator
  388. } while ( i != m_lstServers.end() );
  389. }
  390. m_critServerList.Unlock();
  391. // $CRIT - exit
  392. }
  393. void CConfExplorerTreeView::CleanConfServers()
  394. {
  395. // Clear all archive flags on conf servers
  396. m_critServerList.Lock();
  397. for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i !=m_lstServers.end(); i++ )
  398. (*i)->m_bArchived = false;
  399. m_critServerList.Unlock();
  400. EnumerateConfServers();
  401. ArchiveConfServers();
  402. }
  403. void CConfExplorerTreeView::RemoveServerFromReg( BSTR bstrServer )
  404. {
  405. CRegKey regKey;
  406. //
  407. // Get the 'Conference Services' key name
  408. //
  409. TCHAR szReg[MAX_SERVER_SIZE + 100];
  410. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_KEY, szReg, ARRAYSIZE(szReg) );
  411. //
  412. // open the registry key name
  413. //
  414. if ( regKey.Open(HKEY_CURRENT_USER, szReg) != ERROR_SUCCESS )
  415. {
  416. return;
  417. }
  418. //
  419. // Parse the items
  420. //
  421. int nCount = 1;
  422. TCHAR szSubKey[50];
  423. while( TRUE)
  424. {
  425. //
  426. // Get the item entry name
  427. //
  428. LoadString( _Module.GetResourceInstance(), IDN_REG_CONFSERV_ENTRY, szReg, ARRAYSIZE(szReg) );
  429. _sntprintf( szSubKey, ARRAYSIZE(szSubKey), szReg, nCount );
  430. szSubKey[ARRAYSIZE(szSubKey)-1] = _T('\0');
  431. //
  432. // Get the key value
  433. //
  434. DWORD dwValue = 255;
  435. TCHAR szValue[256];
  436. LONG lReturn = regKey.QueryValue( szValue, szSubKey, &dwValue);
  437. if( lReturn != ERROR_SUCCESS )
  438. {
  439. // Don't go further
  440. break;
  441. }
  442. //
  443. // Let see if is our server
  444. //
  445. if( wcsstr( szValue, bstrServer) != NULL )
  446. {
  447. // We find the server, let's delete it!
  448. regKey.DeleteValue( szSubKey );
  449. break;
  450. }
  451. //
  452. // Go to the next entry
  453. //
  454. nCount++;
  455. }
  456. //
  457. // Close the key
  458. //
  459. regKey.Close();
  460. }
  461. LRESULT CConfExplorerTreeView::OnSelChanged( LPNMHDR lpnmHdr )
  462. {
  463. CConfServerDetails *pConfServer = NULL;
  464. CConfServerDetails csTemp;
  465. BSTR bstrLocation = NULL, bstrServer = NULL;
  466. if ( SUCCEEDED(GetSelection(&bstrLocation, &bstrServer)) )
  467. {
  468. // Get a copy of the information stored for the server
  469. m_critServerList.Lock();
  470. pConfServer = FindConfServer( bstrServer );
  471. if ( pConfServer )
  472. csTemp = *pConfServer;
  473. m_critServerList.Unlock();
  474. // Clean up
  475. SysFreeString( bstrLocation );
  476. SysFreeString( bstrServer );
  477. }
  478. // Set the details list with the information stored for this server location
  479. IConfExplorer *pConfExplorer;
  480. if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
  481. {
  482. IConfExplorerDetailsView *pDetails;
  483. if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
  484. {
  485. pDetails->UpdateConfList( (long *) &csTemp.m_lstConfs );
  486. pDetails->Release();
  487. }
  488. pConfExplorer->Release();
  489. }
  490. return 0;
  491. }
  492. LRESULT CConfExplorerTreeView::OnEndLabelEdit( TV_DISPINFO *pInfo )
  493. {
  494. if ( !pInfo->item.pszText ) return 0;
  495. // Make sure that we're changing the text of something valid
  496. TCHAR szText[MAX_SERVER_SIZE + 1];
  497. TV_ITEM tvi;
  498. tvi.hItem = pInfo->item.hItem;
  499. tvi.mask = TVIF_IMAGE | TVIF_TEXT | TVIF_STATE;
  500. tvi.stateMask = TVIS_OVERLAYMASK;
  501. tvi.pszText = szText;
  502. tvi.cchTextMax = ARRAYSIZE(szText) - 1;
  503. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  504. if ( (tvi.iImage == IMAGE_ROOT) || (tvi.iImage == IMAGE_MYNETWORK) ) return 0;
  505. // Make sure the server isn't presently being queried
  506. if ( (tvi.state >> 8) == SERVER_QUERYING )
  507. {
  508. CErrorInfo er( IDS_ER_RENAME_TREEVIEW_ITEM, IDS_ER_RENAME_UNALLOWED_IN_QUERY );
  509. er.set_hr( E_ABORT );
  510. return 0;
  511. }
  512. // Make sure that we have something to actually change
  513. pInfo->item.mask = TVIF_TEXT;
  514. TreeView_SetItem( m_wndTree.m_hWnd, &pInfo->item );
  515. // If the user is renaming a conference server, we need to go out and change the
  516. // information stored in the ConfDetails object for the server
  517. if ( tvi.iImage == IMAGE_SERVER )
  518. {
  519. USES_CONVERSION;
  520. m_critServerList.Lock();
  521. CConfServerDetails *pDetails = FindConfServer( T2COLE(tvi.pszText) );
  522. if ( pDetails )
  523. SysReAllocString( &pDetails->m_bstrServer, T2COLE(pInfo->item.pszText) );
  524. m_critServerList.Unlock();
  525. }
  526. return 0;
  527. }
  528. ///////////////////////////////////////////////////////////////////////////
  529. // COM interface methods and properties
  530. //
  531. STDMETHODIMP CConfExplorerTreeView::get_ConfExplorer(IConfExplorer **ppVal)
  532. {
  533. HRESULT hr = E_PENDING;
  534. Lock();
  535. if ( m_pIConfExplorer )
  536. hr = m_pIConfExplorer->QueryInterface(IID_IConfExplorer, (void **) ppVal );
  537. Unlock();
  538. return hr;
  539. }
  540. STDMETHODIMP CConfExplorerTreeView::put_ConfExplorer(IConfExplorer * newVal)
  541. {
  542. HRESULT hr = S_OK;
  543. Lock();
  544. RELEASE( m_pIConfExplorer );
  545. if ( newVal )
  546. hr = newVal->QueryInterface( IID_IConfExplorer, (void **) &m_pIConfExplorer );
  547. Unlock();
  548. return hr;
  549. }
  550. STDMETHODIMP CConfExplorerTreeView::get_hWnd(HWND *pVal)
  551. {
  552. *pVal = m_wndTree.m_hWnd;
  553. return S_OK;
  554. }
  555. STDMETHODIMP CConfExplorerTreeView::put_hWnd(HWND newVal)
  556. {
  557. if ( IsWindow(newVal) )
  558. {
  559. // Make sure the window isn't already subclassed
  560. if ( m_wndTree.m_hWnd ) m_wndTree.UnsubclassWindow();
  561. // Set up tree view
  562. if ( m_wndTree.SubclassWindow(newVal) )
  563. {
  564. // Hook up link
  565. m_wndTree.m_pTreeView = this;
  566. // Verify that window has proper styles
  567. ::SetWindowLongPtr( m_wndTree.m_hWnd, GWL_STYLE, GetWindowLongPtr(m_wndTree.m_hWnd, GWL_STYLE) |
  568. TVS_HASLINES |
  569. TVS_HASBUTTONS |
  570. TVS_SHOWSELALWAYS |
  571. TVS_DISABLEDRAGDROP );
  572. // Setup image lists for Tree View
  573. InitImageLists();
  574. UpdateData( false );
  575. }
  576. }
  577. else if ( IsWindow(m_wndTree.m_hWnd) )
  578. {
  579. // Shutdown
  580. UpdateData( true );
  581. TreeView_DeleteAllItems( m_wndTree.m_hWnd );
  582. m_wndTree.UnsubclassWindow();
  583. m_wndTree.m_pTreeView = NULL;
  584. m_wndTree.m_hWnd = NULL;
  585. }
  586. return S_OK;
  587. }
  588. STDMETHODIMP CConfExplorerTreeView::get_dwRefreshInterval(DWORD * pVal)
  589. {
  590. *pVal = m_dwRefreshInterval;
  591. return S_OK;
  592. }
  593. STDMETHODIMP CConfExplorerTreeView::put_dwRefreshInterval(DWORD newVal)
  594. {
  595. m_dwRefreshInterval = newVal;
  596. return S_OK;
  597. }
  598. STDMETHODIMP CConfExplorerTreeView::Select(BSTR bstrName)
  599. {
  600. HRESULT hr;
  601. HTREEITEM hItem;
  602. if ( SUCCEEDED(hr = FindOrAddItem(NULL, bstrName, false, false, (long **) &hItem)) )
  603. TreeView_SelectItem( m_wndTree.m_hWnd, hItem );
  604. return hr;
  605. }
  606. STDMETHODIMP CConfExplorerTreeView::SelectItem(short nSel)
  607. {
  608. // TODO: Add your implementation code here
  609. return S_OK;
  610. }
  611. STDMETHODIMP CConfExplorerTreeView::Refresh()
  612. {
  613. // Load up the conference explorer control
  614. if ( !m_wndTree.m_hWnd ) return E_PENDING;
  615. return S_OK;
  616. }
  617. STDMETHODIMP CConfExplorerTreeView::AddLocation(BSTR bstrLocation)
  618. {
  619. HRESULT hr = S_FALSE;
  620. // Show dialog that let's use add a server
  621. CDlgAddLocation dlg;
  622. if ( bstrLocation )
  623. SysReAllocString( &dlg.m_bstrLocation, bstrLocation );
  624. if ( dlg.DoModal(_Module.GetParentWnd()) == IDOK )
  625. {
  626. // Add items to the tree view
  627. HTREEITEM hItem;
  628. hr = FindOrAddItem( dlg.m_bstrLocation, NULL, true, true, (long **) &hItem );
  629. }
  630. return hr;
  631. }
  632. STDMETHODIMP CConfExplorerTreeView::AddServer( BSTR bstrServer )
  633. {
  634. HRESULT hr = S_FALSE;
  635. if ( bstrServer && !SysStringLen(bstrServer) ) bstrServer = NULL;
  636. // Show dialog that let's use add a server
  637. CDlgAddConfServer dlg;
  638. if ( !bstrServer )
  639. {
  640. // Only want location from current selection
  641. GetSelection( &dlg.m_bstrLocation, &dlg.m_bstrServer );
  642. // Never set server names
  643. SysFreeString( dlg.m_bstrServer );
  644. dlg.m_bstrServer = NULL;
  645. }
  646. else
  647. {
  648. // Use user supplied parameters
  649. dlg.m_bstrServer = SysAllocString( bstrServer );
  650. }
  651. if ( dlg.DoModal(_Module.GetParentWnd()) == IDOK )
  652. {
  653. TCHAR szFormat[255];
  654. TCHAR szMessage[255 + MAX_SERVER_SIZE];
  655. CConfServerDetails *pConfServer = NULL;
  656. bool bMyNetwork = false;
  657. // If the server to add matches "(My Network)" then just ignore it as a duplicate
  658. ::LoadString( _Module.GetResourceInstance(), IDS_DEFAULT_SERVER, szFormat, ARRAYSIZE(szFormat) );
  659. if ( !_tcsicmp(szFormat, OLE2CT(dlg.m_bstrServer)) )
  660. {
  661. bMyNetwork = true;
  662. }
  663. else
  664. {
  665. m_critServerList.Lock();
  666. pConfServer = FindConfServer( dlg.m_bstrServer );
  667. m_critServerList.Unlock();
  668. }
  669. // Does the conference server already exist?
  670. if ( !bMyNetwork && !pConfServer )
  671. {
  672. // Add items to the tree view
  673. HTREEITEM hItem;
  674. if ( SUCCEEDED(hr = FindOrAddItem(NULL, dlg.m_bstrServer, true, false, (long **) &hItem)) )
  675. {
  676. AddConfServer( dlg.m_bstrServer );
  677. // Notify host app of server addition
  678. CComPtr<IAVGeneralNotification> pAVGen;
  679. if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
  680. pAVGen->fire_AddSiteServer( dlg.m_bstrServer );
  681. // Publish our information on the server
  682. CComPtr<IAVTapi> pAVTapi;
  683. if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
  684. pAVTapi->RegisterUser( true, dlg.m_bstrServer );
  685. }
  686. }
  687. else
  688. {
  689. // Notify user that the server already exists
  690. ::LoadString( _Module.GetResourceInstance(), IDS_CONFEXP_SERVEREXISTS, szFormat, ARRAYSIZE(szFormat) );
  691. _sntprintf( szMessage, ARRAYSIZE(szMessage), szFormat, OLE2CT(dlg.m_bstrServer) );
  692. szMessage[ARRAYSIZE(szMessage)-1] = _T('\0');
  693. _Module.DoMessageBox( szMessage, MB_OK | MB_ICONINFORMATION, false );
  694. }
  695. }
  696. return hr;
  697. }
  698. STDMETHODIMP CConfExplorerTreeView::RemoveServer(BSTR bstrLocation, BSTR bstrName )
  699. {
  700. if ( !IsWindow(m_wndTree.m_hWnd) ) return E_FAIL;
  701. HTREEITEM hItem = NULL;
  702. HRESULT hr = S_FALSE;
  703. // if all args NULL that means delete currently selected item
  704. if ( !bstrLocation && !bstrName )
  705. {
  706. hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
  707. }
  708. else
  709. {
  710. if ( FAILED(FindOrAddItem(bstrLocation, bstrName, false, false, (long **) &hItem)) )
  711. hItem = NULL;
  712. }
  713. // Have an item to delete?
  714. if ( hItem && (hItem != TreeView_GetRoot(m_wndTree.m_hWnd)) )
  715. {
  716. TCHAR szText[MAX_SERVER_SIZE];
  717. TV_ITEM tvi = {0};
  718. tvi.mask = TVIF_IMAGE | TVIF_HANDLE | TVIF_TEXT;
  719. tvi.hItem = hItem;
  720. tvi.pszText = szText;
  721. tvi.cchTextMax = ARRAYSIZE(szText);
  722. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  723. if ( tvi.iImage != IMAGE_MYNETWORK )
  724. {
  725. TCHAR szFormat[255];
  726. TCHAR szMessage[255 + MAX_SERVER_SIZE];
  727. ::LoadString( _Module.GetResourceInstance(), IDS_CONFIRM_REMOVE_SERVER, szFormat, ARRAYSIZE(szFormat) );
  728. _sntprintf( szMessage, ARRAYSIZE(szMessage), szFormat, tvi.pszText );
  729. // Confirm
  730. if ( _Module.DoMessageBox(szMessage, MB_YESNO | MB_ICONQUESTION, false) == IDYES )
  731. {
  732. if ( TreeView_DeleteItem(m_wndTree.m_hWnd, hItem) )
  733. {
  734. RemoveServerFromReg( bstrName );
  735. CleanConfServers();
  736. hr = S_OK;
  737. }
  738. }
  739. }
  740. }
  741. return hr;
  742. }
  743. STDMETHODIMP CConfExplorerTreeView::FindOrAddItem(BSTR bstrLocation, BSTR bstrServer, BOOL bAddItem, BOOL bLocationOnly, long **pphItem)
  744. {
  745. #undef FETCH_STRING
  746. #define FETCH_STRING( _IDS_ ) \
  747. LoadString( _Module.GetResourceInstance(), _IDS_, szJunk, ARRAYSIZE(szJunk) ); \
  748. SysReAllocString( &bstrItemText, T2COLE(szJunk) );
  749. if ( !IsWindow(m_wndTree.m_hWnd) ) return E_FAIL;
  750. HRESULT hr = S_OK;
  751. _ASSERT( pphItem );
  752. *pphItem = NULL;
  753. USES_CONVERSION;
  754. TCHAR szText[MAX_SERVER_SIZE], szJunk[MAX_SERVER_SIZE];
  755. TV_ITEM tvi = {0};
  756. tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
  757. tvi.pszText = szText;
  758. tvi.cchTextMax = ARRAYSIZE( szText );
  759. tvi.stateMask = TVIS_EXPANDED;
  760. TV_INSERTSTRUCT tvis;
  761. tvis.hParent = TVI_ROOT;
  762. tvis.hInsertAfter = TVI_SORT;
  763. HTREEITEM hItem = TreeView_GetRoot( m_wndTree.m_hWnd );
  764. BSTR bstrItemText = NULL;
  765. int nImage;
  766. int nEnd = (bLocationOnly) ? IMAGE_LOCATION : IMAGE_SERVER;
  767. for ( int i = 0; i <= nEnd; i++ )
  768. {
  769. // Pick the string based on how deep in the search we are
  770. nImage = i;
  771. switch ( i )
  772. {
  773. case IMAGE_ROOT: FETCH_STRING( IDS_CONFSERV_ROOT ); break;
  774. case IMAGE_LOCATION: SysReAllocString( &bstrItemText, bstrLocation ); break;
  775. case IMAGE_SERVER:
  776. if ( bstrServer )
  777. {
  778. SysReAllocString( &bstrItemText, bstrServer );
  779. }
  780. else
  781. {
  782. FETCH_STRING( IDS_DEFAULT_SERVER );
  783. nImage = IMAGE_MYNETWORK;
  784. }
  785. break;
  786. }
  787. if ( bstrItemText )
  788. {
  789. while ( hItem )
  790. {
  791. tvi.hItem = hItem;
  792. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  793. // Found item
  794. if ( !_tcsicmp(OLE2CT(bstrItemText), tvi.pszText) )
  795. break;
  796. hItem = TreeView_GetNextSibling( m_wndTree.m_hWnd, hItem );
  797. }
  798. // If no item is found, should we add one?
  799. if ( !hItem )
  800. {
  801. if ( bAddItem )
  802. {
  803. _tcscpy( tvi.pszText, OLE2CT(bstrItemText) );
  804. tvi.iSelectedImage = tvi.iImage = nImage;
  805. tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE;
  806. tvis.item = tvi;
  807. hItem = TreeView_InsertItem( m_wndTree.m_hWnd, &tvis );
  808. if ( hItem )
  809. TreeView_SelectItem( m_wndTree.m_hWnd, hItem );
  810. }
  811. else
  812. {
  813. // No item found and can't add
  814. hr = E_FAIL;
  815. break;
  816. }
  817. }
  818. // Set up parent information
  819. if ( hItem )
  820. {
  821. *pphItem = (long *) hItem; // return value
  822. tvis.hParent = hItem;
  823. hItem = TreeView_GetChild( m_wndTree.m_hWnd, hItem );
  824. }
  825. SysFreeString( bstrItemText );
  826. bstrItemText = NULL;
  827. }
  828. }
  829. // Clean-up
  830. SysFreeString( bstrItemText );
  831. return hr;
  832. }
  833. STDMETHODIMP CConfExplorerTreeView::GetSelection(BSTR * pbstrLocation, BSTR * pbstrServer)
  834. {
  835. // Initialize [in,out] parameters
  836. *pbstrLocation = *pbstrServer = NULL;
  837. HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
  838. if ( !hItem ) return E_PENDING;
  839. USES_CONVERSION;
  840. HRESULT hr = E_FAIL;
  841. TCHAR szText[MAX_SERVER_SIZE];
  842. TV_ITEM tvi;
  843. tvi.mask = TVIF_TEXT | TVIF_IMAGE;
  844. tvi.pszText = szText;
  845. tvi.cchTextMax = ARRAYSIZE( szText );
  846. tvi.hItem = hItem;
  847. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  848. switch ( tvi.iImage)
  849. {
  850. case IMAGE_MYNETWORK:
  851. // This is the default (NULL, NULL, NULL)
  852. hr = S_OK;
  853. break;
  854. case IMAGE_SERVER:
  855. hr = S_OK;
  856. *pbstrServer = SysAllocString( T2COLE(tvi.pszText) );
  857. // drop out here if we don't have a parent item
  858. if ( (tvi.hItem = TreeView_GetParent(m_wndTree.m_hWnd, tvi.hItem)) == NULL )
  859. break;
  860. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  861. case IMAGE_LOCATION:
  862. // Don't return root item itself
  863. if ( tvi.hItem != TreeView_GetRoot(m_wndTree.m_hWnd) )
  864. *pbstrLocation = SysAllocString( T2COLE(tvi.pszText) );
  865. break;
  866. }
  867. return hr;
  868. }
  869. void CConfExplorerTreeView::InitImageLists()
  870. {
  871. if ( m_hIml || !IsWindow(m_wndTree.m_hWnd) ) return;
  872. // Normal
  873. if ( (m_hIml = ImageList_LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_LST_CONFSERV), 16, 9, RGB(255, 0, 255))) != NULL )
  874. {
  875. // Overlay images for various states
  876. for ( int i = 1; i < 4; i++ )
  877. ImageList_SetOverlayImage( m_hIml, 5 + i, i );
  878. TreeView_SetImageList( m_wndTree.m_hWnd, m_hIml, TVSIL_NORMAL );
  879. }
  880. }
  881. STDMETHODIMP CConfExplorerTreeView::CanRemoveServer()
  882. {
  883. if ( IsWindow(m_wndTree.m_hWnd) )
  884. {
  885. HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
  886. if ( hItem && (hItem != TreeView_GetRoot(m_wndTree.m_hWnd)) )
  887. {
  888. TV_ITEM tvi = {0};
  889. tvi.mask = TVIF_HANDLE | TVIF_IMAGE;
  890. tvi.hItem = hItem;
  891. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  892. if ( tvi.iImage != IMAGE_MYNETWORK )
  893. return S_OK;
  894. }
  895. }
  896. return S_FALSE;
  897. }
  898. STDMETHODIMP CConfExplorerTreeView::ForceConfServerForEnum( BSTR bstrServer )
  899. {
  900. HRESULT hr = E_FAIL;
  901. m_critServerList.Lock();
  902. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  903. CConfServerDetails csTemp;
  904. if ( pConfServer && (pConfServer->m_nState != SERVER_QUERYING) )
  905. {
  906. pConfServer->m_nState = SERVER_UNKNOWN;
  907. pConfServer->m_dwTickCount = 0;
  908. DELETE_LIST( pConfServer->m_lstConfs );
  909. DELETE_LIST( pConfServer->m_lstPersons );
  910. csTemp.CopyLocalProperties( *pConfServer );
  911. hr = S_OK;
  912. }
  913. m_critServerList.Unlock();
  914. // Repaint if succeeded
  915. if ( SUCCEEDED(hr) )
  916. {
  917. SetServerState( &csTemp );
  918. if ( IsWindow(m_wndTree.m_hWnd) ) m_wndTree.RedrawWindow();
  919. }
  920. return hr;
  921. }
  922. STDMETHODIMP CConfExplorerTreeView::GetConfServerForEnum(BSTR * pbstrServer )
  923. {
  924. HRESULT hr = E_FAIL;
  925. CConfServerDetails *pConfServer = NULL;
  926. CConfServerDetails csTemp;
  927. m_critServerList.Lock();
  928. for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
  929. {
  930. if ( ((*i)->m_nState != SERVER_QUERYING) &&
  931. (!(*i)->m_dwTickCount || ((GetTickCount() - (*i)->m_dwTickCount) > m_dwRefreshInterval)) )
  932. {
  933. if ( !pConfServer || ((GetTickCount() - pConfServer->m_dwTickCount) < (GetTickCount() - (*i)->m_dwTickCount)) )
  934. pConfServer = *i;
  935. }
  936. }
  937. // This is the conference server that is most in need of updating
  938. if ( pConfServer )
  939. {
  940. *pbstrServer = SysAllocString( pConfServer->m_bstrServer );
  941. pConfServer->m_nState = SERVER_QUERYING;
  942. csTemp = *pConfServer;
  943. hr = S_OK;
  944. }
  945. m_critServerList.Unlock();
  946. if ( SUCCEEDED(hr) ) SetServerState( &csTemp );
  947. return hr;
  948. }
  949. STDMETHODIMP CConfExplorerTreeView::SetConfServerForEnum(BSTR bstrServer, long *pList, long *pListPersons, DWORD dwTicks, BOOL bUpdate)
  950. {
  951. m_critServerList.Lock();
  952. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  953. CConfServerDetails csTemp;
  954. bool bSetState = false;
  955. if ( pConfServer )
  956. {
  957. pConfServer->m_dwTickCount = dwTicks;
  958. DELETE_LIST( pConfServer->m_lstConfs );
  959. DELETE_LIST( pConfServer->m_lstPersons );
  960. if ( pList )
  961. {
  962. ///////////////////////////////////////////
  963. // Add all of the conference servers
  964. {
  965. CONFDETAILSLIST::iterator i, iEnd = ((CONFDETAILSLIST *) pList)->end();
  966. for ( i = ((CONFDETAILSLIST *) pList)->begin(); i != iEnd; i++ )
  967. {
  968. CConfDetails *pDetails = new CConfDetails;
  969. if ( pDetails )
  970. {
  971. *pDetails = *(*i);
  972. pConfServer->m_lstConfs.push_back( pDetails );
  973. }
  974. }
  975. }
  976. ///////////////////////////////////////////
  977. // Add all of the people
  978. {
  979. if ( pListPersons )
  980. {
  981. PERSONDETAILSLIST::iterator i, iEnd = ((PERSONDETAILSLIST *) pListPersons)->end();
  982. for ( i = ((PERSONDETAILSLIST *) pListPersons)->begin(); i != iEnd; i++ )
  983. {
  984. CPersonDetails *pDetails = new CPersonDetails;
  985. if ( pDetails )
  986. {
  987. *pDetails = *(*i);
  988. pConfServer->m_lstPersons.push_back( pDetails );
  989. }
  990. }
  991. }
  992. }
  993. pConfServer->m_nState = SERVER_OK;
  994. }
  995. else
  996. {
  997. // Server connection broken
  998. pConfServer->m_nState = SERVER_NOT_RESPONDING;
  999. }
  1000. csTemp = *pConfServer;
  1001. bSetState = true;
  1002. }
  1003. m_critServerList.Unlock();
  1004. // Force update of list if selected
  1005. if ( bSetState ) SetServerState( &csTemp );
  1006. if ( bUpdate )
  1007. {
  1008. IConfExplorer *pConfExplorer;
  1009. if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
  1010. {
  1011. BSTR bstrMyLocation = NULL, bstrMyServer = NULL;
  1012. if ( SUCCEEDED(GetSelection(&bstrMyLocation, &bstrMyServer)) )
  1013. {
  1014. if ( csTemp.IsSameAs(bstrMyServer) )
  1015. {
  1016. IConfExplorerDetailsView *pDetails;
  1017. if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
  1018. {
  1019. pDetails->UpdateConfList( (long *) &csTemp.m_lstConfs );
  1020. pDetails->Release();
  1021. }
  1022. }
  1023. SysFreeString( bstrMyLocation );
  1024. SysFreeString( bstrMyServer );
  1025. }
  1026. pConfExplorer->Release();
  1027. }
  1028. }
  1029. return S_OK;
  1030. }
  1031. STDMETHODIMP CConfExplorerTreeView::BuildJoinConfList(long * pList, VARIANT_BOOL bAllConfs )
  1032. {
  1033. _ASSERT( pList );
  1034. m_critServerList.Lock();
  1035. for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
  1036. (*i)->BuildJoinConfList( (CONFDETAILSLIST *) pList, bAllConfs );
  1037. m_critServerList.Unlock();
  1038. return S_OK;
  1039. }
  1040. STDMETHODIMP CConfExplorerTreeView::get_nServerState(ServerState * pVal)
  1041. {
  1042. // default return value
  1043. *pVal = SERVER_INVALID;
  1044. HTREEITEM hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
  1045. if ( hItem )
  1046. {
  1047. TV_ITEM tvi;
  1048. tvi.hItem = hItem;
  1049. tvi.mask = TVIF_HANDLE | TVIF_STATE | TVIF_IMAGE;
  1050. tvi.stateMask = TVIS_OVERLAYMASK;
  1051. TreeView_GetItem( m_wndTree.m_hWnd, &tvi );
  1052. switch ( tvi.iImage )
  1053. {
  1054. case IMAGE_SERVER:
  1055. case IMAGE_MYNETWORK:
  1056. switch ( tvi.state >> 8 )
  1057. {
  1058. case 0: *pVal = SERVER_OK; break;
  1059. case 1: *pVal = SERVER_UNKNOWN; break;
  1060. case 2: *pVal = SERVER_NOT_RESPONDING; break;
  1061. case 3: *pVal = SERVER_QUERYING; break;
  1062. }
  1063. break;
  1064. }
  1065. }
  1066. return S_OK;
  1067. }
  1068. STDMETHODIMP CConfExplorerTreeView::BuildJoinConfListText(long * pList, BSTR bstrText)
  1069. {
  1070. _ASSERT( pList );
  1071. m_critServerList.Lock();
  1072. for ( CONFSERVERLIST::iterator i = m_lstServers.begin(); i != m_lstServers.end(); i++ )
  1073. (*i)->BuildJoinConfList( (CONFDETAILSLIST *) pList, bstrText );
  1074. m_critServerList.Unlock();
  1075. return S_OK;
  1076. }
  1077. STDMETHODIMP CConfExplorerTreeView::RenameServer()
  1078. {
  1079. HTREEITEM hItem;
  1080. hItem = TreeView_GetSelection( m_wndTree.m_hWnd );
  1081. if ( hItem )
  1082. TreeView_EditLabel( m_wndTree.m_hWnd, hItem );
  1083. return S_OK;
  1084. }
  1085. STDMETHODIMP CConfExplorerTreeView::RemoveConference(BSTR bstrServer, BSTR bstrName)
  1086. {
  1087. HRESULT hr = E_FAIL;
  1088. m_critServerList.Lock();
  1089. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  1090. if ( pConfServer )
  1091. {
  1092. if ( SUCCEEDED(hr = pConfServer->RemoveConference(bstrName)) )
  1093. {
  1094. IConfExplorer *pConfExplorer;
  1095. if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
  1096. {
  1097. IConfExplorerDetailsView *pDetails;
  1098. if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
  1099. {
  1100. pDetails->UpdateConfList( (long *) &pConfServer->m_lstConfs );
  1101. pDetails->Release();
  1102. }
  1103. pConfExplorer->Release();
  1104. }
  1105. }
  1106. }
  1107. m_critServerList.Unlock();
  1108. return hr;
  1109. }
  1110. STDMETHODIMP CConfExplorerTreeView::AddPerson(BSTR bstrServer, ITDirectoryObject * pDirObj)
  1111. {
  1112. HRESULT hr = E_FAIL;
  1113. int nCount = 0;
  1114. bool bRetry;
  1115. bool bSuccess = false;
  1116. // Spin in loop waiting to add person to the conference
  1117. do
  1118. {
  1119. bRetry = false;
  1120. m_critServerList.Lock();
  1121. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  1122. if ( pConfServer )
  1123. {
  1124. if ( pConfServer->m_nState == SERVER_QUERYING )
  1125. {
  1126. ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- sleeping, server being queried.\n"));
  1127. bRetry = true;
  1128. }
  1129. else if ( SUCCEEDED(hr = pConfServer->AddPerson(bstrServer, pDirObj)) )
  1130. {
  1131. ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- adding to list.\n"));
  1132. bSuccess = true;
  1133. }
  1134. }
  1135. m_critServerList.Unlock();
  1136. // Sleep while we're waiting
  1137. if ( bRetry )
  1138. Sleep( 3000 );
  1139. } while ( bRetry && (++nCount < 20) );
  1140. ATLTRACE(_T(".1.CConfExplorerTreeView::AddPerson() -- safely out of spin loop.\n"));
  1141. // Notification for host application of servers being loaded
  1142. if ( bSuccess )
  1143. {
  1144. CComPtr<IAVGeneralNotification> pAVGen;
  1145. _Module.get_AVGenNot( &pAVGen );
  1146. if ( pAVGen )
  1147. pAVGen->fire_AddUser( NULL, NULL, NULL );
  1148. }
  1149. return hr;
  1150. }
  1151. STDMETHODIMP CConfExplorerTreeView::AddConference(BSTR bstrServer, ITDirectoryObject * pDirObj)
  1152. {
  1153. HRESULT hr = E_FAIL;
  1154. m_critServerList.Lock();
  1155. CConfServerDetails *pConfServer = FindConfServer( bstrServer );
  1156. if ( pConfServer )
  1157. {
  1158. if ( SUCCEEDED(hr = pConfServer->AddConference(bstrServer, pDirObj)) )
  1159. {
  1160. IConfExplorer *pConfExplorer;
  1161. if ( SUCCEEDED(get_ConfExplorer(&pConfExplorer)) )
  1162. {
  1163. IConfExplorerDetailsView *pDetails;
  1164. if ( SUCCEEDED(pConfExplorer->get_DetailsView(&pDetails)) )
  1165. {
  1166. pDetails->UpdateConfList( (long *) &pConfServer->m_lstConfs );
  1167. pDetails->Release();
  1168. }
  1169. pConfExplorer->Release();
  1170. }
  1171. }
  1172. }
  1173. m_critServerList.Unlock();
  1174. return hr;
  1175. }
  1176. STDMETHODIMP CConfExplorerTreeView::EnumSiteServer(BSTR bstrName, IEnumSiteServer * * ppEnum)
  1177. {
  1178. // First make a copy of what we have for the server
  1179. CConfServerDetails *pConfServer = NULL;
  1180. CConfServerDetails csTemp;
  1181. m_critServerList.Lock();
  1182. pConfServer = FindConfServer( bstrName );
  1183. if ( pConfServer )
  1184. csTemp = *pConfServer;
  1185. m_critServerList.Unlock();
  1186. // Bad server name
  1187. if ( !pConfServer )
  1188. {
  1189. #ifdef _DEBUG
  1190. USES_CONVERSION;
  1191. ATLTRACE(_T(".warning.CConfExplorerTreeView::EnumSiteServer(%s) name not found in list.\n"), OLE2CT(bstrName) );
  1192. #endif
  1193. return E_FAIL;
  1194. }
  1195. // Make a copy of everything...
  1196. HRESULT hr = E_OUTOFMEMORY;
  1197. *ppEnum = new CComObject<CEnumSiteServer>;
  1198. if ( *ppEnum )
  1199. hr = (*ppEnum)->BuildList( (long *) &csTemp.m_lstPersons );
  1200. return hr;
  1201. }