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.

4028 lines
115 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: amcdoc.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // AMCDoc.cpp : implementation of the CAMCDoc class
  11. //
  12. #include "stdafx.h"
  13. #include "AMC.h"
  14. #include "AMCDoc.h"
  15. #include "AMCView.h"
  16. #include "treectrl.h"
  17. #include "mainfrm.h"
  18. #include "cclvctl.h"
  19. #include "props.h"
  20. #include <algorithm>
  21. #include <vector>
  22. #include <list>
  23. #include "amcmsgid.h"
  24. #include "amcpriv.h"
  25. #include "mmcutil.h"
  26. #include "ndmgrp.h"
  27. #include "strtable.h"
  28. #include "stgio.h"
  29. #include "comdbg.h"
  30. #include "favorite.h"
  31. #include "mscparser.h"
  32. #include "scriptevents.h"
  33. // helper
  34. tstring GetCurrentFileVersionAsString();
  35. //############################################################################
  36. //############################################################################
  37. //
  38. // Implementation of class CMMCDocument
  39. //
  40. //############################################################################
  41. //############################################################################
  42. /*+-------------------------------------------------------------------------*
  43. * class CMMCDocument
  44. *
  45. *
  46. * PURPOSE: The COM 0bject that exposes the Document interface.
  47. *
  48. *+-------------------------------------------------------------------------*/
  49. class CMMCDocument :
  50. public CMMCIDispatchImpl<Document>,
  51. public CTiedComObject<CAMCDoc>
  52. {
  53. public:
  54. typedef CAMCDoc CMyTiedObject;
  55. public:
  56. BEGIN_MMC_COM_MAP(CMMCDocument)
  57. END_MMC_COM_MAP()
  58. //Document interface
  59. public:
  60. MMC_METHOD0(Save);
  61. MMC_METHOD1(SaveAs, BSTR /*bstrFilename*/);
  62. MMC_METHOD1(Close, BOOL /*bSaveChanges*/);
  63. MMC_METHOD1(CreateProperties, PPPROPERTIES /*ppProperties*/);
  64. // properties
  65. MMC_METHOD1(get_Views, PPVIEWS /*ppViews*/);
  66. MMC_METHOD1(get_SnapIns, PPSNAPINS /*ppSnapIns*/);
  67. MMC_METHOD1(get_ActiveView, PPVIEW /*ppView*/);
  68. MMC_METHOD1(get_Name, PBSTR /*pbstrName*/);
  69. MMC_METHOD1(put_Name, BSTR /*bstrName*/);
  70. MMC_METHOD1(get_Location, PBSTR /*pbstrLocation*/);
  71. MMC_METHOD1(get_IsSaved, PBOOL /*pBIsSaved*/);
  72. MMC_METHOD1(get_Mode, PDOCUMENTMODE /*pMode*/);
  73. MMC_METHOD1(put_Mode, DocumentMode /*mode*/);
  74. MMC_METHOD1(get_RootNode, PPNODE /*ppNode*/);
  75. MMC_METHOD1(get_ScopeNamespace, PPSCOPENAMESPACE /*ppScopeNamespace*/);
  76. MMC_METHOD1(get_Application, PPAPPLICATION /*ppApplication*/);
  77. };
  78. /*+-------------------------------------------------------------------------*
  79. * class CMMCViews
  80. *
  81. *
  82. * PURPOSE: The COM 0bject that exposes the Views interface.
  83. *
  84. *+-------------------------------------------------------------------------*/
  85. // the real CMMCViews is typedef'd below.
  86. class _CMMCViews :
  87. public CMMCIDispatchImpl<Views>, // the Views interface
  88. public CTiedComObject<CAMCDoc>
  89. {
  90. public:
  91. typedef CAMCDoc CMyTiedObject;
  92. BEGIN_MMC_COM_MAP(_CMMCViews)
  93. END_MMC_COM_MAP()
  94. // Views interface
  95. public:
  96. MMC_METHOD1(get_Count, PLONG /*pCount*/);
  97. MMC_METHOD2(Add, PNODE /*pNode*/, ViewOptions /*fViewOptions*/);
  98. MMC_METHOD2(Item, long /*Index*/, PPVIEW /*ppView*/);
  99. };
  100. // this typedefs the real CMMCViews class. Implements get__NewEnum using CMMCEnumerator and a CAMCViewPosition object
  101. typedef CMMCNewEnumImpl<_CMMCViews, CAMCViewPosition> CMMCViews;
  102. //############################################################################
  103. //############################################################################
  104. //
  105. // Implementation of class CStringTableString
  106. //
  107. //############################################################################
  108. //############################################################################
  109. /*+-------------------------------------------------------------------------*
  110. * CStringTableString::GetStringTable
  111. *
  112. *
  113. *--------------------------------------------------------------------------*/
  114. IStringTablePrivate* CStringTableString::GetStringTable () const
  115. {
  116. return (CAMCDoc::GetDocument()->GetStringTable());
  117. }
  118. void ShowAdminToolsOnMenu(LPCTSTR lpszFilename);
  119. enum ENodeType
  120. {
  121. entRoot,
  122. entSelected,
  123. };
  124. //############################################################################
  125. //############################################################################
  126. //
  127. // Implementation of class CAMCDoc
  128. //
  129. //############################################################################
  130. //############################################################################
  131. IMPLEMENT_DYNCREATE(CAMCDoc, CDocument)
  132. BEGIN_MESSAGE_MAP(CAMCDoc, CDocument)
  133. //{{AFX_MSG_MAP(CAMCDoc)
  134. ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
  135. ON_COMMAND(ID_CONSOLE_ADDREMOVESNAPIN, OnConsoleAddremovesnapin)
  136. ON_UPDATE_COMMAND_UI(ID_CONSOLE_ADDREMOVESNAPIN, OnUpdateConsoleAddremovesnapin)
  137. //}}AFX_MSG_MAP
  138. END_MESSAGE_MAP()
  139. /////////////////////////////////////////////////////////////////////////////
  140. // CAMCDoc construction/destruction
  141. CAMCDoc* CAMCDoc::m_pDoc = NULL;
  142. CAMCDoc::CAMCDoc()
  143. : m_MTNodeIDForNewView(ROOTNODEID),
  144. m_ViewIDForNewView(0),
  145. m_lNewWindowOptions(MMC_NW_OPTION_NONE),
  146. m_bReadOnlyDoc(false),
  147. m_fFrameModified (false),
  148. m_eSaveStatus (eStat_Succeeded),
  149. m_pFavorites(NULL),
  150. m_bCanCloseViews(true)
  151. {
  152. TRACE_CONSTRUCTOR(CAMCDoc);
  153. DECLARE_SC (sc, TEXT("CAMCDoc::CAMCDoc"));
  154. CComObject<CMasterStringTable> * pStringTable;
  155. sc = CComObject<CMasterStringTable>::CreateInstance (&pStringTable);
  156. if(sc.IsError() || !pStringTable)
  157. {
  158. sc = E_OUTOFMEMORY;
  159. sc.FatalError();
  160. }
  161. m_spStringTable = pStringTable; // does the addref.
  162. if(m_spStringTable == NULL)
  163. {
  164. delete pStringTable;
  165. sc = E_UNEXPECTED;
  166. sc.FatalError();
  167. }
  168. m_pstrCustomTitle = new CStringTableString(m_spStringTable);
  169. if(!m_pstrCustomTitle)
  170. {
  171. sc = E_OUTOFMEMORY;
  172. sc.FatalError();
  173. }
  174. if (m_pDoc)
  175. m_pDoc->OnCloseDocument();
  176. // Set default version update dialog to one appropriate for explicit saves
  177. SetExplicitSave(true);
  178. m_pDoc = this;
  179. m_ConsoleData.m_pConsoleDocument = this;
  180. }
  181. CAMCDoc::~CAMCDoc()
  182. {
  183. TRACE_DESTRUCTOR(CAMCDoc);
  184. if (m_pDoc == this)
  185. m_pDoc = NULL;
  186. if(m_pFavorites != NULL)
  187. {
  188. delete m_pFavorites;
  189. m_pFavorites = NULL;
  190. }
  191. delete m_pstrCustomTitle;
  192. // Tell the node manager to release it's reference on the scope tree
  193. IFramePrivatePtr spFrame;
  194. HRESULT hr = spFrame.CreateInstance(CLSID_NodeInit, NULL, MMC_CLSCTX_INPROC);
  195. if (hr == S_OK)
  196. {
  197. spFrame->SetScopeTree(NULL);
  198. ReleaseNodeManager();
  199. }
  200. /*
  201. * if we used a custom icon, revert to the default icon on the frame
  202. */
  203. if (m_CustomIcon)
  204. {
  205. CMainFrame* pMainFrame = AMCGetMainWnd();
  206. if (pMainFrame != NULL)
  207. {
  208. pMainFrame->SetIconEx (NULL, true);
  209. pMainFrame->SetIconEx (NULL, false);
  210. }
  211. }
  212. }
  213. void CAMCDoc::ReleaseNodeManager()
  214. {
  215. m_spScopeTreePersist = NULL;
  216. m_spScopeTree = NULL;
  217. m_spStorage = NULL;
  218. }
  219. //############################################################################
  220. //############################################################################
  221. //
  222. // CAMCDoc Object model methods.
  223. //
  224. //############################################################################
  225. //############################################################################
  226. // Document interface
  227. /*+-------------------------------------------------------------------------*
  228. * CAMCDoc::ScCreateProperties
  229. *
  230. * Creates an empty Properties collection.
  231. *
  232. * Returns:
  233. * E_UNEXPECTED scope tree wasn't available
  234. * other value returned by IScopeTree::CreateProperties
  235. *--------------------------------------------------------------------------*/
  236. SC CAMCDoc::ScCreateProperties (Properties** ppProperties)
  237. {
  238. DECLARE_SC (sc, _T("CAMCDoc::ScCreateProperties"));
  239. /*
  240. * insure we have a scope tree; ppProperties will be validated downstream
  241. */
  242. if (m_spScopeTree == NULL)
  243. return (sc = E_UNEXPECTED);
  244. /*
  245. * get the scope tree to create a Properties collection for us
  246. */
  247. sc = m_spScopeTree->CreateProperties (ppProperties);
  248. if (sc)
  249. return (sc);
  250. return (sc);
  251. }
  252. /*+-------------------------------------------------------------------------*
  253. *
  254. * CAMCDoc::ScEnumNext
  255. *
  256. * PURPOSE: Returns the next item in the enumeration sequence
  257. *
  258. * PARAMETERS:
  259. * _Position & pos :
  260. * PDISPATCH & pDispatch :
  261. *
  262. * RETURNS:
  263. * SC
  264. *
  265. *+-------------------------------------------------------------------------*/
  266. SC
  267. CAMCDoc::ScEnumNext(CAMCViewPosition &pos, PDISPATCH & pDispatch)
  268. {
  269. DECLARE_SC(sc, TEXT("CAMCDoc::ScEnumNext"));
  270. CAMCView *pView = GetNextAMCView(pos);
  271. if(NULL ==pView) // ran out of elements
  272. {
  273. sc = S_FALSE;
  274. return sc;
  275. }
  276. // at this point, we have a valid CAMCView.
  277. ViewPtr spMMCView = NULL;
  278. sc = pView->ScGetMMCView(&spMMCView);
  279. if(sc)
  280. return sc;
  281. if(spMMCView == NULL)
  282. {
  283. sc = E_UNEXPECTED; // should never happen.
  284. return sc;
  285. }
  286. /*
  287. * return the IDispatch for the object and leave a ref on it for the client
  288. */
  289. pDispatch = spMMCView.Detach();
  290. return sc;
  291. }
  292. /*+-------------------------------------------------------------------------*
  293. *
  294. * CAMCDoc::ScEnumSkip
  295. *
  296. * PURPOSE:
  297. *
  298. * PARAMETERS:
  299. * unsigned long :
  300. * CAMCViewPosition & pos :
  301. *
  302. * RETURNS:
  303. * SC
  304. *
  305. *+-------------------------------------------------------------------------*/
  306. SC
  307. CAMCDoc::ScEnumSkip(unsigned long celt, unsigned long& celtSkipped,
  308. CAMCViewPosition &pos)
  309. {
  310. DECLARE_SC(sc, TEXT("CAMCDoc::ScEnumSkip"));
  311. // skip celt positions, don't check the last skip.
  312. for(celtSkipped=0; celtSkipped<celt; celtSkipped++)
  313. {
  314. if (pos == NULL)
  315. {
  316. sc = S_FALSE;
  317. return sc;
  318. }
  319. // go to the next view
  320. GetNextAMCView(pos);
  321. }
  322. return sc;
  323. }
  324. /*+-------------------------------------------------------------------------*
  325. *
  326. * CAMCDoc::ScEnumReset
  327. *
  328. * PURPOSE:
  329. *
  330. * PARAMETERS:
  331. * CAMCViewPosition & pos :
  332. *
  333. * RETURNS:
  334. * SC
  335. *
  336. *+-------------------------------------------------------------------------*/
  337. SC
  338. CAMCDoc::ScEnumReset(CAMCViewPosition &pos)
  339. {
  340. DECLARE_SC(sc, TEXT("CAMCDoc::ScEnumReset"));
  341. // reset the position to the first view.
  342. pos = GetFirstAMCViewPosition();
  343. return sc;
  344. }
  345. //+-------------------------------------------------------------------
  346. //
  347. // Member: CAMCDoc::ScSave
  348. //
  349. // Synopsis: Saves the document.
  350. //
  351. // Arguments: None
  352. //
  353. // Returns: SC
  354. //
  355. //--------------------------------------------------------------------
  356. SC CAMCDoc::ScSave ()
  357. {
  358. DECLARE_SC(sc, _T("CAMCDoc::ScSave"));
  359. // Return if there is no file name given.
  360. if (m_strPathName.IsEmpty())
  361. return sc = ScFromMMC(IDS_UnableToSaveDocumentMessage);
  362. // save the document (this function may produce UI, but we tried ^ to avoid it)
  363. if (!DoFileSave())
  364. return sc = ScFromMMC(IDS_UnableToSaveDocumentMessage);
  365. return (sc);
  366. }
  367. /*+-------------------------------------------------------------------------*
  368. *
  369. * CAMCDoc::ScSaveAs
  370. *
  371. * PURPOSE: Saves the console file, using the specified filename.
  372. *
  373. * PARAMETERS:
  374. * BSTR bstrFilename : The path to save the file to.
  375. *
  376. * RETURNS:
  377. * STDMETHODIMP
  378. *
  379. *+-------------------------------------------------------------------------*/
  380. SC
  381. CAMCDoc::ScSaveAs(BSTR bstrFilename)
  382. {
  383. DECLARE_SC(sc, TEXT("CAMCDoc::ScSaveAs"));
  384. USES_CONVERSION;
  385. LPCTSTR lpctstrName = OLE2T(bstrFilename);
  386. if(!OnSaveDocument(lpctstrName))
  387. {
  388. sc = ScFromMMC(IDS_UnableToSaveDocumentMessage);
  389. return sc;
  390. }
  391. else
  392. {
  393. DeleteHelpFile ();
  394. SetPathName(lpctstrName);
  395. }
  396. return sc;
  397. }
  398. /***************************************************************************\
  399. *
  400. * METHOD: CAMCDoc::ScClose
  401. *
  402. * PURPOSE: implements Document.Close for object model
  403. *
  404. * PARAMETERS:
  405. * BOOL bSaveChanges - save changes before closing
  406. *
  407. * RETURNS:
  408. * SC - result code
  409. *
  410. \***************************************************************************/
  411. SC
  412. CAMCDoc::ScClose(BOOL bSaveChanges)
  413. {
  414. DECLARE_SC(sc, TEXT("CAMCDoc::ScClose"));
  415. if (bSaveChanges)
  416. {
  417. // cannot save ned document this way!
  418. if (m_strPathName.IsEmpty())
  419. return sc = ScFromMMC(IDS_UnableToSaveDocumentMessage);
  420. // check for property sheets open
  421. if (FArePropertySheetsOpen(NULL))
  422. return sc = ScFromMMC(IDS_ClosePropertyPagesBeforeClosingTheDoc);
  423. // save the document (this function may produce UI, but we tried ^ to avoid it)
  424. if (!DoFileSave())
  425. return sc = ScFromMMC(IDS_UnableToSaveDocumentMessage);
  426. }
  427. OnCloseDocument();
  428. return sc;
  429. }
  430. /*+-------------------------------------------------------------------------*
  431. *
  432. * CAMCDoc::ScItem
  433. *
  434. * PURPOSE: Returns the view specified by the index.
  435. *
  436. * PARAMETERS:
  437. * long Index :
  438. * View ** ppView :
  439. *
  440. * RETURNS:
  441. * STDMETHOD
  442. *
  443. *+-------------------------------------------------------------------------*/
  444. SC
  445. CAMCDoc::ScItem(long Index, PPVIEW ppView)
  446. {
  447. DECLARE_SC(sc, TEXT("CAMCDoc::ScItem"));
  448. // check parameters
  449. if( (Index <= 0) || (Index > GetNumberOfViews()) || (!ppView) )
  450. {
  451. sc = E_INVALIDARG;
  452. return sc;
  453. }
  454. // step to the appropriate view
  455. CAMCViewPosition pos = GetFirstAMCViewPosition();
  456. CAMCView *pView = NULL;
  457. for (int nCount = 0; (nCount< Index) && (pos != NULL); )
  458. {
  459. pView = GetNextAMCView(pos);
  460. VERIFY (++nCount);
  461. }
  462. // make sure we have a valid view.
  463. if( (nCount != Index) || (!pView) )
  464. {
  465. sc = E_UNEXPECTED;
  466. return sc;
  467. }
  468. sc = pView->ScGetMMCView(ppView);
  469. return sc;
  470. }
  471. /*+-------------------------------------------------------------------------*
  472. *
  473. * ScMapViewOptions
  474. *
  475. * PURPOSE: helper function maps ViewOptions to view creation flags
  476. *
  477. * PARAMETERS:
  478. * pNode :
  479. *
  480. * RETURNS:
  481. * SC
  482. *
  483. *+-------------------------------------------------------------------------*/
  484. static SC ScMapViewOptions( ViewOptions fViewOptions, DWORD &value)
  485. {
  486. DECLARE_SC(sc, TEXT("ScMapViewOptions"));
  487. value = MMC_NW_OPTION_NONE;
  488. // test to see if parameter is correct
  489. const DWORD mask = (ViewOption_ScopeTreeHidden |
  490. ViewOption_NoToolBars |
  491. ViewOption_NotPersistable
  492. );
  493. if (fViewOptions & (~mask))
  494. sc = E_INVALIDARG;
  495. if (fViewOptions & ViewOption_ScopeTreeHidden)
  496. value |= MMC_NW_OPTION_NOSCOPEPANE;
  497. if (fViewOptions & ViewOption_NotPersistable)
  498. value |= MMC_NW_OPTION_NOPERSIST;
  499. if (fViewOptions & ViewOption_NoToolBars)
  500. value |= MMC_NW_OPTION_NOTOOLBARS;
  501. return sc;
  502. }
  503. /*+-------------------------------------------------------------------------*
  504. *
  505. * CAMCDoc::ScAdd
  506. *
  507. * PURPOSE: Impelements Views.Add method
  508. *
  509. * PARAMETERS:
  510. * pNode :
  511. *
  512. * RETURNS:
  513. * SC
  514. *
  515. *+-------------------------------------------------------------------------*/
  516. SC
  517. CAMCDoc::ScAdd( PNODE pNode, ViewOptions fViewOptions )
  518. {
  519. DECLARE_SC(sc, TEXT("CAMCDoc::ScAdd"));
  520. // lock AppEvents until this function is done
  521. LockComEventInterface(AppEvents);
  522. sc = ScCheckPointers(m_spScopeTree, E_POINTER);
  523. if (sc)
  524. return sc;
  525. DWORD dwOptions = 0;
  526. sc = ScMapViewOptions( fViewOptions, dwOptions );
  527. if (sc)
  528. return sc;
  529. MTNODEID id;
  530. sc = m_spScopeTree->GetNodeID(pNode, &id);
  531. if (sc)
  532. return sc;
  533. // Set the given node-id as the root.
  534. SetMTNodeIDForNewView(id);
  535. SetNewWindowOptions(dwOptions);
  536. CreateNewView( true );
  537. SetMTNodeIDForNewView(ROOTNODEID);
  538. return sc;
  539. }
  540. /*+-------------------------------------------------------------------------*
  541. *
  542. * CAMCDoc::Scget_Views
  543. *
  544. * PURPOSE: Returns a pointer to the Views interface
  545. * (which is implemented by the same object, but need not be)
  546. *
  547. * PARAMETERS:
  548. * Views ** ppViews :
  549. *
  550. * RETURNS:
  551. * STDMETHODIMP
  552. *
  553. *+-------------------------------------------------------------------------*/
  554. SC
  555. CAMCDoc::Scget_Views(PPVIEWS ppViews)
  556. {
  557. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_Views"));
  558. if(!ppViews)
  559. {
  560. sc = E_POINTER;
  561. return sc;
  562. }
  563. // init out parameter
  564. *ppViews = NULL;
  565. // create a Views if needed.
  566. sc = CTiedComObjectCreator<CMMCViews>::ScCreateAndConnect(*this, m_spViews);
  567. if(sc)
  568. return sc;
  569. sc = ScCheckPointers(m_spViews, E_UNEXPECTED);
  570. if (sc)
  571. return sc;
  572. // addref the pointer for the client.
  573. m_spViews->AddRef();
  574. *ppViews = m_spViews;
  575. return sc;
  576. }
  577. /*+-------------------------------------------------------------------------*
  578. *
  579. * CAMCDoc::Scget_SnapIns
  580. *
  581. * PURPOSE: returns a pointer to the SnapIns object.
  582. *
  583. * PARAMETERS:
  584. * SnapIns ** ppSnapIns :
  585. *
  586. * RETURNS:
  587. * STDMETHODIMP
  588. *
  589. *+-------------------------------------------------------------------------*/
  590. SC
  591. CAMCDoc::Scget_SnapIns(PPSNAPINS ppSnapIns)
  592. {
  593. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_SnapIns"));
  594. if((NULL==ppSnapIns) || (NULL == m_spScopeTree) )
  595. {
  596. sc = E_POINTER;
  597. return sc;
  598. }
  599. sc = m_spScopeTree->QuerySnapIns(ppSnapIns);
  600. return sc;
  601. }
  602. /*+-------------------------------------------------------------------------*
  603. *
  604. * CAMCDoc::Scget_ScopeNamespace
  605. *
  606. * PURPOSE: returns a pointer to the ScopeNamespace object.
  607. *
  608. * PARAMETERS:
  609. * ScopeNamespace ** ppScopeNamespace :
  610. *
  611. * RETURNS:
  612. * STDMETHODIMP
  613. *
  614. *+-------------------------------------------------------------------------*/
  615. SC
  616. CAMCDoc::Scget_ScopeNamespace(PPSCOPENAMESPACE ppScopeNamespace)
  617. {
  618. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_ScopeNamespace"));
  619. if((NULL==ppScopeNamespace) || (NULL == m_spScopeTree) )
  620. {
  621. sc = E_POINTER;
  622. return sc;
  623. }
  624. sc = m_spScopeTree->QueryScopeNamespace(ppScopeNamespace);
  625. return sc;
  626. }
  627. /*+-------------------------------------------------------------------------*
  628. *
  629. * CAMCDoc::Scget_Count
  630. *
  631. * PURPOSE:
  632. *
  633. * PARAMETERS:
  634. * long * pCount :
  635. *
  636. * RETURNS:
  637. * STDMETHODIMP
  638. *
  639. *+-------------------------------------------------------------------------*/
  640. SC
  641. CAMCDoc::Scget_Count(PLONG pCount)
  642. {
  643. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_Count"));
  644. // check parameters
  645. if(!pCount)
  646. {
  647. sc = E_POINTER;
  648. return sc;
  649. }
  650. // this should *not* be GetNumberOfPersistedViews
  651. *pCount = GetNumberOfViews();
  652. return sc;
  653. }
  654. //+-------------------------------------------------------------------
  655. //
  656. // Member: CAMCDoc::Scget_Name
  657. //
  658. // Synopsis: Retrive the name of the current doc.
  659. //
  660. // Arguments: [pbstrName] - Ptr to the name to be returned.
  661. //
  662. // Returns: SC
  663. //
  664. //--------------------------------------------------------------------
  665. SC CAMCDoc::Scget_Name (PBSTR pbstrName)
  666. {
  667. DECLARE_SC(sc, _T("CAMCDoc::Scget_Name"));
  668. sc = ScCheckPointers(pbstrName);
  669. if (sc)
  670. return sc;
  671. CString strPath = GetPathName();
  672. *pbstrName = strPath.AllocSysString();
  673. return (sc);
  674. }
  675. //+-------------------------------------------------------------------
  676. //
  677. // Member: CAMCDoc::Scput_Name
  678. //
  679. // Synopsis: Sets the name of the current document.
  680. //
  681. // Arguments: [bstrName] - The new name.
  682. //
  683. // Returns: SC
  684. //
  685. //--------------------------------------------------------------------
  686. SC CAMCDoc::Scput_Name(BSTR bstrName)
  687. {
  688. DECLARE_SC(sc, _T("CAMCDoc::Scput_Name"));
  689. USES_CONVERSION;
  690. LPCTSTR lpszPath = OLE2CT(bstrName);
  691. SetPathName(lpszPath, FALSE /*Dont add to MRU*/);
  692. return (sc);
  693. }
  694. //+-------------------------------------------------------------------
  695. //
  696. // Member: CAMCDoc::Scget_Mode
  697. //
  698. // Synopsis: Retrieve the document mode.
  699. //
  700. // Arguments: [pMode] - Ptr to doc mode.
  701. //
  702. // Returns: SC
  703. //
  704. //--------------------------------------------------------------------
  705. SC CAMCDoc::Scget_Mode (PDOCUMENTMODE pMode)
  706. {
  707. DECLARE_SC(sc, _T("CAMCDoc::Scget_Mode"));
  708. sc = ScCheckPointers(pMode);
  709. if (sc)
  710. return sc;
  711. if (! GetDocumentMode(pMode))
  712. return (sc = E_FAIL);
  713. return (sc);
  714. }
  715. //+-------------------------------------------------------------------
  716. //
  717. // Member: CAMCDoc::Scput_Mode
  718. //
  719. // Synopsis: Modify the document mode.
  720. //
  721. // Arguments: [mode] - new mode for the document.
  722. //
  723. // Returns: SC
  724. //
  725. //--------------------------------------------------------------------
  726. SC CAMCDoc::Scput_Mode (DocumentMode mode)
  727. {
  728. DECLARE_SC(sc, _T("CAMCDoc::Scput_Mode"));
  729. // SetDocumentMode fails if document mode is invalid.
  730. if (! SetDocumentMode(mode))
  731. return (sc = E_INVALIDARG);
  732. return (sc);
  733. }
  734. //+-------------------------------------------------------------------
  735. //
  736. // Member: CAMCDoc::Scget_ActiveView
  737. //
  738. // Synopsis: Retrieve the Active View object.
  739. //
  740. // Arguments: [ppView] - Ptr to a ptr of View object.
  741. //
  742. // Returns: SC
  743. //
  744. //--------------------------------------------------------------------
  745. SC CAMCDoc::Scget_ActiveView (PPVIEW ppView)
  746. {
  747. DECLARE_SC(sc, _T("CAMCDoc::Scget_ActiveView"));
  748. sc = ScCheckPointers(ppView);
  749. if (sc)
  750. return sc;
  751. *ppView = NULL;
  752. CMainFrame* pMainFrame = AMCGetMainWnd();
  753. sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
  754. if (sc)
  755. return sc;
  756. CAMCView *pView = pMainFrame->GetActiveAMCView();
  757. if (! pView)
  758. {
  759. return (sc = ScFromMMC(IDS_NoActiveView)); // There are no active views.
  760. }
  761. // at this point, we have a valid CAMCView.
  762. ViewPtr spMMCView = NULL;
  763. sc = pView->ScGetMMCView(&spMMCView);
  764. if(sc)
  765. return sc;
  766. sc = ScCheckPointers(spMMCView, E_UNEXPECTED);
  767. if (sc)
  768. return sc;
  769. /*
  770. * return the object and leave a ref on it for the client
  771. */
  772. *ppView = spMMCView.Detach();
  773. return (sc);
  774. }
  775. //+-------------------------------------------------------------------
  776. //
  777. // Member: CAMCDoc::Scget_IsSaved
  778. //
  779. // Synopsis: Returns whether the file was saved. If not,
  780. // it is dirty and needs to be saved.
  781. //
  782. // Arguments: [pBIsSaved] - Ptr to BOOL (IsSaved info).
  783. //
  784. // Returns: SC
  785. //
  786. //--------------------------------------------------------------------
  787. SC CAMCDoc::Scget_IsSaved (PBOOL pBIsSaved)
  788. {
  789. DECLARE_SC(sc, _T("CAMCDoc::Scget_IsSaved"));
  790. sc = ScCheckPointers(pBIsSaved);
  791. if (sc)
  792. return sc;
  793. *pBIsSaved = (IsModified() == FALSE);
  794. return (sc);
  795. }
  796. //+-------------------------------------------------------------------
  797. //
  798. // Member: CAMCDoc::Scget_Location
  799. //
  800. // Synopsis: Gets the location of the current document.
  801. //
  802. // Arguments: [pbstrLocation] - Ptr to BSTR string in which result is returned.
  803. //
  804. // Returns: SC
  805. //
  806. //--------------------------------------------------------------------
  807. SC CAMCDoc::Scget_Location (PBSTR pbstrLocation)
  808. {
  809. DECLARE_SC(sc, _T("CAMCDoc::Scget_Location"));
  810. sc = ScCheckPointers(pbstrLocation);
  811. if (sc)
  812. return sc;
  813. CString strFullPath = GetPathName();
  814. // Even if path is empty below code will return empty string.
  815. int nSlashLoc = strFullPath.ReverseFind(_T('\\'));
  816. CString strLocation = strFullPath.Left(nSlashLoc);
  817. *pbstrLocation = strLocation.AllocSysString();
  818. return (sc);
  819. }
  820. //+-------------------------------------------------------------------
  821. //
  822. // Member: CAMCDoc::Scget_RootNode
  823. //
  824. // Synopsis: Returns the console root node.
  825. //
  826. // Arguments: [ppNode] - Ptr to ptr to root node obj.
  827. //
  828. // Returns: SC
  829. //
  830. //--------------------------------------------------------------------
  831. SC CAMCDoc::Scget_RootNode (PPNODE ppNode)
  832. {
  833. DECLARE_SC(sc, _T("CAMCDoc::Scget_RootNode"));
  834. sc = ScCheckPointers(ppNode);
  835. if (sc)
  836. return sc;
  837. sc = ScCheckPointers(m_spScopeTree, E_UNEXPECTED);
  838. if (sc)
  839. return sc;
  840. sc = m_spScopeTree->QueryRootNode(ppNode);
  841. return (sc);
  842. }
  843. /*+-------------------------------------------------------------------------*
  844. *
  845. * CAMCDoc::ScGetMMCDocument
  846. *
  847. * PURPOSE: Creates, AddRef's, and returns a pointer to the tied COM object.
  848. *
  849. * PARAMETERS:
  850. * Document ** ppDocument :
  851. *
  852. * RETURNS:
  853. * SC
  854. *
  855. *+-------------------------------------------------------------------------*/
  856. SC
  857. CAMCDoc::ScGetMMCDocument(Document **ppDocument)
  858. {
  859. DECLARE_SC(sc, TEXT("CAMCDoc::ScGetMMCDocument"));
  860. // parameter check
  861. sc = ScCheckPointers(ppDocument);
  862. if (sc)
  863. return sc;
  864. // init out parameter
  865. *ppDocument = NULL;
  866. // create a CAMCDoc if needed.
  867. sc = CTiedComObjectCreator<CMMCDocument>::ScCreateAndConnect(*this, m_sp_Document);
  868. if(sc)
  869. return sc;
  870. sc = ScCheckPointers(m_sp_Document, E_UNEXPECTED);
  871. if (sc)
  872. return sc;
  873. // addref the pointer for the client.
  874. m_sp_Document->AddRef();
  875. *ppDocument = m_sp_Document;
  876. return sc;
  877. }
  878. /*+-------------------------------------------------------------------------*
  879. *
  880. * GetFirstAMCViewPosition
  881. *
  882. * PURPOSE: Returns the CAMCViewPosition of the first AMCView, or NULL if there is
  883. * no AMCView.
  884. *
  885. * RETURNS:
  886. * CAMCViewPosition
  887. *
  888. *+-------------------------------------------------------------------------*/
  889. CAMCViewPosition
  890. CAMCDoc::GetFirstAMCViewPosition() const
  891. {
  892. CAMCViewPosition vpos;
  893. POSITION pos = GetFirstViewPosition();
  894. while(pos != NULL)
  895. {
  896. POSITION posTemp = pos; // hold this value.
  897. CAMCView *pView = dynamic_cast<CAMCView *>(GetNextView(pos));
  898. if(pView != NULL) // found the AMCView
  899. {
  900. vpos.SetPosition(posTemp); // NOT pos!
  901. break;
  902. }
  903. }
  904. return (vpos);
  905. }
  906. /*+-------------------------------------------------------------------------*
  907. *
  908. * CAMCDoc::GetNextAMCView
  909. *
  910. * PURPOSE: Returns the next AMCView, starting at pos (inclusive)
  911. *
  912. * PARAMETERS:
  913. * CAMCViewPosition & pos : incremented to the next AMCView, NOT the next View.
  914. *
  915. * RETURNS:
  916. * CAMCView *
  917. *
  918. *+-------------------------------------------------------------------------*/
  919. CAMCView *
  920. CAMCDoc::GetNextAMCView(CAMCViewPosition &pos) const
  921. {
  922. CAMCView *pView = NULL;
  923. // check parameters
  924. if (pos == NULL)
  925. return NULL;
  926. // pos is non-NULL at this point. Loop until we have a CAMCView.
  927. // Note that unless there's a bug in GetFirstAMCViewPosition or
  928. // GetNextAMCView, we'll only go through this loop once, since a
  929. // non-NULL CAMCViewPosition should always refer to a CAMCView.
  930. while( (NULL == pView) && (pos != NULL) )
  931. {
  932. CView *pV = GetNextView(pos.GetPosition());
  933. pView = dynamic_cast<CAMCView *>(pV);
  934. }
  935. // at this point, pView is the correct return value, and it had better
  936. // not be NULL, or we never should have had a non-NULL pos
  937. ASSERT (pView != NULL);
  938. // bump pos to the next CAMCView
  939. // NOTE: This is NOT redundant. Must point to a CAMCView so that
  940. // NULL position tests can be done.
  941. while(pos != NULL)
  942. {
  943. /*
  944. * use temporary POSITION so we won't increment the POSITION
  945. * inside pos until we know pos doesn't refer to a CAMCView
  946. */
  947. POSITION posT = pos.GetPosition();
  948. if(dynamic_cast<CAMCView *>(GetNextView(posT)) != NULL) // found a CAMCView at pos
  949. break;
  950. /*
  951. * update the CAMCViewPosition with the position incremented
  952. * by GetNextView only if we didn't find a CAMCView at its
  953. * previous location
  954. */
  955. pos.SetPosition (posT);
  956. }
  957. #ifdef DBG
  958. /*
  959. * if we're returning a non-NULL, it'd better point to a CAMCView
  960. */
  961. if (pos != NULL)
  962. {
  963. POSITION posT = pos.GetPosition();
  964. ASSERT (dynamic_cast<CAMCView *>(GetNextView(posT)) != NULL);
  965. }
  966. #endif
  967. return pView;
  968. }
  969. /*+-------------------------------------------------------------------------*
  970. *
  971. * CAMCDoc::InitNodeManager
  972. *
  973. * PURPOSE:
  974. *
  975. * RETURNS:
  976. * HRESULT
  977. *
  978. *+-------------------------------------------------------------------------*/
  979. HRESULT CAMCDoc::InitNodeManager()
  980. {
  981. DECLARE_SC(sc, TEXT("CAMCDoc::InitNodeManager"));
  982. TRACE_METHOD(CAMCDoc, InitNodeManager);
  983. // Should not be currently initialized
  984. ASSERT(m_spScopeTree == NULL && m_spScopeTreePersist == NULL);
  985. ASSERT(m_spStorage == NULL);
  986. // The string table should have been created by now
  987. sc = ScCheckPointers(m_spStringTable, E_FAIL);
  988. if(sc)
  989. return sc.ToHr();
  990. // create the favorites at this stage
  991. ASSERT(m_pFavorites == NULL);
  992. m_pFavorites = new CFavorites;
  993. sc = ScCheckPointers(m_pFavorites, E_OUTOFMEMORY);
  994. if(sc)
  995. return sc.ToHr();
  996. // Create the initial private frame
  997. IFramePrivatePtr spFrame;
  998. sc = spFrame.CreateInstance(CLSID_NodeInit, NULL, MMC_CLSCTX_INPROC);
  999. if (sc)
  1000. return sc.ToHr();
  1001. // recheck teh pointer
  1002. sc = ScCheckPointers( spFrame, E_UNEXPECTED );
  1003. if (sc)
  1004. return sc.ToHr();
  1005. // Create the scope tree
  1006. sc = m_spScopeTree.CreateInstance(CLSID_ScopeTree, NULL, MMC_CLSCTX_INPROC);
  1007. if (sc)
  1008. {
  1009. ReleaseNodeManager();
  1010. return sc.ToHr();
  1011. }
  1012. // recheck the pointer
  1013. sc = ScCheckPointers( m_spScopeTree, E_UNEXPECTED );
  1014. if (sc)
  1015. {
  1016. ReleaseNodeManager();
  1017. return sc.ToHr();
  1018. }
  1019. // link frame and scope tree
  1020. sc = spFrame->SetScopeTree(m_spScopeTree);
  1021. if(sc)
  1022. {
  1023. ReleaseNodeManager();
  1024. return sc.ToHr();
  1025. }
  1026. // Initialize the tree
  1027. sc = m_spScopeTree->Initialize(AfxGetMainWnd()->m_hWnd, m_spStringTable);
  1028. if (sc)
  1029. {
  1030. ReleaseNodeManager();
  1031. return sc.ToHr();
  1032. }
  1033. // Get the IPersistStorage interface from the scope tree
  1034. m_spScopeTreePersist = m_spScopeTree; // query for IPersistStorage
  1035. ASSERT(m_spScopeTreePersist != NULL);
  1036. m_ConsoleData.SetScopeTree (m_spScopeTree);
  1037. CMainFrame* pFrame = AMCGetMainWnd();
  1038. m_ConsoleData.m_hwndMainFrame = pFrame->GetSafeHwnd();
  1039. m_ConsoleData.m_pConsoleFrame = pFrame;
  1040. return sc.ToHr();
  1041. }
  1042. BOOL CAMCDoc::OnNewDocument()
  1043. {
  1044. TRACE_METHOD(CAMCDoc, OnNewDocument);
  1045. USES_CONVERSION;
  1046. // Initialize the document and scope view ...
  1047. if (!CDocument::OnNewDocument())
  1048. return FALSE;
  1049. // A new file can't be read-only
  1050. SetPhysicalReadOnlyFlag (false);
  1051. // use latest file version
  1052. m_ConsoleData.m_eFileVer = FileVer_Current;
  1053. ASSERT (IsValidFileVersion (m_ConsoleData.m_eFileVer));
  1054. // Init help doc info times to current time by default
  1055. // Will update when file is first saved
  1056. ::GetSystemTimeAsFileTime(&GetHelpDocInfo()->m_ftimeCreate);
  1057. GetHelpDocInfo()->m_ftimeModify = GetHelpDocInfo()->m_ftimeCreate;
  1058. return TRUE;
  1059. }
  1060. /////////////////////////////////////////////////////////////////////////////
  1061. // CAMCDoc diagnostics
  1062. #ifdef _DEBUG
  1063. void CAMCDoc::AssertValid() const
  1064. {
  1065. CDocument::AssertValid();
  1066. }
  1067. void CAMCDoc::Dump(CDumpContext& dc) const
  1068. {
  1069. CDocument::Dump(dc);
  1070. }
  1071. #endif //_DEBUG
  1072. /////////////////////////////////////////////////////////////////////////////
  1073. // CAMCDoc commands
  1074. inline bool UnableToSaveDocument()
  1075. {
  1076. if (AMCGetApp()->GetMode() == eMode_Author)
  1077. MMCMessageBox(IDS_UnableToSaveDocumentMessage);
  1078. return false;
  1079. }
  1080. static const wchar_t* AMCViewDataStreamName = L"ViewData";
  1081. static const wchar_t* AMCFrameDataStreamName = L"FrameData";
  1082. static const wchar_t* AMCStringTableStorageName = L"String Table";
  1083. static const wchar_t* AMCFavoritesStreamName = L"FavoritesStream";
  1084. static const wchar_t* AMCCustomTitleStreamName = L"Title";
  1085. static const wchar_t* AMCColumnDataStreamName = L"ColumnData";
  1086. static const wchar_t* AMCViewSettingDataStreamName = L"ViewSettingData"; // View settings data stream
  1087. #pragma warning( disable : 4800 )
  1088. struct FrameState
  1089. {
  1090. WINDOWPLACEMENT windowPlacement;
  1091. BOOL fShowStatusBarInUserMode;
  1092. BOOL fShowToolbarInAuthorMode;
  1093. }; // struct FrameState
  1094. struct FrameState2
  1095. {
  1096. UINT cbSize;
  1097. WINDOWPLACEMENT wndplFrame;
  1098. ProgramMode eMode;
  1099. DWORD dwFlags;
  1100. // NOT USED - SIZE PRESERVED FOR COMPATIBILITY
  1101. // DWORD dwHelpDocIndex;
  1102. // DWORD dwHelpDocTime[2];
  1103. DWORD dwUnused;
  1104. DWORD dwUnused2[2];
  1105. FrameState2 (ProgramMode eMode_ = eMode_Author,
  1106. DWORD dwFlags_ = eFlag_Default) :
  1107. cbSize (sizeof (FrameState2)),
  1108. eMode (eMode_),
  1109. dwFlags (dwFlags_),
  1110. // NOT USED - SIZE PRESERVED FOR COMPATIBILITY
  1111. dwUnused(0)
  1112. // dwHelpDocIndex (0)
  1113. {
  1114. // NOT USED - SIZE PRESERVED FOR COMPATIBILITY
  1115. // ZeroMemory (dwHelpDocTime, sizeof (dwHelpDocTime));
  1116. ZeroMemory (&dwUnused2, sizeof (dwUnused2));
  1117. ZeroMemory (&wndplFrame, sizeof (wndplFrame));
  1118. wndplFrame.length = sizeof (wndplFrame);
  1119. }
  1120. }; // struct FrameState2
  1121. /*+-------------------------------------------------------------------------*
  1122. * CFrameState
  1123. *
  1124. * class is designated to be used instead of FrameState2 in Persist methods.
  1125. * It implements functionality of CXMLObject while containing the same data as FrameState2
  1126. * The original struct cannot be extended because many methods do relay on its size.
  1127. *
  1128. *--------------------------------------------------------------------------*/
  1129. class CFrameState : public CXMLObject, public FrameState2
  1130. {
  1131. public:
  1132. CFrameState(ProgramMode eMode_, DWORD dwFlags_) : FrameState2 (eMode_,dwFlags_) {}
  1133. protected:
  1134. DEFINE_XML_TYPE (XML_TAG_FRAME_STATE);
  1135. virtual void Persist(CPersistor &persistor)
  1136. {
  1137. persistor.Persist(CXMLWindowPlacement(wndplFrame));
  1138. // define the table to map enumeration values to strings
  1139. static const EnumLiteral frameStateFlags[] =
  1140. {
  1141. { eFlag_ShowStatusBar, XML_ENUM_FSTATE_SHOWSTATUSBAR },
  1142. { eFlag_HelpDocInvalid, XML_ENUM_FSTATE_HELPDOCINVALID },
  1143. { eFlag_LogicalReadOnly, XML_ENUM_FSTATE_LOGICALREADONLY },
  1144. { eFlag_PreventViewCustomization, XML_ENUM_FSTATE_PREVENTVIEWCUSTOMIZATION },
  1145. };
  1146. // create wrapper to persist enumeration values as strings
  1147. CXMLBitFlags flagPersistor(dwFlags, frameStateFlags, countof(frameStateFlags));
  1148. // persist the wrapper
  1149. persistor.PersistAttribute(XML_ATTR_FRAME_STATE_FLAGS, flagPersistor);
  1150. }
  1151. };
  1152. // what is the size of the Version 1.1 definition of FrameState2?
  1153. const int cbFrameState2_v11 = SIZEOF_STRUCT (FrameState2, dwUnused2 /*dwHelpDocTime*/ );
  1154. /*+-------------------------------------------------------------------------*
  1155. * AdjustRect
  1156. *
  1157. * Adjusts pInnerRect so that it is completely contained within pOuterRect
  1158. *
  1159. * If AR_MOVE is specified, the origin of pInnerRect is moved enough (if
  1160. * necessary) so that the right and/or bottom edges of pInnerRect coincide
  1161. * with those of pOuterRect. pInnerRect's origin is never moved above or to
  1162. * the left of pOuterRect's origin.
  1163. *
  1164. * If AR_SIZE is specified, the right and/or bottom edges of pInnerRect are
  1165. * moved to that they coincide with those of pOuterRect.
  1166. *--------------------------------------------------------------------------*/
  1167. #define AR_MOVE 0x0000001
  1168. #define AR_SIZE 0x0000002
  1169. void AdjustRect (LPCRECT pOuterRect, LPRECT pInnerRect, DWORD dwFlags)
  1170. {
  1171. /*
  1172. * if the inner rectangle is completely within
  1173. * the outer, there's nothing to do
  1174. */
  1175. if ((pInnerRect->left >= pOuterRect->left ) &&
  1176. (pInnerRect->right <= pOuterRect->right ) &&
  1177. (pInnerRect->top >= pOuterRect->top ) &&
  1178. (pInnerRect->bottom <= pOuterRect->bottom))
  1179. return;
  1180. /*
  1181. * handle movement
  1182. */
  1183. if (dwFlags & AR_MOVE)
  1184. {
  1185. int dx = 0;
  1186. /*
  1187. * shift inner rect right?
  1188. */
  1189. if (pInnerRect->left < pOuterRect->left)
  1190. dx = pOuterRect->left - pInnerRect->left;
  1191. /*
  1192. * shift inner rect left? (make sure we don't shift it past the
  1193. * left of the outer rect)
  1194. */
  1195. else if (pInnerRect->right > pOuterRect->right)
  1196. dx = std::_MAX (pOuterRect->right - pInnerRect->right,
  1197. pOuterRect->left - pInnerRect->left);
  1198. /*
  1199. * make sure things are right in the vertical
  1200. */
  1201. int dy = 0;
  1202. /*
  1203. * shift inner rect down?
  1204. */
  1205. if (pInnerRect->top < pOuterRect->top)
  1206. dy = pOuterRect->top - pInnerRect->top;
  1207. /*
  1208. * shift inner rect up? (make sure we don't shift it past the
  1209. * top of the outer rect)
  1210. */
  1211. else if (pInnerRect->bottom > pOuterRect->bottom)
  1212. dy = std::_MAX (pOuterRect->bottom - pInnerRect->bottom,
  1213. pOuterRect->top - pInnerRect->top);
  1214. /*
  1215. * if we need to shift the inner rect, do it now
  1216. */
  1217. if ((dx != 0) || (dy != 0))
  1218. {
  1219. ASSERT (dwFlags & AR_MOVE);
  1220. OffsetRect (pInnerRect, dx, dy);
  1221. }
  1222. }
  1223. /*
  1224. * handle sizing
  1225. */
  1226. if (dwFlags & AR_SIZE)
  1227. {
  1228. if (pInnerRect->right > pOuterRect->right)
  1229. pInnerRect->right = pOuterRect->right;
  1230. if (pInnerRect->bottom > pOuterRect->bottom)
  1231. pInnerRect->bottom = pOuterRect->bottom;
  1232. }
  1233. }
  1234. /*+-------------------------------------------------------------------------*
  1235. * InsurePlacementIsOnScreen
  1236. *
  1237. * This function insures that the window will appear on the virtual screen,
  1238. * and if the whole window can't be located there, that at least the most
  1239. * interesting part is visible.
  1240. *--------------------------------------------------------------------------*/
  1241. void InsurePlacementIsOnScreen (WINDOWPLACEMENT& wndpl)
  1242. {
  1243. /*
  1244. * find the monitor containing the window origin
  1245. */
  1246. HMONITOR hmon = MonitorFromPoint (CPoint (wndpl.rcNormalPosition.left,
  1247. wndpl.rcNormalPosition.top),
  1248. MONITOR_DEFAULTTONEAREST);
  1249. MONITORINFO mi = { sizeof (mi) };
  1250. CRect rectBounds;
  1251. /*
  1252. * if we could get the info for the monitor containing the window origin,
  1253. * use it's workarea as the bounding rectangle; otherwise get the workarea
  1254. * for the default monitor; if that failed as well, default to 640x480
  1255. */
  1256. if (GetMonitorInfo (hmon, &mi))
  1257. rectBounds = mi.rcWork;
  1258. else if (!SystemParametersInfo (SPI_GETWORKAREA, 0, &rectBounds, false))
  1259. rectBounds.SetRect (0, 0, 639, 479);
  1260. /*
  1261. * position the window rectangle within the bounding rectangle
  1262. */
  1263. AdjustRect (rectBounds, &wndpl.rcNormalPosition, AR_MOVE | AR_SIZE);
  1264. }
  1265. //+-------------------------------------------------------------------
  1266. //
  1267. // Member: LoadFrame
  1268. //
  1269. // Synopsis: Load the Frame Data.
  1270. //
  1271. // Note: The app mode was already read by LoadAppMode.
  1272. // The child frames are created so call UpdateFrameWindow.
  1273. //
  1274. // Arguments: None
  1275. //
  1276. // Returns: bool. TRUE if success.
  1277. //
  1278. //--------------------------------------------------------------------
  1279. bool CAMCDoc::LoadFrame()
  1280. // The caller is resposible for calling DeleteContents() and display a message
  1281. // to the user when this function return false.
  1282. {
  1283. TRACE_METHOD(CAMCDoc, LoadFrame);
  1284. // This assertion shouldn't fail until the definition of FrameState2 changes
  1285. // in a version after 1.1. At that time, add another cbFrameState2_vXX
  1286. // with the new version's FrameState2 size.
  1287. ASSERT (cbFrameState2_v11 == sizeof (FrameState2));
  1288. if (!AssertNodeManagerIsLoaded())
  1289. return false;
  1290. // Open the stream containing data for the app and frame
  1291. IStreamPtr spStream;
  1292. HRESULT hr;
  1293. hr = OpenDebugStream (m_spStorage, AMCFrameDataStreamName,
  1294. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1295. &spStream);
  1296. ASSERT(SUCCEEDED(hr) && spStream != NULL);
  1297. if (FAILED(hr))
  1298. return false;
  1299. FrameState2 fs2;
  1300. ULONG cbRead;
  1301. ASSERT (IsValidFileVersion (m_ConsoleData.m_eFileVer));
  1302. // V1.0 file? Migrate it forward
  1303. if (m_ConsoleData.m_eFileVer == FileVer_0100)
  1304. {
  1305. FrameState fs;
  1306. hr = spStream->Read (&fs, sizeof(fs), &cbRead);
  1307. // if we can't read the FrameState, the file is corrupt
  1308. if (FAILED(hr) || (cbRead != sizeof(fs)))
  1309. return (false);
  1310. // migrate FrameState into FrameState2
  1311. fs2.wndplFrame = fs.windowPlacement;
  1312. if (fs.fShowStatusBarInUserMode)
  1313. fs2.dwFlags |= eFlag_ShowStatusBar;
  1314. else
  1315. fs2.dwFlags &= ~eFlag_ShowStatusBar;
  1316. }
  1317. // otherwise, current file
  1318. else
  1319. {
  1320. hr = spStream->Read (&fs2, sizeof(fs2), &cbRead);
  1321. // if we can't read the rest of the FrameState, the file is corrupt
  1322. if (FAILED(hr) || (cbRead != sizeof(fs2)))
  1323. return (false);
  1324. }
  1325. // Set the windows size and location and state
  1326. CMainFrame* pMainFrame = AMCGetMainWnd ();
  1327. ASSERT(pMainFrame != NULL);
  1328. if (pMainFrame == NULL)
  1329. return false;
  1330. CAMCApp* pApp = AMCGetApp();
  1331. pApp->UpdateFrameWindow(true);
  1332. pMainFrame->UpdateChildSystemMenus();
  1333. // the status bar is on the child frame now
  1334. // pMainFrame->ShowStatusBar ((fs2.dwFlags & eFlag_ShowStatusBar) != 0);
  1335. // save the data from the file into the console data
  1336. m_ConsoleData.m_eAppMode = pApp->GetMode();
  1337. m_ConsoleData.m_eConsoleMode = fs2.eMode;
  1338. m_ConsoleData.m_dwFlags = fs2.dwFlags;
  1339. InsurePlacementIsOnScreen (fs2.wndplFrame);
  1340. // if we're initializing, defer the actual show until initialization is complete
  1341. // same if script is under control and MMC is hidden
  1342. if (pApp->IsInitializing()
  1343. || ( !pApp->IsUnderUserControl() && !pMainFrame->IsWindowVisible() ) )
  1344. {
  1345. pApp->m_nCmdShow = fs2.wndplFrame.showCmd;
  1346. fs2.wndplFrame.showCmd = SW_HIDE;
  1347. }
  1348. return (pMainFrame->SetWindowPlacement (&fs2.wndplFrame));
  1349. }
  1350. //+-------------------------------------------------------------------
  1351. //
  1352. // Member: LoadAppMode
  1353. //
  1354. // Synopsis: Read the app mode from the frame and store it in CAMCApp.
  1355. // This is needed during CAMCView::Load.
  1356. //
  1357. // Arguments: None
  1358. //
  1359. // Returns: bool. TRUE if success.
  1360. //
  1361. //--------------------------------------------------------------------
  1362. bool CAMCDoc::LoadAppMode()
  1363. {
  1364. TRACE_METHOD(CAMCDoc, LoadAppMode);
  1365. // Just load the application mode from frame data.
  1366. // This assertion shouldn't fail until the definition of FrameState2 changes
  1367. // in a version after 1.1. At that time, add another cbFrameState2_vXX
  1368. // with the new version's FrameState2 size.
  1369. ASSERT (cbFrameState2_v11 == sizeof (FrameState2));
  1370. if (!AssertNodeManagerIsLoaded())
  1371. return false;
  1372. // Open the stream containing data for the app and frame
  1373. IStreamPtr spStream;
  1374. HRESULT hr;
  1375. hr = OpenDebugStream (m_spStorage, AMCFrameDataStreamName,
  1376. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1377. &spStream);
  1378. ASSERT(SUCCEEDED(hr) && spStream != NULL);
  1379. if (FAILED(hr))
  1380. return false;
  1381. FrameState2 fs2;
  1382. ULONG cbRead;
  1383. ASSERT (IsValidFileVersion (m_ConsoleData.m_eFileVer));
  1384. // V1.0 file? Migrate it forward
  1385. if (m_ConsoleData.m_eFileVer == FileVer_0100)
  1386. {
  1387. FrameState fs;
  1388. hr = spStream->Read (&fs, sizeof(fs), &cbRead);
  1389. // if we can't read the FrameState, the file is corrupt
  1390. if (FAILED(hr) || (cbRead != sizeof(fs)))
  1391. return (false);
  1392. // migrate FrameState into FrameState2
  1393. fs2.wndplFrame = fs.windowPlacement;
  1394. if (fs.fShowStatusBarInUserMode)
  1395. fs2.dwFlags |= eFlag_ShowStatusBar;
  1396. else
  1397. fs2.dwFlags &= ~eFlag_ShowStatusBar;
  1398. }
  1399. // otherwise, current file
  1400. else
  1401. {
  1402. hr = spStream->Read (&fs2, sizeof(fs2), &cbRead);
  1403. // if we can't read the rest of the FrameState, the file is corrupt
  1404. if (FAILED(hr) || (cbRead != sizeof(fs2)))
  1405. return (false);
  1406. }
  1407. CAMCApp* pApp = AMCGetApp();
  1408. pApp->SetMode (fs2.eMode);
  1409. return true;
  1410. }
  1411. bool CAMCDoc::LoadViews()
  1412. // Caller is resposible for calling DeleteContents() and displaying failure
  1413. // message if false is returned.
  1414. {
  1415. TRACE_METHOD(CAMCDoc, LoadViews);
  1416. if (!AssertNodeManagerIsLoaded())
  1417. return false;
  1418. // Open the tree data stream
  1419. IStreamPtr spStream;
  1420. HRESULT hr = OpenDebugStream(m_spStorage, AMCViewDataStreamName,
  1421. STGM_SHARE_EXCLUSIVE | STGM_READ, &spStream);
  1422. ASSERT(SUCCEEDED(hr) && spStream != NULL);
  1423. if (FAILED(hr))
  1424. return false;
  1425. // Read the number of views persisted
  1426. unsigned short numberOfViews;
  1427. unsigned long bytesRead;
  1428. hr = spStream->Read(&numberOfViews, sizeof(numberOfViews), &bytesRead);
  1429. ASSERT(SUCCEEDED(hr) && bytesRead == sizeof(numberOfViews));
  1430. if (FAILED(hr) || bytesRead != sizeof(numberOfViews))
  1431. return false;
  1432. // Loop thru and create each view
  1433. int failedCount = 0;
  1434. while (numberOfViews--)
  1435. {
  1436. // Read the node id for the root node of the view being created.
  1437. m_MTNodeIDForNewView = 0;
  1438. bool bRet = m_spScopeTree->GetNodeIDFromStream(spStream, &m_MTNodeIDForNewView);
  1439. // Read the node id for the selected node of the view being created.
  1440. ULONG idSel = 0;
  1441. bRet = m_spScopeTree->GetNodeIDFromStream(spStream, &idSel);
  1442. // Read the view id of the view being created.
  1443. hr = spStream->Read(&m_ViewIDForNewView,
  1444. sizeof(m_ViewIDForNewView), &bytesRead);
  1445. ASSERT(SUCCEEDED(hr) && bytesRead == sizeof(m_ViewIDForNewView));
  1446. if (FAILED(hr) || bytesRead != sizeof(m_ViewIDForNewView))
  1447. return false;
  1448. if (bRet || m_MTNodeIDForNewView != 0)
  1449. {
  1450. // Create the new view and load its data
  1451. CAMCView* const v = CreateNewView(true);
  1452. m_ViewIDForNewView = 0;
  1453. ASSERT(v != NULL);
  1454. if (v == NULL)
  1455. {
  1456. ++failedCount;
  1457. continue;
  1458. }
  1459. if (!v->Load(*spStream))
  1460. return false;
  1461. v->ScSelectNode(idSel);
  1462. v->SaveStartingSelectedNode();
  1463. v->SetDirty (false);
  1464. //v->GetHistoryList()->Clear();
  1465. }
  1466. }
  1467. // Reset the node ID for future view creation
  1468. m_MTNodeIDForNewView = ROOTNODEID;
  1469. SetModifiedFlag(FALSE);
  1470. return (failedCount == 0);
  1471. }
  1472. SC CAMCDoc::ScCreateAndLoadView(CPersistor& persistor, int nViewID, const CBookmark& rootNode)
  1473. // Caller is resposible for calling DeleteContents() and displaying failure
  1474. // message if false is returned.
  1475. {
  1476. DECLARE_SC(sc, TEXT("CAMCDoc::ScCreateAndLoadView"));
  1477. // Read the node id for the root node of the view being created.
  1478. m_MTNodeIDForNewView = 0;
  1479. MTNODEID idTemp = 0;
  1480. bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark, unused
  1481. sc = m_spScopeTree->GetNodeIDFromBookmark(rootNode, &idTemp, bExactMatchFound);
  1482. if(sc)
  1483. return sc;
  1484. m_MTNodeIDForNewView = idTemp;
  1485. if (m_MTNodeIDForNewView != 0)
  1486. {
  1487. // Read the view id of the view being created.
  1488. m_ViewIDForNewView = nViewID;
  1489. // Create the new view and load its data
  1490. CAMCView* const v = CreateNewView(true);
  1491. m_ViewIDForNewView = 0;
  1492. sc = ScCheckPointers(v, E_FAIL);
  1493. if (sc)
  1494. return sc;
  1495. v->Persist(persistor);
  1496. v->SaveStartingSelectedNode();
  1497. v->SetDirty (false);
  1498. //v->GetHistoryList()->Clear();
  1499. }
  1500. else
  1501. {
  1502. return sc = SC(E_UNEXPECTED);
  1503. }
  1504. // Reset the node ID for future view creation
  1505. m_MTNodeIDForNewView = ROOTNODEID;
  1506. SetModifiedFlag(FALSE);
  1507. return sc;
  1508. }
  1509. /*+-------------------------------------------------------------------------*
  1510. * ShowIncompatibleFileMessage
  1511. *
  1512. *
  1513. *--------------------------------------------------------------------------*/
  1514. static void ShowIncompatibleFileMessage (
  1515. LPCTSTR pszFilename,
  1516. ConsoleFileVersion eFileVer)
  1517. {
  1518. DECLARE_SC(sc, TEXT("ShowIncompatibleFileMessage"));
  1519. TCHAR szFileVersion[16];
  1520. sc = StringCchPrintf(szFileVersion, countof(szFileVersion),
  1521. _T("%d.%d%x"), GetConsoleFileMajorVersion (eFileVer),
  1522. GetConsoleFileMinorVersion (eFileVer),
  1523. GetConsoleFileMinorSubversion (eFileVer));
  1524. // Display error and show incompatible error.
  1525. if (sc)
  1526. sc.TraceAndClear();
  1527. CString strMessage;
  1528. FormatString2 (strMessage, IDS_NewerVersionRequired, pszFilename, szFileVersion);
  1529. MMCMessageBox (strMessage);
  1530. }
  1531. /*+-------------------------------------------------------------------------*
  1532. * CAMCDoc::OnOpenDocument
  1533. *
  1534. * WM_OPENDOCUMENT handler for CAMCDoc.
  1535. *--------------------------------------------------------------------------*/
  1536. BOOL CAMCDoc::OnOpenDocument(LPCTSTR lpszPathName)
  1537. {
  1538. DECLARE_SC(sc, TEXT("CAMCDoc::OnOpenDocument"));
  1539. sc = ScOnOpenDocument(lpszPathName);
  1540. if(sc) // found an error
  1541. {
  1542. DisplayFileOpenError (sc, lpszPathName);
  1543. return false;
  1544. }
  1545. sc = ScFireEvent(CAMCDocumentObserver::ScDocumentLoadCompleted, this);
  1546. if (sc)
  1547. return false;
  1548. /*
  1549. * Success! We shouldn't think that a freshly opened console file is
  1550. * dirty. If we do, someone's dirty bit processing is bogus.
  1551. */
  1552. ASSERT (!IsFrameModified());
  1553. /*
  1554. * Too many snap-ins leave themselves dirty after a load to leave this
  1555. * assert in, so we'll trace instead. Note that this trace doesn't
  1556. * always indicate a snap-in problem, but it frequently does.
  1557. */
  1558. #ifdef DBG
  1559. // ASSERT (!IsModified());
  1560. if (IsModified())
  1561. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after opening"));
  1562. #endif
  1563. return true;
  1564. }
  1565. /*+-------------------------------------------------------------------------*
  1566. * DisplayFileOpenError
  1567. *
  1568. * Displays an error message if we couldn't open a console file.
  1569. *--------------------------------------------------------------------------*/
  1570. int DisplayFileOpenError (SC sc, LPCTSTR pszFilename)
  1571. {
  1572. // if it is any of the known errors, use a friendly string.
  1573. if (sc == SC(STG_E_FILENOTFOUND) || sc == ScFromWin32(ERROR_FILE_NOT_FOUND))
  1574. (sc = ScFromMMC(IDS_FileNotFound));
  1575. else if (sc == ScFromMMC(MMC_E_INVALID_FILE))
  1576. (sc = ScFromMMC(IDS_InvalidVersion));
  1577. else if (sc == SC(STG_E_MEDIUMFULL))
  1578. (sc = ScFromMMC(IDS_DiskFull));
  1579. else
  1580. {
  1581. CString strError;
  1582. AfxFormatString1(strError, IDS_UnableToOpenDocumentMessage, pszFilename);
  1583. return (MMCErrorBox(strError));
  1584. }
  1585. return (MMCErrorBox(sc));
  1586. }
  1587. /*+-------------------------------------------------------------------------*
  1588. * ScGetFileProperties
  1589. *
  1590. * Returns the read-only state of the given file, as well as the creation,
  1591. * last access, and last write times (all optional).
  1592. *
  1593. * We determine if the file is read-only by trying to open the file for
  1594. * writing rather than checking for FILE_ATTRIBUTE_READONLY. We do this
  1595. * because it will catch more read-only conditions, like the file living
  1596. * on a read-only share or NTFS permissions preventing a write.
  1597. *--------------------------------------------------------------------------*/
  1598. static SC ScGetFileProperties (
  1599. LPCTSTR lpszPathName, /* I:name of file to check */
  1600. bool* pfReadOnly, /* O:is file read-only? */
  1601. FILETIME* pftCreate, /* O:creation time (optional) */
  1602. FILETIME* pftLastAccess, /* O:last access time (optional) */
  1603. FILETIME* pftLastWrite) /* O:last write time (optional) */
  1604. {
  1605. DECLARE_SC (sc, _T("ScGetFileProperties"));
  1606. /*
  1607. * validate inputs (pftCreate, pftLastAccess, and pftLastWrite are optional)
  1608. */
  1609. sc = ScCheckPointers (lpszPathName, pfReadOnly);
  1610. if (sc)
  1611. return (sc);
  1612. /*
  1613. * try to open the file for write; if we can't, the file is read-only
  1614. */
  1615. HANDLE hFile = CreateFile (lpszPathName, GENERIC_WRITE, 0, NULL,
  1616. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1617. *pfReadOnly = (hFile == INVALID_HANDLE_VALUE);
  1618. /*
  1619. * if read-only then open in read mode so we'll have a handle to pass
  1620. * to GetFileTime
  1621. */
  1622. if (hFile == INVALID_HANDLE_VALUE)
  1623. {
  1624. hFile = CreateFile (lpszPathName, 0, 0, NULL,
  1625. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1626. if (hFile == INVALID_HANDLE_VALUE)
  1627. {
  1628. sc.FromLastError();
  1629. return (sc);
  1630. }
  1631. }
  1632. /*
  1633. * get the timestamps on the file
  1634. */
  1635. if (!GetFileTime (hFile, pftCreate, pftLastAccess, pftLastWrite))
  1636. sc.FromLastError();
  1637. CloseHandle (hFile);
  1638. return (sc);
  1639. }
  1640. /*+-------------------------------------------------------------------------*
  1641. *
  1642. * CAMCDoc::ScOnOpenDocument
  1643. *
  1644. * PURPOSE: Opens the specified document.
  1645. *
  1646. * PARAMETERS:
  1647. * LPCTSTR lpszPathName :
  1648. *
  1649. * RETURNS:
  1650. * SC
  1651. *
  1652. *+-------------------------------------------------------------------------*/
  1653. SC
  1654. CAMCDoc::ScOnOpenDocument(LPCTSTR lpszPathName)
  1655. {
  1656. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnOpenDocument"));
  1657. // lock AppEvents until this function is done
  1658. LockComEventInterface(AppEvents);
  1659. #define VIVEKJ
  1660. #ifdef VIVEKJ
  1661. // upgrade the console file to the XML version.
  1662. CConsoleFile consoleFile;
  1663. consoleFile.ScUpgrade(lpszPathName);
  1664. #endif
  1665. USES_CONVERSION;
  1666. // check inputs
  1667. if (lpszPathName == NULL || *lpszPathName == 0)
  1668. return (sc = E_UNEXPECTED);
  1669. if (IsModified())
  1670. {
  1671. TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
  1672. }
  1673. if (!AssertNodeManagerIsInitialized())
  1674. return (sc = E_UNEXPECTED);
  1675. /*
  1676. * get the times for the file, as well as its read-only state
  1677. */
  1678. HELPDOCINFO* phdi = GetHelpDocInfo();
  1679. sc = ScCheckPointers (phdi, E_UNEXPECTED);
  1680. if (sc)
  1681. return (sc);
  1682. bool fReadOnly;
  1683. sc = ScGetFileProperties (lpszPathName, &fReadOnly,
  1684. &phdi->m_ftimeCreate, NULL, &phdi->m_ftimeModify);
  1685. if (sc)
  1686. return (sc);
  1687. // load the document using method from the base class (CConsoleFilePersistor)
  1688. bool bXmlBased = false;
  1689. CXMLDocument xmlDocument;
  1690. IStoragePtr spStorage;
  1691. sc = ScLoadConsole(lpszPathName, bXmlBased, xmlDocument, &spStorage);
  1692. if (sc)
  1693. return (sc);
  1694. if ( bXmlBased )
  1695. {
  1696. // load as XML document
  1697. sc = ScLoadFromDocument(xmlDocument);
  1698. if(sc)
  1699. return sc;
  1700. }
  1701. else
  1702. {
  1703. sc = ScCheckPointers(m_spScopeTree, E_UNEXPECTED);
  1704. if (sc)
  1705. return sc;
  1706. // get the console file's version
  1707. ASSERT (sizeof(m_ConsoleData.m_eFileVer) == sizeof(int));
  1708. sc = m_spScopeTree->GetFileVersion(spStorage, (int*)&m_ConsoleData.m_eFileVer);
  1709. if (sc)
  1710. return sc;
  1711. /*
  1712. * check to see if this file is from a newer MMC
  1713. */
  1714. if (m_ConsoleData.m_eFileVer > FileVer_Current)
  1715. {
  1716. ShowIncompatibleFileMessage (lpszPathName, m_ConsoleData.m_eFileVer);
  1717. return (sc = E_UNEXPECTED);
  1718. }
  1719. // Previous storage should have been closed and released
  1720. ASSERT(m_spStorage == NULL);
  1721. /*
  1722. * Load the string table.
  1723. */
  1724. if (!LoadStringTable (spStorage))
  1725. return (sc = E_UNEXPECTED);
  1726. // Load column settings.
  1727. do
  1728. {
  1729. IStreamPtr spStream;
  1730. sc = OpenDebugStream (spStorage, AMCColumnDataStreamName,
  1731. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1732. &spStream);
  1733. if(sc)
  1734. break;
  1735. if (NULL != m_ConsoleData.m_spPersistStreamColumnData)
  1736. sc = m_ConsoleData.m_spPersistStreamColumnData->Load(spStream);
  1737. ASSERT(NULL != m_ConsoleData.m_spPersistStreamColumnData);
  1738. if (sc.IsError() || (NULL == m_ConsoleData.m_spPersistStreamColumnData) )
  1739. return (sc = E_UNEXPECTED);
  1740. } while ( FALSE );
  1741. // Load view settings.
  1742. do
  1743. {
  1744. IStreamPtr spStream;
  1745. sc = OpenDebugStream (spStorage, AMCViewSettingDataStreamName,
  1746. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1747. &spStream);
  1748. if (sc)
  1749. break;
  1750. IPersistStreamPtr spIPeristStreamViewSettings;
  1751. SC sc = ScGetViewSettingsPersistorStream(&spIPeristStreamViewSettings);
  1752. if (sc)
  1753. break;
  1754. sc = ScCheckPointers(spIPeristStreamViewSettings, E_UNEXPECTED);
  1755. if (sc)
  1756. break;
  1757. sc = spIPeristStreamViewSettings->Load(spStream);
  1758. if (sc)
  1759. break;
  1760. } while ( FALSE );
  1761. // Load the tree
  1762. sc = m_spScopeTreePersist->Load(spStorage);
  1763. if (sc)
  1764. {
  1765. ReleaseNodeManager();
  1766. return sc;
  1767. }
  1768. // Save the new storage
  1769. m_spStorage = spStorage;
  1770. /*
  1771. * make sure the tree expansion happens synchronously
  1772. */
  1773. bool fSyncExpandWasRequired = m_spScopeTree->IsSynchronousExpansionRequired() == S_OK;
  1774. m_spScopeTree->RequireSynchronousExpansion (true);
  1775. // Load the favorites data before loading views and frames,
  1776. // so that when frame/view is created the favorite data is ready.
  1777. if (!LoadFavorites())
  1778. {
  1779. // bhanlon ReleaseNodeManager();
  1780. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1781. return (sc = E_UNEXPECTED);
  1782. }
  1783. /*
  1784. * Load string table, custom data, views and frame. Load the
  1785. * custom data (including the icon) before loading the views so
  1786. * the proper icon will be used for the views as they're created.
  1787. */
  1788. /*
  1789. * The LoadAppMode, LoadViews and LoadFrame should be called in that
  1790. * order due to following reason.
  1791. * LoadAppMode reads mode from frame-data and saves it in CAMCApp.
  1792. * The mode is used during LoadViews (in CAMCView::Load) to set the view.
  1793. * LoadFrame again reads the frame-data and calls CAMCApp::UpdateFrameWindow
  1794. * to set toolbar/menus according to the mode.
  1795. */
  1796. if (!LoadCustomData (m_spStorage) || !LoadAppMode() || !LoadViews() || !LoadFrame())
  1797. {
  1798. // bhanlon ReleaseNodeManager();
  1799. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1800. return (sc = E_UNEXPECTED);
  1801. }
  1802. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1803. }
  1804. SetModifiedFlag (false);
  1805. SetFrameModifiedFlag (false);
  1806. SetPhysicalReadOnlyFlag (fReadOnly);
  1807. ASSERT (IsValidFileVersion (m_ConsoleData.m_eFileVer));
  1808. return sc;
  1809. }
  1810. /*+-------------------------------------------------------------------------*
  1811. * CAMCDoc::OnSaveDocument
  1812. *
  1813. * WM_SAVEDOCUMENT handler for CAMCDoc.
  1814. *--------------------------------------------------------------------------*/
  1815. BOOL CAMCDoc::OnSaveDocument(LPCTSTR lpszFilename)
  1816. {
  1817. DECLARE_SC(sc, _T("CAMCDoc::OnSaveDocument"));
  1818. USES_CONVERSION;
  1819. m_eSaveStatus = eStat_Succeeded;
  1820. // Check for a valid filename
  1821. ASSERT(lpszFilename != NULL && *lpszFilename != 0);
  1822. if (lpszFilename == NULL || *lpszFilename == 0)
  1823. {
  1824. return UnableToSaveDocument();
  1825. }
  1826. // Ask the each view to save any data into its data
  1827. // structures (memory) before calling IPersist*::Save.
  1828. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1829. while (pos != NULL)
  1830. {
  1831. CAMCView* const pAMCView = GetNextAMCView(pos);
  1832. sc = ScCheckPointers(pAMCView, E_UNEXPECTED);
  1833. if (sc)
  1834. return UnableToSaveDocument();
  1835. }
  1836. if (!IsCurrentFileVersion (m_ConsoleData.m_eFileVer))
  1837. {
  1838. // If we've arrived at this point then the user is attempting to save the file
  1839. // from an old format into a new one and we will check to see if the user really
  1840. // wants to do this.
  1841. CString strMessage;
  1842. LPCTSTR pszPathName = m_strPathName;
  1843. // A YES/NO/(CANCEL) dialog asking if the user wants to save the file in the new format
  1844. int nResult;
  1845. /*
  1846. * Bug 277586: we don't ever want non-authors to see this dialog
  1847. */
  1848. if (AMCGetApp()->GetMode() != eMode_Author)
  1849. {
  1850. // non-authors are only saving console settings,
  1851. // which are always in the current version
  1852. // no need to ask for conversion - original console is not converted anyway.
  1853. nResult = IDYES;
  1854. }
  1855. else if (IsExplicitSave())
  1856. {
  1857. // 2 button YES/NO dialog appears if this is an explicit save
  1858. tstring strVersion = GetCurrentFileVersionAsString();
  1859. FormatString2 (strMessage, IDS_CONVERT_FILE_FORMAT,
  1860. pszPathName, strVersion.c_str());
  1861. nResult = MMCMessageBox (strMessage, MB_YESNO | MB_DEFBUTTON2);
  1862. }
  1863. else
  1864. {
  1865. // 3 button YES/NO/CANCEL appears if this dialog appears when the program
  1866. // prompts to save changes when the user closes the document
  1867. tstring strVersion = GetCurrentFileVersionAsString();
  1868. FormatString2 (strMessage, IDS_CONVERT_FILE_FORMAT_CLOSE,
  1869. pszPathName, strVersion.c_str());
  1870. nResult = MMCMessageBox (strMessage, MB_YESNOCANCEL | MB_DEFBUTTON3);
  1871. }
  1872. // If we cancel out
  1873. if ((nResult == IDCANCEL) || ((nResult == IDNO) && IsExplicitSave()))
  1874. {
  1875. // Must set this variable otherwise MMC will delete the file
  1876. m_eSaveStatus = eStat_Cancelled;
  1877. return (false);
  1878. }
  1879. // If this will result in us exiting without saving
  1880. if ((nResult == IDNO) && !IsExplicitSave())
  1881. return (true);
  1882. }
  1883. // if we have more than one view, and we'll force SDI in user mode, prompt
  1884. if ((GetNumberOfPersistedViews() > 1) &&
  1885. (m_ConsoleData.m_eConsoleMode == eMode_User_SDI) &&
  1886. (AMCGetApp()->GetMode() == eMode_Author))
  1887. {
  1888. switch (MMCMessageBox (IDS_FORCE_SDI_PROMPT, MB_YESNOCANCEL))
  1889. {
  1890. case IDYES:
  1891. /* do nothing */
  1892. break;
  1893. case IDNO:
  1894. m_ConsoleData.m_eConsoleMode = eMode_User_MDI;
  1895. break;
  1896. case IDCANCEL:
  1897. m_eSaveStatus = eStat_Cancelled;
  1898. return (false);
  1899. }
  1900. }
  1901. // save contents to xml document
  1902. CXMLDocument xmlDocument;
  1903. sc = ScSaveToDocument( xmlDocument );
  1904. if (sc)
  1905. return UnableToSaveDocument();
  1906. // save xml document to file
  1907. bool bAuthor = (AMCGetApp()->GetMode() == eMode_Author);
  1908. sc = ScSaveConsole( lpszFilename, bAuthor, xmlDocument);
  1909. if (sc)
  1910. return UnableToSaveDocument();
  1911. SetModifiedFlag (false);
  1912. SetFrameModifiedFlag (false);
  1913. /*
  1914. * We shouldn't think that a freshly saved console file is
  1915. * dirty. If we do, someone's dirty bit processing is bogus.
  1916. */
  1917. ASSERT (!IsFrameModified());
  1918. /*
  1919. * Too many snap-ins leave themselves dirty after a load to leave this
  1920. * assert in, so we'll trace instead. Note that this trace doesn't
  1921. * always indicate a snap-in problem, but it frequently does.
  1922. */
  1923. #ifdef DBG
  1924. // ASSERT (!IsModified());
  1925. if (IsModified())
  1926. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after saving"));
  1927. #endif
  1928. // if a save was just done, this can't be read-only
  1929. // NOTE: if MMC adds support for "Save Copy As" we have
  1930. // to determine whether a "Save As" or "Save Copy As"
  1931. // was done before clearing the read-only status
  1932. SetPhysicalReadOnlyFlag (false);
  1933. m_ConsoleData.m_eFileVer = FileVer_Current;
  1934. // Show admin tools on start menu if necessary
  1935. ShowAdminToolsOnMenu(lpszFilename);
  1936. return TRUE;
  1937. }
  1938. int CAMCDoc::GetNumberOfViews()
  1939. {
  1940. TRACE_METHOD(CAMCDoc, GetNumberOfViews);
  1941. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1942. int count = 0;
  1943. while (pos != NULL)
  1944. {
  1945. GetNextAMCView(pos);
  1946. VERIFY (++count);
  1947. }
  1948. return (count);
  1949. }
  1950. int CAMCDoc::GetNumberOfPersistedViews()
  1951. {
  1952. unsigned short cPersistedViews = 0;
  1953. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1954. while (pos != NULL)
  1955. {
  1956. CAMCView* v = GetNextAMCView(pos);
  1957. if (v && v->IsPersisted())
  1958. ++cPersistedViews;
  1959. }
  1960. return (cPersistedViews);
  1961. }
  1962. CAMCView* CAMCDoc::CreateNewView(bool fVisible, bool bEmitScriptEvents /*= true*/)
  1963. {
  1964. DECLARE_SC(sc, TEXT("CAMCDoc::CreateNewView"));
  1965. TRACE_FUNCTION(CAMCDoc::CreateNewView);
  1966. CDocTemplate* pTemplate = GetDocTemplate();
  1967. ASSERT(pTemplate != NULL);
  1968. CChildFrame* pFrame = (CChildFrame*) pTemplate->CreateNewFrame(this, NULL);
  1969. ASSERT_KINDOF (CChildFrame, pFrame);
  1970. if (pFrame == NULL)
  1971. {
  1972. TRACE(_T("Warning: failed to create new frame.\n"));
  1973. return NULL; // command failed
  1974. }
  1975. bool fOldCreateVisibleState;
  1976. /*
  1977. * If we're going to create the frame invisibly, set a flag in the frame.
  1978. * When this flag is set, the frame will show itself with the
  1979. * SW_SHOWMINNOACTIVE flag instead of the default flag. Doing this will
  1980. * avoid the side effect of restoring the currently active child frame
  1981. * if it is maximized at the time the new frame is created invisibly.
  1982. */
  1983. // The SW_SHOWMINNOACTIVE was changed to SW_SHOWNOACTIVATE.
  1984. // It does preserve the active window from mentioned side effect,
  1985. // plus it also allows scripts (using Object Moded) to create invisible views,
  1986. // position and then show them as normal (not minimized) windows,
  1987. // thus providing same result as creating visible and then hiding the view.
  1988. // While minimized window must be restored first in order to change their position.
  1989. if (!fVisible)
  1990. {
  1991. fOldCreateVisibleState = pFrame->SetCreateVisible (false);
  1992. }
  1993. /*
  1994. * update the frame as if it is to be visible; we'll hide the frame
  1995. * later if necessary
  1996. */
  1997. // setting visibility to 'true' is required option for MFC to pass control
  1998. // to OnInitialUpdate of child windows.
  1999. pTemplate->InitialUpdateFrame (pFrame, this, true /*fVisible*/);
  2000. if (fVisible)
  2001. {
  2002. // Force drawing of frame and view windows now in case a slow OCX in the result
  2003. // pane delays the initial window update
  2004. pFrame->RedrawWindow();
  2005. }
  2006. else
  2007. {
  2008. pFrame->SetCreateVisible (fOldCreateVisibleState);
  2009. pFrame->ShowWindow (SW_HIDE);
  2010. /*
  2011. * InitialUpdateFrame will update the frame counts. When it executes
  2012. * the new, to-be-invisible frame will be visible, so it'll be included
  2013. * in the count. If the new window is the second frame, then the first
  2014. * frame will have "1:" prepended to its title. This is ugly, so we'll
  2015. * update the frame counts again after the new frame has been hidden
  2016. * to fix all of the existing frames' titles.
  2017. */
  2018. UpdateFrameCounts();
  2019. }
  2020. CAMCView* const v = pFrame->GetAMCView();
  2021. if (!(MMC_NW_OPTION_NOPERSIST & GetNewWindowOptions()))
  2022. SetModifiedFlag();
  2023. ASSERT(v);
  2024. if (!v)
  2025. return v;
  2026. AddObserver(static_cast<CAMCDocumentObserver&>(*v));
  2027. // fire the event to the script
  2028. if (bEmitScriptEvents)
  2029. {
  2030. CAMCApp* pApp = AMCGetApp();
  2031. // check
  2032. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  2033. if (sc)
  2034. return v;
  2035. // forward
  2036. sc = pApp->ScOnNewView(v);
  2037. if (sc)
  2038. return v;
  2039. }
  2040. return v;
  2041. }
  2042. void DeletePropertyPages(void)
  2043. {
  2044. HWND hWnd = NULL;
  2045. DWORD dwPid = 0; // Process Id
  2046. DWORD dwTid = 0; // Thread Id
  2047. while (TRUE)
  2048. {
  2049. USES_CONVERSION;
  2050. // Note: No need to localize this string
  2051. hWnd = ::FindWindowEx(NULL, hWnd, W2T( DATAWINDOW_CLASS_NAME ), NULL);
  2052. if (hWnd == NULL)
  2053. return; // No more windows
  2054. ASSERT(IsWindow(hWnd));
  2055. // Check if the window belongs to the current process
  2056. dwTid = ::GetWindowThreadProcessId(hWnd, &dwPid);
  2057. if (dwPid != ::GetCurrentProcessId())
  2058. continue;
  2059. DataWindowData* pData = GetDataWindowData (hWnd);
  2060. ASSERT (pData != NULL);
  2061. ASSERT (IsWindow (pData->hDlg));
  2062. if (SendMessage(pData->hDlg, WM_COMMAND, IDCANCEL, 0L) != 0)
  2063. {
  2064. DBG_OUT_LASTERROR;
  2065. }
  2066. // Note: For some reason, the send message stays stuck in the threads
  2067. // msg queue causing the sheet not to dismiss itself. By posting a another
  2068. // message( it could be anything), it kick starts the queue and the send message
  2069. // goes through.
  2070. ::PostMessage(pData->hDlg, WM_COMMAND, IDCANCEL, 0L);
  2071. }
  2072. }
  2073. void CAMCDoc::DeleteContents()
  2074. {
  2075. TRACE_METHOD(CAMCDoc, DeleteContents);
  2076. CDocument::DeleteContents();
  2077. }
  2078. void CAMCDoc::DeleteHelpFile ()
  2079. {
  2080. /*
  2081. * Delete the help file on closing a console file
  2082. */
  2083. // Get a node callback interface
  2084. ASSERT(m_spScopeTree != NULL);
  2085. // If this asserts - the document is in invalid state.
  2086. // Most probably it's because our "Load" procedures did not perform proper
  2087. // cleanup when we failed to load the document
  2088. INodeCallbackPtr spNodeCallback;
  2089. if (m_spScopeTree != NULL)
  2090. {
  2091. m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2092. ASSERT(spNodeCallback != NULL);
  2093. }
  2094. // fill in file name and send the delete request
  2095. if (spNodeCallback != NULL)
  2096. {
  2097. USES_CONVERSION;
  2098. GetHelpDocInfo()->m_pszFileName = T2COLE(GetPathName());
  2099. spNodeCallback->Notify(NULL, NCLBK_DELETEHELPDOC, (LPARAM)GetHelpDocInfo(), NULL);
  2100. }
  2101. }
  2102. void CAMCDoc::OnCloseDocument()
  2103. {
  2104. DECLARE_SC(sc, TEXT("CAMCDoc::OnCloseDocument"));
  2105. TRACE_METHOD(CAMCDoc, OnCloseDocument);
  2106. // Inform nodemgr about doc-closing (should change this to observer object)
  2107. do
  2108. {
  2109. sc = ScCheckPointers(m_spScopeTree, E_UNEXPECTED);
  2110. if (sc)
  2111. break;
  2112. INodeCallbackPtr spNodeCallback;
  2113. sc = m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2114. if (sc)
  2115. break;
  2116. sc = ScCheckPointers(spNodeCallback, E_UNEXPECTED);
  2117. if (sc)
  2118. break;
  2119. sc = spNodeCallback->DocumentClosing();
  2120. if (sc)
  2121. break;
  2122. } while ( FALSE );
  2123. if (sc)
  2124. sc.TraceAndClear();
  2125. CAMCApp* pApp = AMCGetApp();
  2126. // check
  2127. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  2128. if (sc)
  2129. sc.TraceAndClear();
  2130. else
  2131. {
  2132. // forward
  2133. sc = pApp->ScOnCloseDocument(this);
  2134. if (sc)
  2135. sc.TraceAndClear();
  2136. }
  2137. // If we are not instantiated as OLESERVER check for open property sheets.
  2138. if (! pApp->IsMMCRunningAsOLEServer() && FArePropertySheetsOpen(NULL))
  2139. {
  2140. CString strMsg, strTitle;
  2141. if (strMsg.LoadString(IDS_MMCWillCancelPropertySheets) &&
  2142. strTitle.LoadString(IDS_WARNING))
  2143. ::MessageBox(NULL, strMsg, strTitle, MB_OK | MB_ICONWARNING);
  2144. }
  2145. DeletePropertyPages();
  2146. DeleteHelpFile ();
  2147. CDocument::OnCloseDocument();
  2148. }
  2149. BOOL CAMCDoc::SaveModified()
  2150. {
  2151. BOOL fDocModified = IsModified();
  2152. BOOL fFrameModified = IsFrameModified();
  2153. // if the file is not read-only and it is modified
  2154. if (!IsReadOnly() && (fDocModified || fFrameModified))
  2155. {
  2156. int idResponse;
  2157. bool fUserMode = (AMCGetApp()->GetMode() != eMode_Author);
  2158. bool fSaveByUserDecision = false;
  2159. // silent saves for the various flavors of user mode
  2160. if (fUserMode)
  2161. idResponse = IDYES;
  2162. // silent saves if the frame was modified but the document wasn't...
  2163. else if (fFrameModified && !fDocModified)
  2164. {
  2165. /*
  2166. * ...unless the console wasn't modified. This will happen
  2167. * if the user ran MMC without opening an existing console file
  2168. * and then moved the frame window.
  2169. */
  2170. // ...unless the console wasn't modified.
  2171. if (m_strPathName.IsEmpty())
  2172. idResponse = IDNO;
  2173. else
  2174. idResponse = IDYES;
  2175. }
  2176. // otherwise, prompt
  2177. else
  2178. {
  2179. CString prompt;
  2180. FormatString1(prompt, IDS_ASK_TO_SAVE, m_strTitle);
  2181. idResponse = AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_SAVE); // dont change to MMCMessageBox - different signature.
  2182. fSaveByUserDecision = true;
  2183. }
  2184. switch (idResponse)
  2185. {
  2186. case IDCANCEL:
  2187. return FALSE; // don't continue
  2188. case IDYES:
  2189. // If so, either Save or Update, as appropriate
  2190. // (ignore failures in User mode)
  2191. // This save is not explicit and shows up when the user closes a modified
  2192. // document. Set it as such. This will result in a different dialog
  2193. // a few functions in.
  2194. SetExplicitSave(false);
  2195. if (!DoFileSave() && fSaveByUserDecision)
  2196. {
  2197. // Restore to the default explicit save
  2198. SetExplicitSave(true);
  2199. return FALSE; // don't continue
  2200. }
  2201. // Restore to the default explicit save
  2202. SetExplicitSave(true);
  2203. break;
  2204. case IDNO:
  2205. // If not saving changes, revert the document
  2206. break;
  2207. default:
  2208. ASSERT(FALSE);
  2209. break;
  2210. }
  2211. }
  2212. // At this point we are committed to closing, so give each AMCView
  2213. // a chance to do its clean-up work
  2214. CAMCViewPosition pos = GetFirstAMCViewPosition();
  2215. while (pos != NULL)
  2216. {
  2217. CAMCView* const pView = GetNextAMCView(pos);
  2218. if (pView != NULL)
  2219. pView->CloseView();
  2220. }
  2221. return TRUE; // keep going
  2222. }
  2223. #if (_MFC_VER > 0x0600)
  2224. #error CAMCDoc::DoSave was copied from CDocument::DoSave from MFC 6.0.
  2225. #error The MFC version has changed. See if CAMCDoc::DoSave needs to be updated.
  2226. #endif
  2227. BOOL CAMCDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
  2228. // Save the document data to a file
  2229. // lpszPathName = path name where to save document file
  2230. // if lpszPathName is NULL then the user will be prompted (SaveAs)
  2231. // note: lpszPathName can be different than 'm_strPathName'
  2232. // if 'bReplace' is TRUE will change file name if successful (SaveAs)
  2233. // if 'bReplace' is FALSE will not change path name (SaveCopyAs)
  2234. {
  2235. CString newName = lpszPathName;
  2236. if (newName.IsEmpty())
  2237. {
  2238. CDocTemplate* pTemplate = GetDocTemplate();
  2239. ASSERT(pTemplate != NULL);
  2240. newName = m_strPathName;
  2241. if (bReplace && newName.IsEmpty())
  2242. {
  2243. newName = m_strTitle;
  2244. #ifndef _MAC
  2245. // check for dubious filename
  2246. int iBad = newName.FindOneOf(_T(" #%;/\\"));
  2247. #else
  2248. int iBad = newName.FindOneOf(_T(":"));
  2249. #endif
  2250. if (iBad != -1)
  2251. newName.ReleaseBuffer(iBad);
  2252. #ifndef _MAC
  2253. // append the default suffix if there is one
  2254. CString strExt;
  2255. if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&
  2256. !strExt.IsEmpty())
  2257. {
  2258. ASSERT(strExt[0] == '.');
  2259. newName += strExt;
  2260. }
  2261. #endif
  2262. }
  2263. if (!AfxGetApp()->DoPromptFileName(newName,
  2264. bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,
  2265. OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, pTemplate))
  2266. return FALSE; // don't even attempt to save
  2267. }
  2268. CWaitCursor wait;
  2269. if (!OnSaveDocument(newName))
  2270. {
  2271. // This is the modified MMC implementation
  2272. #ifdef MMC_DELETE_EXISTING_FILE // See bug 395006
  2273. if ((lpszPathName == NULL) && (m_eSaveStatus != eStat_Cancelled))
  2274. {
  2275. // be sure to delete the file
  2276. try
  2277. {
  2278. CFile::Remove(newName);
  2279. }
  2280. catch (CException* pe)
  2281. {
  2282. TRACE0("Warning: failed to delete file after failed SaveAs.\n");
  2283. pe->Delete();
  2284. }
  2285. }
  2286. #endif
  2287. return FALSE;
  2288. }
  2289. // if changing the name of the open document
  2290. if (bReplace)
  2291. {
  2292. /*
  2293. * Delete the help file for this console file before
  2294. * changing its name, because the help file can't be
  2295. * located once the old name is lost.
  2296. */
  2297. DeleteHelpFile ();
  2298. // reset the title and change the document name
  2299. SetPathName(newName);
  2300. }
  2301. return TRUE; // success
  2302. }
  2303. BOOL CAMCDoc::IsModified()
  2304. {
  2305. TRACE_METHOD(CAMCDoc, IsModified);
  2306. BOOL const bModified = /*CDocument::IsModified() || */
  2307. (m_spScopeTreePersist != NULL && m_spScopeTreePersist->IsDirty() != S_FALSE);
  2308. if (bModified)
  2309. return TRUE;
  2310. // Loop thru and save each view
  2311. CAMCViewPosition pos = GetFirstAMCViewPosition();
  2312. while (pos != NULL)
  2313. {
  2314. // Get the view and skip if its the active view
  2315. CAMCView* const v = GetNextAMCView(pos);
  2316. if (v && v->IsDirty())
  2317. return TRUE;
  2318. }
  2319. // The views should be asked about dirty before
  2320. // asking the columns.
  2321. if ( (NULL != m_ConsoleData.m_spPersistStreamColumnData) &&
  2322. (S_OK == m_ConsoleData.m_spPersistStreamColumnData->IsDirty()) )
  2323. return TRUE;
  2324. // View data.
  2325. IPersistStreamPtr spIPeristStreamViewSettings;
  2326. SC sc = ScGetViewSettingsPersistorStream(&spIPeristStreamViewSettings);
  2327. if ( (! sc.IsError()) &&
  2328. (spIPeristStreamViewSettings != NULL) )
  2329. {
  2330. sc = spIPeristStreamViewSettings->IsDirty();
  2331. if (sc == S_OK)
  2332. return TRUE;
  2333. sc.TraceAndClear();
  2334. }
  2335. return CDocument::IsModified();
  2336. }
  2337. void CAMCDoc::OnUpdateFileSave(CCmdUI* pCmdUI)
  2338. {
  2339. pCmdUI->Enable (!IsReadOnly());
  2340. }
  2341. void CAMCDoc::OnConsoleAddremovesnapin()
  2342. {
  2343. ASSERT(m_spScopeTree != NULL);
  2344. // Can't run snap-in manager with active property sheets
  2345. CString strMsg;
  2346. LoadString(strMsg, IDS_SNAPINMGR_CLOSEPROPSHEET);
  2347. if (FArePropertySheetsOpen(&strMsg))
  2348. return;
  2349. m_spScopeTree->RunSnapIn(AfxGetMainWnd()->m_hWnd);
  2350. ::CoFreeUnusedLibraries();
  2351. }
  2352. void CAMCDoc::OnUpdateConsoleAddremovesnapin(CCmdUI* pCmdUI)
  2353. {
  2354. pCmdUI->Enable (m_spScopeTree != NULL);
  2355. }
  2356. /*--------------------------------------------------------------------------*
  2357. * CAMCDoc::SetMode
  2358. *
  2359. *
  2360. *--------------------------------------------------------------------------*/
  2361. void CAMCDoc::SetMode (ProgramMode eMode)
  2362. {
  2363. /*
  2364. * only set the modified flag if something actually changed
  2365. */
  2366. if (m_ConsoleData.m_eConsoleMode != eMode)
  2367. {
  2368. // should only be able to get here in author mode
  2369. ASSERT (AMCGetApp()->GetMode() == eMode_Author);
  2370. ASSERT (IsValidProgramMode (eMode));
  2371. m_ConsoleData.m_eConsoleMode = eMode;
  2372. SetModifiedFlag ();
  2373. }
  2374. }
  2375. /*+-------------------------------------------------------------------------*
  2376. * CAMCDoc::SetConsoleFlag
  2377. *
  2378. *
  2379. *--------------------------------------------------------------------------*/
  2380. void CAMCDoc::SetConsoleFlag (ConsoleFlags eFlag, bool fSet)
  2381. {
  2382. DWORD dwFlags = m_ConsoleData.m_dwFlags;
  2383. if (fSet)
  2384. dwFlags |= eFlag;
  2385. else
  2386. dwFlags &= ~eFlag;
  2387. /*
  2388. * only set the modified flag if something actually changed
  2389. */
  2390. if (m_ConsoleData.m_dwFlags != dwFlags)
  2391. {
  2392. m_ConsoleData.m_dwFlags = dwFlags;
  2393. SetModifiedFlag ();
  2394. }
  2395. }
  2396. /*+-------------------------------------------------------------------------*
  2397. *
  2398. * mappedModes
  2399. *
  2400. * PURPOSE: provides map to be used when persisting ProgramMode enumeration
  2401. *
  2402. * NOTE: do not remove/ change items unless you're sure no console
  2403. * files will be broken
  2404. *
  2405. *+-------------------------------------------------------------------------*/
  2406. static const EnumLiteral mappedModes[] =
  2407. {
  2408. { eMode_Author, XML_ENUM_PROGRAM_MODE_AUTHOR } ,
  2409. { eMode_User, XML_ENUM_PROGRAM_MODE_USER } ,
  2410. { eMode_User_MDI, XML_ENUM_PROGRAM_MODE_USER_MDI } ,
  2411. { eMode_User_SDI, XML_ENUM_PROGRAM_MODE_USER_SDI } ,
  2412. };
  2413. /*+-------------------------------------------------------------------------*
  2414. *
  2415. * CAMCDoc::Persist
  2416. *
  2417. * PURPOSE:
  2418. *
  2419. * PARAMETERS:
  2420. * CPersistor& persistor :
  2421. *
  2422. * RETURNS:
  2423. * void
  2424. *
  2425. *+-------------------------------------------------------------------------*/
  2426. void CAMCDoc::Persist(CPersistor& persistor)
  2427. {
  2428. DECLARE_SC (sc, _T("CAMCDoc::Persist"));
  2429. CAMCApp* pApp = AMCGetApp();
  2430. // check required pointers before going any further
  2431. sc = ScCheckPointers(m_spStringTable ? pApp : NULL, // + workaround to check more pointers
  2432. m_ConsoleData.m_pXMLPersistColumnData,
  2433. m_spScopeTree ? GetFavorites() : NULL, // + same workaround ^
  2434. E_POINTER);
  2435. if (sc)
  2436. sc.Throw();
  2437. // persist version of the document
  2438. CStr strFileVer = 0.;
  2439. if (persistor.IsStoring())
  2440. {
  2441. strFileVer = GetCurrentFileVersionAsString().c_str();
  2442. GUID guidConsoleId;
  2443. sc = CoCreateGuid(&guidConsoleId);
  2444. if (sc)
  2445. sc.Throw();
  2446. // this parameter is also updated in IDocConfig implementation
  2447. // update that code when changing following lines
  2448. CPersistor persistorGuid(persistor, XML_TAG_CONSOLE_FILE_UID);
  2449. persistorGuid.PersistContents(guidConsoleId);
  2450. }
  2451. persistor.PersistAttribute(XML_ATTR_CONSOLE_VERSION, strFileVer);
  2452. if (persistor.IsLoading())
  2453. {
  2454. // 'decode' the version
  2455. LPCTSTR pstrStart = strFileVer;
  2456. LPTSTR pstrStop = const_cast<LPTSTR>(pstrStart);
  2457. UINT uiMajorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2458. UINT uiMinorVer = 0;
  2459. if (pstrStop != pstrStart && *pstrStop == '.')
  2460. {
  2461. pstrStart = pstrStop + 1;
  2462. uiMinorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2463. }
  2464. UINT uiMinorSubVer = 0;
  2465. if (pstrStop != pstrStart && *pstrStop == '.')
  2466. {
  2467. pstrStart = pstrStop + 1;
  2468. uiMinorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2469. }
  2470. ConsoleFileVersion eVersion = (ConsoleFileVersion)MakeConsoleFileVer_(uiMajorVer,
  2471. uiMinorVer,
  2472. uiMinorSubVer);
  2473. m_ConsoleData.m_eFileVer = eVersion;
  2474. // BUGBUG: this needs to be changed when we implement 'dynamic' SC messages
  2475. if (eVersion != FileVer_Current)
  2476. sc.Throw(E_UNEXPECTED);
  2477. }
  2478. // Create a storage for binaries
  2479. // This will create "detached" XML element which may be used by persistor's
  2480. // childs to store binary informatio.
  2481. // (The element is attached to XML document by calling "CommitBinaryStorage()" )
  2482. if (persistor.IsStoring())
  2483. persistor.GetDocument().CreateBinaryStorage();
  2484. else
  2485. persistor.GetDocument().LocateBinaryStorage();
  2486. /*
  2487. * make sure the tree expansion happens synchronously
  2488. */
  2489. bool fSyncExpandWasRequired = m_spScopeTree->IsSynchronousExpansionRequired() == S_OK;
  2490. m_spScopeTree->RequireSynchronousExpansion (true);
  2491. // historically both loading and saving is to be done in certain order
  2492. // steps are ordered by storing order
  2493. const int STEP_FRAME = 1;
  2494. const int STEP_VIEWS = 2;
  2495. const int STEP_APP_MODE = 3;
  2496. const int STEP_CUST_DATA = 4;
  2497. const int STEP_FAVORITES = 5;
  2498. const int STEP_SCOPE_TREE = 6;
  2499. const int STEP_VIEW_DATA = 7;
  2500. const int STEP_COLUMN_DATA = 8;
  2501. const int STEP_STRING_TABLE = 9;
  2502. const int MIN_STEP = 1;
  2503. const int MAX_STEP = 9;
  2504. for (int iStep = persistor.IsStoring() ? MIN_STEP : MAX_STEP;
  2505. persistor.IsStoring() ? (iStep <= MAX_STEP) : (iStep >= MIN_STEP);
  2506. persistor.IsStoring() ? ++iStep : --iStep
  2507. )
  2508. {
  2509. switch(iStep)
  2510. {
  2511. case STEP_FRAME:
  2512. PersistFrame(persistor);
  2513. break;
  2514. case STEP_VIEWS:
  2515. PersistViews(persistor);
  2516. break;
  2517. case STEP_APP_MODE:
  2518. if (persistor.IsLoading())
  2519. {
  2520. // restore proper application mode
  2521. ProgramMode eMode;
  2522. // create wrapper to persist enumeration values as strings
  2523. CXMLEnumeration modeValuePersistor(eMode, mappedModes, countof(mappedModes));
  2524. // persist the wrapper
  2525. persistor.PersistAttribute(XML_ATTR_APPLICATION_MODE, modeValuePersistor);
  2526. pApp->SetMode(eMode);
  2527. }
  2528. break;
  2529. case STEP_CUST_DATA:
  2530. PersistCustomData (persistor);
  2531. break;
  2532. case STEP_FAVORITES:
  2533. persistor.Persist(*GetFavorites());
  2534. break;
  2535. case STEP_SCOPE_TREE:
  2536. // IDocConfig relies on tree to be under the document.
  2537. // revisit that code if you do the change here
  2538. sc = m_spScopeTree->Persist(reinterpret_cast<HPERSISTOR>(&persistor));
  2539. if (sc)
  2540. sc.Throw();
  2541. break;
  2542. case STEP_VIEW_DATA:
  2543. {
  2544. INodeCallbackPtr spNodeCallback;
  2545. sc = m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2546. if (sc)
  2547. sc.Throw();
  2548. sc = ScCheckPointers(spNodeCallback, E_UNEXPECTED);
  2549. if (sc)
  2550. sc.Throw();
  2551. CXMLObject *pXMLViewSettings = NULL;
  2552. sc = spNodeCallback->QueryViewSettingsPersistor(&pXMLViewSettings);
  2553. if (sc)
  2554. sc.Throw();
  2555. sc = ScCheckPointers(pXMLViewSettings, E_UNEXPECTED);
  2556. if (sc)
  2557. sc.Throw();
  2558. persistor.Persist(*pXMLViewSettings);
  2559. }
  2560. break;
  2561. case STEP_COLUMN_DATA:
  2562. persistor.Persist(*m_ConsoleData.m_pXMLPersistColumnData);
  2563. break;
  2564. case STEP_STRING_TABLE:
  2565. CMasterStringTable *pMasterStringTable = dynamic_cast<CMasterStringTable *>((IStringTablePrivate *)m_spStringTable);
  2566. if(!pMasterStringTable)
  2567. {
  2568. sc = E_UNEXPECTED;
  2569. sc.Throw();
  2570. }
  2571. persistor.Persist(*pMasterStringTable);
  2572. break;
  2573. }
  2574. }
  2575. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  2576. SetModifiedFlag (false);
  2577. SetFrameModifiedFlag (false);
  2578. /*
  2579. * We shouldn't think that a freshly saved console file is
  2580. * dirty. If we do, someone's dirty bit processing is bogus.
  2581. */
  2582. ASSERT (!IsFrameModified());
  2583. /*
  2584. * Too many snap-ins leave themselves dirty after a load to leave this
  2585. * assert in, so we'll trace instead. Note that this trace doesn't
  2586. * always indicate a snap-in problem, but it frequently does.
  2587. */
  2588. #ifdef DBG
  2589. // ASSERT (!IsModified());
  2590. if (IsModified())
  2591. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after %s"),
  2592. persistor.IsLoading() ? _T("opening") : _T("saving"));
  2593. #endif
  2594. // The element used to gather binary information is attached to XML document here
  2595. // Physically it will reside after all elements already added to persistor
  2596. if (persistor.IsStoring())
  2597. persistor.GetDocument().CommitBinaryStorage();
  2598. }
  2599. //***************************************************************************
  2600. // CScopedBool
  2601. //
  2602. //
  2603. // PURPOSE: Owns a bool. The bool is set to false in the constructor and true
  2604. // in the destructor.
  2605. //
  2606. //****************************************************************************
  2607. class CScopedBool
  2608. {
  2609. bool & m_bool;
  2610. public:
  2611. CScopedBool (bool &b) : m_bool(b)
  2612. {
  2613. b= false;
  2614. }
  2615. ~CScopedBool()
  2616. {
  2617. m_bool = true;
  2618. }
  2619. };
  2620. void CAMCDoc::PersistViews(CPersistor& persistor)
  2621. {
  2622. DECLARE_SC(sc, TEXT("CAMCDoc::PersistViews"));
  2623. CScopedBool scopedBool(m_bCanCloseViews); // lock the views from being deleted during the persist operation.
  2624. if (persistor.IsLoading())
  2625. {
  2626. // Read templates for new views
  2627. CViewTemplateList view_list(XML_TAG_VIEW_LIST);
  2628. persistor.Persist(view_list);
  2629. // Get the means for enumerating loaded collection
  2630. CViewTemplateList::List_Type &rList = view_list.GetList();
  2631. CViewTemplateList::List_Type::iterator it;
  2632. // Enumerate all the views to be created
  2633. // Create them one-by-one
  2634. for (it = rList.begin(); it != rList.end(); ++it)
  2635. {
  2636. // extract information for the new view
  2637. int iViewID = it->first;
  2638. const CBookmark& pbm = it->second.first;
  2639. CPersistor& v_persistor = it->second.second;
  2640. // create it!
  2641. sc = ScCreateAndLoadView(v_persistor, iViewID, pbm);
  2642. if (sc)
  2643. sc.Throw();
  2644. }
  2645. }
  2646. else // if (persistor.IsStoring())
  2647. {
  2648. CPersistor persistorViews(persistor, XML_TAG_VIEW_LIST);
  2649. /*
  2650. * Bug 3504: enumerate views in z-order (bottom-to-top) so the
  2651. * z-order will be restored correctly on reload
  2652. */
  2653. CMainFrame* pMainFrame = AMCGetMainWnd();
  2654. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  2655. if (sc)
  2656. sc.Throw();
  2657. /*
  2658. * get the top-most MDI child
  2659. */
  2660. CWnd* pwndMDIChild = pMainFrame->MDIGetActive();
  2661. sc = ScCheckPointers (pwndMDIChild, E_UNEXPECTED);
  2662. if (sc)
  2663. sc.Throw();
  2664. /*
  2665. * iterate through each of the MDI children
  2666. */
  2667. for (pwndMDIChild = pwndMDIChild->GetWindow (GW_HWNDLAST);
  2668. pwndMDIChild != NULL;
  2669. pwndMDIChild = pwndMDIChild->GetNextWindow (GW_HWNDPREV))
  2670. {
  2671. /*
  2672. * turn the generic CMDIChildWnd into a CChildFrame
  2673. */
  2674. CChildFrame* pChildFrame = dynamic_cast<CChildFrame*>(pwndMDIChild);
  2675. sc = ScCheckPointers (pChildFrame, E_UNEXPECTED);
  2676. if (sc)
  2677. sc.Throw();
  2678. /*
  2679. * get the view for this child frame
  2680. */
  2681. CAMCView* pwndView = pChildFrame->GetAMCView();
  2682. sc = ScCheckPointers (pwndView, E_UNEXPECTED);
  2683. if (sc)
  2684. sc.Throw();
  2685. // skip those not persistible
  2686. if ( !pwndView->IsPersisted() )
  2687. continue;
  2688. /*
  2689. * persist the view
  2690. */
  2691. persistorViews.Persist (*pwndView);
  2692. }
  2693. }
  2694. }
  2695. void CAMCDoc::PersistFrame(CPersistor& persistor)
  2696. {
  2697. DECLARE_SC(sc, TEXT("CAMCDoc::PersistFrame"));
  2698. CFrameState fs2 (m_ConsoleData.m_eConsoleMode, m_ConsoleData.m_dwFlags);
  2699. ASSERT (fs2.wndplFrame.length == sizeof (WINDOWPLACEMENT));
  2700. CMainFrame* pMainFrame = AMCGetMainWnd();
  2701. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  2702. if (sc)
  2703. sc.Throw();
  2704. if (persistor.IsStoring())
  2705. {
  2706. // Get the attributes of the window.
  2707. if (!pMainFrame->GetWindowPlacement (&fs2.wndplFrame))
  2708. sc.Throw(E_FAIL);
  2709. if (fs2.wndplFrame.showCmd == SW_SHOWMINIMIZED)
  2710. fs2.wndplFrame.showCmd = SW_SHOWNORMAL;
  2711. }
  2712. persistor.Persist(fs2);
  2713. // this application setting (AppMode) is resored in AMCDoc::Persist, but saved/loaded here
  2714. // create wrapper to persist enumeration values as strings
  2715. CXMLEnumeration modeValuePersistor(m_ConsoleData.m_eConsoleMode, mappedModes, countof(mappedModes));
  2716. // persist the wrapper
  2717. persistor.PersistAttribute(XML_ATTR_APPLICATION_MODE, modeValuePersistor);
  2718. if (persistor.IsLoading())
  2719. {
  2720. // Set the windows size and location and state
  2721. CAMCApp* pApp = AMCGetApp();
  2722. pApp->UpdateFrameWindow(true);
  2723. pMainFrame->UpdateChildSystemMenus();
  2724. // the status bar is on the child frame now
  2725. // pMainFrame->ShowStatusBar ((fs2.dwFlags & eFlag_ShowStatusBar) != 0);
  2726. // save the data from the file into the console data
  2727. m_ConsoleData.m_eAppMode = pApp->GetMode();
  2728. m_ConsoleData.m_dwFlags = fs2.dwFlags;
  2729. InsurePlacementIsOnScreen (fs2.wndplFrame);
  2730. // if we're initializing, defer the actual show until initialization is complete
  2731. // same if script is under control and MMC is hidden
  2732. if (pApp->IsInitializing()
  2733. || ( !pApp->IsUnderUserControl() && !pMainFrame->IsWindowVisible() ) )
  2734. {
  2735. pApp->m_nCmdShow = fs2.wndplFrame.showCmd;
  2736. fs2.wndplFrame.showCmd = SW_HIDE;
  2737. }
  2738. if (!pMainFrame->SetWindowPlacement (&fs2.wndplFrame))
  2739. sc.Throw(E_FAIL);
  2740. }
  2741. }
  2742. /*--------------------------------------------------------------------------*
  2743. * CDocument::DoFileSave
  2744. *
  2745. * This is almost identical to CDocument::DoFileSave. We just override it
  2746. * here because we want to display a message for a read-only file before
  2747. * throwing up the Save As dialog.
  2748. *--------------------------------------------------------------------------*/
  2749. BOOL CAMCDoc::DoFileSave()
  2750. {
  2751. DWORD dwAttrib = GetFileAttributes(m_strPathName);
  2752. // attributes does not matter for user modes - it does not
  2753. // save to the original console file anyway
  2754. if ((AMCGetApp()->GetMode() == eMode_Author) &&
  2755. (dwAttrib != 0xFFFFFFFF) &&
  2756. (dwAttrib & FILE_ATTRIBUTE_READONLY))
  2757. {
  2758. CString strMessage;
  2759. FormatString1 (strMessage, IDS_CONSOLE_READONLY, m_strPathName);
  2760. MMCMessageBox (strMessage);
  2761. // we do not have read-write access or the file does not (now) exist
  2762. if (!DoSave(NULL))
  2763. {
  2764. TRACE0("Warning: File save with new name failed.\n");
  2765. return FALSE;
  2766. }
  2767. }
  2768. else
  2769. {
  2770. if (!DoSave(m_strPathName))
  2771. {
  2772. TRACE0("Warning: File save failed.\n");
  2773. return FALSE;
  2774. }
  2775. }
  2776. return TRUE;
  2777. }
  2778. /*--------------------------------------------------------------------------*
  2779. * CAMCDoc::GetDefaultMenu
  2780. *
  2781. *
  2782. *--------------------------------------------------------------------------*/
  2783. HMENU CAMCDoc::GetDefaultMenu()
  2784. {
  2785. return (AMCGetApp()->GetMenu ());
  2786. }
  2787. /*+-------------------------------------------------------------------------*
  2788. * CAMCDoc::GetCustomIcon
  2789. *
  2790. * Returns the small or large custom icon for the console. Ownership of and
  2791. * deletion responsibility for the icon is retained by CAMCDoc.
  2792. *--------------------------------------------------------------------------*/
  2793. HICON CAMCDoc::GetCustomIcon (bool fLarge, CString* pstrIconFile, int* pnIconIndex) const
  2794. {
  2795. DECLARE_SC (sc, _T("CAMCDoc::ScGetCustomIcon"));
  2796. /*
  2797. * if caller wants either the icon filename or index returned, get them
  2798. */
  2799. if ((pstrIconFile != NULL) || (pnIconIndex != NULL))
  2800. {
  2801. CPersistableIconData IconData;
  2802. m_CustomIcon.GetData (IconData);
  2803. if (pstrIconFile != NULL)
  2804. *pstrIconFile = IconData.m_strIconFile.data();
  2805. if (pnIconIndex != NULL)
  2806. *pnIconIndex = IconData.m_nIndex;
  2807. }
  2808. /*
  2809. * return the icon (m_CustomIcon will hold the reference for the
  2810. * caller)
  2811. */
  2812. CSmartIcon icon;
  2813. sc = m_CustomIcon.GetIcon ((fLarge) ? 32 : 16, icon);
  2814. if (sc)
  2815. return (NULL);
  2816. return (icon);
  2817. }
  2818. /*+-------------------------------------------------------------------------*
  2819. * CAMCDoc::SetCustomIcon
  2820. *
  2821. *
  2822. *--------------------------------------------------------------------------*/
  2823. void CAMCDoc::SetCustomIcon (LPCTSTR pszIconFile, int nIconIndex)
  2824. {
  2825. DECLARE_SC (sc, _T("CAMCDoc::SetCustomIcon"));
  2826. CPersistableIconData IconData (pszIconFile, nIconIndex) ;
  2827. /*
  2828. * if there's no change, bail
  2829. */
  2830. if (m_CustomIcon == IconData)
  2831. return;
  2832. m_CustomIcon = IconData;
  2833. HICON hLargeIcon = GetCustomIcon (true /*fLarge*/);
  2834. HICON hSmallIcon = GetCustomIcon (false /*fLarge*/);
  2835. CMainFrame* pMainFrame = AMCGetMainWnd();
  2836. sc = ScCheckPointers (hLargeIcon, hSmallIcon, pMainFrame, E_UNEXPECTED);
  2837. if (sc)
  2838. return;
  2839. /*
  2840. * change the icon on the frame
  2841. */
  2842. pMainFrame->SetIconEx (hLargeIcon, true);
  2843. pMainFrame->SetIconEx (hSmallIcon, false);
  2844. /*
  2845. * change the icon on each MDI window
  2846. */
  2847. CWnd* pMDIChild = pMainFrame->MDIGetActive();
  2848. while (pMDIChild != NULL)
  2849. {
  2850. ASSERT_KINDOF (CMDIChildWnd, pMDIChild);
  2851. pMDIChild->SetIcon (hLargeIcon, true);
  2852. pMDIChild->SetIcon (hSmallIcon, false);
  2853. pMDIChild = pMDIChild->GetWindow (GW_HWNDNEXT);
  2854. }
  2855. SetModifiedFlag();
  2856. }
  2857. /*+-------------------------------------------------------------------------*
  2858. * CAMCDoc::LoadCustomData
  2859. *
  2860. *
  2861. *--------------------------------------------------------------------------*/
  2862. bool CAMCDoc::LoadCustomData (IStorage* pStorage)
  2863. {
  2864. HRESULT hr;
  2865. IStoragePtr spCustomDataStorage;
  2866. hr = OpenDebugStorage (pStorage, g_pszCustomDataStorage,
  2867. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2868. &spCustomDataStorage);
  2869. if (FAILED (hr))
  2870. return (true);
  2871. LoadCustomIconData (spCustomDataStorage);
  2872. LoadCustomTitleData (spCustomDataStorage);
  2873. return (true);
  2874. }
  2875. /*+-------------------------------------------------------------------------*
  2876. * CAMCDoc::LoadCustomIconData
  2877. *
  2878. *
  2879. *--------------------------------------------------------------------------*/
  2880. bool CAMCDoc::LoadCustomIconData (IStorage* pStorage)
  2881. {
  2882. HRESULT hr = m_CustomIcon.Load (pStorage);
  2883. if (FAILED (hr))
  2884. return (false);
  2885. /*
  2886. * If we get here, we have a custom icon. The view windows
  2887. * (MDI children) haven't been created yet -- they'll get the
  2888. * right icons automatically. The main frame, however, already
  2889. * exists, so we have to explicitly set its icon here.
  2890. */
  2891. CWnd* pMainWnd = AfxGetMainWnd();
  2892. pMainWnd->SetIcon (GetCustomIcon (true), true);
  2893. pMainWnd->SetIcon (GetCustomIcon (false), false);
  2894. return (true);
  2895. }
  2896. /*+-------------------------------------------------------------------------*
  2897. * CAMCDoc::LoadCustomTitleData
  2898. *
  2899. *
  2900. *--------------------------------------------------------------------------*/
  2901. bool CAMCDoc::LoadCustomTitleData (IStorage* pStorage)
  2902. {
  2903. do // not a loop
  2904. {
  2905. /*
  2906. * Open the custom title data stream. It may not exist, and
  2907. * that's OK if it doesn't. It just means we don't have a
  2908. * custom title.
  2909. */
  2910. USES_CONVERSION;
  2911. HRESULT hr;
  2912. IStreamPtr spStream;
  2913. hr = OpenDebugStream (pStorage, AMCCustomTitleStreamName,
  2914. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2915. &spStream);
  2916. BREAK_ON_FAIL (hr);
  2917. try
  2918. {
  2919. /*
  2920. * Read the stream version
  2921. */
  2922. DWORD dwVersion;
  2923. *spStream >> dwVersion;
  2924. /*
  2925. * if this is the beta custom title format, migrate it forward
  2926. */
  2927. switch (dwVersion)
  2928. {
  2929. case 0:
  2930. {
  2931. /*
  2932. * Read the length (in bytes) of the title
  2933. */
  2934. WORD cbTitle;
  2935. *spStream >> cbTitle;
  2936. const WORD cchTitle = cbTitle / sizeof (WCHAR);
  2937. /*
  2938. * Read the title
  2939. */
  2940. std::auto_ptr<WCHAR> spwzWideTitle (new WCHAR[cchTitle + 1]);
  2941. LPWSTR pwzWideTitle = spwzWideTitle.get();
  2942. DWORD cbRead;
  2943. hr = spStream->Read (pwzWideTitle, cbTitle, &cbRead);
  2944. BREAK_ON_FAIL (hr);
  2945. if (cbRead != cbTitle)
  2946. break;
  2947. /*
  2948. * terminate and convert the title string
  2949. */
  2950. pwzWideTitle[cchTitle] = 0;
  2951. if (m_pstrCustomTitle != NULL)
  2952. *m_pstrCustomTitle = W2T (pwzWideTitle);
  2953. break;
  2954. }
  2955. case 1:
  2956. if (m_pstrCustomTitle != NULL)
  2957. *spStream >> (*m_pstrCustomTitle);
  2958. break;
  2959. default:
  2960. ASSERT (false);
  2961. break;
  2962. }
  2963. }
  2964. catch (_com_error& err)
  2965. {
  2966. hr = err.Error();
  2967. ASSERT (false && "Caught _com_error");
  2968. break;
  2969. }
  2970. catch (CMemoryException* pe)
  2971. {
  2972. pe->Delete();
  2973. _com_issue_error (E_OUTOFMEMORY);
  2974. }
  2975. } while (false);
  2976. return (true);
  2977. }
  2978. bool CAMCDoc::HasCustomTitle () const
  2979. {
  2980. if(!m_pstrCustomTitle)
  2981. return false;
  2982. return (!m_pstrCustomTitle->str().empty());
  2983. }
  2984. /*+-------------------------------------------------------------------------*
  2985. * CAMCDoc::LoadStringTable
  2986. *
  2987. *
  2988. *--------------------------------------------------------------------------*/
  2989. bool CAMCDoc::LoadStringTable (IStorage* pStorage)
  2990. {
  2991. DECLARE_SC (sc, _T("CAMCDoc::LoadStringTable"));
  2992. /*
  2993. * open the string table storage
  2994. */
  2995. IStoragePtr spStringTableStg;
  2996. HRESULT hr = OpenDebugStorage (pStorage, AMCStringTableStorageName,
  2997. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2998. &spStringTableStg);
  2999. /*
  3000. * If there's no string table, things are OK. We allow this so
  3001. * we can continue to open older console files.
  3002. */
  3003. if (hr == STG_E_FILENOTFOUND)
  3004. return (true);
  3005. if (SUCCEEDED (hr))
  3006. {
  3007. /*
  3008. * read the string table from the storage
  3009. */
  3010. try
  3011. {
  3012. CMasterStringTable *pMasterStringTable = dynamic_cast<CMasterStringTable *>((IStringTablePrivate *)m_spStringTable);
  3013. if(!pMasterStringTable)
  3014. {
  3015. sc = E_UNEXPECTED;
  3016. sc.Throw();
  3017. }
  3018. *spStringTableStg >> *pMasterStringTable;
  3019. }
  3020. catch (_com_error& err)
  3021. {
  3022. hr = err.Error();
  3023. ASSERT (false && "Caught _com_error");
  3024. }
  3025. }
  3026. return (SUCCEEDED (hr));
  3027. }
  3028. /*+-------------------------------------------------------------------------*
  3029. * CAMCDoc::SetCustomTitle
  3030. *
  3031. *
  3032. *--------------------------------------------------------------------------*/
  3033. void CAMCDoc::SetCustomTitle (CString strNewTitle)
  3034. {
  3035. DECLARE_SC (sc, _T("CAMCDoc::SetCustomTitle"));
  3036. if(!m_pstrCustomTitle)
  3037. return;
  3038. /*
  3039. * if there's no change, just short out
  3040. */
  3041. if ((*m_pstrCustomTitle) == strNewTitle)
  3042. return;
  3043. /*
  3044. * copy the new custom title
  3045. */
  3046. (*m_pstrCustomTitle) = strNewTitle;
  3047. /*
  3048. * force the frame to update
  3049. */
  3050. CMainFrame* pMainFrame = AMCGetMainWnd();
  3051. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  3052. if (sc)
  3053. return;
  3054. pMainFrame->OnUpdateFrameTitle (false);
  3055. SetModifiedFlag();
  3056. }
  3057. /*+-------------------------------------------------------------------------*
  3058. * CAMCDoc::GetCustomTitle
  3059. *
  3060. *
  3061. *--------------------------------------------------------------------------*/
  3062. CString CAMCDoc::GetCustomTitle() const
  3063. {
  3064. if (HasCustomTitle())
  3065. return (m_pstrCustomTitle->data());
  3066. CString strTitle = GetTitle();
  3067. /*
  3068. * strip the extension (extensions, including a separator,
  3069. * are 4 characters or less)
  3070. */
  3071. int nExtSeparator = strTitle.ReverseFind (_T('.'));
  3072. if ((nExtSeparator != -1) && ((strTitle.GetLength()-nExtSeparator) <= 4))
  3073. strTitle = strTitle.Left (nExtSeparator);
  3074. return (strTitle);
  3075. }
  3076. /*+-------------------------------------------------------------------------*
  3077. * CAMCDoc::GetStringTable
  3078. *
  3079. *
  3080. *--------------------------------------------------------------------------*/
  3081. IStringTablePrivate* CAMCDoc::GetStringTable() const
  3082. {
  3083. return m_spStringTable;
  3084. }
  3085. /*+-------------------------------------------------------------------------*
  3086. * CAMCDoc::LoadFavorites
  3087. *
  3088. *
  3089. *--------------------------------------------------------------------------*/
  3090. bool CAMCDoc::LoadFavorites ()
  3091. {
  3092. ASSERT(m_spStorage != NULL);
  3093. // Open the stream for the cache
  3094. IStreamPtr spStream;
  3095. HRESULT hr = OpenDebugStream(m_spStorage, AMCFavoritesStreamName,
  3096. STGM_SHARE_EXCLUSIVE | STGM_READWRITE, L"FavoritesStream", &spStream);
  3097. if (FAILED(hr)) // did not find the stream - could be an older version.
  3098. return hr;
  3099. hr = GetFavorites()->Read(spStream);
  3100. return (SUCCEEDED (hr));
  3101. }
  3102. void ShowAdminToolsOnMenu(LPCTSTR lpszFilename)
  3103. {
  3104. static const TCHAR szAdminKey[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
  3105. static const TCHAR szAdminValue[] = _T("StartMenuAdminTools");
  3106. static const TCHAR szBroadcastParam[] = _T("ShellMenu");
  3107. static const TCHAR szYes[] = _T("YES");
  3108. CString strPath(lpszFilename);
  3109. int nLastSepIndex = strPath.ReverseFind (_T('\\'));
  3110. if (nLastSepIndex != -1)
  3111. {
  3112. // if we got "d:\filename", make sure to include the trailing separator
  3113. if (nLastSepIndex < 3)
  3114. nLastSepIndex++;
  3115. // Form full path name (accounting for current directory info)
  3116. TCHAR szFullPathName[MAX_PATH];
  3117. GetFullPathName (strPath.Left(nLastSepIndex), countof(szFullPathName),
  3118. szFullPathName, NULL);
  3119. // if saving to admin tools
  3120. if (AMCGetApp()->GetDefaultDirectory() == szFullPathName)
  3121. {
  3122. // set reg key to add admin tools to start menu
  3123. HKEY hkey;
  3124. long r = RegOpenKeyEx (HKEY_CURRENT_USER, szAdminKey, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkey);
  3125. ASSERT(r == ERROR_SUCCESS);
  3126. if (r == ERROR_SUCCESS)
  3127. {
  3128. // get current value
  3129. TCHAR szBuffer[4];
  3130. DWORD dwType = REG_SZ;
  3131. DWORD dwCount = sizeof(szBuffer);
  3132. r = RegQueryValueEx (hkey, szAdminValue, NULL, &dwType,(LPBYTE)szBuffer, &dwCount);
  3133. // if value isn't "YES" then change it, and broadcast change message
  3134. if (r != ERROR_SUCCESS || dwType != REG_SZ || lstrcmpi(szBuffer, szYes) != 0)
  3135. {
  3136. r = RegSetValueEx (hkey, szAdminValue, NULL, REG_SZ, (CONST BYTE *)szYes, sizeof(szYes));
  3137. ASSERT(r == ERROR_SUCCESS);
  3138. ULONG_PTR dwRes;
  3139. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)0,
  3140. (LPARAM)szBroadcastParam, SMTO_ABORTIFHUNG|SMTO_NORMAL, 100, &dwRes);
  3141. }
  3142. RegCloseKey(hkey);
  3143. }
  3144. }
  3145. }
  3146. }
  3147. void CAMCDoc::PersistCustomData (CPersistor &persistor)
  3148. {
  3149. CPersistor persistorCustom(persistor, XML_TAG_CUSTOM_DATA);
  3150. // persist custom title
  3151. // It may not exist, and that's OK if it doesn't.
  3152. // It just means we don't have a custom title.
  3153. if ((persistorCustom.IsLoading()
  3154. && persistorCustom.HasElement(XML_TAG_STRING_TABLE_STRING, XML_ATTR_CUSTOM_TITLE))
  3155. || (persistorCustom.IsStoring() && HasCustomTitle()))
  3156. {
  3157. if(m_pstrCustomTitle)
  3158. persistorCustom.PersistString(XML_ATTR_CUSTOM_TITLE, *m_pstrCustomTitle);
  3159. }
  3160. // persist custom icon
  3161. CXMLPersistableIcon persIcon(m_CustomIcon);
  3162. bool bHasIcon = persistorCustom.IsLoading() && persistorCustom.HasElement(persIcon.GetXMLType(), NULL);
  3163. bHasIcon = bHasIcon || persistorCustom.IsStoring() && HasCustomIcon();
  3164. if (!bHasIcon)
  3165. return;
  3166. persistorCustom.Persist(persIcon);
  3167. if (persistorCustom.IsLoading())
  3168. {
  3169. CWnd* pMainWnd = AfxGetMainWnd();
  3170. pMainWnd->SetIcon (GetCustomIcon (true), true);
  3171. pMainWnd->SetIcon (GetCustomIcon (false), false);
  3172. }
  3173. }
  3174. /***************************************************************************\
  3175. *
  3176. * METHOD: GetCurrentFileVersionAsString
  3177. *
  3178. * PURPOSE: formats current file version and returns a string
  3179. *
  3180. * PARAMETERS:
  3181. *
  3182. * RETURNS:
  3183. * CString - resulting string
  3184. *
  3185. \***************************************************************************/
  3186. tstring GetCurrentFileVersionAsString()
  3187. {
  3188. DECLARE_SC(sc, TEXT("GetCurrentFileVersionAsString"));
  3189. TCHAR szFileVersion[16];
  3190. int cChFileVersion = countof(szFileVersion);
  3191. // get file version data
  3192. UINT uiMajorVer = GetConsoleFileMajorVersion(FileVer_Current);
  3193. UINT uiMinorVer = GetConsoleFileMinorVersion(FileVer_Current);
  3194. UINT uiMinorSubVer = GetConsoleFileMinorSubversion(FileVer_Current);
  3195. if (uiMinorSubVer)
  3196. sc = StringCchPrintf(szFileVersion, cChFileVersion, _T("%d.%d.%d"), uiMajorVer, uiMinorVer, uiMinorSubVer);
  3197. else
  3198. sc = StringCchPrintf(szFileVersion, cChFileVersion, _T("%d.%d"), uiMajorVer, uiMinorVer);
  3199. if (sc)
  3200. return _T("");
  3201. return szFileVersion;
  3202. }
  3203. /***************************************************************************\
  3204. *
  3205. * METHOD: CAMCDoc::ScOnSnapinAdded
  3206. *
  3207. * PURPOSE: Script event firing helper. Implements interface accessible from
  3208. * node manager
  3209. *
  3210. * PARAMETERS:
  3211. * PSNAPIN pSnapIn [in] - snapin added to the console
  3212. *
  3213. * RETURNS:
  3214. * SC - result code
  3215. *
  3216. \***************************************************************************/
  3217. SC CAMCDoc::ScOnSnapinAdded(PSNAPIN pSnapIn)
  3218. {
  3219. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnSnapinAdded"));
  3220. CAMCApp* pApp = AMCGetApp();
  3221. // check
  3222. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3223. if (sc)
  3224. return sc;
  3225. // forward
  3226. sc = pApp->ScOnSnapinAdded(this, pSnapIn);
  3227. if (sc)
  3228. return sc;
  3229. return sc;
  3230. }
  3231. /***************************************************************************\
  3232. *
  3233. * METHOD: CAMCDoc::ScOnSnapinRemoved
  3234. *
  3235. * PURPOSE: Script event firing helper. Implements interface accessible from
  3236. * node manager
  3237. *
  3238. * PARAMETERS:
  3239. * PSNAPIN pSnapIn [in] - snapin removed from console
  3240. *
  3241. * RETURNS:
  3242. * SC - result code
  3243. *
  3244. \***************************************************************************/
  3245. SC CAMCDoc::ScOnSnapinRemoved(PSNAPIN pSnapIn)
  3246. {
  3247. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnSnapinRemoved"));
  3248. CAMCApp* pApp = AMCGetApp();
  3249. // check
  3250. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3251. if (sc)
  3252. return sc;
  3253. // forward
  3254. sc = pApp->ScOnSnapinRemoved(this, pSnapIn);
  3255. if (sc)
  3256. return sc;
  3257. return sc;
  3258. }
  3259. //+-------------------------------------------------------------------
  3260. //
  3261. // Member: CAMCDoc::ScSetHelpCollectionInvalid
  3262. //
  3263. // Synopsis: A snapin is added/removed or extension is
  3264. // enabled/disabled therefore help collection
  3265. // no longer reflects current console file.
  3266. //
  3267. // Arguments:
  3268. //
  3269. // Returns: SC
  3270. //
  3271. //--------------------------------------------------------------------
  3272. SC CAMCDoc::ScSetHelpCollectionInvalid ()
  3273. {
  3274. DECLARE_SC(sc, _T("CAMCDoc::ScSetHelpCollectionInvalid"));
  3275. HELPDOCINFO *pHelpDocInfo = GetHelpDocInfo();
  3276. sc = ScCheckPointers(pHelpDocInfo, E_UNEXPECTED);
  3277. if (sc)
  3278. return sc;
  3279. // console file modify time has to be updated for help collection.
  3280. GetSystemTimeAsFileTime(&pHelpDocInfo->m_ftimeModify);
  3281. return (sc);
  3282. }
  3283. SC CAMCDoc::Scget_Application(PPAPPLICATION ppApplication)
  3284. {
  3285. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_Application"));
  3286. // parameter check
  3287. sc = ScCheckPointers(ppApplication, E_UNEXPECTED);
  3288. if (sc)
  3289. return sc;
  3290. // initialization
  3291. *ppApplication = NULL;
  3292. CAMCApp* pApp = AMCGetApp();
  3293. // check
  3294. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3295. if (sc)
  3296. return sc;
  3297. sc = pApp->ScGet_Application(ppApplication);
  3298. if (sc)
  3299. return sc;
  3300. return sc;
  3301. }