Source code of Windows XP (NT5)
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.

959 lines
26 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. tapicomp.cpp
  7. This file contains the derived implementations from CComponent
  8. and CComponentData for the TAPI admin snapin.
  9. FILE HISTORY:
  10. */
  11. #include "stdafx.h"
  12. #include "tapicomp.h"
  13. #include "root.h"
  14. #include "server.h"
  15. #include <atlimpl.cpp>
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. DWORD gdwTapiSnapVersion;
  22. UINT aColumns[TAPISNAP_NODETYPE_MAX][MAX_COLUMNS] =
  23. {
  24. {IDS_ROOT_NAME, 0, 0, 0, 0},
  25. {IDS_SERVER_NAME, 0 , 0, 0, 0},
  26. {IDS_LINE_NAME, IDS_USERS, IDS_STATUS, 0, 0},
  27. {0,0,0,0,0}
  28. };
  29. //
  30. // CODEWORK this should be in a resource, for example code on loading data resources see
  31. // D:\nt\private\net\ui\common\src\applib\applib\lbcolw.cxx ReloadColumnWidths()
  32. // JonN 10/11/96
  33. //
  34. int aColumnWidths[TAPISNAP_NODETYPE_MAX][MAX_COLUMNS] =
  35. {
  36. {200 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // TAPISNAP_ROOT
  37. {200 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // TAPISNAP_SERVER
  38. {150 ,200 ,200 ,AUTO_WIDTH,AUTO_WIDTH}, // TAPISNAP_PROVIDER
  39. {AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH},
  40. };
  41. #define HI HIDDEN
  42. #define EN ENABLED
  43. MMC_CONSOLE_VERB g_ConsoleVerbs[] =
  44. {
  45. MMC_VERB_OPEN,
  46. MMC_VERB_COPY,
  47. MMC_VERB_PASTE,
  48. MMC_VERB_DELETE,
  49. MMC_VERB_PROPERTIES,
  50. MMC_VERB_RENAME,
  51. MMC_VERB_REFRESH,
  52. MMC_VERB_PRINT
  53. };
  54. // default states for the console verbs
  55. MMC_BUTTON_STATE g_ConsoleVerbStates[TAPISNAP_NODETYPE_MAX][ARRAYLEN(g_ConsoleVerbs)] =
  56. {
  57. {HI, HI, HI, HI, HI, HI, HI, HI}, // TAPISNAP_ROOT
  58. {HI, HI, HI, EN, EN, HI, EN, HI}, // TAPISNAP_SERVER
  59. {HI, HI, HI, EN, HI, HI, HI, HI}, // TAPISNAP_PROVIDER
  60. {HI, HI, HI, HI, HI, HI, HI, HI}, // TAPISNAP_LINE
  61. };
  62. // default states for the console verbs
  63. MMC_BUTTON_STATE g_ConsoleVerbStatesMultiSel[TAPISNAP_NODETYPE_MAX][ARRAYLEN(g_ConsoleVerbs)] =
  64. {
  65. {HI, HI, HI, HI, HI, HI, HI, HI}, // TAPISNAP_ROOT
  66. {HI, HI, HI, EN, EN, HI, EN, HI}, // TAPISNAP_SERVER
  67. {HI, HI, HI, EN, HI, HI, EN, HI}, // TAPISNAP_PROVIDER
  68. {HI, HI, HI, EN, HI, HI, HI, HI}, // TAPISNAP_LINE
  69. };
  70. // Help ID array for help on scope items
  71. DWORD g_dwMMCHelp[TAPISNAP_NODETYPE_MAX] =
  72. {
  73. TAPISNAP_HELP_ROOT, // TAPISNAP_ROOT
  74. TAPISNAP_HELP_SERVER, // TAPISNAP_SERVER
  75. TAPISNAP_HELP_PROVIDER, // TAPISNAP_PROVIDER
  76. TAPISNAP_HELP_DEVICE, // TAPISNAP_DEVICE
  77. };
  78. // icon defines
  79. UINT g_uIconMap[ICON_IDX_MAX + 1][2] =
  80. {
  81. {IDI_ICON01, ICON_IDX_SERVER},
  82. {IDI_ICON02, ICON_IDX_SERVER_BUSY},
  83. {IDI_ICON03, ICON_IDX_SERVER_CONNECTED},
  84. {IDI_ICON04, ICON_IDX_SERVER_LOST_CONNECTION},
  85. {IDI_ICON05, ICON_IDX_MACHINE},
  86. {IDI_ICON06, ICON_IDX_FOLDER_CLOSED},
  87. {IDI_ICON07, ICON_IDX_FOLDER_OPEN},
  88. {IDI_TAPI_SNAPIN, ICON_IDX_PRODUCT},
  89. {0, 0}
  90. };
  91. /*!--------------------------------------------------------------------------
  92. GetSystemMessage
  93. Use FormatMessage() to get a system error message
  94. Author: EricDav
  95. ---------------------------------------------------------------------------*/
  96. LONG
  97. GetSystemMessage
  98. (
  99. UINT nId,
  100. TCHAR * chBuffer,
  101. int cbBuffSize
  102. )
  103. {
  104. TCHAR * pszText = NULL ;
  105. HINSTANCE hdll = NULL ;
  106. DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS
  107. | FORMAT_MESSAGE_MAX_WIDTH_MASK;
  108. //
  109. // Interpret the error. Need to special case
  110. // the lmerr & ntstatus ranges, as well as
  111. // dhcp server error messages.
  112. //
  113. if (nId > 0x0000E000 && nId <= 0x0000FFFF)
  114. {
  115. hdll = LoadLibrary( _T("tapiui.dll") );
  116. }
  117. else if( nId >= NERR_BASE && nId <= MAX_NERR )
  118. {
  119. hdll = LoadLibrary( _T("netmsg.dll") );
  120. }
  121. else if( nId >= 0x40000000L )
  122. {
  123. hdll = LoadLibrary( _T("ntdll.dll") );
  124. }
  125. if( hdll == NULL )
  126. {
  127. flags |= FORMAT_MESSAGE_FROM_SYSTEM;
  128. }
  129. else
  130. {
  131. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  132. }
  133. //
  134. // Let FormatMessage do the dirty work.
  135. //
  136. DWORD dwResult = ::FormatMessage( flags,
  137. (LPVOID) hdll,
  138. nId,
  139. 0,
  140. chBuffer,
  141. cbBuffSize,
  142. NULL ) ;
  143. if( hdll != NULL )
  144. {
  145. LONG err = GetLastError();
  146. FreeLibrary( hdll );
  147. if ( dwResult == 0 )
  148. {
  149. ::SetLastError( err );
  150. }
  151. }
  152. return dwResult ? 0 : ::GetLastError() ;
  153. }
  154. /*!--------------------------------------------------------------------------
  155. LoadMessage
  156. Loads the error message from the correct DLL.
  157. Author: EricDav
  158. ---------------------------------------------------------------------------*/
  159. BOOL
  160. LoadMessage
  161. (
  162. UINT nIdPrompt,
  163. TCHAR * chMsg,
  164. int nMsgSize
  165. )
  166. {
  167. BOOL bOk;
  168. //
  169. // Substitute a friendly message for "RPC server not
  170. // available" and "No more endpoints available from
  171. // the endpoint mapper".
  172. //
  173. if (nIdPrompt == EPT_S_NOT_REGISTERED ||
  174. nIdPrompt == RPC_S_SERVER_UNAVAILABLE)
  175. {
  176. nIdPrompt = IDS_ERR_TAPI_DOWN;
  177. }
  178. else if (nIdPrompt == RPC_S_PROCNUM_OUT_OF_RANGE)
  179. {
  180. nIdPrompt = IDS_ERR_RPC_NO_ENTRY;
  181. }
  182. //
  183. // If it's a socket error or our error, the text is in our resource fork.
  184. // Otherwise, use FormatMessage() and the appropriate DLL.
  185. //
  186. if (nIdPrompt >= IDS_ERR_BASE && nIdPrompt < IDS_MESG_MAX)
  187. {
  188. //
  189. // It's in our resource fork
  190. //
  191. bOk = ::LoadString( AfxGetInstanceHandle(), nIdPrompt, chMsg, nMsgSize ) != 0 ;
  192. }
  193. else
  194. {
  195. //
  196. // It's in the system somewhere.
  197. //
  198. bOk = GetSystemMessage( nIdPrompt, chMsg, nMsgSize ) == 0 ;
  199. }
  200. //
  201. // If the error message did not compute, replace it.
  202. //
  203. if ( ! bOk )
  204. {
  205. TCHAR chBuff [STRING_LENGTH_MAX] ;
  206. static const TCHAR * pszReplacement = _T("System Error: %ld");
  207. const TCHAR * pszMsg = pszReplacement ;
  208. //
  209. // Try to load the generic (translatable) error message text
  210. //
  211. if ( ::LoadString( AfxGetInstanceHandle(), IDS_ERR_MESSAGE_GENERIC,
  212. chBuff, sizeof(chBuff)/sizeof(TCHAR) ) != 0 )
  213. {
  214. pszMsg = chBuff ;
  215. }
  216. ::wsprintf( chMsg, pszMsg, nIdPrompt ) ;
  217. }
  218. return bOk;
  219. }
  220. /*!--------------------------------------------------------------------------
  221. TapiMessageBox
  222. Puts up a message box with the corresponding error text.
  223. Author: EricDav
  224. ---------------------------------------------------------------------------*/
  225. int
  226. TapiMessageBox
  227. (
  228. UINT nIdPrompt,
  229. UINT nType,
  230. const TCHAR * pszSuffixString,
  231. UINT nHelpContext
  232. )
  233. {
  234. TCHAR chMesg [4000] ;
  235. BOOL bOk ;
  236. chMesg[0] = 0;
  237. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  238. if ( pszSuffixString )
  239. {
  240. ::lstrcat( chMesg, _T(" ") ) ;
  241. ::lstrcat( chMesg, pszSuffixString ) ;
  242. }
  243. return ::AfxMessageBox( chMesg, nType, nHelpContext ) ;
  244. }
  245. /*!--------------------------------------------------------------------------
  246. TapiMessageBoxEx
  247. Puts up a message box with the corresponding error text.
  248. Author: EricDav
  249. ---------------------------------------------------------------------------*/
  250. int
  251. TapiMessageBoxEx
  252. (
  253. UINT nIdPrompt,
  254. LPCTSTR pszPrefixMessage,
  255. UINT nType,
  256. UINT nHelpContext
  257. )
  258. {
  259. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  260. TCHAR chMesg[4000];
  261. CString strMessage;
  262. BOOL bOk;
  263. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  264. if ( pszPrefixMessage )
  265. {
  266. strMessage = pszPrefixMessage;
  267. strMessage += _T("\n");
  268. strMessage += _T("\n");
  269. strMessage += chMesg;
  270. }
  271. else
  272. {
  273. strMessage = chMesg;
  274. }
  275. return AfxMessageBox(strMessage, nType, nHelpContext);
  276. }
  277. /*---------------------------------------------------------------------------
  278. Class CTapiComponent implementation
  279. ---------------------------------------------------------------------------*/
  280. CTapiComponent::CTapiComponent()
  281. {
  282. m_pbmpToolbar = NULL;
  283. }
  284. CTapiComponent::~CTapiComponent()
  285. {
  286. if (m_pbmpToolbar)
  287. {
  288. delete m_pbmpToolbar;
  289. m_pbmpToolbar = NULL;
  290. }
  291. }
  292. STDMETHODIMP CTapiComponent::InitializeBitmaps(MMC_COOKIE cookie)
  293. {
  294. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  295. ASSERT(m_spImageList != NULL);
  296. HICON hIcon;
  297. for (int i = 0; i < ICON_IDX_MAX; i++)
  298. {
  299. hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(g_uIconMap[i][0]));
  300. if (hIcon)
  301. {
  302. // call mmc
  303. VERIFY(SUCCEEDED(m_spImageList->ImageListSetIcon(reinterpret_cast<LONG_PTR*>(hIcon), g_uIconMap[i][1])));
  304. }
  305. }
  306. return S_OK;
  307. }
  308. /*!--------------------------------------------------------------------------
  309. CTapiComponent::QueryDataObject
  310. Implementation of IComponent::QueryDataObject. We need this for
  311. virtual listbox support. MMC calls us back normally with the cookie
  312. we handed it... In the case of the VLB, it hands us the index of
  313. the item. So, we need to do some extra checking...
  314. Author: EricDav
  315. ---------------------------------------------------------------------------*/
  316. STDMETHODIMP
  317. CTapiComponent::QueryDataObject
  318. (
  319. MMC_COOKIE cookie,
  320. DATA_OBJECT_TYPES type,
  321. LPDATAOBJECT* ppDataObject
  322. )
  323. {
  324. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  325. HRESULT hr = hrOK;
  326. SPITFSNode spSelectedNode;
  327. SPITFSResultHandler spResultHandler;
  328. long lViewOptions;
  329. LPOLESTR pViewType;
  330. CDataObject * pDataObject;
  331. COM_PROTECT_TRY
  332. {
  333. // check to see what kind of result view type the selected node has
  334. CORg (GetSelectedNode(&spSelectedNode));
  335. CORg (spSelectedNode->GetResultHandler(&spResultHandler));
  336. CORg (spResultHandler->OnGetResultViewType(this, spSelectedNode->GetData(TFS_DATA_COOKIE), &pViewType, &lViewOptions));
  337. if ( (lViewOptions & MMC_VIEW_OPTIONS_OWNERDATALIST) ||
  338. (cookie == MMC_MULTI_SELECT_COOKIE) )
  339. {
  340. if (cookie == MMC_MULTI_SELECT_COOKIE)
  341. {
  342. // this is a special case for multiple select. We need to build a list
  343. // of GUIDs and the code to do this is in the handler...
  344. spResultHandler->OnCreateDataObject(this, cookie, type, ppDataObject);
  345. }
  346. else
  347. {
  348. // this node has a virtual listbox for the result pane. Gerenate
  349. // a special data object using the selected node as the cookie
  350. Assert(m_spComponentData != NULL);
  351. CORg (m_spComponentData->QueryDataObject(reinterpret_cast<MMC_COOKIE>((ITFSNode *) spSelectedNode), type, ppDataObject));
  352. }
  353. pDataObject = reinterpret_cast<CDataObject *>(*ppDataObject);
  354. pDataObject->SetVirtualIndex((int) cookie);
  355. }
  356. else
  357. {
  358. // just forward this to the component data
  359. Assert(m_spComponentData != NULL);
  360. CORg (m_spComponentData->QueryDataObject(cookie, type, ppDataObject));
  361. }
  362. COM_PROTECT_ERROR_LABEL;
  363. }
  364. COM_PROTECT_CATCH
  365. return hr;
  366. }
  367. /*!--------------------------------------------------------------------------
  368. CTapiComponentData::SetControlbar
  369. -
  370. Author: EricDav, KennT
  371. ---------------------------------------------------------------------------*/
  372. HRESULT
  373. CTapiComponent::SetControlbar
  374. (
  375. LPCONTROLBAR pControlbar
  376. )
  377. {
  378. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  379. HRESULT hr = hrOK;
  380. if (pControlbar)
  381. {
  382. }
  383. // store the control bar away for future use
  384. m_spControlbar.Set(pControlbar);
  385. return hr;
  386. }
  387. /*!--------------------------------------------------------------------------
  388. CTapiComponentData::ControlbarNotify
  389. -
  390. Author: EricDav
  391. ---------------------------------------------------------------------------*/
  392. STDMETHODIMP
  393. CTapiComponent::ControlbarNotify
  394. (
  395. MMC_NOTIFY_TYPE event,
  396. LPARAM arg,
  397. LPARAM param
  398. )
  399. {
  400. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  401. HRESULT hr = hrOK;
  402. return hr;
  403. }
  404. /*!--------------------------------------------------------------------------
  405. CTapiComponentData::OnSnapinHelp
  406. -
  407. Author: EricDav
  408. ---------------------------------------------------------------------------*/
  409. STDMETHODIMP
  410. CTapiComponent::OnSnapinHelp
  411. (
  412. LPDATAOBJECT pDataObject,
  413. LPARAM arg,
  414. LPARAM param
  415. )
  416. {
  417. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  418. HRESULT hr = hrOK;
  419. HtmlHelpA(NULL, "tapisnap.chm", HH_DISPLAY_TOPIC, 0);
  420. return hr;
  421. }
  422. /*---------------------------------------------------------------------------
  423. Class CTapiComponentData implementation
  424. ---------------------------------------------------------------------------*/
  425. CTapiComponentData::CTapiComponentData()
  426. {
  427. gdwTapiSnapVersion = TAPISNAP_VERSION;
  428. }
  429. /*!--------------------------------------------------------------------------
  430. CTapiComponentData::OnInitialize
  431. -
  432. Author: EricDav, KennT
  433. ---------------------------------------------------------------------------*/
  434. STDMETHODIMP CTapiComponentData::OnInitialize(LPIMAGELIST pScopeImage)
  435. {
  436. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  437. HICON hIcon;
  438. for (int i = 0; i < ICON_IDX_MAX; i++)
  439. {
  440. hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(g_uIconMap[i][0]));
  441. if (hIcon)
  442. {
  443. // call mmc
  444. VERIFY(SUCCEEDED(pScopeImage->ImageListSetIcon(reinterpret_cast<LONG_PTR*>(hIcon), g_uIconMap[i][1])));
  445. }
  446. }
  447. return hrOK;
  448. }
  449. /*!--------------------------------------------------------------------------
  450. CTapiComponentData::OnDestroy
  451. -
  452. Author: EricDav, KennT
  453. ---------------------------------------------------------------------------*/
  454. STDMETHODIMP CTapiComponentData::OnDestroy()
  455. {
  456. m_spNodeMgr.Release();
  457. return hrOK;
  458. }
  459. /*!--------------------------------------------------------------------------
  460. CTapiComponentData::OnInitializeNodeMgr
  461. -
  462. Author: KennT
  463. ---------------------------------------------------------------------------*/
  464. STDMETHODIMP
  465. CTapiComponentData::OnInitializeNodeMgr
  466. (
  467. ITFSComponentData * pTFSCompData,
  468. ITFSNodeMgr * pNodeMgr
  469. )
  470. {
  471. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  472. // For now create a new node handler for each new node,
  473. // this is rather bogus as it can get expensive. We can
  474. // consider creating only a single node handler for each
  475. // node type.
  476. CTapiRootHandler * pHandler = NULL;
  477. SPITFSNodeHandler spHandler;
  478. SPITFSNode spNode;
  479. HRESULT hr = hrOK;
  480. try
  481. {
  482. pHandler = new CTapiRootHandler(pTFSCompData);
  483. // Do this so that it will get released correctly
  484. spHandler = pHandler;
  485. }
  486. catch(...)
  487. {
  488. hr = E_OUTOFMEMORY;
  489. }
  490. CORg( hr );
  491. // Create the root node for this sick puppy
  492. CORg( CreateContainerTFSNode(&spNode,
  493. &GUID_TapiRootNodeType,
  494. pHandler,
  495. pHandler, /* result handler */
  496. pNodeMgr) );
  497. // Need to initialize the data for the root node
  498. pHandler->InitializeNode(spNode);
  499. CORg( pNodeMgr->SetRootNode(spNode) );
  500. m_spRootNode.Set(spNode);
  501. pTFSCompData->SetHTMLHelpFileName(_T("tapisnap.chm"));
  502. Error:
  503. return hr;
  504. }
  505. /*!--------------------------------------------------------------------------
  506. CTapiComponentData::OnCreateComponent
  507. -
  508. Author: EricDav, KennT
  509. ---------------------------------------------------------------------------*/
  510. STDMETHODIMP
  511. CTapiComponentData::OnCreateComponent
  512. (
  513. LPCOMPONENT *ppComponent
  514. )
  515. {
  516. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  517. ASSERT(ppComponent != NULL);
  518. HRESULT hr = hrOK;
  519. CTapiComponent * pComp = NULL;
  520. try
  521. {
  522. pComp = new CTapiComponent;
  523. }
  524. catch(...)
  525. {
  526. hr = E_OUTOFMEMORY;
  527. }
  528. if (FHrSucceeded(hr))
  529. {
  530. pComp->Construct(m_spNodeMgr,
  531. static_cast<IComponentData *>(this),
  532. m_spTFSComponentData);
  533. *ppComponent = static_cast<IComponent *>(pComp);
  534. }
  535. return hr;
  536. }
  537. /*!--------------------------------------------------------------------------
  538. CTapiComponentData::GetCoClassID
  539. -
  540. Author: KennT
  541. ---------------------------------------------------------------------------*/
  542. STDMETHODIMP_(const CLSID *)
  543. CTapiComponentData::GetCoClassID()
  544. {
  545. return &CLSID_TapiSnapin;
  546. }
  547. /*!--------------------------------------------------------------------------
  548. CTapiComponentData::OnCreateDataObject
  549. -
  550. Author: KennT
  551. ---------------------------------------------------------------------------*/
  552. STDMETHODIMP
  553. CTapiComponentData::OnCreateDataObject
  554. (
  555. MMC_COOKIE cookie,
  556. DATA_OBJECT_TYPES type,
  557. IDataObject ** ppDataObject
  558. )
  559. {
  560. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  561. Assert(ppDataObject != NULL);
  562. CDataObject * pObject = NULL;
  563. SPIDataObject spDataObject;
  564. pObject = new CDataObject;
  565. spDataObject = pObject; // do this so that it gets released correctly
  566. Assert(pObject != NULL);
  567. // Save cookie and type for delayed rendering
  568. pObject->SetType(type);
  569. pObject->SetCookie(cookie);
  570. // Store the coclass with the data object
  571. pObject->SetClsid(*GetCoClassID());
  572. pObject->SetTFSComponentData(m_spTFSComponentData);
  573. return pObject->QueryInterface(IID_IDataObject,
  574. reinterpret_cast<void**>(ppDataObject));
  575. }
  576. ///////////////////////////////////////////////////////////////////////////////
  577. //// IPersistStream interface members
  578. STDMETHODIMP
  579. CTapiComponentData::GetClassID
  580. (
  581. CLSID *pClassID
  582. )
  583. {
  584. ASSERT(pClassID != NULL);
  585. // Copy the CLSID for this snapin
  586. *pClassID = CLSID_TapiSnapin;
  587. return hrOK;
  588. }
  589. STDMETHODIMP
  590. CTapiComponentData::IsDirty()
  591. {
  592. HRESULT hr = hrFalse;
  593. if (m_spRootNode->GetData(TFS_DATA_DIRTY))
  594. {
  595. hr = hrOK;
  596. }
  597. else
  598. {
  599. //check whether the cache is dirtry
  600. SPITFSNodeEnum spNodeEnum;
  601. SPITFSNode spCurrentNode;
  602. ULONG nNumReturned = 0;
  603. m_spRootNode->GetEnum(&spNodeEnum);
  604. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  605. while (nNumReturned)
  606. {
  607. CTapiServer * pServer = GETHANDLER(CTapiServer, spCurrentNode);
  608. if (pServer->IsCacheDirty())
  609. {
  610. hr = hrOK;
  611. spCurrentNode.Release();
  612. break;
  613. }
  614. // go to the next node
  615. spCurrentNode.Release();
  616. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  617. }
  618. }
  619. return hr;
  620. }
  621. STDMETHODIMP
  622. CTapiComponentData::Load
  623. (
  624. IStream *pStm
  625. )
  626. {
  627. HRESULT hr = hrOK;
  628. DWORD dwSavedVersion;
  629. CString str;
  630. int i, j;
  631. ASSERT(pStm);
  632. CStringArray strArrayName;
  633. CDWordArray dwArrayRefreshInterval;
  634. CDWordArray dwArrayOptions;
  635. CDWordArray dwArrayColumnInfo;
  636. CDWordArray dwArrayLines;
  637. CDWordArray dwArrayPhones;
  638. ASSERT(pStm);
  639. CTapiRootHandler * pRootHandler = GETHANDLER(CTapiRootHandler, m_spRootNode);
  640. // set the mode for this stream
  641. XferStream xferStream(pStm, XferStream::MODE_READ);
  642. // read the version of the file format
  643. DWORD dwFileVersion;
  644. CORg(xferStream.XferDWORD(TAPISTRM_TAG_VERSION, &dwFileVersion));
  645. if (dwFileVersion < TAPISNAP_FILE_VERSION_1)
  646. {
  647. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  648. AfxMessageBox(IDS_ERR_OLD_CONSOLE_FILE);
  649. return hr;
  650. }
  651. // Read the version # of the admin tool
  652. CORg(xferStream.XferDWORD(TAPISTRM_TAG_VERSIONADMIN, &dwSavedVersion));
  653. if (dwSavedVersion < gdwTapiSnapVersion)
  654. {
  655. // File is an older version. Warn the user and then don't
  656. // load anything else
  657. Assert(FALSE);
  658. }
  659. // now read all of the server information
  660. CORg(xferStream.XferCStringArray(TAPISTRM_TAG_SERVER_NAME, &strArrayName));
  661. CORg(xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_REFRESH_INTERVAL, &dwArrayRefreshInterval));
  662. CORg(xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_OPTIONS, &dwArrayOptions));
  663. // now load the column information
  664. for (i = 0; i < NUM_SCOPE_ITEMS; i++)
  665. {
  666. CORg(xferStream.XferDWORDArray(TAPISTRM_TAG_COLUMN_INFO, &dwArrayColumnInfo));
  667. for (j = 0; j < MAX_COLUMNS; j++)
  668. {
  669. aColumnWidths[i][j] = dwArrayColumnInfo[j];
  670. }
  671. }
  672. if (dwFileVersion >= TAPISNAP_FILE_VERSION)
  673. {
  674. CORg(xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_LINE_SIZE, &dwArrayLines));
  675. CORg(xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_PHONE_SIZE, &dwArrayPhones));
  676. }
  677. // now create the servers based on the information
  678. for (i = 0; i < strArrayName.GetSize(); i++)
  679. {
  680. //
  681. // now create the server object
  682. //
  683. pRootHandler->AddServer(NULL,
  684. strArrayName[i],
  685. FALSE,
  686. dwArrayOptions[i],
  687. dwArrayRefreshInterval[i],
  688. FALSE,
  689. (dwFileVersion >= TAPISNAP_FILE_VERSION) ? dwArrayLines[i] : 0,
  690. (dwFileVersion >= TAPISNAP_FILE_VERSION) ? dwArrayPhones[i] : 0);
  691. }
  692. Error:
  693. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  694. }
  695. STDMETHODIMP
  696. CTapiComponentData::Save
  697. (
  698. IStream *pStm,
  699. BOOL fClearDirty
  700. )
  701. {
  702. HRESULT hr = hrOK;
  703. CStringArray strArrayName;
  704. CDWordArray dwArrayRefreshInterval;
  705. CDWordArray dwArrayOptions;
  706. CDWordArray dwArrayColumnInfo;
  707. CDWordArray dwArrayLines;
  708. CDWordArray dwArrayPhones;
  709. ASSERT(pStm);
  710. // set the mode for this stream
  711. XferStream xferStream(pStm, XferStream::MODE_WRITE);
  712. CString str;
  713. // Write the version # of the file format
  714. DWORD dwFileVersion = TAPISNAP_FILE_VERSION;
  715. xferStream.XferDWORD(TAPISTRM_TAG_VERSION, &dwFileVersion);
  716. // Write the version # of the admin tool
  717. xferStream.XferDWORD(TAPISTRM_TAG_VERSIONADMIN, &gdwTapiSnapVersion);
  718. //
  719. // Build our array of servers
  720. //
  721. int nNumServers = 0, nVisibleCount = 0;
  722. hr = m_spRootNode->GetChildCount(&nVisibleCount, &nNumServers);
  723. strArrayName.SetSize(nNumServers);
  724. dwArrayRefreshInterval.SetSize(nNumServers);
  725. dwArrayOptions.SetSize(nNumServers);
  726. dwArrayColumnInfo.SetSize(MAX_COLUMNS);
  727. dwArrayLines.SetSize(nNumServers);
  728. dwArrayPhones.SetSize(nNumServers);
  729. //
  730. // loop and save off all the server's attributes
  731. //
  732. SPITFSNodeEnum spNodeEnum;
  733. SPITFSNode spCurrentNode;
  734. ULONG nNumReturned = 0;
  735. int nCount = 0;
  736. m_spRootNode->GetEnum(&spNodeEnum);
  737. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  738. while (nNumReturned)
  739. {
  740. CTapiServer * pServer = GETHANDLER(CTapiServer, spCurrentNode);
  741. // query the server for it's options:
  742. // auto refresh
  743. dwArrayRefreshInterval[nCount] = pServer->GetAutoRefreshInterval();
  744. dwArrayOptions[nCount] = pServer->GetOptions();
  745. // put the information in our array
  746. strArrayName[nCount] = pServer->GetName();
  747. // put the cached line and phone size in the array
  748. dwArrayLines[nCount] = pServer->GetCachedLineBuffSize();
  749. dwArrayPhones[nCount] = pServer->GetCachedPhoneBuffSize();
  750. // go to the next node
  751. spCurrentNode.Release();
  752. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  753. nCount++;
  754. }
  755. // now write out all of the server information
  756. xferStream.XferCStringArray(TAPISTRM_TAG_SERVER_NAME, &strArrayName);
  757. xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_REFRESH_INTERVAL, &dwArrayRefreshInterval);
  758. xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_OPTIONS, &dwArrayOptions);
  759. // now save the column information
  760. for (int i = 0; i < NUM_SCOPE_ITEMS; i++)
  761. {
  762. for (int j = 0; j < MAX_COLUMNS; j++)
  763. {
  764. dwArrayColumnInfo[j] = aColumnWidths[i][j];
  765. }
  766. xferStream.XferDWORDArray(TAPISTRM_TAG_COLUMN_INFO, &dwArrayColumnInfo);
  767. }
  768. xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_LINE_SIZE, &dwArrayLines);
  769. xferStream.XferDWORDArray(TAPISTRM_TAG_SERVER_PHONE_SIZE, &dwArrayPhones);
  770. if (fClearDirty)
  771. {
  772. m_spRootNode->SetData(TFS_DATA_DIRTY, FALSE);
  773. }
  774. return SUCCEEDED(hr) ? S_OK : STG_E_CANTSAVE;
  775. }
  776. STDMETHODIMP
  777. CTapiComponentData::GetSizeMax
  778. (
  779. ULARGE_INTEGER *pcbSize
  780. )
  781. {
  782. ASSERT(pcbSize);
  783. // Set the size of the string to be saved
  784. ULISet32(*pcbSize, 10000);
  785. return S_OK;
  786. }
  787. STDMETHODIMP
  788. CTapiComponentData::InitNew()
  789. {
  790. return hrOK;
  791. }
  792. HRESULT
  793. CTapiComponentData::FinalConstruct()
  794. {
  795. HRESULT hr = hrOK;
  796. hr = CComponentData::FinalConstruct();
  797. if (FHrSucceeded(hr))
  798. {
  799. m_spTFSComponentData->GetNodeMgr(&m_spNodeMgr);
  800. }
  801. return hr;
  802. }
  803. void
  804. CTapiComponentData::FinalRelease()
  805. {
  806. CComponentData::FinalRelease();
  807. }