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.

810 lines
19 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : OutboundGroups.cpp //
  3. // //
  4. // DESCRIPTION : Fax Server - Fax OutboundGroups node. //
  5. // //
  6. // AUTHOR : yossg //
  7. // //
  8. // HISTORY : //
  9. // Sep 29 1999 yossg create //
  10. // Jan 3 2000 yossg add new group //
  11. // Oct 17 2000 yossg //
  12. // //
  13. // Copyright (C) 1999 Microsoft Corporation All Rights Reserved //
  14. /////////////////////////////////////////////////////////////////////////////
  15. #include "StdAfx.h"
  16. #include "FaxServer.h"
  17. #include "FaxServerNode.h"
  18. #include "OutboundGroups.h"
  19. #include "OutboundGroup.h"
  20. #include "dlgNewGroup.h"
  21. #include "Icons.h"
  22. //#include "oaidl.h"
  23. // {1036F509-554F-41b7-BE77-CF8E8E994011}
  24. static const GUID CFaxOutboundGroupsNodeGUID_NODETYPE =
  25. { 0x1036f509, 0x554f, 0x41b7, { 0xbe, 0x77, 0xcf, 0x8e, 0x8e, 0x99, 0x40, 0x11 } };
  26. const GUID* CFaxOutboundGroupsNode::m_NODETYPE = &CFaxOutboundGroupsNodeGUID_NODETYPE;
  27. const OLECHAR* CFaxOutboundGroupsNode::m_SZNODETYPE = OLESTR("1036F509-554F-41b7-BE77-CF8E8E994011");
  28. const CLSID* CFaxOutboundGroupsNode::m_SNAPIN_CLASSID = &CLSID_Snapin;
  29. CColumnsInfo CFaxOutboundGroupsNode::m_ColsInfo;
  30. /*
  31. - CFaxOutboundGroupsNode::initRPC
  32. -
  33. * Purpose:
  34. * Initiates the configuration structure from RPC get Call.
  35. *
  36. * Arguments:
  37. *
  38. * Return:
  39. * OLE error code
  40. */
  41. HRESULT CFaxOutboundGroupsNode::InitRPC(PFAX_OUTBOUND_ROUTING_GROUP * pFaxGroupsConfig)
  42. {
  43. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::InitRPC"));
  44. HRESULT hRc = S_OK;
  45. DWORD ec = ERROR_SUCCESS;
  46. CFaxServer * pFaxServer = NULL;
  47. //
  48. // get Fax Handle
  49. //
  50. pFaxServer = ((CFaxServerNode *)GetRootNode())->GetFaxServer();
  51. ATLASSERT(pFaxServer);
  52. if (!pFaxServer->GetFaxServerHandle())
  53. {
  54. ec= GetLastError();
  55. DebugPrintEx(
  56. DEBUG_ERR,
  57. _T("Failed to GetFaxServerHandle. (ec: %ld)"),
  58. ec);
  59. goto Error;
  60. }
  61. //
  62. // Retrieve the Outbound Groups configuration
  63. //
  64. if (!FaxEnumOutboundGroups(pFaxServer->GetFaxServerHandle(),
  65. pFaxGroupsConfig,
  66. &m_dwNumOfGroups))
  67. {
  68. ec = GetLastError();
  69. DebugPrintEx(
  70. DEBUG_ERR,
  71. _T("Fail to get groups configuration. (ec: %ld)"),
  72. ec);
  73. if (IsNetworkError(ec))
  74. {
  75. DebugPrintEx(
  76. DEBUG_ERR,
  77. _T("Network Error was found. (ec: %ld)"),
  78. ec);
  79. pFaxServer->Disconnect();
  80. }
  81. goto Error;
  82. }
  83. //For max verification
  84. ATLASSERT(*pFaxGroupsConfig);
  85. ATLASSERT(FXS_ITEMS_NEVER_COUNTED != m_dwNumOfGroups);
  86. ATLASSERT(ERROR_SUCCESS == ec);
  87. DebugPrintEx( DEBUG_MSG,
  88. _T("Succeed to get groups configuration."));
  89. goto Exit;
  90. Error:
  91. ATLASSERT(ERROR_SUCCESS != ec);
  92. hRc = HRESULT_FROM_WIN32(ec);
  93. //
  94. // allow refresh in case of failure
  95. //
  96. m_dwNumOfGroups = 0;
  97. NodeMsgBox(GetFaxServerErrorMsg(ec));
  98. Exit:
  99. return (hRc);
  100. }
  101. /*
  102. - CFaxOutboundGroupsNode::PopulateScopeChildrenList
  103. -
  104. * Purpose:
  105. * Create all the Fax Outbound Routing Group nodes
  106. *
  107. * Arguments:
  108. *
  109. * Return:
  110. * OLE error code
  111. * Actually it is the last OLE error code that ocoured
  112. * during processing this method.
  113. */
  114. HRESULT CFaxOutboundGroupsNode::PopulateScopeChildrenList()
  115. {
  116. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::PopulateScopeChildrenList"));
  117. HRESULT hRc = S_OK;
  118. CFaxOutboundRoutingGroupNode * pGroup = NULL;
  119. PFAX_OUTBOUND_ROUTING_GROUP pFaxOutboundGroupsConfig = NULL;
  120. DWORD i;
  121. //
  122. // Get the Config. structure
  123. //
  124. hRc = InitRPC(&pFaxOutboundGroupsConfig);
  125. if (FAILED(hRc))
  126. {
  127. //DebugPrint and MsgBox by called func.
  128. //to be safe actually done by InitRPC on error.
  129. pFaxOutboundGroupsConfig = NULL;
  130. goto Error;
  131. }
  132. ATLASSERT(NULL != pFaxOutboundGroupsConfig);
  133. for (i=0; i< m_dwNumOfGroups; i++ )
  134. {
  135. pGroup = new CFaxOutboundRoutingGroupNode(
  136. this,
  137. m_pComponentData);
  138. if (!pGroup)
  139. {
  140. hRc = E_OUTOFMEMORY;
  141. NodeMsgBox(IDS_MEMORY);
  142. DebugPrintEx(
  143. DEBUG_ERR,
  144. TEXT("Out of memory. (hRc: %08X)"),
  145. hRc);
  146. goto Error;
  147. }
  148. else
  149. {
  150. pGroup->InitParentNode(this);
  151. hRc = pGroup->Init(&pFaxOutboundGroupsConfig[i]);
  152. if (FAILED(hRc))
  153. {
  154. DebugPrintEx(
  155. DEBUG_ERR,
  156. TEXT("Fail to init Group. (hRc: %08X)"),
  157. hRc);
  158. NodeMsgBox(IDS_FAILTOINIT_GROUP);
  159. goto Error;
  160. }
  161. hRc = AddChild(pGroup, &pGroup->m_scopeDataItem);
  162. if (FAILED(hRc))
  163. {
  164. DebugPrintEx(
  165. DEBUG_ERR,
  166. TEXT("Fail to add Group. (hRc: %08X)"),
  167. hRc);
  168. NodeMsgBox(IDS_FAILTOADD_GROUP);
  169. goto Error;
  170. }
  171. }
  172. }
  173. pGroup = NULL;
  174. ATLASSERT(S_OK == hRc);
  175. goto Exit;
  176. Error:
  177. ATLASSERT(S_OK != hRc);
  178. //
  179. //Get Rid
  180. //
  181. {
  182. //from the last one
  183. if ( NULL != pGroup ) //(if new succeeded)
  184. {
  185. delete pGroup;
  186. }
  187. //from all the previous (if there are)
  188. int j = m_ScopeChildrenList.GetSize();
  189. for (int index = 0; index < j; index++)
  190. {
  191. pGroup = (CFaxOutboundRoutingGroupNode *)m_ScopeChildrenList[0];
  192. hRc = RemoveChild(pGroup);
  193. if (FAILED(hRc))
  194. {
  195. DebugPrintEx(DEBUG_ERR,
  196. _T("Fail to delete group. (hRc: %08X)"),
  197. hRc);
  198. goto Error;
  199. }
  200. delete pGroup;
  201. }
  202. // Empty the list of all groups added before the one who failed
  203. // already done one by one inside RemoveChild
  204. // m_ScopeChildrenList.RemoveAll();
  205. m_bScopeChildrenListPopulated = FALSE;
  206. }
  207. Exit:
  208. if (NULL != pFaxOutboundGroupsConfig)
  209. {
  210. FaxFreeBuffer(pFaxOutboundGroupsConfig);
  211. }
  212. return hRc;
  213. }
  214. /*
  215. - CFaxOutboundGroupsNode::InsertColumns
  216. -
  217. * Purpose:
  218. * Adds columns to the default result pane.
  219. *
  220. * Arguments:
  221. * [in] pHeaderCtrl - IHeaderCtrl in the console-provided default result view pane
  222. *
  223. * Return:
  224. * OLE error code
  225. */
  226. HRESULT
  227. CFaxOutboundGroupsNode::InsertColumns(IHeaderCtrl *pHeaderCtrl)
  228. {
  229. SCODE hRc;
  230. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::InsertColumns"));
  231. static ColumnsInfoInitData ColumnsInitData[] =
  232. {
  233. {IDS_OUTBOUND_GROUPS_COL1, FXS_WIDE_COLUMN_WIDTH},
  234. {IDS_OUTBOUND_GROUPS_COL2, AUTO_WIDTH},
  235. {IDS_OUTBOUND_GROUPS_COL3, AUTO_WIDTH},
  236. {LAST_IDS, 0}
  237. };
  238. hRc = m_ColsInfo.InsertColumnsIntoMMC(pHeaderCtrl,
  239. _Module.GetResourceInstance(),
  240. ColumnsInitData);
  241. if (hRc != S_OK)
  242. {
  243. DebugPrintEx(DEBUG_ERR,_T("m_ColsInfo.InsertColumnsIntoMMC. (hRc: %08X)"), hRc);
  244. goto Cleanup;
  245. }
  246. Cleanup:
  247. return(hRc);
  248. }
  249. /*
  250. - CFaxOutboundGroupsNode::SetVerbs
  251. -
  252. * Purpose:
  253. * What verbs to enable/disable when this object is selected
  254. *
  255. * Arguments:
  256. * [in] pConsoleVerb - MMC ConsoleVerb interface
  257. *
  258. * Return:
  259. * OLE Error code
  260. */
  261. HRESULT CFaxOutboundGroupsNode::SetVerbs(IConsoleVerb *pConsoleVerb)
  262. {
  263. HRESULT hRc = S_OK;
  264. //
  265. // Refresh
  266. //
  267. hRc = pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  268. //
  269. // We want the default verb to be expand node children
  270. //
  271. hRc = pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  272. return hRc;
  273. }
  274. /*
  275. - CFaxOutboundGroupsNode::OnRefresh
  276. -
  277. * Purpose:
  278. * Called when refreshing the object.
  279. *
  280. * Arguments:
  281. *
  282. * Return:
  283. * OLE error code
  284. */
  285. HRESULT
  286. CFaxOutboundGroupsNode::OnRefresh(LPARAM arg,
  287. LPARAM param,
  288. IComponentData *pComponentData,
  289. IComponent * pComponent,
  290. DATA_OBJECT_TYPES type)
  291. {
  292. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::OnRefresh"));
  293. HRESULT hRc = S_OK;
  294. SCOPEDATAITEM* pScopeData;
  295. CComPtr<IConsole> spConsole;
  296. if (FXS_ITEMS_NEVER_COUNTED != m_dwNumOfGroups)//already expanded before.
  297. {
  298. //
  299. // Repopulate Scope Children List
  300. //
  301. hRc = RepopulateScopeChildrenList();
  302. if (S_OK != hRc)
  303. {
  304. DebugPrintEx(
  305. DEBUG_ERR,
  306. TEXT("Fail to RepopulateScopeChildrenList(). (hRc: %08X)"),
  307. hRc);
  308. // Done by called func. NodeMsgBox(FAIL2REPOPULATE_GROUP_LIST);
  309. goto Exit;
  310. }
  311. }
  312. else //never expanded before
  313. {
  314. DebugPrintEx(
  315. DEBUG_MSG,
  316. _T("User call refresh before expand node's children."));
  317. //continue to reselect the node.
  318. }
  319. //
  320. // Get the updated SCOPEDATAITEM
  321. //
  322. hRc = GetScopeData( &pScopeData );
  323. if (FAILED(hRc))
  324. {
  325. DebugPrintEx(
  326. DEBUG_ERR,
  327. TEXT("Fail to get pScopeData. (hRc: %08X)"),
  328. hRc);
  329. NodeMsgBox(IDS_FAIL2REDRAW_GROUPSNODE);
  330. goto Exit;
  331. }
  332. //
  333. // This will force MMC to redraw the scope node
  334. //
  335. spConsole = m_pComponentData->m_spConsole;
  336. ATLASSERT(spConsole);
  337. hRc = spConsole->SelectScopeItem( pScopeData->ID );
  338. if (FAILED(hRc))
  339. {
  340. DebugPrintEx(
  341. DEBUG_ERR,
  342. TEXT("Fail to select scope Item. (hRc: %08X)"),
  343. hRc);
  344. NodeMsgBox(IDS_FAIL2REDRAW_GROUPSNODE);
  345. }
  346. Exit:
  347. return hRc;
  348. }
  349. /*
  350. - CFaxOutboundGroupsNode::OnNewGroup
  351. -
  352. * Purpose:
  353. *
  354. *
  355. * Arguments:
  356. * [out] bHandled - Do we handle it?
  357. * [in] pRoot - The root node
  358. *
  359. * Return:
  360. * OLE Error code
  361. */
  362. HRESULT
  363. CFaxOutboundGroupsNode::OnNewGroup(bool &bHandled, CSnapInObjectRootBase *pRoot)
  364. {
  365. DEBUG_FUNCTION_NAME( _T("CDlgNewFaxOutboundGroup::OnNewGroup"));
  366. HRESULT hRc = S_OK;
  367. INT_PTR rc = IDOK;
  368. CDlgNewFaxOutboundGroup DlgNewGroup(((CFaxServerNode *)GetRootNode())->GetFaxServer());
  369. //
  370. // Dialog to add group
  371. //
  372. rc = DlgNewGroup.DoModal();
  373. if (rc != IDOK)
  374. {
  375. goto Cleanup;
  376. }
  377. //
  378. // Repopulate (with RPC) and Refresh the view
  379. //
  380. if (m_bScopeChildrenListPopulated)
  381. {
  382. DoRefresh(pRoot);
  383. }
  384. Cleanup:
  385. return hRc;
  386. }
  387. /*
  388. - CFaxOutboundGroupsNode::RepopulateScopeChildrenList
  389. -
  390. * Purpose:
  391. * RePopulateScopeChildrenList
  392. *
  393. * Arguments:
  394. *
  395. * Return:
  396. * OLE Error code
  397. */
  398. HRESULT CFaxOutboundGroupsNode::RepopulateScopeChildrenList()
  399. {
  400. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::RepopulateScopeChildrenList"));
  401. HRESULT hRc = S_OK;
  402. CFaxOutboundRoutingGroupNode *pChildNode ;
  403. CComPtr<IConsole> spConsole;
  404. ATLASSERT(m_pComponentData);
  405. spConsole = ((CSnapin*)m_pComponentData)->m_spConsole;
  406. ATLASSERT( spConsole != NULL );
  407. CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace(spConsole);
  408. //
  409. // Remove group objects from list
  410. //
  411. for (int i = 0; i < m_ScopeChildrenList.GetSize(); i++)
  412. {
  413. pChildNode = (CFaxOutboundRoutingGroupNode *)m_ScopeChildrenList[i];
  414. hRc = spConsoleNameSpace->DeleteItem(pChildNode->m_scopeDataItem.ID, TRUE);
  415. if (FAILED(hRc))
  416. {
  417. DebugPrintEx(DEBUG_ERR,
  418. _T("Fail to delete group. (hRc: %08X)"),
  419. hRc);
  420. // This is a very bad place to catch a failure
  421. // DeleteItem may return S_OK or E_UNEXPECTED
  422. // We do not pop-up this info to the user.
  423. goto Error;
  424. }
  425. delete pChildNode;
  426. }
  427. //
  428. // Empty the list object itself and change it's status
  429. //
  430. m_ScopeChildrenList.RemoveAll();
  431. m_bScopeChildrenListPopulated = FALSE;
  432. //
  433. // Rebuild the list
  434. //
  435. hRc = PopulateScopeChildrenList();
  436. if (FAILED(hRc))
  437. {
  438. DebugPrintEx(DEBUG_ERR,
  439. _T("Fail to Populate groups. (hRc: %08X)"),
  440. hRc);
  441. goto Error;
  442. }
  443. m_bScopeChildrenListPopulated = TRUE;
  444. ATLASSERT(S_OK == hRc);
  445. DebugPrintEx(DEBUG_MSG,
  446. _T("Succeeded to Re Populate Groups. (hRc: %08X)"),
  447. hRc);
  448. goto Cleanup;
  449. Error:
  450. NodeMsgBox(IDS_FAIL2REPOPULATE_GROUPS);
  451. Cleanup:
  452. return hRc;
  453. }
  454. /*
  455. - CFaxOutboundGroupsNode::DoRefresh
  456. -
  457. * Purpose:
  458. * Refresh the view
  459. *
  460. * Arguments:
  461. * [in] pRoot - The root node
  462. *
  463. * Return:
  464. * OLE Error code
  465. */
  466. HRESULT
  467. CFaxOutboundGroupsNode::DoRefresh(CSnapInObjectRootBase *pRoot)
  468. {
  469. CComPtr<IConsole> spConsole;
  470. //
  471. // Repopulate childs
  472. //
  473. RepopulateScopeChildrenList();
  474. if (pRoot)
  475. {
  476. //
  477. // Get the console pointer
  478. //
  479. ATLASSERT(pRoot->m_nType == 1 || pRoot->m_nType == 2);
  480. if (pRoot->m_nType == 1)
  481. {
  482. //
  483. // m_ntype == 1 means the IComponentData implementation
  484. //
  485. CSnapin *pCComponentData = static_cast<CSnapin *>(pRoot);
  486. spConsole = pCComponentData->m_spConsole;
  487. }
  488. else
  489. {
  490. //
  491. // m_ntype == 2 means the IComponent implementation
  492. //
  493. CSnapinComponent *pCComponent = static_cast<CSnapinComponent *>(pRoot);
  494. spConsole = pCComponent->m_spConsole;
  495. }
  496. }
  497. else
  498. {
  499. ATLASSERT(m_pComponentData);
  500. spConsole = m_pComponentData->m_spConsole;
  501. }
  502. ATLASSERT(spConsole);
  503. spConsole->UpdateAllViews(NULL, NULL, NULL);
  504. return S_OK;
  505. }
  506. HRESULT
  507. CFaxOutboundGroupsNode::DoRefresh()
  508. {
  509. DEBUG_FUNCTION_NAME( _T("CFaxOutboundGroupsNode::DoRefresh()"));
  510. HRESULT hRc = S_OK;
  511. CComPtr<IConsole> spConsole;
  512. //
  513. // Repopulate childs
  514. //
  515. RepopulateScopeChildrenList();
  516. ATLASSERT( m_pComponentData != NULL );
  517. ATLASSERT( m_pComponentData->m_spConsole != NULL );
  518. hRc = m_pComponentData->m_spConsole->UpdateAllViews( NULL, NULL, NULL);
  519. if (FAILED(hRc))
  520. {
  521. DebugPrintEx( DEBUG_ERR,
  522. _T("Unexpected error - Fail to UpdateAllViews."));
  523. NodeMsgBox(IDS_FAIL2REFRESH_THEVIEW);
  524. }
  525. return hRc;
  526. }
  527. /*
  528. - CFaxOutboundGroupsNode::InitDisplayName
  529. -
  530. * Purpose:
  531. * To load the node's Displaed-Name string.
  532. *
  533. * Arguments:
  534. *
  535. * Return:
  536. * OLE error code
  537. */
  538. HRESULT CFaxOutboundGroupsNode::InitDisplayName()
  539. {
  540. DEBUG_FUNCTION_NAME(_T("CFaxOutboundGroupNode::InitDisplayName"));
  541. HRESULT hRc = S_OK;
  542. if (!m_bstrDisplayName.LoadString(_Module.GetResourceInstance(), IDS_DISPLAY_STR_OUTROUTEGROUPSNODE) )
  543. {
  544. hRc = E_OUTOFMEMORY;
  545. goto Error;
  546. }
  547. ATLASSERT( S_OK == hRc);
  548. goto Exit;
  549. Error:
  550. ATLASSERT( S_OK != hRc);
  551. m_bstrDisplayName = L"";
  552. DebugPrintEx(
  553. DEBUG_ERR,
  554. TEXT("Fail to Load server name string."));
  555. NodeMsgBox(IDS_MEMORY);
  556. Exit:
  557. return hRc;
  558. }
  559. /*
  560. - CFaxOutboundGroupsNode::DeleteGroup
  561. -
  562. * Purpose:
  563. * Refresh the view
  564. *
  565. * Arguments:
  566. * [in] bstrName - The Group name
  567. * [in] pChildNode - The node to be deleted
  568. *
  569. * Return:
  570. * OLE Error code
  571. */
  572. HRESULT
  573. CFaxOutboundGroupsNode::DeleteGroup(BSTR bstrName, CFaxOutboundRoutingGroupNode *pChildNode)
  574. {
  575. DEBUG_FUNCTION_NAME(_T("CFaxOutboundGroupsNode::DeleteGroup"));
  576. HRESULT hRc = S_OK;
  577. DWORD ec = ERROR_SUCCESS;
  578. BOOL fSkipMessage = FALSE;
  579. CFaxServer * pFaxServer = NULL;
  580. //
  581. // get RPC Handle
  582. //
  583. pFaxServer = ((CFaxServerNode *)GetRootNode())->GetFaxServer();
  584. ATLASSERT(pFaxServer);
  585. if (!pFaxServer->GetFaxServerHandle())
  586. {
  587. ec= GetLastError();
  588. DebugPrintEx(
  589. DEBUG_ERR,
  590. _T("Failed to GetFaxServerHandle. (ec: %ld)"),
  591. ec);
  592. goto Error;
  593. }
  594. //
  595. // Remove with RPC from the server
  596. //
  597. if (!FaxRemoveOutboundGroup (
  598. pFaxServer->GetFaxServerHandle(),
  599. bstrName))
  600. {
  601. ec = GetLastError();
  602. DebugPrintEx(
  603. DEBUG_ERR,
  604. _T("Fail to remove group. (ec: %ld)"),
  605. ec);
  606. if (FAX_ERR_GROUP_IN_USE == ec)
  607. {
  608. DebugPrintEx(
  609. DEBUG_ERR,
  610. _T("The group is empty or none of group devices is valid. (ec: %ld)"),
  611. ec);
  612. NodeMsgBox(IDS_FAX_ERR_GROUP_IN_USE);
  613. fSkipMessage = TRUE;
  614. goto Error;
  615. }
  616. if (IsNetworkError(ec))
  617. {
  618. DebugPrintEx(
  619. DEBUG_ERR,
  620. _T("Network Error was found. (ec: %ld)"),
  621. ec);
  622. pFaxServer->Disconnect();
  623. }
  624. goto Error;
  625. }
  626. //
  627. // Remove from MMC
  628. //
  629. ATLASSERT(pChildNode);
  630. hRc = RemoveChild(pChildNode);
  631. if (FAILED(hRc))
  632. {
  633. DebugPrintEx(
  634. DEBUG_ERR,
  635. TEXT("Fail to remove Group. (hRc: %08X)"),
  636. hRc);
  637. NodeMsgBox(IDS_FAIL_TO_REMOVE_GROUP);
  638. return(hRc);
  639. }
  640. //
  641. // Call the group destructor
  642. //
  643. delete pChildNode;
  644. ATLASSERT(ERROR_SUCCESS == ec);
  645. DebugPrintEx( DEBUG_MSG,
  646. _T("The group was removed successfully."));
  647. goto Exit;
  648. Error:
  649. ATLASSERT(ERROR_SUCCESS != ec);
  650. hRc = HRESULT_FROM_WIN32(ec);
  651. if (!fSkipMessage)
  652. {
  653. NodeMsgBox(GetFaxServerErrorMsg(ec));
  654. }
  655. Exit:
  656. return (hRc);
  657. }
  658. /*
  659. +
  660. + CFaxOutboundGroupsNode::OnShowContextHelp
  661. *
  662. * Purpose:
  663. * Overrides CSnapinNode::OnShowContextHelp.
  664. *
  665. * Arguments:
  666. *
  667. * Return:
  668. - OLE error code
  669. -
  670. */
  671. HRESULT CFaxOutboundGroupsNode::OnShowContextHelp(
  672. IDisplayHelp* pDisplayHelp, LPOLESTR helpFile)
  673. {
  674. return DisplayContextHelp(pDisplayHelp, helpFile, HLP_GROUPS);
  675. }
  676. ///////////////////////////////////////////////////////////////////