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.

1530 lines
44 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: propifs.cxx
  7. //
  8. // Contents: Activation Functions used by object servers.
  9. //
  10. // Functions: Implements classes in propifs.hxx
  11. //
  12. // History: 24-Jan-98 Vinaykr Created
  13. //
  14. ///--------------------------------------------------------------------------
  15. #include <ole2int.h>
  16. #include <context.hxx>
  17. #include <actprops.hxx>
  18. #include <serial.hxx>
  19. #include <hash.hxx>
  20. //---------------------------------------------------------------------------
  21. // This file contains implementations of serializable
  22. // interfaces
  23. //---------------------------------------------------------------------------
  24. //---------------------------------------------------------------------------
  25. // Methods for InstantiationInfo
  26. //---------------------------------------------------------------------------
  27. //-----------------------------------------------------------------------
  28. // Methods from IUnknown
  29. //-----------------------------------------------------------------------
  30. STDMETHODIMP InstantiationInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  31. {
  32. if (_parent)
  33. return _parent->QueryInterface(riid, ppvObj);
  34. else
  35. return SerializableQueryInterface(riid, ppvObj);
  36. }
  37. STDMETHODIMP InstantiationInfo::SerializableQueryInterface( REFIID riid, LPVOID* ppvObj)
  38. {
  39. //Use IID_InstantiationInfo to return the real object right now
  40. if (IsEqualIID(riid, IID_IInstantiationInfo))
  41. {
  42. *ppvObj = (InstantiationInfo*) this;
  43. AddRef();
  44. return S_OK;
  45. }
  46. else
  47. if (IsEqualIID(riid, IID_IUnknown))
  48. {
  49. *ppvObj = (IInstantiationInfo*) this;
  50. AddRef();
  51. return S_OK;
  52. }
  53. else
  54. if (IsEqualIID(riid, IID_ISerializable))
  55. {
  56. *ppvObj = (ISerializable*) this;
  57. AddRef();
  58. return S_OK;
  59. }
  60. *ppvObj = NULL;
  61. return E_NOINTERFACE;
  62. }
  63. ULONG InstantiationInfo::AddRef(void)
  64. {
  65. if (_parent)
  66. return _parent->AddRef();
  67. return 1;
  68. }
  69. ULONG InstantiationInfo::Release(void)
  70. {
  71. if (_parent)
  72. return _parent->Release();
  73. return 0;
  74. }
  75. //-----------------------------------------------------------------------
  76. // Methods from ISerializable
  77. //-----------------------------------------------------------------------
  78. STDMETHODIMP InstantiationInfo::Serialize(void *pv)
  79. {
  80. HRESULT hr;
  81. Serializer *pSer = (Serializer*) pv;
  82. handle_t handle;
  83. hr = pSer->GetSerializationHandle((void*) &handle);
  84. Win4Assert(hr==S_OK);
  85. InstantiationInfoData_Encode(handle, &_instantiationInfoData);
  86. return S_OK;
  87. }
  88. STDMETHODIMP InstantiationInfo::UnSerialize(void *pv)
  89. {
  90. Serializer *pSer = (Serializer*) pv;
  91. if (!_unSerialized)
  92. {
  93. handle_t handle;
  94. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  95. Win4Assert(hr==S_OK);
  96. _instantiationInfoData.pIID = 0;
  97. InstantiationInfoData_Decode(handle, &_instantiationInfoData);
  98. _unSerialized = TRUE;
  99. }
  100. return S_OK;
  101. }
  102. STDMETHODIMP InstantiationInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  103. {
  104. Serializer *pSer = (Serializer*) pv;
  105. if (!IsInproc(pSer))
  106. {
  107. handle_t handle;
  108. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  109. if (FAILED(hr))
  110. return hr;
  111. *pdwSize = InstantiationInfoData_AlignSize(handle,
  112. &_instantiationInfoData);
  113. MesHandleFree(handle);
  114. _instantiationInfoData.thisSize = *pdwSize;
  115. }
  116. else
  117. *pdwSize = 0;
  118. return S_OK;
  119. }
  120. STDMETHODIMP InstantiationInfo::GetCLSID(OUT CLSID *pclsid)
  121. {
  122. *pclsid = IID_IInstantiationInfo;
  123. return S_OK;
  124. }
  125. //---------------------------------------------------------------------------
  126. // Methods for ServerLocationInfo
  127. //---------------------------------------------------------------------------
  128. //-----------------------------------------------------------------------
  129. // Methods from IUnknown
  130. //-----------------------------------------------------------------------
  131. STDMETHODIMP ServerLocationInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  132. {
  133. if (_parent)
  134. return _parent->QueryInterface(riid, ppvObj);
  135. else
  136. return SerializableQueryInterface(riid, ppvObj);
  137. }
  138. STDMETHODIMP ServerLocationInfo::SerializableQueryInterface( REFIID riid, LPVOID* ppvObj)
  139. {
  140. if (IsEqualIID(riid, IID_IServerLocationInfo) ||
  141. IsEqualIID(riid, IID_IUnknown))
  142. {
  143. *ppvObj = (IServerLocationInfo*) this;
  144. AddRef();
  145. return S_OK;
  146. }
  147. else
  148. if (IsEqualIID(riid, IID_ISerializable))
  149. {
  150. *ppvObj = (ISerializable*) this;
  151. AddRef();
  152. return S_OK;
  153. }
  154. *ppvObj = NULL;
  155. return E_NOINTERFACE;
  156. }
  157. ULONG ServerLocationInfo::AddRef(void)
  158. {
  159. if (_parent)
  160. return _parent->AddRef();
  161. return 1;
  162. }
  163. ULONG ServerLocationInfo::Release(void)
  164. {
  165. if (_parent)
  166. return _parent->Release();
  167. return 0;
  168. }
  169. //-----------------------------------------------------------------------
  170. // Constructor/destructor
  171. //-----------------------------------------------------------------------
  172. ServerLocationInfo::ServerLocationInfo()
  173. {
  174. ZeroMemory(&_locationInfoData, sizeof(LocationInfoData));
  175. _pObjectContext = NULL;
  176. _pISSP = NULL;
  177. }
  178. ServerLocationInfo::~ServerLocationInfo()
  179. {
  180. if (_locationInfoData.machineName)
  181. ActMemFree(_locationInfoData.machineName);
  182. if (_pObjectContext)
  183. _pObjectContext->InternalRelease();
  184. // do not release _pISSP
  185. }
  186. //-----------------------------------------------------------------------
  187. // Methods
  188. //-----------------------------------------------------------------------
  189. STDMETHODIMP ServerLocationInfo::SetRemoteServerName(IN WCHAR *pwszMachineName)
  190. {
  191. HRESULT hr;
  192. if (_locationInfoData.machineName)
  193. {
  194. ActMemFree(_locationInfoData.machineName);
  195. _locationInfoData.machineName = NULL;
  196. }
  197. Win4Assert(_locationInfoData.machineName == NULL);
  198. if (pwszMachineName)
  199. {
  200. //
  201. // Some apps may unnecessarily put slashes before their
  202. // server names. We'll allow this and strip them off.
  203. //
  204. if (pwszMachineName[0] == L'\\' &&
  205. pwszMachineName[1] == L'\\' )
  206. pwszMachineName += 2;
  207. if ( 0 == *pwszMachineName)
  208. return CO_E_BAD_SERVER_NAME;
  209. BOOL fIsSelf;
  210. _locationInfoData.machineName =
  211. makeWStringCopy(pwszMachineName);
  212. if (_locationInfoData.machineName == NULL)
  213. return E_OUTOFMEMORY;
  214. }
  215. return S_OK;
  216. }
  217. STDMETHODIMP ServerLocationInfo::SetProcess(IN DWORD processId, OUT DWORD dwPRT)
  218. {
  219. HRESULT hr;
  220. ISpecialSystemProperties* pISSP = NULL;
  221. // This is necessary since we didn't want to break the wire-format
  222. // after RC2. If it wasn't for that, we could have put the storage for
  223. // dwPRT right into _locationInfoData.
  224. // Note: calling this method before this object is aggregated into the
  225. // actpropsin object means that this QI will fail (see
  226. // ServerLocationInfo::QueryInterface up above, _pParent will still be NULL)
  227. hr = this->QueryInterface(IID_ISpecialSystemProperties, (void**)&pISSP);
  228. if (SUCCEEDED(hr))
  229. {
  230. hr = pISSP->SetProcessRequestType(dwPRT);
  231. if (SUCCEEDED(hr))
  232. {
  233. _locationInfoData.processId = processId;
  234. }
  235. pISSP->Release();
  236. }
  237. return hr;
  238. }
  239. STDMETHODIMP ServerLocationInfo::GetProcess(OUT DWORD *pProcessId, OUT DWORD* pdwPRT)
  240. {
  241. HRESULT hr;
  242. ISpecialSystemProperties* pISSP = NULL;
  243. // This is necessary since we didn't want to break the wire-format
  244. // after RC2. If it wasn't for that, we could have put the storage for
  245. // dwPRT right into _locationInfoData.
  246. // Note: calling this method before this object is aggregated into the
  247. // actpropsin object means that this QI will fail (see
  248. // ServerLocationInfo::QueryInterface up above, _pParent will still be NULL)
  249. hr = this->QueryInterface(IID_ISpecialSystemProperties, (void**)&pISSP);
  250. if (SUCCEEDED(hr))
  251. {
  252. hr = pISSP->GetProcessRequestType(pdwPRT);
  253. if (SUCCEEDED(hr))
  254. {
  255. *pProcessId = _locationInfoData.processId;
  256. }
  257. pISSP->Release();
  258. }
  259. return hr;
  260. }
  261. //-----------------------------------------------------------------------
  262. // Methods from ISerializable
  263. //-----------------------------------------------------------------------
  264. STDMETHODIMP ServerLocationInfo::Serialize(void *pv)
  265. {
  266. Serializer *pSer = (Serializer*) pv;
  267. handle_t handle;
  268. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  269. Win4Assert(hr==S_OK);
  270. LocationInfoData_Encode(handle, &_locationInfoData);
  271. return S_OK;
  272. }
  273. STDMETHODIMP ServerLocationInfo::UnSerialize(void *pv)
  274. {
  275. Serializer *pSer = (Serializer*) pv;
  276. if (!_unSerialized)
  277. {
  278. _locationInfoData.machineName=0;
  279. handle_t handle;
  280. pSer->GetSerializationHandle((void*) &handle);
  281. LocationInfoData_Decode(handle, &_locationInfoData);
  282. _unSerialized = TRUE;
  283. }
  284. return S_OK;
  285. }
  286. STDMETHODIMP ServerLocationInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  287. {
  288. Serializer *pSer = (Serializer*) pv;
  289. if (!IsInproc(pSer))
  290. {
  291. handle_t handle;
  292. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  293. if (FAILED(hr))
  294. return hr;
  295. *pdwSize = LocationInfoData_AlignSize(handle, &_locationInfoData);
  296. MesHandleFree(handle);
  297. }
  298. else
  299. *pdwSize = 0;
  300. return S_OK;
  301. }
  302. STDMETHODIMP ServerLocationInfo::GetCLSID(OUT CLSID *pclsid)
  303. {
  304. *pclsid = IID_IServerLocationInfo;
  305. return S_OK;
  306. }
  307. //---------------------------------------------------------------------------
  308. // Methods for SecurityInfo
  309. //---------------------------------------------------------------------------
  310. //-----------------------------------------------------------------------
  311. // Methods from IUnknown
  312. //-----------------------------------------------------------------------
  313. STDMETHODIMP SecurityInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  314. {
  315. if (_parent)
  316. return _parent->QueryInterface(riid, ppvObj);
  317. else
  318. return SerializableQueryInterface(riid, ppvObj);
  319. }
  320. STDMETHODIMP SecurityInfo::SerializableQueryInterface( REFIID riid, LPVOID* ppvObj)
  321. {
  322. if (IsEqualIID(riid, IID_IActivationSecurityInfo) ||
  323. IsEqualIID(riid, IID_IUnknown))
  324. {
  325. *ppvObj = (IActivationSecurityInfo*) this;
  326. AddRef();
  327. return S_OK;
  328. }
  329. else
  330. if (IsEqualIID(riid, IID_ISerializable))
  331. {
  332. *ppvObj = (ISerializable*) this;
  333. AddRef();
  334. return S_OK;
  335. }
  336. else
  337. if (IsEqualIID(riid, IID_ILegacyInfo))
  338. {
  339. *ppvObj = (ILegacyInfo*) this;
  340. AddRef();
  341. return S_OK;
  342. }
  343. *ppvObj = NULL;
  344. return E_NOINTERFACE;
  345. }
  346. ULONG SecurityInfo::AddRef(void)
  347. {
  348. if (_parent)
  349. return _parent->AddRef();
  350. return 1;
  351. }
  352. ULONG SecurityInfo::Release(void)
  353. {
  354. if (_parent)
  355. return _parent->Release();
  356. return 0;
  357. }
  358. //-----------------------------------------------------------------------
  359. // Methods from ISerializable
  360. //-----------------------------------------------------------------------
  361. STDMETHODIMP SecurityInfo::Serialize(IN void *pv)
  362. {
  363. Serializer *pSer = (Serializer*) pv;
  364. handle_t handle;
  365. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  366. Win4Assert(hr==S_OK);
  367. SecurityInfoData_Encode(handle, &_securityInfoData);
  368. return S_OK;
  369. }
  370. STDMETHODIMP SecurityInfo::UnSerialize(IN void *pv)
  371. {
  372. Serializer *pSer = (Serializer*) pv;
  373. if (!_unSerialized)
  374. {
  375. handle_t handle;
  376. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  377. Win4Assert(hr==S_OK);
  378. _securityInfoData.pServerInfo = 0;
  379. _securityInfoData.pAuthIdentityInfo = 0;
  380. SecurityInfoData_Decode(handle, &_securityInfoData);
  381. _unSerialized = TRUE;
  382. }
  383. return S_OK;
  384. }
  385. STDMETHODIMP SecurityInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  386. {
  387. Serializer *pSer = (Serializer*) pv;
  388. if (!IsInproc(pSer))
  389. {
  390. handle_t handle;
  391. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  392. if (FAILED(hr))
  393. return hr;
  394. *pdwSize = SecurityInfoData_AlignSize(handle, &_securityInfoData);
  395. MesHandleFree(handle);
  396. }
  397. else
  398. *pdwSize = 0;
  399. return S_OK;
  400. }
  401. STDMETHODIMP SecurityInfo::GetCLSID(OUT CLSID *pclsid)
  402. {
  403. *pclsid = IID_IActivationSecurityInfo;
  404. return S_OK;
  405. }
  406. //---------------------------------------------------------------------------
  407. // Methods for ScmRequestInfo
  408. //---------------------------------------------------------------------------
  409. //-----------------------------------------------------------------------
  410. // Methods from IUnknown
  411. //-----------------------------------------------------------------------
  412. STDMETHODIMP ScmRequestInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  413. {
  414. if (_parent)
  415. return _parent->QueryInterface(riid, ppvObj);
  416. else
  417. return SerializableQueryInterface(riid, ppvObj);
  418. }
  419. STDMETHODIMP ScmRequestInfo::SerializableQueryInterface( REFIID riid, LPVOID*
  420. ppvObj)
  421. {
  422. if (IsEqualIID(riid, IID_IScmRequestInfo) ||
  423. IsEqualIID(riid, IID_IUnknown))
  424. {
  425. *ppvObj = (IScmRequestInfo*) this;
  426. AddRef();
  427. return S_OK;
  428. }
  429. else
  430. if (IsEqualIID(riid, IID_ISerializable))
  431. {
  432. *ppvObj = (ISerializable*) this;
  433. AddRef();
  434. return S_OK;
  435. }
  436. *ppvObj = NULL;
  437. return E_NOINTERFACE;
  438. }
  439. ULONG ScmRequestInfo::AddRef(void)
  440. {
  441. if (_parent)
  442. return _parent->AddRef();
  443. return 1;
  444. }
  445. ULONG ScmRequestInfo::Release(void)
  446. {
  447. if (_parent)
  448. return _parent->Release();
  449. #if 0 //Always allocate on stack
  450. ULONG count;
  451. if ((count=InterlockedDecrement(&_cRefs)) == 0)
  452. {
  453. delete this;
  454. return 0;
  455. }
  456. return count;
  457. #else
  458. return 0;
  459. #endif
  460. }
  461. //-----------------------------------------------------------------------
  462. // Methods from ISerializable
  463. //-----------------------------------------------------------------------
  464. STDMETHODIMP ScmRequestInfo::Serialize(IN void *pv)
  465. {
  466. Serializer *pSer = (Serializer*) pv;
  467. handle_t handle;
  468. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  469. Win4Assert(hr==S_OK);
  470. ScmRequestInfoData_Encode(handle, &_scmRequestInfoData);
  471. return S_OK;
  472. }
  473. STDMETHODIMP ScmRequestInfo::UnSerialize(IN void *pv)
  474. {
  475. Serializer *pSer = (Serializer*) pv;
  476. if (!_unSerialized)
  477. {
  478. handle_t handle;
  479. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  480. Win4Assert(hr==S_OK);
  481. _scmRequestInfoData.pScmInfo = 0;
  482. _scmRequestInfoData.remoteRequest = 0;
  483. ScmRequestInfoData_Decode(handle, &_scmRequestInfoData);
  484. _unSerialized = TRUE;
  485. }
  486. return S_OK;
  487. }
  488. STDMETHODIMP ScmRequestInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  489. {
  490. Serializer *pSer = (Serializer*) pv;
  491. if (!IsInproc(pSer))
  492. {
  493. handle_t handle;
  494. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  495. if (FAILED(hr))
  496. return hr;
  497. *pdwSize = ScmRequestInfoData_AlignSize(handle, &_scmRequestInfoData);
  498. MesHandleFree(handle);
  499. }
  500. else
  501. *pdwSize = 0;
  502. return S_OK;
  503. }
  504. STDMETHODIMP ScmRequestInfo::GetCLSID(OUT CLSID *pclsid)
  505. {
  506. *pclsid = IID_IScmRequestInfo;
  507. return S_OK;
  508. }
  509. //---------------------------------------------------------------------------
  510. // Methods for ScmReplyInfo
  511. //---------------------------------------------------------------------------
  512. //-----------------------------------------------------------------------
  513. // Methods from IUnknown
  514. //-----------------------------------------------------------------------
  515. STDMETHODIMP ScmReplyInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  516. {
  517. if (_parent)
  518. return _parent->QueryInterface(riid, ppvObj);
  519. else
  520. return SerializableQueryInterface(riid, ppvObj);
  521. }
  522. STDMETHODIMP ScmReplyInfo::SerializableQueryInterface( REFIID riid, LPVOID*
  523. ppvObj)
  524. {
  525. if (IsEqualIID(riid, IID_IScmReplyInfo) ||
  526. IsEqualIID(riid, IID_IUnknown))
  527. {
  528. *ppvObj = (IScmReplyInfo*) this;
  529. AddRef();
  530. return S_OK;
  531. }
  532. else
  533. if (IsEqualIID(riid, IID_ISerializable))
  534. {
  535. *ppvObj = (ISerializable*) this;
  536. AddRef();
  537. return S_OK;
  538. }
  539. *ppvObj = NULL;
  540. return E_NOINTERFACE;
  541. }
  542. ULONG ScmReplyInfo::AddRef(void)
  543. {
  544. if (_parent)
  545. return _parent->AddRef();
  546. return 1;
  547. }
  548. ULONG ScmReplyInfo::Release(void)
  549. {
  550. if (_parent)
  551. return _parent->Release();
  552. #if 0 //Always allocate on stack
  553. ULONG count;
  554. if ((count=InterlockedDecrement(&_cRefs)) == 0)
  555. {
  556. delete this;
  557. return 0;
  558. }
  559. return count;
  560. #else
  561. return 0;
  562. #endif
  563. }
  564. //-----------------------------------------------------------------------
  565. // Methods from ISerializable
  566. //-----------------------------------------------------------------------
  567. STDMETHODIMP ScmReplyInfo::Serialize(IN void *pv)
  568. {
  569. Serializer *pSer = (Serializer*) pv;
  570. handle_t handle;
  571. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  572. Win4Assert(hr==S_OK);
  573. ScmReplyInfoData_Encode(handle, &_scmReplyInfoData);
  574. return S_OK;
  575. }
  576. STDMETHODIMP ScmReplyInfo::UnSerialize(IN void *pv)
  577. {
  578. Serializer *pSer = (Serializer*) pv;
  579. if (!_unSerialized)
  580. {
  581. handle_t handle;
  582. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  583. Win4Assert(hr==S_OK);
  584. _scmReplyInfoData.remoteReply = 0;
  585. _scmReplyInfoData.pResolverInfo = 0;
  586. ScmReplyInfoData_Decode(handle, &_scmReplyInfoData);
  587. _unSerialized = TRUE;
  588. }
  589. return S_OK;
  590. }
  591. STDMETHODIMP ScmReplyInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  592. {
  593. Serializer *pSer = (Serializer*) pv;
  594. handle_t handle;
  595. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  596. if (FAILED(hr))
  597. return hr;
  598. *pdwSize = ScmReplyInfoData_AlignSize(handle, &_scmReplyInfoData);
  599. MesHandleFree(handle);
  600. return S_OK;
  601. }
  602. STDMETHODIMP ScmReplyInfo::GetCLSID(OUT CLSID *pclsid)
  603. {
  604. *pclsid = IID_IScmReplyInfo;
  605. return S_OK;
  606. }
  607. //---------------------------------------------------------------------------
  608. // Methods for ContextInfo
  609. //---------------------------------------------------------------------------
  610. //-----------------------------------------------------------------------
  611. // Methods from IUnknown
  612. //-----------------------------------------------------------------------
  613. STDMETHODIMP ContextInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  614. {
  615. if (_parent)
  616. return _parent->QueryInterface(riid, ppvObj);
  617. else
  618. return SerializableQueryInterface(riid, ppvObj);
  619. }
  620. STDMETHODIMP ContextInfo::SerializableQueryInterface(REFIID riid,
  621. LPVOID* ppvObj)
  622. {
  623. if (IsEqualIID(riid, IID_IPrivActivationContextInfo))
  624. {
  625. *ppvObj = (IPrivActivationContextInfo*) this;
  626. AddRef();
  627. return S_OK;
  628. }
  629. else if (IsEqualIID(riid, IID_IActivationContextInfo)
  630. || IsEqualIID(riid, IID_IUnknown))
  631. {
  632. *ppvObj = (IActivationContextInfo*) this;
  633. AddRef();
  634. return S_OK;
  635. }
  636. else if (IsEqualIID(riid, IID_IOverrideTargetContext))
  637. {
  638. *ppvObj = (IOverrideTargetContext*) this;
  639. AddRef();
  640. return S_OK;
  641. }
  642. else if (IsEqualIID(riid, IID_ISerializable))
  643. {
  644. *ppvObj = (ISerializable*) this;
  645. AddRef();
  646. return S_OK;
  647. }
  648. *ppvObj = NULL;
  649. return E_NOINTERFACE;
  650. }
  651. ULONG ContextInfo::AddRef(void)
  652. {
  653. if (_parent)
  654. return _parent->AddRef();
  655. return 1;
  656. }
  657. ULONG ContextInfo::Release(void)
  658. {
  659. if (_parent)
  660. return _parent->Release();
  661. return 0;
  662. }
  663. HRESULT ContextInfo::GetClientContext(OUT IContext **ppCtx)
  664. {
  665. CObjectContext *pCtx;
  666. HRESULT hr = GetInternalClientContext(&pCtx);
  667. if (SUCCEEDED(hr) && pCtx)
  668. {
  669. pCtx->AddRef();
  670. pCtx->InternalRelease();
  671. *ppCtx = (IContext*)pCtx;
  672. }
  673. return hr;
  674. }
  675. HRESULT ContextInfo::GetInternalClientContext(OUT CObjectContext **ppCtx)
  676. {
  677. HRESULT hr = S_OK;
  678. InitMarshalling();
  679. if ((_unSerialized) &&
  680. (_pClientCtx==NULL) &&
  681. (_contextInfoData.pIFDClientCtx != NULL))
  682. {
  683. if (pfnCoUnmarshalInterface)
  684. {
  685. ActivationStream stream((InterfaceData*)_contextInfoData.pIFDClientCtx);
  686. hr = pfnCoUnmarshalInterface(&stream,
  687. IID_IStdObjectContext,
  688. (void**)&_pClientCtx);
  689. }
  690. else
  691. {
  692. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  693. }
  694. if (SUCCEEDED(hr))
  695. {
  696. // Unmarshaling the context gives a user reference. We want
  697. // an internal ref, so we take one and release the user ref.
  698. _pClientCtx->InternalAddRef();
  699. _pClientCtx->Release();
  700. }
  701. ActMemFree(_contextInfoData.pIFDClientCtx);
  702. _contextInfoData.pIFDClientCtx = NULL;
  703. }
  704. if (_pClientCtx)
  705. _pClientCtx->InternalAddRef();
  706. else
  707. SetClientContextNotOK();
  708. *ppCtx = _pClientCtx;
  709. return hr;
  710. }
  711. STDMETHODIMP ContextInfo::GetPrototypeContext(OUT IContext **ppCtx)
  712. {
  713. CObjectContext *pCtx;
  714. HRESULT hr = GetInternalPrototypeContext(&pCtx);
  715. if (SUCCEEDED(hr))
  716. {
  717. pCtx->AddRef();
  718. pCtx->InternalRelease();
  719. *ppCtx = (IContext*)pCtx;
  720. }
  721. return hr;
  722. }
  723. HRESULT ContextInfo::GetInternalPrototypeContext(OUT CObjectContext **ppCtx)
  724. {
  725. extern HRESULT CObjectContextCF_CreateInstance(IUnknown *pUnkOuter,
  726. REFIID riid,
  727. void** ppv);
  728. InitMarshalling();
  729. HRESULT hr = S_OK;
  730. if ((_unSerialized) &&
  731. (_pPrototypeCtx==NULL) &&
  732. (_contextInfoData.pIFDPrototypeCtx != NULL))
  733. {
  734. if (pfnCoUnmarshalInterface)
  735. {
  736. ActivationStream stream((InterfaceData*)_contextInfoData.pIFDPrototypeCtx);
  737. hr = pfnCoUnmarshalInterface(&stream,
  738. IID_IStdObjectContext,
  739. (void**)&_pPrototypeCtx);
  740. }
  741. else
  742. {
  743. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  744. }
  745. if (SUCCEEDED(hr))
  746. {
  747. // Unmarshaling the context gives a user reference. We want
  748. // an internal ref, so we take one and release the user ref.
  749. _pPrototypeCtx->InternalAddRef();
  750. _pPrototypeCtx->Release();
  751. }
  752. ActMemFree(_contextInfoData.pIFDPrototypeCtx);
  753. _contextInfoData.pIFDPrototypeCtx = NULL;
  754. }
  755. else
  756. if (!_pPrototypeCtx)
  757. {
  758. hr = CObjectContextCF_CreateInstance(NULL,
  759. IID_IStdObjectContext,
  760. (void**) &_pPrototypeCtx);
  761. if (SUCCEEDED(hr))
  762. {
  763. // Creating the context gives a user reference. We want
  764. // an internal ref, so we take one and release the user ref.
  765. _pPrototypeCtx->InternalAddRef();
  766. _pPrototypeCtx->Release();
  767. }
  768. }
  769. if (SUCCEEDED(hr))
  770. _pPrototypeCtx->InternalAddRef();
  771. *ppCtx = _pPrototypeCtx;
  772. return hr;
  773. }
  774. //-----------------------------------------------------------------------
  775. // Methods from ISerializable
  776. //-----------------------------------------------------------------------
  777. STDMETHODIMP ContextInfo::Serialize(IN void *pv)
  778. {
  779. Serializer *pSer = (Serializer*) pv;
  780. //-------------------------------------------------------------------
  781. // Encode header
  782. //-------------------------------------------------------------------
  783. handle_t handle;
  784. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  785. Win4Assert(hr==S_OK);
  786. ActivationContextInfoData_Encode(handle, &_contextInfoData);
  787. _unSerialized = FALSE;
  788. return S_OK;
  789. }
  790. STDMETHODIMP ContextInfo::UnSerialize(IN void *pv)
  791. {
  792. Serializer *pSer = (Serializer*) pv;
  793. if (!_unSerialized)
  794. {
  795. handle_t handle;
  796. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  797. Win4Assert(hr==S_OK);
  798. _pClientCtx = 0;
  799. _pPrototypeCtx = 0;
  800. ActivationContextInfoData_Decode(handle, &_contextInfoData);
  801. _unSerialized = TRUE;
  802. }
  803. return S_OK;
  804. }
  805. STDMETHODIMP ContextInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  806. {
  807. Serializer *pSer = (Serializer*) pv;
  808. HRESULT rethr=S_OK;
  809. //--------------------------------------------------------------------
  810. // If Is an inproc path, no need to marshal context
  811. //--------------------------------------------------------------------
  812. if (IsInproc(pSer))
  813. {
  814. *pdwSize = 0;
  815. return S_OK;
  816. }
  817. _toReleaseIFD = FALSE;
  818. if (_pClientCtx)
  819. {
  820. rethr = GetIFDFromInterface((IUnknown*)(IObjContext*) _pClientCtx,
  821. IID_IContext,
  822. MSHCTX_DIFFERENTMACHINE,
  823. MSHLFLAGS_NORMAL,
  824. &_contextInfoData.pIFDClientCtx);
  825. if (FAILED(rethr))
  826. {
  827. _contextInfoData.pIFDClientCtx = NULL;
  828. return rethr;
  829. }
  830. }
  831. if (_pPrototypeCtx)
  832. {
  833. rethr = GetIFDFromInterface((IUnknown*)(IObjContext*) _pPrototypeCtx,
  834. IID_IContext,
  835. MSHCTX_DIFFERENTMACHINE,
  836. MSHLFLAGS_NORMAL,
  837. &_contextInfoData.pIFDPrototypeCtx);
  838. if (FAILED(rethr))
  839. {
  840. _contextInfoData.pIFDPrototypeCtx = NULL;
  841. return rethr;
  842. }
  843. }
  844. handle_t handle;
  845. rethr = pSer->GetSizingHandle((void*) &handle);
  846. if (SUCCEEDED(rethr))
  847. {
  848. *pdwSize = ActivationContextInfoData_AlignSize(handle,
  849. &_contextInfoData);
  850. MesHandleFree(handle);
  851. }
  852. return rethr;
  853. }
  854. STDMETHODIMP ContextInfo::GetCLSID(OUT CLSID *pclsid)
  855. {
  856. *pclsid = IID_IActivationContextInfo;
  857. return S_OK;
  858. }
  859. //---------------------------------------------------------------------------
  860. // Methods for InstanceInfo
  861. //---------------------------------------------------------------------------
  862. //-----------------------------------------------------------------------
  863. // Methods from IUnknown
  864. //-----------------------------------------------------------------------
  865. STDMETHODIMP InstanceInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  866. {
  867. if (_parent)
  868. return _parent->QueryInterface(riid, ppvObj);
  869. else
  870. return SerializableQueryInterface(riid, ppvObj);
  871. }
  872. STDMETHODIMP InstanceInfo::SerializableQueryInterface( REFIID riid, LPVOID*
  873. ppvObj)
  874. {
  875. if (IsEqualIID(riid, IID_IInstanceInfo) ||
  876. IsEqualIID(riid, IID_IUnknown))
  877. {
  878. *ppvObj = (IInstanceInfo*) this;
  879. AddRef();
  880. return S_OK;
  881. }
  882. else
  883. if (IsEqualIID(riid, IID_ISerializable))
  884. {
  885. *ppvObj = (ISerializable*) this;
  886. AddRef();
  887. return S_OK;
  888. }
  889. *ppvObj = NULL;
  890. return E_NOINTERFACE;
  891. }
  892. ULONG InstanceInfo::AddRef(void)
  893. {
  894. if (_parent)
  895. return _parent->AddRef();
  896. return 1;
  897. }
  898. ULONG InstanceInfo::Release(void)
  899. {
  900. if (_parent)
  901. return _parent->Release();
  902. #if 0 //Always allocate on stack
  903. ULONG count;
  904. if ((count=InterlockedDecrement(&_cRefs)) == 0)
  905. {
  906. delete this;
  907. return 0;
  908. }
  909. return count;
  910. #else
  911. return 0;
  912. #endif
  913. }
  914. //-----------------------------------------------------------------------
  915. // Methods from IInstanceInfo
  916. //-----------------------------------------------------------------------
  917. STDMETHODIMP InstanceInfo::SetStorage(IN IStorage *pstg)
  918. {
  919. _pstg = pstg;
  920. if (_pstg)
  921. _pstg->AddRef();
  922. return S_OK;
  923. }
  924. STDMETHODIMP InstanceInfo::GetStorage(OUT IStorage **ppstg)
  925. {
  926. HRESULT hr = S_OK;
  927. InitMarshalling();
  928. if ((_pstg==NULL) &&
  929. (_instanceInfoData.ifdStg != NULL))
  930. {
  931. if (pfnCoUnmarshalInterface)
  932. {
  933. ActivationStream stream((InterfaceData*)_instanceInfoData.ifdStg);
  934. hr = pfnCoUnmarshalInterface(&stream, IID_IStorage, (void**)&_pstg);
  935. }
  936. else
  937. {
  938. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  939. }
  940. }
  941. if (_pstg)
  942. _pstg->AddRef();
  943. *ppstg = _pstg;
  944. return hr;
  945. }
  946. //-----------------------------------------------------------------------
  947. // Methods from ISerializable
  948. //-----------------------------------------------------------------------
  949. STDMETHODIMP InstanceInfo::Serialize(IN void *pv)
  950. {
  951. Serializer *pSer = (Serializer*) pv;
  952. handle_t handle;
  953. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  954. Win4Assert(hr==S_OK);
  955. InstanceInfoData_Encode(handle, &_instanceInfoData);
  956. _unSerialized = FALSE;
  957. return hr;
  958. }
  959. STDMETHODIMP InstanceInfo::UnSerialize(IN void *pv)
  960. {
  961. Serializer *pSer = (Serializer*) pv;
  962. HRESULT hr = S_OK;
  963. if (!_unSerialized)
  964. {
  965. handle_t handle;
  966. hr = pSer->GetSerializationHandle((void*) &handle);
  967. Win4Assert(hr==S_OK);
  968. InstanceInfoData_Decode(handle, &_instanceInfoData);
  969. _unSerialized = TRUE;
  970. }
  971. return hr;
  972. }
  973. //-----------------------------------------------------------------------
  974. // NOTE: This function should only get called if a storage pointer is
  975. // present during inproc/crossctx marshalling
  976. //-----------------------------------------------------------------------
  977. STDMETHODIMP InstanceInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  978. {
  979. Serializer *pSer = (Serializer*) pv;
  980. HRESULT rethr=S_OK;
  981. DWORD dwCurrDestCtx;
  982. pSer->GetCurrDestCtx(&dwCurrDestCtx);
  983. //-------------------------------------------------------------------
  984. //Need to marshal interface first to compute size
  985. //-------------------------------------------------------------------
  986. if (_pstg)
  987. {
  988. //----------------------------------------------------------------
  989. // Need to free previously marshalled data
  990. //----------------------------------------------------------------
  991. if (_instanceInfoData.ifdStg)
  992. ActMemFree(_instanceInfoData.ifdStg);
  993. if (dwCurrDestCtx == MSHCTX_LOCAL)
  994. dwCurrDestCtx = MSHCTX_DIFFERENTMACHINE;
  995. rethr = GetIFDFromInterface((IUnknown*) _pstg,
  996. IID_IStorage,
  997. dwCurrDestCtx,
  998. MSHLFLAGS_NORMAL,
  999. &_instanceInfoData.ifdStg);
  1000. if (FAILED(rethr))
  1001. {
  1002. _instanceInfoData.ifdStg = NULL;
  1003. return rethr;
  1004. }
  1005. _pstg->Release();
  1006. _pstg = NULL;
  1007. }
  1008. if (IsInproc(pSer))
  1009. {
  1010. *pdwSize = 0;
  1011. }
  1012. else
  1013. {
  1014. //-------------------------------------------------------------------
  1015. // Encode header
  1016. //-------------------------------------------------------------------
  1017. handle_t handle;
  1018. rethr = pSer->GetSizingHandle((void*) &handle);
  1019. if (SUCCEEDED(rethr))
  1020. {
  1021. *pdwSize = InstanceInfoData_AlignSize(handle,
  1022. &_instanceInfoData);
  1023. MesHandleFree(handle);
  1024. }
  1025. }
  1026. return rethr;
  1027. }
  1028. STDMETHODIMP InstanceInfo::GetCLSID(OUT CLSID *pclsid)
  1029. {
  1030. *pclsid = IID_IInstanceInfo;
  1031. return S_OK;
  1032. }
  1033. //-----------------------------------------------------------------------
  1034. // Methods from IOpaqueDataInfo
  1035. //-----------------------------------------------------------------------
  1036. STDMETHODIMP OpaqueDataInfo::AddOpaqueData (OpaqueData *pData)
  1037. {
  1038. HRESULT hr;
  1039. if (_cOpaqueData == _dwCollSize)
  1040. {
  1041. OpaqueData *pNew = (OpaqueData*)
  1042. ActMemAlloc(sizeof(OpaqueData) *(_dwCollSize+20));
  1043. if (pNew == NULL)
  1044. {
  1045. return E_OUTOFMEMORY;
  1046. }
  1047. _dwCollSize += 20;
  1048. CopyOpaqueData(pNew, _pOpaqueData,
  1049. _cOpaqueData, FALSE);
  1050. ActMemFree(_pOpaqueData);
  1051. _pOpaqueData = pNew;
  1052. }
  1053. hr = CopyOpaqueData(&_pOpaqueData[_cOpaqueData], pData,
  1054. 1, TRUE);
  1055. if (FAILED(hr))
  1056. return hr;
  1057. _cOpaqueData++;
  1058. return S_OK;
  1059. }
  1060. STDMETHODIMP OpaqueDataInfo::GetOpaqueData (REFGUID guid,
  1061. OpaqueData **pData)
  1062. {
  1063. for (DWORD i=0; i < _cOpaqueData ; i++)
  1064. {
  1065. if (_pOpaqueData[i].guid == guid)
  1066. {
  1067. *pData = &_pOpaqueData[i];
  1068. return S_OK;
  1069. }
  1070. }
  1071. return E_FAIL;
  1072. }
  1073. STDMETHODIMP OpaqueDataInfo::DeleteOpaqueData (REFGUID guid)
  1074. {
  1075. BOOL found = FALSE;
  1076. for (DWORD i=0; i < _cOpaqueData ; i++)
  1077. {
  1078. if (_pOpaqueData[i].guid == guid)
  1079. {
  1080. found = TRUE;
  1081. break;
  1082. }
  1083. }
  1084. if (!found)
  1085. return E_FAIL;
  1086. ActMemFree(_pOpaqueData[i].data);
  1087. for (i=i+1; i < _cOpaqueData ; i++)
  1088. {
  1089. CopyOpaqueData(&_pOpaqueData[i-1],
  1090. &_pOpaqueData[i],
  1091. 1, FALSE);
  1092. }
  1093. _cOpaqueData--;
  1094. return S_OK;
  1095. }
  1096. STDMETHODIMP OpaqueDataInfo::GetOpaqueDataCount (ULONG *pulCount)
  1097. {
  1098. *pulCount = _cOpaqueData;
  1099. return S_OK;
  1100. }
  1101. STDMETHODIMP OpaqueDataInfo::GetAllOpaqueData (OpaqueData **prgData)
  1102. {
  1103. *prgData = _pOpaqueData;
  1104. return S_OK;
  1105. }
  1106. //-----------------------------------------------------------------------
  1107. // Methods from ISerializable
  1108. //-----------------------------------------------------------------------
  1109. STDMETHODIMP OpaqueDataInfo::Serialize(IN void *pv)
  1110. {
  1111. _unSerialized = FALSE;
  1112. return S_OK;
  1113. }
  1114. STDMETHODIMP OpaqueDataInfo::UnSerialize(IN void *pv)
  1115. {
  1116. if (!_parent)
  1117. return E_INVALIDARG;
  1118. HRESULT hr = S_OK;
  1119. if (!_unSerialized)
  1120. {
  1121. hr = ((ActivationProperties*)_pAct)->GetOpaqueDataInfo(&_cOpaqueData, &_pOpaqueData);
  1122. _unSerialized = TRUE;
  1123. }
  1124. return hr;
  1125. }
  1126. STDMETHODIMP OpaqueDataInfo::GetSize(IN void *pv, OUT DWORD *pdwSize)
  1127. {
  1128. if (!_parent)
  1129. return E_INVALIDARG;
  1130. *pdwSize = 0;
  1131. Serializer *pSer = (Serializer*) pv;
  1132. if ((!IsInproc(pSer)) && _cOpaqueData)
  1133. {
  1134. ((ActivationProperties*)_pAct)->SetOpaqueDataInfo(_cOpaqueData,
  1135. _pOpaqueData);
  1136. _cOpaqueData = 0;
  1137. _pOpaqueData = NULL;
  1138. }
  1139. return S_OK;
  1140. }
  1141. STDMETHODIMP OpaqueDataInfo::GetCLSID(OUT CLSID *pclsid)
  1142. {
  1143. *pclsid = IID_IOpaqueDataInfo;
  1144. return S_OK;
  1145. }
  1146. STDMETHODIMP OpaqueDataInfo::SetParent(ISerializableParent *pParent)
  1147. {
  1148. _parent = pParent;
  1149. if (pParent)
  1150. return pParent->QueryInterface(CLSID_ActivationProperties,
  1151. &_pAct);
  1152. return S_OK;
  1153. }
  1154. //-----------------------------------------------------------------------
  1155. // Methods from IUnknown
  1156. //-----------------------------------------------------------------------
  1157. STDMETHODIMP OpaqueDataInfo::QueryInterface( REFIID riid, LPVOID* ppvObj)
  1158. {
  1159. if (_parent)
  1160. return _parent->QueryInterface(riid, ppvObj);
  1161. else
  1162. return SerializableQueryInterface(riid, ppvObj);
  1163. }
  1164. STDMETHODIMP OpaqueDataInfo::SerializableQueryInterface( REFIID riid, LPVOID* ppvObj)
  1165. {
  1166. //Use IID_OpaqueDataInfo to return the real object right now
  1167. if (IsEqualIID(riid, IID_IOpaqueDataInfo))
  1168. {
  1169. *ppvObj = (OpaqueDataInfo*) this;
  1170. AddRef();
  1171. return S_OK;
  1172. }
  1173. else
  1174. if (IsEqualIID(riid, IID_IUnknown))
  1175. {
  1176. *ppvObj = (IOpaqueDataInfo*) this;
  1177. AddRef();
  1178. return S_OK;
  1179. }
  1180. else
  1181. if (IsEqualIID(riid, IID_ISerializable))
  1182. {
  1183. *ppvObj = (ISerializable*) this;
  1184. AddRef();
  1185. return S_OK;
  1186. }
  1187. *ppvObj = NULL;
  1188. return E_NOINTERFACE;
  1189. }
  1190. ULONG OpaqueDataInfo::AddRef(void)
  1191. {
  1192. if (_parent)
  1193. return _parent->AddRef();
  1194. return 1;
  1195. }
  1196. ULONG OpaqueDataInfo::Release(void)
  1197. {
  1198. if (_parent)
  1199. return _parent->Release();
  1200. return 0;
  1201. }
  1202. //-----------------------------------------------------------------------
  1203. // Methods from IUnknown
  1204. //-----------------------------------------------------------------------
  1205. STDMETHODIMP SpecialProperties::QueryInterface( REFIID riid, LPVOID* ppvObj)
  1206. {
  1207. if (_parent)
  1208. return _parent->QueryInterface(riid, ppvObj);
  1209. else
  1210. return SerializableQueryInterface(riid, ppvObj);
  1211. }
  1212. STDMETHODIMP SpecialProperties::SerializableQueryInterface( REFIID riid, LPVOID
  1213. * ppvObj)
  1214. {
  1215. //Use IID_ISpecialSystemProperties to return the real object right now
  1216. if (IsEqualIID(riid, IID_ISpecialSystemProperties))
  1217. {
  1218. *ppvObj = (SpecialProperties*) this;
  1219. AddRef();
  1220. return S_OK;
  1221. }
  1222. else
  1223. if (IsEqualIID(riid, IID_IUnknown))
  1224. {
  1225. *ppvObj = (ISpecialSystemProperties*) this;
  1226. AddRef();
  1227. return S_OK;
  1228. }
  1229. else
  1230. if (IsEqualIID(riid, IID_ISerializable))
  1231. {
  1232. *ppvObj = (ISerializable*) this;
  1233. AddRef();
  1234. return S_OK;
  1235. }
  1236. *ppvObj = NULL;
  1237. return E_NOINTERFACE;
  1238. }
  1239. ULONG SpecialProperties::AddRef(void)
  1240. {
  1241. if (_parent)
  1242. return _parent->AddRef();
  1243. return 1;
  1244. }
  1245. ULONG SpecialProperties::Release(void)
  1246. {
  1247. if (_parent)
  1248. return _parent->Release();
  1249. return 0;
  1250. }
  1251. //-----------------------------------------------------------------------
  1252. // Methods from ISerializable
  1253. //-----------------------------------------------------------------------
  1254. STDMETHODIMP SpecialProperties::Serialize(IN void *pv)
  1255. {
  1256. Serializer *pSer = (Serializer*) pv;
  1257. handle_t handle;
  1258. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  1259. Win4Assert(hr==S_OK);
  1260. SpecialPropertiesData_Encode(handle, &_data);
  1261. return S_OK;
  1262. }
  1263. STDMETHODIMP SpecialProperties::UnSerialize(IN void *pv)
  1264. {
  1265. Serializer *pSer = (Serializer*) pv;
  1266. if (!_unSerialized)
  1267. {
  1268. handle_t handle;
  1269. HRESULT hr = pSer->GetSerializationHandle((void*) &handle);
  1270. Win4Assert(hr==S_OK);
  1271. SpecialPropertiesData_Decode(handle, &_data);
  1272. _unSerialized = TRUE;
  1273. }
  1274. return S_OK;
  1275. }
  1276. STDMETHODIMP SpecialProperties::GetSize(IN void *pv, OUT DWORD *pdwSize)
  1277. {
  1278. Serializer *pSer = (Serializer*) pv;
  1279. if (!IsInproc(pSer))
  1280. {
  1281. handle_t handle;
  1282. HRESULT hr = pSer->GetSizingHandle((void*) &handle);
  1283. if (FAILED(hr))
  1284. return hr;
  1285. *pdwSize = SpecialPropertiesData_AlignSize(handle, &_data);
  1286. MesHandleFree(handle);
  1287. }
  1288. else
  1289. *pdwSize = 0;
  1290. return S_OK;
  1291. }
  1292. STDMETHODIMP SpecialProperties::GetCLSID(OUT CLSID *pclsid)
  1293. {
  1294. *pclsid = IID_ISpecialSystemProperties;
  1295. return S_OK;
  1296. }