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.

2732 lines
79 KiB

  1. //=============================================================================
  2. // MSInfo.cpp : Implementation of CMSInfo
  3. //
  4. // Contains implementation for some of the functions in the CMSInfo class
  5. // (the ones which aren't inline).
  6. //=============================================================================
  7. #include "stdafx.h"
  8. #include "Msinfo32.h"
  9. #include "MSInfo.h"
  10. #include "cabfunc.h"
  11. #include "msictrl.h"
  12. #include "MSInfo4Category.h"
  13. #include "remotedialog.h"
  14. #include "filestuff.h"
  15. //a-kjaw
  16. #include "dataset.h"
  17. //a-kjaw
  18. WNDPROC CMSInfo::m_wndprocParent = NULL;
  19. CMSInfo * CMSInfo::m_pControl = NULL;
  20. extern CMSInfoHistoryCategory catHistorySystemSummary;
  21. extern CMSInfoHistoryCategory catHistoryResources;
  22. extern CMSInfoHistoryCategory catHistoryComponents;
  23. extern CMSInfoHistoryCategory catHistorySWEnv;
  24. //=========================================================================
  25. // Here's a very simple class to show a message when the data is
  26. // being refreshed.
  27. //=========================================================================
  28. class CWaitForRefreshDialog : public CDialogImpl<CWaitForRefreshDialog>
  29. {
  30. public:
  31. enum { IDD = IDD_WAITFORREFRESHDIALOG };
  32. //-------------------------------------------------------------------------
  33. // Refresh the specified category using the specified source.
  34. //-------------------------------------------------------------------------
  35. int DoRefresh(CLiveDataSource * pSource, CMSInfoLiveCategory * pLiveCategory)
  36. {
  37. m_pSource = pSource;
  38. m_pLiveCategory = pLiveCategory;
  39. m_nCategories = pLiveCategory->GetCategoryCount();
  40. if (m_nCategories == 0) m_nCategories = 1; // should never happen
  41. return (int)DoModal();
  42. };
  43. //-------------------------------------------------------------------------
  44. // When the dialog initializes, the source and category pointers should
  45. // have already been set. Start the refresh and create a timer to control
  46. // the update of information on the dialog. The timer is set to 500ms.
  47. //-------------------------------------------------------------------------
  48. LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  49. {
  50. if (m_pSource && m_pSource->m_pThread && m_pLiveCategory)
  51. m_pSource->m_pThread->StartRefresh(m_pLiveCategory, TRUE);
  52. m_iTimer = (UINT)SetTimer(1, 500);
  53. return 0;
  54. }
  55. //-------------------------------------------------------------------------
  56. // Every time the timer fires, check to see if the refresh is done. If
  57. // it is, close the dialog. Otherwise, update the progress bar and
  58. // refreshing category string.
  59. //-------------------------------------------------------------------------
  60. LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  61. {
  62. if (m_pSource == NULL)
  63. return 0;
  64. if (!m_pSource->m_pThread->IsRefreshing())
  65. {
  66. KillTimer(m_iTimer);
  67. EndDialog(0);
  68. return 0;
  69. }
  70. CString strCurrent;
  71. LONG nCount;
  72. m_pSource->m_pThread->GetRefreshStatus(&nCount, &strCurrent);
  73. if (nCount > 0) nCount -= 1; // this number is incremented before the refresh is complete
  74. UpdateProgress((nCount * 100) / m_nCategories, strCurrent);
  75. return 0;
  76. }
  77. //-------------------------------------------------------------------------
  78. // Update the percentage complete and the refreshing category name.
  79. //-------------------------------------------------------------------------
  80. void UpdateProgress(int iPercent, const CString & strCurrent = _T(""))
  81. {
  82. HWND hwnd = GetDlgItem(IDC_REFRESHPROGRESS);
  83. if (hwnd != NULL)
  84. {
  85. if (iPercent < 0)
  86. iPercent = 0;
  87. if (iPercent > 100)
  88. iPercent = 100;
  89. ::SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  90. ::SendMessage(hwnd, PBM_SETPOS, iPercent, 0);
  91. }
  92. if (!strCurrent.IsEmpty())
  93. {
  94. hwnd = GetDlgItem(IDC_REFRESHCAT);
  95. if (hwnd != NULL)
  96. ::SetWindowText(hwnd, strCurrent);
  97. }
  98. }
  99. private:
  100. CLiveDataSource * m_pSource;
  101. CMSInfoLiveCategory * m_pLiveCategory;
  102. int m_nCategories;
  103. UINT m_iTimer;
  104. BEGIN_MSG_MAP(CWaitForRefreshDialog)
  105. MESSAGE_HANDLER(WM_TIMER, OnTimer)
  106. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  107. END_MSG_MAP()
  108. };
  109. UINT HistoryRefreshDlgThreadProc( LPVOID pParam )
  110. {
  111. CMSInfo* pInfo = (CMSInfo*) pParam;
  112. if (WAIT_OBJECT_0 != WaitForSingleObject(pInfo->m_hEvtHistoryComplete,60*60*10/*10 minutes*/))
  113. {
  114. ASSERT(0 && "Wait Abandoned or timed out");
  115. }
  116. pInfo->m_HistoryProgressDlg.EndDialog(MB_OK);//use if dlg was create with DoModal()
  117. return 0;
  118. }
  119. //=========================================================================
  120. // Dispatch a command from the user (such as a menu bar selection).
  121. //=========================================================================
  122. BOOL CMSInfo::DispatchCommand(int iCommand)
  123. {
  124. BOOL fHandledCommand = TRUE;
  125. // Can't do any command while the find is in progress.
  126. CancelFind();
  127. // Before we execute a command, make sure that any refreshes currently
  128. // in progress are finished.
  129. CMSInfoCategory * pCategory = GetCurrentCategory();
  130. if (pCategory && pCategory->GetDataSourceType() == LIVE_DATA)
  131. {
  132. CLiveDataSource * pLiveDataSource = (CLiveDataSource *) m_pCurrData;
  133. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  134. pLiveDataSource->WaitForRefresh();
  135. ::SetCursor(hc);
  136. }
  137. // Check to see if the selected command is a tool that we added to the
  138. // tools menu.
  139. CMSInfoTool * pTool;
  140. if (m_mapIDToTool.Lookup((WORD) iCommand, (void * &) pTool))
  141. {
  142. ASSERT(pTool);
  143. if (pTool)
  144. pTool->Execute();
  145. return TRUE;
  146. }
  147. switch (iCommand)
  148. {
  149. case ID_FILE_OPENNFO:
  150. if (m_fFindVisible)
  151. DispatchCommand(ID_EDIT_FIND);
  152. OpenNFO();
  153. break;
  154. case ID_FILE_SAVENFO:
  155. SaveNFO();
  156. break;
  157. case ID_FILE_CLOSE:
  158. if (m_fFindVisible)
  159. DispatchCommand(ID_EDIT_FIND);
  160. CloseFile();
  161. break;
  162. case ID_FILE_EXPORT:
  163. Export();
  164. break;
  165. case ID_FILE_PRINT:
  166. DoPrint();
  167. break;
  168. case ID_FILE_EXIT:
  169. if (NULL != m_hwndParent)
  170. ::PostMessage(m_hwndParent, WM_CLOSE, 0, 0);
  171. break;
  172. case ID_EDIT_COPY:
  173. EditCopy();
  174. break;
  175. case ID_EDIT_PASTE:
  176. if (GetFocus() == m_wndFindWhat.m_hWnd && m_wndFindWhat.IsWindowVisible() && m_wndFindWhat.IsWindowEnabled())
  177. {
  178. BOOL fHandled = FALSE;
  179. if (::OpenClipboard(m_hWnd))
  180. {
  181. if (::IsClipboardFormatAvailable(CF_UNICODETEXT))
  182. {
  183. HANDLE h = ::GetClipboardData(CF_UNICODETEXT);
  184. if (h != NULL)
  185. {
  186. LPWSTR szData = (LPWSTR)GlobalLock(h);
  187. if (szData != NULL)
  188. {
  189. // If the user tries to paste a tab character, replace it with spaces.
  190. CString strTemp(szData);
  191. if (strTemp.Find(_T('\t')) != -1)
  192. strTemp.Replace(_T('\t'), _T(' '));
  193. SETTEXTEX st;
  194. st.flags = ST_SELECTION;
  195. st.codepage = 1200; // Unicode
  196. m_wndFindWhat.SendMessage(EM_SETTEXTEX, (WPARAM)&st, (LPARAM)(LPCTSTR)strTemp);
  197. fHandled = TRUE;
  198. GlobalUnlock(h);
  199. }
  200. }
  201. }
  202. ::CloseClipboard();
  203. }
  204. if (!fHandled)
  205. m_wndFindWhat.SendMessage(WM_PASTE);
  206. }
  207. break;
  208. case ID_EDIT_SELECTALL:
  209. EditSelectAll();
  210. break;
  211. case ID_EDIT_FIND:
  212. m_fFindVisible = !m_fFindVisible;
  213. m_fFindNext = FALSE;
  214. m_pcatFind = NULL;
  215. ShowFindControls();
  216. LayoutControl();
  217. SetMenuItems();
  218. UpdateFindControls();
  219. if (m_fFindVisible)
  220. GotoDlgCtrl(m_wndFindWhat.m_hWnd);
  221. break;
  222. case ID_VIEW_REFRESH:
  223. MSInfoRefresh();
  224. break;
  225. case ID_VIEW_BASIC:
  226. if (m_fAdvanced)
  227. {
  228. m_fAdvanced = FALSE;
  229. RefillListView(FALSE);
  230. SetMenuItems();
  231. }
  232. break;
  233. case ID_VIEW_ADVANCED:
  234. if (!m_fAdvanced)
  235. {
  236. m_fAdvanced = TRUE;
  237. RefillListView(FALSE);
  238. SetMenuItems();
  239. }
  240. break;
  241. case ID_VIEW_REMOTE_COMPUTER:
  242. ShowRemoteDialog();
  243. break;
  244. case ID_VIEW_CURRENT:
  245. case ID_VIEW_HISTORY:
  246. {
  247. int iShow = (iCommand == ID_VIEW_HISTORY) ? SW_SHOW : SW_HIDE;
  248. /* v-stlowe 2/27/2001:
  249. problem: if history was loaded from file after combo has been populated,
  250. combo doesn't get updated. So update each time we switch to history view
  251. if (iCommand == ID_VIEW_HISTORY && m_history.SendMessage(CB_GETCURSEL, 0, 0) == CB_ERR)
  252. */
  253. if (iCommand == ID_VIEW_HISTORY)
  254. FillHistoryCombo();
  255. //v-stlowe 3/04/2001
  256. //if (!this->m_pHistoryStream)
  257. //{
  258. if (this->m_pDCO && !((CLiveDataSource *)m_pLiveData)->GetXMLDoc() && ID_VIEW_HISTORY == iCommand)
  259. {
  260. VERIFY(m_pDCO && "NULL datacollection object");
  261. if (m_pDCO)
  262. {
  263. HRESULT hr;
  264. HWND hWnd = m_HistoryProgressDlg.GetDlgItem(IDC_PROGRESS1);
  265. if(::IsWindow(hWnd))
  266. {
  267. ::SendMessage(hWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  268. ::SendMessage(hWnd,PBM_SETPOS,0,0);
  269. ::SendMessage(hWnd, PBM_DELTAPOS, 0, 0L);
  270. }
  271. m_pDCO->ExecuteAsync();
  272. //m_HistoryProgressDlg.Create(m_hWnd);
  273. ResetEvent(m_hEvtHistoryComplete);
  274. AfxBeginThread((AFX_THREADPROC) HistoryRefreshDlgThreadProc,this);
  275. m_HistoryProgressDlg.DoModal(m_hWnd);
  276. }
  277. }
  278. else
  279. {
  280. }
  281. //end v-stlowe 12/17/00
  282. m_history.ShowWindow(iShow);
  283. m_historylabel.ShowWindow(iShow);
  284. LayoutControl();
  285. HTREEITEM htiToSelect = NULL;
  286. if (iCommand == ID_VIEW_HISTORY)
  287. {
  288. m_pLastCurrentCategory = GetCurrentCategory();
  289. int iIndex = (int)m_history.SendMessage(CB_GETCURSEL, 0, 0);
  290. if (iIndex == CB_ERR)
  291. {
  292. iIndex = 0;
  293. m_history.SendMessage(CB_SETCURSEL, (WPARAM)iIndex, 0);
  294. }
  295. ChangeHistoryView(iIndex);
  296. // Select the appropriate history category based on the current info category.
  297. CMSInfoHistoryCategory * pHistoryCat = NULL;
  298. CString strName;
  299. m_pLastCurrentCategory->GetNames(NULL, &strName);
  300. if (!strName.IsEmpty())
  301. {
  302. // This is a little kludgy:
  303. //todo: append file name if XML stream was opened from a file
  304. if (strName.Left(13) == CString(_T("SystemSummary")))
  305. pHistoryCat = &catHistorySystemSummary;
  306. else if (strName.Left(9) == CString(_T("Resources")))
  307. pHistoryCat = &catHistoryResources;
  308. else if (strName.Left(10) == CString(_T("Components")))
  309. pHistoryCat = &catHistoryComponents;
  310. else if (strName.Left(5) == CString(_T("SWEnv")))
  311. pHistoryCat = &catHistorySWEnv;
  312. }
  313. if (pHistoryCat)
  314. htiToSelect = pHistoryCat->GetHTREEITEM();
  315. }
  316. else
  317. {
  318. ChangeHistoryView(-1);
  319. // Changing to always select the system summary category when
  320. // switching back from history view.
  321. //
  322. // if (m_pLastCurrentCategory)
  323. // htiToSelect = m_pLastCurrentCategory->GetHTREEITEM();
  324. htiToSelect = TreeView_GetRoot(m_tree.m_hWnd);
  325. }
  326. if (htiToSelect != NULL)
  327. {
  328. TreeView_EnsureVisible(m_tree.m_hWnd, htiToSelect);
  329. TreeView_SelectItem(m_tree.m_hWnd, htiToSelect);
  330. }
  331. SetMenuItems();
  332. }
  333. break;
  334. case ID_TOOLS_PLACEHOLDER:
  335. break;
  336. case ID_HELP_ABOUT:
  337. {
  338. CSimpleDialog<IDD_ABOUTBOX> dlg;
  339. dlg.DoModal();
  340. }
  341. break;
  342. case ID_HELP_CONTENTS:
  343. ::HtmlHelp(m_hWnd, _T("msinfo32.chm"), HH_DISPLAY_TOPIC, 0);
  344. break;
  345. case ID_HELP_TOPIC:
  346. ShowCategoryHelp(GetCurrentCategory());
  347. break;
  348. default:
  349. fHandledCommand = FALSE;
  350. break;
  351. }
  352. return fHandledCommand;
  353. }
  354. //=========================================================================
  355. // Called to allow the user to remote to a different computer.
  356. //=========================================================================
  357. void CMSInfo::ShowRemoteDialog()
  358. {
  359. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  360. CRemoteDialog dlg;
  361. dlg.SetRemoteDialogValues(m_hWnd, !m_strMachine.IsEmpty(), m_strMachine);
  362. if (dlg.DoModal() == IDOK)
  363. {
  364. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  365. CString strMachine;
  366. BOOL fRemote;
  367. dlg.GetRemoteDialogValues(&fRemote, &strMachine);
  368. if (!fRemote)
  369. strMachine.Empty();
  370. if (strMachine.CompareNoCase(m_strMachine) != 0)
  371. DoRemote(strMachine);
  372. ::SetCursor(hc);
  373. }
  374. }
  375. void CMSInfo::DoRemote(LPCTSTR szMachine)
  376. {
  377. CString strMachine(szMachine);
  378. // The user has changed the machine name. We need to recreate the
  379. // current data source object with the new machine name. Also, make
  380. // sure we aren't showing history data.
  381. if (m_history.IsWindowVisible())
  382. DispatchCommand(ID_VIEW_CURRENT);
  383. CLiveDataSource * pLiveData = new CLiveDataSource;
  384. if (pLiveData)
  385. {
  386. HRESULT hr = pLiveData->Create(strMachine, m_hWnd, m_strCategories);
  387. if (FAILED(hr))
  388. {
  389. // bad news, report an error
  390. delete pLiveData;
  391. }
  392. else
  393. {
  394. // Check to see if the pLiveData works. If it doesn't (for example,
  395. // if it's to a non-existent machine), don't change the data source.
  396. HRESULT hr = pLiveData->ValidDataSource();
  397. if (SUCCEEDED(hr))
  398. {
  399. pLiveData->m_pHistoryStream = ((CLiveDataSource *)m_pLiveData)->m_pHistoryStream;
  400. pLiveData->m_pXMLDoc = ((CLiveDataSource *)m_pLiveData)->m_pXMLDoc;
  401. if (m_pLiveData)
  402. delete m_pLiveData;
  403. m_pLiveData = pLiveData;
  404. m_strMachine = strMachine;
  405. SelectDataSource(m_pLiveData);
  406. }
  407. else
  408. {
  409. // Report the error for the bad connection.
  410. CString strMessage;
  411. if (strMachine.IsEmpty())
  412. strMessage.LoadString(IDS_REMOTEERRORLOCAL);
  413. else
  414. strMessage.Format(IDS_REMOTEERRORREMOTE, strMachine);
  415. MSInfoMessageBox(strMessage);
  416. delete pLiveData;
  417. }
  418. }
  419. }
  420. else
  421. {
  422. // bad news - no memory
  423. }
  424. }
  425. //=========================================================================
  426. // Functions for managing the displayed data.
  427. //=========================================================================
  428. void CMSInfo::SelectDataSource(CDataSource * pDataSource)
  429. {
  430. ASSERT(pDataSource);
  431. if (pDataSource == NULL || m_pCurrData == pDataSource)
  432. return;
  433. m_pCurrData = pDataSource;
  434. m_pCategory = NULL;
  435. // Clear the existing categories in the tree.
  436. TreeClearItems();
  437. // Load the contents of the tree from the data source.
  438. CMSInfoCategory * pRoot = m_pCurrData->GetRootCategory();
  439. if (pRoot)
  440. {
  441. BuildTree(TVI_ROOT, TVI_LAST, pRoot);
  442. TreeView_Expand(m_tree.m_hWnd, TreeView_GetRoot(m_tree.m_hWnd), TVE_EXPAND);
  443. TreeView_SelectItem(m_tree.m_hWnd, TreeView_GetRoot(m_tree.m_hWnd));
  444. }
  445. SetMenuItems();
  446. }
  447. //-------------------------------------------------------------------------
  448. // Select the specified category.
  449. //
  450. // TBD - better to check columns for being the same
  451. //-------------------------------------------------------------------------
  452. void CMSInfo::SelectCategory(CMSInfoCategory * pCategory, BOOL fRefreshDataOnly)
  453. {
  454. ASSERT(pCategory);
  455. if (pCategory == NULL) return;
  456. // If there's a currently selected category, save some information
  457. // for it (such as the widths of the columns that the user might
  458. // have changed).
  459. if (m_pCategory && !fRefreshDataOnly && m_pCategory->GetDataSourceType() != NFO_410)
  460. {
  461. int iWidth;
  462. ASSERT(m_iCategoryColNumberLen <= 64);
  463. for (int iListViewCol = 0; iListViewCol < m_iCategoryColNumberLen; iListViewCol++)
  464. {
  465. iWidth = ListView_GetColumnWidth(m_list.m_hWnd, iListViewCol);
  466. m_pCategory->SetColumnWidth(m_aiCategoryColNumber[iListViewCol], iWidth);
  467. }
  468. }
  469. ListClearItems();
  470. if (!fRefreshDataOnly && pCategory && pCategory->GetDataSourceType() != NFO_410)
  471. {
  472. ListClearColumns();
  473. m_iCategoryColNumberLen = 0;
  474. int iColCount;
  475. if (pCategory->GetCategoryDimensions(&iColCount, NULL))
  476. {
  477. CString strCaption;
  478. UINT uiWidth;
  479. int iListViewCol = 0;
  480. for (int iCategoryCol = 0; iCategoryCol < iColCount; iCategoryCol++)
  481. {
  482. if (!m_fAdvanced && pCategory->IsColumnAdvanced(iCategoryCol))
  483. continue;
  484. if (pCategory->GetColumnInfo(iCategoryCol, &strCaption, &uiWidth, NULL, NULL)) // TBD - faster to return reference to string
  485. {
  486. // Save what the actual column number (for the category) was.
  487. ASSERT(iListViewCol < 64);
  488. m_aiCategoryColNumber[iListViewCol] = iCategoryCol;
  489. ListInsertColumn(iListViewCol++, (int)uiWidth, strCaption);
  490. m_iCategoryColNumberLen = iListViewCol;
  491. }
  492. }
  493. }
  494. }
  495. // If the currently displayed category is from a 4.10 NFO file, and we're showing a
  496. // new category, then hide the existing category.
  497. if (m_pCategory && m_pCategory != pCategory && m_pCategory->GetDataSourceType() == NFO_410)
  498. ((CMSInfo4Category *) m_pCategory)->ShowControl(m_hWnd, this->GetOCXRect(), FALSE);
  499. // Save the currently displayed category.
  500. m_pCategory = pCategory;
  501. // If this is live data and has never been refreshed, refresh and return.
  502. // Refresh will send a message causing this function to be executed again.
  503. if (pCategory->GetDataSourceType() == LIVE_DATA)
  504. {
  505. CMSInfoLiveCategory * pLiveCategory = (CMSInfoLiveCategory *) pCategory;
  506. if (!pLiveCategory->EverBeenRefreshed())
  507. {
  508. SetMessage((m_history.IsWindowVisible()) ? IDS_REFRESHHISTORYMESSAGE : IDS_REFRESHMESSAGE, 0, TRUE);
  509. CLiveDataSource * pLiveDataSource = (CLiveDataSource *) m_pCurrData;
  510. if (pLiveDataSource->InRefresh())
  511. {
  512. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  513. pLiveCategory->Refresh((CLiveDataSource *) m_pCurrData, FALSE);
  514. ::SetCursor(hc);
  515. }
  516. else
  517. pLiveCategory->Refresh((CLiveDataSource *) m_pCurrData, FALSE);
  518. return;
  519. }
  520. }
  521. else if (pCategory->GetDataSourceType() == NFO_410)
  522. {
  523. this->m_list.ShowWindow(SW_HIDE);
  524. CMSInfo4Category * p4Cat = (CMSInfo4Category *) pCategory;
  525. if (!p4Cat->IsDisplayableCategory())
  526. SetMessage(IDS_SELECTCATEGORY, 0, TRUE);
  527. else if (FAILED(p4Cat->ShowControl(m_hWnd,this->GetOCXRect())))
  528. SetMessage(IDS_NOOCX, IDS_NOOCXDETAIL, TRUE);
  529. return;
  530. }
  531. else if (pCategory->GetDataSourceType() == XML_SNAPSHOT)
  532. {
  533. ((CXMLSnapshotCategory*)pCategory)->Refresh((CXMLDataSource*) m_pCurrData, FALSE);
  534. CMSInfoLiveCategory * pLiveCategory = (CMSInfoLiveCategory *) pCategory;
  535. // Any category that has children (besides the root category) doesn't display
  536. // information. So put up a message to that effect.
  537. if (pLiveCategory->GetFirstChild() != NULL && pLiveCategory->GetParent() != NULL)
  538. {
  539. SetMessage(IDS_SELECTCATEGORY, 0, TRUE);
  540. return;
  541. }
  542. else if (!pLiveCategory->EverBeenRefreshed())
  543. {
  544. SetMessage((m_history.IsWindowVisible()) ? IDS_REFRESHHISTORYMESSAGE : IDS_REFRESHMESSAGE, 0, TRUE);
  545. return;
  546. }
  547. }
  548. // Set the columns and fill the rows with the data for this category.
  549. // Note, if this is live data we need to lock it (so we don't have
  550. // a threading problem with the refresh).
  551. CLiveDataSource * pLiveDataSource = NULL;
  552. if (pCategory->GetDataSourceType() == LIVE_DATA)
  553. pLiveDataSource = (CLiveDataSource *) m_pCurrData;
  554. if (pLiveDataSource)
  555. pLiveDataSource->LockData();
  556. if (SUCCEEDED(pCategory->GetHRESULT()))
  557. {
  558. int iColCount, iRowCount;
  559. if (pCategory->GetCategoryDimensions(&iColCount, &iRowCount))
  560. {
  561. CString * pstrData , strCaption , cstring;
  562. DWORD dwData;
  563. int iListViewCol, iListViewRow = 0;
  564. for (int iCategoryRow = 0; iCategoryRow < iRowCount; iCategoryRow++)
  565. {
  566. if (!m_fAdvanced && pCategory->IsRowAdvanced(iCategoryRow))
  567. continue;
  568. iListViewCol = 0;
  569. for (int iCategoryCol = 0; iCategoryCol < iColCount; iCategoryCol++)
  570. {
  571. if (!m_fAdvanced && pCategory->IsColumnAdvanced(iCategoryCol))
  572. continue;
  573. if (pCategory->GetData(iCategoryRow, iCategoryCol, &pstrData, &dwData))
  574. {
  575. //a-kjaw
  576. if(pstrData->IsEmpty())
  577. {
  578. pCategory->GetColumnInfo(iCategoryCol, &strCaption, NULL , NULL, NULL);
  579. cstring.LoadString(IDS_SERVERNAME);
  580. if( strCaption == cstring )
  581. pstrData->LoadString(IDS_LOCALSERVER);
  582. }
  583. //a-kjaw
  584. ListInsertItem(iListViewRow, iListViewCol++, *pstrData, iCategoryRow);
  585. }
  586. }
  587. iListViewRow += 1;
  588. }
  589. }
  590. // Return the sorting to how it was last set.
  591. if (pCategory->m_iSortColumn != -1)
  592. ListView_SortItems(m_list.m_hWnd, (PFNLVCOMPARE) ListSortFunc, (LPARAM) pCategory);
  593. if (iColCount == 0 || (iRowCount == 0 && pCategory->GetFirstChild() != NULL))
  594. SetMessage(IDS_SELECTCATEGORY, 0, TRUE);
  595. else
  596. SetMessage(0);
  597. }
  598. else
  599. {
  600. // The HRESULT for this category indicates some sort of failure. We should display
  601. // an error message instead of the list view.
  602. CString strTitle, strMessage;
  603. pCategory->GetErrorText(&strTitle, &strMessage);
  604. SetMessage(strTitle, strMessage, TRUE);
  605. }
  606. if (pLiveDataSource)
  607. pLiveDataSource->UnlockData();
  608. SetMenuItems();
  609. }
  610. //-------------------------------------------------------------------------
  611. // Get the currently selected category.
  612. //-------------------------------------------------------------------------
  613. CMSInfoCategory * CMSInfo::GetCurrentCategory()
  614. {
  615. HTREEITEM hti = TreeView_GetSelection(m_tree.m_hWnd);
  616. if (hti)
  617. {
  618. TVITEM tvi;
  619. tvi.mask = TVIF_PARAM;
  620. tvi.hItem = hti;
  621. if (TreeView_GetItem(m_tree.m_hWnd, &tvi))
  622. {
  623. ASSERT(tvi.lParam);
  624. ASSERT(tvi.lParam == (LPARAM)m_pCategory);
  625. return (CMSInfoCategory *) tvi.lParam;
  626. }
  627. }
  628. return NULL;
  629. }
  630. //-------------------------------------------------------------------------
  631. // Refresh the displayed data.
  632. //-------------------------------------------------------------------------
  633. void CMSInfo::MSInfoRefresh()
  634. {
  635. CMSInfoCategory * pCategory = GetCurrentCategory();
  636. if (pCategory && pCategory->GetDataSourceType() == LIVE_DATA)
  637. {
  638. CMSInfoLiveCategory * pLiveCategory = (CMSInfoLiveCategory *)pCategory;
  639. ListClearItems();
  640. SetMessage(IDS_REFRESHMESSAGE);
  641. pLiveCategory->Refresh((CLiveDataSource *) m_pCurrData, FALSE);
  642. }
  643. else if (pCategory && pCategory->GetDataSourceType() == NFO_410)
  644. {
  645. CMSInfo4Category* p4Category = (CMSInfo4Category*) pCategory;
  646. p4Category->Refresh();
  647. }
  648. }
  649. //-------------------------------------------------------------------------
  650. // Present the user with a dialog box to select a file to open.
  651. //-------------------------------------------------------------------------
  652. void CMSInfo::OpenNFO()
  653. {
  654. // Display the dialog box and let the user select a file.
  655. TCHAR szBuffer[MAX_PATH] = _T("");
  656. TCHAR szFilter[MAX_PATH];
  657. TCHAR szDefaultExtension[4];
  658. ::LoadString(_Module.GetResourceInstance(), IDS_OPENFILTER, szFilter, MAX_PATH);
  659. ::LoadString(_Module.GetResourceInstance(), IDS_DEFAULTEXTENSION, szDefaultExtension, 4);
  660. for (int i = 0; szFilter[i]; i++)
  661. if (szFilter[i] == _T('|'))
  662. szFilter[i] = _T('\0');
  663. OPENFILENAME ofn;
  664. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  665. ofn.lStructSize = sizeof(OPENFILENAME);
  666. ofn.hwndOwner = m_hWnd;
  667. ofn.lpstrFilter = szFilter;
  668. ofn.nFilterIndex = 1;
  669. ofn.lpstrCustomFilter = NULL;
  670. ofn.lpstrFile = szBuffer;
  671. ofn.nMaxFile = MAX_PATH;
  672. ofn.lpstrFileTitle = NULL; // maybe use later?
  673. ofn.nMaxFileTitle = 0;
  674. ofn.lpstrInitialDir = NULL;
  675. ofn.lpstrTitle = NULL;
  676. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  677. ofn.lpstrDefExt = szDefaultExtension;
  678. if (!::GetOpenFileName(&ofn))
  679. return; // user cancelled
  680. OpenMSInfoFile(ofn.lpstrFile, ofn.nFileExtension);
  681. }
  682. //-------------------------------------------------------------------------
  683. // SaveNFO allows the user to select a filename, and saves the current
  684. // data to an NFO file.
  685. //-------------------------------------------------------------------------
  686. void CMSInfo::SaveNFO()
  687. {
  688. // Present the user with a dialog box to select a name for saving.
  689. TCHAR szBuffer[MAX_PATH] = _T("");
  690. TCHAR szFilter[MAX_PATH];
  691. TCHAR szDefaultExtension[4];
  692. //v-stlowe 3/19/2001 if (m_fHistoryAvailable && m_strMachine.IsEmpty())
  693. if (m_fHistorySaveAvailable && m_strMachine.IsEmpty())
  694. ::LoadString(_Module.GetResourceInstance(), IDS_SAVEBOTHFILTER, szFilter, MAX_PATH);
  695. else
  696. ::LoadString(_Module.GetResourceInstance(), IDS_SAVENFOFILTER, szFilter, MAX_PATH);
  697. ::LoadString(_Module.GetResourceInstance(), IDS_DEFAULTEXTENSION, szDefaultExtension, 4);
  698. for (int i = 0; szFilter[i]; i++)
  699. if (szFilter[i] == _T('|'))
  700. szFilter[i] = _T('\0');
  701. OPENFILENAME ofn;
  702. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  703. ofn.lStructSize = sizeof(OPENFILENAME);
  704. ofn.hwndOwner = m_hWnd;
  705. ofn.lpstrFilter = szFilter;
  706. ofn.nFilterIndex = 0;
  707. ofn.lpstrCustomFilter = NULL;
  708. ofn.lpstrFile = szBuffer;
  709. ofn.nMaxFile = MAX_PATH;
  710. ofn.lpstrFileTitle = NULL; // maybe use later?
  711. ofn.nMaxFileTitle = 0;
  712. ofn.lpstrInitialDir = NULL;
  713. ofn.lpstrTitle = NULL;
  714. ofn.Flags = OFN_OVERWRITEPROMPT;
  715. ofn.lpstrDefExt = szDefaultExtension;
  716. if (!::GetSaveFileName(&ofn))
  717. return; // user cancelled
  718. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  719. CString strFileName(ofn.lpstrFile);
  720. if (strFileName.Right(4).CompareNoCase(_T(".xml")) == 0)
  721. SaveXML(strFileName);
  722. else
  723. SaveMSInfoFile(strFileName, ofn.nFilterIndex);
  724. ::SetCursor(hc);
  725. }
  726. //-------------------------------------------------------------------------
  727. // Actually saves the current information to an NFO file.
  728. //-------------------------------------------------------------------------
  729. void CMSInfo::SaveMSInfoFile(LPCTSTR szFilename, DWORD dwFilterIndex)
  730. {
  731. ASSERT(m_pCurrData);
  732. if (m_history.IsWindowVisible())
  733. DispatchCommand(ID_VIEW_CURRENT);
  734. if (m_pCurrData)
  735. {
  736. CMSInfoCategory * pCategory = m_pCurrData->GetRootCategory();
  737. if (pCategory)
  738. {
  739. HANDLE hFile = ::CreateFile(szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  740. if (hFile != INVALID_HANDLE_VALUE)
  741. {
  742. if (pCategory->GetDataSourceType() == LIVE_DATA)
  743. {
  744. CMSInfoLiveCategory * pLiveCategory = (CMSInfoLiveCategory *) pCategory;
  745. if (m_fNoUI)
  746. pLiveCategory->RefreshSynchronous((CLiveDataSource *) m_pCurrData, TRUE);
  747. else
  748. RefreshData((CLiveDataSource *)m_pCurrData, pLiveCategory);
  749. }
  750. else if (pCategory->GetDataSourceType() == XML_SNAPSHOT)
  751. ((CXMLSnapshotCategory *)pCategory)->Refresh((CXMLDataSource *)m_pCurrData, TRUE);
  752. //PENDING dependence on filter order. Always add new filters to the end.
  753. if (dwFilterIndex == 1)//NFO_700
  754. pCategory->SaveXML(hFile);
  755. else
  756. pCategory->SaveNFO(hFile, pCategory, TRUE);
  757. ::CloseHandle(hFile);
  758. }
  759. else
  760. {
  761. DWORD dwError = ::GetLastError();
  762. LPVOID lpMsgBuf;
  763. ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  764. FORMAT_MESSAGE_FROM_SYSTEM |
  765. FORMAT_MESSAGE_IGNORE_INSERTS,
  766. NULL,
  767. dwError,
  768. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  769. (LPTSTR) &lpMsgBuf,
  770. 0,
  771. NULL);
  772. // TBD Process any inserts in lpMsgBuf.
  773. CString strCaption;
  774. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  775. strCaption.LoadString(IDS_SYSTEMINFO);
  776. ::MessageBox(m_hWnd, (LPCTSTR) lpMsgBuf, strCaption, MB_ICONEXCLAMATION | MB_OK);
  777. ::LocalFree(lpMsgBuf);
  778. }
  779. }
  780. }
  781. }
  782. //-------------------------------------------------------------------------
  783. // Save an XML file containing the history information.
  784. //-------------------------------------------------------------------------
  785. void CMSInfo::SaveXML(const CString & strFileName)
  786. {
  787. if (m_pHistoryStream == NULL)
  788. {
  789. MSInfoMessageBox(IDS_XMLSAVEERR);
  790. return;
  791. }
  792. // get the stream status, so we can determine the size of the stream
  793. STATSTG streamStat;
  794. HRESULT hr = m_pHistoryStream->Stat(&streamStat,STATFLAG_NONAME );
  795. if (FAILED(hr))
  796. {
  797. ASSERT(0 && "couldn't get stream statistics");
  798. MSInfoMessageBox(IDS_XMLSAVEERR);
  799. return;
  800. }
  801. // allocate buffer of appropriate size
  802. BYTE* pBuffer = new BYTE[streamStat.cbSize.LowPart];
  803. ULONG ulRead;
  804. // seek to beginning of stream
  805. ULARGE_INTEGER uliSeekPtr;
  806. LARGE_INTEGER liSeekLoc;
  807. liSeekLoc.QuadPart = 0;
  808. hr = m_pHistoryStream->Seek(liSeekLoc,0,&uliSeekPtr);
  809. if (FAILED(hr))
  810. {
  811. MSInfoMessageBox(IDS_XMLSAVEERR);
  812. return;
  813. }
  814. hr = m_pHistoryStream->Read(pBuffer,streamStat.cbSize.LowPart,&ulRead);
  815. if (FAILED(hr) || !pBuffer)
  816. {
  817. MSInfoMessageBox(IDS_XMLSAVEERR);
  818. return;
  819. }
  820. if(ulRead != streamStat.cbSize.LowPart)
  821. {
  822. ASSERT(0 && "Not enough bytes read from stream");
  823. MSInfoMessageBox(IDS_XMLSAVEERR);
  824. return;
  825. }
  826. CFile file;
  827. try
  828. {
  829. file.Open(strFileName, CFile::modeCreate | CFile::modeWrite);
  830. file.Write(pBuffer,ulRead);
  831. }
  832. catch (CFileException e)
  833. {
  834. e.ReportError();
  835. }
  836. catch (...)
  837. {
  838. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  839. CString strCaption, strMessage;
  840. strCaption.LoadString(IDS_SYSTEMINFO);
  841. strMessage.LoadString(IDS_XMLSAVEERR);
  842. ::MessageBox(NULL,strMessage, strCaption,MB_OK);
  843. }
  844. delete pBuffer;
  845. }
  846. //-------------------------------------------------------------------------
  847. // Export allows the user to select a filename, and saves the current
  848. // data to a text or XML file.
  849. //-------------------------------------------------------------------------
  850. void CMSInfo::Export()
  851. {
  852. // Present the user with a dialog box to select a name for saving.
  853. TCHAR szBuffer[MAX_PATH] = _T("");
  854. TCHAR szFilter[MAX_PATH];
  855. TCHAR szTitle[MAX_PATH] = _T("");
  856. TCHAR szDefaultExtension[4];
  857. ::LoadString(_Module.GetResourceInstance(), IDS_EXPORTFILTER, szFilter, MAX_PATH); // TBD - add XML
  858. ::LoadString(_Module.GetResourceInstance(), IDS_DEFAULTEXPORTEXTENSION, szDefaultExtension, 4);
  859. ::LoadString(_Module.GetResourceInstance(), IDS_EXPORTDIALOGTITLE, szTitle, MAX_PATH);
  860. for (int i = 0; szFilter[i]; i++)
  861. if (szFilter[i] == _T('|'))
  862. szFilter[i] = _T('\0');
  863. OPENFILENAME ofn;
  864. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  865. ofn.lStructSize = sizeof(OPENFILENAME);
  866. ofn.hwndOwner = m_hWnd;
  867. ofn.lpstrFilter = szFilter;
  868. ofn.nFilterIndex = 0;
  869. ofn.lpstrCustomFilter = NULL;
  870. ofn.lpstrFile = szBuffer;
  871. ofn.nMaxFile = MAX_PATH;
  872. ofn.lpstrFileTitle = NULL; // maybe use later?
  873. ofn.nMaxFileTitle = 0;
  874. ofn.lpstrInitialDir = NULL;
  875. ofn.lpstrTitle = (szTitle[0] == _T('\0')) ? NULL : szTitle;
  876. ofn.Flags = OFN_OVERWRITEPROMPT;
  877. ofn.lpstrDefExt = szDefaultExtension;
  878. if (!::GetSaveFileName(&ofn))
  879. return; // user cancelled
  880. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  881. ExportFile(ofn.lpstrFile, ofn.nFileExtension);
  882. ::SetCursor(hc);
  883. }
  884. //-------------------------------------------------------------------------
  885. // Open the specified file (it might be XML, NFO, CAB, etc.). If the open
  886. // succeeds, we should show the contents of the file.
  887. //-------------------------------------------------------------------------
  888. HRESULT CMSInfo::OpenMSInfoFile(LPCTSTR szFilename, int nFileExtension)
  889. {
  890. HRESULT hr = S_OK;
  891. CDataSource * pOldOpenFile = m_pFileData;
  892. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  893. /* v-stlowe 3/04/2001...we don't want to automatically switch from history
  894. in the event we're opening XML.
  895. if (m_history.IsWindowVisible())
  896. DispatchCommand(ID_VIEW_CURRENT);*/
  897. // Open the file.
  898. LPCTSTR szExtension = szFilename + nFileExtension;
  899. if (_tcsicmp(szExtension, _T("NFO")) == 0)
  900. {
  901. // First, try opening it as a 4.x file.
  902. CNFO4DataSource* pMSI4Source = new CNFO4DataSource();
  903. hr = pMSI4Source->Create(szFilename);
  904. if (SUCCEEDED(hr))
  905. {
  906. m_pFileData = pMSI4Source;
  907. }
  908. else
  909. {
  910. delete pMSI4Source;
  911. if (STG_E_ACCESSDENIED == hr || STG_E_SHAREVIOLATION == hr || STG_E_LOCKVIOLATION == hr)
  912. {
  913. MSInfoMessageBox(IDS_OLDNFOSHARINGVIOLATION);
  914. return E_FAIL;
  915. }
  916. }
  917. // If that failed, then try opening it as a 5.0/6.0 file.
  918. if (FAILED(hr))
  919. {
  920. HANDLE h = ::CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  921. if (INVALID_HANDLE_VALUE == h)
  922. {
  923. MSInfoMessageBox(IDS_BADNFOFILE);
  924. return E_FAIL;
  925. }
  926. CNFO6DataSource * p60Source = new CNFO6DataSource;
  927. if (p60Source)
  928. {
  929. hr = p60Source->Create(h, szFilename);
  930. if (FAILED(hr))
  931. {
  932. delete p60Source;
  933. //MSInfoMessageBox(IDS_BADNFOFILE);
  934. }
  935. else
  936. m_pFileData = p60Source;
  937. }
  938. else
  939. hr = E_FAIL; // TBD no memory
  940. ::CloseHandle(h);
  941. }
  942. //Try 7.0
  943. if (FAILED(hr))
  944. {
  945. CNFO7DataSource * p70Source = new CNFO7DataSource;
  946. if (!p70Source)
  947. hr = E_FAIL;
  948. else
  949. {
  950. hr = p70Source->Create(szFilename);//blocks while parsing
  951. if (FAILED(hr))
  952. {
  953. delete p70Source;
  954. MSInfoMessageBox(IDS_BADNFOFILE);
  955. }
  956. else
  957. m_pFileData = p70Source;
  958. }
  959. }
  960. }
  961. else if (_tcsicmp(szExtension, _T("CAB")) == 0)
  962. {
  963. CString strDest;
  964. GetCABExplodeDir(strDest, TRUE, _T(""));
  965. if (!strDest.IsEmpty())
  966. {
  967. if (OpenCABFile(szFilename, strDest))
  968. {
  969. LoadGlobalToolsetWithOpenCAB(m_mapIDToTool, strDest);
  970. UpdateToolsMenu();
  971. CString strFileInCAB;
  972. //first, look for xml files (the incident file specified in the registry, and (possibly) dataspec.xml
  973. //Get default incident file name from registry (create it if it's not there)
  974. CString strIncidentFileName;
  975. HKEY hkey;
  976. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Shared Tools\\MSInfo"), 0, KEY_ALL_ACCESS, &hkey))
  977. {
  978. TCHAR szBuffer[MAX_PATH];
  979. DWORD dwType, dwSize = MAX_PATH * sizeof(TCHAR);
  980. long lErr = RegQueryValueEx(hkey, _T("incidentfilename"), NULL, &dwType, (LPBYTE)szBuffer, &dwSize);
  981. if (ERROR_SUCCESS == lErr)
  982. {
  983. if (dwType == REG_SZ)
  984. {
  985. strIncidentFileName = szBuffer;
  986. }
  987. else
  988. {
  989. ASSERT(0 && "invalid incidentfilename reg key");
  990. return E_FAIL;
  991. }
  992. }
  993. //check lErr to make sure it's appropriate error for value not existing
  994. else if (2 == lErr)
  995. {
  996. //create registry key.
  997. CString strDefaultValue = _T("Incident.xml");
  998. lErr = RegSetValueEx(hkey,_T("incidentfilename"),NULL,REG_SZ,(BYTE*) strDefaultValue.GetBuffer(strDefaultValue.GetLength()),strDefaultValue.GetLength() * sizeof(TCHAR));
  999. strIncidentFileName = strDefaultValue;
  1000. }
  1001. }
  1002. if (IsIncidentXMLFilePresent(strDest,strIncidentFileName))
  1003. {
  1004. strFileInCAB = strDest + "\\";
  1005. strFileInCAB += strIncidentFileName;
  1006. OpenMSInfoFile(strFileInCAB,strFileInCAB.Find(_T(".xml")) +1);
  1007. return S_OK;
  1008. }
  1009. //if there are no xml incident files
  1010. FindFileToOpen(strDest, strFileInCAB);
  1011. if (!strFileInCAB.IsEmpty())
  1012. {
  1013. int iExtension = strFileInCAB.GetLength() - 1;
  1014. while (iExtension && strFileInCAB[iExtension] != _T('.'))
  1015. iExtension--;
  1016. if (iExtension)
  1017. return OpenMSInfoFile(strFileInCAB, iExtension + 1 /* skip the dot */);
  1018. else
  1019. {
  1020. ASSERT(0 && "couldn't find dot in file name");
  1021. }
  1022. }
  1023. }
  1024. }
  1025. else
  1026. {
  1027. // TBD - do something about the error.
  1028. ASSERT(0 && "could get not CAB destination directory");
  1029. }
  1030. MSInfoMessageBox(IDS_BADCABFILE);
  1031. return E_FAIL;
  1032. }
  1033. else if (_tcsicmp(szExtension, _T("XML")) == 0)
  1034. {
  1035. /* v-stlowe 3/04/2001
  1036. CXMLDataSource* pSSDataSource = new CXMLDataSource();
  1037. hr = pSSDataSource->Create(szFilename,(CMSInfoLiveCategory *) this->m_pLiveData->GetRootCategory(),m_hWnd);
  1038. CXMLSnapshotCategory* pRootXML = (CXMLSnapshotCategory*) pSSDataSource->GetRootCategory();
  1039. pRootXML->AppendFilenameToCaption(szFilename);
  1040. if (SUCCEEDED(hr))
  1041. {
  1042. m_pFileData = pSSDataSource;
  1043. }
  1044. else
  1045. {
  1046. delete pSSDataSource;
  1047. }*/
  1048. try
  1049. {
  1050. hr = ((CLiveDataSource *)m_pLiveData)->LoadXMLDoc(szFilename);
  1051. m_pFileData = m_pLiveData;
  1052. this->m_strFileName = szFilename;
  1053. //trigger refresh
  1054. CMSInfoCategory * pCategory = GetCurrentCategory();
  1055. if (pCategory)
  1056. ChangeHistoryView(((CMSInfoHistoryCategory*) pCategory)->m_iDeltaIndex);
  1057. if (FAILED(hr))//v-stlowe 3/9/2001 || !varBSuccess)
  1058. {
  1059. ASSERT(0 && "unable to load xml document");
  1060. return E_FAIL;
  1061. }
  1062. }
  1063. catch(...)
  1064. {
  1065. return E_FAIL;
  1066. }
  1067. DispatchCommand(ID_VIEW_HISTORY);
  1068. }
  1069. else
  1070. {
  1071. // Report that we can't open this kind of file.
  1072. MSInfoMessageBox(IDS_UNKNOWNFILETYPE);
  1073. hr = E_FAIL;
  1074. }
  1075. // It succeeded, so we should show the new data and update the menu
  1076. // for the new state.
  1077. if (SUCCEEDED(hr))
  1078. {
  1079. if (pOldOpenFile && pOldOpenFile != m_pFileData)
  1080. delete pOldOpenFile;
  1081. SelectDataSource(m_pFileData);
  1082. }
  1083. else
  1084. ; // report the error
  1085. return hr;
  1086. }
  1087. //-------------------------------------------------------------------------
  1088. // Export to the specified file. This will be either a TXT or an XML file.
  1089. //-------------------------------------------------------------------------
  1090. void CMSInfo::ExportFile(LPCTSTR szFilename, int nFileExtension)
  1091. {
  1092. ASSERT(m_pCurrData);
  1093. if (m_pCurrData)
  1094. {
  1095. // If there is a selected category, export that node only (bug 185305).
  1096. CMSInfoCategory * pCategory = (m_pCategory) ? m_pCategory : m_pCurrData->GetRootCategory();
  1097. if (pCategory)
  1098. {
  1099. if (pCategory->GetDataSourceType() == LIVE_DATA)
  1100. {
  1101. if (m_history.IsWindowVisible() == TRUE)
  1102. {
  1103. ((CMSInfoHistoryCategory*)pCategory)->Refresh((CLiveDataSource*)m_pCurrData,TRUE);
  1104. }
  1105. else
  1106. {
  1107. CMSInfoLiveCategory * pLiveCategory = (CMSInfoLiveCategory *) pCategory;
  1108. if (m_fNoUI)
  1109. pLiveCategory->RefreshSynchronous((CLiveDataSource *) m_pCurrData, TRUE);
  1110. else
  1111. RefreshData((CLiveDataSource *)m_pCurrData, pLiveCategory);
  1112. }
  1113. }
  1114. else if (pCategory->GetDataSourceType() == NFO_410)
  1115. {
  1116. ((CMSInfo4Category *) pCategory)->RefreshAllForPrint(m_hWnd,this->GetOCXRect());
  1117. }
  1118. else if (pCategory->GetDataSourceType() == XML_SNAPSHOT)
  1119. {
  1120. ((CXMLSnapshotCategory *) pCategory)->Refresh((CXMLDataSource *)m_pCurrData,TRUE);
  1121. }
  1122. /*HANDLE hFile = ::CreateFile(szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1123. if (hFile != INVALID_HANDLE_VALUE)
  1124. {
  1125. pCategory->SaveAsText(hFile, TRUE);
  1126. ::CloseHandle(hFile);
  1127. }
  1128. else
  1129. {
  1130. // TBD - handle the error
  1131. }*/
  1132. //a-stephl: Fixing OSR4.1 bug #133823, not displaying message when saving to write-protected diskette
  1133. try
  1134. {
  1135. HANDLE hFile = ::CreateFile(szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1136. if (hFile != INVALID_HANDLE_VALUE)
  1137. {
  1138. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  1139. LPTSTR lpMachineName = new TCHAR[dwSize];
  1140. GetMachineName(lpMachineName, &dwSize);
  1141. /*a-kjaw To implement save as XML
  1142. if( _tcsicmp(szFilename + nFileExtension , _T("XML")) == 0)
  1143. {
  1144. pCategory->SaveAsXml(hFile, TRUE);
  1145. }
  1146. //a-kjaw */
  1147. // else
  1148. // {
  1149. pCategory->SaveAsText(hFile, TRUE, lpMachineName);
  1150. // }
  1151. delete [] lpMachineName;
  1152. ::CloseHandle(hFile);
  1153. }
  1154. else
  1155. {
  1156. DWORD dwError = ::GetLastError();
  1157. LPVOID lpMsgBuf;
  1158. ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1159. FORMAT_MESSAGE_FROM_SYSTEM |
  1160. FORMAT_MESSAGE_IGNORE_INSERTS,
  1161. NULL,
  1162. dwError,
  1163. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1164. (LPTSTR) &lpMsgBuf,
  1165. 0,
  1166. NULL);
  1167. // TBD Process any inserts in lpMsgBuf.
  1168. CString strCaption;
  1169. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  1170. strCaption.LoadString(IDS_SYSTEMINFO);
  1171. ::MessageBox(m_hWnd, (LPCTSTR) lpMsgBuf, strCaption, MB_ICONEXCLAMATION | MB_OK);
  1172. ::LocalFree(lpMsgBuf);
  1173. }
  1174. }
  1175. catch (CFileException e)
  1176. {
  1177. e.ReportError();
  1178. }
  1179. catch (CException e)
  1180. {
  1181. e.ReportError();
  1182. }
  1183. catch (...)
  1184. {
  1185. DWORD dwError = ::GetLastError();
  1186. LPVOID lpMsgBuf;
  1187. ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1188. FORMAT_MESSAGE_FROM_SYSTEM |
  1189. FORMAT_MESSAGE_IGNORE_INSERTS,
  1190. NULL,
  1191. dwError,
  1192. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1193. (LPTSTR) &lpMsgBuf,
  1194. 0,
  1195. NULL);
  1196. // TBD Process any inserts in lpMsgBuf.
  1197. CString strCaption;
  1198. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  1199. strCaption.LoadString(IDS_SYSTEMINFO);
  1200. ::MessageBox(m_hWnd, (LPCTSTR) lpMsgBuf, strCaption, MB_ICONEXCLAMATION | MB_OK);
  1201. ::LocalFree(lpMsgBuf);
  1202. }
  1203. }
  1204. //end a-stephl: Fixing OSR4.1 bug #133823, not displaying message when saving to write-protected diskette
  1205. }
  1206. }
  1207. //-------------------------------------------------------------------------
  1208. // Close the currently open file (if there is one). Displays the current
  1209. // system information.
  1210. //-------------------------------------------------------------------------
  1211. void CMSInfo::CloseFile()
  1212. {
  1213. ASSERT(m_pFileData);
  1214. //v-stlowe 3/12/2001
  1215. SelectDataSource(m_pLiveData);
  1216. if (m_strFileName.Right(4) == _T(".xml"))
  1217. {
  1218. ((CLiveDataSource *)m_pLiveData)->RevertToLiveXML();
  1219. }
  1220. if (m_pFileData)
  1221. {
  1222. //v-stlowe: so we can use livedata as filedata when opening history xml
  1223. if (m_pFileData != this->m_pLiveData)
  1224. {
  1225. delete m_pFileData;
  1226. }
  1227. m_pFileData = NULL;
  1228. }
  1229. if (!m_history.IsWindowVisible())
  1230. {
  1231. DispatchCommand(ID_VIEW_CURRENT);
  1232. }
  1233. else
  1234. {
  1235. DispatchCommand(ID_VIEW_HISTORY);
  1236. }
  1237. SetMenuItems();
  1238. }
  1239. //-------------------------------------------------------------------------
  1240. // Enable or disable menu items based on the current state.
  1241. //-------------------------------------------------------------------------
  1242. void CMSInfo::SetMenuItems()
  1243. {
  1244. if (NULL == m_hmenu || NULL == m_hwndParent)
  1245. return;
  1246. // This struct will be used a bunch in this function to set menu item states.
  1247. MENUITEMINFO mii;
  1248. mii.cbSize = sizeof(MENUITEMINFO);
  1249. // The type of data being displayed will also be used frequently.
  1250. DataSourceType datatype = LIVE_DATA;
  1251. if (m_pCurrData)
  1252. {
  1253. CMSInfoCategory * pCategory = m_pCurrData->GetRootCategory();
  1254. if (pCategory)
  1255. datatype = pCategory->GetDataSourceType();
  1256. }
  1257. // Enable or disable items in the File menu.
  1258. HMENU hmenuFile = ::GetSubMenu(m_hmenu, 0);
  1259. if (hmenuFile)
  1260. {
  1261. mii.fMask = MIIM_STATE;
  1262. mii.fState = (m_pFileData == m_pCurrData) ? MFS_ENABLED : MFS_GRAYED;
  1263. ::SetMenuItemInfo(hmenuFile, ID_FILE_CLOSE, FALSE, &mii);
  1264. mii.fState = MFS_ENABLED; // Was: (m_pFileData != m_pCurrData) ? MFS_ENABLED : MFS_GRAYED;
  1265. ::SetMenuItemInfo(hmenuFile, ID_FILE_OPENNFO, FALSE, &mii);
  1266. mii.fState = (datatype == LIVE_DATA || datatype == XML_SNAPSHOT) ? MFS_ENABLED : MFS_GRAYED;
  1267. ::SetMenuItemInfo(hmenuFile, ID_FILE_SAVENFO, FALSE, &mii);
  1268. //mii.fState = MFS_ENABLED;
  1269. mii.fState = (datatype != NFO_410) ? MFS_ENABLED : MFS_GRAYED;;
  1270. ::SetMenuItemInfo(hmenuFile, ID_FILE_EXPORT, FALSE, &mii);
  1271. mii.fState = MFS_ENABLED;
  1272. ::SetMenuItemInfo(hmenuFile, ID_FILE_PRINT, FALSE, &mii);
  1273. if (NULL == m_hwndParent)
  1274. {
  1275. // Remove the last two items (the exit command and the divider).
  1276. int nItems = ::GetMenuItemCount(hmenuFile);
  1277. if (ID_FILE_EXIT == ::GetMenuItemID(hmenuFile, nItems - 1))
  1278. {
  1279. ::RemoveMenu(hmenuFile, nItems - 1, MF_BYPOSITION);
  1280. ::RemoveMenu(hmenuFile, nItems - 2, MF_BYPOSITION);
  1281. }
  1282. }
  1283. }
  1284. // Enable or disable items in the Edit menu.
  1285. HMENU hmenuEdit = ::GetSubMenu(m_hmenu, 1);
  1286. if (hmenuEdit)
  1287. {
  1288. mii.fMask = MIIM_STATE;
  1289. if (datatype == NFO_410 || ListView_GetNextItem(m_list.m_hWnd, -1, LVNI_SELECTED) != -1)
  1290. mii.fState = MFS_ENABLED;
  1291. else
  1292. mii.fState = MFS_GRAYED;
  1293. // Disable copy if the list view is not visible.
  1294. if (!m_list.IsWindowVisible())
  1295. mii.fState = MFS_GRAYED;
  1296. // If the find control has focus, enable copy based on that control.
  1297. if (GetFocus() == m_wndFindWhat.m_hWnd && m_wndFindWhat.IsWindowVisible() && m_wndFindWhat.IsWindowEnabled())
  1298. mii.fState = MFS_ENABLED;
  1299. ::SetMenuItemInfo(hmenuEdit, ID_EDIT_COPY, FALSE, &mii);
  1300. mii.fState = (m_list.IsWindowVisible()) ? MFS_ENABLED : MFS_GRAYED;
  1301. ::SetMenuItemInfo(hmenuEdit, ID_EDIT_SELECTALL, FALSE, &mii);
  1302. mii.fState = (datatype != NFO_410) ? MFS_ENABLED : MFS_GRAYED;
  1303. mii.fState |= ((!m_fFindVisible) ? MFS_CHECKED : MFS_UNCHECKED);
  1304. ::SetMenuItemInfo(hmenuEdit, ID_EDIT_FIND, FALSE, &mii);
  1305. }
  1306. // Enable or disable items in the View menu.
  1307. HMENU hmenuView = ::GetSubMenu(m_hmenu, 2);
  1308. if (hmenuView)
  1309. {
  1310. mii.fMask = MIIM_STATE;
  1311. mii.fState = (datatype == LIVE_DATA && !m_history.IsWindowVisible()) ? MFS_ENABLED : MFS_GRAYED;
  1312. ::SetMenuItemInfo(hmenuView, ID_VIEW_REFRESH, FALSE, &mii);
  1313. mii.fState = MFS_ENABLED | ((!m_fAdvanced) ? MFS_CHECKED : MFS_UNCHECKED);
  1314. ::SetMenuItemInfo(hmenuView, ID_VIEW_BASIC, FALSE, &mii);
  1315. mii.fState = MFS_ENABLED | ((m_fAdvanced) ? MFS_CHECKED : MFS_UNCHECKED);
  1316. ::SetMenuItemInfo(hmenuView, ID_VIEW_ADVANCED, FALSE, &mii);
  1317. // Set the menu item for the current system view or snapshot, depending on whether
  1318. // or not there is an XML file open.
  1319. BOOL fEnableHistoryLive = FALSE;
  1320. if (datatype == LIVE_DATA && m_fHistoryAvailable && m_strMachine.IsEmpty())
  1321. fEnableHistoryLive = TRUE;
  1322. BOOL fEnableHistoryXML = FALSE;
  1323. if (m_pFileData)
  1324. {
  1325. CMSInfoCategory * pCategory = m_pFileData->GetRootCategory();
  1326. if (pCategory && (pCategory->GetDataSourceType() == XML_SNAPSHOT || pCategory == &catHistorySystemSummary))
  1327. fEnableHistoryXML = TRUE;
  1328. }
  1329. BOOL fShowingHistory = FALSE;
  1330. if (m_pCurrData)
  1331. {
  1332. CMSInfoCategory * pCategory = m_pCurrData->GetRootCategory();
  1333. if (pCategory == &catHistorySystemSummary)
  1334. fShowingHistory = TRUE;
  1335. }
  1336. // Whether or not you can remote depends on if you are showing live data.
  1337. mii.fState = (datatype == LIVE_DATA && !fEnableHistoryXML) ? MFS_ENABLED : MFS_GRAYED;
  1338. ::SetMenuItemInfo(hmenuView, ID_VIEW_REMOTE_COMPUTER, FALSE, &mii);
  1339. // Enabling the menu items to switch between current (or snapshot) and history
  1340. // are based on whether history is available.
  1341. mii.fState = (fEnableHistoryLive || fEnableHistoryXML) ? MFS_ENABLED : MFS_GRAYED;
  1342. mii.fState |= (!m_history.IsWindowVisible()) ? MFS_CHECKED : MFS_UNCHECKED;
  1343. ::SetMenuItemInfo(hmenuView, ID_VIEW_CURRENT, FALSE, &mii);
  1344. mii.fState = (fEnableHistoryLive || fEnableHistoryXML) ? MFS_ENABLED : MFS_GRAYED;
  1345. mii.fState |= (m_history.IsWindowVisible()) ? MFS_CHECKED : MFS_UNCHECKED;
  1346. ::SetMenuItemInfo(hmenuView, ID_VIEW_HISTORY, FALSE, &mii);
  1347. // Set the menu item text (for system snapshot/current system information) based on
  1348. // whether or not we have an XML file open.
  1349. UINT uiMenuCaption = IDS_VIEWCURRENTSYSTEMINFO;
  1350. if (m_pFileData)
  1351. {
  1352. CMSInfoCategory * pCategory = m_pCurrData->GetRootCategory();
  1353. // v-stlowe 6/26/2001...pCategory && (pCategory->GetDataSourceType() == XML_SNAPSHOT no longer possible... if (pCategory && (pCategory->GetDataSourceType() == XML_SNAPSHOT || pCategory == &catHistorySystemSummary))
  1354. if (pCategory && (pCategory == &catHistorySystemSummary))
  1355. {
  1356. //v-stlowe 6/26/2001: we need to remove "snapshot" uiMenuCaption = IDS_VIEWSYSTEMSNAPSHOT;
  1357. uiMenuCaption = IDS_VIEWCURRENTSYSTEMINFO;
  1358. }
  1359. }
  1360. CString strMenuItem;
  1361. strMenuItem.LoadString(uiMenuCaption);
  1362. MENUITEMINFO miiName;
  1363. miiName.cbSize = sizeof(MENUITEMINFO);
  1364. miiName.fMask = MIIM_TYPE;
  1365. miiName.fType = MFT_STRING;
  1366. miiName.dwTypeData = (LPTSTR)(LPCTSTR)strMenuItem;
  1367. ::SetMenuItemInfo(hmenuView, ID_VIEW_CURRENT, FALSE, &miiName);
  1368. }
  1369. // Enable or disable items in the Help menu.
  1370. HMENU hmenuHelp = ::GetSubMenu(m_hmenu, 4);
  1371. if (hmenuHelp)
  1372. {
  1373. mii.fMask = MIIM_STATE;
  1374. mii.fState = MFS_ENABLED;
  1375. ::SetMenuItemInfo(hmenuHelp, ID_HELP_ABOUT, FALSE, &mii);
  1376. }
  1377. }
  1378. //-------------------------------------------------------------------------
  1379. // Set a message in the right hand pane (hiding the list view).
  1380. //-------------------------------------------------------------------------
  1381. void CMSInfo::SetMessage(const CString & strTitle, const CString & strMessage, BOOL fRedraw)
  1382. {
  1383. m_strMessTitle = strTitle;
  1384. m_strMessText = strMessage;
  1385. if (strTitle.IsEmpty() && strMessage.IsEmpty())
  1386. {
  1387. m_list.ShowWindow(SW_SHOW);
  1388. return;
  1389. }
  1390. m_list.ShowWindow(SW_HIDE);
  1391. if (fRedraw)
  1392. {
  1393. RECT rectList;
  1394. m_list.GetWindowRect(&rectList);
  1395. ScreenToClient(&rectList);
  1396. InvalidateRect(&rectList, TRUE);
  1397. UpdateWindow();
  1398. }
  1399. }
  1400. void CMSInfo::SetMessage(UINT uiTitle, UINT uiMessage, BOOL fRedraw)
  1401. {
  1402. CString strTitle(_T(""));
  1403. CString strMessage(_T(""));
  1404. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  1405. if (uiTitle)
  1406. strTitle.LoadString(uiTitle);
  1407. if (uiMessage)
  1408. strMessage.LoadString(uiMessage);
  1409. SetMessage(strTitle, strMessage, fRedraw);
  1410. }
  1411. //---------------------------------------------------------------------------
  1412. // This function is used to sort the list by a specified column.
  1413. //---------------------------------------------------------------------------
  1414. int CALLBACK ListSortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  1415. {
  1416. int iReturn = 0;
  1417. CMSInfoCategory * pCategory = (CMSInfoCategory *) lParamSort;
  1418. if (pCategory)
  1419. {
  1420. CString * pstrFirst;
  1421. CString * pstrSecond;
  1422. DWORD dwFirst = 0, dwSecond = 0;
  1423. pCategory->GetData((int)lParam1, pCategory->m_iSortColumn, &pstrFirst, &dwFirst);
  1424. pCategory->GetData((int)lParam2, pCategory->m_iSortColumn, &pstrSecond, &dwSecond);
  1425. //a-kjaw . To fix bug "Sort order style for an nfo file differs from that of live data."
  1426. if(pCategory->GetDataSourceType() == NFO_500/*|| pCategory->GetDataSourceType() == NFO_410 */) //BugBug
  1427. if(pstrFirst->Left(3) == _T("IRQ"))//Very weird fix. Need Loc?
  1428. {
  1429. LPTSTR strIrq = pstrFirst->GetBuffer(pstrFirst->GetLength() + 1);
  1430. dwFirst = _ttoi(strIrq + 4 );
  1431. pstrFirst->ReleaseBuffer();
  1432. strIrq = pstrSecond->GetBuffer(pstrSecond->GetLength() + 1);
  1433. dwSecond = _ttoi(strIrq + 4 );
  1434. pstrSecond->ReleaseBuffer();
  1435. }
  1436. //a-kjaw
  1437. if (pCategory->m_fSortLexical)
  1438. iReturn = pstrFirst->Collate(*pstrSecond);
  1439. else
  1440. iReturn = (dwFirst < dwSecond) ? -1 : (dwFirst == dwSecond) ? 0 : 1;
  1441. if (!pCategory->m_fSortAscending)
  1442. iReturn *= -1;
  1443. }
  1444. return iReturn;
  1445. }
  1446. //---------------------------------------------------------------------------
  1447. // Copy selected text from the list view into the clipboard.
  1448. //---------------------------------------------------------------------------
  1449. void CMSInfo::EditCopy()
  1450. {
  1451. if (GetFocus() == m_wndFindWhat.m_hWnd && m_wndFindWhat.IsWindowVisible() && m_wndFindWhat.IsWindowEnabled())
  1452. {
  1453. m_wndFindWhat.SendMessage(WM_COPY);
  1454. return;
  1455. }
  1456. CString strClipboardText(_T(""));
  1457. CMSInfoCategory * pCategory = GetCurrentCategory();
  1458. if (pCategory == NULL)
  1459. return;
  1460. if (pCategory && pCategory->GetDataSourceType() == NFO_410)
  1461. {
  1462. CMSInfo4Category * pCategory4 = (CMSInfo4Category *) pCategory;
  1463. CMSIControl * p4Ctrl = NULL;
  1464. if (CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(pCategory4->m_strCLSID, p4Ctrl) && p4Ctrl)
  1465. p4Ctrl->MSInfoCopy();
  1466. return;
  1467. }
  1468. int iRowCount, iColCount;
  1469. pCategory->GetCategoryDimensions(&iColCount, &iRowCount);
  1470. // Build the string to put in the clipboard by finding all of the
  1471. // selected lines in the list view.
  1472. LVITEM lvi;
  1473. lvi.mask = LVIF_PARAM;
  1474. lvi.iSubItem = 0;
  1475. CString * pstrCell;
  1476. int iSelected = ListView_GetNextItem(m_list.m_hWnd, -1, LVNI_SELECTED);
  1477. while (iSelected != -1)
  1478. {
  1479. lvi.iItem = iSelected;
  1480. if (ListView_GetItem(m_list.m_hWnd, &lvi))
  1481. {
  1482. ASSERT(lvi.lParam < iRowCount);
  1483. if (lvi.lParam < iRowCount)
  1484. for (int iCol = 0; iCol < iColCount; iCol++)
  1485. if (SUCCEEDED(pCategory->GetData((int)lvi.lParam, iCol, &pstrCell, NULL)))
  1486. {
  1487. if (iCol)
  1488. strClipboardText += _T("\t");
  1489. strClipboardText += *pstrCell;
  1490. }
  1491. strClipboardText += _T("\r\n");
  1492. }
  1493. iSelected = ListView_GetNextItem(m_list.m_hWnd, iSelected, LVNI_SELECTED);
  1494. }
  1495. // Put the string in the clipboard.
  1496. if (OpenClipboard())
  1497. {
  1498. if (EmptyClipboard())
  1499. {
  1500. DWORD dwSize = (strClipboardText.GetLength() + 1) * sizeof(TCHAR);
  1501. HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dwSize);
  1502. if (hMem)
  1503. {
  1504. LPVOID lpvoid = ::GlobalLock(hMem);
  1505. if (lpvoid)
  1506. {
  1507. memcpy(lpvoid, (LPCTSTR) strClipboardText, dwSize);
  1508. ::GlobalUnlock(hMem);
  1509. SetClipboardData(CF_UNICODETEXT, hMem);
  1510. }
  1511. }
  1512. }
  1513. CloseClipboard();
  1514. }
  1515. }
  1516. //---------------------------------------------------------------------------
  1517. // Select all of the text in the list view.
  1518. //---------------------------------------------------------------------------
  1519. void CMSInfo::EditSelectAll()
  1520. {
  1521. CMSInfoCategory * pCategory = GetCurrentCategory();
  1522. if (pCategory && pCategory->GetDataSourceType() == NFO_410)
  1523. {
  1524. CMSInfo4Category * pCategory4 = (CMSInfo4Category *) pCategory;
  1525. CMSIControl * p4Ctrl = NULL;
  1526. if (CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(pCategory4->m_strCLSID, p4Ctrl) && p4Ctrl)
  1527. p4Ctrl->MSInfoSelectAll();
  1528. }
  1529. else
  1530. {
  1531. int iCount = ListView_GetItemCount(m_list.m_hWnd);
  1532. for (int i = 0; i < iCount; i++)
  1533. ListView_SetItemState(m_list.m_hWnd, i, LVIS_SELECTED, LVIS_SELECTED);
  1534. }
  1535. }
  1536. void CMSInfo::GetMachineName(LPTSTR lpBuffer, LPDWORD lpnSize)
  1537. {
  1538. if (_tcslen(m_strMachine) == 0)
  1539. GetComputerName(lpBuffer, lpnSize);
  1540. else
  1541. _tcsncpy(lpBuffer, m_strMachine, *lpnSize);
  1542. }
  1543. //---------------------------------------------------------------------------
  1544. // Print the currently displayed information.
  1545. //---------------------------------------------------------------------------
  1546. void CMSInfo::DoPrint(BOOL fNoUI)
  1547. {
  1548. if (m_pCurrData == NULL)
  1549. return;
  1550. CMSInfoCategory * pRootCategory = m_pCurrData->GetRootCategory();
  1551. CMSInfoCategory * pSelectedCategory = GetCurrentCategory();
  1552. if (pRootCategory == NULL)
  1553. return;
  1554. DWORD dwFlags = PD_RETURNDC | PD_HIDEPRINTTOFILE | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOPAGENUMS;
  1555. if (pSelectedCategory)
  1556. dwFlags |= PD_SELECTION;
  1557. else
  1558. dwFlags |= PD_NOSELECTION | PD_ALLPAGES;
  1559. PRINTDLG pd;
  1560. ::ZeroMemory(&pd, sizeof(PRINTDLG));
  1561. pd.Flags = dwFlags;
  1562. pd.lStructSize = sizeof(PRINTDLG);
  1563. pd.hwndOwner = this->m_hWnd;
  1564. if (fNoUI)
  1565. pd.Flags |= PD_RETURNDEFAULT;
  1566. if (::PrintDlg(&pd) == IDOK)
  1567. {
  1568. CMSInfoCategory * pPrintCategory = ((pd.Flags & PD_SELECTION) != 0) ? pSelectedCategory : pRootCategory;
  1569. if (pPrintCategory)
  1570. {
  1571. if (pPrintCategory->GetDataSourceType() == LIVE_DATA)
  1572. {
  1573. RefreshData((CLiveDataSource *)m_pCurrData, (CMSInfoLiveCategory *)pPrintCategory);
  1574. }
  1575. else if (pPrintCategory->GetDataSourceType() == NFO_410)
  1576. {
  1577. ((CMSInfo4Category *) pPrintCategory)->RefreshAllForPrint(m_hWnd,this->GetOCXRect());
  1578. }
  1579. else if (pPrintCategory->GetDataSourceType() == XML_SNAPSHOT)
  1580. {
  1581. ((CXMLSnapshotCategory*) pPrintCategory)->Refresh((CXMLDataSource*) m_pCurrData, TRUE);
  1582. }
  1583. DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  1584. LPTSTR lpMachineName = new TCHAR[dwSize];
  1585. GetMachineName(lpMachineName, &dwSize);
  1586. pPrintCategory->Print(pd.hDC, TRUE, -1, -1, lpMachineName); // -1's to include all pages
  1587. delete [] lpMachineName;
  1588. }
  1589. }
  1590. }
  1591. //---------------------------------------------------------------------------
  1592. // Update the tools menu to match the contents of the tools map.
  1593. //---------------------------------------------------------------------------
  1594. void CMSInfo::UpdateToolsMenu()
  1595. {
  1596. if (NULL == m_hmenu)
  1597. return;
  1598. HMENU hmenuTool = ::GetSubMenu(m_hmenu, 3);
  1599. if (hmenuTool)
  1600. {
  1601. // Remove all the current tools in the menu.
  1602. while (DeleteMenu(hmenuTool, 0, MF_BYPOSITION));
  1603. // Add the tools from the map. This will add the top level tools.
  1604. WORD wCommand;
  1605. CMSInfoTool * pTool;
  1606. for (POSITION pos = m_mapIDToTool.GetStartPosition(); pos != NULL; )
  1607. {
  1608. m_mapIDToTool.GetNextAssoc(pos, wCommand, (void * &) pTool);
  1609. if (pTool && pTool->GetParentID() == 0)
  1610. {
  1611. if (!pTool->HasSubitems())
  1612. InsertMenu(hmenuTool, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, (UINT) pTool->GetID(), pTool->GetName());
  1613. else
  1614. {
  1615. HMENU hmenuNew = CreatePopupMenu();
  1616. InsertMenu(hmenuTool, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT_PTR) hmenuNew, pTool->GetName());
  1617. pTool->SetHMENU(hmenuNew);
  1618. }
  1619. }
  1620. }
  1621. // Now add the second level tools (the subitems).
  1622. for (pos = m_mapIDToTool.GetStartPosition(); pos != NULL; )
  1623. {
  1624. m_mapIDToTool.GetNextAssoc(pos, wCommand, (void * &) pTool);
  1625. if (pTool && pTool->GetParentID())
  1626. {
  1627. CMSInfoTool * pParentTool;
  1628. if (m_mapIDToTool.Lookup((WORD) pTool->GetParentID(), (void * &) pParentTool))
  1629. InsertMenu(pParentTool->GetHMENU(), 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, (UINT) pTool->GetID(), pTool->GetName());
  1630. }
  1631. }
  1632. }
  1633. }
  1634. //---------------------------------------------------------------------------
  1635. // Gets the right pane rect in which to display a MSInfo 4.x OCX.
  1636. //---------------------------------------------------------------------------
  1637. CRect CMSInfo::GetOCXRect()
  1638. {
  1639. CRect rectList;
  1640. m_list.GetWindowRect(&rectList);
  1641. ScreenToClient(&rectList);
  1642. rectList.DeflateRect(1, 1, 2, 2);
  1643. return rectList;
  1644. }
  1645. //=============================================================================
  1646. // Find Functionality
  1647. //=============================================================================
  1648. //-------------------------------------------------------------------------
  1649. // CancelFind does what is says. It also waits until the find is done
  1650. // before returning.
  1651. //-------------------------------------------------------------------------
  1652. void CMSInfo::CancelFind()
  1653. {
  1654. if (m_fInFind)
  1655. {
  1656. m_fCancelFind = TRUE;
  1657. m_fFindNext = FALSE;
  1658. GotoDlgCtrl(m_wndStopFind.m_hWnd);
  1659. UpdateFindControls();
  1660. if (m_pcatFind && m_pcatFind->GetDataSourceType() == LIVE_DATA)
  1661. {
  1662. CLiveDataSource * pLiveDataSource = (CLiveDataSource *) m_pCurrData;
  1663. HCURSOR hc = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  1664. pLiveDataSource->WaitForRefresh();
  1665. ::SetCursor(hc);
  1666. }
  1667. }
  1668. }
  1669. //-------------------------------------------------------------------------
  1670. // When the user clicks on Stop Find, it will either cancel the current
  1671. // find operation (if there is one in progress) or hide the find controls
  1672. // (if there is no find in progress).
  1673. //-------------------------------------------------------------------------
  1674. LRESULT CMSInfo::OnStopFind(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1675. {
  1676. if (m_fInFind)
  1677. {
  1678. m_fCancelFind = TRUE;
  1679. m_fFindNext = FALSE;
  1680. GotoDlgCtrl(m_wndStopFind.m_hWnd);
  1681. UpdateFindControls();
  1682. }
  1683. else
  1684. {
  1685. m_fFindNext = FALSE;
  1686. DispatchCommand(ID_EDIT_FIND);
  1687. }
  1688. return 0;
  1689. }
  1690. //-------------------------------------------------------------------------
  1691. // UpdateFindControls updates the state of the controls (the text and
  1692. // enabling/disabling) based on the settings of the find member vars.
  1693. //-------------------------------------------------------------------------
  1694. void CMSInfo::UpdateFindControls()
  1695. {
  1696. if (!m_fFindVisible)
  1697. return;
  1698. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  1699. m_wndCancelFind.ShowWindow(m_fInFind ? SW_SHOW : SW_HIDE);
  1700. m_wndStopFind.ShowWindow(m_fInFind ? SW_HIDE : SW_SHOW);
  1701. m_wndFindNext.ShowWindow(m_fFindNext ? SW_SHOW : SW_HIDE);
  1702. m_wndStartFind.ShowWindow(m_fFindNext ? SW_HIDE : SW_SHOW);
  1703. m_wndStopFind.EnableWindow(!m_fInFind && ((m_fInFind && !m_fCancelFind) || !m_fInFind));
  1704. m_wndCancelFind.EnableWindow(m_fInFind && ((m_fInFind && !m_fCancelFind) || !m_fInFind));
  1705. m_wndStartFind.EnableWindow(!m_fFindNext && (!m_fInFind && !m_strFind.IsEmpty()));
  1706. m_wndFindNext.EnableWindow(m_fFindNext && (!m_fInFind && !m_strFind.IsEmpty()));
  1707. m_wndFindWhatLabel.EnableWindow(!m_fInFind);
  1708. m_wndFindWhat.EnableWindow(!m_fInFind);
  1709. m_wndSearchSelected.EnableWindow(!m_fInFind);
  1710. m_wndSearchCategories.EnableWindow(!m_fInFind);
  1711. }
  1712. //-------------------------------------------------------------------------
  1713. // When the user changes the text in the find what edit box, we need to
  1714. // make sure we keep track of the string, and that we are in "find" (rather
  1715. // than "find next") mode.
  1716. //-------------------------------------------------------------------------
  1717. LRESULT CMSInfo::OnChangeFindWhat(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1718. {
  1719. m_fFindNext = FALSE;
  1720. // Get the find text from the rich edit control (use EM_GETTEXTEX
  1721. // to preserve its Unicode-ness).
  1722. TCHAR szBuffer[MAX_PATH];
  1723. GETTEXTEX gte;
  1724. gte.cb = MAX_PATH;
  1725. gte.flags = GT_DEFAULT;
  1726. gte.codepage = 1200; // Unicode
  1727. gte.lpDefaultChar = NULL;
  1728. gte.lpUsedDefChar = NULL;
  1729. m_wndFindWhat.SendMessage(EM_GETTEXTEX, (WPARAM)&gte, (LPARAM)szBuffer);
  1730. m_strFind = szBuffer;
  1731. UpdateFindControls();
  1732. SetMenuItems();
  1733. return 0;
  1734. }
  1735. //-------------------------------------------------------------------------
  1736. // When the user clicks on Find, it will either be for a "Find" or a
  1737. // "Find Next".
  1738. //-------------------------------------------------------------------------
  1739. LRESULT CMSInfo::OnFind(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  1740. {
  1741. m_fSearchCatNamesOnly = IsDlgButtonChecked(IDC_CHECKSEARCHCATSONLY);
  1742. m_fSearchSelectedCatOnly = IsDlgButtonChecked(IDC_CHECKSEARCHSELECTED);
  1743. if (!m_fFindNext)
  1744. {
  1745. m_fInFind = TRUE;
  1746. m_fCancelFind = FALSE;
  1747. m_fFindNext = TRUE;
  1748. m_iFindLine = -2;
  1749. // Based on the user's setting of "Search selected category only", start
  1750. // with either the selected category or the root category.
  1751. if (m_fSearchSelectedCatOnly)
  1752. m_pcatFind = GetCurrentCategory();
  1753. else
  1754. m_pcatFind = m_pCurrData->GetRootCategory();
  1755. UpdateFindControls();
  1756. ::SetFocus(m_wndCancelFind.m_hWnd);
  1757. }
  1758. else
  1759. {
  1760. if (FindInCurrentCategory())
  1761. return 0;
  1762. m_fInFind = TRUE;
  1763. m_fCancelFind = FALSE;
  1764. UpdateFindControls();
  1765. ::SetFocus(m_wndCancelFind.m_hWnd);
  1766. }
  1767. // The refresh will post a message that data is ready, so we can search the
  1768. // specified category. If we aren't going to refresh the category, we'll just
  1769. // post the message ourselves.
  1770. if (m_pcatFind)
  1771. {
  1772. SetMessage(IDS_SEARCHMESSAGE, 0, TRUE);
  1773. if (m_pcatFind->GetDataSourceType() == LIVE_DATA && !m_fSearchCatNamesOnly)
  1774. ((CMSInfoLiveCategory *) m_pcatFind)->Refresh((CLiveDataSource *) m_pCurrData, FALSE);
  1775. else
  1776. PostMessage(WM_MSINFODATAREADY, 0, (LPARAM)m_pcatFind);
  1777. }
  1778. return 0;
  1779. }
  1780. //-------------------------------------------------------------------------
  1781. // This is the function that's called when the data ready message is
  1782. // received by the window. Look for the data in the current find category.
  1783. // If there is a match, it will be shown and the find operation stopped.
  1784. // Otherwise (unless the option's been selected to search only the current
  1785. // category) continue the find operation with the next category.
  1786. //-------------------------------------------------------------------------
  1787. void CMSInfo::FindRefreshComplete()
  1788. {
  1789. if (m_fCancelFind)
  1790. {
  1791. m_fInFind = FALSE;
  1792. m_fFindNext = FALSE;
  1793. GotoDlgCtrl(m_wndStopFind.m_hWnd);
  1794. // SetMessage(0);
  1795. SelectCategory(GetCurrentCategory());
  1796. UpdateFindControls();
  1797. ::SetFocus(m_wndStartFind.m_hWnd);
  1798. return;
  1799. }
  1800. if (FindInCurrentCategory())
  1801. return;
  1802. // If the user checked "Search selected category only", then we should
  1803. // not look through any additional categories.
  1804. if (m_fSearchSelectedCatOnly)
  1805. m_pcatFind = NULL;
  1806. else
  1807. {
  1808. m_iFindLine = -2;
  1809. CMSInfoCategory * pNextCategory;
  1810. pNextCategory = m_pcatFind->GetFirstChild();
  1811. if (pNextCategory == NULL)
  1812. while (m_pcatFind)
  1813. {
  1814. pNextCategory = m_pcatFind->GetNextSibling();
  1815. if (pNextCategory)
  1816. break;
  1817. m_pcatFind = m_pcatFind->GetParent();
  1818. }
  1819. m_pcatFind = pNextCategory;
  1820. }
  1821. // If the category is NULL, there are no more matches. Return the
  1822. // controls to a normal state and notify the user.
  1823. if (m_pcatFind == NULL)
  1824. {
  1825. m_fInFind = FALSE;
  1826. m_fFindNext = FALSE;
  1827. UpdateFindControls();
  1828. MSInfoMessageBox(IDS_NOMOREMATCHES);
  1829. SelectCategory(GetCurrentCategory());
  1830. GotoDlgCtrl(m_wndStopFind.m_hWnd);
  1831. return;
  1832. }
  1833. SetMessage(IDS_SEARCHMESSAGE);
  1834. if (m_pcatFind->GetDataSourceType() == LIVE_DATA && !m_fSearchCatNamesOnly)
  1835. ((CMSInfoLiveCategory *) m_pcatFind)->Refresh((CLiveDataSource *) m_pCurrData, FALSE);
  1836. else
  1837. PostMessage(WM_MSINFODATAREADY, 0, (LPARAM)m_pcatFind);
  1838. }
  1839. //-------------------------------------------------------------------------
  1840. // Look for the string in the current category. This function will be
  1841. // called when data is avaible for the category. If there is a match, show
  1842. // it and return TRUE, otherwise return FALSE.
  1843. //
  1844. // m_iFindLine contains the list view row number of the last match. If it
  1845. // is -1, it means we are just starting on this category (since we would
  1846. // start looking at row 0). If it is -2, then we should look for the string
  1847. // in the category name. (Note - this might be all we do, depending on the
  1848. // setting for m_fSearchCatNamesOnly.)
  1849. //-------------------------------------------------------------------------
  1850. BOOL CMSInfo::FindInCurrentCategory()
  1851. {
  1852. if (m_pcatFind == NULL)
  1853. return FALSE;
  1854. // The search is case insensitive, so convert our search string to lower case.
  1855. CString strLookFor(m_strFind);
  1856. strLookFor.TrimLeft(_T("\t\r\n "));
  1857. strLookFor.TrimRight(_T("\t\r\n "));
  1858. strLookFor.MakeLower();
  1859. // If m_iFindLine is -2, then we should look at the category name for a match.
  1860. if (m_iFindLine == -2)
  1861. {
  1862. m_iFindLine += 1;
  1863. CString strCatName;
  1864. m_pcatFind->GetNames(&strCatName, NULL);
  1865. strCatName.MakeLower();
  1866. if (strCatName.Find(strLookFor) != -1)
  1867. {
  1868. // There was a match. Get the HTREEITEM for the category and select it.
  1869. HTREEITEM hti = m_pcatFind->GetHTREEITEM();
  1870. if (hti)
  1871. {
  1872. m_fInFind = FALSE;
  1873. m_fFindNext = TRUE;
  1874. TreeView_EnsureVisible(m_tree.m_hWnd, hti);
  1875. TreeView_SelectItem(m_tree.m_hWnd, hti);
  1876. SetMessage(0);
  1877. UpdateFindControls();
  1878. GotoDlgCtrl(m_wndFindNext.m_hWnd);
  1879. return TRUE;
  1880. }
  1881. }
  1882. }
  1883. // If we are search category names only, then we stop here (before looking
  1884. // through the data for this category).
  1885. if (m_fSearchCatNamesOnly)
  1886. return FALSE;
  1887. // If m_iFindLine is -1, then we need to look in the data for this category
  1888. // to see if there is a match. If there is, then we select the category and
  1889. // start looking through the lines of the list view (we can't use the index
  1890. // we found looking through the data directly, because if the list view is
  1891. // sorted we would be searching out of order).
  1892. int iRow, iCol, iRowCount, iColCount;
  1893. if (!m_pcatFind->GetCategoryDimensions(&iColCount, &iRowCount))
  1894. return FALSE;
  1895. if (m_iFindLine == -1)
  1896. {
  1897. CString * pstrCell, strCell;
  1898. BOOL fFound = FALSE;
  1899. for (iRow = 0; iRow < iRowCount && !fFound; iRow++)
  1900. if (m_fAdvanced || !m_pcatFind->IsRowAdvanced(iRow))
  1901. for (iCol = 0; iCol < iColCount && !fFound; iCol++)
  1902. if (m_fAdvanced || !m_pcatFind->IsColumnAdvanced(iCol))
  1903. if (m_pcatFind->GetData(iRow, iCol, &pstrCell, NULL))
  1904. {
  1905. strCell = *pstrCell;
  1906. strCell.MakeLower();
  1907. if (strCell.Find(strLookFor) != -1)
  1908. fFound = TRUE;
  1909. }
  1910. if (!fFound)
  1911. return FALSE;
  1912. // We found data in this category. Select it so it populates the list view.
  1913. HTREEITEM hti = m_pcatFind->GetHTREEITEM();
  1914. if (hti)
  1915. {
  1916. TreeView_EnsureVisible(m_tree.m_hWnd, hti);
  1917. TreeView_SelectItem(m_tree.m_hWnd, hti);
  1918. SetMessage(0);
  1919. }
  1920. }
  1921. // If we get here, m_iFindLine will be >= -1, and represents the line in the
  1922. // list view after which we should start searching.
  1923. m_iFindLine += 1;
  1924. CString strData;
  1925. int iListRowCount = ListView_GetItemCount(m_list.m_hWnd);
  1926. int iListColCount = 0;
  1927. // Determine the number of columns in the list view.
  1928. for (iCol = 0; iCol < iColCount; iCol++)
  1929. if (m_fAdvanced || !m_pcatFind->IsColumnAdvanced(iCol))
  1930. iListColCount += 1;
  1931. while (m_iFindLine < iListRowCount)
  1932. {
  1933. for (iCol = 0; iCol < iListColCount; iCol++)
  1934. {
  1935. ListView_GetItemText(m_list.m_hWnd, m_iFindLine, iCol, strData.GetBuffer(MAX_PATH), MAX_PATH);
  1936. strData.ReleaseBuffer();
  1937. if (strData.GetLength())
  1938. {
  1939. strData.MakeLower();
  1940. if (strData.Find(strLookFor) != -1)
  1941. {
  1942. // We found a match. The category should already be selected,
  1943. // so all we need to do is select the line (and make sure
  1944. // all the other lines are not selected).
  1945. for (int iRow = 0; iRow < iListRowCount; iRow++)
  1946. if (iRow == m_iFindLine)
  1947. {
  1948. ListView_EnsureVisible(m_list.m_hWnd, iRow, TRUE);
  1949. ListView_SetItemState(m_list.m_hWnd, iRow, LVIS_SELECTED, LVIS_SELECTED);
  1950. }
  1951. else
  1952. {
  1953. ListView_SetItemState(m_list.m_hWnd, iRow, 0, LVIS_SELECTED);
  1954. }
  1955. m_fInFind = FALSE;
  1956. m_fFindNext = TRUE;
  1957. SetMessage(0);
  1958. UpdateFindControls();
  1959. GotoDlgCtrl(m_wndFindNext.m_hWnd);
  1960. return TRUE;
  1961. }
  1962. }
  1963. }
  1964. m_iFindLine += 1;
  1965. }
  1966. // If we fall through to here, then there were no more matches in the
  1967. // list view. Return FALSE.
  1968. return FALSE;
  1969. }
  1970. //-------------------------------------------------------------------------
  1971. // ShowFindControls is called to show or hide the dialog controls used
  1972. // for find.
  1973. //-------------------------------------------------------------------------
  1974. void CMSInfo::ShowFindControls()
  1975. {
  1976. int iShowCommand = (m_fFindVisible) ? SW_SHOW : SW_HIDE;
  1977. if (m_fFindVisible)
  1978. PositionFindControls();
  1979. m_wndFindWhatLabel.ShowWindow(iShowCommand);
  1980. m_wndFindWhat.ShowWindow(iShowCommand);
  1981. m_wndSearchSelected.ShowWindow(iShowCommand);
  1982. m_wndSearchCategories.ShowWindow(iShowCommand);
  1983. m_wndStartFind.ShowWindow(iShowCommand);
  1984. m_wndStopFind.ShowWindow(iShowCommand);
  1985. m_wndFindNext.ShowWindow(iShowCommand);
  1986. m_wndCancelFind.ShowWindow(iShowCommand);
  1987. if (iShowCommand == SW_HIDE)
  1988. {
  1989. m_wndFindWhatLabel.EnableWindow(FALSE);
  1990. m_wndFindWhat.EnableWindow(FALSE);
  1991. m_wndSearchSelected.EnableWindow(FALSE);
  1992. m_wndSearchCategories.EnableWindow(FALSE);
  1993. m_wndStartFind.EnableWindow(FALSE);
  1994. m_wndStopFind.EnableWindow(FALSE);
  1995. m_wndFindNext.EnableWindow(FALSE);
  1996. m_wndCancelFind.EnableWindow(FALSE);
  1997. }
  1998. if (!m_fFindVisible)
  1999. return;
  2000. }
  2001. //-------------------------------------------------------------------------
  2002. // Position the find controls on the control surface. This will be called
  2003. // when the find controls are shown, or when the control is resized.
  2004. //-------------------------------------------------------------------------
  2005. int CMSInfo::PositionFindControls()
  2006. {
  2007. if (!m_fFindVisible)
  2008. return 0;
  2009. // Get some useful sizes of the various controls we need to move around
  2010. // the window.
  2011. CRect rectFindWhatLabel, rectFindWhat, rectSearchSelected, rectSearchCategories;
  2012. CRect rectStartFind, rectStopFind, rectClient;
  2013. GetClientRect(&rectClient);
  2014. m_wndFindWhatLabel.GetWindowRect(&rectFindWhatLabel);
  2015. m_wndFindWhat.GetWindowRect(&rectFindWhat);
  2016. m_wndStartFind.GetWindowRect(&rectStartFind);
  2017. m_wndStopFind.GetWindowRect(&rectStopFind);
  2018. m_wndSearchSelected.GetWindowRect(&rectSearchSelected);
  2019. m_wndSearchCategories.GetWindowRect(&rectSearchCategories);
  2020. int iSpacer = 5;
  2021. // The control rect is the space we have to work with for placing the controls.
  2022. CRect rectControl(rectClient);
  2023. rectControl.DeflateRect(iSpacer, iSpacer);
  2024. // Determine if we have enough room to lay out the controls
  2025. // horizontally, or if we need to stack them. Horizontally, it looks like:
  2026. //
  2027. // <spacer><Find What label><spacer><Find What edit><spacer><Start Find><spacer><Stop Find><spacer>
  2028. // <spacer><Search Selected check><spacer><Search Cats check><spacer>
  2029. int cxTopLine = iSpacer * 5 + rectFindWhatLabel.Width() * 2 + rectStartFind.Width() + rectStopFind.Width();
  2030. int cxBottomLine = iSpacer * 3 + rectSearchSelected.Width() + rectSearchCategories.Width();
  2031. BOOL fHorizontal = (cxTopLine <= rectClient.Width() && cxBottomLine <= rectClient.Width());
  2032. // If it get's wider than a certain size, it becomes less usable. So put a reasonable
  2033. // limit on the width:
  2034. int cxMaxWidth = iSpacer * 5 + rectFindWhatLabel.Width() + rectSearchSelected.Width() + rectSearchCategories.Width() + rectStartFind.Width() + rectStopFind.Width();
  2035. if (fHorizontal && rectControl.Width() > cxMaxWidth)
  2036. rectControl.DeflateRect((rectControl.Width() - cxMaxWidth) / 2, 0);
  2037. // Figure the height of the control rectangle.
  2038. int cyControlRectHeight = rectStartFind.Height() + ((fHorizontal) ? 0 : rectStopFind.Height() + iSpacer);
  2039. int cyLeftSideHeight;
  2040. if (fHorizontal)
  2041. cyLeftSideHeight = rectFindWhat.Height() + iSpacer + rectSearchSelected.Height();
  2042. else
  2043. cyLeftSideHeight = rectFindWhat.Height() + iSpacer * 2 + rectSearchSelected.Height() * 2;
  2044. if (cyControlRectHeight < cyLeftSideHeight)
  2045. cyControlRectHeight = cyLeftSideHeight;
  2046. rectControl.top = rectControl.bottom - cyControlRectHeight;
  2047. // Position the buttons appropriately.
  2048. if (fHorizontal)
  2049. {
  2050. rectStopFind.OffsetRect(rectControl.right - rectStopFind.right, rectControl.top - rectStopFind.top);
  2051. rectStartFind.OffsetRect(rectStopFind.left - rectStartFind.right - iSpacer, rectControl.top - rectStartFind.top);
  2052. }
  2053. else
  2054. {
  2055. rectStartFind.OffsetRect(rectControl.right - rectStartFind.right, rectControl.top - rectStartFind.top);
  2056. rectStopFind.OffsetRect(rectControl.right - rectStopFind.right, rectStartFind.bottom + iSpacer - rectStopFind.top);
  2057. }
  2058. // Position the find label and the find edit box.
  2059. rectFindWhatLabel.OffsetRect(rectControl.left - rectFindWhatLabel.left, rectControl.top - rectFindWhatLabel.top + (rectFindWhat.Height() - rectFindWhatLabel.Height()) / 2);
  2060. rectFindWhat.OffsetRect(rectFindWhatLabel.right - rectFindWhat.left + iSpacer, rectControl.top - rectFindWhat.top);
  2061. rectFindWhat.right = rectStartFind.left - iSpacer;
  2062. // Position the check boxes.
  2063. rectSearchSelected.OffsetRect(rectControl.left - rectSearchSelected.left, rectFindWhat.bottom - rectSearchSelected.top + iSpacer);
  2064. if (fHorizontal)
  2065. rectSearchCategories.OffsetRect(rectSearchSelected.right - rectSearchCategories.left + iSpacer, rectSearchSelected.top - rectSearchCategories.top);
  2066. else
  2067. rectSearchCategories.OffsetRect(rectControl.left - rectSearchCategories.left, rectSearchSelected.bottom - rectSearchCategories.top + iSpacer);
  2068. // If the check boxes are going to overlap the buttons (we'd be very narrow), adjust the button
  2069. // position (which might end up off the control, but what're ya gonna do?).
  2070. int iRightMostCheckboxEdge = rectSearchCategories.right;
  2071. if (iRightMostCheckboxEdge < rectSearchSelected.right)
  2072. iRightMostCheckboxEdge = rectSearchSelected.right;
  2073. iRightMostCheckboxEdge += iSpacer;
  2074. if (!fHorizontal && rectStopFind.left < iRightMostCheckboxEdge)
  2075. {
  2076. rectStopFind.OffsetRect(iRightMostCheckboxEdge - rectStopFind.left, 0);
  2077. rectStartFind.OffsetRect(rectStopFind.left - rectStartFind.left, 0);
  2078. rectFindWhat.right = rectStartFind.left - iSpacer;
  2079. }
  2080. m_wndStopFind.MoveWindow(&rectStopFind);
  2081. m_wndStartFind.MoveWindow(&rectStartFind);
  2082. m_wndFindNext.MoveWindow(&rectStartFind);
  2083. m_wndCancelFind.MoveWindow(&rectStopFind);
  2084. m_wndFindWhatLabel.MoveWindow(&rectFindWhatLabel);
  2085. m_wndFindWhat.MoveWindow(&rectFindWhat);
  2086. m_wndSearchSelected.MoveWindow(&rectSearchSelected);
  2087. m_wndSearchCategories.MoveWindow(&rectSearchCategories);
  2088. return (rectControl.Height() + iSpacer * 2);
  2089. }
  2090. //-------------------------------------------------------------------------
  2091. // Refresh all of the data prior to saving, exporting, printing. This will
  2092. // present a dialog box with the refresh message and a progress bar, but
  2093. // will not return until the refresh is completed.
  2094. //-------------------------------------------------------------------------
  2095. void CMSInfo::RefreshData(CLiveDataSource * pSource, CMSInfoLiveCategory * pLiveCategory)
  2096. {
  2097. if (pSource == NULL || pSource->m_pThread == NULL)
  2098. return;
  2099. // Create the dialog with the refresh message and progress
  2100. // bar, and display it.
  2101. CWaitForRefreshDialog dlg;
  2102. dlg.DoRefresh(pSource, pLiveCategory);
  2103. }
  2104. //=============================================================================
  2105. // Functions for managing the DCO (the object providing history).
  2106. //=============================================================================
  2107. STDMETHODIMP CMSInfo::UpdateDCOProgress(VARIANT varPctDone)
  2108. {
  2109. AFX_MANAGE_STATE(AfxGetStaticModuleState())
  2110. //V-stlowe 1/30/2001
  2111. VERIFY(SUCCEEDED(VariantChangeType(&varPctDone,&varPctDone,0,VT_INT)));
  2112. if (this->m_HistoryProgressDlg.IsWindow())//todo: is there a better state function to determine if dlg is modal?
  2113. {
  2114. HWND hWnd = m_HistoryProgressDlg.GetDlgItem(IDC_PROGRESS1);
  2115. if(::IsWindow(hWnd))
  2116. {
  2117. //int nOffset = varPctDone.iVal - (int) ::SendMessage(m_hWnd, PBM_GETPOS, 0, 0);
  2118. //To do: don't rely on 3 (current SAF progress step); find way to get offset.
  2119. ::SendMessage(hWnd, PBM_DELTAPOS,3, 0L);
  2120. }
  2121. }
  2122. return S_OK;
  2123. }
  2124. STDMETHODIMP CMSInfo::SetHistoryStream(IStream *pStream)
  2125. {
  2126. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2127. #ifdef A_STEPHL
  2128. ASSERT(0);
  2129. #endif
  2130. //v-stlowe 2/23/2001 shut down progress bar dialog
  2131. SetEvent(m_hEvtHistoryComplete);
  2132. HRESULT hr = pStream->QueryInterface(IID_IStream,(void**) &m_pHistoryStream);
  2133. if (FAILED(hr) || !m_pHistoryStream)
  2134. {
  2135. m_pHistoryStream = NULL;
  2136. return E_FAIL;
  2137. }
  2138. if (m_pLiveData)
  2139. ((CLiveDataSource *)m_pLiveData)->SetHistoryStream(m_pHistoryStream);
  2140. // When the history stream is available, we need to modify the UI to allow
  2141. // the user to select the history.
  2142. if (!m_fHistoryAvailable)
  2143. {
  2144. m_fHistoryAvailable = TRUE;//actually this should already be true...
  2145. SetMenuItems();
  2146. }
  2147. m_fHistorySaveAvailable = TRUE;
  2148. FillHistoryCombo();
  2149. //if history window is current view, refresh
  2150. if (m_history.IsWindowVisible())
  2151. {
  2152. CMSInfoCategory * pCategory = GetCurrentCategory();
  2153. if (pCategory != NULL && pCategory->GetDataSourceType() == LIVE_DATA)
  2154. {
  2155. m_pLastCurrentCategory = GetCurrentCategory();
  2156. int iIndex = (int)m_history.SendMessage(CB_GETCURSEL, 0, 0);
  2157. if (iIndex == CB_ERR)
  2158. {
  2159. iIndex = 0;
  2160. m_history.SendMessage(CB_SETCURSEL, (WPARAM)iIndex, 0);
  2161. }
  2162. ChangeHistoryView(iIndex);
  2163. }
  2164. }
  2165. else if (m_fShowPCH && !m_history.IsWindowVisible() && m_strMachine.IsEmpty())
  2166. {
  2167. // If m_fShowPCH is set, then the command line option to launch into
  2168. // the history view was selected.
  2169. DispatchCommand(ID_VIEW_HISTORY);
  2170. }
  2171. #ifdef A_STEPHL
  2172. //STATSTG streamStat;
  2173. //hr = m_pHistoryStream->Stat(&streamStat,STATFLAG_NONAME );
  2174. //ASSERT(SUCCEEDED(hr) && "couldn't get stream statistics");
  2175. //BYTE* pBuffer = new BYTE[streamStat.cbSize.LowPart];
  2176. //ULONG ulRead;
  2177. //m_pHistoryStream->Read(pBuffer,streamStat.cbSize.LowPart,&ulRead);
  2178. // CFile file;
  2179. //file.Open("c:\\history.xml", CFile::modeCreate | CFile::modeWrite);
  2180. // file.Write(pBuffer,ulRead);
  2181. // delete pBuffer;
  2182. #endif
  2183. return S_OK;
  2184. }
  2185. STDMETHODIMP CMSInfo::get_DCO_IUnknown(IUnknown **pVal)
  2186. {
  2187. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2188. if (m_pDCO == NULL)
  2189. return E_FAIL;
  2190. return (m_pDCO->QueryInterface(IID_IUnknown,(void**) pVal));
  2191. }
  2192. STDMETHODIMP CMSInfo::put_DCO_IUnknown(IUnknown *newVal)
  2193. {
  2194. //v-stlowe 2/23/2001
  2195. //beware situation where put_DCO_IUnknown gets called before control is finished initializing.
  2196. WaitForSingleObject(m_evtControlInit,INFINITE);
  2197. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2198. HRESULT hr = newVal->QueryInterface( __uuidof(ISAFDataCollection), (void**)&m_pDCO );
  2199. if (FAILED(hr))
  2200. return E_FAIL;
  2201. //end v-stlowe 2/23/2001
  2202. TCHAR szDataspecPath[MAX_PATH];
  2203. if (ExpandEnvironmentStrings(_T("%windir%\\pchealth\\helpctr\\config\\dataspec.xml"), szDataspecPath, MAX_PATH))
  2204. {
  2205. hr = m_pDCO->put_MachineData_DataSpec(CComBSTR(szDataspecPath));
  2206. hr = m_pDCO->put_History_DataSpec(CComBSTR(szDataspecPath));
  2207. // This is done by the script now: m_pDCO->ExecuteAsync();
  2208. }
  2209. // Have to put this after the calls made using the DCO, so that the /pch
  2210. // flag (which is to start MSInfo with history showing) works.
  2211. if (!m_fHistoryAvailable)
  2212. {
  2213. m_fHistoryAvailable = TRUE;
  2214. if (m_fShowPCH && !m_history.IsWindowVisible() && m_strMachine.IsEmpty())
  2215. DispatchCommand(ID_VIEW_HISTORY);
  2216. SetMenuItems();
  2217. }
  2218. return S_OK;
  2219. }
  2220. //=============================================================================
  2221. // Interface methods to do a silent save of a file.
  2222. //=============================================================================
  2223. STDMETHODIMP CMSInfo::SaveFile(BSTR filename, BSTR computer, BSTR category)
  2224. {
  2225. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2226. CString strFilename(filename);
  2227. CString strComputer(computer);
  2228. CString strCategory(category);
  2229. HRESULT hr = E_FAIL;
  2230. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  2231. CLiveDataSource * pSilentSource = new CLiveDataSource;
  2232. if (pSilentSource)
  2233. hr = pSilentSource->Create(strComputer, NULL, strCategory);
  2234. if (SUCCEEDED(hr))
  2235. {
  2236. m_fNoUI = TRUE;
  2237. CDataSource * pOldSource = m_pCurrData;
  2238. m_pCurrData = pSilentSource;
  2239. if (strFilename.Right(4).CompareNoCase(CString(_T(".nfo"))) == 0)
  2240. SaveMSInfoFile(strFilename);
  2241. else
  2242. ExportFile(strFilename, 0);
  2243. m_pCurrData = pOldSource;
  2244. delete pSilentSource;
  2245. m_fNoUI = FALSE;
  2246. }
  2247. return hr;
  2248. }
  2249. LRESULT CHistoryRefreshDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2250. {
  2251. return 1; // Let the system set the focus
  2252. }