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.

574 lines
18 KiB

  1. // DataSrc.h Objects which provide the sources of data for the MMC
  2. // data display; One object exists for Gatherer (WBEM:Web-Based
  3. // Enterprise Management), one for version 5.0 save files, and
  4. // one for version 4.10 save files.
  5. //
  6. // This module contains interface. Implementation for these objects
  7. // live in GathSrc.cpp (Gatherer), V500File.cpp (Version 5.0 file),
  8. // and V410File.cpp (Version 4.1 file), DataSrc.cpp (shared functions)
  9. //
  10. // History: a-jsari 10/9/97 Initial version
  11. //
  12. // Copyright (c) 1998-1999 Microsoft Corporation
  13. #pragma once // MSINFO_DATASRC_H
  14. #define MSINFO_DATASRC_H
  15. #include <afxtempl.h>
  16. #include "StdAfx.h"
  17. #include "gather.h"
  18. #include "FileIO.h"
  19. #include "StrList.h"
  20. #include "thread.h"
  21. #include <mmc.h>
  22. class CFolder;
  23. class CBufferFolder;
  24. /*
  25. * CDataSource - Abstract base for a source for display data.
  26. *
  27. * History: a-jsari 10/9/97 Initial version
  28. */
  29. class CDataSource {
  30. public:
  31. // Allow FindNext to access our internal path variable.
  32. friend class CSystemInfoScope;
  33. friend class CFolder;
  34. // Enumerate the different types of sources we can use to
  35. enum SourceType {
  36. GATHERER = 0x80, OCX = 0x40, BUFFER = 0x08,
  37. V410FILE = 0x09, V500FILE = 0x0a, TEXTFILE = 0x0c
  38. };
  39. enum FindOptions {
  40. FIND_OPTION_ONE_CATEGORY = 0x01,
  41. FIND_OPTION_CATEGORY_ONLY = 0x02,
  42. FIND_OPTION_REPEAT_SEARCH = 0x04
  43. };
  44. CDataSource(LPCTSTR szMachineName);
  45. virtual ~CDataSource();
  46. virtual BOOL GetNodeName(CString &strName);
  47. virtual BOOL SetDataComplexity(enum DataComplexity Complexity);
  48. virtual SourceType GetType() const = 0;
  49. virtual CFolder *GetRootNode() { return m_RootFolder; }
  50. virtual BOOL Refresh(BOOL fOptional = FALSE) = 0;
  51. virtual HRESULT Save(IStream *pStm) = 0;
  52. virtual BOOL Find(const CString & strSearch, long lFindOptions = 0) = 0;
  53. // StopSearch is called asynchronously by the Find UI thread.
  54. // No CriticalSection because the method is atomic and no race conditions
  55. // can exist.
  56. BOOL StartSearch()
  57. { if (!m_fCanceled) return FALSE; m_fCanceled = FALSE; return TRUE; }
  58. virtual BOOL StopSearch()
  59. { if (m_fCanceled) return FALSE; m_fCanceled = TRUE; return TRUE; };
  60. BOOL FindStopped() { return m_fCanceled; }
  61. void SetLastFolder(CFolder *pFolder) { m_pfLast = pFolder; }
  62. HRESULT SaveFile(LPCTSTR cszFilename, CFolder *pSaveRoot = NULL);
  63. HRESULT ReportWrite(LPCTSTR szReportFile, CFolder *pRootNode = NULL);
  64. BOOL PrintReport(CPrintDialog *pdlgPrint, CFolder *pfolSelection = NULL);
  65. BOOL RefreshPrintData(CPrintDialog * pdlgPrint, CFolder * pfolSelection);
  66. const CString &MachineName() { return m_strHeaderLeft; }
  67. virtual BOOL SetCategories(const CString & strCategory) { return FALSE; };
  68. static CDataSource *CreateFromIStream(IStream *pStm);
  69. protected:
  70. // Data save functions.
  71. HRESULT WriteOutput(CMSInfoFile *pFile, CFolder *pRootNode);
  72. void WriteChildMark(CMSInfoFile *pFile);
  73. void WriteEndMark(CMSInfoFile *pFile);
  74. void WriteNextMark(CMSInfoFile *pFile);
  75. void WriteParentMark(CMSInfoFile *pFile, unsigned count);
  76. // Print functions.
  77. int BeginPrinting(CPrintDialog *pdlgPrint, CFolder *pfolSelection);
  78. void GetLine(LPTSTR szLineBuffer, int cSize);
  79. void GetTextSize(int &cLineLength, int &cCharHeight, CRect &rectOuter,
  80. CRect &rectText);
  81. void PrintPage(CPrintDialog *pdlgPrint);
  82. void EndPrinting();
  83. protected:
  84. CFolder *m_RootFolder; // The root folder of the data.
  85. CString m_strPath; // Stored path to result of last find operation
  86. int m_iLine; // Stored line of last find operation.
  87. DataComplexity m_Complexity; // The complexity of the displayed data.
  88. volatile BOOL m_fCanceled; // Flag to manage cancel of multi-threaded find
  89. CFolder *m_pfLast; // The last node found.
  90. // For Printing.
  91. private:
  92. CDC *m_pDC; // Printer's device context.
  93. CFont *m_pprinterFont; // The font the printer uses.
  94. CString m_strHeaderLeft; // Header text displayed at the page's top left
  95. CString m_strHeaderRight; // Header text displayed at the page's top right.
  96. CString m_strFooterCenter; // Footer text at the center of the page.
  97. CPrintInfo *m_pPrintInfo; // Information about the print job
  98. CMSInfoFile *m_pPrintContent; // A memory file containing print data.
  99. BOOL m_fEndOfFile; // Flag specifying whether the print job ends.
  100. };
  101. /*
  102. * CFolder - Abstract base for an individual folder item.
  103. *
  104. * History: a-jsari 10/9/97 Initial version
  105. */
  106. class CFolder {
  107. public:
  108. friend class CScopeItemMap;
  109. friend class CWBEMDataSource;
  110. friend class CBufferV500DataSource;
  111. friend class CBufferV410DataSource;
  112. friend class COCXFolder;
  113. // Really don't want this to be a friend, but required to make Refresh work.
  114. friend class CSystemInfoScope;
  115. CFolder(CDataSource *pDataSource, CFolder *pParentNode = NULL);
  116. virtual ~CFolder();
  117. virtual CDataSource::SourceType GetType() const { return m_pDataSource->GetType(); }
  118. virtual CFolder *GetChildNode() { return m_ChildFolder; }
  119. virtual CFolder *GetNextNode() { return m_NextFolder; }
  120. virtual CFolder *GetParentNode() { return m_ParentFolder; }
  121. virtual BOOL GetName(CString &szName) const = 0;
  122. virtual BOOL HasDynamicChildren() const = 0;
  123. virtual BOOL IsDynamic() const = 0;
  124. virtual BOOL Refresh(BOOL fRecursive = FALSE) = 0;
  125. virtual BOOL FileSave(CMSInfoFile *pFile) = 0;
  126. CDataSource *DataSource() { return m_pDataSource; }
  127. // One-time only line selection interface for find implementation.
  128. // Used instead of MMC
  129. void SetSelectedItem(int nLine) { m_nLine = nLine; }
  130. int GetSelectedItem() { int nLine = m_nLine; m_nLine = -1; return nLine; }
  131. // Save the HSCOPEITEM for this folder, so we can reselect it when
  132. // there is new data.
  133. HSCOPEITEM m_hsi;
  134. protected:
  135. DataComplexity GetComplexity() const { return m_pDataSource->m_Complexity; }
  136. void InternalName(CString &szName) const;
  137. protected:
  138. CDataSource *m_pDataSource; // The data source we apply to.
  139. CFolder *m_NextFolder; // Next folder at the same level in the tree.
  140. CFolder *m_ParentFolder; // Back-pointer to parent for traversing
  141. CFolder *m_ChildFolder; // Pointer to the first child folder.
  142. BOOL fNextTested; // Optimization flag for getting sibling pointer
  143. BOOL fChildTested; // Optimization flag for getting child pointer
  144. int m_nLine; // This folder's selected line.
  145. };
  146. /*
  147. * CListViewFolder - Abstract base for folders which enumerate listview items
  148. * (As opposed to the OCX folders which handle display of listview items
  149. * themselves.)
  150. *
  151. * History: a-jsari 10/28/97 Initial version
  152. */
  153. class CListViewFolder : public CFolder {
  154. public:
  155. CListViewFolder(CDataSource *pDataSource, CFolder *pParentNode = NULL)
  156. :CFolder(pDataSource, pParentNode) { }
  157. ~CListViewFolder() { }
  158. virtual BOOL GetSubElement(unsigned iRow, unsigned iColumn, CString &szName) const = 0;
  159. virtual DWORD GetSortIndex(unsigned iRow, unsigned iColumn) const = 0;
  160. virtual unsigned GetColumns() const = 0;
  161. virtual unsigned GetRows() const = 0;
  162. virtual DataComplexity GetColumnComplexity(unsigned iColumn) = 0;
  163. virtual DataComplexity GetRowComplexity(unsigned iRow) = 0;
  164. virtual int GetColumnTextAndWidth(unsigned iColumn, CString &szText, unsigned &uColWidth) const = 0;
  165. virtual BOOL GetSortType(unsigned iColumn, MSIColumnSortType &stColumn) const = 0;
  166. BOOL ReportWrite(CMSInfoFile *pFile);
  167. BOOL FileSave(CMSInfoFile *pFile);
  168. protected:
  169. void SaveTitle(CMSInfoFile *pFile);
  170. void SaveElements(CMSInfoFile *pFile);
  171. void ReportWriteTitle(CMSInfoFile *pFile);
  172. void ReportWriteElements(CMSInfoFile *pFile);
  173. };
  174. /*
  175. * CWBEMFolder - Folder that queries WBEM to provide data.
  176. *
  177. * History: a-jsari 10/9/97 Initial version
  178. */
  179. extern DWORD WINAPI ThreadRefresh(void * pArg);
  180. class CThreadingRefresh;
  181. class CWBEMFolder : public CListViewFolder {
  182. friend DWORD WINAPI ThreadRefresh(void * pArg);
  183. friend class CThreadingRefresh;
  184. public:
  185. CWBEMFolder(CDataCategory *pdcNode, CDataSource *pDataSource, CFolder *pParentNode = NULL);
  186. ~CWBEMFolder();
  187. CDataSource::SourceType GetType() const { return CDataSource::GATHERER; }
  188. CFolder *GetChildNode();
  189. CFolder *GetNextNode();
  190. BOOL GetName(CString &szName) const { return m_pCategory->GetName(szName); }
  191. BOOL HasDynamicChildren() const;
  192. BOOL IsDynamic() const;
  193. BOOL GetSubElement(unsigned nRow, unsigned nCol, CString &szName) const;
  194. DWORD GetSortIndex(unsigned nRow, unsigned nCol) const;
  195. unsigned GetRows() const;
  196. unsigned GetColumns() const;
  197. DataComplexity GetColumnComplexity(unsigned iColumn);
  198. DataComplexity GetRowComplexity(unsigned iRow);
  199. int GetColumnTextAndWidth(unsigned iColumn, CString &szText, unsigned &uColWidth) const;
  200. BOOL GetSortType(unsigned iColumn, MSIColumnSortType &stColumn) const;
  201. BOOL Refresh(BOOL fRecursive = FALSE);
  202. // Recursively reset the refresh flag.
  203. void ResetRefreshFlag()
  204. {
  205. m_fBeenRefreshed = FALSE;
  206. CWBEMFolder * pWBEMFolder = reinterpret_cast<CWBEMFolder *>(m_NextFolder);
  207. if (pWBEMFolder)
  208. pWBEMFolder->ResetRefreshFlag();
  209. pWBEMFolder = reinterpret_cast<CWBEMFolder *>(m_ChildFolder);
  210. if (pWBEMFolder)
  211. pWBEMFolder->ResetRefreshFlag();
  212. }
  213. private:
  214. CDataCategory *m_pCategory;
  215. BOOL m_fBeenRefreshed;
  216. };
  217. /*
  218. * CWBEMDataSource - Data source that queries WBEM to provide data.
  219. *
  220. * History: a-jsari 10/9/97 Initial version
  221. */
  222. class CWBEMDataSource : public CDataSource {
  223. public:
  224. friend class CSystemInfoScope;
  225. CWBEMDataSource(LPCTSTR szMachineName = NULL);
  226. ~CWBEMDataSource();
  227. // BOOL StopSearch();
  228. BOOL SetDataComplexity(enum DataComplexity Complexity);
  229. SourceType GetType() const { return CDataSource::GATHERER; }
  230. CFolder *GetRootNode();
  231. BOOL Refresh(BOOL fOptional = FALSE)
  232. {
  233. StartSearch();
  234. BOOL fReturn = TRUE;
  235. if (!m_fEverRefreshed || !fOptional)
  236. {
  237. if (m_pThreadRefresh && GetRootNode())
  238. m_pThreadRefresh->RefreshAll(GetRootNode(), &m_fCanceled);
  239. else
  240. fReturn = m_pGatherer->Refresh(&m_fCanceled);
  241. m_fEverRefreshed = fReturn;
  242. }
  243. StopSearch();
  244. return fReturn;
  245. }
  246. void ResetCategoryRefresh()
  247. {
  248. if (m_pGatherer)
  249. m_pGatherer->ResetCategoryRefresh();
  250. CWBEMFolder * pWBEMFolder = reinterpret_cast<CWBEMFolder *>(m_RootFolder);
  251. if (pWBEMFolder)
  252. pWBEMFolder->ResetRefreshFlag();
  253. };
  254. BOOL GetNodeName(CString &strName);
  255. BOOL SetMachineName(const CString &strMachine);
  256. HRESULT Save(IStream *pStm);
  257. BOOL Find(const CString & strSearch, long lFindOptions);
  258. BOOL SetCategories(const CString & strCategory) { if (m_pGatherer) return m_pGatherer->SetCategories(strCategory); return FALSE; };
  259. private:
  260. CDataGatherer *m_pGatherer;
  261. CString m_strMachineName;
  262. CString m_strParentPath;
  263. BOOL m_fEverRefreshed;
  264. public:
  265. CThreadingRefresh * m_pThreadRefresh;
  266. };
  267. /*
  268. * CBufferDataSource - Abstract Data Source that reads data from an
  269. * unspecified buffer source. Comes in two flavors: Version 4.10
  270. * data and V 5.00 data
  271. *
  272. * History: a-jsari 10/9/97 Initial version
  273. */
  274. class CBufferDataSource : public CDataSource {
  275. public:
  276. CBufferDataSource(CMSInfoFile *pfileSink);
  277. virtual ~CBufferDataSource();
  278. virtual SourceType GetType() const = 0;
  279. LPCTSTR FileName();
  280. BOOL SetDataComplexity(enum DataComplexity Complexity)
  281. {
  282. CDataSource::SetDataComplexity(Complexity);
  283. return TRUE;
  284. }
  285. // BufferDataSources don't get refreshed.
  286. BOOL Refresh(BOOL fOptional = FALSE) { return TRUE; }
  287. BOOL HasCAB() { return !m_strCabDirectory.IsEmpty(); }
  288. const CString &CABDirectory() { return m_strCabDirectory; }
  289. static CBufferDataSource *CreateDataSourceFromFile(LPCTSTR szFilename);
  290. // Buffer read functions
  291. public:
  292. virtual void ReadFolder(CMSInfoFile *pFileSink, CFolder * & pFolder, CFolder *pParentFolder = NULL) = 0;
  293. virtual void ReadHeader(CMSInfoFile *pFileSink) = 0;
  294. protected:
  295. CString m_strCabDirectory; // The name of a CAB file directory.
  296. CString m_strFileName; // The name of the buffer's open file
  297. time_t m_tsSaveTime; // The time at which the data source was saved.
  298. CString m_strUserName; // The network username who saved the file.
  299. CString m_strMachine; // The network machine which saved the file.
  300. };
  301. /*
  302. * CBufferV50DataSource - Code for parsing a version 5.00 data file
  303. *
  304. * History: a-jsari 10/9/97 Initial version
  305. */
  306. class CBufferV500DataSource : public CBufferDataSource {
  307. public:
  308. CBufferV500DataSource(CMSInfoFile *pfileSink);
  309. ~CBufferV500DataSource();
  310. SourceType GetType() const { return V500FILE; }
  311. BOOL GetNodeName(CString &strName);
  312. HRESULT Save(IStream *pStm);
  313. BOOL Find(const CString &strSearch, long lFindOptions);
  314. static BOOL VerifyFileVersion(CMSInfoFile *pFile);
  315. // MASK is required so that we can or a count in with the parent value to
  316. // store a number of iterations for a parent code.
  317. enum NodeType { CHILD = 0x8000, NEXT = 0x4000, END = 0x2000, PARENT = 0x1000,
  318. MASK = 0xf000 };
  319. public:
  320. void ReadFolder(CMSInfoFile *pFileSink, CFolder * & pFolder, CFolder *pParentFolder = NULL);
  321. void ReadHeader(CMSInfoFile *pFileSink);
  322. private:
  323. void ReadElements(CMSInfoFile *pFileSink, CBufferFolder *pFolder);
  324. BOOL FolderContains(const CListViewFolder *fCurrent,
  325. const CString &strSearch, int &wRow, long lFolderOptions);
  326. CString m_szFileName;
  327. unsigned m_iLastLine; // The last line found.
  328. };
  329. /*
  330. * CBufferV410DataSource - Code for parsing a version 4.10 data file
  331. *
  332. * History: a-jsari 10/9/97 Initial version
  333. */
  334. class CBufferV410DataSource : public CBufferDataSource
  335. {
  336. friend class COCXFolder;
  337. public:
  338. CBufferV410DataSource(CMSInfoFile *pfileSink);
  339. CBufferV410DataSource(IStorage * pStorage, IStream * pStream);
  340. ~CBufferV410DataSource();
  341. BOOL GetNodeName(CString &strName);
  342. SourceType GetType() const { return V410FILE; }
  343. CFolder *GetRootNode();
  344. HRESULT Save(IStream *pStm);
  345. BOOL Find(const CString &szSearch, long lFindOptions);
  346. public:
  347. void ReadFolder(CMSInfoFile *pFileSink, CFolder * & pFolder, CFolder *pParentFolder = NULL);
  348. void ReadHeader(CMSInfoFile *pFileSink);
  349. private:
  350. BOOL ReadMSInfo410Stream(IStream *pStream);
  351. BOOL RecurseLoad410Tree(IStream *pStream);
  352. COCXFolder * ReadOCXFolder(IStream *pStream, COCXFolder * pParent, COCXFolder * pPrevious);
  353. private:
  354. CMapStringToString m_mapStreams;
  355. IStorage * m_pStorage;
  356. };
  357. /*
  358. * CBufferTextDataSource - Code for parsing a text file.
  359. *
  360. * History: a-jsari 10/24/97 Initial version
  361. */
  362. class CBufferTextDataSource : public CBufferDataSource {
  363. public:
  364. CBufferTextDataSource(CMSInfoFile *pfileSink);
  365. ~CBufferTextDataSource();
  366. SourceType GetType() const { return TEXTFILE; }
  367. CFolder *GetRootNode();
  368. };
  369. /*
  370. * CBufferSortData - A class to manage sort data for a CBufferFolder
  371. *
  372. * History: a-jsari 12/1/97 Initial version
  373. */
  374. class CBufferSortData {
  375. public:
  376. CBufferSortData();
  377. ~CBufferSortData();
  378. BOOL SetColumns(unsigned cColumns);
  379. BOOL SetRows(unsigned cRows);
  380. BOOL SetSortType(unsigned iColumn, unsigned stColumn);
  381. BOOL GetSortType(unsigned iColumn, MSIColumnSortType &stColumn) const;
  382. BOOL ReadSortValues(CMSInfoFile *pFile, unsigned iColumn);
  383. DWORD GetSortValue(unsigned iRow, unsigned iColumn) const;
  384. private:
  385. int ValueIndexFromColumn(unsigned iColumn) const;
  386. private:
  387. unsigned m_cRows;
  388. unsigned m_cColumns;
  389. CArray <MSIColumnSortType, MSIColumnSortType &> m_SortTypes;
  390. CArray <CDwordValues, CDwordValues &> m_dwSortIndices;
  391. CArray <unsigned, unsigned &> m_ValueColumns;
  392. };
  393. /*
  394. * CBufferFolder - Folder that reads data from an unspecified buffer source.
  395. *
  396. * History: a-jsari 10/9/97 Initial version
  397. */
  398. class CBufferFolder : public CListViewFolder {
  399. public:
  400. friend class CBufferV500DataSource;
  401. // friend class CBufferV410DataSource;
  402. CBufferFolder(CDataSource *pDataSource, CFolder *pParent = NULL);
  403. virtual ~CBufferFolder();
  404. CDataSource::SourceType GetType() const { return CDataSource::BUFFER; }
  405. // Currently there are no dynamic buffer nodes.
  406. BOOL HasDynamicChildren() const { return FALSE; }
  407. BOOL IsDynamic() const { return FALSE; }
  408. BOOL GetName(CString &szName) const;
  409. BOOL Refresh(BOOL fRecursive = FALSE) { return TRUE; }
  410. BOOL GetSubElement(unsigned nRow, unsigned nCol, CString &szName) const;
  411. unsigned GetColumns() const;
  412. unsigned GetRows() const;
  413. DataComplexity GetColumnComplexity(unsigned iColumn);
  414. DataComplexity GetRowComplexity(unsigned iRow);
  415. int GetColumnTextAndWidth(unsigned iColumn, CString &szText, unsigned &uColWidth) const;
  416. BOOL GetSortType(unsigned iColumn, MSIColumnSortType &stColumn) const;
  417. DWORD GetSortIndex(unsigned iRow, unsigned iColumn) const;
  418. private:
  419. CBufferDataSource *GetDataSource()
  420. { return dynamic_cast<CBufferDataSource *>(m_pDataSource); }
  421. void SetName(CString szName);
  422. void SetSubElement(DWORD nRow, DWORD nColumn, CString szName);
  423. void SetColumns(unsigned cColumns);
  424. void SetRows(unsigned cRows);
  425. unsigned BasicColumn(unsigned iColumn) const;
  426. unsigned BasicRow(unsigned iRow) const;
  427. private:
  428. unsigned m_cRows;
  429. unsigned m_cColumns;
  430. CString m_szName;
  431. CStringValues m_szColumns;
  432. CBufferSortData m_SortData;
  433. CArray <unsigned, unsigned &> m_uWidths;
  434. CArray <CStringValues, CStringValues &> m_szElements;
  435. CArray <DataComplexity, DataComplexity &> m_dcColumns;
  436. CArray <DataComplexity, DataComplexity &> m_dcRows;
  437. };
  438. /*
  439. * COCXFolder - A folder which contains data provided by an OCX.
  440. * This is planned expansion, not currently implemented.
  441. *
  442. * History: a-jsari 10/27/97 Initial version
  443. */
  444. class COCXFolder : public CFolder
  445. {
  446. public:
  447. COCXFolder(CDataSource *pDataSource) : CFolder(pDataSource) {}
  448. COCXFolder(CDataSource * pSource, CLSID clsid, CFolder * pParent, CFolder * pPrevious, DWORD dwView, LPOLESTR lpName)
  449. : CFolder(pSource, pParent),
  450. m_clsid(clsid),
  451. m_dwView(dwView),
  452. m_strName(lpName)
  453. {
  454. if (pParent && pParent->m_ChildFolder == NULL)
  455. pParent->m_ChildFolder = this;
  456. if (pPrevious)
  457. pPrevious->m_NextFolder = this;
  458. }
  459. ~COCXFolder() {}
  460. CDataSource::SourceType GetType() const { return CDataSource::OCX; }
  461. CFolder * GetChildNode() { return m_ChildFolder; };
  462. CFolder * GetNextNode() { return m_NextFolder; };
  463. BOOL Refresh(IUnknown * pUnknown = NULL);
  464. BOOL Refresh(BOOL fRecursive = FALSE) { return (Refresh((IUnknown *)NULL)); };
  465. BOOL ReportWrite(CMSInfoFile *pFile) { return FALSE; };
  466. BOOL FileSave(CMSInfoFile *pFile) { return FALSE; };
  467. BOOL GetName(CString &szName) const { szName = m_strName; return TRUE; };
  468. BOOL HasDynamicChildren() const { return FALSE; };
  469. BOOL IsDynamic() const { return FALSE; };
  470. BOOL GetCLSID(LPOLESTR * ppCLSID) { return (SUCCEEDED(StringFromCLSID(m_clsid, ppCLSID))); };
  471. BOOL GetCLSIDString(CString & strCLSID);
  472. void SetOCXView(IUnknown * pUnknown, DWORD dwView);
  473. BOOL GetDISPID(IDispatch * pDispatch, LPOLESTR szMember, DISPID *pID);
  474. public:
  475. CLSID m_clsid;
  476. DWORD m_dwView;
  477. CString m_strName;
  478. CString m_strCLSID;
  479. };