Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3846 lines
115 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: amc.cpp
  7. //
  8. // Contents: The one and only app
  9. //
  10. // History: 01-Jan-96 TRomano Created
  11. // 16-Jul-96 WayneSc Add code to switch views
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include "AMC.h"
  16. #include "MainFrm.h"
  17. #include "ChildFrm.h"
  18. #include "AMCDoc.h"
  19. #include "AMCView.h"
  20. #include "amcdocmg.h"
  21. #include "sysmenu.h"
  22. #include <shlobj.h>
  23. #include "strings.h"
  24. #include "macros.h"
  25. #include "scripthost.h"
  26. #include "HtmlHelp.h"
  27. #include "scriptevents.h"
  28. #include "mmcutil.h"
  29. #include "guidhelp.h" // for CLSID relational operators
  30. #include "archpicker.h"
  31. #include "classreg.h"
  32. #define DECLSPEC_UUID(x) __declspec(uuid(x))
  33. #include "websnk.h"
  34. #include "websnk_i.c"
  35. // We aren't picking this up from winuser.h for some reason.
  36. #define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID MAKEINTRESOURCE(3)
  37. /*
  38. * define our own Win64 symbol to make it easy to include 64-bit only
  39. * code in the 32-bit build, so we can exercise some code on 32-bit Windows
  40. * where the debuggers are better
  41. */
  42. #ifdef _WIN64
  43. #define MMC_WIN64
  44. #endif
  45. #ifndef MMC_WIN64
  46. #include <wow64t.h> // for Wow64DisableFilesystemRedirector
  47. #endif
  48. /*
  49. * multimon.h is included by stdafx.h, without defining COMPILE_MULTIMON_STUBS
  50. * first. We need to include it again here after defining COMPILE_MULTIMON_STUBS
  51. * so we'll get the stub functions.
  52. */
  53. #if (_WIN32_WINNT < 0x0500)
  54. #define COMPILE_MULTIMON_STUBS
  55. #include <multimon.h>
  56. #endif
  57. #ifdef DBG
  58. CTraceTag tagEnableScriptEngines(_T("MMCScriptEngines"), _T("Enable"));
  59. CTraceTag tag32BitTransfer(_T("64/32-bit interop"), _T("64/32-bit interop"));
  60. #endif
  61. // Note: These strings do not need to be localizable.
  62. const TCHAR CAMCApp::m_szSettingsSection[] = _T("Settings");
  63. const TCHAR CAMCApp::m_szUserDirectoryEntry[] = _T("Save Location");
  64. bool CanCloseDoc(void);
  65. SC ScExpandEnvironmentStrings (CString& str);
  66. //############################################################################
  67. //############################################################################
  68. //
  69. // ATL Support
  70. //
  71. //############################################################################
  72. //############################################################################
  73. #include <atlimpl.cpp>
  74. #include <atlwin.cpp>
  75. // The one and only instance of CAtlGlobalModule
  76. CAtlGlobalModule _Module;
  77. //############################################################################
  78. //############################################################################
  79. //
  80. // Trace Tags
  81. //
  82. //############################################################################
  83. //############################################################################
  84. #ifdef DBG
  85. // enable this tag if you suspect memory corruption
  86. // and you don't mind things slowing way down
  87. BEGIN_TRACETAG(CDebugCRTCheck)
  88. void OnEnable()
  89. {
  90. _CrtSetDbgFlag (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
  91. | _CRTDBG_CHECK_ALWAYS_DF
  92. | _CRTDBG_DELAY_FREE_MEM_DF);
  93. }
  94. void OnDisable()
  95. {
  96. _CrtSetDbgFlag (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
  97. & ~(_CRTDBG_CHECK_ALWAYS_DF
  98. | _CRTDBG_DELAY_FREE_MEM_DF) );
  99. }
  100. END_TRACETAG(CDebugCRTCheck, TEXT("Debug CRTs"), TEXT("Memory Check - SLOW!"))
  101. CTraceTag tagAMCAppInit(TEXT("CAMCView"), TEXT("InitInstance"));
  102. CTraceTag tagATLLock(TEXT("ATL"), TEXT("Lock/Unlock")); // used by atlconui.h
  103. CTraceTag tagGDIBatching(TEXT("CAMCView"), TEXT("Disable Graphics/GDI Batching"));
  104. CTraceTag tagForceMirror(TEXT("Mirroring"), TEXT("Force MMC windows to be mirrored on non-mirrored systems"));
  105. #endif
  106. //############################################################################
  107. //############################################################################
  108. //
  109. // Implementation of class CMMCApplication - the root level
  110. // automation class
  111. //
  112. //############################################################################
  113. //############################################################################
  114. class CMMCApplication :
  115. public CMMCIDispatchImpl<_Application, &CLSID_Application>,
  116. public CComCoClass<CMMCApplication, &CLSID_Application>,
  117. // support for connection points (script events)
  118. public IConnectionPointContainerImpl<CMMCApplication>,
  119. public IConnectionPointImpl<CMMCApplication, &DIID_AppEvents, CComDynamicUnkArray>,
  120. public IProvideClassInfo2Impl<&CLSID_Application, &DIID_AppEvents, &LIBID_MMC20>
  121. {
  122. public:
  123. BEGIN_MMC_COM_MAP(CMMCApplication)
  124. COM_INTERFACE_ENTRY(IProvideClassInfo)
  125. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  126. COM_INTERFACE_ENTRY(IConnectionPointContainer)
  127. END_MMC_COM_MAP()
  128. DECLARE_NOT_AGGREGATABLE(CMMCApplication)
  129. static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
  130. {
  131. CObjectRegParams op (
  132. CLSID_Application,
  133. _T("mmc.exe"),
  134. _T("MMC Application Class"),
  135. _T("MMC20.Application.1"),
  136. _T("MMC20.Application"),
  137. _T("LocalServer32") );
  138. return (MMCUpdateRegistry (bRegister, &op, NULL));
  139. }
  140. //hooks into ATL's construction
  141. HRESULT InternalFinalConstructRelease(); // not FinalConstruct() - this is to work around a bogus ATL assert.
  142. BEGIN_CONNECTION_POINT_MAP(CMMCApplication)
  143. CONNECTION_POINT_ENTRY(DIID_AppEvents)
  144. END_CONNECTION_POINT_MAP()
  145. // overriden to do more job than the base class does
  146. virtual ::SC ScOnDisconnectObjects();
  147. private:
  148. //IMMCApplication
  149. public:
  150. void STDMETHODCALLTYPE Help();
  151. void STDMETHODCALLTYPE Quit();
  152. STDMETHOD(get_Document) (Document **ppDocument);
  153. STDMETHOD(Load) (BSTR bstrFilename);
  154. STDMETHOD(get_Frame) (Frame **ppFrame);
  155. STDMETHOD(get_Visible) (BOOL *pVisible);
  156. STDMETHOD(Show) ();
  157. STDMETHOD(Hide) ();
  158. STDMETHOD(get_UserControl) (PBOOL pUserControl);
  159. STDMETHOD(put_UserControl) (BOOL bUserControl);
  160. STDMETHOD(get_VersionMajor) (PLONG pVersionMajor);
  161. STDMETHOD(get_VersionMinor) (PLONG pVersionMinor);
  162. private:
  163. // Return the CAMCApp only if it is initialized. We do not want
  164. // object model methods to operate on app while initializing.
  165. CAMCApp *GetApp()
  166. {
  167. CAMCApp *pApp = AMCGetApp();
  168. if ( (! pApp) || (pApp->IsInitializing()) )
  169. return NULL;
  170. return pApp;
  171. }
  172. };
  173. //############################################################################
  174. //############################################################################
  175. //
  176. // Event map for application events
  177. //
  178. //############################################################################
  179. //############################################################################
  180. DISPATCH_CALL_MAP_BEGIN(AppEvents)
  181. DISPATCH_CALL1( AppEvents, OnQuit, PAPPLICATION )
  182. DISPATCH_CALL2( AppEvents, OnDocumentOpen, PDOCUMENT, BOOL)
  183. DISPATCH_CALL1( AppEvents, OnDocumentClose, PDOCUMENT )
  184. DISPATCH_CALL2( AppEvents, OnSnapInAdded, PDOCUMENT, PSNAPIN )
  185. DISPATCH_CALL2( AppEvents, OnSnapInRemoved, PDOCUMENT, PSNAPIN )
  186. DISPATCH_CALL1( AppEvents, OnNewView, PVIEW )
  187. DISPATCH_CALL1( AppEvents, OnViewClose, PVIEW )
  188. DISPATCH_CALL2( AppEvents, OnViewChange, PVIEW, PNODE );
  189. DISPATCH_CALL2( AppEvents, OnSelectionChange, PVIEW, PNODES )
  190. DISPATCH_CALL1( AppEvents, OnContextMenuExecuted, PMENUITEM );
  191. DISPATCH_CALL0( AppEvents, OnToolbarButtonClicked )
  192. DISPATCH_CALL1( AppEvents, OnListUpdated, PVIEW )
  193. DISPATCH_CALL_MAP_END()
  194. /*+-------------------------------------------------------------------------*
  195. *
  196. * CMMCApplication::InternalFinalConstructRelease
  197. *
  198. * PURPOSE: Hands the CAMCApp a pointer to the 'this' object.
  199. *
  200. *+-------------------------------------------------------------------------*/
  201. HRESULT
  202. CMMCApplication::InternalFinalConstructRelease()
  203. {
  204. MMC_COM_MANAGE_STATE();
  205. DECLARE_SC(sc, TEXT("CMMCApplication::InternalFinalConstructRelease"));
  206. // Dont use GetApp, we need to get CAMCApp even if it is not fully initialized.
  207. CAMCApp *pApp = AMCGetApp();
  208. sc = ScCheckPointers(pApp);
  209. if(sc)
  210. return sc.ToHr(); // some wierd error.
  211. sc = pApp->ScRegister_Application(this);
  212. return sc.ToHr();
  213. }
  214. /*+-------------------------------------------------------------------------*
  215. *
  216. * CMMCApplication::GetFrame
  217. *
  218. * PURPOSE: A static function that hooks into the COM interface entry list
  219. * and allows a tear-off object to be created that implements the
  220. * Frame interface.
  221. *
  222. * PARAMETERS:
  223. * void* pv : Defined by ATL to hold a pointer to the CMMCApplication object
  224. * because this is a static method.
  225. * REFIID riid : As per QI
  226. * LPVOID* ppv : As per QI
  227. * DWORD dw : ignored
  228. *
  229. * RETURNS:
  230. * HRESULT WINAPI
  231. *
  232. *+-------------------------------------------------------------------------*/
  233. STDMETHODIMP
  234. CMMCApplication::get_Frame(Frame **ppFrame)
  235. {
  236. MMC_COM_MANAGE_STATE();
  237. DECLARE_SC(sc, TEXT("CMMCApplication::get_Frame"));
  238. if(!ppFrame)
  239. {
  240. sc = E_POINTER;
  241. return sc.ToHr();
  242. }
  243. // get the app
  244. CAMCApp *pApp = GetApp();
  245. if(NULL == pApp)
  246. {
  247. sc = E_UNEXPECTED;
  248. return sc.ToHr();
  249. }
  250. CMainFrame *pMainFrame = pApp->GetMainFrame();
  251. if(!pMainFrame)
  252. {
  253. sc = E_UNEXPECTED;
  254. return sc.ToHr();
  255. }
  256. sc = pMainFrame->ScGetFrame(ppFrame);
  257. return sc.ToHr();
  258. }
  259. STDMETHODIMP
  260. CMMCApplication::get_Document(Document **ppDocument)
  261. {
  262. MMC_COM_MANAGE_STATE();
  263. DECLARE_SC(sc, TEXT("CMMCApplication::get_Document"));
  264. CAMCDoc* const pDoc = CAMCDoc::GetDocument();
  265. ASSERT(ppDocument != NULL);
  266. if(ppDocument == NULL || (pDoc == NULL))
  267. {
  268. sc = E_POINTER;
  269. return sc.ToHr();
  270. }
  271. sc = pDoc->ScGetMMCDocument(ppDocument);
  272. if(sc)
  273. return sc.ToHr();
  274. return sc.ToHr();
  275. }
  276. /***************************************************************************\
  277. *
  278. * METHOD: CMMCApplication::Load
  279. *
  280. * PURPOSE: implements Application.Load for object model
  281. *
  282. * PARAMETERS:
  283. * BSTR bstrFilename - console file to load
  284. *
  285. * RETURNS:
  286. * SC - result code
  287. *
  288. \***************************************************************************/
  289. STDMETHODIMP
  290. CMMCApplication::Load(BSTR bstrFilename)
  291. {
  292. MMC_COM_MANAGE_STATE();
  293. DECLARE_SC(sc, TEXT("CMMCApplication::Load"));
  294. CAMCApp *pApp = GetApp();
  295. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  296. if (sc)
  297. return sc.ToHr();
  298. USES_CONVERSION;
  299. pApp->OpenDocumentFile(OLE2CT(bstrFilename));
  300. return sc.ToHr();
  301. }
  302. void
  303. STDMETHODCALLTYPE CMMCApplication::Help()
  304. {
  305. MMC_COM_MANAGE_STATE();
  306. DECLARE_SC(sc, TEXT("CMMCApplication::Help"));
  307. CAMCApp *pApp = GetApp();
  308. if(NULL == pApp)
  309. {
  310. sc = E_UNEXPECTED;
  311. return;
  312. }
  313. sc = pApp->ScHelp();
  314. if(sc)
  315. return;
  316. return;
  317. }
  318. void
  319. STDMETHODCALLTYPE CMMCApplication::Quit()
  320. {
  321. MMC_COM_MANAGE_STATE();
  322. SC sc;
  323. CAMCApp *pApp = GetApp();
  324. if(NULL == pApp)
  325. goto Error;
  326. // confiscate the control from user
  327. pApp->SetUnderUserControl(false);
  328. // get mainframe
  329. {
  330. CMainFrame * pMainFrame = pApp->GetMainFrame();
  331. if(NULL == pMainFrame)
  332. goto Error;
  333. // close it gracefully.
  334. pMainFrame->PostMessage(WM_CLOSE);
  335. }
  336. Cleanup:
  337. return;
  338. Error:
  339. sc = E_UNEXPECTED;
  340. TraceError(TEXT("CMMCApplication::Quit"), sc);
  341. goto Cleanup;
  342. }
  343. /*+-------------------------------------------------------------------------*
  344. *
  345. * CMMCApplication::get_VersionMajor
  346. *
  347. * PURPOSE: Returns the major version number for the installed version of MMC.
  348. *
  349. * PARAMETERS:
  350. * PLONG pVersionMajor :
  351. *
  352. * RETURNS:
  353. * HRESULT
  354. *
  355. *+-------------------------------------------------------------------------*/
  356. HRESULT
  357. CMMCApplication::get_VersionMajor(PLONG pVersionMajor)
  358. {
  359. MMC_COM_MANAGE_STATE();
  360. DECLARE_SC(sc, TEXT("CMMCApplication::get_VersionMajor"));
  361. sc = ScCheckPointers(pVersionMajor);
  362. if(sc)
  363. return sc.ToHr();
  364. *pVersionMajor = MMC_VERSION_MAJOR;
  365. return sc.ToHr();
  366. }
  367. /*+-------------------------------------------------------------------------*
  368. *
  369. * CMMCApplication::get_VersionMinor
  370. *
  371. * PURPOSE: Returns the minor version number for the installed version of MMC.
  372. *
  373. * PARAMETERS:
  374. * PLONG pVersionMinor :
  375. *
  376. * RETURNS:
  377. * HRESULT
  378. *
  379. *+-------------------------------------------------------------------------*/
  380. HRESULT
  381. CMMCApplication::get_VersionMinor(PLONG pVersionMinor)
  382. {
  383. MMC_COM_MANAGE_STATE();
  384. DECLARE_SC(sc, TEXT("CMMCApplication::get_VersionMinor"));
  385. sc = ScCheckPointers(pVersionMinor);
  386. if(sc)
  387. return sc.ToHr();
  388. *pVersionMinor = MMC_VERSION_MINOR;
  389. return sc.ToHr();
  390. }
  391. //+-------------------------------------------------------------------
  392. //
  393. // Member: CMMCApplication::get_Visible
  394. //
  395. // Synopsis: Returns the visible property
  396. //
  397. // Arguments: [PBOOL] - out bool
  398. //
  399. // Returns: HRESULT
  400. //
  401. //--------------------------------------------------------------------
  402. HRESULT CMMCApplication::get_Visible (PBOOL pbVisible)
  403. {
  404. MMC_COM_MANAGE_STATE();
  405. DECLARE_SC(sc, _T("CMMCApplication::get_Visible"));
  406. sc = ScCheckPointers(pbVisible);
  407. if (sc)
  408. return sc.ToHr();
  409. // get the app
  410. CAMCApp *pApp = GetApp();
  411. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  412. if (sc)
  413. return (sc.ToHr());
  414. CMainFrame *pMainFrame = pApp->GetMainFrame();
  415. sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
  416. if (sc)
  417. return (sc.ToHr());
  418. *pbVisible = pMainFrame->IsWindowVisible();
  419. return (sc.ToHr());
  420. }
  421. //+-------------------------------------------------------------------
  422. //
  423. // Member: CMMCApplication::Show
  424. //
  425. // Synopsis: Shows the application
  426. //
  427. // Arguments: None
  428. //
  429. // Returns: HRESULT
  430. //
  431. //--------------------------------------------------------------------
  432. HRESULT CMMCApplication::Show ()
  433. {
  434. MMC_COM_MANAGE_STATE();
  435. DECLARE_SC(sc, _T("CMMCApplication::Show"));
  436. // get the app
  437. CAMCApp *pApp = GetApp();
  438. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  439. if (sc)
  440. return (sc.ToHr());
  441. CMainFrame *pMainFrame = pApp->GetMainFrame();
  442. sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
  443. if (sc)
  444. return (sc.ToHr());
  445. sc = pMainFrame->ShowWindow(SW_SHOW);
  446. return (sc.ToHr());
  447. }
  448. //+-------------------------------------------------------------------
  449. //
  450. // Member: CMMCApplication::Hide
  451. //
  452. // Synopsis: Hides the application.
  453. //
  454. // Arguments: None
  455. //
  456. // Returns: HRESULT
  457. //
  458. // Note: If the user is under control (UserControl property is set)
  459. // then Hide fails.
  460. //
  461. //--------------------------------------------------------------------
  462. HRESULT CMMCApplication::Hide ()
  463. {
  464. MMC_COM_MANAGE_STATE();
  465. DECLARE_SC(sc, _T("CMMCApplication::Hide"));
  466. // get the app
  467. CAMCApp *pApp = GetApp();
  468. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  469. if (sc)
  470. return (sc.ToHr());
  471. // Cant hide if app is under user control.
  472. if (pApp->IsUnderUserControl())
  473. {
  474. sc = E_FAIL;
  475. return sc.ToHr();
  476. }
  477. CMainFrame *pMainFrame = pApp->GetMainFrame();
  478. sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
  479. if (sc)
  480. return (sc.ToHr());
  481. sc = pMainFrame->ShowWindow(SW_HIDE);
  482. return (sc.ToHr());
  483. }
  484. //+-------------------------------------------------------------------
  485. //
  486. // Member: CMMCApplication::get_UserControl
  487. //
  488. // Synopsis: Returns the UserControl property
  489. //
  490. // Arguments: PBOOL - out param.
  491. //
  492. // Returns: HRESULT
  493. //
  494. //--------------------------------------------------------------------
  495. HRESULT CMMCApplication::get_UserControl (PBOOL pbUserControl)
  496. {
  497. MMC_COM_MANAGE_STATE();
  498. DECLARE_SC(sc, _T("CMMCApplication::get_UserControl"));
  499. sc = ScCheckPointers(pbUserControl);
  500. if (sc)
  501. return (sc.ToHr());
  502. // get the app
  503. CAMCApp *pApp = GetApp();
  504. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  505. if (sc)
  506. return (sc.ToHr());
  507. *pbUserControl = pApp->IsUnderUserControl();
  508. return (sc.ToHr());
  509. }
  510. //+-------------------------------------------------------------------
  511. //
  512. // Member: CMMCApplication::put_UserControl
  513. //
  514. // Synopsis: Sets the UserControl property
  515. //
  516. // Arguments: BOOL
  517. //
  518. // Returns: HRESULT
  519. //
  520. //--------------------------------------------------------------------
  521. HRESULT CMMCApplication::put_UserControl (BOOL bUserControl)
  522. {
  523. MMC_COM_MANAGE_STATE();
  524. DECLARE_SC(sc, _T("CMMCApplication::put_UserControl"));
  525. // get the app
  526. CAMCApp *pApp = GetApp();
  527. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  528. if (sc)
  529. return (sc.ToHr());
  530. pApp->SetUnderUserControl(bUserControl);
  531. return (sc.ToHr());
  532. }
  533. /***************************************************************************\
  534. *
  535. * METHOD: CMMCApplication::ScOnDisconnectObjects
  536. *
  537. * PURPOSE: special disconnect implementation. For this object implementation
  538. * provided by the base class is not enough, since connection point
  539. * is an internal object which may also have strong references on it
  540. *
  541. * PARAMETERS:
  542. *
  543. * RETURNS:
  544. * SC - result code
  545. *
  546. \***************************************************************************/
  547. SC CMMCApplication::ScOnDisconnectObjects()
  548. {
  549. MMC_COM_MANAGE_STATE();
  550. DECLARE_SC(sc, TEXT("CMMCApplication::ScOnDisconnectObjects"));
  551. // get the connection point container
  552. IConnectionPointContainerPtr spContainer(GetUnknown());
  553. sc = ScCheckPointers( spContainer, E_UNEXPECTED );
  554. if (sc)
  555. return sc;
  556. // get the connection point
  557. IConnectionPointPtr spConnectionPoint;
  558. sc = spContainer->FindConnectionPoint( DIID_AppEvents, &spConnectionPoint );
  559. if (sc)
  560. return sc;
  561. // cut connection point references
  562. sc = CoDisconnectObject( spConnectionPoint, 0/*dwReserved*/ );
  563. if (sc)
  564. return sc;
  565. // let the base class do the rest
  566. sc = CMMCIDispatchImplClass::ScOnDisconnectObjects();
  567. if (sc)
  568. return sc;
  569. return sc;
  570. }
  571. //############################################################################
  572. //############################################################################
  573. //
  574. // ATL GLobal Object Map
  575. //
  576. //############################################################################
  577. //############################################################################
  578. BEGIN_OBJECT_MAP(ObjectMap)
  579. OBJECT_ENTRY(CLSID_Application, CMMCApplication)
  580. END_OBJECT_MAP()
  581. /*+-------------------------------------------------------------------------*
  582. * CLockChildWindowUpdate
  583. *
  584. * Helper class whose constructor turns off redraw for all of the children
  585. * of the given window, and whose destructor turns redraw back on for all
  586. * of the windows for which it was turned off.
  587. *
  588. * This is used to prevent ugly transient drawing while opening console
  589. * files that take a long time to completely open (bug 150356).
  590. *--------------------------------------------------------------------------*/
  591. class CLockChildWindowUpdate
  592. {
  593. public:
  594. CLockChildWindowUpdate (CWnd* pwndLock) : m_pwndLock(pwndLock)
  595. {
  596. if (m_pwndLock != NULL)
  597. {
  598. CWnd* pwndChild;
  599. /*
  600. * turn off redraw for each child, saving the HWND for later
  601. * so we can turn it back on (we save the HWND instead of the
  602. * CWnd* because MFC might have returned a temporary object).
  603. */
  604. for (pwndChild = m_pwndLock->GetWindow (GW_CHILD);
  605. pwndChild != NULL;
  606. pwndChild = pwndChild->GetNextWindow())
  607. {
  608. pwndChild->SetRedraw (false);
  609. m_vChildren.push_back (pwndChild->GetSafeHwnd());
  610. }
  611. }
  612. }
  613. ~CLockChildWindowUpdate()
  614. {
  615. std::vector<HWND>::iterator it;
  616. /*
  617. * for every window for which we turned off redraw, turn it back on
  618. */
  619. for (it = m_vChildren.begin(); it != m_vChildren.end(); ++it)
  620. {
  621. HWND hWndChild = *it;
  622. if ( (hWndChild != NULL) && ::IsWindow(hWndChild) )
  623. {
  624. CWnd *pwndChild = CWnd::FromHandle(hWndChild);
  625. pwndChild->SetRedraw (true);
  626. pwndChild->RedrawWindow (NULL, NULL,
  627. RDW_INVALIDATE | RDW_UPDATENOW |
  628. RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
  629. }
  630. }
  631. }
  632. private:
  633. CWnd* const m_pwndLock;
  634. std::vector<HWND> m_vChildren;
  635. };
  636. /*+-------------------------------------------------------------------------*
  637. * class CCausalityCounter
  638. *
  639. *
  640. * PURPOSE: used to determine whether a function has resulted in a call back to itself on the same stack
  641. *
  642. * USAGE: Initialize with a variable that is set to zero.
  643. *
  644. * NOTE: Copied from MMCaxwin.cpp
  645. *+-------------------------------------------------------------------------*/
  646. class CCausalityCounter
  647. {
  648. UINT & m_bCounter;
  649. public:
  650. CCausalityCounter(UINT &bCounter) : m_bCounter(bCounter){++m_bCounter;}
  651. ~CCausalityCounter() {--m_bCounter;}
  652. bool HasReentered()
  653. {
  654. return (m_bCounter>1);
  655. }
  656. };
  657. //############################################################################
  658. //############################################################################
  659. //
  660. // Implementation of class CAMCMultiDocTemplate
  661. //
  662. //############################################################################
  663. //############################################################################
  664. class CAMCMultiDocTemplate : public CMultiDocTemplate
  665. {
  666. public:
  667. CAMCMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
  668. CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
  669. : CMultiDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass)
  670. {
  671. }
  672. CDocument* OpenDocumentFile(LPCTSTR lpszPathName,
  673. BOOL bMakeVisible)
  674. {
  675. DECLARE_SC(sc, TEXT("CAMCMultiDocTemplate::OpenDocumentFile"));
  676. CAMCDoc* const pDoc = CAMCDoc::GetDocument();
  677. if (pDoc && (!pDoc->SaveModified() || !CanCloseDoc() ))
  678. return NULL; // leave the original one
  679. CLockChildWindowUpdate lock (AfxGetMainWnd());
  680. CAMCDoc* pDocument = (CAMCDoc*)CreateNewDocument();
  681. if (pDocument == NULL)
  682. {
  683. TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n");
  684. AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); // do not change to MMCMessageBox
  685. return NULL;
  686. }
  687. HRESULT hr;
  688. if ((hr = pDocument->InitNodeManager()) != S_OK)
  689. {
  690. TRACE1("CAMCDoc::InitNodeManager failed, 0x%08x\n", hr);
  691. CAMCApp* pApp = AMCGetApp();
  692. MMCErrorBox((pApp && pApp->IsWin9xPlatform())
  693. ? IDS_NODEMGR_FAILED_9x
  694. : IDS_NODEMGR_FAILED);
  695. delete pDocument; // explicit delete on error
  696. return NULL;
  697. }
  698. ASSERT_VALID(pDocument);
  699. BOOL bAutoDelete = pDocument->m_bAutoDelete;
  700. pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong
  701. CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
  702. pDocument->m_bAutoDelete = bAutoDelete;
  703. if (pFrame == NULL)
  704. {
  705. AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); // do not change to MMCMessageBox
  706. delete pDocument; // explicit delete on error
  707. return NULL;
  708. }
  709. ASSERT_VALID(pFrame);
  710. if (lpszPathName == NULL)
  711. {
  712. // create a new document - with default document name
  713. SetDefaultTitle(pDocument);
  714. // avoid creating temporary compound file when starting up invisible
  715. if (!bMakeVisible)
  716. pDocument->m_bEmbedded = TRUE;
  717. if (!pDocument->OnNewDocument())
  718. {
  719. // user has be alerted to what failed in OnNewDocument
  720. TRACE0("CDocument::OnNewDocument returned FALSE.\n");
  721. AfxMessageBox (AFX_IDP_FAILED_TO_CREATE_DOC); // do not change to MMCMessageBox
  722. pFrame->DestroyWindow();
  723. return NULL;
  724. }
  725. // it worked, now bump untitled count
  726. m_nUntitledCount++;
  727. InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
  728. }
  729. else
  730. {
  731. // open an existing document
  732. CWaitCursor wait;
  733. if (!pDocument->OnOpenDocument(lpszPathName))
  734. {
  735. // user has be alerted to what failed in OnOpenDocument
  736. TRACE0("CDocument::OnOpenDocument returned FALSE.\n");
  737. pFrame->DestroyWindow();
  738. return NULL;
  739. }
  740. #ifdef _MAC
  741. // if the document is dirty, we must have opened a stationery pad
  742. // - don't change the pathname because we want to treat the document
  743. // as untitled
  744. if (!pDocument->IsModified())
  745. #endif
  746. pDocument->SetPathName(lpszPathName);
  747. //REVIEW: dburg: InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
  748. pFrame->DestroyWindow();
  749. pDocument->SetModifiedFlag (false);
  750. pDocument->SetFrameModifiedFlag (false);
  751. }
  752. // fire script event
  753. CAMCApp* pApp = AMCGetApp();
  754. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  755. if (sc)
  756. return pDocument;
  757. sc = pApp->ScOnNewDocument(pDocument, (lpszPathName != NULL));
  758. if (sc)
  759. sc.TraceAndClear();
  760. return pDocument;
  761. }
  762. // this method is overrided to catch application quit event
  763. virtual void CloseAllDocuments( BOOL bEndSession )
  764. {
  765. DECLARE_SC(sc, TEXT("CAMCMultiDocTemplate::CloseAllDocuments"));
  766. /* Bug 620422: CloseAllDocuments can end up being called again
  767. * before a previous invocation has returned, e.g., when the actions
  768. * of closing this application and of logging out overlap.
  769. * MFC's handlers for these events: CFrameWnd::OnClose and
  770. * CFrameWnd::OnEndSession both call CloseAllDocuments.
  771. *
  772. * We keep track of whether a call to CloseAllDocuments is in
  773. * progress by a causality counter tied to the static variable
  774. * cInvocations (initialized to 0).
  775. * Following invocations, if any, simply return.
  776. */
  777. static UINT cInvocations = 0;
  778. CCausalityCounter counter(cInvocations);
  779. if (counter.HasReentered())
  780. return;
  781. // invoke base class to perform required tasks
  782. CMultiDocTemplate::CloseAllDocuments( bEndSession );
  783. // no other way we can get here but exit app
  784. // so that's a good time for script to know it
  785. CAMCApp* pApp = AMCGetApp();
  786. sc = ScCheckPointers(pApp, E_UNEXPECTED);
  787. if (sc)
  788. return;
  789. // forward to application to emit the script event
  790. sc = pApp->ScOnQuitApp();
  791. if (sc)
  792. sc.TraceAndClear();
  793. // cut off all strong references now.
  794. // Quit was executed - nothing else matters
  795. sc = GetComObjectEventSource().ScFireEvent( CComObjectObserver::ScOnDisconnectObjects );
  796. if (sc)
  797. sc.TraceAndClear();
  798. }
  799. };
  800. // Declare debug infolevel for this component
  801. DECLARE_INFOLEVEL(AMCConUI);
  802. //############################################################################
  803. //############################################################################
  804. //
  805. // Implementation of class CAMCApp
  806. //
  807. //############################################################################
  808. //############################################################################
  809. IMPLEMENT_DYNAMIC(CAMCApp, CWinApp)
  810. BEGIN_MESSAGE_MAP(CAMCApp, CWinApp)
  811. //{{AFX_MSG_MAP(CAMCApp)
  812. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  813. //}}AFX_MSG_MAP
  814. // Standard file based document commands
  815. ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
  816. ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
  817. // Standard print setup command
  818. ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
  819. ON_COMMAND(ID_FILE_NEW_USER_MODE, OnFileNewInUserMode) // CTRL+N in user mode - do nothing
  820. END_MESSAGE_MAP()
  821. /////////////////////////////////////////////////////////////////////////////
  822. // CAMCApp construction
  823. CAMCApp::CAMCApp() :
  824. m_bOleInitialized(FALSE),
  825. m_bDefaultDirSet(FALSE),
  826. m_eMode(eMode_Error),
  827. m_fAuthorModeForced(false),
  828. m_fInitializing(true),
  829. m_fDelayCloseUntilIdle(false),
  830. m_fCloseCameFromMainPump(false),
  831. m_nMessagePumpNestingLevel(0),
  832. m_fIsWin9xPlatform(false),
  833. m_dwHelpCookie(0),
  834. m_bHelpInitialized(false),
  835. m_fUnderUserControl(true),
  836. m_fRunningAsOLEServer(false)
  837. {
  838. }
  839. /////////////////////////////////////////////////////////////////////////////
  840. // The one and only CAMCApp object
  841. CAMCApp theApp;
  842. const CRect g_rectEmpty (0, 0, 0, 0);
  843. void DeleteDDEKeys()
  844. {
  845. HKEY key;
  846. if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_CLASSES_ROOT,
  847. _T("MSCFile\\shell\\open"),
  848. 0, KEY_SET_VALUE, &key))
  849. {
  850. theApp.DelRegTree (key, _T("ddeexec"));
  851. RegCloseKey (key);
  852. }
  853. }
  854. /*+-------------------------------------------------------------------------*
  855. *
  856. * CAMCApp::GetMainFrame
  857. *
  858. * PURPOSE: Returns a pointer to the main frame.
  859. *
  860. * RETURNS:
  861. * CMainFrame *
  862. *
  863. *+-------------------------------------------------------------------------*/
  864. CMainFrame *
  865. CAMCApp::GetMainFrame()
  866. {
  867. return dynamic_cast<CMainFrame *>(m_pMainWnd);
  868. }
  869. /*+-------------------------------------------------------------------------*
  870. *
  871. * CAMCApp::ScGet_Application
  872. *
  873. * PURPOSE: Returns a pointer to an _Application object.
  874. *
  875. * PARAMETERS:
  876. * _Application ** pp_Application :
  877. *
  878. * RETURNS:
  879. * SC
  880. *
  881. *+-------------------------------------------------------------------------*/
  882. SC
  883. CAMCApp::ScGet_Application(_Application **pp_Application)
  884. {
  885. DECLARE_SC(sc, TEXT("CAMCApp::ScGet_Application"));
  886. // parameter check
  887. sc = ScCheckPointers(pp_Application);
  888. if (sc)
  889. return sc;
  890. // init out param
  891. *pp_Application = NULL;
  892. // see if we have a chached one
  893. if (m_sp_Application != NULL)
  894. {
  895. *pp_Application = m_sp_Application;
  896. (*pp_Application)->AddRef(); // addref for the client.
  897. return sc;
  898. }
  899. // create an _Application object. This is needed if MMC was instantiated
  900. // by a user, not COM.
  901. sc = CMMCApplication::CreateInstance(pp_Application);
  902. if(sc)
  903. return sc;
  904. // The constructor of the CMMCApplication calls ScRegister_Application
  905. // which sets the m_sp_Application pointer. Do not set this pointer here.
  906. sc = ScCheckPointers(*pp_Application, E_UNEXPECTED);
  907. if (sc)
  908. return sc;
  909. // done
  910. return sc;
  911. }
  912. /*+-------------------------------------------------------------------------*
  913. *
  914. * CAMCApp::ScRegister_Application
  915. *
  916. * PURPOSE: called by a CMMCApplication object to enable the CAMCApp to store
  917. * a pointer to it.
  918. *
  919. * PARAMETERS:
  920. * _Application * p_Application :
  921. *
  922. * RETURNS:
  923. * SC
  924. *
  925. *+-------------------------------------------------------------------------*/
  926. SC
  927. CAMCApp::ScRegister_Application(_Application *p_Application)
  928. {
  929. DECLARE_SC(sc, TEXT("CAMCApp::ScRegister_Application"));
  930. ASSERT(m_sp_Application == NULL); // only one _Application object should ever register.
  931. sc = ScCheckPointers(p_Application);
  932. if(sc)
  933. return sc;
  934. m_sp_Application = p_Application;
  935. return sc;
  936. }
  937. //+-------------------------------------------------------------------
  938. //
  939. // Member: RegisterShellFileTypes
  940. //
  941. // Synopsis: Register the file associations.
  942. //
  943. // Note: Also set all other relevant registry keys like
  944. // Open, Author, RunAs. Eventhough the setup has
  945. // done this it may have been deleted mistakenly.
  946. //
  947. // History:
  948. // [AnandhaG] - Added the registry repair.
  949. // Returns: None.
  950. //
  951. //--------------------------------------------------------------------
  952. void CAMCApp::RegisterShellFileTypes(BOOL bCompat)
  953. {
  954. CWinApp::RegisterShellFileTypes (bCompat);
  955. DECLARE_SC(sc, _T("CAMCApp::RegisterShellFileTypes"));
  956. do
  957. {
  958. // Create the top level MSCFile key.
  959. CRegKey regKey;
  960. LONG lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile"), REG_NONE,
  961. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  962. if (ERROR_SUCCESS != lRet)
  963. break;
  964. /*
  965. * for platforms that support it (i.e. not Win9x), set the MUI-friendly
  966. * value for the MSCFile document type
  967. */
  968. if (!IsWin9xPlatform())
  969. {
  970. CString strMUIValue;
  971. strMUIValue.Format (_T("@%%SystemRoot%%\\system32\\mmcbase.dll,-%d"), IDR_MUIFRIENDLYNAME);
  972. lRet = RegSetValueEx (regKey, _T("FriendlyTypeName"), NULL, REG_EXPAND_SZ,
  973. (CONST BYTE *)(LPCTSTR) strMUIValue,
  974. sizeof(TCHAR) * (strMUIValue.GetLength()+1) );
  975. if (ERROR_SUCCESS != lRet)
  976. break;
  977. }
  978. // Set the EditFlags value.
  979. lRet = regKey.SetValue(0x100000, _T("EditFlags"));
  980. if (ERROR_SUCCESS != lRet)
  981. break;
  982. // Create the Author verb.
  983. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\Author"), REG_NONE,
  984. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  985. if (ERROR_SUCCESS != lRet)
  986. break;
  987. // And set default value for author (this reflects in shell menu).
  988. CString strRegVal;
  989. LoadString(strRegVal, IDS_MENUAUTHOR);
  990. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_SZ,
  991. (CONST BYTE *)(LPCTSTR)strRegVal, sizeof(TCHAR) * (strRegVal.GetLength()+1) );
  992. if (ERROR_SUCCESS != lRet)
  993. break;
  994. /*
  995. * for platforms that support it (i.e. not Win9x), set the MUI-friendly
  996. * value for the menu item
  997. */
  998. if (!IsWin9xPlatform())
  999. {
  1000. CString strMUIValue;
  1001. strMUIValue.Format (_T("@%%SystemRoot%%\\system32\\mmcbase.dll,-%d"), IDS_MENUAUTHOR);
  1002. lRet = RegSetValueEx (regKey, _T("MUIVerb"), NULL, REG_EXPAND_SZ,
  1003. (CONST BYTE *)(LPCTSTR) strMUIValue,
  1004. sizeof(TCHAR) * (strMUIValue.GetLength()+1) );
  1005. if (ERROR_SUCCESS != lRet)
  1006. break;
  1007. }
  1008. // Create the Author command.
  1009. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\Author\\command"), REG_NONE,
  1010. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  1011. if (ERROR_SUCCESS != lRet)
  1012. break;
  1013. //////////////////////////////////////////////////////////////
  1014. // Win95 does not support REG_EXPAND_SZ for default values. //
  1015. // So we set expand strings and set registry strings as //
  1016. // REG_SZ for Win9x. //
  1017. // The following declarations are for Win9x platform. //
  1018. //////////////////////////////////////////////////////////////
  1019. TCHAR szRegValue[2 * MAX_PATH];
  1020. int cchRegValue = 2 * MAX_PATH;
  1021. TCHAR szWinDir[MAX_PATH];
  1022. if (0 == ExpandEnvironmentStrings(_T("%WinDir%"), szWinDir, countof(szWinDir)) )
  1023. break;
  1024. DWORD dwCount = 0;
  1025. LPTSTR lpszRegValue = NULL;
  1026. // Set the default value for Author command.
  1027. if (IsWin9xPlatform() == false)
  1028. {
  1029. lpszRegValue = _T("%SystemRoot%\\system32\\mmc.exe /a \"%1\" %*");
  1030. dwCount = sizeof(TCHAR) * (1 + _tcslen(lpszRegValue));
  1031. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_EXPAND_SZ,
  1032. (CONST BYTE *)lpszRegValue, dwCount);
  1033. }
  1034. else // Win9x platform
  1035. {
  1036. lpszRegValue = _T("\\mmc.exe /a \"%1\" %2 %3 %4 %5 %6 %7 %8 %9");
  1037. sc = StringCchCopy(szRegValue, cchRegValue, szWinDir);
  1038. if (sc)
  1039. return;
  1040. sc = StringCchCat(szRegValue, cchRegValue, lpszRegValue);
  1041. if (sc)
  1042. return;
  1043. dwCount = sizeof(TCHAR) * (1 + _tcslen(szRegValue));
  1044. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_SZ,
  1045. (CONST BYTE *)szRegValue, dwCount);
  1046. }
  1047. if (ERROR_SUCCESS != lRet)
  1048. break;
  1049. // Create the Open verb.
  1050. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\Open"), REG_NONE,
  1051. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  1052. if (ERROR_SUCCESS != lRet)
  1053. break;
  1054. // Set default value for Open.
  1055. LoadString(strRegVal, IDS_MENUOPEN);
  1056. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_SZ,
  1057. (CONST BYTE *)(LPCTSTR)strRegVal,sizeof(TCHAR) * (strRegVal.GetLength()+1) );
  1058. if (ERROR_SUCCESS != lRet)
  1059. break;
  1060. /*
  1061. * for platforms that support it (i.e. not Win9x), set the MUI-friendly
  1062. * value for the menu item
  1063. */
  1064. if (!IsWin9xPlatform())
  1065. {
  1066. CString strMUIValue;
  1067. strMUIValue.Format (_T("@%%SystemRoot%%\\system32\\mmcbase.dll,-%d"), IDS_MENUOPEN);
  1068. lRet = RegSetValueEx (regKey, _T("MUIVerb"), NULL, REG_EXPAND_SZ,
  1069. (CONST BYTE *)(LPCTSTR) strMUIValue,
  1070. sizeof(TCHAR) * (strMUIValue.GetLength()+1) );
  1071. if (ERROR_SUCCESS != lRet)
  1072. break;
  1073. }
  1074. // Create the Open command.
  1075. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\Open\\command"), REG_NONE,
  1076. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  1077. if (ERROR_SUCCESS != lRet)
  1078. break;
  1079. // Set the default value for Open command.
  1080. if (IsWin9xPlatform() == false)
  1081. {
  1082. lpszRegValue = _T("%SystemRoot%\\system32\\mmc.exe \"%1\" %*");
  1083. dwCount = sizeof(TCHAR) * (1 + _tcslen(lpszRegValue));
  1084. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_EXPAND_SZ,
  1085. (CONST BYTE *)lpszRegValue, dwCount);
  1086. }
  1087. else // Win9x platform
  1088. {
  1089. lpszRegValue = _T("\\mmc.exe \"%1\" %2 %3 %4 %5 %6 %7 %8 %9");
  1090. sc = StringCchCopy(szRegValue, cchRegValue, szWinDir);
  1091. if (sc)
  1092. return;
  1093. sc = StringCchCat(szRegValue, cchRegValue, lpszRegValue);
  1094. if (sc)
  1095. return;
  1096. dwCount = sizeof(TCHAR) * (1 + _tcslen(szRegValue));
  1097. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_SZ,
  1098. (CONST BYTE *)szRegValue, dwCount);
  1099. }
  1100. if (ERROR_SUCCESS != lRet)
  1101. break;
  1102. // Create the RunAs verb (only on NT).
  1103. if (IsWin9xPlatform() == false)
  1104. {
  1105. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\RunAs"), REG_NONE,
  1106. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  1107. if (ERROR_SUCCESS != lRet)
  1108. break;
  1109. // Set default value for RunAs verb.
  1110. LoadString(strRegVal, IDS_MENURUNAS);
  1111. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_SZ,
  1112. (CONST BYTE *)(LPCTSTR)strRegVal,sizeof(TCHAR) * (strRegVal.GetLength()+1) );
  1113. if (ERROR_SUCCESS != lRet)
  1114. break;
  1115. /*
  1116. * for platforms that support it (i.e. not Win9x), set the MUI-friendly
  1117. * value for the menu item
  1118. */
  1119. if (!IsWin9xPlatform())
  1120. {
  1121. CString strMUIValue;
  1122. strMUIValue.Format (_T("@%%SystemRoot%%\\system32\\mmcbase.dll,-%d"), IDS_MENURUNAS);
  1123. lRet = RegSetValueEx (regKey, _T("MUIVerb"), NULL, REG_EXPAND_SZ,
  1124. (CONST BYTE *)(LPCTSTR) strMUIValue,
  1125. sizeof(TCHAR) * (strMUIValue.GetLength()+1) );
  1126. if (ERROR_SUCCESS != lRet)
  1127. break;
  1128. }
  1129. // Create the RunAs command.
  1130. lRet = regKey.Create(HKEY_CLASSES_ROOT, _T("MSCFile\\shell\\RunAs\\command"), REG_NONE,
  1131. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  1132. if (ERROR_SUCCESS != lRet)
  1133. break;
  1134. // Set the default value for RunAs command. (Only on NT Unicode)
  1135. lpszRegValue = _T("%SystemRoot%\\system32\\mmc.exe \"%1\" %*");
  1136. dwCount = sizeof(TCHAR) * (1 + _tcslen(lpszRegValue));
  1137. lRet = RegSetValueEx ((HKEY)regKey, (LPCTSTR)NULL, NULL, REG_EXPAND_SZ,
  1138. (CONST BYTE *)lpszRegValue, dwCount);
  1139. }
  1140. if (ERROR_SUCCESS != lRet)
  1141. break;
  1142. } while ( FALSE );
  1143. return;
  1144. }
  1145. /////////////////////////////////////////////////////////////////////////////
  1146. // CAMCApp initialization
  1147. #ifdef UNICODE
  1148. SC ScLaunchMMC (eArchitecture eArch, int nCmdShow);
  1149. #endif
  1150. #ifdef MMC_WIN64
  1151. class CMMCCommandLineInfo;
  1152. SC ScDetermineArchitecture (const CMMCCommandLineInfo& rCmdInfo, eArchitecture& eArch);
  1153. #else
  1154. bool IsWin64();
  1155. #endif // MMC_WIN64
  1156. class CMMCCommandLineInfo : public CCommandLineInfo
  1157. {
  1158. public:
  1159. eArchitecture m_eArch;
  1160. bool m_fForceAuthorMode;
  1161. bool m_fRegisterServer;
  1162. CString m_strDumpFilename;
  1163. public:
  1164. CMMCCommandLineInfo() :
  1165. m_eArch (eArch_Any),
  1166. m_fForceAuthorMode(false),
  1167. m_fRegisterServer(false)
  1168. {}
  1169. virtual void ParseParam (LPCTSTR pszParam, BOOL bFlag, BOOL bLast)
  1170. {
  1171. DECLARE_SC(sc, _T("ParseParam"));
  1172. bool fHandledHere = false;
  1173. if (bFlag)
  1174. {
  1175. sc = ScCheckPointers(pszParam);
  1176. if (sc)
  1177. return;
  1178. /*
  1179. * ignore the following parameters:
  1180. * -dde (await DDE command), -s (splash screen, obsolete).
  1181. */
  1182. if ((lstrcmpi (pszParam, _T("s")) == 0) ||
  1183. (lstrcmpi (pszParam, _T("dde")) == 0))
  1184. {
  1185. fHandledHere = true;
  1186. }
  1187. // force author mode
  1188. else if (lstrcmpi (pszParam, _T("a")) == 0)
  1189. {
  1190. m_fForceAuthorMode = true;
  1191. fHandledHere = true;
  1192. }
  1193. // register the server only
  1194. else if (lstrcmpi (pszParam, _T("RegServer")) == 0)
  1195. {
  1196. m_fRegisterServer = true;
  1197. fHandledHere = true;
  1198. }
  1199. // force 64-bit MMC to run
  1200. else if (lstrcmp (pszParam, _T("64")) == 0)
  1201. {
  1202. m_eArch = eArch_64bit;
  1203. fHandledHere = true;
  1204. }
  1205. // force 32-bit MMC to run
  1206. else if (lstrcmp (pszParam, _T("32")) == 0)
  1207. {
  1208. m_eArch = eArch_32bit;
  1209. fHandledHere = true;
  1210. }
  1211. else
  1212. {
  1213. static const TCHAR szDumpParam[] = _T("dump:");
  1214. const int cchDumpParam = 1000;
  1215. TCHAR szParam[cchDumpParam];
  1216. sc = StringCchCopy(szParam, cchDumpParam, pszParam);
  1217. if(sc)
  1218. sc.TraceAndClear();// suppress errors here. Truncation is OK. StringCchCopy will always add a NULL terminator
  1219. // dump console file contents
  1220. if (lstrcmpi (szParam, szDumpParam) == 0)
  1221. {
  1222. m_strDumpFilename = pszParam + cchDumpParam - 1;
  1223. fHandledHere = true;
  1224. }
  1225. }
  1226. }
  1227. // if not handled, pass it on to base class
  1228. // if just handled last parameter, call base class ParseLast
  1229. // so it can do the final processing
  1230. if (!fHandledHere)
  1231. CCommandLineInfo::ParseParam (pszParam, bFlag, bLast);
  1232. else if (bLast)
  1233. CCommandLineInfo::ParseLast(bLast);
  1234. }
  1235. }; // class CMMCCommandLineInfo
  1236. /*+-------------------------------------------------------------------------*
  1237. * CWow64FilesystemRedirectionDisabler
  1238. *
  1239. * Disables Wow64 file system redirection for the file represented in the
  1240. * given CMMCCommandLineInfo. We do this so MMC32 can open consoles in
  1241. * %windir%\system32 without having the path redirected to %windir%\syswow64.
  1242. *--------------------------------------------------------------------------*/
  1243. class CWow64FilesystemRedirectionDisabler
  1244. {
  1245. public:
  1246. CWow64FilesystemRedirectionDisabler (LPCTSTR pszFilename)
  1247. {
  1248. #ifndef MMC_WIN64
  1249. m_fDisabled = ((pszFilename != NULL) && IsWin64());
  1250. if (m_fDisabled)
  1251. {
  1252. Trace (tag32BitTransfer, _T("Disabling Wow64 file system redirection for %s"), pszFilename);
  1253. Wow64DisableFilesystemRedirector (pszFilename);
  1254. }
  1255. #endif // !MMC_WIN64
  1256. }
  1257. ~CWow64FilesystemRedirectionDisabler ()
  1258. {
  1259. #ifndef MMC_WIN64
  1260. if (m_fDisabled)
  1261. {
  1262. Trace (tag32BitTransfer, _T("Enabling Wow64 file system redirection"));
  1263. Wow64EnableFilesystemRedirector();
  1264. }
  1265. #endif // !MMC_WIN64
  1266. }
  1267. private:
  1268. #ifndef MMC_WIN64
  1269. bool m_fDisabled;
  1270. #endif // !MMC_WIN64
  1271. };
  1272. /*+-------------------------------------------------------------------------*
  1273. *
  1274. * CAMCApp::ScProcessAuthorModeRestrictions
  1275. *
  1276. * PURPOSE: Determines whether author mode restrictions are being enforced
  1277. * by system policy, and if author mode is not allowed,
  1278. * displays an error box and exits.
  1279. *
  1280. * RETURNS:
  1281. * SC
  1282. *
  1283. *+-------------------------------------------------------------------------*/
  1284. SC
  1285. CAMCApp::ScProcessAuthorModeRestrictions()
  1286. {
  1287. DECLARE_SC(sc, TEXT("CAMCApp::ScProcessAuthorModeRestrictions"));
  1288. CRegKey regKey;
  1289. // The mode is initialized to "author", if it is not in
  1290. // initialized state just return.
  1291. if (eMode_Author != m_eMode)
  1292. return sc;
  1293. // The console file mode is already read.
  1294. // Check if user policy permits author mode.
  1295. long lResult = regKey.Open(HKEY_CURRENT_USER, POLICY_KEY, KEY_READ);
  1296. if (lResult != ERROR_SUCCESS)
  1297. return sc;
  1298. // get the value of RestrictAuthorMode.
  1299. DWORD dwRestrictAuthorMode = 0;
  1300. lResult = regKey.QueryValue(dwRestrictAuthorMode, g_szRestrictAuthorMode);
  1301. if (lResult != ERROR_SUCCESS)
  1302. return sc;
  1303. if (dwRestrictAuthorMode == 0) // Author mode is not restricted so return.
  1304. return sc;
  1305. /*
  1306. * If called from script (running as embedded server) see if policy
  1307. * restricts scripts from entering into author mode.
  1308. *
  1309. * If restricted then script will fail, thus restricting rogue scripts.
  1310. *
  1311. * Even if not restricted here cannot add snapins that are restricted.
  1312. */
  1313. if (IsMMCRunningAsOLEServer())
  1314. {
  1315. DWORD dwRestrictScriptsFromEnteringAuthorMode = 0;
  1316. lResult = regKey.QueryValue(dwRestrictScriptsFromEnteringAuthorMode, g_szRestrictScriptsFromEnteringAuthorMode);
  1317. if (lResult != ERROR_SUCCESS)
  1318. return sc;
  1319. if (dwRestrictScriptsFromEnteringAuthorMode == 0) // Scripts can enter author mode so return
  1320. return sc;
  1321. sc = ScFromMMC(IDS_AUTHORMODE_NOTALLOWED_FORSCRIPTS);
  1322. }
  1323. else
  1324. // If author mode is not allowed and
  1325. // the user tried to force author mode
  1326. // then display error message and exit.
  1327. sc = ScFromMMC(IDS_AUTHORMODE_NOTALLOWED);
  1328. return sc;
  1329. }
  1330. /*+-------------------------------------------------------------------------*
  1331. *
  1332. * CAMCApp::ScCheckMMCPrerequisites
  1333. *
  1334. * PURPOSE: Checks all prerequisites. These are: (add to the list as appropriate)
  1335. * 1) Internet Explorer 5.5 or greater must be installed
  1336. *
  1337. * RETURNS:
  1338. * SC
  1339. *
  1340. *+-------------------------------------------------------------------------*/
  1341. SC
  1342. CAMCApp::ScCheckMMCPrerequisites()
  1343. {
  1344. DECLARE_SC(sc, TEXT("CAMCApp::ScCheckMMCPrerequisites"));
  1345. // 1. Determine the installed version of Internet Explorer.
  1346. const int cchDATA = 100;
  1347. TCHAR szVersion[cchDATA];
  1348. BOOL bIE55Found = false;
  1349. HKEY hkey = NULL;
  1350. DWORD dwType =0;
  1351. DWORD dwMajor =0;
  1352. DWORD dwMinor =0;
  1353. DWORD dwRevision =0;
  1354. DWORD dwBuild =0;
  1355. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Internet Explorer"), 0, KEY_READ, &hkey))
  1356. {
  1357. DWORD cbData = sizeof(TCHAR) * cchDATA;
  1358. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("Version"), 0, &dwType, (LPBYTE)szVersion, &cbData))
  1359. {
  1360. if (lstrlen(szVersion) > 0)
  1361. {
  1362. if (_stscanf(szVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild) >= 2)
  1363. {
  1364. //Make sure IE 5.5 or greater is installed. To do this:
  1365. // 1) Check if the major version is >= 6. If so we're done.
  1366. // 2) If the major version is 5, the minor version should be >= 50
  1367. if (dwMajor >= 6)
  1368. {
  1369. bIE55Found = true;
  1370. }
  1371. if (dwMajor == 5)
  1372. {
  1373. if(dwMinor >= 50)
  1374. bIE55Found = true;
  1375. }
  1376. }
  1377. }
  1378. }
  1379. RegCloseKey(hkey);
  1380. }
  1381. if (!bIE55Found)
  1382. {
  1383. sc = ScFromMMC(MMC_E_INCORRECT_IE_VERSION); // NOTE: update the string when the version requirement changes
  1384. return sc;
  1385. }
  1386. return sc;
  1387. }
  1388. /*+-------------------------------------------------------------------------*
  1389. *
  1390. * CAMCApp::InitInstance
  1391. *
  1392. * PURPOSE: Initializes the document.
  1393. *
  1394. * NOTE: as an aside, if you need to break on, say, the 269th allocation,
  1395. * add the following code:
  1396. *
  1397. * #define ALLOCATION_NUM 269
  1398. * _CrtSetBreakAlloc(ALLOCATION_NUM);
  1399. * _crtBreakAlloc = ALLOCATION_NUM;
  1400. *
  1401. * RETURNS:
  1402. * BOOL
  1403. *
  1404. *+-------------------------------------------------------------------------*/
  1405. BOOL CAMCApp::InitInstance()
  1406. {
  1407. DECLARE_SC(sc, TEXT("CAMCApp::InitInstance"));
  1408. /*
  1409. * Initialize Fusion.
  1410. */
  1411. //RAID 656865: Prefix: return value from SHFusionInitializeFromModuleID ignored
  1412. if (!SHFusionInitializeFromModuleID (NULL, static_cast<int>(reinterpret_cast<ULONG_PTR>(SXS_MANIFEST_RESOURCE_ID))))
  1413. {
  1414. sc = E_UNEXPECTED;
  1415. return FALSE;
  1416. }
  1417. #ifdef DBG
  1418. if (tagForceMirror.FAny())
  1419. {
  1420. HINSTANCE hmodUser = GetModuleHandle (_T("user32.dll"));
  1421. if (hmodUser != NULL)
  1422. {
  1423. BOOL (WINAPI* pfnSetProcessDefaultLayout)(DWORD);
  1424. (FARPROC&)pfnSetProcessDefaultLayout = GetProcAddress (hmodUser, "SetProcessDefaultLayout");
  1425. if (pfnSetProcessDefaultLayout != NULL)
  1426. (*pfnSetProcessDefaultLayout)(LAYOUT_RTL);
  1427. }
  1428. }
  1429. #endif
  1430. BOOL bRet = TRUE;
  1431. // Initialize OLE libraries
  1432. if (InitializeOLE() == FALSE)
  1433. return FALSE;
  1434. // Initialize the ATL Module
  1435. _Module.Init(ObjectMap,m_hInstance);
  1436. #ifdef DBG
  1437. if(tagGDIBatching.FAny())
  1438. {
  1439. // disable GDI batching so we'll see drawing as it happens
  1440. GdiSetBatchLimit (1);
  1441. }
  1442. #endif
  1443. Unregister();
  1444. Trace(tagAMCAppInit, TEXT("CAMCApp::InitInstance"));
  1445. CMMCCommandLineInfo cmdInfo;
  1446. ParseCommandLine(cmdInfo);
  1447. /*
  1448. * if we got a file on the command line, expand environment
  1449. * variables in the filename so we can open files like
  1450. * "%SystemRoot%\system32\compmgmt.msc"
  1451. */
  1452. if (!cmdInfo.m_strFileName.IsEmpty())
  1453. {
  1454. CWow64FilesystemRedirectionDisabler disabler (cmdInfo.m_strFileName);
  1455. sc = ScExpandEnvironmentStrings (cmdInfo.m_strFileName);
  1456. if (sc)
  1457. {
  1458. MMCErrorBox (sc);
  1459. return (false);
  1460. }
  1461. }
  1462. // Don't use an .ini file for the MRU or Settings
  1463. // Note: This string does not need to be localizable.
  1464. // HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft Management Console
  1465. SetRegistryKey(_T("Microsoft"));
  1466. // Find out OS version.
  1467. OSVERSIONINFO versInfo;
  1468. versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1469. BOOL bStat = GetVersionEx(&versInfo);
  1470. ASSERT(bStat);
  1471. m_fIsWin9xPlatform = (versInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
  1472. // default to Author mode (loading a console may change this later)
  1473. InitializeMode (eMode_Author);
  1474. m_fAuthorModeForced = cmdInfo.m_fForceAuthorMode ||
  1475. cmdInfo.m_strFileName.IsEmpty();
  1476. /*
  1477. * dump the snap-ins (and do nothing else) if we got "-dump:<filename>"
  1478. */
  1479. if (!cmdInfo.m_strDumpFilename.IsEmpty())
  1480. {
  1481. DumpConsoleFile (cmdInfo.m_strFileName, cmdInfo.m_strDumpFilename);
  1482. return (false);
  1483. }
  1484. #ifdef MMC_WIN64
  1485. /*
  1486. * We're currently running the MMC64. See if we need to defer to MMC32.
  1487. * If we do, try to launch MMC32. If we were able to launch MMC32
  1488. * successfully, abort MMC64.
  1489. */
  1490. eArchitecture eArch = eArch_64bit;
  1491. sc = ScDetermineArchitecture (cmdInfo, eArch);
  1492. if (sc)
  1493. {
  1494. DisplayFileOpenError (sc, cmdInfo.m_strFileName);
  1495. return (false);
  1496. }
  1497. switch (eArch)
  1498. {
  1499. /*
  1500. * MMC64 is fine, do nothing
  1501. */
  1502. case eArch_64bit:
  1503. break;
  1504. /*
  1505. * User cancelled action, abort
  1506. */
  1507. case eArch_None:
  1508. return (false);
  1509. break;
  1510. /*
  1511. * We need MMC32, so try to launch it. If we were able to launch MMC32
  1512. * successfully, abort MMC64; if not, continue running MMC64.
  1513. */
  1514. case eArch_32bit:
  1515. if (!ScLaunchMMC(eArch_32bit, m_nCmdShow).IsError())
  1516. {
  1517. Trace (tag32BitTransfer, _T("32-bit MMC launched successfully"));
  1518. return (false);
  1519. }
  1520. Trace (tag32BitTransfer, _T("32-bit MMC failed to launch"));
  1521. MMCErrorBox (MMC_E_UnableToLaunchMMC32);
  1522. break;
  1523. default:
  1524. ASSERT (false && "Unexpected architecture returned from ScDetermineArchitecture");
  1525. break;
  1526. }
  1527. #elif defined(UNICODE)
  1528. /*
  1529. * We're currently running the MMC32. If it's running on IA64 and 32-bit
  1530. * wasn't specifically requested with a "-32" switch (this is what MMC64
  1531. * will do when it defers to MMC32), defer to MMC64 so it can do snap-in
  1532. * analysis and determine the appropriate "bitness" to run.
  1533. */
  1534. if ((cmdInfo.m_eArch != eArch_32bit) && IsWin64())
  1535. {
  1536. /*
  1537. * We need MMC64, so try to launch it. If we were able to launch MMC64
  1538. * successfully, abort MMC32; if not, continue running MMC32.
  1539. */
  1540. if (!ScLaunchMMC(eArch_64bit, m_nCmdShow).IsError())
  1541. {
  1542. Trace (tag32BitTransfer, _T("64-bit MMC launched successfully"));
  1543. return (false);
  1544. }
  1545. Trace (tag32BitTransfer, _T("64-bit MMC failed to launch"));
  1546. MMCErrorBox (MMC_E_UnableToLaunchMMC64);
  1547. }
  1548. #endif // MMC_WIN64
  1549. AfxEnableControlContainer();
  1550. // Standard initialization
  1551. #ifdef _AFXDLL
  1552. Enable3dControls(); // Call this when using MFC in a shared DLL
  1553. #else
  1554. Enable3dControlsStatic(); // Call this when linking to MFC statically
  1555. #endif
  1556. LoadStdProfileSettings(); // Load standard INI file options (including MRU)
  1557. // create our own CDocManager derivative before adding any templates
  1558. // (CWinApp::~CWinApp will delete it)
  1559. m_pDocManager = new CAMCDocManager;
  1560. // Register document templates
  1561. CMultiDocTemplate* pDocTemplate;
  1562. pDocTemplate = new CAMCMultiDocTemplate(
  1563. IDR_AMCTYPE,
  1564. RUNTIME_CLASS(CAMCDoc),
  1565. RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  1566. RUNTIME_CLASS(CAMCView));
  1567. AddDocTemplate(pDocTemplate);
  1568. // Note: MDI applications register all server objects without regard
  1569. // to the /Embedding or /Automation on the command line.
  1570. if (cmdInfo.m_fRegisterServer)
  1571. {
  1572. sc = _Module.RegisterServer(TRUE);// ATL Classes
  1573. if (sc == TYPE_E_REGISTRYACCESS)
  1574. sc.TraceAndClear();
  1575. }
  1576. if (sc)
  1577. {
  1578. MMCErrorBox (sc);
  1579. return (false);
  1580. }
  1581. // create main MDI Frame window
  1582. CMainFrame *pMainFrame = new CMainFrame;
  1583. if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
  1584. return FALSE;
  1585. m_pMainWnd = pMainFrame;
  1586. // set the HWND to use as the parent for modal error dialogs.
  1587. SC::SetHWnd(pMainFrame->GetSafeHwnd());
  1588. // save this main thread's ID to check if snapins call MMC
  1589. // interfaces from main thread.
  1590. SC::SetMainThreadID(::GetCurrentThreadId());
  1591. m_fRunningAsOLEServer = false;
  1592. // Check to see if launched as OLE server
  1593. if (RunEmbedded() || RunAutomated())
  1594. {
  1595. m_fRunningAsOLEServer = true;
  1596. // Application was run with /Embedding or /Automation. Don't show the
  1597. // main window in this case.
  1598. //return TRUE;
  1599. // Also set that script is controlling the application not the user
  1600. // The script can modify the UserControl property on the application.
  1601. SetUnderUserControl(false);
  1602. // When a server application is launched stand-alone, it is a good idea to register all objects
  1603. // ATL ones specifically register with REGCLS_MULTIPLEUSE
  1604. // we register class objects only when run as an OLE server. This way, cannot connect to
  1605. // an existing instance of MMC.
  1606. sc = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE);
  1607. if(sc)
  1608. goto Error;
  1609. }
  1610. if (cmdInfo.m_fRegisterServer)
  1611. {
  1612. CString strTypeLib;
  1613. strTypeLib.Format(TEXT("\\%d"), IDR_WEBSINK_TYPELIB); // this should evaluate to something like "\\4"
  1614. sc = _Module.RegisterTypeLib((LPCTSTR)strTypeLib);
  1615. if (sc == TYPE_E_REGISTRYACCESS)
  1616. sc.TraceAndClear();
  1617. if(sc)
  1618. goto Error;
  1619. }
  1620. // Don't Enable drag/drop open
  1621. // m_pMainWnd->DragAcceptFiles();
  1622. // Enable DDE Execute open
  1623. if (cmdInfo.m_fRegisterServer)
  1624. RegisterShellFileTypes(FALSE);
  1625. EnableShellOpen();
  1626. if (cmdInfo.m_fRegisterServer)
  1627. DeleteDDEKeys();
  1628. /*
  1629. * At this point, all of our registration is complete. If we were invoked
  1630. * with -RegServer, we can bail now.
  1631. */
  1632. if (cmdInfo.m_fRegisterServer)
  1633. return (false);
  1634. { // limit scope of disabler
  1635. CWow64FilesystemRedirectionDisabler disabler (cmdInfo.m_strFileName);
  1636. // Dispatch commands specified on the command line.
  1637. // This loads a console file if necessary.
  1638. if (!ProcessShellCommand(cmdInfo))
  1639. return (false); // user is already informed about errors
  1640. }
  1641. // Now the console file is loaded. Check if Author mode
  1642. // is permitted.
  1643. sc = ScProcessAuthorModeRestrictions(); // check if there are any restrictions set by policy
  1644. if(sc)
  1645. goto Error;
  1646. // if proccessing the command line put MMC into author mode,
  1647. // it has to stick with it forever.
  1648. // see bug 102465 openning an author mode console file and then
  1649. // a user mode console switched MMC into user mode
  1650. if (eMode_Author == m_eMode)
  1651. m_fAuthorModeForced = true;
  1652. // create a document automatically only if we're not instantiated as an
  1653. // OLE server.
  1654. if(! IsMMCRunningAsOLEServer ())
  1655. {
  1656. // if we don't have a document now (maybe because
  1657. // the Node Manager wasn't registered), punt
  1658. CAMCDoc* pDoc = CAMCDoc::GetDocument ();
  1659. if (pDoc == NULL)
  1660. return (FALSE);
  1661. pDoc->SetFrameModifiedFlag (false);
  1662. pDoc->UpdateFrameCounts ();
  1663. CMainFrame *pMainFrame = GetMainFrame();
  1664. if (pMainFrame)
  1665. {
  1666. pMainFrame->ShowWindow(m_nCmdShow);
  1667. pMainFrame->UpdateWindow();
  1668. }
  1669. // showing will set the frame and "Modified" - reset it
  1670. pDoc->SetFrameModifiedFlag (false);
  1671. }
  1672. // register itself as dispatcher able to dispatch com events
  1673. sc = CConsoleEventDispatcherProvider::ScSetConsoleEventDispatcher( this );
  1674. if (sc)
  1675. goto Error;
  1676. m_fInitializing = false;
  1677. // check for all MMC prerequisites
  1678. sc = ScCheckMMCPrerequisites();
  1679. if (sc)
  1680. goto Error;
  1681. // Comment out below line when script engines hosted in mmc are enabled.
  1682. // sc = ScRunTestScript();
  1683. Cleanup:
  1684. return bRet;
  1685. Error:
  1686. MMCErrorBox(sc);
  1687. bRet = FALSE;
  1688. goto Cleanup;
  1689. }
  1690. //+-------------------------------------------------------------------
  1691. //
  1692. // Member: ScRunTestScript
  1693. //
  1694. // Synopsis: Test program to run a script. Once script input mechanisms
  1695. // are defined this can be removed.
  1696. //
  1697. // Arguments: None
  1698. //
  1699. // Returns: SC
  1700. //
  1701. //--------------------------------------------------------------------
  1702. SC CAMCApp::ScRunTestScript ()
  1703. {
  1704. DECLARE_SC(sc, _T("CAMCApp::ScRunTestScript"));
  1705. // The Running of scripts is enabled only in debug mode.
  1706. bool bEnableScriptEngines = false;
  1707. #ifdef DBG
  1708. if (tagEnableScriptEngines.FAny())
  1709. bEnableScriptEngines = true;
  1710. #endif
  1711. if (!bEnableScriptEngines)
  1712. return sc;
  1713. // Get the IDispatch from MMC object, the script engine needs
  1714. // the IUnknown to top level object & the ITypeInfo ptr.
  1715. CComPtr<_Application> spApplication;
  1716. sc = ScGet_Application(&spApplication);
  1717. if (sc)
  1718. return sc;
  1719. IDispatchPtr spDispatch = NULL;
  1720. sc = spApplication->QueryInterface(IID_IDispatch, (LPVOID*)&spDispatch);
  1721. if (sc)
  1722. return sc;
  1723. // The CScriptHostMgr should be instead created on the stack (as we have only
  1724. // one per app) and destroyed with app. This change can be made once we decide
  1725. // how & when the script host will be used to execute the scripts.
  1726. CScriptHostMgr* pMgr = new CScriptHostMgr(spDispatch);
  1727. if (NULL == pMgr)
  1728. return (sc = E_OUTOFMEMORY);
  1729. LPOLESTR pszScript = L"set WShShell=CreateObject(\"WScript.Shell\")\n\
  1730. WshShell.Popup(\"Anand\")\n\
  1731. Select Case WshShell.Popup(\"Anand\",5,\"Ganesan\", vbyesnocancel)\n\
  1732. End Select";
  1733. tstring strExtn = _T(".vbs");
  1734. sc = pMgr->ScExecuteScript(pszScript, strExtn);
  1735. tstring strFile = _T("E:\\newnt\\admin\\mmcdev\\test\\script\\MMCStartupScript.vbs");
  1736. sc = pMgr->ScExecuteScript(strFile);
  1737. delete pMgr;
  1738. return (sc);
  1739. }
  1740. // App command to run the dialog
  1741. void CAMCApp::OnAppAbout()
  1742. {
  1743. /*
  1744. * load the title of the about dialog
  1745. */
  1746. CString strTitle (MAKEINTRESOURCE (IDS_APP_NAME));
  1747. CString strVersion (MAKEINTRESOURCE (IDS_APP_VERSION));
  1748. strTitle += _T(" ");
  1749. strTitle += strVersion;
  1750. ShellAbout(*AfxGetMainWnd(), strTitle, NULL, LoadIcon(IDR_MAINFRAME));
  1751. }
  1752. /*+-------------------------------------------------------------------------*
  1753. *
  1754. * CAMCApp::OnFileNewInUserMode
  1755. *
  1756. * PURPOSE: Do nothing in user mode when CTRL+N is pressed.
  1757. * This handler prevents the hotkey from going to any WebBrowser controls
  1758. *
  1759. * RETURNS:
  1760. * void
  1761. *
  1762. *+-------------------------------------------------------------------------*/
  1763. void CAMCApp::OnFileNewInUserMode()
  1764. {
  1765. MessageBeep(-1);
  1766. }
  1767. //+-------------------------------------------------------------------
  1768. //
  1769. // Member: ScShowHtmlHelp
  1770. //
  1771. // Synopsis: Initialize and then call Help control to display help topic.
  1772. //
  1773. // Arguments: [pszFile] - File to display.
  1774. // [dwData] - Depends on uCommand for HH_DISPLAY_TOPIC it
  1775. // is help topic string.
  1776. //
  1777. // Note: The command is always HH_DISPLAY_TOPIC. HWND is NULL so that
  1778. // Help can get behind MMC window.
  1779. // See ScUnintializeHelpControl's Note for more info.
  1780. //
  1781. // Returns: SC
  1782. //
  1783. //--------------------------------------------------------------------
  1784. SC CAMCApp::ScShowHtmlHelp(LPCTSTR pszFile, DWORD_PTR dwData)
  1785. {
  1786. DECLARE_SC(sc, _T("CAMCApp::ScInitializeHelpControl"));
  1787. /*
  1788. * displaying HtmlHelp might take awhile, so show a wait cursor
  1789. */
  1790. CWaitCursor wait;
  1791. if (! m_bHelpInitialized)
  1792. HtmlHelp (NULL, NULL, HH_INITIALIZE, (DWORD_PTR)&m_dwHelpCookie);
  1793. // No documented return value for HH_INITIALIZE so always assume
  1794. // Initialize is successful.
  1795. m_bHelpInitialized = true;
  1796. HtmlHelp (NULL, pszFile, HH_DISPLAY_TOPIC, dwData);
  1797. return sc;
  1798. }
  1799. //+-------------------------------------------------------------------
  1800. //
  1801. // Member: ScUninitializeHelpControl
  1802. //
  1803. // Synopsis: UnInitialize the help if it was initialized by MMC.
  1804. //
  1805. // Note: The help-control calls OleInitialize & OleUninitialize
  1806. // in its DllMain. If a snapin creates any free threaded object
  1807. // on main thread (STA), the OLE creates an MTA.
  1808. // The last OleUninitialize does OLEProcessUninitialize in which
  1809. // then OLE waits for the above MTA to cleanup and return.
  1810. // By the time help-control does last OleUninitialize in its
  1811. // DllMain the MTA is already terminated so OLE waits for this
  1812. // MTA to signal which it never would.
  1813. // We call HtmlHelp(.. HH_UNINITIALIZE..) to force help control
  1814. // to uninit so that MMC does last OleUninit.
  1815. // (This will not solve the problem of snapins calling help directly).
  1816. //
  1817. // Arguments:
  1818. //
  1819. // Returns: SC, S_FALSE if already uninitialized else S_OK.
  1820. //
  1821. //--------------------------------------------------------------------
  1822. SC CAMCApp::ScUninitializeHelpControl()
  1823. {
  1824. DECLARE_SC(sc, _T("CAMCApp::ScUninitializeHelpControl"));
  1825. if (false == m_bHelpInitialized)
  1826. return (sc = S_FALSE);
  1827. HtmlHelp (NULL, NULL, HH_UNINITIALIZE, m_dwHelpCookie);
  1828. m_bHelpInitialized = false;
  1829. m_dwHelpCookie = 0;
  1830. return sc;
  1831. }
  1832. BOOL CAMCApp::InitializeOLE()
  1833. {
  1834. if (FAILED(::OleInitialize(NULL)))
  1835. return FALSE;
  1836. return (m_bOleInitialized = TRUE);
  1837. }
  1838. void CAMCApp::DeinitializeOLE()
  1839. {
  1840. // Uninit help, see ScUninitializeHelpControl note.
  1841. SC sc = ScUninitializeHelpControl();
  1842. if (sc)
  1843. {
  1844. TraceError(_T("Uninit Help control failed"), sc);
  1845. }
  1846. // Forced DllCanUnloadNow before mmc exits.
  1847. ::CoFreeUnusedLibraries();
  1848. if (m_bOleInitialized == TRUE)
  1849. {
  1850. ::OleUninitialize();
  1851. m_bOleInitialized = FALSE;
  1852. }
  1853. }
  1854. /////////////////////////////////////////////////////////////////////////////
  1855. // CAMCApp diagnostics
  1856. #ifdef _DEBUG
  1857. void CAMCApp::AssertValid() const
  1858. {
  1859. CWinApp::AssertValid();
  1860. }
  1861. #endif //_DEBUG
  1862. /////////////////////////////////////////////////////////////////////////////
  1863. // CAMCApp commands
  1864. int CAMCApp::ExitInstance()
  1865. {
  1866. DECLARE_SC(sc, TEXT("CAMCApp::ExitInstance"));
  1867. // if the main window is not destroyed yet - do that now.
  1868. // since we need to get rid of all the objects before denitializing OLE.
  1869. // It is not requred in most cases, since usually quit starts from closing the mainframe,
  1870. // but in cases like system shut down it will come here with a valid window
  1871. // See WindowsBug(ntbug9) #178858
  1872. if ( ::IsWindow( AfxGetMainWnd()->GetSafeHwnd() ) )
  1873. {
  1874. AfxGetMainWnd()->DestroyWindow();
  1875. }
  1876. // disconnect the pointers to event dispatcher
  1877. sc = CConsoleEventDispatcherProvider::ScSetConsoleEventDispatcher( NULL );
  1878. if (sc)
  1879. sc.TraceAndClear();
  1880. // release cached application object
  1881. m_sp_Application = NULL;
  1882. // MFC's class factories registration is automatically revoked by MFC itself
  1883. if (RunEmbedded() || RunAutomated())
  1884. _Module.RevokeClassObjects(); // Revoke class factories for ATL
  1885. _Module.Term(); // clanup ATL GLobal Module
  1886. // Ask node manager to cleanup what's got cached
  1887. CComPtr<IComCacheCleanup> spComCacheCleanup;
  1888. HRESULT hr = spComCacheCleanup.CoCreateInstance(CLSID_ComCacheCleanup, NULL, MMC_CLSCTX_INPROC);
  1889. if (hr == S_OK)
  1890. {
  1891. spComCacheCleanup->ReleaseCachedOleObjects();
  1892. spComCacheCleanup.Release();
  1893. }
  1894. // by now EVERY reference should be released
  1895. ASSERT(_Module.GetLockCount() == 0 && "Outstanding references still exist on exit");
  1896. DeinitializeOLE();
  1897. /*
  1898. * uninitialize Fusion
  1899. */
  1900. SHFusionUninitialize();
  1901. int iRet = CWinApp::ExitInstance();
  1902. DEBUG_VERIFY_INSTANCE_COUNT(CAMCTreeView);
  1903. DEBUG_VERIFY_INSTANCE_COUNT(CAMCListView);
  1904. DEBUG_VERIFY_INSTANCE_COUNT(CCCListViewCtrl);
  1905. return iRet;
  1906. }
  1907. BOOL CAMCApp::PreTranslateMessage(MSG* pMsg)
  1908. {
  1909. // Give HTML help a chance to crack the message. (Bug# 119355 & 206909).
  1910. if ( m_bHelpInitialized && HtmlHelp(NULL, NULL, HH_PRETRANSLATEMESSAGE, (DWORD_PTR)pMsg) )
  1911. return TRUE;
  1912. // let all of the hook windows have a crack at this message
  1913. WindowListIterator it = m_TranslateMessageHookWindows.begin();
  1914. while (it != m_TranslateMessageHookWindows.end())
  1915. {
  1916. HWND hwndHook = *it;
  1917. CWnd* pwndHook = CWnd::FromHandlePermanent (hwndHook);
  1918. // if this window is no longer valid, or it's not a permanent
  1919. // window, remove it from the list
  1920. if (!IsWindow (hwndHook) || (pwndHook == NULL))
  1921. it = m_TranslateMessageHookWindows.erase (it);
  1922. else
  1923. {
  1924. // otherwise if the hook window handled the message, bail
  1925. if (pwndHook->PreTranslateMessage (pMsg))
  1926. return (TRUE);
  1927. ++it;
  1928. }
  1929. }
  1930. // give the MMC defined main window accelerators a crack at the message
  1931. if (m_Accel.TranslateAccelerator (AfxGetMainWnd()->GetSafeHwnd(), pMsg))
  1932. return TRUE;
  1933. return CWinApp::PreTranslateMessage(pMsg);
  1934. }
  1935. /*+-------------------------------------------------------------------------*
  1936. * CAMCApp::SaveUserDirectory
  1937. *
  1938. *
  1939. *--------------------------------------------------------------------------*/
  1940. void CAMCApp::SaveUserDirectory(LPCTSTR pszUserDir)
  1941. {
  1942. // if we got an empty string, change the pointer to NULL so
  1943. // the entry will be removed from the registry
  1944. if ((pszUserDir != NULL) && (lstrlen(pszUserDir) == 0))
  1945. pszUserDir = NULL;
  1946. WriteProfileString (m_szSettingsSection, m_szUserDirectoryEntry,
  1947. pszUserDir);
  1948. }
  1949. /*+-------------------------------------------------------------------------*
  1950. * CAMCApp::GetUserDirectory
  1951. *
  1952. *
  1953. *--------------------------------------------------------------------------*/
  1954. CString CAMCApp::GetUserDirectory(void)
  1955. {
  1956. return (GetProfileString (m_szSettingsSection, m_szUserDirectoryEntry));
  1957. }
  1958. /*+-------------------------------------------------------------------------*
  1959. * CAMCApp::GetDefaultDirectory
  1960. *
  1961. *
  1962. *--------------------------------------------------------------------------*/
  1963. CString CAMCApp::GetDefaultDirectory(void)
  1964. {
  1965. static CString strDefaultDir;
  1966. if (strDefaultDir.IsEmpty())
  1967. {
  1968. LPITEMIDLIST pidl;
  1969. if (SUCCEEDED(SHGetSpecialFolderLocation(
  1970. AfxGetMainWnd()->GetSafeHwnd(),
  1971. CSIDL_ADMINTOOLS | CSIDL_FLAG_CREATE, &pidl)))
  1972. {
  1973. // Convert to path name
  1974. SHGetPathFromIDList (pidl, strDefaultDir.GetBuffer (MAX_PATH));
  1975. strDefaultDir.ReleaseBuffer ();
  1976. // Free IDList
  1977. LPMALLOC pMalloc;
  1978. if (SUCCEEDED(SHGetMalloc (&pMalloc)))
  1979. {
  1980. pMalloc->Free(pidl);
  1981. pMalloc->Release();
  1982. }
  1983. }
  1984. }
  1985. return (strDefaultDir);
  1986. }
  1987. /*+-------------------------------------------------------------------------*
  1988. * CAMCApp::SetDefaultDirectory
  1989. *
  1990. *
  1991. *--------------------------------------------------------------------------*/
  1992. void CAMCApp::SetDefaultDirectory(void)
  1993. {
  1994. // Only set default first time, so we don't override user selection
  1995. if (m_bDefaultDirSet)
  1996. return;
  1997. // Set the current directory to the default directory
  1998. CString strDirectory;
  1999. BOOL rc = FALSE;
  2000. strDirectory = GetDefaultDirectory ();
  2001. if (!strDirectory.IsEmpty())
  2002. rc = SetCurrentDirectory (strDirectory);
  2003. m_bDefaultDirSet = rc;
  2004. }
  2005. /*+-------------------------------------------------------------------------*
  2006. * CAMCApp::PumpMessage
  2007. *
  2008. *
  2009. *--------------------------------------------------------------------------*/
  2010. BOOL CAMCApp::PumpMessage()
  2011. {
  2012. m_nMessagePumpNestingLevel++;
  2013. MSG msg;
  2014. ::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
  2015. if (msg.message == WM_CLOSE)
  2016. m_fCloseCameFromMainPump = true;
  2017. BOOL rc = CWinApp::PumpMessage();
  2018. if (m_fDelayCloseUntilIdle && (m_nMessagePumpNestingLevel == 1))
  2019. {
  2020. m_fCloseCameFromMainPump = true;
  2021. CMainFrame *pMainFrame = GetMainFrame();
  2022. if (pMainFrame)
  2023. pMainFrame->SendMessage (WM_CLOSE);
  2024. m_fDelayCloseUntilIdle = false;
  2025. }
  2026. m_fCloseCameFromMainPump = false;
  2027. m_nMessagePumpNestingLevel--;
  2028. ASSERT (m_nMessagePumpNestingLevel >= 0);
  2029. return (rc);
  2030. }
  2031. /*+-------------------------------------------------------------------------*
  2032. *
  2033. * CAMCApp::ScHelp
  2034. *
  2035. * PURPOSE: Displays help for the application.
  2036. *
  2037. * RETURNS:
  2038. * SC
  2039. *
  2040. *+-------------------------------------------------------------------------*/
  2041. SC
  2042. CAMCApp::ScHelp()
  2043. {
  2044. DECLARE_SC(sc, TEXT("CAMCApp::ScHelp"));
  2045. CMainFrame * pMainFrame = GetMainFrame();
  2046. if(!pMainFrame)
  2047. {
  2048. sc = E_UNEXPECTED;
  2049. return sc;
  2050. }
  2051. pMainFrame->OnHelpTopics();
  2052. return sc;
  2053. }
  2054. /*+-------------------------------------------------------------------------*
  2055. * CAMCApp::OnIdle
  2056. *
  2057. * WM_IDLE handler for CAMCApp.
  2058. *--------------------------------------------------------------------------*/
  2059. BOOL CAMCApp::OnIdle(LONG lCount)
  2060. {
  2061. SC sc;
  2062. CIdleTaskQueue * pQueue = GetIdleTaskQueue();
  2063. BOOL fMoreIdleWork = TRUE;
  2064. if(NULL == pQueue)
  2065. {
  2066. ASSERT(0 && "Should not come here.");
  2067. goto Error;
  2068. }
  2069. fMoreIdleWork = CWinApp::OnIdle(lCount);
  2070. if (!fMoreIdleWork)
  2071. {
  2072. CMainFrame *pMainFrame = GetMainFrame();
  2073. if (pMainFrame)
  2074. pMainFrame->OnIdle ();
  2075. }
  2076. /*
  2077. * if MFC doesn't have any more idle work to do,
  2078. * check our idle task queue (if we have one)
  2079. */
  2080. if (!fMoreIdleWork && (pQueue != NULL))
  2081. {
  2082. LONG_PTR cIdleTasks;
  2083. pQueue->ScGetTaskCount (&cIdleTasks);
  2084. if(sc)
  2085. goto Error;
  2086. /*
  2087. * do we have any idle tasks?
  2088. */
  2089. if (cIdleTasks > 0)
  2090. {
  2091. SC sc = pQueue->ScPerformNextTask();
  2092. if(sc)
  2093. goto Error;
  2094. /*
  2095. * this idle task may have added others; refresh the count
  2096. */
  2097. sc = pQueue->ScGetTaskCount(&cIdleTasks);
  2098. if(sc)
  2099. goto Error;
  2100. }
  2101. /*
  2102. * do we have any more idle work to do?
  2103. */
  2104. fMoreIdleWork = (cIdleTasks > 0);
  2105. }
  2106. if (!fMoreIdleWork)
  2107. {
  2108. // this code is to trigger MMC exit sequence when it
  2109. // is under the script control and the last reference is released.
  2110. // (we do not use MFC [which would simply delete the mainframe] to do that)
  2111. if ( !IsUnderUserControl() && CMMCStrongReferences::LastRefReleased() )
  2112. {
  2113. // we are in script control mode and all references are released
  2114. // a good time to say goodbye
  2115. CMainFrame *pMainFrame = GetMainFrame();
  2116. sc = ScCheckPointers(pMainFrame, E_UNEXPECTED);
  2117. if (sc)
  2118. goto Error;
  2119. // disabled main window will probably mean we are under modal dialog
  2120. // wait until it is dismissed ( and try again )
  2121. if (pMainFrame->IsWindowEnabled())
  2122. {
  2123. // here is the deal: if MMC is shown - we will initiate the exit sequence,
  2124. // but put into the user mode first, so if user chooses to cancel it - it will have
  2125. // the control over the application. He will also have to handle save request if
  2126. // something has changed in the console
  2127. if ( pMainFrame->IsWindowVisible() )
  2128. {
  2129. if ( !m_fUnderUserControl )
  2130. SetUnderUserControl();
  2131. pMainFrame->PostMessage(WM_CLOSE);
  2132. }
  2133. else
  2134. {
  2135. // if the application is hidden it should wait until user closes all open property sheets.
  2136. // since it will come back here, waiting means just doing nothing at this point.
  2137. if ( !FArePropertySheetsOpen(NULL, false /*bBringToFrontAndAskToClose*/ ) )
  2138. {
  2139. // if there are not sheets open - we must die silently
  2140. CAMCDoc* const pDoc = CAMCDoc::GetDocument();
  2141. if(pDoc == NULL)
  2142. {
  2143. sc = E_POINTER;
  2144. //fall thru; (need to close anyway)
  2145. }
  2146. else
  2147. {
  2148. // discard document without asking to save
  2149. pDoc->OnCloseDocument();
  2150. }
  2151. // say goodbye
  2152. pMainFrame->PostMessage(WM_CLOSE);
  2153. }
  2154. }
  2155. }
  2156. }
  2157. }
  2158. Cleanup:
  2159. return (fMoreIdleWork);
  2160. Error:
  2161. TraceError(TEXT("CAMCApp::OnIdle"), sc);
  2162. goto Cleanup;
  2163. }
  2164. //+-------------------------------------------------------------------
  2165. //
  2166. // Member: InitializeMode
  2167. //
  2168. // Synopsis: Set the mode and load the menus, accelerator tables.
  2169. //
  2170. // Arguments: [eMode] - New application mode.
  2171. //
  2172. // Returns: None.
  2173. //
  2174. //--------------------------------------------------------------------
  2175. void CAMCApp::InitializeMode (ProgramMode eMode)
  2176. {
  2177. SetMode(eMode);
  2178. UpdateFrameWindow(false);
  2179. }
  2180. //+-------------------------------------------------------------------
  2181. //
  2182. // Member: SetMode
  2183. //
  2184. // Synopsis: Set the mode.
  2185. //
  2186. // Note: Call UpdateFrameWindow some time soon to update
  2187. // menus/toolbars for this mode.
  2188. // Cannot do this in this method. This is called
  2189. // from CAMCDoc::LoadAppMode. The CAMCDoc::LoadFrame
  2190. // calls the UpdateFrameWindow.
  2191. //
  2192. // Arguments: [eMode] - New application mode.
  2193. //
  2194. // Returns: None.
  2195. //
  2196. //--------------------------------------------------------------------
  2197. void CAMCApp::SetMode (ProgramMode eMode)
  2198. {
  2199. ASSERT (IsValidProgramMode (eMode));
  2200. if (m_fAuthorModeForced)
  2201. {
  2202. ASSERT (m_eMode == eMode_Author);
  2203. ASSERT (GetMainFrame()->IsMenuVisible ());
  2204. }
  2205. else
  2206. m_eMode = eMode;
  2207. }
  2208. //+-------------------------------------------------------------------
  2209. //
  2210. // Member: UpdateFrameWindow
  2211. //
  2212. // Synopsis: Load the menu/accelerator tables and update
  2213. // them if loaded from console file.
  2214. //
  2215. // Note: Call UpdateFrameWindow some time soon after
  2216. // calling SetMode to update menus/toolbars for this mode.
  2217. // This is called from CAMCDoc::LoadFrame.
  2218. //
  2219. // Arguments: [bUpdate] - BOOL
  2220. // We need to update the toolbar/menus only
  2221. // if loaded from console file
  2222. //
  2223. // Returns: None.
  2224. //
  2225. //--------------------------------------------------------------------
  2226. void CAMCApp::UpdateFrameWindow(bool bUpdate)
  2227. {
  2228. static const struct ModeDisplayParams
  2229. {
  2230. int nResourceID;
  2231. bool fShowToolbar;
  2232. } aDisplayParams[eMode_Count] =
  2233. {
  2234. { IDR_AMCTYPE, true }, // eMode_Author
  2235. { IDR_AMCTYPE_USER, false }, // eMode_User
  2236. { IDR_AMCTYPE_MDI_USER, false }, // eMode_User_MDI
  2237. { IDR_AMCTYPE_SDI_USER, false }, // eMode_User_SDI
  2238. };
  2239. if (m_fAuthorModeForced)
  2240. {
  2241. ASSERT (m_eMode == eMode_Author);
  2242. ASSERT (GetMainFrame()->IsMenuVisible ());
  2243. return;
  2244. }
  2245. m_Menu.DestroyMenu ();
  2246. m_Accel.DestroyAcceleratorTable ();
  2247. VERIFY (m_Menu.LoadMenu (aDisplayParams[m_eMode].nResourceID));
  2248. m_Accel.LoadAccelerators (aDisplayParams[m_eMode].nResourceID);
  2249. if (bUpdate)
  2250. {
  2251. CMainFrame *pMainFrame = GetMainFrame();
  2252. ASSERT (pMainFrame != NULL);
  2253. ASSERT_VALID (pMainFrame);
  2254. CMDIChildWnd* pwndActive = pMainFrame ? pMainFrame->MDIGetActive () : NULL;
  2255. // bypass CMainFrame::OnUpdateFrameMenu so CMainFrame::NotifyMenuChanged
  2256. // doesn't get called twice and remove the new menu entirely
  2257. if (pwndActive != NULL)
  2258. pwndActive->OnUpdateFrameMenu (TRUE, pwndActive, m_Menu);
  2259. else if (pMainFrame)
  2260. pMainFrame->OnUpdateFrameMenu (m_Menu);
  2261. if (m_eMode == eMode_User_SDI)
  2262. {
  2263. if (pwndActive != NULL)
  2264. pwndActive->MDIMaximize ();
  2265. if (pMainFrame)
  2266. AppendToSystemMenu (pMainFrame, eMode_User_SDI);
  2267. }
  2268. if (pMainFrame)
  2269. pMainFrame->ShowMenu (true /*Always show menu*/);
  2270. }
  2271. }
  2272. /*+-------------------------------------------------------------------------*
  2273. * IsInContainer
  2274. *
  2275. *
  2276. *--------------------------------------------------------------------------*/
  2277. template<class InputIterator, class T>
  2278. bool Find (InputIterator itFirst, InputIterator itLast, const T& t)
  2279. {
  2280. return (std::find (itFirst, itLast, t) != itLast);
  2281. }
  2282. /*+-------------------------------------------------------------------------*
  2283. * CAMCApp::HookPreTranslateMessage
  2284. *
  2285. * Adds a window the the list of windows that get prioritized cracks at
  2286. * PreTranslateMessage. Hooks set later get priority over earlier hooks.
  2287. *--------------------------------------------------------------------------*/
  2288. void CAMCApp::HookPreTranslateMessage (CWnd* pwndHook)
  2289. {
  2290. HWND hwndHook = pwndHook->GetSafeHwnd();
  2291. ASSERT (IsWindow (hwndHook));
  2292. // this only makes sense for permanent windows
  2293. ASSERT (CWnd::FromHandlePermanent(hwndHook) == pwndHook);
  2294. /*
  2295. * Put the hook window at the front of the hook list. We're preserving
  2296. * the HWND instead of the CWnd* so we don't have unnecessary list<>
  2297. * code generated. We already use a list<HWND> for m_DelayedUpdateWindows,
  2298. * so using list<HWND> here doesn't cause any more code to be generated.
  2299. */
  2300. if (!Find (m_TranslateMessageHookWindows.begin(),
  2301. m_TranslateMessageHookWindows.end(),
  2302. hwndHook))
  2303. {
  2304. m_TranslateMessageHookWindows.push_front (hwndHook);
  2305. }
  2306. }
  2307. /*+-------------------------------------------------------------------------*
  2308. * CAMCApp::UnhookPreTranslateMessage
  2309. *
  2310. *
  2311. *--------------------------------------------------------------------------*/
  2312. void CAMCApp::UnhookPreTranslateMessage (CWnd* pwndUnhook)
  2313. {
  2314. HWND hwndUnhook = pwndUnhook->GetSafeHwnd();
  2315. ASSERT (IsWindow (hwndUnhook));
  2316. WindowListIterator itEnd = m_TranslateMessageHookWindows.end();
  2317. WindowListIterator itFound = std::find (m_TranslateMessageHookWindows.begin(),
  2318. itEnd, hwndUnhook);
  2319. if (itFound != itEnd)
  2320. m_TranslateMessageHookWindows.erase (itFound);
  2321. }
  2322. /*+-------------------------------------------------------------------------*
  2323. * CAMCApp::GetIdleTaskQueue
  2324. *
  2325. * Returns the IIdleTaskQueue interface for the application, creating it
  2326. * if necessary.
  2327. *--------------------------------------------------------------------------*/
  2328. CIdleTaskQueue * CAMCApp::GetIdleTaskQueue ()
  2329. {
  2330. return &m_IdleTaskQueue;
  2331. }
  2332. /*+-------------------------------------------------------------------------*
  2333. * ScExpandEnvironmentStrings
  2334. *
  2335. * Expands the any environment string (e.g. %SystemRoot%) in the input
  2336. * string, in place.
  2337. *--------------------------------------------------------------------------*/
  2338. SC ScExpandEnvironmentStrings (CString& str)
  2339. {
  2340. DECLARE_SC (sc, _T("ScExpandEnvironmentStrings"));
  2341. if (str.Find(_T('%')) != -1)
  2342. {
  2343. TCHAR szBuffer[MAX_PATH];
  2344. if (!ExpandEnvironmentStrings (str, szBuffer, countof(szBuffer)))
  2345. return (sc.FromLastError());
  2346. str = szBuffer;
  2347. }
  2348. return (sc);
  2349. }
  2350. /*+-------------------------------------------------------------------------*
  2351. * ScCreateDumpSnapins
  2352. *
  2353. * Creates a CLSID_MMCDocConfig object, opens it on the supplied filename,
  2354. * and returns a pointer to the IDumpSnapins interface on the object.
  2355. *--------------------------------------------------------------------------*/
  2356. SC ScCreateDumpSnapins (
  2357. CString& strConsoleFile, /* I/O:console file */
  2358. IDumpSnapins** ppDumpSnapins) /* O:IDumpSnapins interface */
  2359. {
  2360. DECLARE_SC (sc, _T("ScCreateDumpSnapins"));
  2361. /*
  2362. * validate input
  2363. */
  2364. sc = ScCheckPointers (ppDumpSnapins);
  2365. if (sc)
  2366. return (sc);
  2367. *ppDumpSnapins = NULL;
  2368. /*
  2369. * create a doc config object
  2370. */
  2371. IDocConfigPtr spDocConfig;
  2372. sc = spDocConfig.CreateInstance (CLSID_MMCDocConfig);
  2373. if (sc)
  2374. return (sc);
  2375. /*
  2376. * expand any embedded environment strings in the console filename
  2377. */
  2378. sc = ScExpandEnvironmentStrings (strConsoleFile);
  2379. if (sc)
  2380. return (sc);
  2381. /*
  2382. * open the console file
  2383. */
  2384. sc = spDocConfig->OpenFile (::ATL::CComBSTR (strConsoleFile));
  2385. if (sc)
  2386. return (sc);
  2387. /*
  2388. * get the IDumpSnapins interface
  2389. */
  2390. sc = spDocConfig.QueryInterface (IID_IDumpSnapins, *ppDumpSnapins);
  2391. if (sc)
  2392. return (sc);
  2393. return (sc);
  2394. }
  2395. /*+-------------------------------------------------------------------------*
  2396. * CAMCApp::DumpConsoleFile
  2397. *
  2398. *
  2399. *--------------------------------------------------------------------------*/
  2400. HRESULT CAMCApp::DumpConsoleFile (CString strConsoleFile, CString strDumpFile)
  2401. {
  2402. DECLARE_SC (sc, _T("CAMCApp::DumpConsoleFile"));
  2403. const CString* pstrFileWithError = &strConsoleFile;
  2404. /*
  2405. * get an IDumpSnapins interface on this console file
  2406. */
  2407. IDumpSnapinsPtr spDumpSnapins;
  2408. sc = ScCreateDumpSnapins (strConsoleFile, &spDumpSnapins);
  2409. if (sc)
  2410. goto Error;
  2411. sc = ScCheckPointers (spDumpSnapins, E_UNEXPECTED);
  2412. if (sc)
  2413. goto Error;
  2414. /*
  2415. * expand the dump filename if necessary
  2416. */
  2417. sc = ScExpandEnvironmentStrings (strDumpFile);
  2418. if (sc)
  2419. goto Error;
  2420. /*
  2421. * If there's no directory specifier on the dump file, put a "current
  2422. * directory" marker on it. We do this to prevent WritePrivateProfile*
  2423. * from putting the file in the Windows directory.
  2424. */
  2425. if (strDumpFile.FindOneOf(_T(":\\")) == -1)
  2426. strDumpFile = _T(".\\") + strDumpFile;
  2427. /*
  2428. * future file-related errors will pertain to the dump file
  2429. * (see Error handler)
  2430. */
  2431. pstrFileWithError = &strDumpFile;
  2432. /*
  2433. * wipe out the existing file, if any
  2434. */
  2435. if ((GetFileAttributes (strDumpFile) != 0xFFFFFFFF) && !DeleteFile (strDumpFile))
  2436. {
  2437. sc.FromLastError();
  2438. goto Error;
  2439. }
  2440. /*
  2441. * dump the contents of the console file
  2442. */
  2443. sc = spDumpSnapins->Dump (strDumpFile);
  2444. if (sc)
  2445. goto Error;
  2446. return (sc.ToHr());
  2447. Error:
  2448. MMCErrorBox (*pstrFileWithError, sc);
  2449. return (sc.ToHr());
  2450. }
  2451. /***************************************************************************\
  2452. *
  2453. * METHOD: CAMCApp::ScOnNewDocument
  2454. *
  2455. * PURPOSE: Emits script event for application object
  2456. *
  2457. * PARAMETERS:
  2458. * CAMCDoc *pDocument [in] document being created/opened
  2459. * BOOL bLoadedFromConsole [in] if document is loaded from file
  2460. *
  2461. * RETURNS:
  2462. * SC - result code
  2463. *
  2464. \***************************************************************************/
  2465. SC CAMCApp::ScOnNewDocument(CAMCDoc *pDocument, BOOL bLoadedFromConsole)
  2466. {
  2467. DECLARE_SC(sc, TEXT("CAMCApp::ScOnNewDocument"));
  2468. // check if there are "listeners"
  2469. sc = ScHasSinks(m_sp_Application, AppEvents);
  2470. if (sc)
  2471. return sc;
  2472. if (sc == SC(S_FALSE)) // no sinks;
  2473. return sc;
  2474. // construct document com object
  2475. DocumentPtr spComDoc;
  2476. sc = pDocument->ScGetMMCDocument(&spComDoc);
  2477. if (sc)
  2478. return sc;
  2479. // check pointer
  2480. sc = ScCheckPointers(spComDoc, E_POINTER);
  2481. if (sc)
  2482. return sc;
  2483. // fire the event
  2484. sc = ScFireComEvent(m_sp_Application, AppEvents , OnDocumentOpen (spComDoc , bLoadedFromConsole == FALSE));
  2485. if (sc)
  2486. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2487. return sc;
  2488. }
  2489. /***************************************************************************\
  2490. *
  2491. * METHOD: CAMCApp::ScOnQuitApp
  2492. *
  2493. * PURPOSE: Emits script event for application object
  2494. *
  2495. * PARAMETERS:
  2496. *
  2497. * RETURNS:
  2498. * SC - result code
  2499. *
  2500. \***************************************************************************/
  2501. SC CAMCApp::ScOnQuitApp()
  2502. {
  2503. DECLARE_SC(sc, TEXT("CAMCApp::ScOnQuitApp"));
  2504. // fire the event
  2505. sc = ScFireComEvent(m_sp_Application, AppEvents , OnQuit (m_sp_Application));
  2506. if (sc)
  2507. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2508. return sc;
  2509. }
  2510. /***************************************************************************\
  2511. *
  2512. * METHOD: CAMCApp::ScOnCloseView
  2513. *
  2514. * PURPOSE: Script event firing helper. Invoked when the view is closed
  2515. *
  2516. * PARAMETERS:
  2517. * CAMCView *pView [in] - view being closed
  2518. *
  2519. * RETURNS:
  2520. * SC - result code
  2521. *
  2522. \***************************************************************************/
  2523. SC CAMCApp::ScOnCloseView( CAMCView *pView )
  2524. {
  2525. DECLARE_SC(sc, TEXT("CAMCApp::ScOnCloseView"));
  2526. // parameter check
  2527. sc = ScCheckPointers(pView);
  2528. if (sc)
  2529. return sc;
  2530. // check if we have sinks connected
  2531. sc = ScHasSinks(m_sp_Application, AppEvents);
  2532. if (sc)
  2533. return sc;
  2534. if (sc == SC(S_FALSE)) // no sinks
  2535. return sc;
  2536. // construct view com object
  2537. ViewPtr spView;
  2538. sc = pView->ScGetMMCView(&spView);
  2539. if (sc)
  2540. return sc;
  2541. // fire the event
  2542. sc = ScFireComEvent(m_sp_Application, AppEvents , OnViewClose (spView));
  2543. if (sc)
  2544. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2545. return sc;
  2546. }
  2547. /***************************************************************************\
  2548. *
  2549. * METHOD: CAMCApp::ScOnViewChange
  2550. *
  2551. * PURPOSE: Script event firing helper. Invoked when scope selection change
  2552. *
  2553. * PARAMETERS:
  2554. * CAMCView *pView [in] affected view
  2555. * HNODE hNode [in] new selected scope node
  2556. *
  2557. * RETURNS:
  2558. * SC - result code
  2559. *
  2560. \***************************************************************************/
  2561. SC CAMCApp::ScOnViewChange( CAMCView *pView, HNODE hNode )
  2562. {
  2563. DECLARE_SC(sc, TEXT("CAMCApp::ScOnViewChange"));
  2564. // parameter check
  2565. sc = ScCheckPointers(pView);
  2566. if (sc)
  2567. return sc;
  2568. // check if we have sinks connected
  2569. sc = ScHasSinks(m_sp_Application, AppEvents);
  2570. if (sc)
  2571. return sc;
  2572. if (sc == SC(S_FALSE)) // no sinks
  2573. return sc;
  2574. // construct view com object
  2575. ViewPtr spView;
  2576. sc = pView->ScGetMMCView(&spView);
  2577. if (sc)
  2578. return sc;
  2579. // construct Node com object
  2580. NodePtr spNode;
  2581. sc = pView->ScGetScopeNode( hNode, &spNode );
  2582. if (sc)
  2583. return sc;
  2584. // fire script event
  2585. sc = ScFireComEvent(m_sp_Application, AppEvents , OnViewChange(spView, spNode));
  2586. if (sc)
  2587. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2588. return sc;
  2589. }
  2590. /***************************************************************************\
  2591. *
  2592. * METHOD: CAMCApp::ScOnResultSelectionChange
  2593. *
  2594. * PURPOSE: Script event firing helper. Invoked when result selection change
  2595. *
  2596. * PARAMETERS:
  2597. * CAMCView *pView [in] - affected view
  2598. *
  2599. * RETURNS:
  2600. * SC - result code
  2601. *
  2602. \***************************************************************************/
  2603. SC CAMCApp::ScOnResultSelectionChange( CAMCView *pView )
  2604. {
  2605. DECLARE_SC(sc, TEXT("CAMCApp::ScOnResultSelectionChange"));
  2606. // parameter check
  2607. sc = ScCheckPointers(pView);
  2608. if (sc)
  2609. return sc;
  2610. // check if we have sinks connected
  2611. sc = ScHasSinks(m_sp_Application, AppEvents);
  2612. if (sc)
  2613. return sc;
  2614. if (sc == SC(S_FALSE)) // no sinks
  2615. return sc;
  2616. // construct view com object
  2617. ViewPtr spView;
  2618. sc = pView->ScGetMMCView(&spView);
  2619. if (sc)
  2620. return sc;
  2621. // construct Node com object
  2622. NodesPtr spNodes;
  2623. sc = pView->Scget_Selection( &spNodes );
  2624. if (sc)
  2625. return sc;
  2626. // fire script event
  2627. sc = ScFireComEvent(m_sp_Application, AppEvents , OnSelectionChange(spView, spNodes));
  2628. if (sc)
  2629. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2630. return sc;
  2631. }
  2632. /***************************************************************************\
  2633. *
  2634. * METHOD: CMMCApplication::ScOnContextMenuExecuted
  2635. *
  2636. * PURPOSE: called when the context menu is executed to fire the event to script
  2637. *
  2638. * PARAMETERS:
  2639. * PMENUITEM pMenuItem - menu item (note: it may be NULL if menu item is gone)
  2640. *
  2641. * RETURNS:
  2642. * SC - result code
  2643. *
  2644. \***************************************************************************/
  2645. SC CAMCApp::ScOnContextMenuExecuted( PMENUITEM pMenuItem )
  2646. {
  2647. MMC_COM_MANAGE_STATE();
  2648. DECLARE_SC(sc, TEXT("CAMCApp::ScOnContextMenuExecuted"));
  2649. // see if we have sinks connected
  2650. sc = ScHasSinks(m_sp_Application, AppEvents);
  2651. if (sc)
  2652. return sc;
  2653. if (sc == SC(S_FALSE)) // no sinks
  2654. return sc;
  2655. // fire the event
  2656. sc = ScFireComEvent(m_sp_Application, AppEvents, OnContextMenuExecuted( pMenuItem ) );
  2657. if (sc)
  2658. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2659. return sc;
  2660. }
  2661. /*+-------------------------------------------------------------------------*
  2662. *
  2663. * CAMCApp::ScOnListViewItemUpdated
  2664. *
  2665. * PURPOSE:
  2666. *
  2667. * PARAMETERS:
  2668. * CAMCView * pView :
  2669. * int nIndex :
  2670. *
  2671. * RETURNS:
  2672. * SC
  2673. *
  2674. *+-------------------------------------------------------------------------*/
  2675. SC
  2676. CAMCApp::ScOnListViewItemUpdated(CAMCView *pView , int nIndex)
  2677. {
  2678. DECLARE_SC(sc, TEXT("CAMCApp::ScOnListViewItemUpdated"));
  2679. // parameter check
  2680. sc = ScCheckPointers(pView);
  2681. if (sc)
  2682. return sc;
  2683. // check if we have sinks connected
  2684. sc = ScHasSinks(m_sp_Application, AppEvents);
  2685. if (sc)
  2686. return sc;
  2687. if (sc == SC(S_FALSE)) // no sinks
  2688. return sc;
  2689. // construct view com object
  2690. ViewPtr spView;
  2691. sc = pView->ScGetMMCView(&spView);
  2692. if (sc)
  2693. return sc;
  2694. // fire script event
  2695. sc = ScFireComEvent(m_sp_Application, AppEvents , OnListUpdated(spView));
  2696. if (sc)
  2697. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2698. return sc;
  2699. }
  2700. /***************************************************************************\
  2701. *
  2702. * METHOD: CAMCApp::ScOnSnapinAdded
  2703. *
  2704. * PURPOSE: Script event firing helper. Implements interface accessible from
  2705. * node manager
  2706. *
  2707. * PARAMETERS:
  2708. * PSNAPIN pSnapIn [in] - snapin added to the console
  2709. *
  2710. * RETURNS:
  2711. * SC - result code
  2712. *
  2713. \***************************************************************************/
  2714. SC CAMCApp::ScOnSnapinAdded(CAMCDoc *pAMCDoc, PSNAPIN pSnapIn)
  2715. {
  2716. DECLARE_SC(sc, TEXT("CAMCApp::ScOnSnapinAdded"));
  2717. // parameter check
  2718. sc = ScCheckPointers(pAMCDoc, pSnapIn);
  2719. if (sc)
  2720. return sc;
  2721. // see if we have sinks connected
  2722. sc = ScHasSinks(m_sp_Application, AppEvents);
  2723. if (sc)
  2724. return sc;
  2725. if (sc == SC(S_FALSE)) // no sinks
  2726. return sc;
  2727. DocumentPtr spDocument;
  2728. sc = pAMCDoc->ScGetMMCDocument(&spDocument);
  2729. if (sc)
  2730. return sc;
  2731. // check
  2732. sc = ScCheckPointers(spDocument, E_UNEXPECTED);
  2733. if (sc)
  2734. return sc;
  2735. // fire the event
  2736. sc = ScFireComEvent(m_sp_Application, AppEvents , OnSnapInAdded (spDocument, pSnapIn));
  2737. if (sc)
  2738. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2739. return sc;
  2740. }
  2741. /***************************************************************************\
  2742. *
  2743. * METHOD: CAMCApp::ScOnSnapinRemoved
  2744. *
  2745. * PURPOSE: Script event firing helper. Implements interface accessible from
  2746. * node manager
  2747. *
  2748. * PARAMETERS:
  2749. * PSNAPIN pSnapIn [in] - snapin removed from console
  2750. *
  2751. * RETURNS:
  2752. * SC - result code
  2753. *
  2754. \***************************************************************************/
  2755. SC CAMCApp::ScOnSnapinRemoved(CAMCDoc *pAMCDoc, PSNAPIN pSnapIn)
  2756. {
  2757. DECLARE_SC(sc, TEXT("CAMCApp::ScOnSnapinRemoved"));
  2758. // parameter check
  2759. sc = ScCheckPointers(pAMCDoc, pSnapIn);
  2760. if (sc)
  2761. return sc;
  2762. // see if we have sinks connected
  2763. sc = ScHasSinks(m_sp_Application, AppEvents);
  2764. if (sc)
  2765. return sc;
  2766. if (sc == SC(S_FALSE)) // no sinks
  2767. return sc;
  2768. DocumentPtr spDocument;
  2769. sc = pAMCDoc->ScGetMMCDocument(&spDocument);
  2770. if (sc)
  2771. return sc;
  2772. // check
  2773. sc = ScCheckPointers(spDocument, E_UNEXPECTED);
  2774. if (sc)
  2775. return sc;
  2776. // fire the event
  2777. sc = ScFireComEvent(m_sp_Application, AppEvents , OnSnapInRemoved (spDocument, pSnapIn));
  2778. if (sc)
  2779. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2780. return sc;
  2781. }
  2782. /***************************************************************************\
  2783. *
  2784. * METHOD: CAMCApp::ScOnNewView
  2785. *
  2786. * PURPOSE: Script event firing helper
  2787. *
  2788. * PARAMETERS:
  2789. * CAMCView *pView [in] - created view
  2790. *
  2791. * RETURNS:
  2792. * SC - result code
  2793. *
  2794. \***************************************************************************/
  2795. SC CAMCApp::ScOnNewView(CAMCView *pView)
  2796. {
  2797. DECLARE_SC(sc, TEXT("CAMCApp::ScOnNewView"));
  2798. // parameter check
  2799. sc = ScCheckPointers(pView);
  2800. if (sc)
  2801. return sc;
  2802. // see if we have sinks connected
  2803. sc = ScHasSinks(m_sp_Application, AppEvents);
  2804. if (sc)
  2805. return sc;
  2806. if (sc == SC(S_FALSE)) // no sinks
  2807. return sc;
  2808. // construct View com object
  2809. ViewPtr spView;
  2810. sc = pView->ScGetMMCView(&spView);
  2811. if (sc)
  2812. return sc;
  2813. // fire the event
  2814. sc = ScFireComEvent(m_sp_Application, AppEvents , OnNewView(spView));
  2815. if (sc)
  2816. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2817. return sc;
  2818. }
  2819. /***************************************************************************\
  2820. *
  2821. * METHOD: CAMCApp::OnCloseDocument
  2822. *
  2823. * PURPOSE: Helper for invoking com event
  2824. *
  2825. * PARAMETERS:
  2826. * CAMCDoc *pAMCDoc [in] - document being closed
  2827. *
  2828. * RETURNS:
  2829. * SC - result code
  2830. *
  2831. \***************************************************************************/
  2832. SC CAMCApp::ScOnCloseDocument(CAMCDoc *pAMCDoc)
  2833. {
  2834. DECLARE_SC(sc, TEXT("CAMCApp::OnCloseDocument"));
  2835. // parameter check
  2836. sc = ScCheckPointers(pAMCDoc);
  2837. if (sc)
  2838. return sc;
  2839. // see if we have sinks connected
  2840. sc = ScHasSinks(m_sp_Application, AppEvents);
  2841. if (sc)
  2842. return sc;
  2843. if (sc == SC(S_FALSE)) // no sinks
  2844. return sc;
  2845. DocumentPtr spDocument;
  2846. sc = pAMCDoc->ScGetMMCDocument(&spDocument);
  2847. if (sc)
  2848. return sc;
  2849. // check
  2850. sc = ScCheckPointers(spDocument, E_UNEXPECTED);
  2851. if (sc)
  2852. return sc;
  2853. // fire the event
  2854. sc = ScFireComEvent(m_sp_Application, AppEvents , OnDocumentClose (spDocument));
  2855. if (sc)
  2856. sc.TraceAndClear(); // failure to issue the com event is not critical to this action
  2857. return sc;
  2858. }
  2859. /***************************************************************************\
  2860. *
  2861. * METHOD: CAMCApp::ScOnToolbarButtonClicked
  2862. *
  2863. * PURPOSE: Observed toolbar event - used to fire com event
  2864. *
  2865. * PARAMETERS:
  2866. * CAMCView *pAMCView - [in] view which toobar is executed
  2867. *
  2868. * RETURNS:
  2869. * SC - result code
  2870. *
  2871. \***************************************************************************/
  2872. SC CAMCApp::ScOnToolbarButtonClicked( )
  2873. {
  2874. DECLARE_SC(sc, TEXT("CAMCApp::ScOnToolbarButtonClicked"));
  2875. // see if we have sinks connected
  2876. sc = ScHasSinks(m_sp_Application, AppEvents);
  2877. if (sc)
  2878. return sc;
  2879. if (sc == SC(S_FALSE)) // no sinks
  2880. return sc;
  2881. // fire the event
  2882. sc = ScFireComEvent(m_sp_Application, AppEvents , OnToolbarButtonClicked ( ));
  2883. if (sc)
  2884. sc.TraceAndClear(); // ignore the error - should not affect main behavior
  2885. return sc;
  2886. }
  2887. /***************************************************************************\
  2888. *
  2889. * METHOD: CAMCApp::SetUnderUserControl
  2890. *
  2891. * PURPOSE: puts application into user control/script control mode
  2892. * implements Application.UserControl property
  2893. *
  2894. * PARAMETERS:
  2895. * bool bUserControl [in] true == set user control
  2896. *
  2897. * RETURNS:
  2898. * void
  2899. *
  2900. \***************************************************************************/
  2901. void CAMCApp::SetUnderUserControl(bool bUserControl /* = true */ )
  2902. {
  2903. m_fUnderUserControl = bUserControl;
  2904. AfxOleSetUserCtrl(bUserControl); // allow MFC to know that
  2905. if (bUserControl)
  2906. {
  2907. // make sure application is visible if it's under user control
  2908. CMainFrame *pMainFrame = GetMainFrame();
  2909. if(pMainFrame && !pMainFrame->IsWindowVisible())
  2910. {
  2911. pMainFrame->ShowWindow(SW_SHOW);
  2912. }
  2913. }
  2914. }
  2915. #ifdef MMC_WIN64
  2916. /*+-------------------------------------------------------------------------*
  2917. * CompareBasicSnapinInfo
  2918. *
  2919. * Implements a less-than comparison for CBasicSnapinInfo, based solely on
  2920. * the CLSID. Returns true if the CLSID for bsi1 is less than the CLSID
  2921. * for bsi2, false otherwise.
  2922. *--------------------------------------------------------------------------*/
  2923. bool CompareBasicSnapinInfo (const CBasicSnapinInfo& bsi1, const CBasicSnapinInfo& bsi2)
  2924. {
  2925. return (bsi1.m_clsid < bsi2.m_clsid);
  2926. }
  2927. /*+-------------------------------------------------------------------------*
  2928. * ScDetermineArchitecture
  2929. *
  2930. * Determines whether MMC64 (which is currently executing) should chain
  2931. * to MMC32. This will occur in one of three situations:
  2932. *
  2933. * 1. The "-32" command line parameter was specified.
  2934. *
  2935. * 2. A console file was specified on the command line, and it contains
  2936. * one or more snap-ins that were not registered in the 64-bit HKCR
  2937. * hive, but all snap-ins are registered in the 32-bit HKCR hive.
  2938. *
  2939. * 3. A console file was specified on the command line, and it contained
  2940. * one or more snap-ins that were not registered in the 64-bit HKCR
  2941. * hive, and one or more snap-ins that are not registered in the 32-bit
  2942. * HKCR hive. In this case we'll do one of three things:
  2943. *
  2944. * a. If the set of unavailable 64-bit snap-ins is a subset of the
  2945. * set of unavailable 32-bit snap-ins, the 64-bit console will be
  2946. * more functional than the 32-bit console, so we'll run MMC64.
  2947. *
  2948. * b. If the set of unavailable 32-bit snap-ins is a subset of the
  2949. * set of unavailable 64-bit snap-ins, the 32-bit console will be
  2950. * more functional than the 64-bit console, so we'll run MMC32.
  2951. *
  2952. * c. If neither a. or b. is true, we'll display UI asking which
  2953. * version of MMC to run.
  2954. *
  2955. * Returns:
  2956. * eArch == eArch_64bit - 64-bit MMC is needed (or an error occurred)
  2957. * eArch == eArch_32bit - 32-bit MMC is needed
  2958. * eArch == eArch_None - user cancelled the operation
  2959. *--------------------------------------------------------------------------*/
  2960. SC ScDetermineArchitecture (const CMMCCommandLineInfo& rCmdInfo, eArchitecture& eArch)
  2961. {
  2962. DECLARE_SC (sc, _T("ScDetermineArchitecture"));
  2963. /*
  2964. * default to 64-bit
  2965. */
  2966. eArch = eArch_64bit;
  2967. /*
  2968. * Case 0: Was "-64" specified on the command line? 64-bit needed
  2969. */
  2970. if (rCmdInfo.m_eArch == eArch_64bit)
  2971. {
  2972. Trace (tag32BitTransfer, _T("\"-64\" parameter specified, 64-bit MMC needed"));
  2973. return (sc);
  2974. }
  2975. /*
  2976. * Case 1: Was "-32" specified on the command line? 32-bit needed
  2977. */
  2978. if (rCmdInfo.m_eArch == eArch_32bit)
  2979. {
  2980. Trace (tag32BitTransfer, _T("\"-32\" parameter specified, 32-bit MMC needed"));
  2981. eArch = eArch_32bit;
  2982. return (sc);
  2983. }
  2984. /*
  2985. * No file on the command line? 64-bit needed
  2986. */
  2987. if (rCmdInfo.m_nShellCommand != CCommandLineInfo::FileOpen)
  2988. {
  2989. Trace (tag32BitTransfer, _T("No console file specified, 64-bit MMC needed"));
  2990. return (sc);
  2991. }
  2992. /*
  2993. * Cases 2 and 3: Analyze the specified console file
  2994. */
  2995. Trace (tag32BitTransfer, _T("Analyzing snap-ins in \"%s\""), (LPCTSTR) rCmdInfo.m_strFileName);
  2996. /*
  2997. * get an IDumpSnapins interface so we can analyze the console file
  2998. */
  2999. IDumpSnapinsPtr spDumpSnapins;
  3000. CString strConsoleFile = rCmdInfo.m_strFileName;
  3001. sc = ScCreateDumpSnapins (strConsoleFile, &spDumpSnapins);
  3002. if (sc)
  3003. return (sc);
  3004. sc = ScCheckPointers (spDumpSnapins, E_UNEXPECTED);
  3005. if (sc)
  3006. return (sc);
  3007. /*
  3008. * analyze the 64-bit snap-ins in this console
  3009. */
  3010. CAvailableSnapinInfo asi64(false);
  3011. sc = spDumpSnapins->CheckSnapinAvailability (asi64);
  3012. if (sc)
  3013. return (sc);
  3014. /*
  3015. * if no snap-ins are unavailable in 64-bit form, no need for MMC32
  3016. */
  3017. if (asi64.m_vAvailableSnapins.size() == asi64.m_cTotalSnapins)
  3018. {
  3019. Trace (tag32BitTransfer, _T("All snapins are available in 64-bit form, 64-bit MMC needed"));
  3020. return (sc);
  3021. }
  3022. /*
  3023. * analyze the 32-bit snap-ins in this console
  3024. */
  3025. CAvailableSnapinInfo asi32(true);
  3026. sc = spDumpSnapins->CheckSnapinAvailability (asi32);
  3027. if (sc)
  3028. return (sc);
  3029. /*
  3030. * Case 2: If no snap-ins are unavailable in 32-bit form, 32-bit needed
  3031. */
  3032. if (asi32.m_vAvailableSnapins.size() == asi32.m_cTotalSnapins)
  3033. {
  3034. Trace (tag32BitTransfer, _T("All snapins are available in 32-bit form, 32-bit MMC needed"));
  3035. eArch = eArch_32bit;
  3036. return (sc);
  3037. }
  3038. /*
  3039. * std::includes depends on its ranges being sorted, so make sure
  3040. * that's the case
  3041. */
  3042. std::sort (asi32.m_vAvailableSnapins.begin(), asi32.m_vAvailableSnapins.end(), CompareBasicSnapinInfo);
  3043. std::sort (asi64.m_vAvailableSnapins.begin(), asi64.m_vAvailableSnapins.end(), CompareBasicSnapinInfo);
  3044. /*
  3045. * Case 3a: If the set of available 64-bit snap-ins is a
  3046. * superset of the set of available 32-bit snap-ins, run MMC64
  3047. */
  3048. if (std::includes (asi64.m_vAvailableSnapins.begin(), asi64.m_vAvailableSnapins.end(),
  3049. asi32.m_vAvailableSnapins.begin(), asi32.m_vAvailableSnapins.end(),
  3050. CompareBasicSnapinInfo))
  3051. {
  3052. Trace (tag32BitTransfer, _T("The set of available 64-bit snapins is a superset of..."));
  3053. Trace (tag32BitTransfer, _T("...the set of available 32-bit snapins, 64-bit MMC needed"));
  3054. return (sc);
  3055. }
  3056. /*
  3057. * Case 3b: If the set of available 32-bit snap-ins is a
  3058. * superset of the set of available 64-bit snap-ins, run MMC32
  3059. */
  3060. if (std::includes (asi32.m_vAvailableSnapins.begin(), asi32.m_vAvailableSnapins.end(),
  3061. asi64.m_vAvailableSnapins.begin(), asi64.m_vAvailableSnapins.end(),
  3062. CompareBasicSnapinInfo))
  3063. {
  3064. Trace (tag32BitTransfer, _T("The set of available 32-bit snapins is a superset of..."));
  3065. Trace (tag32BitTransfer, _T("...the set of available 64-bit snapins, 32-bit MMC needed"));
  3066. eArch = eArch_32bit;
  3067. return (sc);
  3068. }
  3069. /*
  3070. * Case 3c: Ask the user which to run
  3071. */
  3072. CArchitecturePicker dlg (rCmdInfo.m_strFileName, asi64, asi32);
  3073. if (dlg.DoModal() == IDOK)
  3074. {
  3075. eArch = dlg.GetArchitecture();
  3076. Trace (tag32BitTransfer, _T("User chose %d-bit, %d-bit MMC needed"), (eArch == eArch_32bit) ? 32 : 64, (eArch == eArch_32bit) ? 32 : 64);
  3077. }
  3078. else
  3079. {
  3080. Trace (tag32BitTransfer, _T("User chose to exit, terminating"));
  3081. eArch = eArch_None;
  3082. }
  3083. return (sc);
  3084. }
  3085. #endif // MMC_WIN64
  3086. #ifdef UNICODE
  3087. /*+-------------------------------------------------------------------------*
  3088. * ScLaunchMMC
  3089. *
  3090. * Launches a specific architecture of MMC (i.e. MMC32 from MMC64 or vice
  3091. * versa) with the same command line used to launch this process.
  3092. *
  3093. * Returns S_OK if the given architecture of MMC was launched successfully,
  3094. * or an error code if an error occurred.
  3095. *--------------------------------------------------------------------------*/
  3096. SC ScLaunchMMC (
  3097. eArchitecture eArch, /* I:desired architecture */
  3098. int nCmdShow) /* I:show state */
  3099. {
  3100. DECLARE_SC (sc, _T("ScLaunchMMC"));
  3101. CString strArgs;
  3102. int nFolder;
  3103. switch (eArch)
  3104. {
  3105. case eArch_64bit:
  3106. nFolder = CSIDL_SYSTEM;
  3107. break;
  3108. case eArch_32bit:
  3109. /*
  3110. * make sure we give MMC32 a "-32" argument so it won't defer
  3111. * to MMC64 again (see CAMCApp::InitInstance)
  3112. */
  3113. strArgs = _T("-32 ");
  3114. nFolder = CSIDL_SYSTEMX86;
  3115. break;
  3116. default:
  3117. return (sc = E_INVALIDARG);
  3118. break;
  3119. }
  3120. /*
  3121. * Get the directory where MMC32 lives (%SystemRoot%\syswow64) and
  3122. * append the executable name
  3123. */
  3124. CString strProgram, strPath;
  3125. sc = SHGetFolderPath (NULL, nFolder, NULL, 0, strProgram.GetBuffer(MAX_PATH));
  3126. if (sc)
  3127. return (sc);
  3128. strProgram.ReleaseBuffer();
  3129. strPath = strProgram;
  3130. strProgram += _T("\\mmc.exe");
  3131. /*
  3132. * disable file system redirection so MMC32 will be able to launch MMC64
  3133. */
  3134. CWow64FilesystemRedirectionDisabler disabler (strProgram);
  3135. /*
  3136. * get the arguments for the original invocation of MMC, skipping
  3137. * argv[0] (the executable name) and any "-32" or "-64" parameters
  3138. */
  3139. int argc;
  3140. CAutoGlobalPtr<LPWSTR> argv (CommandLineToArgvW (GetCommandLine(), &argc));
  3141. if (argv == NULL)
  3142. return (sc.FromLastError());
  3143. for (int i = 1; i < argc; i++)
  3144. {
  3145. CString strArg = argv[i];
  3146. if ((strArg != _T("-32")) && (strArg != _T("/32")) &&
  3147. (strArg != _T("-64")) && (strArg != _T("/64")))
  3148. {
  3149. strArgs += _T("\"") + strArg + _T("\" ");
  3150. }
  3151. }
  3152. /*
  3153. * start the requested architecture of MMC
  3154. */
  3155. Trace (tag32BitTransfer, _T("Attempting to run: %s %s"), (LPCTSTR) strProgram, (LPCTSTR) strArgs);
  3156. SHELLEXECUTEINFO sei = {0};
  3157. sei.cbSize = sizeof (sei);
  3158. sei.fMask = SEE_MASK_FLAG_NO_UI;
  3159. sei.lpFile = strProgram;
  3160. sei.lpDirectory = strPath;
  3161. sei.lpParameters = strArgs;
  3162. sei.nShow = nCmdShow;
  3163. if (!ShellExecuteEx (&sei))
  3164. return (sc.FromLastError());
  3165. return (sc);
  3166. }
  3167. #endif // UNICODE
  3168. #ifndef MMC_WIN64
  3169. /*+-------------------------------------------------------------------------*
  3170. * IsWin64
  3171. *
  3172. * Returns true if we're running on Win64, false otherwise.
  3173. *--------------------------------------------------------------------------*/
  3174. bool IsWin64()
  3175. {
  3176. #ifdef UNICODE
  3177. /*
  3178. * get a pointer to kernel32!GetSystemWow64Directory
  3179. */
  3180. HMODULE hmod = GetModuleHandle (_T("kernel32.dll"));
  3181. if (hmod == NULL)
  3182. return (false);
  3183. UINT (WINAPI* pfnGetSystemWow64Directory)(LPTSTR, UINT);
  3184. (FARPROC&)pfnGetSystemWow64Directory = GetProcAddress (hmod, "GetSystemWow64DirectoryW");
  3185. if (pfnGetSystemWow64Directory == NULL)
  3186. return (false);
  3187. /*
  3188. * if GetSystemWow64Directory fails and sets the last error to
  3189. * ERROR_CALL_NOT_IMPLEMENTED, we're on a 32-bit OS
  3190. */
  3191. TCHAR szWow64Dir[MAX_PATH];
  3192. if (((pfnGetSystemWow64Directory)(szWow64Dir, countof(szWow64Dir)) == 0) &&
  3193. (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
  3194. {
  3195. return (false);
  3196. }
  3197. /*
  3198. * if we get here, we're on Win64
  3199. */
  3200. return (true);
  3201. #else
  3202. /*
  3203. * non-Unicode platforms cannot be Win64
  3204. */
  3205. return (false);
  3206. #endif // UNICODE
  3207. }
  3208. #endif // !MMC_WIN64