Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3995 lines
110 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. protected:
  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. protected:
  91. typedef CAMCDoc CMyTiedObject;
  92. public:
  93. BEGIN_MMC_COM_MAP(_CMMCViews)
  94. END_MMC_COM_MAP()
  95. // Views interface
  96. public:
  97. MMC_METHOD1(get_Count, PLONG /*pCount*/);
  98. MMC_METHOD2(Add, PNODE /*pNode*/, ViewOptions /*fViewOptions*/);
  99. MMC_METHOD2(Item, long /*Index*/, PPVIEW /*ppView*/);
  100. };
  101. // this typedefs the real CMMCViews class. Implements get__NewEnum using CMMCEnumerator and a CAMCViewPosition object
  102. typedef CMMCNewEnumImpl<_CMMCViews, CAMCViewPosition> CMMCViews;
  103. //############################################################################
  104. //############################################################################
  105. //
  106. // Implementation of class CStringTableString
  107. //
  108. //############################################################################
  109. //############################################################################
  110. /*+-------------------------------------------------------------------------*
  111. * CStringTableString::GetStringTable
  112. *
  113. *
  114. *--------------------------------------------------------------------------*/
  115. IStringTablePrivate* CStringTableString::GetStringTable () const
  116. {
  117. return (CAMCDoc::GetDocument()->GetStringTable());
  118. }
  119. void ShowAdminToolsOnMenu(LPCTSTR lpszFilename);
  120. enum ENodeType
  121. {
  122. entRoot,
  123. entSelected,
  124. };
  125. //############################################################################
  126. //############################################################################
  127. //
  128. // Implementation of class CAMCDoc
  129. //
  130. //############################################################################
  131. //############################################################################
  132. IMPLEMENT_DYNCREATE(CAMCDoc, CDocument)
  133. BEGIN_MESSAGE_MAP(CAMCDoc, CDocument)
  134. //{{AFX_MSG_MAP(CAMCDoc)
  135. ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
  136. ON_COMMAND(ID_CONSOLE_ADDREMOVESNAPIN, OnConsoleAddremovesnapin)
  137. ON_UPDATE_COMMAND_UI(ID_CONSOLE_ADDREMOVESNAPIN, OnUpdateConsoleAddremovesnapin)
  138. //}}AFX_MSG_MAP
  139. END_MESSAGE_MAP()
  140. /////////////////////////////////////////////////////////////////////////////
  141. // CAMCDoc construction/destruction
  142. CAMCDoc* CAMCDoc::m_pDoc = NULL;
  143. CAMCDoc::CAMCDoc()
  144. : m_MTNodeIDForNewView(ROOTNODEID),
  145. m_ViewIDForNewView(0),
  146. m_lNewWindowOptions(MMC_NW_OPTION_NONE),
  147. m_bReadOnlyDoc(false),
  148. m_fFrameModified (false),
  149. m_eSaveStatus (eStat_Succeeded),
  150. m_pFavorites(NULL)
  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. TCHAR szFileVersion[16];
  1519. wsprintf (szFileVersion, _T("%d.%d%x"),
  1520. GetConsoleFileMajorVersion (eFileVer),
  1521. GetConsoleFileMinorVersion (eFileVer),
  1522. GetConsoleFileMinorSubversion (eFileVer));
  1523. CString strMessage;
  1524. FormatString2 (strMessage, IDS_NewerVersionRequired, pszFilename, szFileVersion);
  1525. MMCMessageBox (strMessage);
  1526. }
  1527. /*+-------------------------------------------------------------------------*
  1528. * CAMCDoc::OnOpenDocument
  1529. *
  1530. * WM_OPENDOCUMENT handler for CAMCDoc.
  1531. *--------------------------------------------------------------------------*/
  1532. BOOL CAMCDoc::OnOpenDocument(LPCTSTR lpszPathName)
  1533. {
  1534. DECLARE_SC(sc, TEXT("CAMCDoc::OnOpenDocument"));
  1535. sc = ScOnOpenDocument(lpszPathName);
  1536. if(sc) // found an error
  1537. {
  1538. DisplayFileOpenError (sc, lpszPathName);
  1539. return false;
  1540. }
  1541. sc = ScFireEvent(CAMCDocumentObserver::ScDocumentLoadCompleted, this);
  1542. if (sc)
  1543. return false;
  1544. /*
  1545. * Success! We shouldn't think that a freshly opened console file is
  1546. * dirty. If we do, someone's dirty bit processing is bogus.
  1547. */
  1548. ASSERT (!IsFrameModified());
  1549. /*
  1550. * Too many snap-ins leave themselves dirty after a load to leave this
  1551. * assert in, so we'll trace instead. Note that this trace doesn't
  1552. * always indicate a snap-in problem, but it frequently does.
  1553. */
  1554. #ifdef DBG
  1555. // ASSERT (!IsModified());
  1556. if (IsModified())
  1557. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after opening"));
  1558. #endif
  1559. return true;
  1560. }
  1561. /*+-------------------------------------------------------------------------*
  1562. * DisplayFileOpenError
  1563. *
  1564. * Displays an error message if we couldn't open a console file.
  1565. *--------------------------------------------------------------------------*/
  1566. int DisplayFileOpenError (SC sc, LPCTSTR pszFilename)
  1567. {
  1568. // if it is any of the known errors, use a friendly string.
  1569. if (sc == SC(STG_E_FILENOTFOUND) || sc == ScFromWin32(ERROR_FILE_NOT_FOUND))
  1570. (sc = ScFromMMC(IDS_FileNotFound));
  1571. else if (sc == ScFromMMC(MMC_E_INVALID_FILE))
  1572. (sc = ScFromMMC(IDS_InvalidVersion));
  1573. else if (sc == SC(STG_E_MEDIUMFULL))
  1574. (sc = ScFromMMC(IDS_DiskFull));
  1575. else
  1576. {
  1577. CString strError;
  1578. AfxFormatString1(strError, IDS_UnableToOpenDocumentMessage, pszFilename);
  1579. return (MMCErrorBox(strError));
  1580. }
  1581. return (MMCErrorBox(sc));
  1582. }
  1583. /*+-------------------------------------------------------------------------*
  1584. * ScGetFileProperties
  1585. *
  1586. * Returns the read-only state of the given file, as well as the creation,
  1587. * last access, and last write times (all optional).
  1588. *
  1589. * We determine if the file is read-only by trying to open the file for
  1590. * writing rather than checking for FILE_ATTRIBUTE_READONLY. We do this
  1591. * because it will catch more read-only conditions, like the file living
  1592. * on a read-only share or NTFS permissions preventing a write.
  1593. *--------------------------------------------------------------------------*/
  1594. static SC ScGetFileProperties (
  1595. LPCTSTR lpszPathName, /* I:name of file to check */
  1596. bool* pfReadOnly, /* O:is file read-only? */
  1597. FILETIME* pftCreate, /* O:creation time (optional) */
  1598. FILETIME* pftLastAccess, /* O:last access time (optional) */
  1599. FILETIME* pftLastWrite) /* O:last write time (optional) */
  1600. {
  1601. DECLARE_SC (sc, _T("ScGetFileProperties"));
  1602. /*
  1603. * validate inputs (pftCreate, pftLastAccess, and pftLastWrite are optional)
  1604. */
  1605. sc = ScCheckPointers (lpszPathName, pfReadOnly);
  1606. if (sc)
  1607. return (sc);
  1608. /*
  1609. * try to open the file for write; if we can't, the file is read-only
  1610. */
  1611. HANDLE hFile = CreateFile (lpszPathName, GENERIC_WRITE, 0, NULL,
  1612. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1613. *pfReadOnly = (hFile == INVALID_HANDLE_VALUE);
  1614. /*
  1615. * if read-only then open in read mode so we'll have a handle to pass
  1616. * to GetFileTime
  1617. */
  1618. if (hFile == INVALID_HANDLE_VALUE)
  1619. {
  1620. hFile = CreateFile (lpszPathName, 0, 0, NULL,
  1621. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1622. if (hFile == INVALID_HANDLE_VALUE)
  1623. {
  1624. sc.FromLastError();
  1625. return (sc);
  1626. }
  1627. }
  1628. /*
  1629. * get the timestamps on the file
  1630. */
  1631. if (!GetFileTime (hFile, pftCreate, pftLastAccess, pftLastWrite))
  1632. sc.FromLastError();
  1633. CloseHandle (hFile);
  1634. return (sc);
  1635. }
  1636. /*+-------------------------------------------------------------------------*
  1637. *
  1638. * CAMCDoc::ScOnOpenDocument
  1639. *
  1640. * PURPOSE: Opens the specified document.
  1641. *
  1642. * PARAMETERS:
  1643. * LPCTSTR lpszPathName :
  1644. *
  1645. * RETURNS:
  1646. * SC
  1647. *
  1648. *+-------------------------------------------------------------------------*/
  1649. SC
  1650. CAMCDoc::ScOnOpenDocument(LPCTSTR lpszPathName)
  1651. {
  1652. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnOpenDocument"));
  1653. // lock AppEvents until this function is done
  1654. LockComEventInterface(AppEvents);
  1655. #define VIVEKJ
  1656. #ifdef VIVEKJ
  1657. // upgrade the console file to the XML version.
  1658. CConsoleFile consoleFile;
  1659. consoleFile.ScUpgrade(lpszPathName);
  1660. #endif
  1661. USES_CONVERSION;
  1662. // check inputs
  1663. if (lpszPathName == NULL || *lpszPathName == 0)
  1664. return (sc = E_UNEXPECTED);
  1665. if (IsModified())
  1666. {
  1667. TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
  1668. }
  1669. if (!AssertNodeManagerIsInitialized())
  1670. return (sc = E_UNEXPECTED);
  1671. /*
  1672. * get the times for the file, as well as its read-only state
  1673. */
  1674. HELPDOCINFO* phdi = GetHelpDocInfo();
  1675. sc = ScCheckPointers (phdi, E_UNEXPECTED);
  1676. if (sc)
  1677. return (sc);
  1678. bool fReadOnly;
  1679. sc = ScGetFileProperties (lpszPathName, &fReadOnly,
  1680. &phdi->m_ftimeCreate, NULL, &phdi->m_ftimeModify);
  1681. if (sc)
  1682. return (sc);
  1683. // load the document using method from the base class (CConsoleFilePersistor)
  1684. bool bXmlBased = false;
  1685. CXMLDocument xmlDocument;
  1686. IStoragePtr spStorage;
  1687. sc = ScLoadConsole(lpszPathName, bXmlBased, xmlDocument, &spStorage);
  1688. if (sc)
  1689. return (sc);
  1690. if ( bXmlBased )
  1691. {
  1692. // load as XML document
  1693. sc = ScLoadFromDocument(xmlDocument);
  1694. if(sc)
  1695. return sc;
  1696. }
  1697. else
  1698. {
  1699. sc = ScCheckPointers(m_spScopeTree, E_UNEXPECTED);
  1700. if (sc)
  1701. return sc;
  1702. // get the console file's version
  1703. ASSERT (sizeof(m_ConsoleData.m_eFileVer) == sizeof(int));
  1704. sc = m_spScopeTree->GetFileVersion(spStorage, (int*)&m_ConsoleData.m_eFileVer);
  1705. if (sc)
  1706. return sc;
  1707. /*
  1708. * check to see if this file is from a newer MMC
  1709. */
  1710. if (m_ConsoleData.m_eFileVer > FileVer_Current)
  1711. {
  1712. ShowIncompatibleFileMessage (lpszPathName, m_ConsoleData.m_eFileVer);
  1713. return (sc = E_UNEXPECTED);
  1714. }
  1715. // Previous storage should have been closed and released
  1716. ASSERT(m_spStorage == NULL);
  1717. /*
  1718. * Load the string table.
  1719. */
  1720. if (!LoadStringTable (spStorage))
  1721. return (sc = E_UNEXPECTED);
  1722. // Load column settings.
  1723. do
  1724. {
  1725. IStreamPtr spStream;
  1726. sc = OpenDebugStream (spStorage, AMCColumnDataStreamName,
  1727. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1728. &spStream);
  1729. if(sc)
  1730. break;
  1731. if (NULL != m_ConsoleData.m_spPersistStreamColumnData)
  1732. sc = m_ConsoleData.m_spPersistStreamColumnData->Load(spStream);
  1733. ASSERT(NULL != m_ConsoleData.m_spPersistStreamColumnData);
  1734. if (sc.IsError() || (NULL == m_ConsoleData.m_spPersistStreamColumnData) )
  1735. return (sc = E_UNEXPECTED);
  1736. } while ( FALSE );
  1737. // Load view settings.
  1738. do
  1739. {
  1740. IStreamPtr spStream;
  1741. sc = OpenDebugStream (spStorage, AMCViewSettingDataStreamName,
  1742. STGM_SHARE_EXCLUSIVE | STGM_READ,
  1743. &spStream);
  1744. if (sc)
  1745. break;
  1746. IPersistStreamPtr spIPeristStreamViewSettings;
  1747. SC sc = ScGetViewSettingsPersistorStream(&spIPeristStreamViewSettings);
  1748. if (sc)
  1749. break;
  1750. sc = ScCheckPointers(spIPeristStreamViewSettings, E_UNEXPECTED);
  1751. if (sc)
  1752. break;
  1753. sc = spIPeristStreamViewSettings->Load(spStream);
  1754. if (sc)
  1755. break;
  1756. } while ( FALSE );
  1757. // Load the tree
  1758. sc = m_spScopeTreePersist->Load(spStorage);
  1759. if (sc)
  1760. {
  1761. ReleaseNodeManager();
  1762. return sc;
  1763. }
  1764. // Save the new storage
  1765. m_spStorage = spStorage;
  1766. /*
  1767. * make sure the tree expansion happens synchronously
  1768. */
  1769. bool fSyncExpandWasRequired = m_spScopeTree->IsSynchronousExpansionRequired() == S_OK;
  1770. m_spScopeTree->RequireSynchronousExpansion (true);
  1771. // Load the favorites data before loading views and frames,
  1772. // so that when frame/view is created the favorite data is ready.
  1773. if (!LoadFavorites())
  1774. {
  1775. // bhanlon ReleaseNodeManager();
  1776. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1777. return (sc = E_UNEXPECTED);
  1778. }
  1779. /*
  1780. * Load string table, custom data, views and frame. Load the
  1781. * custom data (including the icon) before loading the views so
  1782. * the proper icon will be used for the views as they're created.
  1783. */
  1784. /*
  1785. * The LoadAppMode, LoadViews and LoadFrame should be called in that
  1786. * order due to following reason.
  1787. * LoadAppMode reads mode from frame-data and saves it in CAMCApp.
  1788. * The mode is used during LoadViews (in CAMCView::Load) to set the view.
  1789. * LoadFrame again reads the frame-data and calls CAMCApp::UpdateFrameWindow
  1790. * to set toolbar/menus according to the mode.
  1791. */
  1792. if (!LoadCustomData (m_spStorage) || !LoadAppMode() || !LoadViews() || !LoadFrame())
  1793. {
  1794. // bhanlon ReleaseNodeManager();
  1795. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1796. return (sc = E_UNEXPECTED);
  1797. }
  1798. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  1799. }
  1800. SetModifiedFlag (false);
  1801. SetFrameModifiedFlag (false);
  1802. SetPhysicalReadOnlyFlag (fReadOnly);
  1803. ASSERT (IsValidFileVersion (m_ConsoleData.m_eFileVer));
  1804. return sc;
  1805. }
  1806. /*+-------------------------------------------------------------------------*
  1807. * CAMCDoc::OnSaveDocument
  1808. *
  1809. * WM_SAVEDOCUMENT handler for CAMCDoc.
  1810. *--------------------------------------------------------------------------*/
  1811. BOOL CAMCDoc::OnSaveDocument(LPCTSTR lpszFilename)
  1812. {
  1813. DECLARE_SC(sc, _T("CAMCDoc::OnSaveDocument"));
  1814. USES_CONVERSION;
  1815. m_eSaveStatus = eStat_Succeeded;
  1816. // Check for a valid filename
  1817. ASSERT(lpszFilename != NULL && *lpszFilename != 0);
  1818. if (lpszFilename == NULL || *lpszFilename == 0)
  1819. {
  1820. return UnableToSaveDocument();
  1821. }
  1822. // Ask the each view to save any data into its data
  1823. // structures (memory) before calling IPersist*::Save.
  1824. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1825. while (pos != NULL)
  1826. {
  1827. CAMCView* const pAMCView = GetNextAMCView(pos);
  1828. sc = ScCheckPointers(pAMCView, E_UNEXPECTED);
  1829. if (sc)
  1830. return UnableToSaveDocument();
  1831. }
  1832. if (!IsCurrentFileVersion (m_ConsoleData.m_eFileVer))
  1833. {
  1834. // If we've arrived at this point then the user is attempting to save the file
  1835. // from an old format into a new one and we will check to see if the user really
  1836. // wants to do this.
  1837. CString strMessage;
  1838. LPCTSTR pszPathName = m_strPathName;
  1839. // A YES/NO/(CANCEL) dialog asking if the user wants to save the file in the new format
  1840. int nResult;
  1841. /*
  1842. * Bug 277586: we don't ever want non-authors to see this dialog
  1843. */
  1844. if (AMCGetApp()->GetMode() != eMode_Author)
  1845. {
  1846. // non-authors are only saving console settings,
  1847. // which are always in the current version
  1848. // no need to ask for conversion - original console is not converted anyway.
  1849. nResult = IDYES;
  1850. }
  1851. else if (IsExplicitSave())
  1852. {
  1853. // 2 button YES/NO dialog appears if this is an explicit save
  1854. tstring strVersion = GetCurrentFileVersionAsString();
  1855. FormatString2 (strMessage, IDS_CONVERT_FILE_FORMAT,
  1856. pszPathName, strVersion.c_str());
  1857. nResult = MMCMessageBox (strMessage, MB_YESNO | MB_DEFBUTTON2);
  1858. }
  1859. else
  1860. {
  1861. // 3 button YES/NO/CANCEL appears if this dialog appears when the program
  1862. // prompts to save changes when the user closes the document
  1863. tstring strVersion = GetCurrentFileVersionAsString();
  1864. FormatString2 (strMessage, IDS_CONVERT_FILE_FORMAT_CLOSE,
  1865. pszPathName, strVersion.c_str());
  1866. nResult = MMCMessageBox (strMessage, MB_YESNOCANCEL | MB_DEFBUTTON3);
  1867. }
  1868. // If we cancel out
  1869. if ((nResult == IDCANCEL) || ((nResult == IDNO) && IsExplicitSave()))
  1870. {
  1871. // Must set this variable otherwise MMC will delete the file
  1872. m_eSaveStatus = eStat_Cancelled;
  1873. return (false);
  1874. }
  1875. // If this will result in us exiting without saving
  1876. if ((nResult == IDNO) && !IsExplicitSave())
  1877. return (true);
  1878. }
  1879. // if we have more than one view, and we'll force SDI in user mode, prompt
  1880. if ((GetNumberOfPersistedViews() > 1) &&
  1881. (m_ConsoleData.m_eConsoleMode == eMode_User_SDI) &&
  1882. (AMCGetApp()->GetMode() == eMode_Author))
  1883. {
  1884. switch (MMCMessageBox (IDS_FORCE_SDI_PROMPT, MB_YESNOCANCEL))
  1885. {
  1886. case IDYES:
  1887. /* do nothing */
  1888. break;
  1889. case IDNO:
  1890. m_ConsoleData.m_eConsoleMode = eMode_User_MDI;
  1891. break;
  1892. case IDCANCEL:
  1893. m_eSaveStatus = eStat_Cancelled;
  1894. return (false);
  1895. }
  1896. }
  1897. // save contents to xml document
  1898. CXMLDocument xmlDocument;
  1899. sc = ScSaveToDocument( xmlDocument );
  1900. if (sc)
  1901. return UnableToSaveDocument();
  1902. // save xml document to file
  1903. bool bAuthor = (AMCGetApp()->GetMode() == eMode_Author);
  1904. sc = ScSaveConsole( lpszFilename, bAuthor, xmlDocument);
  1905. if (sc)
  1906. return UnableToSaveDocument();
  1907. SetModifiedFlag (false);
  1908. SetFrameModifiedFlag (false);
  1909. /*
  1910. * We shouldn't think that a freshly saved console file is
  1911. * dirty. If we do, someone's dirty bit processing is bogus.
  1912. */
  1913. ASSERT (!IsFrameModified());
  1914. /*
  1915. * Too many snap-ins leave themselves dirty after a load to leave this
  1916. * assert in, so we'll trace instead. Note that this trace doesn't
  1917. * always indicate a snap-in problem, but it frequently does.
  1918. */
  1919. #ifdef DBG
  1920. // ASSERT (!IsModified());
  1921. if (IsModified())
  1922. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after saving"));
  1923. #endif
  1924. // if a save was just done, this can't be read-only
  1925. // NOTE: if MMC adds support for "Save Copy As" we have
  1926. // to determine whether a "Save As" or "Save Copy As"
  1927. // was done before clearing the read-only status
  1928. SetPhysicalReadOnlyFlag (false);
  1929. m_ConsoleData.m_eFileVer = FileVer_Current;
  1930. // Show admin tools on start menu if necessary
  1931. ShowAdminToolsOnMenu(lpszFilename);
  1932. return TRUE;
  1933. }
  1934. int CAMCDoc::GetNumberOfViews()
  1935. {
  1936. TRACE_METHOD(CAMCDoc, GetNumberOfViews);
  1937. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1938. int count = 0;
  1939. while (pos != NULL)
  1940. {
  1941. GetNextAMCView(pos);
  1942. VERIFY (++count);
  1943. }
  1944. return (count);
  1945. }
  1946. int CAMCDoc::GetNumberOfPersistedViews()
  1947. {
  1948. unsigned short cPersistedViews = 0;
  1949. CAMCViewPosition pos = GetFirstAMCViewPosition();
  1950. while (pos != NULL)
  1951. {
  1952. CAMCView* v = GetNextAMCView(pos);
  1953. if (v && v->IsPersisted())
  1954. ++cPersistedViews;
  1955. }
  1956. return (cPersistedViews);
  1957. }
  1958. CAMCView* CAMCDoc::CreateNewView(bool fVisible, bool bEmitScriptEvents /*= true*/)
  1959. {
  1960. DECLARE_SC(sc, TEXT("CAMCDoc::CreateNewView"));
  1961. TRACE_FUNCTION(CAMCDoc::CreateNewView);
  1962. CDocTemplate* pTemplate = GetDocTemplate();
  1963. ASSERT(pTemplate != NULL);
  1964. CChildFrame* pFrame = (CChildFrame*) pTemplate->CreateNewFrame(this, NULL);
  1965. ASSERT_KINDOF (CChildFrame, pFrame);
  1966. if (pFrame == NULL)
  1967. {
  1968. TRACE(_T("Warning: failed to create new frame.\n"));
  1969. return NULL; // command failed
  1970. }
  1971. bool fOldCreateVisibleState;
  1972. /*
  1973. * If we're going to create the frame invisibly, set a flag in the frame.
  1974. * When this flag is set, the frame will show itself with the
  1975. * SW_SHOWMINNOACTIVE flag instead of the default flag. Doing this will
  1976. * avoid the side effect of restoring the currently active child frame
  1977. * if it is maximized at the time the new frame is created invisibly.
  1978. */
  1979. // The SW_SHOWMINNOACTIVE was changed to SW_SHOWNOACTIVATE.
  1980. // It does preserve the active window from mentioned side effect,
  1981. // plus it also allows scripts (using Object Moded) to create invisible views,
  1982. // position and then show them as normal (not minimized) windows,
  1983. // thus providing same result as creating visible and then hiding the view.
  1984. // While minimized window must be restored first in order to change their position.
  1985. if (!fVisible)
  1986. {
  1987. fOldCreateVisibleState = pFrame->SetCreateVisible (false);
  1988. }
  1989. /*
  1990. * update the frame as if it is to be visible; we'll hide the frame
  1991. * later if necessary
  1992. */
  1993. // setting visibility to 'true' is required option for MFC to pass control
  1994. // to OnInitialUpdate of child windows.
  1995. pTemplate->InitialUpdateFrame (pFrame, this, true /*fVisible*/);
  1996. if (fVisible)
  1997. {
  1998. // Force drawing of frame and view windows now in case a slow OCX in the result
  1999. // pane delays the initial window update
  2000. pFrame->RedrawWindow();
  2001. }
  2002. else
  2003. {
  2004. pFrame->SetCreateVisible (fOldCreateVisibleState);
  2005. pFrame->ShowWindow (SW_HIDE);
  2006. /*
  2007. * InitialUpdateFrame will update the frame counts. When it executes
  2008. * the new, to-be-invisible frame will be visible, so it'll be included
  2009. * in the count. If the new window is the second frame, then the first
  2010. * frame will have "1:" prepended to its title. This is ugly, so we'll
  2011. * update the frame counts again after the new frame has been hidden
  2012. * to fix all of the existing frames' titles.
  2013. */
  2014. UpdateFrameCounts();
  2015. }
  2016. CAMCView* const v = pFrame->GetAMCView();
  2017. if (!(MMC_NW_OPTION_NOPERSIST & GetNewWindowOptions()))
  2018. SetModifiedFlag();
  2019. ASSERT(v);
  2020. if (!v)
  2021. return v;
  2022. AddObserver(static_cast<CAMCDocumentObserver&>(*v));
  2023. // fire the event to the script
  2024. if (bEmitScriptEvents)
  2025. {
  2026. CAMCApp* pApp = AMCGetApp();
  2027. // check
  2028. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  2029. if (sc)
  2030. return v;
  2031. // forward
  2032. sc = pApp->ScOnNewView(v);
  2033. if (sc)
  2034. return v;
  2035. }
  2036. return v;
  2037. }
  2038. void DeletePropertyPages(void)
  2039. {
  2040. HWND hWnd = NULL;
  2041. DWORD dwPid = 0; // Process Id
  2042. DWORD dwTid = 0; // Thread Id
  2043. while (TRUE)
  2044. {
  2045. USES_CONVERSION;
  2046. // Note: No need to localize this string
  2047. hWnd = ::FindWindowEx(NULL, hWnd, W2T( DATAWINDOW_CLASS_NAME ), NULL);
  2048. if (hWnd == NULL)
  2049. return; // No more windows
  2050. ASSERT(IsWindow(hWnd));
  2051. // Check if the window belongs to the current process
  2052. dwTid = ::GetWindowThreadProcessId(hWnd, &dwPid);
  2053. if (dwPid != ::GetCurrentProcessId())
  2054. continue;
  2055. DataWindowData* pData = GetDataWindowData (hWnd);
  2056. ASSERT (pData != NULL);
  2057. ASSERT (IsWindow (pData->hDlg));
  2058. if (SendMessage(pData->hDlg, WM_COMMAND, IDCANCEL, 0L) != 0)
  2059. {
  2060. DBG_OUT_LASTERROR;
  2061. }
  2062. // Note: For some reason, the send message stays stuck in the threads
  2063. // msg queue causing the sheet not to dismiss itself. By posting a another
  2064. // message( it could be anything), it kick starts the queue and the send message
  2065. // goes through.
  2066. ::PostMessage(pData->hDlg, WM_COMMAND, IDCANCEL, 0L);
  2067. }
  2068. }
  2069. void CAMCDoc::DeleteContents()
  2070. {
  2071. TRACE_METHOD(CAMCDoc, DeleteContents);
  2072. CDocument::DeleteContents();
  2073. }
  2074. void CAMCDoc::DeleteHelpFile ()
  2075. {
  2076. /*
  2077. * Delete the help file on closing a console file
  2078. */
  2079. // Get a node callback interface
  2080. ASSERT(m_spScopeTree != NULL);
  2081. // If this asserts - the document is in invalid state.
  2082. // Most probably it's because our "Load" procedures did not perform proper
  2083. // cleanup when we failed to load the document
  2084. INodeCallbackPtr spNodeCallback;
  2085. if (m_spScopeTree != NULL)
  2086. {
  2087. m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2088. ASSERT(spNodeCallback != NULL);
  2089. }
  2090. // fill in file name and send the delete request
  2091. if (spNodeCallback != NULL)
  2092. {
  2093. USES_CONVERSION;
  2094. GetHelpDocInfo()->m_pszFileName = T2COLE(GetPathName());
  2095. spNodeCallback->Notify(NULL, NCLBK_DELETEHELPDOC, (LPARAM)GetHelpDocInfo(), NULL);
  2096. }
  2097. }
  2098. void CAMCDoc::OnCloseDocument()
  2099. {
  2100. DECLARE_SC(sc, TEXT("CAMCDoc::OnCloseDocument"));
  2101. TRACE_METHOD(CAMCDoc, OnCloseDocument);
  2102. // Inform nodemgr about doc-closing (should change this to observer object)
  2103. do
  2104. {
  2105. sc = ScCheckPointers(m_spScopeTree, E_UNEXPECTED);
  2106. if (sc)
  2107. break;
  2108. INodeCallbackPtr spNodeCallback;
  2109. sc = m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2110. if (sc)
  2111. break;
  2112. sc = ScCheckPointers(spNodeCallback, E_UNEXPECTED);
  2113. if (sc)
  2114. break;
  2115. sc = spNodeCallback->DocumentClosing();
  2116. if (sc)
  2117. break;
  2118. } while ( FALSE );
  2119. if (sc)
  2120. sc.TraceAndClear();
  2121. CAMCApp* pApp = AMCGetApp();
  2122. // check
  2123. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  2124. if (sc)
  2125. sc.TraceAndClear();
  2126. else
  2127. {
  2128. // forward
  2129. sc = pApp->ScOnCloseDocument(this);
  2130. if (sc)
  2131. sc.TraceAndClear();
  2132. }
  2133. // If we are not instantiated as OLESERVER check for open property sheets.
  2134. if (! pApp->IsMMCRunningAsOLEServer() && FArePropertySheetsOpen(NULL))
  2135. {
  2136. CString strMsg, strTitle;
  2137. if (strMsg.LoadString(IDS_MMCWillCancelPropertySheets) &&
  2138. strTitle.LoadString(IDS_WARNING))
  2139. ::MessageBox(NULL, strMsg, strTitle, MB_OK | MB_ICONWARNING);
  2140. }
  2141. DeletePropertyPages();
  2142. DeleteHelpFile ();
  2143. CDocument::OnCloseDocument();
  2144. }
  2145. BOOL CAMCDoc::SaveModified()
  2146. {
  2147. BOOL fDocModified = IsModified();
  2148. BOOL fFrameModified = IsFrameModified();
  2149. // if the file is not read-only and it is modified
  2150. if (!IsReadOnly() && (fDocModified || fFrameModified))
  2151. {
  2152. int idResponse;
  2153. bool fUserMode = (AMCGetApp()->GetMode() != eMode_Author);
  2154. bool fSaveByUserDecision = false;
  2155. // silent saves for the various flavors of user mode
  2156. if (fUserMode)
  2157. idResponse = IDYES;
  2158. // silent saves if the frame was modified but the document wasn't...
  2159. else if (fFrameModified && !fDocModified)
  2160. {
  2161. /*
  2162. * ...unless the console wasn't modified. This will happen
  2163. * if the user ran MMC without opening an existing console file
  2164. * and then moved the frame window.
  2165. */
  2166. // ...unless the console wasn't modified.
  2167. if (m_strPathName.IsEmpty())
  2168. idResponse = IDNO;
  2169. else
  2170. idResponse = IDYES;
  2171. }
  2172. // otherwise, prompt
  2173. else
  2174. {
  2175. CString prompt;
  2176. FormatString1(prompt, IDS_ASK_TO_SAVE, m_strTitle);
  2177. idResponse = AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_SAVE); // dont change to MMCMessageBox - different signature.
  2178. fSaveByUserDecision = true;
  2179. }
  2180. switch (idResponse)
  2181. {
  2182. case IDCANCEL:
  2183. return FALSE; // don't continue
  2184. case IDYES:
  2185. // If so, either Save or Update, as appropriate
  2186. // (ignore failures in User mode)
  2187. // This save is not explicit and shows up when the user closes a modified
  2188. // document. Set it as such. This will result in a different dialog
  2189. // a few functions in.
  2190. SetExplicitSave(false);
  2191. if (!DoFileSave() && fSaveByUserDecision)
  2192. {
  2193. // Restore to the default explicit save
  2194. SetExplicitSave(true);
  2195. return FALSE; // don't continue
  2196. }
  2197. // Restore to the default explicit save
  2198. SetExplicitSave(true);
  2199. break;
  2200. case IDNO:
  2201. // If not saving changes, revert the document
  2202. break;
  2203. default:
  2204. ASSERT(FALSE);
  2205. break;
  2206. }
  2207. }
  2208. // At this point we are committed to closing, so give each AMCView
  2209. // a chance to do its clean-up work
  2210. CAMCViewPosition pos = GetFirstAMCViewPosition();
  2211. while (pos != NULL)
  2212. {
  2213. CAMCView* const pView = GetNextAMCView(pos);
  2214. if (pView != NULL)
  2215. pView->CloseView();
  2216. }
  2217. return TRUE; // keep going
  2218. }
  2219. #if (_MFC_VER > 0x0600)
  2220. #error CAMCDoc::DoSave was copied from CDocument::DoSave from MFC 6.0.
  2221. #error The MFC version has changed. See if CAMCDoc::DoSave needs to be updated.
  2222. #endif
  2223. BOOL CAMCDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
  2224. // Save the document data to a file
  2225. // lpszPathName = path name where to save document file
  2226. // if lpszPathName is NULL then the user will be prompted (SaveAs)
  2227. // note: lpszPathName can be different than 'm_strPathName'
  2228. // if 'bReplace' is TRUE will change file name if successful (SaveAs)
  2229. // if 'bReplace' is FALSE will not change path name (SaveCopyAs)
  2230. {
  2231. CString newName = lpszPathName;
  2232. if (newName.IsEmpty())
  2233. {
  2234. CDocTemplate* pTemplate = GetDocTemplate();
  2235. ASSERT(pTemplate != NULL);
  2236. newName = m_strPathName;
  2237. if (bReplace && newName.IsEmpty())
  2238. {
  2239. newName = m_strTitle;
  2240. #ifndef _MAC
  2241. // check for dubious filename
  2242. int iBad = newName.FindOneOf(_T(" #%;/\\"));
  2243. #else
  2244. int iBad = newName.FindOneOf(_T(":"));
  2245. #endif
  2246. if (iBad != -1)
  2247. newName.ReleaseBuffer(iBad);
  2248. #ifndef _MAC
  2249. // append the default suffix if there is one
  2250. CString strExt;
  2251. if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) &&
  2252. !strExt.IsEmpty())
  2253. {
  2254. ASSERT(strExt[0] == '.');
  2255. newName += strExt;
  2256. }
  2257. #endif
  2258. }
  2259. if (!AfxGetApp()->DoPromptFileName(newName,
  2260. bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY,
  2261. OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, pTemplate))
  2262. return FALSE; // don't even attempt to save
  2263. }
  2264. CWaitCursor wait;
  2265. if (!OnSaveDocument(newName))
  2266. {
  2267. // This is the modified MMC implementation
  2268. #ifdef MMC_DELETE_EXISTING_FILE // See bug 395006
  2269. if ((lpszPathName == NULL) && (m_eSaveStatus != eStat_Cancelled))
  2270. {
  2271. // be sure to delete the file
  2272. try
  2273. {
  2274. CFile::Remove(newName);
  2275. }
  2276. catch (CException* pe)
  2277. {
  2278. TRACE0("Warning: failed to delete file after failed SaveAs.\n");
  2279. pe->Delete();
  2280. }
  2281. }
  2282. #endif
  2283. return FALSE;
  2284. }
  2285. // if changing the name of the open document
  2286. if (bReplace)
  2287. {
  2288. /*
  2289. * Delete the help file for this console file before
  2290. * changing its name, because the help file can't be
  2291. * located once the old name is lost.
  2292. */
  2293. DeleteHelpFile ();
  2294. // reset the title and change the document name
  2295. SetPathName(newName);
  2296. }
  2297. return TRUE; // success
  2298. }
  2299. BOOL CAMCDoc::IsModified()
  2300. {
  2301. TRACE_METHOD(CAMCDoc, IsModified);
  2302. BOOL const bModified = /*CDocument::IsModified() || */
  2303. (m_spScopeTreePersist != NULL && m_spScopeTreePersist->IsDirty() != S_FALSE);
  2304. if (bModified)
  2305. return TRUE;
  2306. // Loop thru and save each view
  2307. CAMCViewPosition pos = GetFirstAMCViewPosition();
  2308. while (pos != NULL)
  2309. {
  2310. // Get the view and skip if its the active view
  2311. CAMCView* const v = GetNextAMCView(pos);
  2312. if (v && v->IsDirty())
  2313. return TRUE;
  2314. }
  2315. // The views should be asked about dirty before
  2316. // asking the columns.
  2317. if ( (NULL != m_ConsoleData.m_spPersistStreamColumnData) &&
  2318. (S_OK == m_ConsoleData.m_spPersistStreamColumnData->IsDirty()) )
  2319. return TRUE;
  2320. // View data.
  2321. IPersistStreamPtr spIPeristStreamViewSettings;
  2322. SC sc = ScGetViewSettingsPersistorStream(&spIPeristStreamViewSettings);
  2323. if ( (! sc.IsError()) &&
  2324. (spIPeristStreamViewSettings != NULL) )
  2325. {
  2326. sc = spIPeristStreamViewSettings->IsDirty();
  2327. if (sc == S_OK)
  2328. return TRUE;
  2329. sc.TraceAndClear();
  2330. }
  2331. return CDocument::IsModified();
  2332. }
  2333. void CAMCDoc::OnUpdateFileSave(CCmdUI* pCmdUI)
  2334. {
  2335. pCmdUI->Enable (!IsReadOnly());
  2336. }
  2337. void CAMCDoc::OnConsoleAddremovesnapin()
  2338. {
  2339. ASSERT(m_spScopeTree != NULL);
  2340. // Can't run snap-in manager with active property sheets
  2341. CString strMsg;
  2342. LoadString(strMsg, IDS_SNAPINMGR_CLOSEPROPSHEET);
  2343. if (FArePropertySheetsOpen(&strMsg))
  2344. return;
  2345. m_spScopeTree->RunSnapIn(AfxGetMainWnd()->m_hWnd);
  2346. ::CoFreeUnusedLibraries();
  2347. }
  2348. void CAMCDoc::OnUpdateConsoleAddremovesnapin(CCmdUI* pCmdUI)
  2349. {
  2350. pCmdUI->Enable (m_spScopeTree != NULL);
  2351. }
  2352. /*--------------------------------------------------------------------------*
  2353. * CAMCDoc::SetMode
  2354. *
  2355. *
  2356. *--------------------------------------------------------------------------*/
  2357. void CAMCDoc::SetMode (ProgramMode eMode)
  2358. {
  2359. /*
  2360. * only set the modified flag if something actually changed
  2361. */
  2362. if (m_ConsoleData.m_eConsoleMode != eMode)
  2363. {
  2364. // should only be able to get here in author mode
  2365. ASSERT (AMCGetApp()->GetMode() == eMode_Author);
  2366. ASSERT (IsValidProgramMode (eMode));
  2367. m_ConsoleData.m_eConsoleMode = eMode;
  2368. SetModifiedFlag ();
  2369. }
  2370. }
  2371. /*+-------------------------------------------------------------------------*
  2372. * CAMCDoc::SetConsoleFlag
  2373. *
  2374. *
  2375. *--------------------------------------------------------------------------*/
  2376. void CAMCDoc::SetConsoleFlag (ConsoleFlags eFlag, bool fSet)
  2377. {
  2378. DWORD dwFlags = m_ConsoleData.m_dwFlags;
  2379. if (fSet)
  2380. dwFlags |= eFlag;
  2381. else
  2382. dwFlags &= ~eFlag;
  2383. /*
  2384. * only set the modified flag if something actually changed
  2385. */
  2386. if (m_ConsoleData.m_dwFlags != dwFlags)
  2387. {
  2388. m_ConsoleData.m_dwFlags = dwFlags;
  2389. SetModifiedFlag ();
  2390. }
  2391. }
  2392. /*+-------------------------------------------------------------------------*
  2393. *
  2394. * mappedModes
  2395. *
  2396. * PURPOSE: provides map to be used when persisting ProgramMode enumeration
  2397. *
  2398. * NOTE: do not remove/ change items unless you're sure no console
  2399. * files will be broken
  2400. *
  2401. *+-------------------------------------------------------------------------*/
  2402. static const EnumLiteral mappedModes[] =
  2403. {
  2404. { eMode_Author, XML_ENUM_PROGRAM_MODE_AUTHOR } ,
  2405. { eMode_User, XML_ENUM_PROGRAM_MODE_USER } ,
  2406. { eMode_User_MDI, XML_ENUM_PROGRAM_MODE_USER_MDI } ,
  2407. { eMode_User_SDI, XML_ENUM_PROGRAM_MODE_USER_SDI } ,
  2408. };
  2409. /*+-------------------------------------------------------------------------*
  2410. *
  2411. * CAMCDoc::Persist
  2412. *
  2413. * PURPOSE:
  2414. *
  2415. * PARAMETERS:
  2416. * CPersistor& persistor :
  2417. *
  2418. * RETURNS:
  2419. * void
  2420. *
  2421. *+-------------------------------------------------------------------------*/
  2422. void CAMCDoc::Persist(CPersistor& persistor)
  2423. {
  2424. DECLARE_SC (sc, _T("CAMCDoc::Persist"));
  2425. CAMCApp* pApp = AMCGetApp();
  2426. // check required pointers before going any further
  2427. sc = ScCheckPointers(m_spStringTable ? pApp : NULL, // + workaround to check more pointers
  2428. m_ConsoleData.m_pXMLPersistColumnData,
  2429. m_spScopeTree ? GetFavorites() : NULL, // + same workaround ^
  2430. E_POINTER);
  2431. if (sc)
  2432. sc.Throw();
  2433. // persist version of the document
  2434. CStr strFileVer = 0.;
  2435. if (persistor.IsStoring())
  2436. {
  2437. strFileVer = GetCurrentFileVersionAsString().c_str();
  2438. GUID guidConsoleId;
  2439. sc = CoCreateGuid(&guidConsoleId);
  2440. if (sc)
  2441. sc.Throw();
  2442. // this parameter is also updated in IDocConfig implementation
  2443. // update that code when changing following lines
  2444. CPersistor persistorGuid(persistor, XML_TAG_CONSOLE_FILE_UID);
  2445. persistorGuid.PersistContents(guidConsoleId);
  2446. }
  2447. persistor.PersistAttribute(XML_ATTR_CONSOLE_VERSION, strFileVer);
  2448. if (persistor.IsLoading())
  2449. {
  2450. // 'decode' the version
  2451. LPCTSTR pstrStart = strFileVer;
  2452. LPTSTR pstrStop = const_cast<LPTSTR>(pstrStart);
  2453. UINT uiMajorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2454. UINT uiMinorVer = 0;
  2455. if (pstrStop != pstrStart && *pstrStop == '.')
  2456. {
  2457. pstrStart = pstrStop + 1;
  2458. uiMinorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2459. }
  2460. UINT uiMinorSubVer = 0;
  2461. if (pstrStop != pstrStart && *pstrStop == '.')
  2462. {
  2463. pstrStart = pstrStop + 1;
  2464. uiMinorVer = _tcstol(pstrStart, &pstrStop, 10) ;
  2465. }
  2466. ConsoleFileVersion eVersion = (ConsoleFileVersion)MakeConsoleFileVer_(uiMajorVer,
  2467. uiMinorVer,
  2468. uiMinorSubVer);
  2469. m_ConsoleData.m_eFileVer = eVersion;
  2470. // BUGBUG: this needs to be changed when we implement 'dynamic' SC messages
  2471. if (eVersion != FileVer_Current)
  2472. sc.Throw(E_UNEXPECTED);
  2473. }
  2474. // Create a storage for binaries
  2475. // This will create "detached" XML element which may be used by persistor's
  2476. // childs to store binary informatio.
  2477. // (The element is attached to XML document by calling "CommitBinaryStorage()" )
  2478. if (persistor.IsStoring())
  2479. persistor.GetDocument().CreateBinaryStorage();
  2480. else
  2481. persistor.GetDocument().LocateBinaryStorage();
  2482. /*
  2483. * make sure the tree expansion happens synchronously
  2484. */
  2485. bool fSyncExpandWasRequired = m_spScopeTree->IsSynchronousExpansionRequired() == S_OK;
  2486. m_spScopeTree->RequireSynchronousExpansion (true);
  2487. // historically both loading and saving is to be done in certain order
  2488. // steps are ordered by storing order
  2489. const int STEP_FRAME = 1;
  2490. const int STEP_VIEWS = 2;
  2491. const int STEP_APP_MODE = 3;
  2492. const int STEP_CUST_DATA = 4;
  2493. const int STEP_FAVORITES = 5;
  2494. const int STEP_SCOPE_TREE = 6;
  2495. const int STEP_VIEW_DATA = 7;
  2496. const int STEP_COLUMN_DATA = 8;
  2497. const int STEP_STRING_TABLE = 9;
  2498. const int MIN_STEP = 1;
  2499. const int MAX_STEP = 9;
  2500. for (int iStep = persistor.IsStoring() ? MIN_STEP : MAX_STEP;
  2501. persistor.IsStoring() ? (iStep <= MAX_STEP) : (iStep >= MIN_STEP);
  2502. persistor.IsStoring() ? ++iStep : --iStep
  2503. )
  2504. {
  2505. switch(iStep)
  2506. {
  2507. case STEP_FRAME:
  2508. PersistFrame(persistor);
  2509. break;
  2510. case STEP_VIEWS:
  2511. PersistViews(persistor);
  2512. break;
  2513. case STEP_APP_MODE:
  2514. if (persistor.IsLoading())
  2515. {
  2516. // restore proper application mode
  2517. ProgramMode eMode;
  2518. // create wrapper to persist enumeration values as strings
  2519. CXMLEnumeration modeValuePersistor(eMode, mappedModes, countof(mappedModes));
  2520. // persist the wrapper
  2521. persistor.PersistAttribute(XML_ATTR_APPLICATION_MODE, modeValuePersistor);
  2522. pApp->SetMode(eMode);
  2523. }
  2524. break;
  2525. case STEP_CUST_DATA:
  2526. PersistCustomData (persistor);
  2527. break;
  2528. case STEP_FAVORITES:
  2529. persistor.Persist(*GetFavorites());
  2530. break;
  2531. case STEP_SCOPE_TREE:
  2532. // IDocConfig relies on tree to be under the document.
  2533. // revisit that code if you do the change here
  2534. sc = m_spScopeTree->Persist(reinterpret_cast<HPERSISTOR>(&persistor));
  2535. if (sc)
  2536. sc.Throw();
  2537. break;
  2538. case STEP_VIEW_DATA:
  2539. {
  2540. INodeCallbackPtr spNodeCallback;
  2541. sc = m_spScopeTree->QueryNodeCallback(&spNodeCallback);
  2542. if (sc)
  2543. sc.Throw();
  2544. sc = ScCheckPointers(spNodeCallback, E_UNEXPECTED);
  2545. if (sc)
  2546. sc.Throw();
  2547. CXMLObject *pXMLViewSettings = NULL;
  2548. sc = spNodeCallback->QueryViewSettingsPersistor(&pXMLViewSettings);
  2549. if (sc)
  2550. sc.Throw();
  2551. sc = ScCheckPointers(pXMLViewSettings, E_UNEXPECTED);
  2552. if (sc)
  2553. sc.Throw();
  2554. persistor.Persist(*pXMLViewSettings);
  2555. }
  2556. break;
  2557. case STEP_COLUMN_DATA:
  2558. persistor.Persist(*m_ConsoleData.m_pXMLPersistColumnData);
  2559. break;
  2560. case STEP_STRING_TABLE:
  2561. CMasterStringTable *pMasterStringTable = dynamic_cast<CMasterStringTable *>((IStringTablePrivate *)m_spStringTable);
  2562. if(!pMasterStringTable)
  2563. {
  2564. sc = E_UNEXPECTED;
  2565. sc.Throw();
  2566. }
  2567. persistor.Persist(*pMasterStringTable);
  2568. break;
  2569. }
  2570. }
  2571. m_spScopeTree->RequireSynchronousExpansion (fSyncExpandWasRequired);
  2572. SetModifiedFlag (false);
  2573. SetFrameModifiedFlag (false);
  2574. /*
  2575. * We shouldn't think that a freshly saved console file is
  2576. * dirty. If we do, someone's dirty bit processing is bogus.
  2577. */
  2578. ASSERT (!IsFrameModified());
  2579. /*
  2580. * Too many snap-ins leave themselves dirty after a load to leave this
  2581. * assert in, so we'll trace instead. Note that this trace doesn't
  2582. * always indicate a snap-in problem, but it frequently does.
  2583. */
  2584. #ifdef DBG
  2585. // ASSERT (!IsModified());
  2586. if (IsModified())
  2587. TraceErrorMsg (_T("CAMCDoc::IsModified returns true after %s"),
  2588. persistor.IsLoading() ? _T("opening") : _T("saving"));
  2589. #endif
  2590. // The element used to gather binary information is attached to XML document here
  2591. // Physically it will reside after all elements already added to persistor
  2592. if (persistor.IsStoring())
  2593. persistor.GetDocument().CommitBinaryStorage();
  2594. }
  2595. void CAMCDoc::PersistViews(CPersistor& persistor)
  2596. {
  2597. DECLARE_SC(sc, TEXT("CAMCDoc::PersistViews"));
  2598. if (persistor.IsLoading())
  2599. {
  2600. // Read templates for new views
  2601. CViewTemplateList view_list(XML_TAG_VIEW_LIST);
  2602. persistor.Persist(view_list);
  2603. // Get the means for enumerating loaded collection
  2604. CViewTemplateList::List_Type &rList = view_list.GetList();
  2605. CViewTemplateList::List_Type::iterator it;
  2606. // Enumerate all the views to be created
  2607. // Create them one-by-one
  2608. for (it = rList.begin(); it != rList.end(); ++it)
  2609. {
  2610. // extract information for the new view
  2611. int iViewID = it->first;
  2612. const CBookmark& pbm = it->second.first;
  2613. CPersistor& v_persistor = it->second.second;
  2614. // create it!
  2615. sc = ScCreateAndLoadView(v_persistor, iViewID, pbm);
  2616. if (sc)
  2617. sc.Throw();
  2618. }
  2619. }
  2620. else // if (persistor.IsStoring())
  2621. {
  2622. CPersistor persistorViews(persistor, XML_TAG_VIEW_LIST);
  2623. /*
  2624. * Bug 3504: enumerate views in z-order (bottom-to-top) so the
  2625. * z-order will be restored correctly on reload
  2626. */
  2627. CMainFrame* pMainFrame = AMCGetMainWnd();
  2628. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  2629. if (sc)
  2630. sc.Throw();
  2631. /*
  2632. * get the top-most MDI child
  2633. */
  2634. CWnd* pwndMDIChild = pMainFrame->MDIGetActive();
  2635. sc = ScCheckPointers (pwndMDIChild, E_UNEXPECTED);
  2636. if (sc)
  2637. sc.Throw();
  2638. /*
  2639. * iterate through each of the MDI children
  2640. */
  2641. for (pwndMDIChild = pwndMDIChild->GetWindow (GW_HWNDLAST);
  2642. pwndMDIChild != NULL;
  2643. pwndMDIChild = pwndMDIChild->GetNextWindow (GW_HWNDPREV))
  2644. {
  2645. /*
  2646. * turn the generic CMDIChildWnd into a CChildFrame
  2647. */
  2648. CChildFrame* pChildFrame = dynamic_cast<CChildFrame*>(pwndMDIChild);
  2649. sc = ScCheckPointers (pChildFrame, E_UNEXPECTED);
  2650. if (sc)
  2651. sc.Throw();
  2652. /*
  2653. * get the view for this child frame
  2654. */
  2655. CAMCView* pwndView = pChildFrame->GetAMCView();
  2656. sc = ScCheckPointers (pwndView, E_UNEXPECTED);
  2657. if (sc)
  2658. sc.Throw();
  2659. // skip those not persistible
  2660. if ( !pwndView->IsPersisted() )
  2661. continue;
  2662. /*
  2663. * persist the view
  2664. */
  2665. persistorViews.Persist (*pwndView);
  2666. }
  2667. }
  2668. }
  2669. void CAMCDoc::PersistFrame(CPersistor& persistor)
  2670. {
  2671. DECLARE_SC(sc, TEXT("CAMCDoc::PersistFrame"));
  2672. CFrameState fs2 (m_ConsoleData.m_eConsoleMode, m_ConsoleData.m_dwFlags);
  2673. ASSERT (fs2.wndplFrame.length == sizeof (WINDOWPLACEMENT));
  2674. CMainFrame* pMainFrame = AMCGetMainWnd();
  2675. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  2676. if (sc)
  2677. sc.Throw();
  2678. if (persistor.IsStoring())
  2679. {
  2680. // Get the attributes of the window.
  2681. if (!pMainFrame->GetWindowPlacement (&fs2.wndplFrame))
  2682. sc.Throw(E_FAIL);
  2683. if (fs2.wndplFrame.showCmd == SW_SHOWMINIMIZED)
  2684. fs2.wndplFrame.showCmd = SW_SHOWNORMAL;
  2685. }
  2686. persistor.Persist(fs2);
  2687. // this application setting (AppMode) is resored in AMCDoc::Persist, but saved/loaded here
  2688. // create wrapper to persist enumeration values as strings
  2689. CXMLEnumeration modeValuePersistor(m_ConsoleData.m_eConsoleMode, mappedModes, countof(mappedModes));
  2690. // persist the wrapper
  2691. persistor.PersistAttribute(XML_ATTR_APPLICATION_MODE, modeValuePersistor);
  2692. if (persistor.IsLoading())
  2693. {
  2694. // Set the windows size and location and state
  2695. CAMCApp* pApp = AMCGetApp();
  2696. pApp->UpdateFrameWindow(true);
  2697. pMainFrame->UpdateChildSystemMenus();
  2698. // the status bar is on the child frame now
  2699. // pMainFrame->ShowStatusBar ((fs2.dwFlags & eFlag_ShowStatusBar) != 0);
  2700. // save the data from the file into the console data
  2701. m_ConsoleData.m_eAppMode = pApp->GetMode();
  2702. m_ConsoleData.m_dwFlags = fs2.dwFlags;
  2703. InsurePlacementIsOnScreen (fs2.wndplFrame);
  2704. // if we're initializing, defer the actual show until initialization is complete
  2705. // same if script is under control and MMC is hidden
  2706. if (pApp->IsInitializing()
  2707. || ( !pApp->IsUnderUserControl() && !pMainFrame->IsWindowVisible() ) )
  2708. {
  2709. pApp->m_nCmdShow = fs2.wndplFrame.showCmd;
  2710. fs2.wndplFrame.showCmd = SW_HIDE;
  2711. }
  2712. if (!pMainFrame->SetWindowPlacement (&fs2.wndplFrame))
  2713. sc.Throw(E_FAIL);
  2714. }
  2715. }
  2716. /*--------------------------------------------------------------------------*
  2717. * CDocument::DoFileSave
  2718. *
  2719. * This is almost identical to CDocument::DoFileSave. We just override it
  2720. * here because we want to display a message for a read-only file before
  2721. * throwing up the Save As dialog.
  2722. *--------------------------------------------------------------------------*/
  2723. BOOL CAMCDoc::DoFileSave()
  2724. {
  2725. DWORD dwAttrib = GetFileAttributes(m_strPathName);
  2726. // attributes does not matter for user modes - it does not
  2727. // save to the original console file anyway
  2728. if ((AMCGetApp()->GetMode() == eMode_Author) &&
  2729. (dwAttrib != 0xFFFFFFFF) &&
  2730. (dwAttrib & FILE_ATTRIBUTE_READONLY))
  2731. {
  2732. CString strMessage;
  2733. FormatString1 (strMessage, IDS_CONSOLE_READONLY, m_strPathName);
  2734. MMCMessageBox (strMessage);
  2735. // we do not have read-write access or the file does not (now) exist
  2736. if (!DoSave(NULL))
  2737. {
  2738. TRACE0("Warning: File save with new name failed.\n");
  2739. return FALSE;
  2740. }
  2741. }
  2742. else
  2743. {
  2744. if (!DoSave(m_strPathName))
  2745. {
  2746. TRACE0("Warning: File save failed.\n");
  2747. return FALSE;
  2748. }
  2749. }
  2750. return TRUE;
  2751. }
  2752. /*--------------------------------------------------------------------------*
  2753. * CAMCDoc::GetDefaultMenu
  2754. *
  2755. *
  2756. *--------------------------------------------------------------------------*/
  2757. HMENU CAMCDoc::GetDefaultMenu()
  2758. {
  2759. return (AMCGetApp()->GetMenu ());
  2760. }
  2761. /*+-------------------------------------------------------------------------*
  2762. * CAMCDoc::GetCustomIcon
  2763. *
  2764. * Returns the small or large custom icon for the console. Ownership of and
  2765. * deletion responsibility for the icon is retained by CAMCDoc.
  2766. *--------------------------------------------------------------------------*/
  2767. HICON CAMCDoc::GetCustomIcon (bool fLarge, CString* pstrIconFile, int* pnIconIndex) const
  2768. {
  2769. DECLARE_SC (sc, _T("CAMCDoc::ScGetCustomIcon"));
  2770. /*
  2771. * if caller wants either the icon filename or index returned, get them
  2772. */
  2773. if ((pstrIconFile != NULL) || (pnIconIndex != NULL))
  2774. {
  2775. CPersistableIconData IconData;
  2776. m_CustomIcon.GetData (IconData);
  2777. if (pstrIconFile != NULL)
  2778. *pstrIconFile = IconData.m_strIconFile.data();
  2779. if (pnIconIndex != NULL)
  2780. *pnIconIndex = IconData.m_nIndex;
  2781. }
  2782. /*
  2783. * return the icon (m_CustomIcon will hold the reference for the
  2784. * caller)
  2785. */
  2786. CSmartIcon icon;
  2787. sc = m_CustomIcon.GetIcon ((fLarge) ? 32 : 16, icon);
  2788. if (sc)
  2789. return (NULL);
  2790. return (icon);
  2791. }
  2792. /*+-------------------------------------------------------------------------*
  2793. * CAMCDoc::SetCustomIcon
  2794. *
  2795. *
  2796. *--------------------------------------------------------------------------*/
  2797. void CAMCDoc::SetCustomIcon (LPCTSTR pszIconFile, int nIconIndex)
  2798. {
  2799. DECLARE_SC (sc, _T("CAMCDoc::SetCustomIcon"));
  2800. CPersistableIconData IconData (pszIconFile, nIconIndex) ;
  2801. /*
  2802. * if there's no change, bail
  2803. */
  2804. if (m_CustomIcon == IconData)
  2805. return;
  2806. m_CustomIcon = IconData;
  2807. HICON hLargeIcon = GetCustomIcon (true /*fLarge*/);
  2808. HICON hSmallIcon = GetCustomIcon (false /*fLarge*/);
  2809. CMainFrame* pMainFrame = AMCGetMainWnd();
  2810. sc = ScCheckPointers (hLargeIcon, hSmallIcon, pMainFrame, E_UNEXPECTED);
  2811. if (sc)
  2812. return;
  2813. /*
  2814. * change the icon on the frame
  2815. */
  2816. pMainFrame->SetIconEx (hLargeIcon, true);
  2817. pMainFrame->SetIconEx (hSmallIcon, false);
  2818. /*
  2819. * change the icon on each MDI window
  2820. */
  2821. CWnd* pMDIChild = pMainFrame->MDIGetActive();
  2822. while (pMDIChild != NULL)
  2823. {
  2824. ASSERT_KINDOF (CMDIChildWnd, pMDIChild);
  2825. pMDIChild->SetIcon (hLargeIcon, true);
  2826. pMDIChild->SetIcon (hSmallIcon, false);
  2827. pMDIChild = pMDIChild->GetWindow (GW_HWNDNEXT);
  2828. }
  2829. SetModifiedFlag();
  2830. }
  2831. /*+-------------------------------------------------------------------------*
  2832. * CAMCDoc::LoadCustomData
  2833. *
  2834. *
  2835. *--------------------------------------------------------------------------*/
  2836. bool CAMCDoc::LoadCustomData (IStorage* pStorage)
  2837. {
  2838. HRESULT hr;
  2839. IStoragePtr spCustomDataStorage;
  2840. hr = OpenDebugStorage (pStorage, g_pszCustomDataStorage,
  2841. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2842. &spCustomDataStorage);
  2843. if (FAILED (hr))
  2844. return (true);
  2845. LoadCustomIconData (spCustomDataStorage);
  2846. LoadCustomTitleData (spCustomDataStorage);
  2847. return (true);
  2848. }
  2849. /*+-------------------------------------------------------------------------*
  2850. * CAMCDoc::LoadCustomIconData
  2851. *
  2852. *
  2853. *--------------------------------------------------------------------------*/
  2854. bool CAMCDoc::LoadCustomIconData (IStorage* pStorage)
  2855. {
  2856. HRESULT hr = m_CustomIcon.Load (pStorage);
  2857. if (FAILED (hr))
  2858. return (false);
  2859. /*
  2860. * If we get here, we have a custom icon. The view windows
  2861. * (MDI children) haven't been created yet -- they'll get the
  2862. * right icons automatically. The main frame, however, already
  2863. * exists, so we have to explicitly set its icon here.
  2864. */
  2865. CWnd* pMainWnd = AfxGetMainWnd();
  2866. pMainWnd->SetIcon (GetCustomIcon (true), true);
  2867. pMainWnd->SetIcon (GetCustomIcon (false), false);
  2868. return (true);
  2869. }
  2870. /*+-------------------------------------------------------------------------*
  2871. * CAMCDoc::LoadCustomTitleData
  2872. *
  2873. *
  2874. *--------------------------------------------------------------------------*/
  2875. bool CAMCDoc::LoadCustomTitleData (IStorage* pStorage)
  2876. {
  2877. do // not a loop
  2878. {
  2879. /*
  2880. * Open the custom title data stream. It may not exist, and
  2881. * that's OK if it doesn't. It just means we don't have a
  2882. * custom title.
  2883. */
  2884. USES_CONVERSION;
  2885. HRESULT hr;
  2886. IStreamPtr spStream;
  2887. hr = OpenDebugStream (pStorage, AMCCustomTitleStreamName,
  2888. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2889. &spStream);
  2890. BREAK_ON_FAIL (hr);
  2891. try
  2892. {
  2893. /*
  2894. * Read the stream version
  2895. */
  2896. DWORD dwVersion;
  2897. *spStream >> dwVersion;
  2898. /*
  2899. * if this is the beta custom title format, migrate it forward
  2900. */
  2901. switch (dwVersion)
  2902. {
  2903. case 0:
  2904. {
  2905. /*
  2906. * Read the length (in bytes) of the title
  2907. */
  2908. WORD cbTitle;
  2909. *spStream >> cbTitle;
  2910. const WORD cchTitle = cbTitle / sizeof (WCHAR);
  2911. /*
  2912. * Read the title
  2913. */
  2914. std::auto_ptr<WCHAR> spwzWideTitle (new WCHAR[cchTitle + 1]);
  2915. LPWSTR pwzWideTitle = spwzWideTitle.get();
  2916. DWORD cbRead;
  2917. hr = spStream->Read (pwzWideTitle, cbTitle, &cbRead);
  2918. BREAK_ON_FAIL (hr);
  2919. if (cbRead != cbTitle)
  2920. break;
  2921. /*
  2922. * terminate and convert the title string
  2923. */
  2924. pwzWideTitle[cchTitle] = 0;
  2925. if (m_pstrCustomTitle != NULL)
  2926. *m_pstrCustomTitle = W2T (pwzWideTitle);
  2927. break;
  2928. }
  2929. case 1:
  2930. if (m_pstrCustomTitle != NULL)
  2931. *spStream >> (*m_pstrCustomTitle);
  2932. break;
  2933. default:
  2934. ASSERT (false);
  2935. break;
  2936. }
  2937. }
  2938. catch (_com_error& err)
  2939. {
  2940. hr = err.Error();
  2941. ASSERT (false && "Caught _com_error");
  2942. break;
  2943. }
  2944. catch (CMemoryException* pe)
  2945. {
  2946. pe->Delete();
  2947. _com_issue_error (E_OUTOFMEMORY);
  2948. }
  2949. } while (false);
  2950. return (true);
  2951. }
  2952. bool CAMCDoc::HasCustomTitle () const
  2953. {
  2954. if(!m_pstrCustomTitle)
  2955. return false;
  2956. return (!m_pstrCustomTitle->str().empty());
  2957. }
  2958. /*+-------------------------------------------------------------------------*
  2959. * CAMCDoc::LoadStringTable
  2960. *
  2961. *
  2962. *--------------------------------------------------------------------------*/
  2963. bool CAMCDoc::LoadStringTable (IStorage* pStorage)
  2964. {
  2965. DECLARE_SC (sc, _T("CAMCDoc::LoadStringTable"));
  2966. /*
  2967. * open the string table storage
  2968. */
  2969. IStoragePtr spStringTableStg;
  2970. HRESULT hr = OpenDebugStorage (pStorage, AMCStringTableStorageName,
  2971. STGM_SHARE_EXCLUSIVE | STGM_READ,
  2972. &spStringTableStg);
  2973. /*
  2974. * If there's no string table, things are OK. We allow this so
  2975. * we can continue to open older console files.
  2976. */
  2977. if (hr == STG_E_FILENOTFOUND)
  2978. return (true);
  2979. if (SUCCEEDED (hr))
  2980. {
  2981. /*
  2982. * read the string table from the storage
  2983. */
  2984. try
  2985. {
  2986. CMasterStringTable *pMasterStringTable = dynamic_cast<CMasterStringTable *>((IStringTablePrivate *)m_spStringTable);
  2987. if(!pMasterStringTable)
  2988. {
  2989. sc = E_UNEXPECTED;
  2990. sc.Throw();
  2991. }
  2992. *spStringTableStg >> *pMasterStringTable;
  2993. }
  2994. catch (_com_error& err)
  2995. {
  2996. hr = err.Error();
  2997. ASSERT (false && "Caught _com_error");
  2998. }
  2999. }
  3000. return (SUCCEEDED (hr));
  3001. }
  3002. /*+-------------------------------------------------------------------------*
  3003. * CAMCDoc::SetCustomTitle
  3004. *
  3005. *
  3006. *--------------------------------------------------------------------------*/
  3007. void CAMCDoc::SetCustomTitle (CString strNewTitle)
  3008. {
  3009. DECLARE_SC (sc, _T("CAMCDoc::SetCustomTitle"));
  3010. if(!m_pstrCustomTitle)
  3011. return;
  3012. /*
  3013. * if there's no change, just short out
  3014. */
  3015. if ((*m_pstrCustomTitle) == strNewTitle)
  3016. return;
  3017. /*
  3018. * copy the new custom title
  3019. */
  3020. (*m_pstrCustomTitle) = strNewTitle;
  3021. /*
  3022. * force the frame to update
  3023. */
  3024. CMainFrame* pMainFrame = AMCGetMainWnd();
  3025. sc = ScCheckPointers (pMainFrame, E_UNEXPECTED);
  3026. if (sc)
  3027. return;
  3028. pMainFrame->OnUpdateFrameTitle (false);
  3029. SetModifiedFlag();
  3030. }
  3031. /*+-------------------------------------------------------------------------*
  3032. * CAMCDoc::GetCustomTitle
  3033. *
  3034. *
  3035. *--------------------------------------------------------------------------*/
  3036. CString CAMCDoc::GetCustomTitle() const
  3037. {
  3038. if (HasCustomTitle())
  3039. return (m_pstrCustomTitle->data());
  3040. CString strTitle = GetTitle();
  3041. /*
  3042. * strip the extension (extensions, including a separator,
  3043. * are 4 characters or less)
  3044. */
  3045. int nExtSeparator = strTitle.ReverseFind (_T('.'));
  3046. if ((nExtSeparator != -1) && ((strTitle.GetLength()-nExtSeparator) <= 4))
  3047. strTitle = strTitle.Left (nExtSeparator);
  3048. return (strTitle);
  3049. }
  3050. /*+-------------------------------------------------------------------------*
  3051. * CAMCDoc::GetStringTable
  3052. *
  3053. *
  3054. *--------------------------------------------------------------------------*/
  3055. IStringTablePrivate* CAMCDoc::GetStringTable() const
  3056. {
  3057. return m_spStringTable;
  3058. }
  3059. /*+-------------------------------------------------------------------------*
  3060. * CAMCDoc::LoadFavorites
  3061. *
  3062. *
  3063. *--------------------------------------------------------------------------*/
  3064. bool CAMCDoc::LoadFavorites ()
  3065. {
  3066. ASSERT(m_spStorage != NULL);
  3067. // Open the stream for the cache
  3068. IStreamPtr spStream;
  3069. HRESULT hr = OpenDebugStream(m_spStorage, AMCFavoritesStreamName,
  3070. STGM_SHARE_EXCLUSIVE | STGM_READWRITE, L"FavoritesStream", &spStream);
  3071. if (FAILED(hr)) // did not find the stream - could be an older version.
  3072. return hr;
  3073. hr = GetFavorites()->Read(spStream);
  3074. return (SUCCEEDED (hr));
  3075. }
  3076. void ShowAdminToolsOnMenu(LPCTSTR lpszFilename)
  3077. {
  3078. static const TCHAR szAdminKey[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
  3079. static const TCHAR szAdminValue[] = _T("StartMenuAdminTools");
  3080. static const TCHAR szBroadcastParam[] = _T("ShellMenu");
  3081. static const TCHAR szYes[] = _T("YES");
  3082. CString strPath(lpszFilename);
  3083. int nLastSepIndex = strPath.ReverseFind (_T('\\'));
  3084. if (nLastSepIndex != -1)
  3085. {
  3086. // if we got "d:\filename", make sure to include the trailing separator
  3087. if (nLastSepIndex < 3)
  3088. nLastSepIndex++;
  3089. // Form full path name (accounting for current directory info)
  3090. TCHAR szFullPathName[MAX_PATH];
  3091. GetFullPathName (strPath.Left(nLastSepIndex), countof(szFullPathName),
  3092. szFullPathName, NULL);
  3093. // if saving to admin tools
  3094. if (AMCGetApp()->GetDefaultDirectory() == szFullPathName)
  3095. {
  3096. // set reg key to add admin tools to start menu
  3097. HKEY hkey;
  3098. long r = RegOpenKeyEx (HKEY_CURRENT_USER, szAdminKey, 0, KEY_ALL_ACCESS, &hkey);
  3099. ASSERT(r == ERROR_SUCCESS);
  3100. if (r == ERROR_SUCCESS)
  3101. {
  3102. // get current value
  3103. TCHAR szBuffer[4];
  3104. DWORD dwType = REG_SZ;
  3105. DWORD dwCount = sizeof(szBuffer);
  3106. r = RegQueryValueEx (hkey, szAdminValue, NULL, &dwType,(LPBYTE)szBuffer, &dwCount);
  3107. // if value isn't "YES" then change it, and broadcast change message
  3108. if (r != ERROR_SUCCESS || dwType != REG_SZ || lstrcmpi(szBuffer, szYes) != 0)
  3109. {
  3110. r = RegSetValueEx (hkey, szAdminValue, NULL, REG_SZ, (CONST BYTE *)szYes, sizeof(szYes));
  3111. ASSERT(r == ERROR_SUCCESS);
  3112. ULONG_PTR dwRes;
  3113. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)0,
  3114. (LPARAM)szBroadcastParam, SMTO_ABORTIFHUNG|SMTO_NORMAL, 100, &dwRes);
  3115. }
  3116. RegCloseKey(hkey);
  3117. }
  3118. }
  3119. }
  3120. }
  3121. void CAMCDoc::PersistCustomData (CPersistor &persistor)
  3122. {
  3123. CPersistor persistorCustom(persistor, XML_TAG_CUSTOM_DATA);
  3124. // persist custom title
  3125. // It may not exist, and that's OK if it doesn't.
  3126. // It just means we don't have a custom title.
  3127. if ((persistorCustom.IsLoading()
  3128. && persistorCustom.HasElement(XML_TAG_STRING_TABLE_STRING, XML_ATTR_CUSTOM_TITLE))
  3129. || (persistorCustom.IsStoring() && HasCustomTitle()))
  3130. {
  3131. if(m_pstrCustomTitle)
  3132. persistorCustom.PersistString(XML_ATTR_CUSTOM_TITLE, *m_pstrCustomTitle);
  3133. }
  3134. // persist custom icon
  3135. CXMLPersistableIcon persIcon(m_CustomIcon);
  3136. bool bHasIcon = persistorCustom.IsLoading() && persistorCustom.HasElement(persIcon.GetXMLType(), NULL);
  3137. bHasIcon = bHasIcon || persistorCustom.IsStoring() && HasCustomIcon();
  3138. if (!bHasIcon)
  3139. return;
  3140. persistorCustom.Persist(persIcon);
  3141. if (persistorCustom.IsLoading())
  3142. {
  3143. CWnd* pMainWnd = AfxGetMainWnd();
  3144. pMainWnd->SetIcon (GetCustomIcon (true), true);
  3145. pMainWnd->SetIcon (GetCustomIcon (false), false);
  3146. }
  3147. }
  3148. /***************************************************************************\
  3149. *
  3150. * METHOD: GetCurrentFileVersionAsString
  3151. *
  3152. * PURPOSE: formats current file version and returns a string
  3153. *
  3154. * PARAMETERS:
  3155. *
  3156. * RETURNS:
  3157. * CString - resulting string
  3158. *
  3159. \***************************************************************************/
  3160. tstring GetCurrentFileVersionAsString()
  3161. {
  3162. TCHAR szFileVersion[16];
  3163. // get file version data
  3164. UINT uiMajorVer = GetConsoleFileMajorVersion(FileVer_Current);
  3165. UINT uiMinorVer = GetConsoleFileMinorVersion(FileVer_Current);
  3166. UINT uiMinorSubVer = GetConsoleFileMinorSubversion(FileVer_Current);
  3167. if (uiMinorSubVer)
  3168. wsprintf (szFileVersion, _T("%d.%d.%d"), uiMajorVer, uiMinorVer, uiMinorSubVer);
  3169. else
  3170. wsprintf (szFileVersion, _T("%d.%d"), uiMajorVer, uiMinorVer);
  3171. return szFileVersion;
  3172. }
  3173. /***************************************************************************\
  3174. *
  3175. * METHOD: CAMCDoc::ScOnSnapinAdded
  3176. *
  3177. * PURPOSE: Script event firing helper. Implements interface accessible from
  3178. * node manager
  3179. *
  3180. * PARAMETERS:
  3181. * PSNAPIN pSnapIn [in] - snapin added to the console
  3182. *
  3183. * RETURNS:
  3184. * SC - result code
  3185. *
  3186. \***************************************************************************/
  3187. SC CAMCDoc::ScOnSnapinAdded(PSNAPIN pSnapIn)
  3188. {
  3189. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnSnapinAdded"));
  3190. CAMCApp* pApp = AMCGetApp();
  3191. // check
  3192. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3193. if (sc)
  3194. return sc;
  3195. // forward
  3196. sc = pApp->ScOnSnapinAdded(this, pSnapIn);
  3197. if (sc)
  3198. return sc;
  3199. return sc;
  3200. }
  3201. /***************************************************************************\
  3202. *
  3203. * METHOD: CAMCDoc::ScOnSnapinRemoved
  3204. *
  3205. * PURPOSE: Script event firing helper. Implements interface accessible from
  3206. * node manager
  3207. *
  3208. * PARAMETERS:
  3209. * PSNAPIN pSnapIn [in] - snapin removed from console
  3210. *
  3211. * RETURNS:
  3212. * SC - result code
  3213. *
  3214. \***************************************************************************/
  3215. SC CAMCDoc::ScOnSnapinRemoved(PSNAPIN pSnapIn)
  3216. {
  3217. DECLARE_SC(sc, TEXT("CAMCDoc::ScOnSnapinRemoved"));
  3218. CAMCApp* pApp = AMCGetApp();
  3219. // check
  3220. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3221. if (sc)
  3222. return sc;
  3223. // forward
  3224. sc = pApp->ScOnSnapinRemoved(this, pSnapIn);
  3225. if (sc)
  3226. return sc;
  3227. return sc;
  3228. }
  3229. //+-------------------------------------------------------------------
  3230. //
  3231. // Member: CAMCDoc::ScSetHelpCollectionInvalid
  3232. //
  3233. // Synopsis: A snapin is added/removed or extension is
  3234. // enabled/disabled therefore help collection
  3235. // no longer reflects current console file.
  3236. //
  3237. // Arguments:
  3238. //
  3239. // Returns: SC
  3240. //
  3241. //--------------------------------------------------------------------
  3242. SC CAMCDoc::ScSetHelpCollectionInvalid ()
  3243. {
  3244. DECLARE_SC(sc, _T("CAMCDoc::ScSetHelpCollectionInvalid"));
  3245. HELPDOCINFO *pHelpDocInfo = GetHelpDocInfo();
  3246. sc = ScCheckPointers(pHelpDocInfo, E_UNEXPECTED);
  3247. if (sc)
  3248. return sc;
  3249. // console file modify time has to be updated for help collection.
  3250. GetSystemTimeAsFileTime(&pHelpDocInfo->m_ftimeModify);
  3251. return (sc);
  3252. }
  3253. SC CAMCDoc::Scget_Application(PPAPPLICATION ppApplication)
  3254. {
  3255. DECLARE_SC(sc, TEXT("CAMCDoc::Scget_Application"));
  3256. // parameter check
  3257. sc = ScCheckPointers(ppApplication, E_UNEXPECTED);
  3258. if (sc)
  3259. return sc;
  3260. // initialization
  3261. *ppApplication = NULL;
  3262. CAMCApp* pApp = AMCGetApp();
  3263. // check
  3264. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  3265. if (sc)
  3266. return sc;
  3267. sc = pApp->ScGet_Application(ppApplication);
  3268. if (sc)
  3269. return sc;
  3270. return sc;
  3271. }