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.

1332 lines
38 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : C_Snapin.cpp (Snapin.cpp) //
  3. // //
  4. // DESCRIPTION : Implementation file for //
  5. // CSnapin class //
  6. // CSnapinComponent class //
  7. // //
  8. // AUTHOR : ATL Snapin wizard //
  9. // //
  10. // HISTORY : //
  11. // May 25 1998 adik Init. //
  12. // Aug 24 1998 adik WEB IVR instead IVR. //
  13. // Sep 14 1998 yossg seperate common source to an included file //
  14. // Oct 18 1998 adik Merged with new wizard version. //
  15. // Jan 12 1999 adik Add ParentArrayInterfaceFromDataObject. //
  16. // Mar 28 1999 adik Remove persistence support. //
  17. // Mar 30 1999 adik Support of ICometSnapinNode in IDataObject. //
  18. // Apr 27 1999 adik Help support. //
  19. // Jun 10 1999 adik Change bitmap mask to white. //
  20. // Jun 14 1999 roytal used UNREFERENCED_PARAMETER to fix build wrn //
  21. // Jun 21 1999 adik Handle MMCN_COLUMN_CLICK to avoid ASSERT. //
  22. // Jun 22 1999 zvib change handling of property change //
  23. // //
  24. // Oct 13 1999 yossg Welcome to Fax Server //
  25. // Jan 19 2000 yossg Add CFaxPropertyChangeNotification to //
  26. // CSnapinComponent::Notify MMCN_PROPERTY_CHANGE //
  27. // Apr 14 2000 yossg Add support for primary snapin mode //
  28. // Jun 25 2000 yossg Add stream and command line primary snapin //
  29. // machine targeting. //
  30. // //
  31. // Copyright (C) 1998 - 2000 Microsoft Corporation All Rights Reserved //
  32. /////////////////////////////////////////////////////////////////////////////
  33. #include "StdAfx.h"
  34. #include "C_Snapin.h"
  35. #include "ResUtil.h"
  36. #include "FaxServerNode.h"
  37. #include "FaxMMCPropertyChange.h"
  38. #include "FxsValid.h"
  39. #include "Icons.h"
  40. #include <ObjBase.h>
  41. #include <windns.h> //DNS_MAX_NAME_BUFFER_LENGTH
  42. HRESULT
  43. AddBitmaps(IImageList *pImageList)
  44. {
  45. HBITMAP hBitmap16 = NULL;
  46. HBITMAP hBitmap32 = NULL;
  47. HINSTANCE hInst;
  48. HRESULT hr;
  49. // Load bitmaps associated with the scope pane
  50. // and add them to the image list
  51. // Loads the default bitmaps generated by the wizard
  52. // Change as required
  53. hInst = _Module.GetResourceInstance();
  54. //
  55. // Load 16 bits
  56. //
  57. hBitmap16 = LoadBitmap(hInst, MAKEINTRESOURCE(IDR_TOOLBAR_16));
  58. if (hBitmap16 == NULL)
  59. {
  60. hr = E_FAIL;
  61. ATLTRACE(_T("LoadBitmap failed\n"));
  62. goto Cleanup;
  63. }
  64. //
  65. // Load 32 bits
  66. //
  67. hBitmap32 = LoadBitmap(hInst, MAKEINTRESOURCE(IDR_TOOLBAR_32));
  68. if (hBitmap32 == NULL)
  69. {
  70. hr = E_FAIL;
  71. ATLTRACE(_T("LoadBitmap failed\n"));
  72. goto Cleanup;
  73. }
  74. //
  75. // Add to image list
  76. //
  77. hr = pImageList->ImageListSetStrip(
  78. (LONG_PTR*)hBitmap16,
  79. (LONG_PTR*)hBitmap32,
  80. 0,
  81. RGB(0, 0, 0));
  82. if ( FAILED(hr) )
  83. {
  84. ATLTRACE(_T("IImageList::ImageListSetStrip failed\n"));
  85. goto Cleanup;
  86. }
  87. Cleanup:
  88. if (NULL != hBitmap32)
  89. {
  90. DeleteObject(hBitmap32);
  91. }
  92. if (NULL != hBitmap16)
  93. {
  94. DeleteObject(hBitmap16);
  95. }
  96. return hr;
  97. }
  98. class CFaxServerNode;
  99. CSnapin::CSnapin()
  100. {
  101. m_bstrServerName = L""; //LocalMachine as default
  102. m_fAllowOverrideServerName = TRUE;
  103. m_pPrimaryFaxServerNode = new CFaxServerNode(
  104. NULL,
  105. this,
  106. L""); //m_bstrServerName.m_str
  107. ATLASSERT(m_pPrimaryFaxServerNode != NULL);
  108. m_pPrimaryFaxServerNode->SetIcons(IMAGE_FAX, IMAGE_FAX);
  109. m_pNode = (CSnapInItem *) m_pPrimaryFaxServerNode;
  110. m_pComponentData = this;
  111. m_CSnapinExtData.m_pComponentData = this;
  112. }
  113. CSnapin::~CSnapin()
  114. {
  115. if (NULL != m_pPrimaryFaxServerNode)
  116. {
  117. delete m_pPrimaryFaxServerNode;
  118. m_pPrimaryFaxServerNode = NULL;
  119. }
  120. m_pNode = NULL;
  121. }
  122. HRESULT
  123. CSnapin::Initialize(LPUNKNOWN pUnknown)
  124. {
  125. HRESULT hr = IComponentDataImpl<CSnapin, CSnapinComponent >::Initialize(pUnknown);
  126. if (FAILED(hr))
  127. return hr;
  128. CComPtr<IImageList> spImageList;
  129. if (m_spConsole->QueryScopeImageList(&spImageList) != S_OK)
  130. {
  131. ATLTRACE(_T("IConsole::QueryScopeImageList failed\n"));
  132. return E_UNEXPECTED;
  133. }
  134. hr = ::AddBitmaps(spImageList);
  135. return hr;
  136. }
  137. HRESULT
  138. CSnapinExtData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  139. LONG_PTR handle,
  140. IUnknown* pUnk,
  141. DATA_OBJECT_TYPES type)
  142. {
  143. UNREFERENCED_PARAMETER (lpProvider);
  144. UNREFERENCED_PARAMETER (handle);
  145. UNREFERENCED_PARAMETER (pUnk);
  146. // override this method.
  147. if (type == CCT_SCOPE || type == CCT_RESULT)
  148. {
  149. return S_OK;
  150. }
  151. return E_UNEXPECTED;
  152. }
  153. //////////////////////////////////////////////////////////////////////////////
  154. CSnapinComponent::CSnapinComponent():m_pSelectedNode(NULL)
  155. {
  156. }
  157. //////////////////////////////////////////////////////////////////////////////
  158. CSnapinComponent::~CSnapinComponent()
  159. {
  160. }
  161. //////////////////////////////////////////////////////////////////////////////
  162. /*++
  163. CSnapinComponent::Notify
  164. --*/
  165. //////////////////////////////////////////////////////////////////////////////
  166. HRESULT
  167. CSnapinComponent::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  168. {
  169. DEBUG_FUNCTION_NAME( _T("CSnapinComponent::Notify"));
  170. HRESULT hr = S_OK;
  171. if(lpDataObject != NULL && MMCN_SHOW != event)
  172. {
  173. return IComponentImpl<CSnapinComponent>::Notify(lpDataObject, event, arg, param);
  174. }
  175. //
  176. // In this routine we handle only
  177. // lpDataObject ==NULL, or we have a MMCN_SHOW event.
  178. //
  179. if(MMCN_SHOW == event)
  180. {
  181. //
  182. // On Show event, we want to keep, or reset
  183. // the node currenlty selected
  184. //
  185. ATLASSERT(lpDataObject != NULL);
  186. //
  187. // Retreive the pItem data type
  188. //
  189. CSnapInItem* pItem;
  190. DATA_OBJECT_TYPES type;
  191. hr = m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
  192. if(FAILED(hr))
  193. return(hr);
  194. if( arg )
  195. {
  196. // We are being selected.
  197. m_pSelectedNode = pItem;
  198. }
  199. else
  200. {
  201. // We are being deselected.
  202. // Check to make sure that our result view doesn't think
  203. // this node is the currently selected one.
  204. if( m_pSelectedNode == pItem)
  205. {
  206. // We don't want to be the selected node anymore.
  207. m_pSelectedNode = NULL;
  208. }
  209. }
  210. //
  211. // Call SnapinItem notification routine
  212. //
  213. return IComponentImpl<CSnapinComponent>::Notify(lpDataObject, event, arg, param);
  214. }
  215. //
  216. // lpDataObject == NULL
  217. //
  218. // Currently handling only View Change (UpdateAllViews)
  219. // And PropertyChange
  220. switch (event)
  221. {
  222. case MMCN_VIEW_CHANGE:
  223. if( ( arg == NULL || (CSnapInItem *) arg == m_pSelectedNode ) && m_pSelectedNode != NULL )
  224. {
  225. if ( FXS_HINT_DELETE_ALL_RSLT_ITEMS == param)
  226. {
  227. ATLASSERT(m_spConsole);
  228. CComQIPtr<IResultData, &IID_IResultData> pResultData(m_spConsole);
  229. ATLASSERT(pResultData);
  230. hr = pResultData->DeleteAllRsltItems();
  231. if( FAILED(hr) )
  232. {
  233. DebugPrintEx(
  234. DEBUG_ERR,
  235. TEXT("Fail to DeleteAllRsltItems().(hRc: %08X)"),
  236. hr);
  237. return( hr );
  238. }
  239. break;
  240. }
  241. // We basically tell MMC to simulate reselecting the
  242. // currently selected node, which causes it to redraw.
  243. // This will cause MMC to send the MMCN_SHOW notification
  244. // to the selected node.
  245. // This function requires an HSCOPEITEM. This is the ID member
  246. // of the HSCOPEDATAITEM associated with this node.
  247. SCOPEDATAITEM *pScopeDataItem;
  248. m_pSelectedNode->GetScopeData(&pScopeDataItem);
  249. hr = m_spConsole->SelectScopeItem(pScopeDataItem->ID);
  250. }
  251. break;
  252. case MMCN_PROPERTY_CHANGE:
  253. CFaxPropertyChangeNotification * pNotification;
  254. CSnapInItem * pItem;
  255. pNotification = ( CFaxPropertyChangeNotification * ) param;
  256. ATLASSERT(pNotification);
  257. pItem = pNotification->pItem;
  258. ATLASSERT(pItem);
  259. hr = pItem->Notify(event, arg, param, NULL, (IComponent*) this, CCT_RESULT);
  260. break;
  261. // CSnapInItem * pNode;
  262. // pNode = (CSnapInItem *) param;
  263. // hr = pNode->Notify(event, arg, param, NULL, (IComponent*) this, CCT_RESULT);
  264. // break;
  265. // case MMCN_PROPERTY_CHANGE:
  266. // {
  267. //
  268. // CComQIPtr<IResultData, &IID_IResultData> spResultData(m_spConsole);
  269. // hr = spResultData->UpdateItem((HRESULTITEM)(param));
  270. // }
  271. // break;
  272. case MMCN_SNAPINHELP:
  273. ATLASSERT(0); // Shouldn't been called since we support ISnapinHelp
  274. //
  275. // Call imported method from NeMmcUtl.dll
  276. //
  277. OnSnapinHelp(arg, param);
  278. break;
  279. case MMCN_COLUMN_CLICK:
  280. //
  281. // MMC 1.2 handles this
  282. //
  283. break;
  284. default:
  285. //
  286. // Catch un handeled events
  287. //
  288. ATLASSERT(0);
  289. } // endswitch (event)
  290. return hr;
  291. }
  292. /////////////////////////////////////////////////////////////////////////////
  293. /*++
  294. CSnapinComponent::CompareObjects
  295. Needed so that IPropertySheetProvider::FindPropertySheet will work.
  296. FindPropertySheet is used to bring a pre-existing property sheet to the foreground
  297. so that we don't open multiple copies of Properties on the same node.
  298. It requires CompareObjects to be implemented on both IComponent and IComponentData.
  299. --*/
  300. //////////////////////////////////////////////////////////////////////////////
  301. STDMETHODIMP
  302. CSnapinComponent::CompareObjects(LPDATAOBJECT lpDataObjectA,
  303. LPDATAOBJECT lpDataObjectB)
  304. {
  305. ATLTRACE(_T("# CSnapinComponent::CompareObjects\n"));
  306. HRESULT hr;
  307. CSnapInItem *pDataA, *pDataB;
  308. DATA_OBJECT_TYPES typeA, typeB;
  309. hr = GetDataClass(lpDataObjectA, &pDataA, &typeA);
  310. if ( FAILED( hr ) )
  311. {
  312. return hr;
  313. }
  314. hr = GetDataClass(lpDataObjectB, &pDataB, &typeB);
  315. if ( FAILED( hr ) )
  316. {
  317. return hr;
  318. }
  319. if( pDataA == pDataB )
  320. {
  321. // They are the same object.
  322. return S_OK;
  323. }
  324. else
  325. {
  326. // They are different.
  327. return S_FALSE;
  328. }
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. /*++
  332. CSnapinComponent::OnColumnClick
  333. HRESULT OnColumnClick(
  334. LPARAM arg
  335. , LPARAM param
  336. )
  337. In our implementation, this method gets called when the MMCN_COLUMN_CLICK
  338. Notify message is sent for our IComponent object.
  339. MMC sends this message when the user clicks on a result-list view column header.
  340. Parameters
  341. arg
  342. Column number.
  343. param
  344. Sort option flags. By default, the sort is in ascending order. To specify descending order, use the RSI_DESCENDING (0x0001) flag.
  345. Return Values
  346. Not used.
  347. --*/
  348. //////////////////////////////////////////////////////////////////////////////
  349. HRESULT
  350. CSnapinComponent::OnColumnClick(LPARAM arg, LPARAM param)
  351. {
  352. ATLTRACE(_T("# CSnapinComponent::OnColumnClick -- Not implemented\n"));
  353. UNREFERENCED_PARAMETER (arg);
  354. UNREFERENCED_PARAMETER (param);
  355. // Check for preconditions:
  356. // None.
  357. return E_NOTIMPL;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. /*++
  361. CSnapinComponent::OnCutOrMove
  362. HRESULT OnCutOrMove(
  363. LPARAM arg
  364. , LPARAM param
  365. )
  366. In our implementation, this method gets called when the MMCN_COLUMN_CLICK
  367. Notify message is sent for our IComponent object.
  368. MMC sends this message when the user clicks on a result-list view column header.
  369. Parameters
  370. arg
  371. Column number.
  372. param
  373. Sort option flags. By default, the sort is in ascending order. To specify descending order, use the RSI_DESCENDING (0x0001) flag.
  374. Return Values
  375. Not used.
  376. --*/
  377. //////////////////////////////////////////////////////////////////////////////
  378. HRESULT
  379. CSnapinComponent::OnCutOrMove(LPARAM arg, LPARAM param)
  380. {
  381. ATLTRACE(_T("# CSnapinComponent::OnCutOrMove\n"));
  382. // ISSUE: This may need to be changed once the MMC team finalizes their
  383. // cut and paste protocol -- they seem to be in flux for 1.1 as of 02/16/98.
  384. // Currently, we will assume that the arg value passed to us is the source item
  385. // in the cut-and-paste or drag-n-drop operation. That is, it is the object
  386. // to be deleted.
  387. // We supplied this pointer in our response to the MMCN_PASTE notification,
  388. // when we set param to point to the source IDataObject.
  389. HRESULT hr;
  390. if( arg != NULL )
  391. {
  392. CSnapInItem* pData;
  393. DATA_OBJECT_TYPES type;
  394. hr = CSnapInItem::GetDataClass( (IDataObject *) arg, &pData, &type);
  395. ATLASSERT(SUCCEEDED(hr));
  396. if (SUCCEEDED(hr))
  397. {
  398. // We need a richer Notify method which has information about the IComponent and IComponentData objects
  399. //hr = pData->Notify(event, arg, param, TRUE, m_spConsole, NULL, NULL);
  400. hr = pData->Notify( MMCN_CUTORMOVE, arg, param, NULL, this, type );
  401. }
  402. }
  403. // return E_NOTIMPL;
  404. return S_OK;
  405. }
  406. /////////////////////////////////////////////////////////////////////////////
  407. /*++
  408. CSnapinComponent::OnSnapinHelp
  409. HRESULT OnSnapinHelp(
  410. LPARAM arg
  411. , LPARAM param
  412. )
  413. In our implementation, this method gets called when the MMCN_SNAPINHELP
  414. Notify message is sent for our IComponent object.
  415. MMC sends this message when the user requests help about the snap-in.
  416. Parameters
  417. arg
  418. 0
  419. param
  420. 0
  421. Return Values
  422. Not used.
  423. --*/
  424. //////////////////////////////////////////////////////////////////////////////
  425. HRESULT
  426. CSnapinComponent::OnSnapinHelp(LPARAM arg, LPARAM param)
  427. {
  428. ATLTRACE(_T("# CSnapinComponent::OnSnapinHelp\n"));
  429. UNREFERENCED_PARAMETER (arg);
  430. UNREFERENCED_PARAMETER (param);
  431. // Check for preconditions:
  432. _ASSERTE( m_spConsole != NULL );
  433. ::OnSnapinHelp(m_spConsole);
  434. #if 0
  435. HRESULT hr;
  436. //TCHAR szFileName[MAX_PATH];
  437. HWND hWnd;
  438. // Get HWND from MMC.
  439. hr = m_spConsole->GetMainWindow( &hWnd );
  440. _ASSERTE( SUCCEEDED( hr ) && NULL != hWnd );
  441. #ifdef UNICODE_HHCTRL
  442. // ISSUE: We seemed to have a problem with passing WCHAR's to the hhctrl.ocx
  443. // installed on this machine -- it appears to be non-unicode.
  444. //lstrcpy( szFileName, HTMLHELP_NAME );
  445. //HtmlHelp( hWnd, szFileName, HH_DISPLAY_TOPIC, (DWORD) _T("iasmmc_main_help.htm") );
  446. #else
  447. //strcpy( (CHAR *) szFileName, HTMLHELP_NAME );
  448. //HtmlHelp( hWnd, (TCHAR *) szFileName, HH_DISPLAY_TOPIC, (DWORD) "iasmmc_main_help.htm" );
  449. #endif
  450. #endif // 0
  451. return S_OK;
  452. }
  453. //////////////////////////////////////////////////////////////////////////////
  454. /*++
  455. CSnapinComponent::OnViewChange
  456. HRESULT OnViewChange(
  457. LPARAM arg
  458. , LPARAM param
  459. )
  460. This is where we respond to an MMCN_VIEW_CHANGE notification.
  461. In our implementation, this is a signal to check the currently selected node in
  462. the result pane for this component, and refresh the view if the node happens to
  463. be the same as the pointer to a CSnapInItem passed in through arg.
  464. We do this because you only want to refresh the view of the currently selected
  465. node, and you only want to do that if its children have changed.
  466. If the arg passed in is NULL, we just reselect the currently selected node.
  467. --*/
  468. //////////////////////////////////////////////////////////////////////////////
  469. HRESULT
  470. CSnapinComponent::OnViewChange(LPARAM arg, LPARAM param)
  471. {
  472. ATLTRACE(_T("# CNodeWithResultChildrenList::OnViewChange\n"));
  473. // Check for preconditions:
  474. UNREFERENCED_PARAMETER (param);
  475. _ASSERTE( m_spConsole != NULL );
  476. HRESULT hr = S_FALSE;
  477. // What localsec snapin checks for:
  478. if( ( arg == NULL || (CSnapInItem *) arg == m_pSelectedNode ) && m_pSelectedNode != NULL )
  479. {
  480. // We basically tell MMC to simulate reselecting the
  481. // currently selected node, which causes it to redraw.
  482. // This will cause MMC to send the MMCN_SHOW notification
  483. // to the selected node.
  484. // This function requires an HSCOPEITEM. This is the ID member
  485. // of the HSCOPEDATAITEM associated with this node.
  486. SCOPEDATAITEM *pScopeDataItem;
  487. m_pSelectedNode->GetScopeData( &pScopeDataItem );
  488. hr = m_spConsole->SelectScopeItem( pScopeDataItem->ID );
  489. }
  490. return hr;
  491. }
  492. //////////////////////////////////////////////////////////////////////////////
  493. /*++
  494. CSnapinComponent::OnPropertyChange
  495. HRESULT OnPropertyChange(
  496. LPARAM arg
  497. , LPARAM param
  498. )
  499. This is where we respond to an MMCN_PROPERTY_CHANGE notification.
  500. This notification is sent when we call MMCPropertyChangeNotify.
  501. We call this in our property pages when changes are made to the data
  502. they contain and we may need to update of view of the data.
  503. --*/
  504. //////////////////////////////////////////////////////////////////////////////
  505. HRESULT
  506. CSnapinComponent::OnPropertyChange(LPARAM arg, LPARAM param)
  507. {
  508. ATLTRACE(_T("# CSnapinComponent::OnPropertyChange\n"));
  509. // Check for preconditions:
  510. _ASSERTE( m_spConsole != NULL );
  511. UNREFERENCED_PARAMETER (arg);
  512. HRESULT hr = S_FALSE;
  513. if( param == NULL )
  514. {
  515. // We want to make sure all views get updated.
  516. hr = m_spConsole->UpdateAllViews( NULL, (LPARAM) m_pSelectedNode, NULL);
  517. }
  518. else
  519. {
  520. // We passed a pointer to a CSnapInItem in the param argument.
  521. // We call notify on that node, passing it our own custom event type
  522. // so that it knows that it must refresh its data.
  523. CSnapInItem * pSnapInItem = (CSnapInItem *) param;
  524. // Call notify on this node with the MMCN_PROPERTY_CHANGE notification.
  525. // We had to use this trick because of the fact that we are using template
  526. // classes and so we have no common object among all our nodes
  527. // other than CSnapInItem. But we can't change CSnapInItem
  528. // so instead we use the notify method it already has with a new
  529. // notification.
  530. // Note: We are trying to deal gracefully here with the fact that the
  531. // MMCN_PROPERTY_CHANGE notification doesn't pass us an lpDataObject
  532. // so we have to have our own protocol for picking out which node
  533. // needs to update itself.
  534. hr = pSnapInItem->Notify( MMCN_PROPERTY_CHANGE
  535. , NULL
  536. , NULL
  537. , NULL
  538. , NULL
  539. , (DATA_OBJECT_TYPES) 0
  540. );
  541. // We want to make sure all views with this node select also get updated.
  542. hr = m_spConsole->UpdateAllViews( NULL, (LPARAM) pSnapInItem, NULL);
  543. }
  544. return hr;
  545. }
  546. //////////////////////////////////////////////////////////////////////////////
  547. /*++
  548. CSnapinComponent::GetTitle
  549. IExtendTaskPad interface member.
  550. This is the title that show up under the banner.
  551. ISSUE: Why does this not appear to be working?
  552. --*/
  553. //////////////////////////////////////////////////////////////////////////////
  554. STDMETHODIMP
  555. CSnapinComponent::GetTitle(LPOLESTR pszGroup, LPOLESTR *pszTitle)
  556. {
  557. ATLTRACE(_T("# CSnapinComponent::GetTitle\n"));
  558. UNREFERENCED_PARAMETER (pszGroup);
  559. // Check for preconditions:
  560. _ASSERTE( pszTitle != NULL );
  561. OLECHAR szTitle[256];
  562. int nLoadStringResult = LoadString(_Module.GetResourceInstance(), IDS_TASKPAD_TITLE, szTitle, 256);
  563. _ASSERT( nLoadStringResult > 0 );
  564. *pszTitle= (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*(lstrlen(szTitle)+1) );
  565. if( ! *pszTitle )
  566. {
  567. return E_OUTOFMEMORY;
  568. }
  569. lstrcpy( *pszTitle, szTitle );
  570. return S_OK;
  571. }
  572. //////////////////////////////////////////////////////////////////////////////
  573. /*++
  574. CSnapinComponent::GetBanner
  575. IExtendTaskPad interface member.
  576. We provide the color bar banner that appears at the top of the taskpad.
  577. It is a resource in our snapin DLL.
  578. --*/
  579. //////////////////////////////////////////////////////////////////////////////
  580. STDMETHODIMP
  581. CSnapinComponent::GetBanner (LPOLESTR pszGroup, LPOLESTR *pszBitmapResource)
  582. {
  583. ATLTRACE(_T("# CSnapinComponent::GetBanner\n"));
  584. UNREFERENCED_PARAMETER (pszGroup);
  585. // We are constructing a string pointing to the bitmap resource
  586. // of the form: "res://D:\MyPath\MySnapin.dll/img\ntbanner.gif"
  587. OLECHAR szBuffer[MAX_PATH*2]; // A little extra.
  588. // Get "res://"-type string for bitmap.
  589. lstrcpy (szBuffer, L"res://");
  590. OLECHAR * temp = szBuffer + lstrlen(szBuffer);
  591. // Get our executable's filename.
  592. HINSTANCE hInstance = _Module.GetResourceInstance();
  593. ::GetModuleFileName (hInstance, temp, MAX_PATH);
  594. // Add the name of the image within our resources.
  595. lstrcat (szBuffer, L"/img\\IASTaskpadBanner.gif");
  596. // Alloc and copy bitmap resource string.
  597. *pszBitmapResource = (LPOLESTR) CoTaskMemAlloc(sizeof(OLECHAR)*(lstrlen(szBuffer)+1) );
  598. if (!*pszBitmapResource)
  599. {
  600. return E_OUTOFMEMORY;
  601. }
  602. lstrcpy( *pszBitmapResource, szBuffer);
  603. return S_OK;
  604. }
  605. /*
  606. - CSnapin::GetHelpTopic
  607. -
  608. * Purpose:
  609. * See MMC help on ISnapinHelp::GetHelpTopic
  610. *
  611. * Arguments:
  612. * [out] lpCompiledHelpFile - Pointer to the address of the NULL-terminated
  613. * UNICODE string that contains the full path of
  614. * the compiled help file (.chm) for the snap-in.
  615. *
  616. * Return:
  617. * OLE error code
  618. */
  619. HRESULT STDMETHODCALLTYPE
  620. CSnapin::GetHelpTopic(LPOLESTR* lpCompiledHelpFile)
  621. {
  622. WCHAR *pszFilePath;
  623. WCHAR *pszTopic;
  624. HRESULT hRc = S_OK;
  625. ULONG ulLen;
  626. DEBUG_FUNCTION_NAME( _T("CSnapin::GetHelpTopic"));
  627. ATLASSERT(lpCompiledHelpFile != NULL);
  628. //
  629. // Get the CHM file name and the current topic
  630. //
  631. pszFilePath = GetHelpFile();
  632. pszTopic = NULL; //pszTopic = GetHelpTopic(); current implementation.
  633. if (pszFilePath == NULL)
  634. {
  635. hRc = E_OUTOFMEMORY;
  636. DebugPrintEx(DEBUG_ERR,_T("Failed to GetHelpFile(). (hRc: %08X)"), hRc);
  637. goto Cleanup;
  638. }
  639. //
  640. // Allocate mem for it
  641. ulLen = lstrlen(pszFilePath) + 1;
  642. if (pszTopic && *pszTopic)
  643. {
  644. ulLen += 2 /* for "::" */ + lstrlen(pszTopic);
  645. }
  646. ulLen *= sizeof(WCHAR);
  647. *lpCompiledHelpFile = reinterpret_cast<LPOLESTR>(::CoTaskMemAlloc(ulLen));
  648. if (*lpCompiledHelpFile == NULL)
  649. {
  650. hRc = E_OUTOFMEMORY;
  651. DebugPrintEx(DEBUG_ERR,_T("Failed to do CoTaskMemAlloc. (hRc: %08X)"), hRc);
  652. goto Cleanup;
  653. }
  654. wcscpy(*lpCompiledHelpFile, pszFilePath);
  655. //
  656. // Copy the help file::topic
  657. //
  658. if (pszTopic && *pszTopic)
  659. {
  660. wcscat(*lpCompiledHelpFile, L"::");
  661. wcscat(*lpCompiledHelpFile, pszTopic);
  662. }
  663. Cleanup:
  664. return hRc;
  665. }
  666. WCHAR*
  667. CSnapin::GetHelpFile()
  668. {
  669. DEBUG_FUNCTION_NAME( _T("CSnapin::GetHelpFile"));
  670. return ::GetHelpFile();
  671. }
  672. ///////////////////////////////////////////////////////////////
  673. //
  674. // IPesistStream
  675. //
  676. /////////////////////////////////////////////////////////////////////
  677. //const WCHAR szOverrideCommandLineEquals[] = _T("/Computer="); // Not subject to localization
  678. //const WCHAR szOverrideCommandLineColon[] = _T("/Computer:"); // Not subject to localization
  679. const WCHAR g_szFaxOverrideCommandLineEquals[] = _T("/FAX="); // Not subject to localization
  680. const WCHAR g_szLocalMachine[] = _T("LocalMachine"); // Not subject to localization
  681. //we keep the version of persistence information of CSnapin
  682. //when the persistence format is changed we need to increase this integer number
  683. //we will read persistnce information only if the persistence version in the stream
  684. //matches that of the PERISISTENCE_VERSION.
  685. #define PERISISTENCE_VERSION 100002
  686. //
  687. // The persist stream format is:
  688. //
  689. // Version (UINT)
  690. // AllowOverride (BOOL)
  691. // Server Name length (UINT)
  692. // Server Name string ( <= WCHAR * DNS_MAX_NAME_BUFFER_LENGTH )
  693. //
  694. /*
  695. - CSnapin::Load
  696. -
  697. * Purpose:
  698. * Initializes an object from the stream where it was previously saved.
  699. *
  700. * Arguments:
  701. * [in] pStm - Pointer to the stream from which the object
  702. * should be loaded.
  703. * Return:
  704. * S_OK - The object was successfully loaded.
  705. * E_OUTOFMEMORY - The object was not loaded due to a lack of memory.
  706. * E_FAIL - The object was not loaded due to some reason other
  707. * than a lack of memory.
  708. *
  709. */
  710. STDMETHODIMP CSnapin::Load(IStream *pStm)
  711. {
  712. DEBUG_FUNCTION_NAME( _T("CSnapin::Load"));
  713. HRESULT hRc = S_OK;
  714. BOOL fServerNameFoundInCommandLine = FALSE;
  715. CComBSTR bstrCommandLineServerName = L"";
  716. WCHAR wszPersistStreamServerName[DNS_MAX_NAME_BUFFER_LENGTH+1] = {0};
  717. UINT uiVersion = 0;
  718. ULONG nBytesRead = 0;
  719. //
  720. // Pre-conditions
  721. //
  722. ATLASSERT( NULL != pStm );
  723. //
  724. // A. Read the Stream
  725. // ==================
  726. //
  727. //
  728. // Read the Version
  729. //
  730. hRc = pStm->Read(&uiVersion, sizeof(uiVersion), NULL);
  731. if( FAILED( hRc ) )
  732. {
  733. DebugPrintEx( DEBUG_ERR,
  734. _T("pStm->Read(version). (hRc: %08X)"), hRc);
  735. return E_FAIL;
  736. }
  737. if (uiVersion == PERISISTENCE_VERSION)
  738. {
  739. //
  740. // Read Allow-to-override stream machine-name flag
  741. // from command line source
  742. //
  743. hRc = pStm->Read( &m_fAllowOverrideServerName, sizeof(m_fAllowOverrideServerName), NULL );
  744. if( FAILED( hRc ) )
  745. {
  746. DebugPrintEx( DEBUG_ERR,
  747. _T("pStm->Read(fAllowOverrideServerName). (hRc: %08X)"), hRc);
  748. return E_FAIL;
  749. }
  750. //
  751. // Read the Server Name from stream
  752. //
  753. hRc = pStm->Read (&nBytesRead , sizeof(ULONG), NULL);
  754. if( FAILED( hRc ) )
  755. {
  756. DebugPrintEx( DEBUG_ERR,
  757. _T("Fail to Read server name length from stream. (hRc: %08X)"), hRc);
  758. return E_FAIL;
  759. }
  760. ATLASSERT (nBytesRead <= DNS_MAX_NAME_BUFFER_LENGTH * sizeof (WCHAR));
  761. if (nBytesRead <= DNS_MAX_NAME_BUFFER_LENGTH * sizeof (WCHAR))
  762. {
  763. hRc = pStm->Read ((PVOID) wszPersistStreamServerName, nBytesRead, NULL);
  764. if( FAILED( hRc ) )
  765. {
  766. DebugPrintEx( DEBUG_ERR,
  767. _T("Fail to Read server name from stream. (hRc: %08X)"), hRc);
  768. return E_FAIL;
  769. }
  770. }
  771. }
  772. else // version!=PERISISTENCE_VERSION
  773. {
  774. //
  775. // Persistance data will not be read due to inconsitency.
  776. //
  777. DebugPrintEx( DEBUG_ERR,
  778. _T("The current *.msc file version (%ld) is differnt from the\n pesistance version the dll expecting (%ld)."), uiVersion, PERISISTENCE_VERSION);
  779. //
  780. // Next we'll try to Read ServerName from Command line
  781. //
  782. }
  783. //
  784. // B. Try to read from command line
  785. // ================================
  786. //
  787. // fServerNameFoundInCommandLine initial state == FALSE
  788. if (m_fAllowOverrideServerName)
  789. {
  790. int argCount = 0;
  791. PWSTR* argV = NULL;
  792. const int cchFaxOverrideCommandLine = ( sizeof(g_szFaxOverrideCommandLineEquals) / sizeof(g_szFaxOverrideCommandLineEquals[0]) ) - 1;
  793. argV = CommandLineToArgvW(GetCommandLine() , &argCount);
  794. if (argV == NULL)
  795. {
  796. DWORD ec;
  797. ec = GetLastError();
  798. DebugPrintEx(
  799. DEBUG_ERR,
  800. _T("Fail to parse Command Line To Argv. (ec: %ld)"),
  801. ec);
  802. return E_FAIL;
  803. }
  804. //argV[0] is not an argument
  805. for (int i = 1; i < argCount; i++)
  806. {
  807. WCHAR * psz = argV[i];
  808. if ( 0 == wcsnicmp( psz , g_szFaxOverrideCommandLineEquals , cchFaxOverrideCommandLine ) )
  809. {
  810. fServerNameFoundInCommandLine = TRUE;
  811. psz = _tcsninc(psz, cchFaxOverrideCommandLine); //psz = psz + cchFaxOverrideCommandLine;
  812. if ( 0 != wcscmp( psz , g_szLocalMachine ) )
  813. {
  814. //
  815. // Server Name initial '\\' trancation (if they are there)
  816. //
  817. if ( ( _tcslen(psz) > 2 ) && ( 0 == wcsncmp( psz , _T("\\\\") , 2 )) )
  818. {
  819. psz = _tcsninc(psz, 2);
  820. }
  821. if ( _tcslen(psz) > 0)
  822. {
  823. //
  824. // Server Name validity checks
  825. //
  826. CComBSTR bstrServerNameValidation = psz;
  827. UINT uTmp = 0;
  828. if (!IsValidServerNameString(bstrServerNameValidation, &uTmp, TRUE /*DNS Name Length*/))
  829. {
  830. // Err msg by called func.
  831. // As in comupter management we do not pop-up here
  832. // but we fix the found flag to be FALSE
  833. fServerNameFoundInCommandLine = FALSE;
  834. break;
  835. }
  836. bstrCommandLineServerName = psz;
  837. //
  838. // we will also check if the explictly inserted Server Name
  839. // is the local Server Name. This check will be done in one place
  840. // the selected readed server name (Command line or Stream)
  841. //
  842. }
  843. else // the case of argV[2] == "/FAX=" only => LocalMachine
  844. {
  845. bstrCommandLineServerName = L""; //just to be sure - the default
  846. }
  847. }
  848. else // "/FAX=LocalMachine"
  849. {
  850. bstrCommandLineServerName = L""; //just to be sure - the default
  851. }
  852. break;
  853. }
  854. } //if /FAX= was not found bstrCommandLineServerName stays L""
  855. //
  856. // free resources
  857. //
  858. GlobalFree(argV);
  859. }
  860. //
  861. // C. Derived Server name from the results
  862. // =======================================
  863. //
  864. //
  865. // When there is no command line explicitly request for server name
  866. //
  867. // or
  868. //
  869. // when we are not allowed to take the command data and to use it
  870. // to override the straem server name
  871. //
  872. // just then the server is taken from the stream
  873. //
  874. ATLASSERT (0 == m_bstrServerName.Length());
  875. if (
  876. (!fServerNameFoundInCommandLine)
  877. ||
  878. (!m_fAllowOverrideServerName)
  879. )
  880. {
  881. //
  882. // We should take the stream server name
  883. //
  884. if (NULL != wszPersistStreamServerName)
  885. {
  886. if ( 0 != wcscmp( wszPersistStreamServerName , g_szLocalMachine ) )
  887. {
  888. m_bstrServerName = wszPersistStreamServerName;
  889. }
  890. else //LocalMachine
  891. {
  892. m_bstrServerName = L""; //Just to be sure
  893. }
  894. }
  895. else
  896. {
  897. // not a regular case:
  898. // for example can occur while version inconsitancy
  899. // and no command line /FAX= server name instruction
  900. m_bstrServerName = L""; //Just to be sure this is actually the default
  901. }
  902. }
  903. else
  904. {
  905. //
  906. // We should take the command line server name
  907. //
  908. m_bstrServerName = bstrCommandLineServerName;
  909. }
  910. //
  911. // Checks if the explictly inserted Server Name
  912. // is the local Server Name
  913. //
  914. if (m_bstrServerName.Length() > 0 )
  915. {
  916. if ( IsLocalServerName(m_bstrServerName.m_str) )
  917. {
  918. DebugPrintEx( DEBUG_MSG,
  919. _T("The computer name %ws is the same as the name of the current managed server."),m_bstrServerName.m_str);
  920. m_bstrServerName = L"";
  921. }
  922. }
  923. //
  924. // We do not check here if the server is on the net
  925. // and if fax is installed and running there
  926. //
  927. //
  928. // D. Update FaxServer and FaxServerNode DisplayName with the name
  929. // retrieved during the load process
  930. // =======================================
  931. //
  932. ATLASSERT( m_pNode);
  933. CFaxServerNode * pFaxServerNode = (CFaxServerNode *)m_pNode;
  934. ATLASSERT( pFaxServerNode);
  935. hRc = pFaxServerNode->UpdateServerName(m_bstrServerName);
  936. if (S_OK != hRc)
  937. {
  938. DebugPrintEx(DEBUG_MSG,_T("Out of memory - fail to UpdateServerName."));
  939. return hRc; //E_OUTOFMEMORY;
  940. }
  941. hRc = pFaxServerNode->InitDetailedDisplayName();
  942. if (S_OK != hRc)
  943. {
  944. DebugPrintEx(DEBUG_MSG,_T("Out of memory - fail to InitDetailedDisplayName."));
  945. return hRc; //E_OUTOFMEMORY;
  946. }
  947. pFaxServerNode->SetIsLaunchedFromSavedMscFile();
  948. ATLASSERT (S_OK == hRc);
  949. return hRc;
  950. }
  951. /////////////////////////////////////////////////////////////////////
  952. STDMETHODIMP CSnapin::Save(IStream *pStm, BOOL /*fClearDirty*/)
  953. {
  954. DEBUG_FUNCTION_NAME( _T("CSnapin::Save"));
  955. HRESULT hRc = S_OK;
  956. UINT uiVersion = PERISISTENCE_VERSION;
  957. ATLASSERT( NULL != pStm );
  958. //
  959. // Write the version
  960. //
  961. hRc = pStm->Write((void *)&uiVersion, sizeof(uiVersion), 0);
  962. if( FAILED( hRc ) )
  963. {
  964. DebugPrintEx( DEBUG_ERR,
  965. _T("pStm->Write(&uiVersion). (hRc: %08X)"), hRc);
  966. return STG_E_CANTSAVE;
  967. }
  968. //
  969. // Write Allow-to-override machine-name flag to the stream
  970. //
  971. hRc = pStm->Write((void *)&m_fAllowOverrideServerName, sizeof(m_fAllowOverrideServerName), 0);
  972. if( FAILED( hRc ) )
  973. {
  974. DebugPrintEx( DEBUG_ERR,
  975. _T("pStm->Write(&uiVersion. (hRc: %08X)"), hRc);
  976. return STG_E_CANTSAVE;
  977. }
  978. //
  979. // Write the Server Name length
  980. //
  981. LPCWSTR wcszMachineName;
  982. if ( 0 == m_bstrServerName.Length() ) // m_bstrServerName == L"" -> LocalMachine
  983. {
  984. wcszMachineName = g_szLocalMachine; // m_bstrServerName = L"LocalMachine"
  985. }
  986. else
  987. {
  988. wcszMachineName = m_bstrServerName;
  989. }
  990. DWORD dwLen = (::wcslen (wcszMachineName) + 1) * sizeof (WCHAR);
  991. hRc = pStm->Write ((void *)&dwLen, sizeof(DWORD), NULL);
  992. if ( FAILED(hRc) )
  993. {
  994. DebugPrintEx( DEBUG_ERR,
  995. _T("Fail to Write server name length to stream. (hRc: %08X)"), hRc);
  996. return STG_E_CANTSAVE;
  997. }
  998. //
  999. // Write the Server Name
  1000. //
  1001. hRc = pStm->Write ((void *)wcszMachineName, dwLen, NULL);
  1002. if ( FAILED (hRc) )
  1003. {
  1004. DebugPrintEx( DEBUG_ERR,
  1005. _T("Fail to Write server name to stream. (hRc: %08X)"), hRc);
  1006. return STG_E_CANTSAVE;
  1007. }
  1008. ATLASSERT( S_OK == hRc);
  1009. return hRc;
  1010. }
  1011. STDMETHODIMP CSnapin::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1012. {
  1013. ATLASSERT(pcbSize);
  1014. ULISet32(*pcbSize, (DNS_MAX_NAME_BUFFER_LENGTH * sizeof(WCHAR)) + (2 * sizeof(UINT)) + 1);
  1015. return S_OK;
  1016. }
  1017. /*
  1018. - CSnapin::GetSizeMax
  1019. -
  1020. * Purpose:
  1021. * Checks the object for changes since it was last saved.
  1022. *
  1023. * Arguments:
  1024. *
  1025. * Return:
  1026. * OLE error code
  1027. */
  1028. STDMETHODIMP CSnapin::IsDirty()
  1029. {
  1030. // Always save / Always dirty.
  1031. return S_OK;
  1032. }