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.

620 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: propstg.hxx
  7. //
  8. // Contents: Class that directly implements IPropertyStorage
  9. //
  10. // Classes: CCoTaskAllocator
  11. // CPropertyStorage
  12. // CEnumSTATPROPSTG
  13. //
  14. // Functions:
  15. //
  16. // Notes:
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "../h/ref.hxx"
  20. #include "h/stgprops.hxx"
  21. //+-------------------------------------------------------------------------
  22. //
  23. // Class: CCoTaskAllocator
  24. //
  25. // Purpose: Class used by RtlQueryProperties to allocate memory.
  26. //
  27. //--------------------------------------------------------------------------
  28. class CCoTaskAllocator : public PMemoryAllocator
  29. {
  30. public:
  31. virtual void *Allocate(ULONG cbSize);
  32. virtual void Free(void *pv);
  33. };
  34. //+-------------------------------------------------------------------------
  35. //
  36. // Class: CPropertyStorage
  37. //
  38. // Purpose: Implements IPropertyStorage for docfile and native file systems.
  39. //
  40. // Notes: This class uses the functionality provided by
  41. // RtlCreatePropertySet, RtlSetProperties, RtlQueryProperties etc
  42. // to manipulate the property set stream.
  43. //
  44. // The constructors (one for create, one for open) create
  45. // an NTPROP (expected by RtlSetProperties etc) with the
  46. // correct type of NTMAPPEDSTREAM (CExposedStream::CPubMappedStream
  47. // to handle making a docfile stream look like a real memory mapped
  48. // stream, and CNtMappedStream, created by RtlCreateMappedStream,
  49. // for native file systems.)
  50. //
  51. //--------------------------------------------------------------------------
  52. #define PROPERTYSTORAGE_SIG LONGSIG('P','R','P','S')
  53. #define PROPERTYSTORAGE_SIGDEL LONGSIG('P','R','P','s')
  54. #define PROPERTYSTORAGE_SIGZOMBIE LONGSIG('P','R','P','z')
  55. #define ENUMSTATPROPSTG_SIG LONGSIG('E','P','S','S')
  56. #define ENUMSTATPROPSTG_SIGDEL LONGSIG('E','P','S','s')
  57. class CPropertyStorage : public IPropertyStorage
  58. {
  59. public:
  60. CPropertyStorage( // create ctor
  61. IPrivateStorage * pprivstg,
  62. REFFMTID rfmtid,
  63. const CLSID * pclsid,
  64. DWORD grfFlags,
  65. DWORD grfMode,
  66. HRESULT * phr);
  67. CPropertyStorage( // open ctor
  68. IPrivateStorage * pprivstg,
  69. REFFMTID rfmtid,
  70. DWORD grfMode,
  71. BOOL fDelete,
  72. HRESULT * phr);
  73. ~CPropertyStorage();
  74. // IUnknown
  75. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
  76. STDMETHOD_(ULONG, AddRef)(void);
  77. STDMETHOD_(ULONG, Release)(void);
  78. // IPropertyStorage
  79. STDMETHOD(ReadMultiple)(
  80. ULONG cpspec,
  81. const PROPSPEC rgpspec[],
  82. PROPVARIANT rgpropvar[]);
  83. STDMETHOD(WriteMultiple)(
  84. ULONG cpspec,
  85. const PROPSPEC rgpspec[],
  86. const PROPVARIANT rgpropvar[],
  87. PROPID propidNameFirst);
  88. STDMETHOD(DeleteMultiple)(
  89. ULONG cpspec,
  90. const PROPSPEC rgpspec[]);
  91. STDMETHOD(ReadPropertyNames)(
  92. ULONG cpropid,
  93. const PROPID rgpropid[],
  94. LPOLESTR rglpwstrName[]);
  95. STDMETHOD(WritePropertyNames)(
  96. ULONG cpropid,
  97. const PROPID rgpropid[],
  98. const LPOLESTR rglpwstrName[]);
  99. STDMETHOD(DeletePropertyNames)(
  100. ULONG cpropid,
  101. const PROPID rgpropid[]);
  102. STDMETHOD(Commit)(DWORD grfCommitFlags);
  103. STDMETHOD(Revert)();
  104. STDMETHOD(Enum)(IEnumSTATPROPSTG ** ppenum);
  105. STDMETHOD(SetTimes)(
  106. FILETIME const * pctime,
  107. FILETIME const * patime,
  108. FILETIME const * pmtime);
  109. STDMETHOD(SetClass)(REFCLSID clsid);
  110. STDMETHOD(Stat)(STATPROPSETSTG * pstatpsstg);
  111. // used by implementation helper classes
  112. inline NTPROP GetNtPropSetHandle(void) { return _np; }
  113. private:
  114. VOID Initialize();
  115. HRESULT InitializePropertyStream(
  116. USHORT Flags,
  117. const GUID * pguid,
  118. GUID const * pclsid);
  119. HRESULT _WriteMultiple(
  120. ULONG cpspec,
  121. const PROPSPEC rgpspec[],
  122. const PROPVARIANT rgpropvar[],
  123. PROPID propidNameFirst);
  124. HRESULT _WritePropertyNames(
  125. ULONG cpropid,
  126. const PROPID rgpropid[],
  127. const LPOLESTR rglpwstrName[]);
  128. HRESULT HandleLowMemory();
  129. HRESULT _CreateDocumentSummary2Stream(
  130. IStorage * pstg,
  131. CPropSetName & psn,
  132. DWORD grfMode,
  133. BOOL * fCreated);
  134. inline HRESULT Validate();
  135. inline HRESULT ValidateRef();
  136. inline HRESULT ValidateRGPROPSPEC( ULONG cpspec, const PROPSPEC rgpropspec[] );
  137. inline HRESULT ValidateInRGPROPVARIANT( ULONG cpspec, const PROPVARIANT rgpropvar[] );
  138. inline HRESULT ValidateOutRGPROPVARIANT( ULONG cpspec, PROPVARIANT rgpropvar[] );
  139. inline HRESULT ValidateRGPROPID( ULONG cpropid, const PROPID rgpropid[] );
  140. inline HRESULT ValidateInRGLPOLESTR( ULONG cpropid, const LPOLESTR rglpwstrName[] );
  141. inline HRESULT ValidateOutRGLPOLESTR( ULONG cpropid, LPOLESTR rglpwstrName[] );
  142. inline BOOL IsSimple();
  143. inline HRESULT IsWriteable();
  144. inline HRESULT IsReadable();
  145. inline DWORD GetCreationMode();
  146. inline HRESULT IsReverted();
  147. private:
  148. ULONG _ulSig;
  149. LONG _cRefs;
  150. IStorage * _pstgPropSet;
  151. IStream * _pstmPropSet;
  152. NTPROP _np;
  153. NTMAPPEDSTREAM _ms;
  154. // We need to remember if the property set is the second section
  155. // of the DocumentSummaryInformation property set used by Office. This
  156. // is the only case where we support a multiple-section property set, and
  157. // requires special handling in ::Revert().
  158. BOOL _fUserDefinedProperties;
  159. USHORT _usCodePage; // Ansi Codepage or Mac Script
  160. // (disambiguate with _dwOSVersion)
  161. ULONG _dwOSVersion; // Shows the OS Kind, major/minor version
  162. DWORD _grfFlags; // PROPSETFLAG_NONSIMPLE and PROPSETFLAG_ANSI
  163. DWORD _grfAccess; // grfMode & 3
  164. DWORD _grfShare; // grfMode & 0xF0
  165. };
  166. //+-------------------------------------------------------------------
  167. //
  168. // Member: CPropertyStorage::Validate
  169. //
  170. // Synopsis: S_OK if signature valid and not zombie.
  171. //
  172. // Notes: If the Revert calls fails due to low memory, then
  173. // the object becomes a zombie.
  174. //
  175. //--------------------------------------------------------------------
  176. inline HRESULT CPropertyStorage::Validate()
  177. {
  178. if (_ulSig == PROPERTYSTORAGE_SIG)
  179. return S_OK;
  180. else
  181. if (_ulSig == PROPERTYSTORAGE_SIGZOMBIE)
  182. return STG_E_INSUFFICIENTMEMORY;
  183. else
  184. return STG_E_INVALIDHANDLE;
  185. }
  186. //+-------------------------------------------------------------------
  187. //
  188. // Member: CPropertyStorage::ValidateRef
  189. //
  190. // Synopsis: S_OK if signature valid.
  191. //
  192. //--------------------------------------------------------------------
  193. inline HRESULT CPropertyStorage::ValidateRef()
  194. {
  195. if (_ulSig == PROPERTYSTORAGE_SIG || _ulSig == PROPERTYSTORAGE_SIGZOMBIE)
  196. return(S_OK);
  197. else
  198. return(STG_E_INVALIDHANDLE);
  199. }
  200. //+-------------------------------------------------------------------
  201. //
  202. // Member: CPropertyStorage::ValidateRGPROPSPEC
  203. //
  204. // Synopsis: S_OK if PROPSPEC[] is valid
  205. // E_INVALIDARG otherwise.
  206. //
  207. //--------------------------------------------------------------------
  208. inline HRESULT CPropertyStorage::ValidateRGPROPSPEC( ULONG cpspec,
  209. const PROPSPEC rgpropspec[] )
  210. {
  211. HRESULT hr = E_INVALIDARG;
  212. // Validate the array itself.
  213. VDATESIZEREADPTRIN_LABEL(rgpropspec, cpspec * sizeof(PROPSPEC), errRet, hr);
  214. // Validate the elements of the array.
  215. for( ; cpspec > 0; cpspec-- )
  216. {
  217. // Is this an LPWSTR?
  218. if( PRSPEC_LPWSTR == rgpropspec[cpspec-1].ulKind )
  219. {
  220. // We better at least be able to read the first
  221. // character.
  222. VDATEREADPTRIN_LABEL(rgpropspec[cpspec-1].lpwstr, WCHAR, errRet, hr);
  223. }
  224. // Otherwise, this better be a PROPID.
  225. else if( PRSPEC_PROPID != rgpropspec[cpspec-1].ulKind )
  226. {
  227. goto errRet;
  228. }
  229. }
  230. hr = S_OK;
  231. // ----
  232. // Exit
  233. // ----
  234. errRet:
  235. return( hr );
  236. }
  237. //+-------------------------------------------------------------------
  238. //
  239. // Member: CPropertyStorage::ValidateInRGPROPVARIANT
  240. //
  241. // Synopsis: S_OK if PROPVARIANT[] is valid for Read.
  242. // E_INVALIDARG otherwise.
  243. //
  244. //--------------------------------------------------------------------
  245. inline HRESULT CPropertyStorage::ValidateInRGPROPVARIANT(
  246. ULONG cpspec,
  247. const PROPVARIANT rgpropvar[] )
  248. {
  249. UNREFERENCED_PARM(cpspec);
  250. // We verify that we can read the whole PropVariant[], but
  251. // we don't validate the content of those elements.
  252. HRESULT hr;
  253. VDATESIZEREADPTRIN_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), errRet, hr);
  254. hr = S_OK;
  255. errRet:
  256. return( hr );
  257. }
  258. //+-------------------------------------------------------------------
  259. //
  260. // Member: CPropertyStorage::ValidateOutRGPROPVARIANT
  261. //
  262. // Synopsis: S_OK if PROPVARIANT[] is valid for Write.
  263. // E_INVALIDARG otherwise.
  264. //
  265. //--------------------------------------------------------------------
  266. inline HRESULT CPropertyStorage::ValidateOutRGPROPVARIANT( ULONG cpspec,
  267. PROPVARIANT rgpropvar[] )
  268. {
  269. UNREFERENCED_PARM(cpspec);
  270. // We verify that we can write the whole PropVariant[], but
  271. // we don't validate the content of those elements.
  272. HRESULT hr;
  273. VDATESIZEPTROUT_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), errRet, hr);
  274. hr = S_OK;
  275. errRet:
  276. return( hr );
  277. }
  278. //+-------------------------------------------------------------------
  279. //
  280. // Member: CPropertyStorage::ValidateRGPROPID
  281. //
  282. // Synopsis: S_OK if RGPROPID[] is valid for Read.
  283. // E_INVALIDARG otherwise.
  284. //
  285. //--------------------------------------------------------------------
  286. inline HRESULT CPropertyStorage::ValidateRGPROPID( ULONG cpropid,
  287. const PROPID rgpropid[] )
  288. {
  289. HRESULT hr;
  290. UNREFERENCED_PARM(cpropid);
  291. VDATESIZEREADPTRIN_LABEL( rgpropid, cpropid * sizeof(PROPID), errRet, hr );
  292. hr = S_OK;
  293. errRet:
  294. return( hr );
  295. }
  296. //+-------------------------------------------------------------------
  297. //
  298. // Member: CPropertyStorage::ValidateOutRGLPOLESTR.
  299. //
  300. // Synopsis: S_OK if LPOLESTR[] is valid for Write.
  301. // E_INVALIDARG otherwise.
  302. //
  303. //--------------------------------------------------------------------
  304. inline HRESULT CPropertyStorage::ValidateOutRGLPOLESTR( ULONG cpropid,
  305. LPOLESTR rglpwstrName[] )
  306. {
  307. UNREFERENCED_PARM(cpropid);
  308. HRESULT hr;
  309. VDATESIZEPTROUT_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), errRet, hr );
  310. hr = S_OK;
  311. errRet:
  312. return( hr );
  313. }
  314. //+-------------------------------------------------------------------
  315. //
  316. // Member: CPropertyStorage::ValidateInRGLPOLESTR
  317. //
  318. // Synopsis: S_OK if LPOLESTR[] is valid for Read.
  319. // E_INVALIDARG otherwise.
  320. //
  321. //--------------------------------------------------------------------
  322. inline HRESULT CPropertyStorage::ValidateInRGLPOLESTR( ULONG cpropid,
  323. const LPOLESTR rglpwstrName[] )
  324. {
  325. // Validate that we can read the entire vector.
  326. HRESULT hr;
  327. VDATESIZEREADPTRIN_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), errRet, hr );
  328. // Validate that we can at least read the first character of
  329. // each of the strings.
  330. for( ; cpropid > 0; cpropid-- )
  331. {
  332. VDATEREADPTRIN_LABEL( rglpwstrName[cpropid-1], WCHAR, errRet, hr );
  333. }
  334. hr = S_OK;
  335. errRet:
  336. return( hr );
  337. }
  338. //+-------------------------------------------------------------------
  339. //
  340. // Member: CPropertyStorage::IsSimple
  341. //
  342. // Synopsis: true if simple
  343. //
  344. //--------------------------------------------------------------------
  345. inline BOOL CPropertyStorage::IsSimple()
  346. {
  347. PROPASSERT((_grfFlags & PROPSETFLAG_NONSIMPLE) == 0);
  348. return TRUE; // always simple fo reference implementation
  349. }
  350. //+-------------------------------------------------------------------
  351. //
  352. // Member: CPropertyStorage::IsWriteable
  353. //
  354. // Synopsis: S_OK if writeable otherwise STG_E_ACCESSDENIED
  355. //
  356. //--------------------------------------------------------------------
  357. inline HRESULT CPropertyStorage::IsWriteable()
  358. {
  359. return (_grfAccess == STGM_WRITE || _grfAccess == STGM_READWRITE) ?
  360. S_OK : STG_E_ACCESSDENIED;
  361. }
  362. //+-------------------------------------------------------------------
  363. //
  364. // Member: CPropertyStorage::IsReadable
  365. //
  366. // Synopsis: S_OK if readable otherwise STG_E_ACCESSDENIED
  367. //
  368. //--------------------------------------------------------------------
  369. inline HRESULT CPropertyStorage::IsReadable()
  370. {
  371. return (_grfAccess == STGM_READ || _grfAccess == STGM_READWRITE) ?
  372. S_OK : STG_E_ACCESSDENIED;
  373. }
  374. //+-------------------------------------------------------------------
  375. //
  376. // Member: CPropertyStorage::IsReverted
  377. //
  378. // Synopsis: S_OK if not reverted, STG_E_REVERTED otherwise.
  379. //
  380. //--------------------------------------------------------------------
  381. inline HRESULT CPropertyStorage::IsReverted()
  382. {
  383. // note that although there is no transacted mode in ref,
  384. // it could still be possible that the parent has been deleted
  385. // and cause STG_E_REVERTED to be returned.
  386. IUnknown *punk;
  387. HRESULT hr = ((IUnknown*)_pstmPropSet) ->
  388. QueryInterface(IID_IUnknown, (void**)&punk);
  389. if (hr == S_OK)
  390. {
  391. punk->Release();
  392. }
  393. return(hr);
  394. }
  395. //+-------------------------------------------------------------------------
  396. //
  397. // Class: CStatArray
  398. //
  399. // Purpose: Class to allow sharing of enumeration STATPROPSTG state.
  400. //
  401. // Interface: CStatArray -- Enumerate entire NTPROP np.
  402. // NextAt -- Perform an OLE-type Next operation starting at
  403. // specified offset.
  404. // AddRef -- for sharing of this by CEnumSTATPROPSTG
  405. // Release -- ditto
  406. //
  407. // Notes: Each IEnumSTATPROPSTG instance has a reference to a
  408. // CStatArray. When IEnumSTATPROPSTG::Clone is called, a
  409. // new reference to the extant CStatArray is used: no copying.
  410. //
  411. // The CEnumSTATPROPSTG has a cursor into the CStatArray.
  412. //
  413. //--------------------------------------------------------------------------
  414. class CStatArray
  415. {
  416. public:
  417. CStatArray(NTPROP np, HRESULT *phr);
  418. NTSTATUS NextAt(ULONG ipropNext, STATPROPSTG *pspsDest, ULONG *pceltFetched);
  419. inline VOID AddRef();
  420. inline VOID Release();
  421. ~CStatArray();
  422. private:
  423. LONG _cRefs;
  424. STATPROPSTG * _psps;
  425. ULONG _cpropActual;
  426. };
  427. //+-------------------------------------------------------------------
  428. //
  429. // Member: CStatArray::AddRef
  430. //
  431. // Synopsis: Increment ref count.
  432. //
  433. //--------------------------------------------------------------------
  434. inline VOID CStatArray::AddRef()
  435. {
  436. InterlockedIncrement(&_cRefs);
  437. }
  438. //+-------------------------------------------------------------------
  439. //
  440. // Member: CStatArray::AddRef
  441. //
  442. // Synopsis: Decrement ref count and delete object if refs == 0.
  443. //
  444. //--------------------------------------------------------------------
  445. inline VOID CStatArray::Release()
  446. {
  447. if (0 == InterlockedDecrement(&_cRefs))
  448. delete this;
  449. }
  450. //+-------------------------------------------------------------------------
  451. //
  452. // Class: CEnumSTATPROPSTG
  453. //
  454. // Purpose: Implement IEnumSTATPROPSTG
  455. //
  456. // Notes: Just holds a reference to a CStatArray that contains
  457. // a static copy of the enumeration when the original
  458. // Enum call was made. This object contains the cursor
  459. // into the CStatArray.
  460. //
  461. //--------------------------------------------------------------------------
  462. NTSTATUS CopySTATPROPSTG(ULONG celt,
  463. STATPROPSTG * pspsDest,
  464. const STATPROPSTG * pspsSrc);
  465. VOID CleanupSTATPROPSTG(ULONG celt, STATPROPSTG * psps);
  466. class CEnumSTATPROPSTG : public IEnumSTATPROPSTG
  467. {
  468. public:
  469. CEnumSTATPROPSTG(NTPROP np, HRESULT *phr);
  470. CEnumSTATPROPSTG(const CEnumSTATPROPSTG &other, HRESULT *phr);
  471. ~CEnumSTATPROPSTG();
  472. STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
  473. STDMETHOD_(ULONG, AddRef)(void);
  474. STDMETHOD_(ULONG, Release)(void);
  475. STDMETHOD(Next)(ULONG celt,
  476. STATPROPSTG * rgelt,
  477. ULONG * pceltFetched);
  478. // We don't need RemoteNext.
  479. STDMETHOD(Skip)(ULONG celt);
  480. STDMETHOD(Reset)();
  481. STDMETHOD(Clone)(IEnumSTATPROPSTG ** ppenum);
  482. private:
  483. HRESULT Validate();
  484. ULONG _ulSig;
  485. LONG _cRefs;
  486. CStatArray * _psa;
  487. ULONG _ipropNext;
  488. };
  489. //+-------------------------------------------------------------------
  490. //
  491. // Member: CEnumSTATPROPSTG::Validate
  492. //
  493. // Synopsis: S_OK if signature is valid, otherwise error
  494. //
  495. //--------------------------------------------------------------------
  496. inline HRESULT CEnumSTATPROPSTG::Validate()
  497. {
  498. return _ulSig == ENUMSTATPROPSTG_SIG ? S_OK : STG_E_INVALIDHANDLE;
  499. }