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.

691 lines
19 KiB

  1. // GathSrc.cpp - Implementation of the WBEM Data Source and Folder Objects
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation
  4. #include <io.h>
  5. #include "StdAfx.h"
  6. #include "DataSrc.h"
  7. #include "gather.h"
  8. #include "Resource.h"
  9. #include "resrc1.h"
  10. #include <atlbase.h> // Last to prevent a #error statement about <windows.h>
  11. LPCTSTR cszDefaultNFT = _T("default.nft");
  12. LPCTSTR cszClsid = _T("Clsid");
  13. LPCTSTR cszInprocServerKey = _T("InprocServer32");
  14. LPCTSTR cszDefaultDirectory = _T("Microsoft Shared\\MSInfo");
  15. LPCTSTR cszProgramFiles = _T("C:\\Program Files");
  16. LPCTSTR cszRegistryRoot = _T("Software\\Microsoft\\Shared Tools\\MSInfo");
  17. LPCTSTR cszDirectoryKey = _T("Path");
  18. /*
  19. * GetInprocServerDirectory - Return the directory portion of the InprocServer32
  20. * Subkey of HKEY_CLASSES_ROOT\Clsid\<cszClassID>
  21. *
  22. * History: a-jsari 10/24/97 Initial version
  23. */
  24. static inline BOOL GetInprocServerDirectory(LPCTSTR cszClassID, LPTSTR szDirectoryBuffer, DWORD &dwSize)
  25. {
  26. CRegKey rkDirectory;
  27. CRegKey rkSubdirectory;
  28. long lResult = rkDirectory.Open(HKEY_CLASSES_ROOT, _T("Clsid"), KEY_QUERY_VALUE);
  29. ASSERT(lResult == ERROR_SUCCESS);
  30. if (lResult != ERROR_SUCCESS) return FALSE;
  31. lResult = rkSubdirectory.Open(rkDirectory, cszClassID, KEY_QUERY_VALUE);
  32. ASSERT(lResult == ERROR_SUCCESS);
  33. if (lResult != ERROR_SUCCESS) return FALSE;
  34. lResult = rkDirectory.Open(rkSubdirectory, cszInprocServerKey, KEY_QUERY_VALUE);
  35. ASSERT(lResult == ERROR_SUCCESS);
  36. if (lResult != ERROR_SUCCESS) return FALSE;
  37. // Pointer == NULL: Get the default value
  38. lResult = rkDirectory.QueryValue(szDirectoryBuffer, NULL, &dwSize);
  39. ASSERT(lResult == ERROR_SUCCESS);
  40. if (lResult != ERROR_SUCCESS) return FALSE;
  41. unsigned short ch = '\\';
  42. LPTSTR szEnd = ::_tcsrchr(szDirectoryBuffer, ch);
  43. ASSERT(szEnd != NULL);
  44. if (szEnd == NULL) return FALSE;
  45. *szEnd = 0;
  46. return TRUE;
  47. }
  48. /*
  49. * GetDefaultMSInfoDirectory - Get the location of the Program Files directory from the
  50. * Registry and append our known path to it.
  51. *
  52. * History: a-jsari 11/21/97 Initial version
  53. */
  54. void CMSInfoFile::GetDefaultMSInfoDirectory(LPTSTR szDefaultDirectory, DWORD dwSize)
  55. {
  56. CRegKey keyProgramFiles;
  57. long lResult;
  58. do {
  59. lResult = keyProgramFiles.Open(HKEY_LOCAL_MACHINE, cszWindowsCurrentKey);
  60. ASSERT(lResult == ERROR_SUCCESS);
  61. if (lResult != ERROR_SUCCESS) break;
  62. lResult = keyProgramFiles.QueryValue(szDefaultDirectory, cszCommonFilesValue, &dwSize);
  63. ASSERT(lResult == ERROR_SUCCESS);
  64. } while (FALSE);
  65. if (lResult != ERROR_SUCCESS) {
  66. _tcscpy(szDefaultDirectory, cszProgramFiles);
  67. }
  68. _tcsncat(szDefaultDirectory, cszDefaultDirectory, dwSize);
  69. }
  70. /*
  71. * CWBEMDataSource - Constructor. Defaults to loading all .nft files in the
  72. * DLL file's directory. Alternately, loads the szTemplateFile as a
  73. * template file.
  74. *
  75. * History: a-jsari 10/15/97 Initial version.
  76. */
  77. CWBEMDataSource::CWBEMDataSource(LPCTSTR szMachineName)
  78. : m_pGatherer(new CDataGatherer),
  79. m_strMachineName(_T("")),
  80. CDataSource(szMachineName),
  81. m_fEverRefreshed(FALSE),
  82. m_pThreadRefresh(NULL)
  83. {
  84. BOOL fGathererResult;
  85. // m_pGatherer is deleted in the CWBEMDataSource destructor.
  86. ASSERT(m_pGatherer);
  87. if (m_pGatherer == NULL)
  88. ::AfxThrowMemoryException();
  89. if (szMachineName != NULL)
  90. {
  91. if ((*szMachineName == (TCHAR)'\\' || *szMachineName == (TCHAR)'/')
  92. && (szMachineName[1] == (TCHAR)'\\' || szMachineName[1] == (TCHAR)'/'))
  93. szMachineName += 2;
  94. }
  95. m_strMachineName = szMachineName;
  96. fGathererResult = m_pGatherer->Create(szMachineName);
  97. if (fGathererResult == FALSE)
  98. {
  99. CString strErrorMessage, strTitle;
  100. DWORD dwError = m_pGatherer->GetLastError();
  101. AFX_MANAGE_STATE(::AfxGetStaticModuleState()); // Needed for AfxGetMainWnd()
  102. switch (dwError)
  103. {
  104. case GATH_ERR_ALLOCATIONFAILED:
  105. case GATH_ERR_NOWBEMOUTOFMEM:
  106. ::AfxThrowMemoryException();
  107. break;
  108. case GATH_ERR_NOWBEMCONNECT:
  109. strErrorMessage.Format(IDS_NOGATHERER, szMachineName);
  110. break;
  111. case GATH_ERR_NOWBEMLOCATOR:
  112. strErrorMessage.Format(IDS_NOLOCATOR, szMachineName);
  113. break;
  114. case GATH_ERR_NOWBEMACCESSDENIED:
  115. strErrorMessage.Format(IDS_GATHERACCESS, szMachineName);
  116. break;
  117. case GATH_ERR_NOWBEMBADSERVER:
  118. strErrorMessage.Format(IDS_BADSERVER, szMachineName);
  119. break;
  120. case GATH_ERR_NOWBEMNETWORKFAILURE:
  121. strErrorMessage.Format(IDS_NETWORKERROR, szMachineName);
  122. break;
  123. case GATH_ERR_BADCATEGORYID:
  124. strErrorMessage.LoadString(IDS_UNEXPECTED);
  125. break;
  126. }
  127. strTitle.LoadString( IDS_DESCRIPTION);
  128. ::MessageBox( ::AfxGetMainWnd()->GetSafeHwnd(), strErrorMessage, strTitle, MB_OK);
  129. delete m_pGatherer;
  130. ::AfxThrowUserException();
  131. }
  132. m_pThreadRefresh = new CThreadingRefresh(m_pGatherer);
  133. }
  134. #if FALSE
  135. BOOL fGathererResult;
  136. CString strFile;
  137. TCHAR szTemplateBuffer[MAX_PATH];
  138. // m_pGatherer is deleted in the CWBEMDataSource destructor.
  139. ASSERT(m_pGatherer);
  140. if (m_pGatherer == NULL)
  141. ::AfxThrowMemoryException();
  142. int wBufferSize = sizeof(szTemplateBuffer) / sizeof(TCHAR);
  143. // Change directory to the directory where our snap-in DLL lives.
  144. ChangeToTemplateDirectory(szTemplateBuffer, wBufferSize);
  145. do {
  146. // Load the default file and all .nft files in the current directory.
  147. // Remove a leading \\ or a leading // from the machine name.
  148. if (szMachineName != NULL) {
  149. if ((*szMachineName == (TCHAR)'\\' || *szMachineName == (TCHAR)'/')
  150. && (szMachineName[1] == (TCHAR)'\\' || szMachineName[1] == (TCHAR)'/'))
  151. szMachineName += 2;
  152. }
  153. m_strMachineName = szMachineName;
  154. strFile = szTemplateBuffer;
  155. fGathererResult = m_pGatherer->Create(strFile, szMachineName);
  156. if (fGathererResult == FALSE)
  157. break;
  158. // Read all subsidiary template files.
  159. CFileFind ffTemplate;
  160. if (ffTemplate.FindFile(_T("*.nft"))) {
  161. BOOL fResult;
  162. do {
  163. fResult = ffTemplate.FindNextFile();
  164. if (!fResult) {
  165. DWORD dwError = ::GetLastError();
  166. ASSERT(dwError == ERROR_NO_MORE_FILES);
  167. }
  168. strFile = ffTemplate.GetFileName();
  169. // Don't reload the default template file.
  170. if (strFile.CompareNoCase(cszDefaultNFT) == 0) continue;
  171. // fGathererResult = m_pGatherer->AddTemplateFile(ffTemplate.GetFilePath());
  172. if (fGathererResult == FALSE)
  173. break;
  174. } while (fResult);
  175. } else {
  176. fGathererResult = FALSE;
  177. break;
  178. }
  179. } while (FALSE);
  180. if (fGathererResult == FALSE) {
  181. CString strErrorMessage, strTitle;
  182. DWORD dwError = m_pGatherer->GetLastError();
  183. AFX_MANAGE_STATE(::AfxGetStaticModuleState()); // Needed for AfxGetMainWnd
  184. switch (dwError) {
  185. case GATH_ERR_ALLOCATIONFAILED:
  186. case GATH_ERR_NOWBEMOUTOFMEM:
  187. ::AfxThrowMemoryException();
  188. break;
  189. case GATH_ERR_NOWBEMCONNECT:
  190. strErrorMessage.Format(IDS_NOGATHERER, szMachineName);
  191. break;
  192. case GATH_ERR_NOWBEMLOCATOR:
  193. strErrorMessage.Format(IDS_NOLOCATOR, szMachineName);
  194. break;
  195. case GATH_ERR_NOWBEMACCESSDENIED:
  196. strErrorMessage.Format(IDS_GATHERACCESS, szMachineName);
  197. break;
  198. case GATH_ERR_NOWBEMBADSERVER:
  199. strErrorMessage.Format(IDS_BADSERVER, szMachineName);
  200. break;
  201. case GATH_ERR_NOWBEMNETWORKFAILURE:
  202. strErrorMessage.Format(IDS_NETWORKERROR, szMachineName);
  203. break;
  204. case GATH_ERR_BADCATEGORYID:
  205. strErrorMessage.LoadString(IDS_UNEXPECTED);
  206. break;
  207. }
  208. strTitle.LoadString(IDS_DESCRIPTION);
  209. ::MessageBox( ::AfxGetMainWnd()->GetSafeHwnd(), strErrorMessage, strTitle, MB_OK);
  210. delete m_pGatherer;
  211. ::AfxThrowUserException();
  212. }
  213. }
  214. #endif
  215. /*
  216. * ~CWBEMDataSource - Destructor - Delete the gatherer pointer.
  217. *
  218. * History: a-jsari 10/15/97 Initial version
  219. */
  220. CWBEMDataSource::~CWBEMDataSource()
  221. {
  222. delete m_pGatherer;
  223. if (m_pThreadRefresh)
  224. {
  225. delete m_pThreadRefresh;
  226. m_pThreadRefresh = NULL;
  227. }
  228. }
  229. /*
  230. * GetNodeName - Return the node name for the root node.
  231. *
  232. * History: a-jsari 1/16/98 Initial version.
  233. */
  234. BOOL CWBEMDataSource::GetNodeName(CString &strName)
  235. {
  236. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  237. if (m_strMachineName.GetLength() > 0)
  238. strName.Format(IDS_NODENAME, (LPCTSTR)m_strMachineName);
  239. else {
  240. CString strLocal;
  241. VERIFY(strLocal.LoadString(IDS_LOCALMACHINE));
  242. strName.Format(IDS_NODENAME, (LPCTSTR)strLocal);
  243. }
  244. return TRUE;
  245. }
  246. /*
  247. * SetMachineName - Sets the name of the connected machine.
  248. *
  249. * History: a-jsari 1/16/98 Initial version.
  250. */
  251. BOOL CWBEMDataSource::SetMachineName(const CString &strMachine)
  252. {
  253. BOOL fReturn;
  254. m_strMachineName = strMachine;
  255. fReturn = m_pGatherer->SetConnect(strMachine);
  256. if (fReturn == FALSE) {
  257. CString strErrorMessage, strTitle;
  258. DWORD dwError = m_pGatherer->GetLastError();
  259. // Needed for AfxGetMainWnd and LoadString/Format
  260. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  261. switch (dwError) {
  262. case GATH_ERR_NOWBEMCONNECT:
  263. strErrorMessage.Format(IDS_NOGATHERER, (LPCTSTR)strMachine);
  264. break;
  265. case GATH_ERR_NOWBEMLOCATOR:
  266. strErrorMessage.Format(IDS_NOLOCATOR, (LPCTSTR)strMachine);
  267. break;
  268. case GATH_ERR_NOWBEMACCESSDENIED:
  269. strErrorMessage.Format(IDS_GATHERACCESS, (LPCTSTR)strMachine);
  270. break;
  271. case GATH_ERR_NOWBEMBADSERVER:
  272. strErrorMessage.Format(IDS_BADSERVER, (LPCTSTR)strMachine);
  273. break;
  274. case GATH_ERR_NOWBEMNETWORKFAILURE:
  275. strErrorMessage.Format(IDS_NETWORKERROR, (LPCTSTR)strMachine);
  276. break;
  277. default:
  278. VERIFY(strErrorMessage.LoadString(IDS_UNEXPECTED));
  279. ASSERT(FALSE);
  280. break;
  281. }
  282. strTitle.LoadString(IDS_DESCRIPTION);
  283. ::MessageBox( ::AfxGetMainWnd()->GetSafeHwnd(), strErrorMessage, strTitle, MB_OK);
  284. }
  285. return fReturn;
  286. }
  287. /*
  288. * Find - Locate in the tree, by path and line number, the string contained
  289. * in strSearch.
  290. *
  291. * History: a-jsari 12/11/97 Initial version
  292. */
  293. BOOL CWBEMDataSource::Find(const CString &strSearch, long lFindOptions)
  294. {
  295. BOOL fReturn;
  296. MSI_FIND_STRUCT mfsFind;
  297. StartSearch();
  298. mfsFind.m_fSearchData = (lFindOptions & FIND_OPTION_CATEGORY_ONLY) == 0;
  299. if ((lFindOptions & FIND_OPTION_REPEAT_SEARCH) == 0) {
  300. if ((lFindOptions & FIND_OPTION_ONE_CATEGORY) != 0) {
  301. // Set our path to the selected node.
  302. ASSERT(m_pfLast != NULL);
  303. m_pfLast->InternalName(m_strPath);
  304. m_iLine = -1;
  305. } else {
  306. m_strPath = _T("");
  307. }
  308. m_strParentPath = m_strPath;
  309. m_iLine = -1;
  310. } else {
  311. // The root path does not have specific lines. (This if statement will
  312. // fail if we cancel a find and then repeat it, when we don't want to
  313. // increment the initial line to search.)
  314. // We do want to increment the line, even when the path is empty. Otherwise,
  315. // we can't get past a match on the root category when we do a find next.
  316. // [old code] if (!m_strPath.IsEmpty()) ++m_iLine;
  317. ++m_iLine;
  318. }
  319. mfsFind.m_strSearch = strSearch;
  320. mfsFind.m_fCaseSensitive = FALSE;
  321. mfsFind.m_fSearchCategories = TRUE;
  322. mfsFind.m_strParentPath = m_strParentPath;
  323. mfsFind.m_strPath = m_strPath;
  324. mfsFind.m_iLine = m_iLine;
  325. mfsFind.m_pfCancel = &m_fCanceled;
  326. fReturn = m_pGatherer->Find(&mfsFind);
  327. if (mfsFind.m_fFound) {
  328. m_strPath = mfsFind.m_strPath;
  329. m_iLine = mfsFind.m_iLine;
  330. return TRUE;
  331. }
  332. return FALSE;
  333. }
  334. #if 0
  335. /*
  336. * StopSearch - Ends the current search
  337. *
  338. * History: a-jsari 1/19/98 Initial version
  339. */
  340. BOOL CWBEMDataSource::StopSearch()
  341. {
  342. return FALSE;
  343. }
  344. #endif
  345. /*
  346. * GetRootNode - Return the root CFolder pointer.
  347. *
  348. * History: a-jsari 10/15/97 Initial version
  349. */
  350. CFolder *CWBEMDataSource::GetRootNode()
  351. {
  352. if (!m_RootFolder) {
  353. // Deleted in the CWBEMDataSource destructor
  354. m_RootFolder = new CWBEMFolder(m_pGatherer->GetRootDataCategory(), this);
  355. if (m_RootFolder == NULL) AfxThrowMemoryException();
  356. }
  357. return CDataSource::GetRootNode();
  358. }
  359. /*
  360. * SetDataComplexity - Set the gatherer's data complexity.
  361. *
  362. * History: a-jsari 12/3/97 Initial version.
  363. */
  364. BOOL CWBEMDataSource::SetDataComplexity(enum DataComplexity Complexity)
  365. {
  366. CDataSource::SetDataComplexity(Complexity);
  367. return m_pGatherer->SetDataComplexity(Complexity);
  368. }
  369. /*
  370. * Save - Save information about the data source to a stream.
  371. *
  372. * History: a-jsari 11/13/97 Initial version
  373. */
  374. HRESULT CWBEMDataSource::Save(IStream *pStm)
  375. {
  376. unsigned wValue;
  377. ULONG cWrite;
  378. HRESULT hResult;
  379. USES_CONVERSION;
  380. wValue = GetType();
  381. hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite);
  382. ASSERT(SUCCEEDED(hResult) && (cWrite == sizeof(wValue)));
  383. wValue = m_strMachineName.GetLength();
  384. hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite);
  385. wValue *= sizeof(WCHAR);
  386. ASSERT(SUCCEEDED(hResult) && (cWrite == sizeof(wValue)));
  387. if (wValue != 0) {
  388. // Write the machine name as a wide character string to avoid
  389. // conversion issues.
  390. LPWSTR pszMachine = T2W(const_cast<LPTSTR>((LPCTSTR)m_strMachineName));
  391. hResult = pStm->Write(pszMachine, wValue, &cWrite);
  392. ASSERT(SUCCEEDED(hResult) && (cWrite == wValue));
  393. }
  394. return hResult;
  395. }
  396. /*
  397. * CWBEMFolder - Construct a folder.
  398. *
  399. * History: a-jsari 10/15/97 Initial version
  400. */
  401. CWBEMFolder::CWBEMFolder(CDataCategory *pCategory, CDataSource *pDataSource, CFolder *pParentNode)
  402. :CListViewFolder(pDataSource, pParentNode), m_pCategory(pCategory), m_fBeenRefreshed(FALSE)
  403. {
  404. ASSERT(pDataSource != NULL);
  405. ASSERT(pDataSource->GetType() == CDataSource::GATHERER);
  406. if (pParentNode)
  407. ASSERT(pParentNode->GetType() == CDataSource::GATHERER);
  408. }
  409. /*
  410. * ~CWBEMFolder - Destruct the folder.
  411. *
  412. * History: a-jsari 10/15/97 Initial version
  413. */
  414. CWBEMFolder::~CWBEMFolder()
  415. {
  416. delete m_pCategory;
  417. }
  418. /*
  419. * GetColumns - Return the number of columns.
  420. *
  421. * History: a-jsari 10/15/97 Initial version
  422. */
  423. unsigned CWBEMFolder::GetColumns() const
  424. {
  425. ASSERT(m_pCategory != NULL);
  426. if (m_pCategory == NULL)
  427. return 0;
  428. if (m_pCategory->GetResultType() != CDataCategory::LISTVIEW) return 0;
  429. return (int) dynamic_cast<CDataListCategory *>(m_pCategory)->GetColumnCount();
  430. }
  431. /*
  432. * GetColumnTextAndWidth - Return the column width and text of the specified column.
  433. *
  434. * History: a-jsari 10/15/97 Initial version
  435. */
  436. BOOL CWBEMFolder::GetColumnTextAndWidth(unsigned iColumn, CString &strName, unsigned &uWidth) const
  437. {
  438. if (m_pCategory->GetResultType() != CDataCategory::LISTVIEW) {
  439. ASSERT(FALSE);
  440. return FALSE;
  441. }
  442. BOOL fResult;
  443. fResult = dynamic_cast<CDataListCategory *>(m_pCategory)->
  444. GetColumnCaption((DWORD)iColumn, strName);
  445. ASSERT(fResult);
  446. if (!fResult) return FALSE;
  447. fResult = dynamic_cast<CDataListCategory *>(m_pCategory)->
  448. GetColumnWidth((DWORD)iColumn, (DWORD &)uWidth);
  449. ASSERT(fResult);
  450. return fResult;
  451. }
  452. /*
  453. * GetSubElement - Return the name of the sub-element indexed by iRow, iColumn
  454. *
  455. * History: a-jsari 10/15/97 Initial version
  456. */
  457. BOOL CWBEMFolder::GetSubElement(unsigned iRow, unsigned iColumn, CString &szName) const
  458. {
  459. DWORD dwSortIndex;
  460. if (m_pCategory->GetResultType() != CDataCategory::LISTVIEW) {
  461. ASSERT(FALSE);
  462. return FALSE;
  463. }
  464. // dwSortIndex ignored - should be stored in sort array
  465. return dynamic_cast<CDataListCategory *>(m_pCategory)->GetValue(iRow, iColumn, szName, dwSortIndex);
  466. }
  467. /*
  468. * GetSortType - Return the type of sorting which goes on for each column.
  469. *
  470. * History: a-jsari 12/1/97 Initial version
  471. */
  472. BOOL CWBEMFolder::GetSortType(unsigned iColumn, MSIColumnSortType &stColumn) const
  473. {
  474. if (m_pCategory->GetResultType() != CDataCategory::LISTVIEW) {
  475. ASSERT(FALSE);
  476. return 0;
  477. }
  478. if (!dynamic_cast<CDataListCategory *>(m_pCategory)->GetColumnSort((DWORD)iColumn, stColumn))
  479. stColumn = NOSORT;
  480. return TRUE;
  481. }
  482. /*
  483. * GetSortIndex - Returns the index of a specific Row/Column indexed element.
  484. *
  485. * History: a-jsari 12/1/97 Initial version.
  486. */
  487. DWORD CWBEMFolder::GetSortIndex(unsigned iRow, unsigned iColumn) const
  488. {
  489. DWORD dwSortIndex;
  490. CString szName;
  491. if (m_pCategory->GetResultType() != CDataCategory::LISTVIEW) {
  492. ASSERT(FALSE);
  493. return 0;
  494. }
  495. VERIFY(dynamic_cast<CDataListCategory *>(m_pCategory)->GetValue(iRow, iColumn, szName, dwSortIndex));
  496. return dwSortIndex;
  497. }
  498. /*
  499. * GetRows - returns the number of rows in the folder.
  500. *
  501. * History: a-jsari 10/15/97 Initial version
  502. */
  503. unsigned CWBEMFolder::GetRows() const
  504. {
  505. // Add NULL check to fix 277774.
  506. if (m_pCategory == NULL || m_pCategory->GetResultType() != CDataCategory::LISTVIEW) return 0;
  507. return (int) dynamic_cast<CDataListCategory *>(m_pCategory)->GetRowCount();
  508. }
  509. /*
  510. * GetNextNode - Return the folder's next sibling pointer, creating a CFolder
  511. * from the CDataCategory pointer if necessary.
  512. *
  513. * History: a-jsari 10/15/97 Initial version
  514. */
  515. CFolder *CWBEMFolder::GetNextNode()
  516. {
  517. // If we haven't tested this next pointer before, create the next CFolder.
  518. if (fNextTested == FALSE) {
  519. fNextTested = TRUE;
  520. ASSERT(m_pCategory != NULL);
  521. if (m_pCategory == NULL)
  522. return NULL;
  523. CDataCategory *NextCategory = m_pCategory->GetNextSibling();
  524. if (NextCategory) {
  525. m_NextFolder = new CWBEMFolder(NextCategory, m_pDataSource, GetParentNode());
  526. if (m_NextFolder == NULL)
  527. AfxThrowMemoryException();
  528. }
  529. }
  530. return m_NextFolder;
  531. }
  532. /*
  533. * GetChildNode - Return the CFolder which represents the child's category.
  534. *
  535. * History: a-jsari 10/15/97 Initial version
  536. */
  537. CFolder *CWBEMFolder::GetChildNode()
  538. {
  539. // If we haven't tested this child pointer, create the child CFolder.
  540. if (fChildTested == FALSE) {
  541. fChildTested = TRUE;
  542. ASSERT(m_pCategory != NULL);
  543. if (m_pCategory == NULL)
  544. return FALSE;
  545. CDataCategory *ChildCategory = m_pCategory->GetChild();
  546. if (ChildCategory) {
  547. m_ChildFolder = new CWBEMFolder(ChildCategory, m_pDataSource, this);
  548. if (m_ChildFolder == NULL)
  549. AfxThrowMemoryException();
  550. }
  551. }
  552. return m_ChildFolder;
  553. }
  554. /*
  555. * HasDynamicChildren - Return a flag describing whether any of the children of
  556. * the folder have any dynamic data items.
  557. *
  558. * History: a-jsari 10/15/97 Initial version
  559. */
  560. BOOL CWBEMFolder::HasDynamicChildren() const
  561. {
  562. return m_pCategory->HasDynamicChildren(TRUE);
  563. }
  564. /*
  565. * IsDynamic - Determine whether the category has any dynamic data items.
  566. *
  567. * History: a-jsari 10/15/97 Initial version
  568. */
  569. BOOL CWBEMFolder::IsDynamic() const
  570. {
  571. return m_pCategory->IsDynamic();
  572. }
  573. /*
  574. * Refresh - Refresh this node in the tree.
  575. *
  576. * History: a-jsari 10/15/97 Initial version
  577. */
  578. BOOL CWBEMFolder::Refresh(BOOL fRecursive)
  579. {
  580. ASSERT(m_pCategory != NULL);
  581. if (m_pCategory == NULL)
  582. return FALSE;
  583. if (DataSource() && CDataSource::GATHERER == DataSource()->GetType())
  584. {
  585. CWBEMDataSource * pSource = reinterpret_cast<CWBEMDataSource *>(DataSource());
  586. if (pSource && pSource->m_pThreadRefresh)
  587. {
  588. pSource->m_pThreadRefresh->RefreshAll(this, NULL);
  589. return TRUE;
  590. }
  591. }
  592. return m_pCategory->Refresh(fRecursive);
  593. }
  594. /*
  595. * GetColumnComplexity - Return the Complexity for the given column.
  596. *
  597. * History: a-jsari 12/23/97 Initial version
  598. */
  599. DataComplexity CWBEMFolder::GetColumnComplexity(unsigned iColumn)
  600. {
  601. DataComplexity dcCurrent = BASIC;//ASSUMPTION :To avoid uninitialized memory warning by Prefix.
  602. ASSERT(iColumn < GetColumns());
  603. VERIFY(reinterpret_cast<CDataListCategory *>(m_pCategory)->GetColumnDataComplexity(iColumn, dcCurrent));
  604. return dcCurrent;
  605. }
  606. /*
  607. * GetRowComplexity - Return the Complexity for the given row.
  608. *
  609. * History: a-jsari 12/23/97 Initial version
  610. */
  611. DataComplexity CWBEMFolder::GetRowComplexity(unsigned iRow)
  612. {
  613. DataComplexity dcCurrent = BASIC;//ASSUMPTION :To avoid uninitialized memory warning by Prefix.
  614. ASSERT(iRow < GetRows());
  615. VERIFY(reinterpret_cast<CDataListCategory *>(m_pCategory)->GetRowDataComplexity(iRow, dcCurrent));
  616. return dcCurrent;
  617. }