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.

531 lines
14 KiB

  1. /*
  2. * _ F S M E T A . H
  3. *
  4. * File system metadata routines
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #ifndef __FSMETA_H_
  9. #define __FSMETA_H_
  10. // STL helpers ---------------------------------------------------------------
  11. //
  12. // Use pragmas to disable the specific level 4 warnings
  13. // that appear when we use the STL. One would hope our version of the
  14. // STL compiles clean at level 4, but alas it doesn't....
  15. #pragma warning(disable:4663) // C language, template<> syntax
  16. #pragma warning(disable:4244) // return conversion, data loss
  17. // Turn this warning off for good.
  18. #pragma warning(disable:4786) // symbol truncated in debug info
  19. // Put STL includes here
  20. #include <list>
  21. // Turn warnings back on
  22. #pragma warning(default:4663) // C language, template<> syntax
  23. #pragma warning(default:4244) // return conversion, data loss
  24. // OLE and NT5 properties ----------------------------------------------------
  25. //
  26. #define OLEDBVER 0x200
  27. #include <ole2.h>
  28. #include <stgint.h>
  29. #include <pbagex.h>
  30. typedef HRESULT (__stdcall * STGOPENSTORAGEONHANDLE)(
  31. IN HANDLE hStream,
  32. IN DWORD grfMode,
  33. IN void *reserved1,
  34. IN void *reserved2,
  35. IN REFIID riid,
  36. OUT void **ppObjectOpen );
  37. typedef HRESULT (__stdcall * STGCREATESTORAGEONHANDLE)(
  38. IN HANDLE hStream,
  39. IN DWORD grfMode,
  40. IN DWORD stgfmt,
  41. IN void *reserved1,
  42. IN void *reserved2,
  43. IN REFIID riid,
  44. OUT void **ppObjectOpen );
  45. extern STGOPENSTORAGEONHANDLE g_pfnStgOpenStorageOnHandle;
  46. // reserved properties ------------------------------------------------------
  47. //
  48. // There are two conditions that make a property reserved.
  49. //
  50. // The first and foremost is that the property is not something that is stored
  51. // in the resource's property container, but instead is calculated from file
  52. // system information or DAV specific conditions (lock info, etc.)
  53. //
  54. // The second is that the property is not something that can be set via
  55. // PROPPATCH calls. This distinction is needed when asking if a property is
  56. // reserved.
  57. //
  58. enum {
  59. // The properties in this section are all properties that are calculated
  60. // from the filesystem or DAV specific information.
  61. //
  62. iana_rp_content_length,
  63. iana_rp_creation_date,
  64. iana_rp_displayname,
  65. iana_rp_etag,
  66. iana_rp_last_modified,
  67. iana_rp_resourcetype,
  68. iana_rp_lockdiscovery,
  69. iana_rp_supportedlock,
  70. iana_rp_ishidden,
  71. iana_rp_iscollection,
  72. sc_crp_get_reserved,
  73. // The properties in this section are actually stored in the property
  74. // container (via PUT) but are reserved for the purpose of PUT.
  75. //
  76. // IMPORTANT! "DAV:getcontenttype" must be the first non-get reserved
  77. // property!
  78. //
  79. iana_rp_content_type = sc_crp_get_reserved,
  80. iana_rp_content_encoding,
  81. iana_rp_content_language,
  82. // To be consistent with DAVEX, make the following property reserved
  83. //
  84. iana_rp_searchrequest,
  85. sc_crp_set_reserved
  86. };
  87. typedef struct RP { DWORD dwCRC; LPCWSTR pwsz; } RP;
  88. #define IanaItemCrc(_sz,_crc) { _crc, L"DAV:" L#_sz }
  89. DEC_CONST RP sc_rp[sc_crp_set_reserved] = {
  90. IanaItemCrc(getcontentlength, 0x25412A26),
  91. IanaItemCrc(creationdate, 0xA8A9F240),
  92. IanaItemCrc(displayname, 0xA399DB8D),
  93. IanaItemCrc(getetag, 0x5E54D3B8),
  94. IanaItemCrc(getlastmodified, 0x45D75CD4),
  95. IanaItemCrc(resourcetype, 0x8155BECE),
  96. IanaItemCrc(lockdiscovery, 0xC7ED2F96),
  97. IanaItemCrc(supportedlock, 0x39B9A692),
  98. IanaItemCrc(ishidden, 0xE31B1632),
  99. IanaItemCrc(iscollection, 0xD3E3FF13),
  100. IanaItemCrc(getcontenttype, 0xC28B9FED),
  101. IanaItemCrc(getcontentencoding, 0x4B7C7220),
  102. IanaItemCrc(getcontentlanguage, 0x5E9717C2),
  103. IanaItemCrc(searchrequest, 0x5AC72D67),
  104. };
  105. // DAV Metadata --------------------------------------------------------------
  106. //
  107. #include <xmeta.h>
  108. // The FS impl of DAV uses the NT5 property interfaces and IPropertyBag
  109. // as its underlying property storage implementation. This mechanism uses
  110. // strings and/or PROPVARIANTS to refer to properties and their values.
  111. //
  112. // Therefore the PROPFIND and PROPPATCH contexts are written with this in
  113. // mind.
  114. //
  115. // CFSFind/CFSPatch ----------------------------------------------------------
  116. //
  117. class CFSProp;
  118. class CFSFind : public CFindContext, public IPreloadNamespaces
  119. {
  120. ChainedStringBuffer<WCHAR> m_csb;
  121. ULONG m_cProps;
  122. ULONG m_cMaxProps;
  123. auto_heap_ptr<LPCWSTR> m_rgwszProps;
  124. LONG m_ip_getcontenttype;
  125. // non-implemented operators
  126. //
  127. CFSFind( const CFSFind& );
  128. CFSFind& operator=( const CFSFind& );
  129. public:
  130. virtual ~CFSFind() {}
  131. CFSFind()
  132. : m_cProps(0),
  133. m_cMaxProps(0),
  134. m_ip_getcontenttype(-1)
  135. {
  136. }
  137. // When the parser finds an item that the client wants returned,
  138. // the item is added to the context via the following set context
  139. // methods. Each add is qualified by the resource on which the
  140. // request is made. fExcludeProp is used for full-fidelity special
  141. // cases in the Exchange implementation only.
  142. //
  143. virtual SCODE ScAddProp(LPCWSTR pwszPath, LPCWSTR pwszProp, BOOL fExcludeProp);
  144. // The ScFind() method is used to invoke the context onto a given
  145. // resources property object.
  146. //
  147. SCODE ScFind (CXMLEmitter& msr, IMethUtil * pmu, CFSProp& fpt);
  148. // Add an error to the response that is based on the context.
  149. //
  150. SCODE ScErrorAllProps (CXMLEmitter& msr,
  151. IMethUtil * pmu,
  152. LPCWSTR pwszPath,
  153. BOOL fCollection,
  154. CVRoot* pcvrTranslation,
  155. SCODE scErr)
  156. {
  157. // Add an item to the msr that says this entire
  158. // file was not accessible
  159. //
  160. return ScAddMulti (msr,
  161. pmu,
  162. pwszPath,
  163. NULL,
  164. HscFromHresult(scErr),
  165. fCollection,
  166. pcvrTranslation);
  167. }
  168. // IPreloadNamespaces
  169. //
  170. SCODE ScLoadNamespaces(CXMLEmitter * pmsr);
  171. };
  172. class CFSPatch : public CPatchContext, public IPreloadNamespaces
  173. {
  174. class CFSPropContext : public CPropContext
  175. {
  176. PROPVARIANT* m_pvar;
  177. BOOL m_fHasValue;
  178. // non-implemented operators
  179. //
  180. CFSPropContext( const CFSPropContext& );
  181. CFSPropContext& operator=( const CFSPropContext& );
  182. public:
  183. CFSPropContext(PROPVARIANT* pvar)
  184. : m_pvar(pvar),
  185. m_fHasValue(FALSE)
  186. {
  187. Assert (pvar != NULL);
  188. }
  189. virtual ~CFSPropContext() {}
  190. virtual SCODE ScSetType(LPCWSTR pwszType)
  191. {
  192. return ScVariantTypeFromString (pwszType, m_pvar->vt);
  193. }
  194. virtual SCODE ScSetValue(LPCWSTR pwszValue, UINT cmvValues)
  195. {
  196. // At this time, HTTPEXT does not support multivalued
  197. // properties.
  198. //
  199. Assert (0 == cmvValues);
  200. // If no type was specified, we default to a string
  201. //
  202. m_fHasValue = TRUE;
  203. if (m_pvar->vt == VT_EMPTY)
  204. m_pvar->vt = VT_LPWSTR;
  205. return ScVariantValueFromString (*m_pvar, pwszValue);
  206. }
  207. virtual SCODE ScComplete(BOOL fEmpty)
  208. {
  209. Assert (m_fHasValue);
  210. return m_fHasValue ? S_OK : E_DAV_XML_PARSE_ERROR;
  211. }
  212. // At this time, HTTPEXT does not support multivalued
  213. // properties.
  214. //
  215. virtual BOOL FMultiValued() { return FALSE; }
  216. };
  217. // PATCH_SET items
  218. //
  219. ChainedStringBuffer<WCHAR> m_csb;
  220. ULONG m_cSetProps;
  221. ULONG m_cMaxSetProps;
  222. auto_heap_ptr<LPCWSTR> m_rgwszSetProps;
  223. auto_heap_ptr<PROPVARIANT> m_rgvSetProps;
  224. // Failed Propserties including reserverd properties
  225. //
  226. CStatusCache m_csn;
  227. // PATCH_DELETE items
  228. //
  229. ULONG m_cDeleteProps;
  230. ULONG m_cMaxDeleteProps;
  231. auto_heap_ptr<LPCWSTR> m_rgwszDeleteProps;
  232. // non-implemented operators
  233. //
  234. CFSPatch( const CFSPatch& );
  235. CFSPatch& operator=( const CFSPatch& );
  236. public:
  237. virtual ~CFSPatch();
  238. CFSPatch()
  239. : m_cSetProps(0),
  240. m_cMaxSetProps(0),
  241. m_cDeleteProps(0),
  242. m_cMaxDeleteProps(0)
  243. {
  244. }
  245. SCODE ScInit() { return m_csn.ScInit(); }
  246. // When the parser finds an item that the client wants operated on,
  247. // the item is added to the context via the following set context
  248. // methods. Each request is qualified by the resource on which the
  249. // request is made.
  250. //
  251. virtual SCODE ScDeleteProp(LPCWSTR pwszPath,
  252. LPCWSTR pwszProp);
  253. virtual SCODE ScSetProp(LPCWSTR pwszPath,
  254. LPCWSTR pwszProp,
  255. auto_ref_ptr<CPropContext>& pPropCtx);
  256. // The ScPatch() method is used to invoke the context onto a given
  257. // resources property object.
  258. //
  259. SCODE ScPatch (CXMLEmitter& msr, IMethUtil * pmu, CFSProp& fpt);
  260. // IPreloadNamespaces
  261. //
  262. SCODE ScLoadNamespaces(CXMLEmitter * pmsr);
  263. };
  264. // CFSProp -------------------------------------------------------------------
  265. //
  266. #include "_voltype.h"
  267. class CFSProp
  268. {
  269. IMethUtil* m_pmu;
  270. LPCWSTR m_pwszURI;
  271. LPCWSTR m_pwszPath;
  272. CVRoot* m_pcvrTranslation;
  273. CResourceInfo& m_cri;
  274. auto_com_ptr<IPropertyBagEx>& m_pbag;
  275. BOOL FInvalidPbag() const { return (m_pbag.get() == NULL); }
  276. // Volume type of the drive on which m_pwszPath resides
  277. //
  278. mutable VOLTYPE m_voltype;
  279. BOOL FIsVolumeNTFS() const
  280. {
  281. // If we don't already know it, figure out the volume type
  282. // for the volume on which our path resides.
  283. //
  284. if (VOLTYPE_UNKNOWN == m_voltype)
  285. m_voltype = VolumeType(m_pwszPath, m_pmu->HitUser());
  286. // Return whether that volume is NTFS.
  287. //
  288. Assert(m_voltype != VOLTYPE_UNKNOWN);
  289. return VOLTYPE_NTFS == m_voltype;
  290. }
  291. // non-implemented operators
  292. //
  293. CFSProp( const CFSProp& );
  294. CFSProp& operator=( const CFSProp& );
  295. enum { PROP_CHUNK_SIZE = 16 };
  296. SCODE ScGetPropsInternal (ULONG cProps,
  297. LPCWSTR* rgwszPropNames,
  298. PROPVARIANT* rgvar,
  299. LONG ip_getcontenttype);
  300. public:
  301. CFSProp(IMethUtil* pmu,
  302. auto_com_ptr<IPropertyBagEx>& pbag,
  303. LPCWSTR pwszUri,
  304. LPCWSTR pwszPath,
  305. CVRoot* pcvr,
  306. CResourceInfo& cri)
  307. : m_pmu(pmu),
  308. m_pwszURI(pwszUri),
  309. m_pwszPath(pwszPath),
  310. m_pcvrTranslation(pcvr),
  311. m_cri(cri),
  312. m_pbag(pbag),
  313. m_voltype(VOLTYPE_UNKNOWN)
  314. {
  315. }
  316. LPCWSTR PwszPath() const { return m_pwszPath; }
  317. CVRoot* PcvrTranslation() const { return m_pcvrTranslation; }
  318. BOOL FCollection() const
  319. {
  320. if (m_cri.FLoaded())
  321. return m_cri.FCollection();
  322. else
  323. return FALSE;
  324. }
  325. // Reserved Properties
  326. //
  327. typedef enum { RESERVED_GET, RESERVED_SET } RESERVED_TYPE;
  328. static BOOL FReservedProperty (LPCWSTR pwszProp, RESERVED_TYPE rt, UINT* prp);
  329. SCODE ScGetReservedProp (CXMLEmitter& xml,
  330. CEmitterNode& en,
  331. UINT irp,
  332. BOOL fValues = TRUE);
  333. // PROPFIND context access
  334. //
  335. SCODE ScGetAllProps (CXMLEmitter&, CEmitterNode&, BOOL fValues);
  336. SCODE ScGetSpecificProps (CXMLEmitter&,
  337. CEmitterNode&,
  338. ULONG cProps,
  339. LPCWSTR* rgwszProps,
  340. LONG ip_gcontenttype);
  341. // PROPPATCH context access
  342. //
  343. SCODE ScSetProps (CStatusCache & csn,
  344. ULONG cProps,
  345. LPCWSTR* rgwszProps,
  346. PROPVARIANT* rgvProps);
  347. SCODE ScDeleteProps (CStatusCache & csn,
  348. ULONG cProps,
  349. LPCWSTR* rgwszProps);
  350. SCODE ScPersist();
  351. // Non-context access
  352. //
  353. SCODE ScSetStringProp (LPCWSTR pwszProp, LPCWSTR pwszValue)
  354. {
  355. PROPVARIANT var = {0};
  356. SCODE sc = S_OK;
  357. var.vt = VT_LPWSTR;
  358. var.pwszVal = const_cast<LPWSTR>(pwszValue);
  359. Assert (!FInvalidPbag());
  360. sc = m_pbag->WriteMultiple (1, &pwszProp, &var);
  361. if (FAILED(sc))
  362. {
  363. // This is the common path for when we are trying to access
  364. // something over an SMB, but the host cannot support the
  365. // request (it is not an NT5 NTFS machine).
  366. //
  367. if ((sc == STG_E_INVALIDNAME) || !FIsVolumeNTFS())
  368. sc = E_DAV_SMB_PROPERTY_ERROR;
  369. }
  370. return sc;
  371. }
  372. };
  373. // Support functions ---------------------------------------------------------
  374. //
  375. SCODE ScFindFileProps (IMethUtil* pmu,
  376. CFSFind& cfc,
  377. CXMLEmitter& msr,
  378. LPCWSTR pwszUri,
  379. LPCWSTR pwszPath,
  380. CVRoot* pcvrTranslation,
  381. CResourceInfo& cri,
  382. BOOL fEmbedErrorsInResponse);
  383. SCODE ScFindFilePropsDeep (IMethUtil* pmu,
  384. CFSFind& cfc,
  385. CXMLEmitter& msr,
  386. LPCWSTR pwszUri,
  387. LPCWSTR pwszPath,
  388. CVRoot* pcvrTranslation,
  389. LONG lDepth);
  390. SCODE ScSetContentProperties (IMethUtil * pmu, LPCWSTR pwszPath,
  391. HANDLE hFile = INVALID_HANDLE_VALUE);
  392. SCODE ScCopyProps (IMethUtil* pmu,
  393. LPCWSTR pwszSrc,
  394. LPCWSTR pwszDst,
  395. BOOL fCollection,
  396. HANDLE hSource = INVALID_HANDLE_VALUE,
  397. HANDLE hfDest = INVALID_HANDLE_VALUE);
  398. // ScGetPropertyBag ----------------------------------------------------------
  399. //
  400. // Helper function used to get IPropertyBagEx interface
  401. //
  402. SCODE ScGetPropertyBag (LPCWSTR pwszPath,
  403. DWORD dwAccessDesired,
  404. IPropertyBagEx** ppbe,
  405. BOOL fCollection,
  406. HANDLE hLockFile = INVALID_HANDLE_VALUE);
  407. inline BOOL FGetDepth (IMethUtil * pmu, LONG * plDepth)
  408. {
  409. LONG lDepth = pmu->LDepth (DEPTH_INFINITY);
  410. // "Depth" header, if appears, can only be '0', '1' or 'infinity',
  411. // all other values are treated as error
  412. //
  413. switch (lDepth)
  414. {
  415. case DEPTH_ZERO:
  416. case DEPTH_ONE:
  417. case DEPTH_ONE_NOROOT:
  418. case DEPTH_INFINITY:
  419. *plDepth = lDepth;
  420. break;
  421. default:
  422. return FALSE;
  423. }
  424. return TRUE;
  425. }
  426. // safe_statpropbag -------------------------------------------------------------
  427. //
  428. #pragma pack(8)
  429. class safe_statpropbag
  430. {
  431. // IMPORTANT: Do not add any other members to this class
  432. // other than the STATPROP that is to be protected.
  433. //
  434. STATPROPBAG sp;
  435. // non-implemented
  436. //
  437. safe_statpropbag(const safe_statpropbag& b);
  438. safe_statpropbag& operator=(const safe_statpropbag& b);
  439. public:
  440. explicit safe_statpropbag()
  441. {
  442. memset (&sp, 0, sizeof(safe_statpropbag));
  443. }
  444. ~safe_statpropbag()
  445. {
  446. CoTaskMemFree (sp.lpwstrName);
  447. }
  448. // ACCESSORS
  449. //
  450. STATPROPBAG* load() { return &sp; }
  451. STATPROPBAG get() { return sp; }
  452. };
  453. #pragma pack()
  454. #endif // __FSMETA_H_