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

2351 lines
62 KiB

  1. /* CompData.cpp : Implementation of the ComponentData (namespace items) for
  2. * the MSInfo Snapin.
  3. *
  4. * Copyright (c) 1998-1999 Microsoft Corporation
  5. *
  6. * History: a-jsari 8/27/97 Initial version
  7. */
  8. #include "StdAfx.h"
  9. #include <Commdlg.h>
  10. #include <iostream.h>
  11. #include <atlbase.h>
  12. #include <htmlhelp.h>
  13. #ifndef IDB_16x16
  14. #include "Resource.h"
  15. #endif // IDB_16x16
  16. #include "resrc1.h"
  17. #include "DataObj.h"
  18. #include "CompData.h"
  19. #include "DataSrc.h"
  20. #include "SysInfo.h"
  21. #include "ViewObj.h"
  22. #include "Dialogs.h"
  23. #include "chooser.h"
  24. static LPCTSTR cszViewKey = _T("Software\\Microsoft\\MSInfo");
  25. static LPCTSTR cszViewValue = _T("View");
  26. static LPCTSTR cszBasicValue = _T("basic");
  27. static LPCTSTR cszAdvancedValue = _T("advanced");
  28. /*
  29. * CSystemInfoScope - Trivial constructor. Make sure all of our
  30. * essential pointers start NULL.
  31. *
  32. * History: a-jsari 8/27/97 Initial version
  33. */
  34. CSystemInfoScope::CSystemInfoScope()
  35. :m_pScope(NULL),
  36. m_pConsole(NULL),
  37. m_pSource(NULL),
  38. m_bIsDirty(FALSE),
  39. m_bInitializedCD(FALSE),
  40. m_fViewUninitialized(FALSE),
  41. m_prdSave(NULL),
  42. m_prdOpen(NULL),
  43. m_prdReport(NULL),
  44. m_pthdFind(NULL),
  45. m_BasicFlags(0L),
  46. m_AdvancedFlags(MF_CHECKED),
  47. m_pwConsole(NULL),
  48. m_pmapCategories(NULL),
  49. m_pstrMachineName(new CString),
  50. m_pstrOverrideName(new CString),
  51. m_pstrCategory(NULL),
  52. m_RootCookie(0),
  53. m_fSelectCategory(FALSE),
  54. m_pSetSourceSource(NULL),
  55. m_fSetSourcePreLaunch(FALSE),
  56. m_pViewCABTool(NULL),
  57. m_pSaveUnknown(NULL),
  58. m_fInternalDelete(FALSE),
  59. m_pLastSystemInfo(NULL)
  60. {
  61. #ifdef _DEBUG
  62. m_bDestroyedCD = true;
  63. #endif // _DEBUG
  64. }
  65. /*
  66. * ~CSystemInfoScope - Never called. Don't use.
  67. *
  68. * History: a-jsari 8/27/97 Initial version
  69. */
  70. CSystemInfoScope::~CSystemInfoScope()
  71. {
  72. #ifdef _DEBUG
  73. if (m_bInitializedCD)
  74. ASSERT(m_pScope == NULL);
  75. ASSERT(m_pConsole == NULL);
  76. ASSERT(m_bDestroyedCD);
  77. #endif
  78. }
  79. /*
  80. * InitializeDialogs - Pre-create our Dialog pointers to speed their loading when
  81. * they are needed.
  82. *
  83. * History: a-jsari 11/28/97 Moved from Initialize
  84. */
  85. inline HRESULT CSystemInfoScope::InitializeDialogs()
  86. {
  87. HWND hWindow;
  88. ASSERT(m_pConsole != NULL);
  89. HRESULT hr = m_pConsole->GetMainWindow(&hWindow);
  90. ASSERT(hr == S_OK);
  91. if (FAILED(hr))
  92. return hr;
  93. ASSERT(m_prdReport == NULL);
  94. m_prdReport = new CMSInfoReportDialog(hWindow);
  95. ASSERT(m_prdReport != NULL);
  96. if (m_prdReport == NULL) ::AfxThrowMemoryException();
  97. m_prdSave = new CMSInfoSaveDialog(hWindow);
  98. ASSERT(m_prdSave != NULL);
  99. if (m_prdSave == NULL) ::AfxThrowMemoryException();
  100. m_prdOpen = new CMSInfoOpenDialog(hWindow);
  101. ASSERT(m_prdOpen != NULL);
  102. if (m_prdOpen == NULL) ::AfxThrowMemoryException();
  103. return hr;
  104. }
  105. /*
  106. * FindWindowProc - The window proc for the hidden window that will allow us to
  107. * call find from the Find Dialog Thread.
  108. *
  109. * History: a-jsari 2/6/98 Initial version
  110. */
  111. static LRESULT CALLBACK FindWindowProc(HWND, UINT uMsg, WPARAM wParam, LPARAM lParam)
  112. {
  113. // ASSERT(uMsg == CFindDialog::WM_MSINFO_FIND);
  114. // Only process our specific message.
  115. if (uMsg == CFindDialog::WM_MSINFO_FIND)
  116. reinterpret_cast<CSystemInfoScope *>(wParam)->ExecuteFind((long)lParam);
  117. return 1;
  118. }
  119. /*
  120. * InitializeInternal - Because MMC never calls our destructor, we are leaking
  121. * memory in our member classes. To fix this, allocate them on the heap
  122. * and delete them in our Destroy method.
  123. *
  124. * History: a-jsari 12/30/97 Initial version
  125. */
  126. inline HRESULT CSystemInfoScope::InitializeInternal()
  127. {
  128. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  129. m_pmapCategories = new CScopeItemMap;
  130. ASSERT(m_pmapCategories != NULL);
  131. if (m_pmapCategories == NULL) ::AfxThrowMemoryException();
  132. CString strClassName;
  133. CString strWindowName;
  134. HWND hwndParent;
  135. CREATESTRUCT csFind;
  136. VERIFY(strClassName.LoadString(IDS_FINDCLASS));
  137. VERIFY(strWindowName.LoadString(IDS_FINDWINDOWNAME));
  138. WNDCLASSEX wceFind;
  139. ::memset(&wceFind, 0, sizeof(wceFind));
  140. wceFind.cbSize = sizeof(wceFind);
  141. wceFind.style = CS_CLASSDC;
  142. wceFind.lpfnWndProc = FindWindowProc;
  143. wceFind.hInstance = ::AfxGetInstanceHandle();
  144. wceFind.lpszClassName = (LPCTSTR)strClassName;
  145. ::RegisterClassEx(&wceFind);
  146. pConsole()->GetMainWindow(&hwndParent);
  147. m_hwndFind = ::CreateWindow(strClassName, strWindowName, WS_CHILD,
  148. 0, 0, 0, 0, hwndParent, NULL, wceFind.hInstance, &csFind);
  149. ASSERT(m_hwndFind != NULL);
  150. return S_OK;
  151. }
  152. /*
  153. * SkipSpaces - Advance the pointer passed in beyond all spaces.
  154. *
  155. * History: a-jsari 11/28/97 Initial version
  156. */
  157. inline void SkipSpaces(LPTSTR &pszString)
  158. {
  159. while (_istspace(*pszString)) ++pszString;
  160. }
  161. /*
  162. * GetValue - Save the value (of the form '= Value' out of pszString into
  163. * szValue.
  164. *
  165. * History: a-jsari 11/28/97 Initial version
  166. */
  167. static inline BOOL GetValue(LPTSTR &pszString, LPTSTR szValue)
  168. {
  169. SkipSpaces(pszString);
  170. //if (*pszString++ != (TCHAR)'=')
  171. // return FALSE;
  172. if (*pszString == (TCHAR)'=')
  173. pszString++;
  174. SkipSpaces(pszString);
  175. if (*pszString == (TCHAR)'"') {
  176. ++pszString;
  177. do {
  178. *szValue = *pszString;
  179. if (*szValue++ == 0)
  180. return FALSE;
  181. } while ((*pszString++ != '"'));
  182. *--szValue = (TCHAR)0;
  183. } else {
  184. do {
  185. *szValue++ = *pszString;
  186. if (*pszString == 0)
  187. return TRUE;
  188. } while (!::_istspace(*pszString++));
  189. *--szValue = (TCHAR)0;
  190. }
  191. return TRUE;
  192. }
  193. /*
  194. * DisplayHelp - Show the help information for MSInfo
  195. *
  196. * History: a-jsari 11/28/97 Initial version
  197. */
  198. static inline void DisplayHelp(LPTSTR /* szHelp */)
  199. {
  200. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  201. CString strHelpFile;
  202. VERIFY(strHelpFile.LoadString(IDS_HELPFILE));
  203. ::HtmlHelp(/* HWND */ NULL, strHelpFile, HH_DISPLAY_TOPIC, 0);
  204. }
  205. /*
  206. * ProcessCommandLine - Grab all of the essential values out of our command
  207. * line.
  208. *
  209. * History: a-jsari 11/28/97 Initial version
  210. */
  211. HRESULT CSystemInfoScope::ProcessCommandLine()
  212. {
  213. const int VALUE_SIZE = 256;
  214. LPTSTR szCommands = ::GetCommandLine();
  215. LPTSTR pszCurrent = szCommands;
  216. TCHAR szValueBuffer[VALUE_SIZE];
  217. int iFirst;
  218. if (pszCurrent == NULL) return E_FAIL;
  219. while (TRUE) {
  220. iFirst = _tcscspn(pszCurrent, _T(" \t"));
  221. // If our match is \0, we have reached the end of the string.
  222. if (pszCurrent[iFirst] == (TCHAR)'\0') break;
  223. pszCurrent += iFirst;
  224. ++pszCurrent;
  225. SkipSpaces(pszCurrent);
  226. // Not a command line switch, check the next parameter.
  227. if (!(*pszCurrent == (TCHAR)'/' || *pszCurrent == (TCHAR)'-'))
  228. continue;
  229. else
  230. ++pszCurrent;
  231. // We are processing the computer flag.
  232. if (_tcsnicmp(pszCurrent, _T("computer"), 8) == 0)
  233. {
  234. pszCurrent += 8;
  235. if (GetValue(pszCurrent, szValueBuffer) == TRUE)
  236. m_strDeferredMachine = szValueBuffer;
  237. }
  238. // After this point, all flags are msinfo specific.
  239. if (_tcsnicmp(pszCurrent, _T("msinfo"), 6) != 0) continue;
  240. pszCurrent += 6; // pszCurrent += strlen("msinfo");
  241. if (*pszCurrent == (TCHAR)'?'
  242. || _tcsnicmp(pszCurrent, _T("_help"), 5) == 0) {
  243. LPTSTR pszValue;
  244. if (GetValue(pszCurrent, szValueBuffer) == TRUE) {
  245. pszValue = szValueBuffer;
  246. } else {
  247. // No value for help switch, back up to the previous space, unless we're
  248. // at the end of the string.
  249. if (*pszCurrent != 0)
  250. do --pszCurrent; while (!::_istspace(*pszCurrent));
  251. pszValue = NULL;
  252. }
  253. DisplayHelp(pszValue);
  254. continue;
  255. }
  256. if (_tcsnicmp(pszCurrent, _T("_category"), 9) == 0) {
  257. pszCurrent += 9;
  258. if (GetValue(pszCurrent, szValueBuffer) == TRUE) {
  259. // -1 parameter means select no result pane item.
  260. m_pstrCategory = new CString(szValueBuffer);
  261. // SelectItem(szValueBuffer, -1);
  262. }
  263. continue;
  264. }
  265. if (_tcsnicmp(pszCurrent, _T("_file"), 5) == 0)
  266. {
  267. pszCurrent += 5;
  268. if (GetValue(pszCurrent, szValueBuffer) == TRUE)
  269. m_strDeferredLoad = szValueBuffer;
  270. continue;
  271. }
  272. if (_tcsnicmp(pszCurrent, _T("_showcategories"), 15) == 0)
  273. {
  274. pszCurrent += 15;
  275. if (GetValue(pszCurrent, szValueBuffer) == TRUE)
  276. m_strDeferredCategories = szValueBuffer;
  277. continue;
  278. }
  279. }
  280. return S_OK;
  281. }
  282. /*
  283. * Initialize - Called from MMC; we Initialize all of our relevant pointers
  284. * using QueryInterface and set the IConsole ImageList.
  285. *
  286. * History: a-jsari 8/27/97 Initial version
  287. */
  288. STDMETHODIMP CSystemInfoScope::Initialize(LPUNKNOWN pUnknown)
  289. {
  290. ASSERT(pUnknown != NULL);
  291. TRACE(_T("CSystemInfoScope::Initialize\n"));
  292. HRESULT hr;
  293. do {
  294. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  295. // MMC should only call ::Initialize once!
  296. ASSERT(m_pScope == NULL);
  297. hr = pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast<void **>(&m_pScope));
  298. ASSERT(hr == S_OK);
  299. if (FAILED(hr))
  300. break;
  301. ASSERT(m_pConsole == NULL);
  302. hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void **>(&m_pConsole));
  303. ASSERT(hr == S_OK);
  304. if (FAILED(hr))
  305. break;
  306. if (m_pSaveUnknown == NULL) // check this out, reversed
  307. {
  308. // We are reinitializing, so don't do the image list code again.
  309. ::CBitmap bmp16x16;
  310. ::CBitmap bmp32x32;
  311. LPIMAGELIST lpScopeImage;
  312. hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
  313. ASSERT(hr == S_OK);
  314. if (FAILED(hr))
  315. break;
  316. VERIFY(bmp16x16.LoadBitmap(IDB_16x16));
  317. VERIFY(bmp32x32.LoadBitmap(IDB_32x32));
  318. hr = lpScopeImage->ImageListSetStrip(
  319. reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmp16x16)),
  320. reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmp32x32)),
  321. 0, RGB(255,0,255));
  322. (void)lpScopeImage->Release();
  323. ASSERT(hr == S_OK);
  324. if (FAILED(hr))
  325. break;
  326. // This is also a fine place to add the log entry for starting MSInfo,
  327. // so it won't be repeated when we reinitialize.
  328. if (msiLog.IsLogging())
  329. msiLog.WriteLog(CMSInfoLog::BASIC, _T("START MSInfo\r\n"));
  330. }
  331. hr = InitializeDialogs();
  332. if (FAILED(hr)) break;
  333. hr = InitializeInternal();
  334. if (FAILED(hr)) break;
  335. hr = ProcessCommandLine();
  336. } while (FALSE);
  337. if (FAILED(hr)) {
  338. SAFE_RELEASE(m_pScope);
  339. SAFE_RELEASE(m_pConsole);
  340. }
  341. else {
  342. m_bInitializedCD = true;
  343. }
  344. #ifdef _DEBUG
  345. m_bDestroyedCD = false;
  346. #endif
  347. // Note that MMC does not permit us to fail return from Initialize,
  348. // so we always return S_OK, whether or not our Initialization is
  349. // successful.
  350. return S_OK;
  351. }
  352. /*
  353. * InitializeView - Read the current user's view information from the registry
  354. *
  355. * History: a-jsari 12/3/97 Initial version.
  356. */
  357. HRESULT CSystemInfoScope::InitializeView()
  358. {
  359. CRegKey crkView;
  360. long lResult;
  361. TCHAR szBuffer[1024];
  362. DWORD dwSize;
  363. lResult = crkView.Open(HKEY_CURRENT_USER, cszViewKey);
  364. if (lResult == ERROR_SUCCESS) {
  365. dwSize = sizeof(szBuffer);
  366. lResult = crkView.QueryValue(szBuffer, cszViewValue, &dwSize);
  367. }
  368. if (lResult != ERROR_SUCCESS)
  369. // Default to basic view.
  370. SetView(BASIC, TRUE);
  371. else {
  372. if (::_tcscmp(szBuffer, cszBasicValue) == 0)
  373. SetView(BASIC, FALSE);
  374. else if (::_tcscmp(szBuffer, cszAdvancedValue) == 0)
  375. SetView(ADVANCED, FALSE);
  376. else {
  377. ASSERT(FALSE);
  378. return E_FAIL;
  379. }
  380. }
  381. return S_OK;
  382. }
  383. HRESULT CSystemInfoScope::MessageBox( CString strText)
  384. {
  385. CString strTitle;
  386. strTitle.LoadString( IDS_DESCRIPTION);
  387. int nRC;
  388. return pConsole()->MessageBox( strText, strTitle, MB_OK, &nRC);
  389. }
  390. /*
  391. * InitializeSource - Perform any initialization which may fail.
  392. *
  393. * History: a-jsari 12/3/97 Initial version.
  394. */
  395. HRESULT CSystemInfoScope::InitializeSource()
  396. {
  397. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  398. CWaitCursor DoWaitCursor;
  399. try {
  400. // m_pSource will exist if we were loaded from a stream.
  401. if (m_pSource == NULL) {
  402. m_bInitializedCD = true;
  403. // Initialize WBEM with the machine name.
  404. // Deleted in either SetView or Destroy
  405. m_pSource = new CWBEMDataSource(MachineName());
  406. }
  407. }
  408. catch (CUserException *) {
  409. CString strLocalConnect;
  410. VERIFY(strLocalConnect.LoadString(IDS_LOCAL_CONNECT));
  411. MessageBox((LPCTSTR)strLocalConnect);
  412. try {
  413. (*m_pstrMachineName) = _T("");
  414. m_pSource = new CWBEMDataSource(NULL);
  415. }
  416. catch (CUserException *) {
  417. m_bInitializedCD = false;
  418. return E_FAIL;
  419. }
  420. }
  421. m_fViewUninitialized = TRUE;
  422. InitializeView();
  423. return S_OK;
  424. }
  425. /*
  426. * DestroyInternal - Delete all of our internal pointers. This method of dealing
  427. * with pointers is required because MMC never calls our object's destructor.
  428. *
  429. * History: a-jsari 12/30/97 Initial version
  430. */
  431. void CSystemInfoScope::DestroyInternal()
  432. {
  433. // AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  434. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  435. {
  436. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  437. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  438. pWBEMSource->m_pThreadRefresh->CancelRefresh(FALSE);
  439. }
  440. // If there is a find thread, it will take care of getting rid of the window.
  441. // Otherwise, we must destroy it here. Fixes bug 395091.
  442. if (m_pthdFind)
  443. dynamic_cast<CFindThread *>(m_pthdFind)->RemoteQuit();
  444. else
  445. ::DestroyWindow(m_hwndFind);
  446. if (m_pSource) { delete m_pSource; m_pSource = NULL; }
  447. if (m_prdSave) { delete m_prdSave; m_prdSave = NULL; }
  448. if (m_prdOpen) { delete m_prdOpen; m_prdOpen = NULL; }
  449. if (m_prdReport) { delete m_prdReport; m_prdReport = NULL; }
  450. if (m_pstrMachineName) { delete m_pstrMachineName; m_pstrMachineName = NULL; }
  451. if (m_pstrOverrideName) { delete m_pstrOverrideName; m_pstrOverrideName = NULL; }
  452. if (m_pmapCategories) { delete m_pmapCategories; m_pmapCategories = NULL; }
  453. if (m_pViewCABTool) { delete m_pViewCABTool; m_pViewCABTool = NULL; }
  454. }
  455. /*
  456. * CreateComponent - Create the IComponent interface object (the CSystemInfo
  457. * object in this framework) and attach myself (the IComponentData
  458. * interface object) to it. Return the QueryInterfaced IComponent
  459. * pointer in ppComponent.
  460. *
  461. * History: a-jsari 8/27/97 Initial version
  462. */
  463. STDMETHODIMP CSystemInfoScope::CreateComponent(LPCOMPONENT *ppComponent)
  464. {
  465. ASSERT(ppComponent != NULL);
  466. TRACE(_T("CSystemInfoScope::CreateComponent\n"));
  467. #if 0
  468. if (m_bInitializedCD == false) {
  469. *ppComponent = NULL;
  470. return S_OK;
  471. }
  472. #endif
  473. CComObject<CSystemInfo> *pObject;
  474. CComObject<CSystemInfo>::CreateInstance(&pObject);
  475. ASSERT(pObject != NULL);
  476. if(NULL == pObject)
  477. return E_OUTOFMEMORY;
  478. m_pLastSystemInfo = pObject;
  479. //Store IComponentData
  480. HRESULT hr;
  481. hr = pObject->SetIComponentData(this);
  482. ASSERT(hr == S_OK);
  483. if (FAILED(hr)) {
  484. return hr;
  485. }
  486. return pObject->QueryInterface(IID_IComponent, reinterpret_cast<void **>(ppComponent));
  487. }
  488. /*
  489. * PreUIInit - Make any changes required just before the UI initializes.
  490. *
  491. * History: a-jsari 3/6/98 Initial version
  492. */
  493. HRESULT CSystemInfoScope::PreUIInit()
  494. {
  495. HRESULT hr = S_OK;
  496. if (m_pSource == NULL) {
  497. hr = InitializeSource();
  498. } else {
  499. hr = InitializeView();
  500. }
  501. return hr;
  502. }
  503. /*
  504. * PostUIInit - Do all initialization which can only occur after the result
  505. * pane UI
  506. *
  507. * History: a-jsari 3/6/98 Initial version
  508. */
  509. void CSystemInfoScope::PostUIInit()
  510. {
  511. if (!m_strDeferredLoad.IsEmpty() || !m_strDeferredMachine.IsEmpty())
  512. {
  513. // Instead of doing a "SetSource(m_pSource, FALSE)", which deletes the
  514. // tree, all we need to do here is rename the root node to match the
  515. // opened file. A non-empty m_strDeferredLoad indicates this is necessary.
  516. // (Or a non empty deferred machine change.)
  517. m_strDeferredLoad.Empty();
  518. m_strDeferredMachine.Empty();
  519. SCOPEDATAITEM sdiRoot;
  520. CString strNodeName;
  521. HSCOPEITEM hsiRoot;
  522. HRESULT hr;
  523. if (m_pmapCategories->ScopeFromView(NULL, hsiRoot))
  524. {
  525. ::memset(&sdiRoot, 0, sizeof(sdiRoot));
  526. sdiRoot.ID = hsiRoot;
  527. sdiRoot.mask = SDI_STR;
  528. hr = pScope()->GetItem(&sdiRoot);
  529. ASSERT(SUCCEEDED(hr));
  530. if (SUCCEEDED(hr))
  531. {
  532. m_pSource->GetNodeName(strNodeName);
  533. sdiRoot.displayname = T2OLE(const_cast<LPTSTR>((LPCTSTR)strNodeName));
  534. hr = pScope()->SetItem(&sdiRoot);
  535. ASSERT(SUCCEEDED(hr));
  536. }
  537. }
  538. }
  539. // This is the first point at which we can set UI values.
  540. if (m_fViewUninitialized && m_fSelectCategory) {
  541. m_fViewUninitialized = FALSE;
  542. SetSource(m_pSource, FALSE);
  543. }
  544. if (m_pstrCategory != NULL && m_fSelectCategory) {
  545. // Before the SelectItem call to prevent recursion.
  546. m_fSelectCategory = FALSE;
  547. SelectItem(*m_pstrCategory);
  548. delete m_pstrCategory;
  549. m_pstrCategory = NULL;
  550. }
  551. }
  552. /*
  553. * Notify - Handle any MSInfo namespace node events posted by MMC.
  554. *
  555. * History: a-jsari 8/27/97 Initial version
  556. */
  557. STDMETHODIMP CSystemInfoScope::Notify(LPDATAOBJECT pDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  558. {
  559. TRACE(_T("CSystemInfoScope::Notify (DataObject, %lx, %p, %p)\n"), event, arg, param);
  560. HRESULT hr;
  561. if (m_bInitializedCD == false)
  562. return S_OK;
  563. switch(event)
  564. {
  565. case MMCN_EXPAND:
  566. if (m_pSaveUnknown)
  567. {
  568. m_pstrMachineName = new CString;
  569. m_pstrOverrideName = new CString;
  570. Initialize(m_pSaveUnknown);
  571. m_pSaveUnknown = NULL;
  572. }
  573. hr = PreUIInit();
  574. if (FAILED(hr)) break;
  575. hr = OnExpand(pDataObject, arg, param);
  576. PostUIInit();
  577. break;
  578. case MMCN_REMOVE_CHILDREN:
  579. // Sometimes we make an internal call which causes this notification to be
  580. // sent, but we don't want to process it the same way.
  581. if (!m_fInternalDelete)
  582. {
  583. m_pSaveUnknown = m_pScope;
  584. DestroyInternal();
  585. SAFE_RELEASE(m_pScope);
  586. SAFE_RELEASE(m_pConsole);
  587. m_pScope = NULL;
  588. m_pConsole = NULL;
  589. m_pSource = NULL;
  590. m_prdSave = NULL;
  591. m_prdOpen = NULL;
  592. m_prdReport = NULL;
  593. m_pstrMachineName = NULL;
  594. m_pstrOverrideName = NULL;
  595. m_pmapCategories = NULL;
  596. }
  597. hr = S_OK;
  598. break;
  599. case MMCN_PROPERTY_CHANGE:
  600. hr = OnProperties(param);
  601. break;
  602. case MMCN_EXPANDSYNC:
  603. break;
  604. default:
  605. ASSERT(FALSE);
  606. break;
  607. }
  608. return hr;
  609. }
  610. /*
  611. * Destroy - Release all of our Initialized pointers.
  612. *
  613. * History: a-jsari 8/27/97 Initial version
  614. */
  615. STDMETHODIMP CSystemInfoScope::Destroy()
  616. {
  617. TRACE(L"CSystemInfoScope::Destroy\n");
  618. if (m_pwConsole != NULL) {
  619. m_pwConsole->Detach();
  620. delete m_pwConsole;
  621. }
  622. #if FALSE
  623. #ifdef _DEBUG
  624. m_bDestroyedCD = true;
  625. #endif
  626. #if 0
  627. if (m_bInitializedCD == FALSE) return S_OK;
  628. #endif
  629. DestroyInternal();
  630. SAFE_RELEASE(m_pScope);
  631. SAFE_RELEASE(m_pConsole);
  632. #endif
  633. return S_OK;
  634. }
  635. /*
  636. * QueryDataObject - Return the DataObject referred to by the cookie
  637. * and type.
  638. *
  639. * History: a-jsari 8/27/97 Initial version
  640. */
  641. STDMETHODIMP CSystemInfoScope::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  642. LPDATAOBJECT *ppDataObject)
  643. {
  644. TRACE(_T("CSystemInfoScope::QueryDataObject (%lx, %x, DataObject)\n"), cookie, type);
  645. return CDataObject::CreateDataObject(cookie, type, this, ppDataObject);
  646. }
  647. /*
  648. * CompareObjects - Compare two objects to see if they are equivalent.
  649. *
  650. * History: a-jsari 8/27/97 Initial version
  651. */
  652. STDMETHODIMP CSystemInfoScope::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  653. {
  654. TRACE(_T("CSystemInfoScope::CompareObjects\n"));
  655. return CDataObject::CompareObjects(lpDataObjectA, lpDataObjectB);
  656. }
  657. /*
  658. * GetDisplayInfo - Returns display information for this node in the scope pane.
  659. *
  660. * History: a-jsari 8/27/97 Initial version
  661. */
  662. STDMETHODIMP CSystemInfoScope::GetDisplayInfo(SCOPEDATAITEM *pScopeDataItem)
  663. {
  664. USES_CONVERSION;
  665. #if 0
  666. TRACE(_T("CSystemInfoScope::GetDisplayInfo\n"));
  667. #endif
  668. ASSERT(pScopeDataItem != NULL);
  669. if (pScopeDataItem == NULL) return E_POINTER;
  670. ASSERT(pScopeDataItem->mask & SDI_STR);
  671. if (pScopeDataItem->mask & SDI_STR) {
  672. CViewObject *pDataCategory = reinterpret_cast<CViewObject *>(pScopeDataItem->lParam);
  673. pScopeDataItem->displayname = T2OLE(const_cast<LPTSTR>(pDataCategory->GetTextItem()));
  674. }
  675. return S_OK;
  676. }
  677. /*
  678. * AddToMenu - Add an item to a menu. This method assumes that the calling
  679. * function has called AFX_MANAGE_STATE(AfxGetStaticModuleState()) prior
  680. * to calling this function.
  681. *
  682. * History: a-jsari 9/15/97 Initial version
  683. */
  684. HRESULT CSystemInfoScope::AddToMenu(LPCONTEXTMENUCALLBACK lpCallback, long lNameResource,
  685. long lStatusResource, long lCommandID, long lInsertionPoint, long fFlags)
  686. {
  687. USES_CONVERSION;
  688. CONTEXTMENUITEM cmiMenuItem = { NULL, NULL, lCommandID,
  689. lInsertionPoint, fFlags, 0L};
  690. CString szResourceName;
  691. CString szResourceStatus;
  692. // FIX: Make these resources load only once.
  693. VERIFY(szResourceName.LoadString(lNameResource));
  694. VERIFY(szResourceStatus.LoadString(lStatusResource));
  695. cmiMenuItem.strName = WSTR_FROM_CSTRING(szResourceName);
  696. cmiMenuItem.strStatusBarText = WSTR_FROM_CSTRING(szResourceStatus);
  697. HRESULT hr = lpCallback->AddItem(&cmiMenuItem);
  698. ASSERT(hr == S_OK);
  699. return hr;
  700. }
  701. /*
  702. * AddMenuItems - Add the "Save Report" and "Save System Information" items to
  703. * the context menu.
  704. *
  705. * History: a-jsari 9/15/97 Initial version
  706. */
  707. extern BOOL fCABOpened;
  708. STDMETHODIMP CSystemInfoScope::AddMenuItems(LPDATAOBJECT lpDataObject,
  709. LPCONTEXTMENUCALLBACK lpCallback, long *pInsertionAllowed)
  710. {
  711. TRACE(_T("CSystemInfoScope::AddMenuItems\n"));
  712. ASSERT(lpDataObject != NULL);
  713. ASSERT(lpCallback != NULL);
  714. ASSERT(pInsertionAllowed != NULL);
  715. if (lpDataObject == NULL || lpCallback == NULL || pInsertionAllowed == NULL)
  716. return E_POINTER;
  717. HRESULT hr = S_OK;
  718. // Note - snap-ins need to look at the data object and determine in what
  719. // context menu items need to be added. They must also observe the
  720. // insertion allowed flags to see what items can be added.
  721. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  722. // CHECK: Will this ever work differently for multiselect?
  723. do {
  724. // Save Report and Save File are both task items and context items.
  725. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) {
  726. hr = AddToTopMenu(lpCallback, IDS_SAVEREPORTMENUNAME, IDS_SAVEREPORTSTATUS, IDM_SAVEREPORT);
  727. if (FAILED(hr)) break;
  728. hr = AddToTopMenu(lpCallback, IDS_SAVEFILEMENUNAME, IDS_SAVEFILESTATUS, IDM_SAVEFILE);
  729. if (FAILED(hr)) break;
  730. hr = AddToTopMenu(lpCallback, IDS_FINDMENUNAME, IDS_FINDSTATUS, IDM_FIND);
  731. if (FAILED(hr)) break;
  732. }
  733. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) {
  734. hr = AddToTaskMenu(lpCallback, IDS_FINDMENUNAME, IDS_FINDSTATUS, IDM_TASK_FIND);
  735. if (FAILED(hr)) break;
  736. // Don't add the Open File menu item for Extension snap-ins.
  737. if (IsPrimaryImpl())
  738. {
  739. hr = AddToTaskMenu(lpCallback, IDS_OPENFILEMENUNAME, IDS_OPENFILESTATUS, IDM_TASK_OPENFILE);
  740. if (FAILED(hr))
  741. break;
  742. CDataSource * pCurrentSource = pSource();
  743. if (pCurrentSource && pCurrentSource->GetType() != CDataSource::GATHERER)
  744. hr = AddToTaskMenu(lpCallback, IDS_CLOSEFILEMENUNAME, IDS_CLOSEFILEMENUSTATUS, IDM_TASK_CLOSE);
  745. else
  746. hr = AddToMenu(lpCallback, IDS_CLOSEFILEMENUNAME, IDS_CLOSEFILEMENUSTATUS, IDM_TASK_CLOSE, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_GRAYED);
  747. if (FAILED(hr))
  748. break;
  749. }
  750. hr = AddToTaskMenu(lpCallback, IDS_SAVEFILEMENUNAME, IDS_SAVEFILESTATUS, IDM_TASK_SAVEFILE);
  751. if (FAILED(hr)) break;
  752. hr = AddToTaskMenu(lpCallback, IDS_SAVEREPORTMENUNAME, IDS_SAVEREPORTSTATUS, IDM_TASK_SAVEREPORT);
  753. if (FAILED(hr)) break;
  754. // If a CAB file has been opened, add the view CAB contents menu item. Also
  755. // take this opportunity to create the tool to view the CAB contents, if it
  756. // has not already been created.
  757. if (fCABOpened)
  758. {
  759. if (m_pViewCABTool == NULL)
  760. m_pViewCABTool = new CCabTool(this);
  761. if (m_pViewCABTool != NULL)
  762. {
  763. hr = AddToTaskMenu(lpCallback, IDS_CAB_NAME, IDS_CAB_DESCRIPTION, IDM_TASK_VIEWCAB);
  764. if (FAILED(hr)) break;
  765. }
  766. }
  767. }
  768. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) {
  769. hr = AddToViewMenu(lpCallback, IDS_ADVANCEDVIEWNAME, IDS_ADVANCEDSTATUS, IDM_VIEW_ADVANCED,
  770. m_AdvancedFlags);
  771. if (FAILED(hr)) break;
  772. hr = AddToViewMenu(lpCallback, IDS_BASICVIEWNAME, IDS_BASICSTATUS, IDM_VIEW_BASIC, m_BasicFlags);
  773. if (FAILED(hr)) break;
  774. }
  775. } while (FALSE);
  776. return hr;
  777. }
  778. /*
  779. * DisplayFileError - Show a message box with an error message taken from
  780. * the exception thrown.
  781. *
  782. * History: a-jsari 2/13/98 Initial version
  783. */
  784. static inline void DisplayError(HRESULT hr, const CString &strFileName)
  785. {
  786. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  787. USES_CONVERSION;
  788. CString strFileError, strTitle;
  789. switch (hr) {
  790. case STG_E_PATHNOTFOUND:
  791. strFileError.Format(IDS_BAD_PATH, (LPCTSTR)strFileName);
  792. break;
  793. case STG_E_TOOMANYOPENFILES:
  794. VERIFY(strFileError.LoadString(IDS_TOOMANYOPENFILES));
  795. break;
  796. case STG_E_ACCESSDENIED:
  797. strFileError.Format(IDS_ACCESS_DENIED, (LPCTSTR)strFileName);
  798. break;
  799. case STG_E_SHAREVIOLATION:
  800. strFileError.Format(IDS_SHARING_VIOLATION, (LPCTSTR)strFileName);
  801. break;
  802. case STG_E_WRITEFAULT:
  803. VERIFY(strFileError.LoadString(IDS_HARDIO));
  804. break;
  805. case STG_E_MEDIUMFULL:
  806. strFileError.Format(IDS_DISK_FULL, (LPCTSTR)strFileName);
  807. break;
  808. default:
  809. VERIFY(strFileError.LoadString(IDS_UNKNOWN_FILE));
  810. break;
  811. }
  812. strTitle.LoadString(IDS_DESCRIPTION);
  813. ::MessageBox( ::AfxGetMainWnd()->GetSafeHwnd(), strFileError, strTitle, MB_OK);
  814. }
  815. /*
  816. * SaveReport - Create the save report save file dialog and save the selected file.
  817. *
  818. * History: a-jsari 12/8/97 Initial version
  819. */
  820. void CSystemInfoScope::SaveReport()
  821. {
  822. if (m_prdReport->DoModal() == IDOK) {
  823. CWaitCursor DoWaitCursor;
  824. if (m_pLastSystemInfo)
  825. m_pLastSystemInfo->SetStatusText(IDS_REFRESHING_MSG);
  826. HRESULT hr = pSource()->ReportWrite(m_prdReport->GetPathName(), m_pfLast);
  827. if (m_pLastSystemInfo)
  828. m_pLastSystemInfo->SetStatusText(_T(""));
  829. if (FAILED(hr)) {
  830. ::DisplayError(hr, m_prdReport->GetPathName());
  831. }
  832. }
  833. }
  834. /*
  835. * SaveFile - Create the save file dialog and save the selected file.
  836. *
  837. * History: a-jsari 12/8/97 Initial version
  838. */
  839. void CSystemInfoScope::SaveFile()
  840. {
  841. if (m_prdSave->DoModal() == IDOK)
  842. {
  843. CWaitCursor DoWaitCursor;
  844. if (m_pLastSystemInfo)
  845. m_pLastSystemInfo->SetStatusText(IDS_REFRESHING_MSG);
  846. HRESULT hr = pSource()->SaveFile(m_prdSave->GetPathName());
  847. if (m_pLastSystemInfo)
  848. m_pLastSystemInfo->SetStatusText(_T(""));
  849. if (FAILED(hr))
  850. ::DisplayError(hr, m_prdSave->GetPathName());
  851. }
  852. }
  853. /*
  854. * PrintReport - Create the print dialog and do the print.
  855. *
  856. * History: a-jsari 12/8/97 Initial version
  857. */
  858. void CSystemInfoScope::PrintReport()
  859. {
  860. HWND hWindow;
  861. ASSERT(m_pConsole != NULL);
  862. HRESULT hr = m_pConsole->GetMainWindow(&hWindow);
  863. ASSERT(hr == S_OK);
  864. if (FAILED(hr))
  865. return;
  866. CMSInfoPrintDialog * prdPrint = new CMSInfoPrintDialog(hWindow);
  867. ASSERT(prdPrint != NULL);
  868. if (prdPrint == NULL)
  869. ::AfxThrowMemoryException();
  870. prdPrint->m_pd.nToPage = prdPrint->m_pd.nFromPage = prdPrint->m_pd.nMinPage = 1;
  871. prdPrint->m_pd.nMaxPage = 1000;
  872. if (prdPrint->DoModal() == IDOK)
  873. {
  874. CWaitCursor DoWaitCursor;
  875. pSource()->RefreshPrintData(prdPrint, m_pfLast);
  876. pSource()->PrintReport(prdPrint, m_pfLast);
  877. }
  878. delete prdPrint;
  879. }
  880. /*
  881. * DoFind - Display the Find dialog
  882. *
  883. * History: a-jsari 12/8/97 Initial version.
  884. */
  885. void CSystemInfoScope::DoFind()
  886. {
  887. const UINT STACK_SIZE_PARENT = 0;
  888. // const DWORD FLAGS_IMMEDIATE_START = 0;
  889. const LPSECURITY_ATTRIBUTES NO_ATTRIBUTES = NULL;
  890. if (m_pthdFind == NULL)
  891. {
  892. m_pthdFind = dynamic_cast<CFindThread *>(::AfxBeginThread(RUNTIME_CLASS(CFindThread),
  893. THREAD_PRIORITY_NORMAL, STACK_SIZE_PARENT, CREATE_SUSPENDED, NO_ATTRIBUTES));
  894. m_pthdFind->SetScope(this);
  895. HWND hwndMMC;
  896. if (pConsole() == NULL || FAILED(pConsole()->GetMainWindow(&hwndMMC)))
  897. hwndMMC = NULL;
  898. m_pthdFind->SetParent(m_hwndFind, hwndMMC);
  899. m_pthdFind->ResumeThread();
  900. }
  901. else
  902. m_pthdFind->Activate();
  903. }
  904. /*
  905. * ExecuteFind - This function is actually called via a hook into
  906. * MMC's main window's WindowProc, by a message posted by
  907. * CFindThread's Find button function..
  908. *
  909. * The Refresh and Find functions may be interrupted by the Find
  910. * window's UI thread, and m_pthdFind may be deleted while this
  911. * function is executing.
  912. *
  913. * Instead of taking parameters, this function calls back to our
  914. * existing find thread to get its search string and last
  915. * search string. This simplifies the PostMessage call, but
  916. * would need to change if we ever decide to have multiple
  917. * find windows per IComponentData...unlikely.
  918. *
  919. * History: a-jsari 1/22/98 Initial version.
  920. */
  921. void CSystemInfoScope::ExecuteFind(long lFindState)
  922. {
  923. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  924. CWaitCursor DoWaitCursor; // Display the hourglass
  925. CString strFindData; // Our current search string.
  926. // The restricted context within which our search occurs.
  927. static CFolder *pfContext;
  928. // Check m_pthdFind since there's a remote possibility of thread pointer
  929. // invalidation (by the user closing the Find dialog while the
  930. // find is running).
  931. if (m_pthdFind == NULL)
  932. return;
  933. strFindData = m_pthdFind->FindString();
  934. CDataSource *pdsSearch = pSource();
  935. do {
  936. if ((lFindState & CDataSource::FIND_OPTION_REPEAT_SEARCH) == 0)
  937. {
  938. // Only refresh the first time we search for a given string.
  939. // Also, only refresh if we are searching more than category names.
  940. BOOL fRefreshResult = TRUE;
  941. if ((lFindState & CDataSource::FIND_OPTION_CATEGORY_ONLY) == 0)
  942. {
  943. // If we are only searching in one category, only refresh that
  944. // category.
  945. if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0)
  946. {
  947. if (pdsSearch->GetType() == CDataSource::GATHERER)
  948. {
  949. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  950. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  951. pWBEMSource->m_pThreadRefresh->RefreshFolder(m_pfLast, TRUE, FALSE);
  952. }
  953. }
  954. else
  955. fRefreshResult = pdsSearch->Refresh(TRUE);
  956. }
  957. if (!fRefreshResult)
  958. {
  959. if (m_pthdFind != NULL)
  960. m_pthdFind->ResetSearch();
  961. break;
  962. }
  963. // Set our context the first time we start a restricted search.
  964. if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0)
  965. pfContext = m_pfLast;
  966. else
  967. pfContext = NULL;
  968. }
  969. else if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0)
  970. {
  971. // If we set a restricted search inside an already started search
  972. // restrict our context.
  973. // CHECK: iDepth???
  974. if (pfContext == NULL)
  975. pfContext = m_pfLast;
  976. }
  977. if (pdsSearch->Find(strFindData, lFindState) == FALSE) {
  978. // Failed find means no match or halted execution.
  979. // If the user stoppped the find, no message necessary.
  980. if (!pdsSearch->FindStopped()) {
  981. CString strError; // Error display
  982. CString strTitle; // Error title.
  983. int nReturn;
  984. // Test the thread because the find window might vanish in the middle
  985. // of our find operation.
  986. if (m_pthdFind != NULL)
  987. m_pthdFind->FindComplete();
  988. if (m_pthdFind != NULL)
  989. m_pthdFind->ResetSearch();
  990. // If we're repeating a search, no more matches otherwise, not found.
  991. if ((lFindState & CDataSource::FIND_OPTION_REPEAT_SEARCH) == 0) {
  992. strError.Format(IDS_DATANOTFOUND, (LPCTSTR)strFindData);
  993. } else
  994. strError.Format(IDS_NOMOREMATCHES, (LPCTSTR)strFindData);
  995. VERIFY(strTitle.LoadString(IDS_FIND_TITLE));
  996. pConsole()->MessageBox((LPCTSTR)strError, (LPCTSTR)strTitle,
  997. MB_TOPMOST|MB_SETFOREGROUND, &nReturn);
  998. // If we are restricting our search, reset the selected folder to the
  999. // beginning of our restricted search.
  1000. if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0)
  1001. SetSelectedFolder(pfContext);
  1002. // We've already completed the find, don't drop out.
  1003. return;
  1004. }
  1005. } else {
  1006. SelectItem(pdsSearch->m_strPath, pdsSearch->m_iLine);
  1007. }
  1008. } while (FALSE);
  1009. // The find window might vanish in the middle of our find operation.
  1010. if (m_pthdFind != NULL)
  1011. m_pthdFind->FindComplete();
  1012. }
  1013. /*
  1014. * MainThreadStopFind - Stops a find operation running in an alternate thread.
  1015. *
  1016. * History: a-jsari 1/22/98 Initial version.
  1017. */
  1018. void CSystemInfoScope::StopFind()
  1019. {
  1020. // This will be called by an alternate UI thread.
  1021. pSource()->StopSearch();
  1022. }
  1023. /*
  1024. * Refresh - Refresh the data, and redraw the current node if applicable.
  1025. *
  1026. * History: a-jsari 2/25/98 Initial version
  1027. */
  1028. void CSystemInfoScope::Refresh(CFolder * pfSelected, CSystemInfo * pSystemInfo)
  1029. {
  1030. CWaitCursor DoWaitCursor;
  1031. if (pfSelected && pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1032. {
  1033. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1034. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  1035. {
  1036. if (pSystemInfo)
  1037. pWBEMSource->m_pThreadRefresh->RefreshFolderAsync(pfSelected, pSystemInfo, TRUE, FALSE);
  1038. else
  1039. pWBEMSource->m_pThreadRefresh->RefreshFolder(pfSelected, TRUE, FALSE);
  1040. }
  1041. }
  1042. else
  1043. pSource()->Refresh();
  1044. if (pfSelected != NULL)
  1045. {
  1046. CString strName;
  1047. int nLine = 0;
  1048. pfSelected->InternalName(strName);
  1049. SelectItem(strName, nLine);
  1050. }
  1051. }
  1052. /*
  1053. * CloseFindWindow - Function to be called when the find window closes.
  1054. *
  1055. * History: a-jsari 1/22/97 Initial version.
  1056. */
  1057. void CSystemInfoScope::CloseFindWindow()
  1058. {
  1059. // Don't delete m_pthdFind; it will delete itself.
  1060. m_pthdFind = NULL;
  1061. }
  1062. /*
  1063. * OpenFile - Create the open file file dialog and open the resultant file
  1064. *
  1065. * History: a-jsari 12/8/97 Initial version
  1066. */
  1067. void CSystemInfoScope::OpenFile()
  1068. {
  1069. const long DONT_USE_LAST_FOLDER = 1;
  1070. if (m_prdOpen->DoModal() == IDOK)
  1071. {
  1072. CWaitCursor DoWaitCursor;
  1073. CDataSource *pSource = NULL;
  1074. try
  1075. {
  1076. pSource = CBufferDataSource::CreateDataSourceFromFile(m_prdOpen->GetPathName());
  1077. }
  1078. catch (...)
  1079. {
  1080. delete pSource;
  1081. pSource = NULL;
  1082. }
  1083. if (pSource != NULL)
  1084. {
  1085. SetSource(pSource);
  1086. InitializeView();
  1087. }
  1088. pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L);
  1089. // Reset the selected folder (it's no longer valid with the new tree).
  1090. SetSelectedFolder(NULL);
  1091. HSCOPEITEM hsiNode = NULL;
  1092. if (m_pmapCategories && m_pmapCategories->ScopeFromView(NULL, hsiNode))
  1093. pConsole()->SelectScopeItem(hsiNode);
  1094. }
  1095. }
  1096. //-----------------------------------------------------------------------------
  1097. // Close the currently opened file.
  1098. //-----------------------------------------------------------------------------
  1099. void CSystemInfoScope::CloseFile()
  1100. {
  1101. CDataSource * pDataSource = pSource();
  1102. if (pDataSource && pDataSource->GetType() == CDataSource::GATHERER)
  1103. return;
  1104. try
  1105. {
  1106. (*m_pstrMachineName) = _T("");
  1107. pDataSource = new CWBEMDataSource(NULL);
  1108. }
  1109. catch (CUserException *)
  1110. {
  1111. m_bInitializedCD = false;
  1112. return;
  1113. }
  1114. if (pDataSource != NULL)
  1115. {
  1116. SetSource(pDataSource);
  1117. InitializeView();
  1118. }
  1119. const long DONT_USE_LAST_FOLDER = 1;
  1120. pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L);
  1121. // Reset the selected folder (it's no longer valid with the new tree).
  1122. SetSelectedFolder(NULL);
  1123. }
  1124. /*
  1125. * Command - Call the function represented by nCommandID.
  1126. *
  1127. * History: a-jsari 9/15/97 Initial version
  1128. *
  1129. * Note: This function currently takes no notice of the context represented
  1130. * by pdoContext.
  1131. */
  1132. STDMETHODIMP CSystemInfoScope::Command(long nCommandID, LPDATAOBJECT)
  1133. {
  1134. HRESULT hr = S_OK;
  1135. TRACE(_T("CSystemInfoScope::Command(%lx)\n"), nCommandID);
  1136. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1137. // For any of these commands, we want to cancel an async category refresh
  1138. // is there is one in progress.
  1139. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1140. {
  1141. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1142. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  1143. {
  1144. CWaitCursor waitcursor;
  1145. pWBEMSource->m_pThreadRefresh->WaitForRefresh();
  1146. }
  1147. }
  1148. try {
  1149. switch (nCommandID) {
  1150. case IDM_SAVEREPORT:
  1151. case IDM_TASK_SAVEREPORT:
  1152. if (msiLog.IsLogging())
  1153. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Save As Text\"\r\n"));
  1154. SaveReport();
  1155. break;
  1156. case IDM_SAVEFILE:
  1157. case IDM_TASK_SAVEFILE:
  1158. if (msiLog.IsLogging())
  1159. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Save NFO\"\r\n"));
  1160. SaveFile();
  1161. break;
  1162. case IDM_TASK_FIND:
  1163. case IDM_FIND:
  1164. if (msiLog.IsLogging())
  1165. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Find\"\r\n"));
  1166. DoFind();
  1167. break;
  1168. case IDM_TASK_OPENFILE:
  1169. if (msiLog.IsLogging())
  1170. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Open NFO\"\r\n"));
  1171. OpenFile();
  1172. break;
  1173. case IDM_TASK_VIEWCAB:
  1174. if (msiLog.IsLogging())
  1175. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"View CAB\"\r\n"));
  1176. if (m_pViewCABTool)
  1177. m_pViewCABTool->RunTool();
  1178. break;
  1179. case IDM_VIEW_ADVANCED:
  1180. if (msiLog.IsLogging())
  1181. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Set View ADVANCED\"\r\n"));
  1182. SetView(ADVANCED, TRUE);
  1183. break;
  1184. case IDM_VIEW_BASIC:
  1185. if (msiLog.IsLogging())
  1186. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Set View BASIC\"\r\n"));
  1187. SetView(BASIC, TRUE);
  1188. break;
  1189. case IDM_TASK_CLOSE:
  1190. if (msiLog.IsLogging())
  1191. msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Close NFO\"\r\n"));
  1192. CloseFile();
  1193. break;
  1194. case ~0:
  1195. // We get this result when we back arrow on the taskpad.
  1196. break;
  1197. default:
  1198. ASSERT(FALSE);
  1199. break;
  1200. }
  1201. }
  1202. catch (...) {
  1203. ASSERT(FALSE);
  1204. hr = HRESULT_FROM_WIN32(::GetLastError());
  1205. }
  1206. return hr;
  1207. }
  1208. /*
  1209. * CreatePropertyPages - Create an instance of our property pages and attach them
  1210. * to MMC's property sheet.
  1211. *
  1212. * History: a-jsari 9/17/97 Initial version
  1213. */
  1214. STDMETHODIMP CSystemInfoScope::CreatePropertyPages(LPPROPERTYSHEETCALLBACK pProvider,
  1215. LONG_PTR handle, LPDATAOBJECT pDataObject)
  1216. {
  1217. ASSERT(pProvider != NULL);
  1218. ASSERT(pDataObject != NULL);
  1219. TRACE(_T("CSystemInfoScope::CreatePropertyPages\n"));
  1220. if (pProvider == NULL || pDataObject == NULL) return E_INVALIDARG;
  1221. // Special code goes here if we're used as an extension.
  1222. HRESULT hResult;
  1223. do {
  1224. CChooseMachinePropPage *pPropChoose;
  1225. HPROPSHEETPAGE hGeneralPage;
  1226. BOOL fOverride;
  1227. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1228. // Deleted automatically.
  1229. pPropChoose = new CChooseMachinePropPage(IDD_CHOOSER_CHOOSE_MACHINE);
  1230. if (pPropChoose == NULL) {
  1231. ::MMCFreeNotifyHandle(handle);
  1232. ::AfxThrowMemoryException();
  1233. }
  1234. // Save the current machine name, in case the one selected in the property
  1235. // page is not any good.
  1236. m_strLastMachineName = *m_pstrMachineName;
  1237. pPropChoose->SetHandle(handle);
  1238. pPropChoose->SetOutputBuffers(m_pstrMachineName, &fOverride, m_pstrOverrideName);
  1239. hGeneralPage = ::CreatePropertySheetPage(&pPropChoose->m_psp);
  1240. if (!hGeneralPage) {
  1241. hResult = E_FAIL;
  1242. break;
  1243. }
  1244. hResult = pProvider->AddPage(hGeneralPage);
  1245. ASSERT(SUCCEEDED(hResult));
  1246. } while (FALSE);
  1247. if (FAILED(hResult)) return hResult;
  1248. return S_OK;
  1249. }
  1250. /*
  1251. * QueryPagesFor - Return S_OK, informing MMC that we have property sheets available.
  1252. *
  1253. * History: a-jsari 9/17/97 Initial version
  1254. */
  1255. STDMETHODIMP CSystemInfoScope::QueryPagesFor(LPDATAOBJECT pDataObject)
  1256. {
  1257. TRACE(_T("CSystemInfoScope::QueryPagesFor\n"));
  1258. ASSERT(pDataObject != NULL);
  1259. if (pDataObject == NULL) return E_POINTER;
  1260. // If we are being loaded as an extension, don't display property pages.
  1261. // We do this because the base snap-in is responsible for the connected
  1262. // machine, not us.
  1263. if (!IsPrimaryImpl()) return S_FALSE;
  1264. #if 0
  1265. // Not sure why I did this.
  1266. // If the machine name is already set, don't display the property page.
  1267. if (m_pstrMachineName && m_pstrMachineName->GetLength() > 0) return S_FALSE;
  1268. #endif
  1269. return S_OK;
  1270. }
  1271. /*
  1272. * Load - Load our state from the stream provided.
  1273. *
  1274. * History: a-jsari 11/5/97 Initial version
  1275. */
  1276. STDMETHODIMP CSystemInfoScope::Load(IStream *pStm)
  1277. {
  1278. CDataSource *pSource;
  1279. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1280. TRACE(_T("CSystemInfoScope::Load\n"));
  1281. ASSERT(pStm != NULL);
  1282. if (pStm == NULL) return E_POINTER;
  1283. ClearDirty();
  1284. // If our command-line parameters have specified a source, don't replace it.
  1285. if (!m_fViewUninitialized)
  1286. {
  1287. if (m_strDeferredLoad.IsEmpty())
  1288. pSource = CDataSource::CreateFromIStream(pStm);
  1289. else
  1290. {
  1291. pSource = CBufferDataSource::CreateDataSourceFromFile(m_strDeferredLoad);
  1292. if (pSource)
  1293. {
  1294. const long DONT_USE_LAST_FOLDER = 1;
  1295. SetSource(pSource, TRUE);
  1296. pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L);
  1297. SetSelectedFolder(NULL);
  1298. return S_OK;
  1299. }
  1300. else
  1301. m_strDeferredLoad.Empty();
  1302. }
  1303. if (pSource == NULL)
  1304. InitializeSource();
  1305. else
  1306. {
  1307. if (!m_strDeferredCategories.IsEmpty())
  1308. pSource->SetCategories(m_strDeferredCategories);
  1309. SetSource(pSource, TRUE);
  1310. if (!m_strDeferredMachine.IsEmpty())
  1311. SetMachine(m_strDeferredMachine);
  1312. }
  1313. }
  1314. return S_OK;
  1315. }
  1316. /*
  1317. * Save - Save our state to the stream provided.
  1318. *
  1319. * History: a-jsari 11/5/97 Initial version
  1320. */
  1321. STDMETHODIMP CSystemInfoScope::Save(IStream *pStm, BOOL fClearDirty)
  1322. {
  1323. TRACE(_T("CSystemInfoScope::Save\n"));
  1324. ASSERT(pStm != NULL);
  1325. if (pStm == NULL) return E_POINTER;
  1326. if (fClearDirty)
  1327. ClearDirty();
  1328. HRESULT hResult = S_OK;
  1329. // If there is a source, let it save its state to the stream. Otherwise,
  1330. // save the state for the default source (GATHERER with no machine name).
  1331. if (m_pSource)
  1332. hResult = m_pSource->Save(pStm);
  1333. else
  1334. {
  1335. unsigned wValue;
  1336. ULONG cWrite;
  1337. wValue = CDataSource::GATHERER;
  1338. hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite);
  1339. if (SUCCEEDED(hResult))
  1340. {
  1341. wValue = 0;
  1342. hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite);
  1343. }
  1344. }
  1345. return hResult;
  1346. }
  1347. /*
  1348. * IsDirty - Return our Dirty status, to see if a save would be beneficial.
  1349. *
  1350. * History: a-jsari 11/5/97 Initial version
  1351. */
  1352. STDMETHODIMP CSystemInfoScope::IsDirty()
  1353. {
  1354. TRACE(_T("CSystemInfoScope::IsDirty\n"));
  1355. return ObjectIsDirty() ? S_OK : S_FALSE;
  1356. }
  1357. /*
  1358. * GetClassID - Return our Component Object Class ID.
  1359. *
  1360. * History: a-jsari 11/5/97 Initial version
  1361. */
  1362. STDMETHODIMP CSystemInfoScope::GetClassID(CLSID *pClassID)
  1363. {
  1364. TRACE(_T("CSystemInfoScope::GetClassID\n"));
  1365. ASSERT(pClassID != NULL);
  1366. if (pClassID == NULL) return E_POINTER;
  1367. *pClassID = GetCoClassID();
  1368. return S_OK;
  1369. }
  1370. /*
  1371. * GetSizeMax - Return the maximum size consumed in a stream by our
  1372. * persistance.
  1373. *
  1374. * History: a-jsari 11/5/97 Initial version
  1375. */
  1376. STDMETHODIMP CSystemInfoScope::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1377. {
  1378. TRACE(_T("CSystemInfoScope::GetSizeMax\n"));
  1379. ASSERT(pcbSize != NULL);
  1380. if (pcbSize == NULL) return E_POINTER;
  1381. pcbSize->LowPart = 2 * sizeof(unsigned) + MAX_PATH;
  1382. pcbSize->HighPart = 0;
  1383. return E_NOTIMPL;
  1384. }
  1385. //-----------------------------------------------------------------------------
  1386. // Implementation of GetHelpTopic, which supplies the location of our help
  1387. // file to MMC for merging into the combined help. Adapted from example in
  1388. // the MMC help file.
  1389. //-----------------------------------------------------------------------------
  1390. STDMETHODIMP CSystemInfoScope::GetHelpTopic(LPOLESTR* lpCompiledHelpFile)
  1391. {
  1392. if (lpCompiledHelpFile == NULL)
  1393. return E_POINTER;
  1394. // Get the name of our help file, and prepend the help directory.
  1395. // Actually, although the MMC documentation said that a full path is
  1396. // required, we can just put the file name, since it is being stored in
  1397. // the system help directory (HTMLHelp will find it there).
  1398. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1399. CString strHelp;
  1400. strHelp.LoadString(IDS_MSINFO_HELP_FILE);
  1401. // NOTE: It looks like HTMLHelp has been changed, and will not locate
  1402. // the help file in the standard help directory. So we'll need to get
  1403. // the full path to the help file. (JCM, 7/1/98)
  1404. TCHAR szFilePath[MAX_PATH];
  1405. DWORD dwCnt = ExpandEnvironmentStrings(CString(_T("%WINDIR%\\help\\")) + strHelp, szFilePath, MAX_PATH);
  1406. ASSERT(dwCnt != 0);
  1407. if (dwCnt != 0) strHelp = szFilePath;
  1408. // Allocate the string to hold the help file path. MMC will be responsible
  1409. // for deallocating this buffer later.
  1410. *lpCompiledHelpFile = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc((strHelp.GetLength() + 1)* sizeof(wchar_t)));
  1411. if (*lpCompiledHelpFile == NULL)
  1412. return E_OUTOFMEMORY;
  1413. // Copy from the path string to the buffer and return success.
  1414. USES_CONVERSION;
  1415. wcscpy(*lpCompiledHelpFile, T2OLE((LPTSTR)(LPCTSTR)strHelp));
  1416. return S_OK;
  1417. }
  1418. /*
  1419. * SetMachine - Set our internal machine name.
  1420. *
  1421. * History: a-jsari 1/16/98 Initial version.
  1422. */
  1423. BOOL CSystemInfoScope::SetMachine(const CString &strMachine)
  1424. {
  1425. BOOL fReturn = FALSE;
  1426. *m_pstrMachineName = strMachine;
  1427. ASSERT(pSource() != NULL);
  1428. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1429. {
  1430. // Changing the machine name is only meaningful if we are connected to a WBEM
  1431. // data source.
  1432. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1433. fReturn = pWBEMSource->SetMachineName(*m_pstrMachineName);
  1434. if (fReturn)
  1435. {
  1436. // If we succeeded, reset the root node text. Also, there's a hack in place
  1437. // to keep SetSource from running twice during initialization. Which requires
  1438. // another hack here to make it run - change the flag it uses to keep track
  1439. // of the last call so that this call is different. I hate this.
  1440. m_fSetSourcePreLaunch = TRUE;
  1441. SetSource(pSource(), FALSE);
  1442. }
  1443. else {
  1444. }
  1445. }
  1446. return fReturn;
  1447. }
  1448. /*
  1449. * SetView - Set the view on the data.
  1450. *
  1451. * History: a-jsari 12/3/97 Initial version.
  1452. */
  1453. void CSystemInfoScope::SetView(enum DataComplexity Complexity, BOOL fViewInitialized)
  1454. {
  1455. CDataSource *pDataSource = pSource();
  1456. switch (Complexity) {
  1457. case BASIC:
  1458. m_BasicFlags = MF_CHECKED;
  1459. m_AdvancedFlags = 0L;
  1460. break;
  1461. case ADVANCED:
  1462. m_BasicFlags = 0L;
  1463. m_AdvancedFlags = MF_CHECKED;
  1464. break;
  1465. }
  1466. if (pDataSource != NULL)
  1467. VERIFY(pDataSource->SetDataComplexity(Complexity));
  1468. if (fViewInitialized) {
  1469. CRegKey crkView;
  1470. long lResult;
  1471. pConsole()->UpdateAllViews(NULL, 0, 0);
  1472. lResult = crkView.Create(HKEY_CURRENT_USER, cszViewKey);
  1473. if (lResult != ERROR_SUCCESS) return;
  1474. switch (Complexity) {
  1475. case ADVANCED:
  1476. lResult = crkView.SetValue(cszAdvancedValue, cszViewValue);
  1477. break;
  1478. case BASIC:
  1479. lResult = crkView.SetValue(cszBasicValue, cszViewValue);
  1480. break;
  1481. }
  1482. }
  1483. }
  1484. /*
  1485. * SetSource - Remove the old data source, and replace it with a new one.
  1486. *
  1487. * History: a-jsari 9/25/97 Initial version.
  1488. */
  1489. void CSystemInfoScope::SetSource(CDataSource *pNewSource, BOOL fPreLaunch)
  1490. {
  1491. HSCOPEITEM hsiRoot;
  1492. HRESULT hr;
  1493. BOOL fUIOK = FALSE;
  1494. // We have some variables in this class to make sure that SetSource
  1495. // isn't called twice during initialization with the same parameters.
  1496. if (m_pSetSourceSource == pNewSource && m_fSetSourcePreLaunch == fPreLaunch)
  1497. return;
  1498. m_pSetSourceSource = pNewSource;
  1499. m_fSetSourcePreLaunch = fPreLaunch;
  1500. // If fPreLaunch is TRUE, we have not yet created our UI items.
  1501. if (fPreLaunch == FALSE) {
  1502. if (m_pmapCategories == NULL)
  1503. m_pmapCategories = new CScopeItemMap;
  1504. // Select the root node so we can remove all its children.
  1505. if (m_pmapCategories && !m_pmapCategories->ScopeFromView(NULL, hsiRoot))
  1506. return;
  1507. hr = pConsole()->SelectScopeItem(hsiRoot);
  1508. ASSERT(SUCCEEDED(hr));
  1509. if (FAILED(hr)) return;
  1510. // Before we delete the item, we want to make sure that it's actually
  1511. // been added. Try a call to GetItem to make sure it's there.
  1512. SCOPEDATAITEM item; item.mask = SDI_CHILDREN; item.ID = hsiRoot;
  1513. fUIOK = SUCCEEDED(pScope()->GetItem(&item));
  1514. if (fUIOK)
  1515. {
  1516. m_fInternalDelete = TRUE;
  1517. hr = pScope()->DeleteItem(hsiRoot, FALSE);
  1518. m_fInternalDelete = FALSE;
  1519. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1520. ((CWBEMDataSource *) pSource())->ResetCategoryRefresh();
  1521. ASSERT(SUCCEEDED(hr));
  1522. if (FAILED(hr)) return;
  1523. if (m_pSaveUnknown)
  1524. {
  1525. m_pstrMachineName = new CString;
  1526. m_pstrOverrideName = new CString;
  1527. Initialize(m_pSaveUnknown);
  1528. m_pSaveUnknown = NULL;
  1529. }
  1530. }
  1531. // Remove our memory of data items.
  1532. m_pmapCategories->Clear();
  1533. }
  1534. // Don't delete our pointer if we are resetting the same pointer.
  1535. if (m_pSource != pNewSource) {
  1536. if (!m_pSource)
  1537. m_pSource = pNewSource;
  1538. else {
  1539. DataComplexity Complexity;
  1540. Complexity = m_pSource->m_Complexity;
  1541. delete m_pSource;
  1542. m_pSource = pNewSource;
  1543. m_pSource->SetDataComplexity(Complexity);
  1544. }
  1545. }
  1546. if (fPreLaunch == FALSE) {
  1547. CFolder *pFolder;
  1548. SCOPEDATAITEM sdiRoot;
  1549. CString strNodeName;
  1550. USES_CONVERSION;
  1551. ::memset(&sdiRoot, 0, sizeof(sdiRoot));
  1552. // Identify the node.
  1553. sdiRoot.ID = hsiRoot;
  1554. sdiRoot.mask = SDI_STR;
  1555. m_pSource->GetNodeName(strNodeName);
  1556. sdiRoot.displayname = T2OLE(const_cast<LPTSTR>((LPCTSTR)strNodeName));
  1557. hr = pScope()->SetItem(&sdiRoot);
  1558. ASSERT(SUCCEEDED(hr));
  1559. hr = AddRoot(hsiRoot, &pFolder);
  1560. ASSERT(SUCCEEDED(hr));
  1561. if (FAILED(hr)) return;
  1562. if (fUIOK)
  1563. {
  1564. hr = ScopeEnumerate(hsiRoot, pFolder);
  1565. ASSERT(SUCCEEDED(hr));
  1566. if (FAILED(hr)) return;
  1567. }
  1568. }
  1569. }
  1570. /*
  1571. * AddRoot - Insert a CCategoryObject of the root folder into our Category map.
  1572. *
  1573. * History: a-jsari 11/20/97 Initial version
  1574. */
  1575. HRESULT CSystemInfoScope::AddRoot(HSCOPEITEM hsiRoot, CFolder **ppFolder)
  1576. {
  1577. ASSERT(ppFolder != NULL);
  1578. (*ppFolder) = pRootCategory();
  1579. ASSERT(*ppFolder != NULL);
  1580. if (*ppFolder == NULL) return E_FAIL;
  1581. // This object gets deleted in the mapCategories destructor
  1582. CViewObject *pvoData = new CCategoryObject(*ppFolder);
  1583. if (pvoData == NULL) ::AfxThrowMemoryException();
  1584. m_pmapCategories->InsertRoot(pvoData, hsiRoot);
  1585. return S_OK;
  1586. }
  1587. /*
  1588. * GetNamedChildFolder - Update strCategory to add the next backslash-
  1589. * delimited path element from strPath.
  1590. *
  1591. * History: a-jsari 12/17/97 Initial version
  1592. */
  1593. static inline void GetNamedChildFolder(
  1594. CString &strCategory,
  1595. const CString &strPath)
  1596. {
  1597. int iString;
  1598. CString strSubCategory;
  1599. CString strName;
  1600. // Remove the Category prefix from the path
  1601. iString = strPath.Find(strCategory);
  1602. ASSERT(iString == 0);
  1603. strSubCategory = strPath.Mid(iString + strCategory.GetLength() + 1);
  1604. // Remove the trailing categories
  1605. // (We'll deal with your rebel friends soon enough).
  1606. iString = strSubCategory.Find((TCHAR) '\\');
  1607. if (iString != -1)
  1608. strSubCategory = strSubCategory.Left(iString);
  1609. // Update the category to add the current category
  1610. strCategory += _T("\\");
  1611. strCategory += strSubCategory;
  1612. #if 0
  1613. // Turned out not to need this code.
  1614. // Find the Sub-folder with the name of the Sub-category.
  1615. pfNext = pfNext->GetChildNode();
  1616. do {
  1617. pfNext->GetName(szName);
  1618. if (szName == szSubCategory) break;
  1619. pfNext = pfNext->GetNextNode();
  1620. } while (pfNext != NULL);
  1621. ASSERT(pfNext != NULL);
  1622. #endif
  1623. }
  1624. //-----------------------------------------------------------------------------
  1625. // If were are currently refreshing, hang here until it's done.
  1626. //-----------------------------------------------------------------------------
  1627. void CSystemInfoScope::WaitForRefresh()
  1628. {
  1629. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1630. {
  1631. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1632. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  1633. pWBEMSource->m_pThreadRefresh->WaitForRefresh();
  1634. }
  1635. }
  1636. //-----------------------------------------------------------------------------
  1637. // Is an asynchronous refresh currently in progress?
  1638. //-----------------------------------------------------------------------------
  1639. BOOL CSystemInfoScope::InRefresh()
  1640. {
  1641. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1642. {
  1643. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1644. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  1645. return pWBEMSource->m_pThreadRefresh->IsRefreshing();
  1646. }
  1647. return FALSE;
  1648. }
  1649. /*
  1650. * SelectItem - Select the item pointed to by szPath
  1651. *
  1652. * History: a-jsari 12/11/97 Initial version
  1653. */
  1654. BOOL CSystemInfoScope::SelectItem(const CString &strPath, int iLine)
  1655. {
  1656. HSCOPEITEM hsiNode;
  1657. HRESULT hr;
  1658. // Get the named node from our internal list.
  1659. if (m_pmapCategories->ScopeFromName(strPath, hsiNode)) {
  1660. CFolder *pFolder = m_pmapCategories->CategoryFromScope(hsiNode);
  1661. pFolder->SetSelectedItem(iLine);
  1662. hr = pConsole()->SelectScopeItem(hsiNode);
  1663. ASSERT(hr == S_OK);
  1664. if (m_pLastSystemInfo)
  1665. m_pLastSystemInfo->SelectLine(iLine);
  1666. if (FAILED(hr)) return FALSE;
  1667. } else {
  1668. CString strCategory = strPath;
  1669. int iEnumerations = 0;
  1670. int iString;
  1671. // If the category isn't in our list, we need to enumerate all nodes
  1672. // leading up to it.
  1673. while (!m_pmapCategories->ScopeFromName(strCategory, hsiNode)) {
  1674. ++iEnumerations;
  1675. // Strip the last Category off the Path.
  1676. iString = strCategory.ReverseFind((TCHAR) '\\');
  1677. if (iString == -1) {
  1678. // If this fails, no nodes have been yet enumerated.
  1679. if (!m_pmapCategories->ScopeFromName(_T(""), hsiNode)) {
  1680. // --iEnumerations;
  1681. break;
  1682. }
  1683. } else {
  1684. strCategory = strCategory.Left(iString);
  1685. }
  1686. }
  1687. HRESULT hr;
  1688. // Enumerate all unenumerated nodes.
  1689. #if 0
  1690. // Commented out because InsertItem in ScopeEnumerate fails inexplicably.
  1691. CFolder *pfCurrent = pmapCategories->CategoryFromScope(hsiNode);
  1692. #endif
  1693. while (iEnumerations--) {
  1694. #if 0
  1695. hr = ScopeEnumerate(hsiNode, pfCurrent);
  1696. #else
  1697. hr = pConsole()->SelectScopeItem(hsiNode);
  1698. #endif
  1699. ASSERT(hr == S_OK);
  1700. if (FAILED(hr)) return FALSE;
  1701. GetNamedChildFolder(strCategory, strPath);
  1702. if (!m_pmapCategories->ScopeFromName(strCategory, hsiNode))
  1703. // The scope item we are searching for cannot be enumerated (The
  1704. // attempt to do so in SelectScopeItem has failed.) This can happen
  1705. // when we are connected to a remote computer which can't be accessed.
  1706. return FALSE;
  1707. }
  1708. CFolder *pFolder = m_pmapCategories->CategoryFromScope(hsiNode);
  1709. // Using this method of selecting a line because MMC won't
  1710. // just allow me to call GetItem.
  1711. pFolder->SetSelectedItem(iLine);
  1712. hr = pConsole()->SelectScopeItem(hsiNode);
  1713. if (m_pLastSystemInfo)
  1714. m_pLastSystemInfo->SelectLine(iLine);
  1715. ASSERT(hr == S_OK);
  1716. if (FAILED(hr)) return FALSE;
  1717. }
  1718. return TRUE;
  1719. }
  1720. /*
  1721. * ScopeEnumerate - Insert all categories of the given pFolder as namespace children
  1722. * of hsiNode.
  1723. *
  1724. * History: a-jsari 11/20/97 Initial version
  1725. */
  1726. HRESULT CSystemInfoScope::ScopeEnumerate(HSCOPEITEM hsiNode, CFolder *pFolder)
  1727. {
  1728. HRESULT hr = S_OK;
  1729. ASSERT(pFolder);
  1730. if (pFolder == NULL)
  1731. return hr;
  1732. SCOPEDATAITEM sdiNode;
  1733. sdiNode.mask = SDI_STR | SDI_PARAM | SDI_PARENT;
  1734. sdiNode.displayname = MMC_CALLBACK;
  1735. sdiNode.relativeID = hsiNode;
  1736. // If GetChildNode returned a NULL pointer, and this is the root node,
  1737. // then some sort of error must have occurred.
  1738. CFolder * pfolIterator = pFolder->GetChildNode();
  1739. if (pfolIterator == NULL && pFolder->GetParentNode() == NULL)
  1740. {
  1741. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1742. if (m_pSource && m_pSource->GetType() == CDataSource::GATHERER)
  1743. if (((CWBEMDataSource *)m_pSource)->m_pGatherer)
  1744. {
  1745. DWORD dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError();
  1746. if (dwError)
  1747. DisplayGatherError(dwError, (LPCTSTR)((CWBEMDataSource *)m_pSource)->m_strMachineName);
  1748. }
  1749. }
  1750. while (pfolIterator)
  1751. {
  1752. // This object gets deleted inthe mapCategories destructor.
  1753. CViewObject * pCategory = new CCategoryObject(pfolIterator);
  1754. ASSERT(pCategory != NULL);
  1755. if (pCategory == NULL)
  1756. return E_OUTOFMEMORY;
  1757. // If there are no children, modify the node we're inserting so
  1758. // we don't get a '+' sign next to the folder.
  1759. if (pfolIterator->GetChildNode() == NULL)
  1760. {
  1761. sdiNode.cChildren = 0;
  1762. sdiNode.mask |= SDI_CHILDREN;
  1763. }
  1764. else
  1765. {
  1766. sdiNode.cChildren = 1;
  1767. sdiNode.mask &= ~SDI_CHILDREN;
  1768. }
  1769. sdiNode.lParam = reinterpret_cast<LPARAM>(pCategory);
  1770. hr = pScope()->InsertItem(&sdiNode);
  1771. ASSERT(hr == S_OK);
  1772. if (FAILED(hr))
  1773. {
  1774. delete pCategory;
  1775. break;
  1776. }
  1777. pfolIterator->m_hsi = sdiNode.ID;
  1778. m_pmapCategories->Insert(pCategory, sdiNode.ID);
  1779. pfolIterator = pfolIterator->GetNextNode();
  1780. }
  1781. return hr;
  1782. }
  1783. /*
  1784. * AddExtensionRoot - If the snapin is loaded as an extension, create the root node.
  1785. *
  1786. * History: a-jsari 1/6/97 Initial version
  1787. */
  1788. HRESULT CSystemInfoScope::AddExtensionRoot(HSCOPEITEM &hsiNode, CFolder **pFolder)
  1789. {
  1790. SCOPEDATAITEM sdiNode;
  1791. HRESULT hrReturn;
  1792. CViewObject *pView;
  1793. ::memset(&sdiNode, 0, sizeof(sdiNode));
  1794. sdiNode.mask = SDI_STR | SDI_PARAM | SDI_PARENT | SDI_IMAGE | SDI_OPENIMAGE;
  1795. sdiNode.nImage = 0;
  1796. sdiNode.nOpenImage = 0;
  1797. sdiNode.displayname = MMC_CALLBACK;
  1798. sdiNode.relativeID = hsiNode;
  1799. pView = new CExtensionRootObject(pRootCategory());
  1800. ASSERT(pView != NULL);
  1801. if (pView == NULL) ::AfxThrowMemoryException();
  1802. m_RootCookie = sdiNode.lParam = reinterpret_cast<LPARAM>(pView);
  1803. hrReturn = pScope()->InsertItem(&sdiNode);
  1804. hsiNode = sdiNode.ID;
  1805. m_pmapCategories->InsertRoot(pView, hsiNode);
  1806. *pFolder = pRootCategory();
  1807. return hrReturn;
  1808. }
  1809. /*
  1810. * OnExpand - If fExpand is TRUE, expand the item pointed to by pDataObject,
  1811. * otherwise contract it. If expanding, enumerate children.
  1812. *
  1813. * History: a-jsari 9/25/97 Initial version
  1814. */
  1815. HRESULT CSystemInfoScope::OnExpand(LPDATAOBJECT pDataObject, LPARAM fExpand, HSCOPEITEM hsiNode)
  1816. {
  1817. CFolder *pfolSelection;
  1818. HRESULT hr;
  1819. // Log the expand event, so we know that the user clicked on a node.
  1820. if (msiLog.IsLogging(CMSInfoLog::CATEGORY))
  1821. {
  1822. CFolder * pFolder = m_pmapCategories->CategoryFromScope(hsiNode);
  1823. if (pFolder)
  1824. {
  1825. CString strName;
  1826. if (pFolder->GetName(strName))
  1827. msiLog.WriteLog(CMSInfoLog::CATEGORY, _T("CATEGORY \"%s\"\r\n"), strName);
  1828. }
  1829. }
  1830. // We have nothing to do if we are contracting a node.
  1831. // This never happens.
  1832. if (fExpand == 0) return S_OK;
  1833. // If our initialization failed, exit.
  1834. if (!m_bInitializedCD) return S_OK;
  1835. // Look up the CViewObject in our internal table based on our hsiNode value,
  1836. // and
  1837. // CHECK: Consider the memory leak potential in this map.
  1838. if ((pfolSelection = m_pmapCategories->CategoryFromScope(hsiNode)) == NULL) {
  1839. // If the expanded node isn't in our internal hash table, we should
  1840. // be looking at the root node, so get it.
  1841. if (IsPrimaryImpl() == FALSE) {
  1842. // If we are an extension . . .
  1843. FORMATETC fmtMachine = {
  1844. (CLIPFORMAT) CDataObject::m_cfMachineName,
  1845. NULL,
  1846. DVASPECT_CONTENT,
  1847. TYMED_HGLOBAL
  1848. };
  1849. STGMEDIUM stgMachine;
  1850. stgMachine.tymed = TYMED_HGLOBAL;
  1851. stgMachine.hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, (MAX_PATH + 1)* sizeof(WCHAR));
  1852. stgMachine.pUnkForRelease = NULL;
  1853. // Only look externally for the machine when we are an extension.
  1854. hr = pDataObject->GetDataHere(&fmtMachine, &stgMachine);
  1855. if (hr == S_OK) {
  1856. USES_CONVERSION;
  1857. CString strMachine = W2T((LPWSTR)::GlobalLock(stgMachine.hGlobal));
  1858. ::GlobalUnlock(stgMachine.hGlobal);
  1859. HGLOBAL hGlobal = ::GlobalFree(stgMachine.hGlobal);
  1860. ASSERT(hGlobal == NULL);
  1861. SetMachine(strMachine);
  1862. } else
  1863. ASSERT(hr == DV_E_FORMATETC);
  1864. hr = AddExtensionRoot(hsiNode, &pfolSelection);
  1865. ASSERT(SUCCEEDED(hr));
  1866. return hr;
  1867. } else {
  1868. hr = AddRoot(hsiNode, &pfolSelection);
  1869. ASSERT(SUCCEEDED(hr));
  1870. if (FAILED(hr)) return hr;
  1871. }
  1872. }
  1873. return ScopeEnumerate(hsiNode, pfolSelection);
  1874. }
  1875. /*
  1876. * OnProperties - Called when a property value changes.
  1877. *
  1878. * History: a-jsari 9/25/97 Initial version.
  1879. */
  1880. HRESULT CSystemInfoScope::OnProperties(LPARAM)
  1881. {
  1882. DWORD dwError = 0;
  1883. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1884. if (m_pSource && m_pSource->GetType() == CDataSource::GATHERER)
  1885. {
  1886. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  1887. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  1888. pWBEMSource->m_pThreadRefresh->CancelRefresh();
  1889. if (m_strLastMachineName.CompareNoCase((LPCTSTR) *m_pstrMachineName) != 0)
  1890. {
  1891. // Try to connect to the new machine. If the connection fails, display
  1892. // an appropriate error message and restore the machine name to the
  1893. // original string.
  1894. if (((CWBEMDataSource *)m_pSource)->m_pGatherer->SetConnect(*m_pstrMachineName))
  1895. {
  1896. if (NULL == ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetProvider())
  1897. dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError();
  1898. }
  1899. else
  1900. dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError();
  1901. if (dwError)
  1902. {
  1903. // Display the error, and reset the machine name and the data source
  1904. // to the previous known good name.
  1905. DisplayGatherError(dwError, (LPCTSTR) *m_pstrMachineName);
  1906. *m_pstrMachineName = m_strLastMachineName;
  1907. ((CWBEMDataSource *)m_pSource)->m_pGatherer->SetConnect(*m_pstrMachineName);
  1908. ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetProvider();
  1909. RefreshAsync(m_pfLast, m_pLastSystemInfo, FALSE);
  1910. }
  1911. else
  1912. {
  1913. if (pSource() != NULL)
  1914. SetMachine(*m_pstrMachineName);
  1915. }
  1916. }
  1917. // This doesn't really seem necessary...
  1918. // if (m_pfLast && pConsole())
  1919. // pConsole()->SelectScopeItem(m_pfLast->m_hsi);
  1920. }
  1921. return S_OK;
  1922. }
  1923. //-----------------------------------------------------------------------------
  1924. // DisplayGatherError
  1925. //
  1926. // There are multiple places we need to display a connection error to the user,
  1927. // so the functionality is gathered here.
  1928. //-----------------------------------------------------------------------------
  1929. void CSystemInfoScope::DisplayGatherError(DWORD dwError, LPCTSTR szMachineName)
  1930. {
  1931. CString strMachine, strErrorMessage;
  1932. if (!dwError)
  1933. return;
  1934. if (szMachineName)
  1935. strMachine = CString(szMachineName);
  1936. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1937. if (strMachine.IsEmpty())
  1938. strMachine.LoadString(IDS_LOCALCOMPLABEL);
  1939. switch (dwError)
  1940. {
  1941. case GATH_ERR_ALLOCATIONFAILED:
  1942. case GATH_ERR_NOWBEMOUTOFMEM:
  1943. strErrorMessage.LoadString(IDS_OUTOFMEMERROR);
  1944. break;
  1945. case GATH_ERR_NOWBEMLOCATOR:
  1946. strErrorMessage.LoadString(IDS_NOLOCATOR);
  1947. break;
  1948. case GATH_ERR_NOWBEMCONNECT:
  1949. strErrorMessage.Format(IDS_NOGATHERER, strMachine);
  1950. break;
  1951. case GATH_ERR_NOWBEMACCESSDENIED:
  1952. strErrorMessage.Format(IDS_GATHERACCESS, strMachine);
  1953. break;
  1954. case GATH_ERR_NOWBEMBADSERVER:
  1955. strErrorMessage.Format(IDS_BADSERVER, strMachine);
  1956. break;
  1957. case GATH_ERR_NOWBEMNETWORKFAILURE:
  1958. strErrorMessage.Format(IDS_NETWORKERROR, strMachine);
  1959. break;
  1960. case GATH_ERR_BADCATEGORYID:
  1961. strErrorMessage.LoadString(IDS_UNEXPECTED);
  1962. break;
  1963. default:
  1964. ASSERT(FALSE);
  1965. strErrorMessage.LoadString(IDS_UNEXPECTED);
  1966. break;
  1967. }
  1968. MessageBox(strErrorMessage);
  1969. }
  1970. /*
  1971. * MachineName - Return the current connected machine as a LPCSTR.
  1972. *
  1973. * History: a-jsari 11/12/97 Initial version.
  1974. */
  1975. LPCTSTR CSystemInfoScope::MachineName() const
  1976. {
  1977. if (m_pstrMachineName == NULL || m_pstrMachineName->GetLength() == 0) return NULL;
  1978. return (LPCTSTR)(*m_pstrMachineName)+2; // +2 to skip over the initial "\\"
  1979. }
  1980. /*
  1981. * SetSelectedFolder - Remember the last selected folder for context-
  1982. * sensitive operations (i.e. Print, Report, Find)
  1983. *
  1984. * History: a-jsari 2/12/98 Initial version
  1985. */
  1986. void CSystemInfoScope::SetSelectedFolder(CFolder *pFolder)
  1987. {
  1988. m_pfLast = pFolder;
  1989. if (pSource() != NULL)
  1990. pSource()->SetLastFolder(pFolder);
  1991. }
  1992. //-----------------------------------------------------------------------------
  1993. // Start an async refresh of the specified folder.
  1994. //-----------------------------------------------------------------------------
  1995. void CSystemInfoScope::RefreshAsync(CFolder * pFolder, CSystemInfo * pSystemInfo, BOOL fSoftRefresh)
  1996. {
  1997. if (pSource() && pSource()->GetType() == CDataSource::GATHERER)
  1998. {
  1999. CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
  2000. if (pWBEMSource && pWBEMSource->m_pThreadRefresh)
  2001. pWBEMSource->m_pThreadRefresh->RefreshFolderAsync(pFolder, pSystemInfo, FALSE, fSoftRefresh);
  2002. }
  2003. }