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.

514 lines
12 KiB

  1. /*
  2. * X E M I T . H
  3. *
  4. * XML emitting
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #ifndef _EX_XEMIT_H_
  9. #define _EX_XEMIT_H_
  10. #include <ex\sz.h>
  11. #include <ex\autoptr.h>
  12. #include <ex\cnvt.h>
  13. #include <ex\nmspc.h>
  14. #include <ex\xmldata.h>
  15. #include <ex\atomcache.h>
  16. typedef UINT XNT;
  17. // Interface IPreloadNamespaces
  18. //
  19. // This is a virtual class which is to be implemented by everyone
  20. // that emits XML.
  21. //
  22. class CXMLEmitter;
  23. class IPreloadNamespaces
  24. {
  25. // NOT IMPLEMENTED
  26. //
  27. IPreloadNamespaces& operator=( const IPreloadNamespaces& );
  28. public:
  29. // CREATORS
  30. //
  31. virtual ~IPreloadNamespaces() = 0 {};
  32. // MANIPULATORS
  33. //
  34. virtual SCODE ScLoadNamespaces(CXMLEmitter* pxe) = 0;
  35. };
  36. // class CXMLEmitter ---------------------------------------------------------
  37. //
  38. class CXNode;
  39. class CEmitterNode;
  40. class CXMLEmitter : public CEmitterNmspcCache
  41. {
  42. private:
  43. // Ref' counting.
  44. //
  45. // !!! Please note that this is NON-THREADSAFE !!!
  46. //
  47. // CXNodes should be operated on a single thread at
  48. // any given time.
  49. //
  50. LONG m_cRef;
  51. public:
  52. void AddRef() { m_cRef++; }
  53. void Release() { if (0 == --m_cRef) delete this; }
  54. private:
  55. // Other important bits
  56. //
  57. // Because CXNode::ScDone (which references IXMLBody * m_pxb) is called in CXNode
  58. // dtor, so we must have m_pxb defined befor m_pxnRoot, so that it will be destroyed
  59. // after CXNode is destroyed
  60. //
  61. auto_ref_ptr<IXMLBody> m_pxb;
  62. auto_ref_ptr<CXNode> m_pxnRoot;
  63. IPreloadNamespaces* m_pNmspcLoader;
  64. NmspcCache m_cacheLocal;
  65. class NmspcEmittingOp : public CNmspcCache::NmspcCache::IOp
  66. {
  67. private:
  68. auto_ref_ptr<CXMLEmitter> m_emitter;
  69. auto_ref_ptr<CXNode> m_pxnParent;
  70. // NOT IMPLEMENTED
  71. //
  72. NmspcEmittingOp( const NmspcEmittingOp& );
  73. NmspcEmittingOp& operator=( const NmspcEmittingOp& );
  74. public:
  75. NmspcEmittingOp (CXMLEmitter * pemitter,
  76. CXNode * pxnParent)
  77. :m_emitter (pemitter),
  78. m_pxnParent (pxnParent)
  79. {
  80. }
  81. BOOL operator()( const CRCWszN&,
  82. const auto_ref_ptr<CNmspc>& nmspc );
  83. };
  84. // non-implemented
  85. //
  86. CXMLEmitter(const CXMLEmitter& p);
  87. CXMLEmitter& operator=(const CXMLEmitter& p);
  88. public:
  89. ~CXMLEmitter()
  90. {
  91. // According to standard C++, There's no garantee on the order of member
  92. // being deleted. so delete explicitly.
  93. //
  94. m_pxnRoot.clear();
  95. m_pxb.clear();
  96. }
  97. CXMLEmitter(IXMLBody * pxb, IPreloadNamespaces * pNmspcLoader = NULL)
  98. : m_cRef(1),
  99. m_pxb(pxb),
  100. m_pNmspcLoader(pNmspcLoader)
  101. {
  102. INIT_TRACE(Xml);
  103. }
  104. CXNode* PxnRoot() { return m_pxnRoot.get(); }
  105. // Find the appropriate namespace for the given name
  106. //
  107. SCODE ScFindNmspc (LPCWSTR, UINT, auto_ref_ptr<CNmspc>&);
  108. // Attach the namespace to a given node
  109. //
  110. inline SCODE ScAddNmspc(const auto_ref_ptr<CNmspc>&, CXNode *);
  111. SCODE ScAddAttribute (
  112. /* [in] */ CXNode * pxn,
  113. /* [in] */ LPCWSTR pwszTag,
  114. /* [in] */ UINT cchTag,
  115. /* [in] */ LPCWSTR pwszValue,
  116. /* [in] */ UINT cchValue);
  117. SCODE ScNewNode (
  118. /* [in] */ XNT xnt,
  119. /* [in] */ LPCWSTR pwszTag,
  120. /* [in] */ CXNode* pxnParent,
  121. /* [out] */ auto_ref_ptr<CXNode>& pxnOut);
  122. // Create a root node for this document
  123. // including prologue.
  124. //
  125. SCODE ScSetRoot (LPCWSTR);
  126. // Create a root node with NO prologue, this node can be
  127. // used to build XML piece.
  128. //
  129. // This function should not be used directly in IIS side. it may
  130. // be used directly in store side to build XML chunks
  131. //
  132. SCODE ScNewRootNode (LPCWSTR);
  133. SCODE ScPreloadNamespace (LPCWSTR pwszTag);
  134. SCODE ScPreloadLocalNamespace (CXNode * pxn, LPCWSTR pwszTag);
  135. VOID DoneWithLocalNamespace ()
  136. {
  137. // Reuse the namespace alises
  138. //
  139. //$ NOTE: we can do this by simply deducting the the number of aliases
  140. //$ NOTE: in the local cache. because all local aliases are added
  141. //$ NOTE: after root level aliases is added. so this way do cleanup
  142. //$ NOTE: only those aliases taken the by the local cache.
  143. //$ NOTE: Note that this is based on the fact that at any time, we
  144. //$ NOTE: we have only one <response> node under contruction
  145. //
  146. AdjustAliasNumber (0 - m_cacheLocal.CItems());
  147. // Cleanup all the entries in the local cache
  148. //
  149. m_cacheLocal.Clear();
  150. }
  151. VOID Done()
  152. {
  153. // Close the root node
  154. //
  155. m_pxnRoot.clear();
  156. // Emit the body part;
  157. //
  158. m_pxb->Done();
  159. }
  160. };
  161. // class CXNode --------------------------------------------------------------
  162. //
  163. class CXNode
  164. {
  165. private:
  166. // Ref' counting.
  167. //
  168. // !!! Please note that this is NON-THREADSAFE !!!
  169. //
  170. // CXNodes should be operated on a single thread at
  171. // any given time.
  172. //
  173. LONG m_cRef;
  174. public:
  175. void AddRef() { m_cRef++; }
  176. void Release() { if (0 == --m_cRef) delete this; }
  177. private:
  178. // Node type
  179. //
  180. const XNT m_xnt;
  181. // The body part manager
  182. //
  183. IXMLBody * m_pxb;
  184. // The namespace that applies to this node
  185. //
  186. auto_ref_ptr<CNmspc> m_pns;
  187. // The escaped property tag of the node.
  188. //
  189. auto_heap_ptr<WCHAR> m_pwszTagEscaped;
  190. UINT m_cchTagEscaped;
  191. // Whether or not the propertyname has an empty namespace (no namespace).
  192. //
  193. BOOL m_fHasEmptyNamespace;
  194. // If an open node. i.e. <tag>, not <tag/>, Used for element node only
  195. //
  196. UINT m_fNodeOpen;
  197. // Whether this node is done emitting
  198. //
  199. BOOL m_fDone;
  200. // The CXMLEmitter from which we persist the pilot namespace
  201. //
  202. CXMLEmitter * m_pmsr;
  203. // Emitting --------------------------------------------------------------
  204. //
  205. SCODE ScAddUnicodeResponseBytes (UINT cch, LPCWSTR pwsz);
  206. SCODE ScAddEscapedValueBytes (UINT cch, LPCSTR psz);
  207. SCODE ScAddEscapedAttributeBytes (UINT cch, LPCSTR psz);
  208. SCODE ScWriteTagName ();
  209. // non-implemented
  210. //
  211. CXNode(const CXNode& p);
  212. CXNode& operator=(const CXNode& p);
  213. public:
  214. CXNode(XNT xnt, IXMLBody* pxb) :
  215. m_cRef(1),
  216. m_fDone(FALSE),
  217. m_pmsr(NULL),
  218. m_xnt(xnt),
  219. m_fNodeOpen(FALSE),
  220. m_cchTagEscaped(0),
  221. m_pxb(pxb),
  222. m_fHasEmptyNamespace(FALSE)
  223. {
  224. }
  225. ~CXNode()
  226. {
  227. if (!m_fDone)
  228. {
  229. // Close the node
  230. //
  231. //$REVIEW: ScDone() could only fail for E_OUTMEMORY. Yes, we cannot
  232. //$REVIEW: return the failure from dtor. but how much better can be done
  233. //$REVIEW: when run out of memory?
  234. //$REVIEW: This does help to relievate the dependence on client to
  235. //$REVIEW: call ScDone correctly. (Of course, they still need to declare
  236. //$REVIEW: the nodes in correct order
  237. //
  238. (void)ScDone();
  239. }
  240. }
  241. // CXNode types ----------------------------------------------------------
  242. //
  243. typedef enum {
  244. XN_ELEMENT = 0,
  245. XN_ATTRIBUTE,
  246. XN_NAMESPACE
  247. };
  248. // Construction ----------------------------------------------------------
  249. //
  250. // Set the name of the node
  251. //
  252. SCODE ScSetTag (CXMLEmitter* pmsr, UINT cch, LPCWSTR pwszTag);
  253. // Sets the value of a node.
  254. //
  255. // IMPORTANT: setting the value of a node appends the value of the node
  256. // to the child.
  257. //
  258. SCODE ScSetValue (LPCSTR pszValue, UINT cch);
  259. SCODE ScSetValue (LPCWSTR pwszValue, UINT cch);
  260. SCODE ScSetValue (LPCWSTR pwszValue)
  261. {
  262. return ScSetValue (pwszValue, static_cast<UINT>(wcslen(pwszValue)));
  263. }
  264. SCODE ScSetUTF8Value (LPCSTR pszValue, UINT cch);
  265. SCODE ScSetFormatedXML (LPCSTR pszValue, UINT cchValue);
  266. SCODE ScSetFormatedXML (LPCWSTR pwszValue, UINT cchValue);
  267. // Adds an child to the this node
  268. //
  269. SCODE ScGetChildNode (XNT xntType, CXNode ** ppxnChild);
  270. SCODE ScDone();
  271. };
  272. // class CEmitterNode --------------------------------------------------------
  273. //
  274. class CEmitterNode
  275. {
  276. auto_ref_ptr<CXMLEmitter> m_emitter;
  277. auto_ref_ptr<CXNode> m_pxn;
  278. // non-implemented
  279. //
  280. CEmitterNode(const CEmitterNode& p);
  281. CEmitterNode& operator=(const CEmitterNode& p);
  282. public:
  283. CEmitterNode ()
  284. {
  285. }
  286. // Pass back a reference to the Emitter
  287. //
  288. CXMLEmitter* PEmitter() const { return m_emitter.get(); }
  289. VOID SetEmitter (CXMLEmitter* pmsr) { m_emitter = pmsr; }
  290. // Pass back a reference to the CXNode
  291. //
  292. CXNode* Pxn() const { return m_pxn.get(); }
  293. VOID SetPxn (CXNode* pxn) { m_pxn = pxn; }
  294. // New node construction -------------------------------------------------
  295. //
  296. SCODE ScConstructNode (CXMLEmitter& emitter,
  297. CXNode * pxnParent,
  298. LPCWSTR pwszTag,
  299. LPCWSTR pwszValue = NULL,
  300. LPCWSTR pwszType = NULL);
  301. // Add a child node to this node. This API is the heart of the emitter
  302. // processing and all other AddXXX() methods are written in terms of
  303. // this method.
  304. //
  305. SCODE ScAddNode (LPCWSTR pwszTag,
  306. CEmitterNode& en,
  307. LPCWSTR pwszValue = NULL,
  308. LPCWSTR pwszType = NULL);
  309. // Non-wide char nodes
  310. //
  311. SCODE ScAddMultiByteNode (LPCWSTR pwszTag,
  312. CEmitterNode& en,
  313. LPCSTR pszValue,
  314. LPCWSTR pwszType = NULL);
  315. SCODE ScAddUTF8Node (LPCWSTR pwszTag,
  316. CEmitterNode& en,
  317. LPCSTR pszValue,
  318. LPCWSTR pwszType = NULL);
  319. // "date.iso8601"
  320. //
  321. SCODE ScAddDateNode (LPCWSTR pwszTag,
  322. FILETIME * pft,
  323. CEmitterNode& en);
  324. // "int"
  325. //
  326. SCODE ScAddInt64Node (LPCWSTR pwszTag,
  327. LARGE_INTEGER * pli,
  328. CEmitterNode& en);
  329. // "boolean"
  330. //
  331. SCODE ScAddBoolNode (LPCWSTR pwszTag,
  332. BOOL f,
  333. CEmitterNode& en);
  334. // "bin.base64"
  335. //
  336. SCODE ScAddBase64Node (LPCWSTR pwszTag,
  337. ULONG cb,
  338. LPVOID pv,
  339. CEmitterNode& en,
  340. BOOL fSupressTypeAttr = FALSE,
  341. // For WebFolders, we need to emit zero length
  342. // binary properties as bin.hex instead of bin.base64.
  343. //
  344. BOOL fUseBinHexIfNoValue = FALSE);
  345. // Multi-Status ----------------------------------------------------------
  346. //
  347. SCODE ScDone ()
  348. {
  349. SCODE sc = S_OK;
  350. if (m_pxn.get())
  351. {
  352. sc = m_pxn->ScDone();
  353. m_pxn.clear();
  354. }
  355. m_emitter.clear();
  356. return sc;
  357. }
  358. };
  359. // String constants ----------------------------------------------------------
  360. //
  361. DEC_CONST CHAR gc_chAmp = '&';
  362. DEC_CONST CHAR gc_chBang = '!';
  363. DEC_CONST CHAR gc_chColon = ':';
  364. DEC_CONST CHAR gc_chDash = '-';
  365. DEC_CONST CHAR gc_chEquals = '=';
  366. DEC_CONST CHAR gc_chForwardSlash = '/';
  367. DEC_CONST CHAR gc_chBackSlash = '\\';
  368. DEC_CONST CHAR gc_chGreaterThan = '>';
  369. DEC_CONST CHAR gc_chLessThan = '<';
  370. DEC_CONST CHAR gc_chApos = '\'';
  371. DEC_CONST CHAR gc_chQuestionMark = '?';
  372. DEC_CONST CHAR gc_chQuote = '"';
  373. DEC_CONST CHAR gc_chSpace = ' ';
  374. DEC_CONST CHAR gc_szAmp[] = "&amp;";
  375. DEC_CONST CHAR gc_szGreaterThan[] = "&gt;";
  376. DEC_CONST CHAR gc_szLessThan[] = "&lt;";
  377. DEC_CONST CHAR gc_szApos[] = "&apos;";
  378. DEC_CONST CHAR gc_szQuote[] = "&quot;";
  379. DEC_CONST WCHAR gc_wszAmp[] = L"&amp;";
  380. DEC_CONST WCHAR gc_wszGreaterThan[] = L"&gt;";
  381. DEC_CONST WCHAR gc_wszLessThan[] = L"&lt;";
  382. DEC_CONST WCHAR gc_wszApos[] = L"&apos;";
  383. DEC_CONST WCHAR gc_wszQuote[] = L"&quot;";
  384. // XML property emitting helpers ---------------------------------------------
  385. //
  386. SCODE __fastcall
  387. ScEmitPropToXml (
  388. /* [in] */ CEmitterNode* penProp,
  389. /* [in] */ const BOOL fFilterValues,
  390. /* [in] */ const USHORT usPt,
  391. /* [in] */ const LPCWSTR wszTag,
  392. /* [in] */ const BYTE* pb);
  393. SCODE __fastcall
  394. ScEmitStringPropToXml (
  395. /* [in] */ CEmitterNode* penProp,
  396. /* [in] */ const BOOL fFilterValues,
  397. /* [in] */ const USHORT usPt,
  398. /* [in] */ const LPCWSTR wszTag,
  399. /* [in] */ const ULONG cpid,
  400. /* [in] */ const UINT cch,
  401. /* [in] */ const VOID* pv);
  402. SCODE __fastcall
  403. ScEmitBinaryPropToXml (
  404. /* [in] */ CEmitterNode* penProp,
  405. /* [in] */ const BOOL fFilterValues,
  406. /* [in] */ const USHORT usPt,
  407. /* [in] */ const LPCWSTR wszTag,
  408. /* [in] */ const UINT cb,
  409. /* [in] */ const BYTE* pb);
  410. SCODE __fastcall
  411. ScEmitMultiValuedAtomicToXml (
  412. /* [in] */ CEmitterNode* penProp,
  413. /* [in] */ const BOOL fFilterValues,
  414. /* [in] */ const USHORT usPt,
  415. /* [in] */ const UINT cbItem,
  416. /* [in] */ const LPCWSTR wszTag,
  417. /* [in] */ const ULONG cValues,
  418. /* [in] */ const BYTE* pb);
  419. SCODE __fastcall
  420. ScEmitMutliValuedStringToXml (
  421. /* [in] */ CEmitterNode* penProp,
  422. /* [in] */ const BOOL fFilterValues,
  423. /* [in] */ const USHORT usPt,
  424. /* [in] */ const LPCWSTR wszTag,
  425. /* [in] */ const ULONG cpid,
  426. /* [in] */ const UINT cchMax,
  427. /* [in] */ const LPVOID* pv);
  428. SCODE __fastcall
  429. ScEmitMutliValuedBinaryToXml (
  430. /* [in] */ CEmitterNode* penProp,
  431. /* [in] */ const BOOL fFilterValues,
  432. /* [in] */ const USHORT usPt,
  433. /* [in] */ const LPCWSTR wszTag,
  434. /* [in] */ const BYTE** ppb,
  435. /* [in] */ const DWORD* pcb,
  436. /* [in] */ const DWORD cbMax);
  437. #endif // _EX_XEMIT_H_