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

540 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. metabag.h
  5. Abstract:
  6. This module contains the definition for the
  7. ISEODictionary object on the Metabase.
  8. Author:
  9. Andy Jacobs (andyj@microsoft.com)
  10. Revision History:
  11. andyj 03/11/97 created
  12. --*/
  13. // METABAG.h : Declaration of the CSEOMetaDictionary
  14. //#define TIMEOUT 15000
  15. #define ALWAYS_LOCK 0
  16. #define SafeStrlen(x) ((x)?wcslen(x):0)
  17. class CGlobalInterfaceImpl {
  18. public:
  19. void Init() {
  20. m_pUnkObject = NULL;
  21. m_piGIT = NULL;
  22. };
  23. void Term() {
  24. if (m_pUnkObject) {
  25. m_pUnkObject->Release();
  26. m_pUnkObject = NULL;
  27. }
  28. if (m_piGIT) {
  29. HRESULT hrRes = m_piGIT->RevokeInterfaceFromGlobal(m_dwCookie);
  30. _ASSERTE(SUCCEEDED(hrRes));
  31. m_piGIT->Release();
  32. m_piGIT = NULL;
  33. }
  34. };
  35. bool operator!() {
  36. return (!m_pUnkObject&&!m_piGIT);
  37. };
  38. operator bool() {
  39. return (m_pUnkObject||m_piGIT);
  40. };
  41. protected:
  42. HRESULT Load(REFCLSID rclsid, REFIID riid) {
  43. return (LoadImpl(rclsid,riid,NULL));
  44. };
  45. HRESULT Load(REFIID riid, IUnknown *pUnkObject) {
  46. if (!pUnkObject) {
  47. return (E_POINTER);
  48. }
  49. return (LoadImpl(GUID_NULL,riid,pUnkObject));
  50. };
  51. HRESULT GetInterface(REFIID riid, IUnknown **ppUnkObject) {
  52. if (ppUnkObject) {
  53. *ppUnkObject = NULL;
  54. }
  55. if (!ppUnkObject) {
  56. return (E_POINTER);
  57. }
  58. _ASSERTE(m_pUnkObject||m_piGIT); // Not loaded.
  59. _ASSERTE(!m_pUnkObject||!m_piGIT); // Internal error.
  60. if (m_pUnkObject) {
  61. *ppUnkObject = m_pUnkObject;
  62. (*ppUnkObject)->AddRef();
  63. return (S_OK);
  64. }
  65. if (m_piGIT) {
  66. return (m_piGIT->GetInterfaceFromGlobal(m_dwCookie,riid,(LPVOID *) ppUnkObject));
  67. }
  68. return (E_FAIL);
  69. };
  70. HRESULT GetInterfaceQI(REFIID riid, REFIID riidDesired, LPVOID *ppvObject) {
  71. CComPtr<IUnknown> pUnkObject;
  72. HRESULT hrRes;
  73. if (ppvObject) {
  74. *ppvObject = NULL;
  75. }
  76. if (!ppvObject) {
  77. return (E_POINTER);
  78. }
  79. hrRes = GetInterface(riid,&pUnkObject);
  80. if (!SUCCEEDED(hrRes)) {
  81. return (hrRes);
  82. }
  83. return (pUnkObject->QueryInterface(riidDesired,ppvObject));
  84. };
  85. private:
  86. HRESULT LoadImpl(REFCLSID rclsid, REFIID riid, IUnknown *pUnkObject) {
  87. HRESULT hrRes;
  88. hrRes = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
  89. NULL,
  90. CLSCTX_ALL,
  91. IID_IGlobalInterfaceTable,
  92. (LPVOID *) &m_piGIT);
  93. _ASSERTE(SUCCEEDED(hrRes)); // Should always succeed on NT4 SP3 and later.
  94. if (!SUCCEEDED(hrRes) && (hrRes != REGDB_E_CLASSNOTREG)) {
  95. return (hrRes);
  96. }
  97. if (!pUnkObject) {
  98. hrRes = CoCreateInstance(rclsid,NULL,CLSCTX_ALL,riid,(LPVOID *) &m_pUnkObject);
  99. if (!SUCCEEDED(hrRes)) {
  100. if (m_piGIT) {
  101. m_piGIT->Release();
  102. m_piGIT = NULL;
  103. }
  104. return (hrRes);
  105. }
  106. } else {
  107. m_pUnkObject = pUnkObject;
  108. m_pUnkObject->AddRef();
  109. }
  110. if (m_piGIT) {
  111. hrRes = m_piGIT->RegisterInterfaceInGlobal(m_pUnkObject,riid,&m_dwCookie);
  112. m_pUnkObject->Release();
  113. m_pUnkObject = NULL;
  114. if (!SUCCEEDED(hrRes)) {
  115. m_piGIT->Release();
  116. m_piGIT = NULL;
  117. return (hrRes);
  118. }
  119. }
  120. return (S_OK);
  121. };
  122. IUnknown *m_pUnkObject;
  123. DWORD m_dwCookie;
  124. IGlobalInterfaceTable *m_piGIT;
  125. };
  126. template<class T, const IID *pIID>
  127. class CGlobalInterface : public CGlobalInterfaceImpl {
  128. public:
  129. HRESULT Load(REFCLSID rclsid) {
  130. return (CGlobalInterfaceImpl::Load(rclsid,*pIID));
  131. };
  132. HRESULT Load(T *pT) {
  133. if (!pT) {
  134. return (E_POINTER);
  135. }
  136. return (CGlobalInterfaceImpl::Load(*pIID,(IUnknown *) pT));
  137. };
  138. HRESULT GetInterface(T **ppT) {
  139. return (CGlobalInterfaceImpl::GetInterface(*pIID,(IUnknown **) ppT));
  140. };
  141. HRESULT GetInterfaceQI(REFIID riidDesired,LPVOID *ppv) {
  142. return (CGlobalInterfaceImpl::GetInterfaceQI(*pIID,riidDesired,ppv));
  143. };
  144. };
  145. struct IMSAdminBaseW;
  146. class CSEOMetabaseLock;
  147. enum LockStatus {Closed, Read, Write, Error, DontCare, InitError};
  148. class CSEOMetabase { // Wrapper for Metabase funcitons
  149. public:
  150. CSEOMetabase() {
  151. m_mhHandle = METADATA_MASTER_ROOT_HANDLE;
  152. m_eStatus = Closed; // Closed until we delegate
  153. m_pszPath = (LPWSTR) MyMalloc(sizeof(*m_pszPath));
  154. m_pmbDefer = NULL;
  155. if(!m_pszPath) {
  156. m_hrInitRes = E_OUTOFMEMORY;
  157. goto Exit;
  158. }
  159. *m_pszPath = 0;
  160. m_hrInitRes = InitializeMetabase();
  161. Exit:
  162. if(!SUCCEEDED(m_hrInitRes)) {
  163. m_eStatus = InitError;
  164. }
  165. };
  166. ~CSEOMetabase() {
  167. if(!m_pmbDefer) SetStatus(Closed); // Close self on cleanup
  168. if (SUCCEEDED(m_hrInitRes)) {
  169. TerminateMetabase();
  170. }
  171. if(m_pszPath) MyFree(m_pszPath);
  172. m_pszPath = NULL;
  173. m_pmbDefer = NULL;
  174. };
  175. void operator=(const CSEOMetabase &mbMetabase) {
  176. SetPath(mbMetabase.m_pszPath);
  177. };
  178. HRESULT InitShare(CSEOMetabase *pmbOther, LPCWSTR pszPath, LPUNKNOWN punkOwner = NULL) {
  179. LPWSTR pszTmp = NULL;
  180. m_punkDeferOwner = punkOwner;
  181. m_pmbDefer = pmbOther;
  182. if (pszPath) {
  183. pszTmp = (LPWSTR) MyMalloc(sizeof(*pszPath)*(SafeStrlen(pszPath) + 1));
  184. if(!pszTmp) return E_OUTOFMEMORY;
  185. wcscpy(pszTmp, pszPath);
  186. }
  187. if(m_pszPath) MyFree(m_pszPath);
  188. m_pszPath = pszTmp;
  189. return S_OK;
  190. };
  191. LockStatus Status() const {
  192. return (m_pmbDefer ? m_pmbDefer->Status() : m_eStatus);
  193. };
  194. HRESULT SetStatus(LockStatus ls, long lTimeout=15000);
  195. HRESULT EnumKeys(LPCWSTR pszPath, DWORD dwNum, LPWSTR pszName);
  196. HRESULT AddKey(LPCWSTR pszPathBuf);
  197. HRESULT DeleteKey(LPCWSTR pszPathBuf);
  198. HRESULT GetData(LPCWSTR path, DWORD &dwType, DWORD &dwLen, PBYTE pbData);
  199. HRESULT SetData(LPCWSTR path, DWORD dwType, DWORD dwLen, PBYTE pbData);
  200. HRESULT SetDWord(LPCWSTR path, DWORD dwData) {
  201. return SetData(path, DWORD_METADATA, sizeof(DWORD), (PBYTE) &dwData);
  202. };
  203. HRESULT SetString(LPCWSTR path, LPCWSTR psData, int iLen = -1) {
  204. if(iLen < 0) iLen = sizeof(*psData) * (SafeStrlen(psData) + 1);
  205. return SetData(path, STRING_METADATA, iLen, (PBYTE) psData);
  206. };
  207. METADATA_HANDLE GetHandle() {
  208. if(m_pmbDefer) {
  209. return m_pmbDefer->GetHandle();
  210. } else {
  211. return m_mhHandle; // Not defering, so use our handle
  212. }
  213. };
  214. int GetPathLength() {
  215. int iRet = SafeStrlen(m_pszPath);
  216. if(m_pmbDefer) {
  217. iRet += (3 + m_pmbDefer->GetPathLength());
  218. }
  219. return iRet;
  220. };
  221. LPCWSTR GetRelPath(LPWSTR psRet) { // Get the Relative Path from the original deferer
  222. if(!psRet) return psRet;
  223. if(m_pmbDefer) {
  224. LPWSTR psBuf = (LPWSTR) alloca(sizeof(*psBuf)*(m_pmbDefer->GetPathLength() + 1));
  225. m_pmbDefer->GetRelPath(psBuf);
  226. ConcatinatePaths(psRet,psBuf,m_pszPath);
  227. } else {
  228. *psRet = 0; // Empty string
  229. }
  230. return psRet;
  231. };
  232. LPCWSTR GetPath(LPWSTR psRet) {
  233. if(!psRet) return psRet;
  234. if(m_pmbDefer) {
  235. LPWSTR psBuf = (LPWSTR) alloca(sizeof(*psBuf)*(m_pmbDefer->GetPathLength() + 1));
  236. m_pmbDefer->GetPath(psBuf);
  237. ConcatinatePaths(psRet, psBuf,m_pszPath);
  238. } else {
  239. wcscpy(psRet,m_pszPath);
  240. }
  241. return psRet;
  242. };
  243. void AppendPath(LPCWSTR pszPathParam) {
  244. LPWSTR pszPath = (LPWSTR) alloca(sizeof(*pszPath)*(SafeStrlen(m_pszPath)+SafeStrlen(pszPathParam)+3));
  245. ConcatinatePaths(pszPath,m_pszPath,pszPathParam);
  246. SetPath(pszPath);
  247. };
  248. void SetPath(LPCWSTR pszPath) {
  249. LPWSTR pszTmp = NULL;
  250. SetStatus(Closed); // Make sure we're closed
  251. if (pszPath) {
  252. pszTmp = (LPWSTR) MyMalloc((sizeof(*pszTmp))*(SafeStrlen(pszPath)+3));
  253. if(!pszTmp)
  254. return;
  255. ConcatinatePaths(pszTmp,pszPath,NULL);
  256. }
  257. if(m_pszPath) MyFree(m_pszPath);
  258. m_pszPath = pszTmp;
  259. };
  260. static HRESULT InitializeMetabase();
  261. static HRESULT TerminateMetabase();
  262. protected:
  263. void ConcatinatePaths(LPWSTR pszResult, LPCWSTR pszP1, LPCWSTR pszP2);
  264. HRESULT OpenPath(CSEOMetabaseLock &mbLocker, LPCWSTR pszPath,
  265. LPWSTR pszPathBuf, DWORD &dwId, LockStatus lsOpen = Read);
  266. private:
  267. LPWSTR m_pszPath;
  268. METADATA_HANDLE m_mhHandle;
  269. LockStatus m_eStatus;
  270. CSEOMetabase *m_pmbDefer; // Defer to this object if set
  271. CComPtr<IUnknown> m_punkDeferOwner; // Keep reference count
  272. HRESULT m_hrInitRes;
  273. static CGlobalInterface<IMSAdminBaseW,&IID_IMSAdminBase_W> m_MetabaseHandle;
  274. static CGlobalInterface<IMSAdminBaseW,&IID_IMSAdminBase_W> m_MetabaseChangeHandle;
  275. static int m_iCount; // Number of calls to InitializeMetabase()
  276. };
  277. class CSEOMetabaseLock {
  278. public:
  279. CSEOMetabaseLock(CSEOMetabase *piObject, LockStatus ls = DontCare) {
  280. m_bChanged = FALSE;
  281. m_piObject = piObject;
  282. if(DontCare != ls) SetStatus(ls);
  283. };
  284. ~CSEOMetabaseLock() {
  285. if(m_bChanged) SetStatus(m_lsPrevious);
  286. };
  287. HRESULT SetStatus(LockStatus ls) {
  288. if(!m_piObject) return E_FAIL; // Not initialized
  289. m_lsPrevious = m_piObject->Status();
  290. HRESULT hRes = m_piObject->SetStatus(ls);
  291. LockStatus lsNewStatus = m_piObject->Status();
  292. if((lsNewStatus != m_lsPrevious) && (hRes != S_FALSE)) m_bChanged = TRUE;
  293. if(lsNewStatus == Closed) m_bChanged = FALSE;
  294. return hRes;
  295. };
  296. private:
  297. CSEOMetabase *m_piObject;
  298. BOOL m_bChanged; // True if we are responsible for restoring in our destructor
  299. LockStatus m_lsPrevious;
  300. };
  301. // The following macro may be inserted in a method to support
  302. // reading/writing from just that method if handle not already opened.
  303. // The object will take care of closing the handle if needed, etc.
  304. #define METABASE_HELPER(x,y) CSEOMetabaseLock mbHelper(x, y)
  305. /////////////////////////////////////////////////////////////////////////////
  306. // CSEOMetaDictionary
  307. class ATL_NO_VTABLE CSEOMetaDictionary :
  308. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  309. public CComCoClass<CSEOMetaDictionary, &CLSID_CSEOMetaDictionary>,
  310. public ISEOInitObject,
  311. public IDispatchImpl<ISEODictionary, &IID_ISEODictionary, &LIBID_SEOLib>,
  312. public IPropertyBag,
  313. public IDispatchImpl<IEventPropertyBag, &IID_IEventPropertyBag, &LIBID_SEOLib>,
  314. public IDispatchImpl<IEventLock, &IID_IEventLock, &LIBID_SEOLib>,
  315. public IConnectionPointContainerImpl<CSEOMetaDictionary>,
  316. // public IConnectionPointImpl<CSEOMetaDictionary, &IID_IEventNotifyBindingChange>
  317. public CSEOConnectionPointImpl<CSEOMetaDictionary, &IID_IEventNotifyBindingChange>
  318. {
  319. friend class CSEOMetaDictionaryEnum; // Helper class
  320. public:
  321. HRESULT FinalConstruct();
  322. void FinalRelease();
  323. HRESULT OnChange(LPCWSTR *apszPath);
  324. HRESULT GetVariantA(LPCSTR pszName, VARIANT *pvarResult, BOOL bCreate);
  325. HRESULT GetVariantW(LPCWSTR pszName, VARIANT *pvarResult, BOOL bCreate);
  326. DECLARE_PROTECT_FINAL_CONSTRUCT();
  327. DECLARE_REGISTRY_RESOURCEID_EX(IDR_StdAfx,
  328. L"SEOMetaDictionary Class",
  329. L"SEO.SEOMetaDictionary.1",
  330. L"SEO.SEOMetaDictionary");
  331. BEGIN_COM_MAP(CSEOMetaDictionary)
  332. COM_INTERFACE_ENTRY(ISEODictionary)
  333. COM_INTERFACE_ENTRY(ISEOInitObject)
  334. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
  335. COM_INTERFACE_ENTRY(IPropertyBag)
  336. COM_INTERFACE_ENTRY(IEventPropertyBag)
  337. COM_INTERFACE_ENTRY_IID(IID_IDispatch, IEventPropertyBag)
  338. COM_INTERFACE_ENTRY(IEventLock)
  339. COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
  340. END_COM_MAP()
  341. BEGIN_CONNECTION_POINT_MAP(CSEOMetaDictionary)
  342. CONNECTION_POINT_ENTRY(IID_IEventNotifyBindingChange)
  343. END_CONNECTION_POINT_MAP()
  344. // CSEOConnectionPointImp<>
  345. public:
  346. void AdviseCalled(IUnknown *pUnk, DWORD *pdwCookie, REFIID riid, DWORD dwCount);
  347. void UnadviseCalled(DWORD dwCookie, REFIID riid, DWORD dwCount);
  348. // ISEODictionary
  349. public:
  350. virtual /* [id][propget][helpstring] */ HRESULT STDMETHODCALLTYPE get_Item(
  351. /* [in] */ VARIANT __RPC_FAR *pvarName,
  352. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult);
  353. virtual /* [propput][helpstring] */ HRESULT STDMETHODCALLTYPE put_Item(
  354. /* [in] */ VARIANT __RPC_FAR *pvarName,
  355. /* [in] */ VARIANT __RPC_FAR *pvarValue);
  356. virtual /* [hidden][id][propget][helpstring] */ HRESULT STDMETHODCALLTYPE get__NewEnum(
  357. /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult);
  358. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVariantA(
  359. /* [in] */ LPCSTR pszName,
  360. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult);
  361. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVariantW(
  362. /* [in] */ LPCWSTR pszName,
  363. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult);
  364. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetVariantA(
  365. /* [in] */ LPCSTR pszName,
  366. /* [in] */ VARIANT __RPC_FAR *pvarValue);
  367. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetVariantW(
  368. /* [in] */ LPCWSTR pszName,
  369. /* [in] */ VARIANT __RPC_FAR *pvarValue);
  370. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetStringA(
  371. /* [in] */ LPCSTR pszName,
  372. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  373. /* [retval][size_is][out] */ LPSTR pszResult);
  374. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetStringW(
  375. /* [in] */ LPCWSTR pszName,
  376. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  377. /* [retval][size_is][out] */ LPWSTR pszResult);
  378. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetStringA(
  379. /* [in] */ LPCSTR pszName,
  380. /* [in] */ DWORD chCount,
  381. /* [size_is][in] */ LPCSTR pszValue);
  382. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetStringW(
  383. /* [in] */ LPCWSTR pszName,
  384. /* [in] */ DWORD chCount,
  385. /* [size_is][in] */ LPCWSTR pszValue);
  386. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDWordA(
  387. /* [in] */ LPCSTR pszName,
  388. /* [retval][out] */ DWORD __RPC_FAR *pdwResult);
  389. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDWordW(
  390. /* [in] */ LPCWSTR pszName,
  391. /* [retval][out] */ DWORD __RPC_FAR *pdwResult);
  392. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetDWordA(
  393. /* [in] */ LPCSTR pszName,
  394. /* [in] */ DWORD dwValue);
  395. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetDWordW(
  396. /* [in] */ LPCWSTR pszName,
  397. /* [in] */ DWORD dwValue);
  398. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetInterfaceA(
  399. /* [in] */ LPCSTR pszName,
  400. /* [in] */ REFIID iidDesired,
  401. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult);
  402. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetInterfaceW(
  403. /* [in] */ LPCWSTR pszName,
  404. /* [in] */ REFIID iidDesired,
  405. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult);
  406. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetInterfaceA(
  407. /* [in] */ LPCSTR pszName,
  408. /* [in] */ IUnknown __RPC_FAR *punkValue);
  409. virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetInterfaceW(
  410. /* [in] */ LPCWSTR pszName,
  411. /* [in] */ IUnknown __RPC_FAR *punkValue);
  412. // ISEOInitObject (IPersistPropertyBag)
  413. public:
  414. virtual HRESULT STDMETHODCALLTYPE GetClassID(/* [out] */ CLSID __RPC_FAR *pClassID);
  415. virtual HRESULT STDMETHODCALLTYPE InitNew(void);
  416. virtual HRESULT STDMETHODCALLTYPE Load(
  417. /* [in] */ IPropertyBag __RPC_FAR *pPropBag,
  418. /* [in] */ IErrorLog __RPC_FAR *pErrorLog);
  419. virtual HRESULT STDMETHODCALLTYPE Save(
  420. /* [in] */ IPropertyBag __RPC_FAR *pPropBag,
  421. /* [in] */ BOOL fClearDirty,
  422. /* [in] */ BOOL fSaveAllProperties);
  423. // IPropertyBag
  424. public:
  425. HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog);
  426. HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT *pVar);
  427. // IEventPropertyBag
  428. public:
  429. HRESULT STDMETHODCALLTYPE Item(VARIANT *pvarPropDesired, VARIANT *pvarPropValue);
  430. HRESULT STDMETHODCALLTYPE Name(long lPropIndex, BSTR *pbstrPropName);
  431. HRESULT STDMETHODCALLTYPE Add(BSTR pszPropName, VARIANT *pvarPropValue);
  432. HRESULT STDMETHODCALLTYPE Remove(VARIANT *pvarPropDesired);
  433. HRESULT STDMETHODCALLTYPE get_Count(long *plCount);
  434. /* Just use the get__NewEnum from ISEODictionary
  435. HRESULT STDMETHODCALLTYPE get__NewEnum(IUnknown **ppUnkEnum); */
  436. DECLARE_GET_CONTROLLING_UNKNOWN();
  437. // IEventLock
  438. public:
  439. HRESULT STDMETHODCALLTYPE LockRead(int iTimeoutMS);
  440. HRESULT STDMETHODCALLTYPE UnlockRead();
  441. HRESULT STDMETHODCALLTYPE LockWrite(int iTimeoutMS);
  442. HRESULT STDMETHODCALLTYPE UnlockWrite();
  443. protected:
  444. HRESULT CopyDictionary(LPCWSTR pszName, ISEODictionary *pBag);
  445. HRESULT Init(const CSEOMetabase &pmbOther, LPCWSTR pszPath) {
  446. m_mbHelper = pmbOther;
  447. m_mbHelper.AppendPath(pszPath);
  448. return S_OK;
  449. };
  450. HRESULT InitShare(CSEOMetabase &pmbOther, LPCWSTR pszPath) {
  451. return m_mbHelper.InitShare(&pmbOther, pszPath,
  452. this->GetControllingUnknown());
  453. };
  454. private: // Private data
  455. CSEOMetabase m_mbHelper; // The master helper
  456. CComPtr<IUnknown> m_pUnkMarshaler;
  457. };