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.

330 lines
8.1 KiB

  1. /*
  2. * X P R S . H
  3. *
  4. * XML push-model parsing
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #ifndef _EX_XPRS_H_
  9. #define _EX_XPRS_H_
  10. #include <xmlparser.h>
  11. #include <ex\autoptr.h>
  12. #include <ex\nmspc.h>
  13. #include <davsc.h>
  14. #include <exo.h>
  15. // XML Namespace scopes ------------------------------------------------------
  16. //
  17. class CXmlnsScope
  18. {
  19. private:
  20. // Ref' counting.
  21. //
  22. // !!! Please note that this is NON-THREADSAFE !!!
  23. //
  24. // CXNodes should be operated on a single thread at
  25. // any given time.
  26. //
  27. LONG m_cRef;
  28. public:
  29. void AddRef() { m_cRef++; }
  30. void Release() { if (0 == --m_cRef) delete this; }
  31. private:
  32. auto_ref_ptr<CNmspc> m_pns;
  33. // non-implemented
  34. //
  35. CXmlnsScope(const CXmlnsScope& p);
  36. CXmlnsScope& operator=(const CXmlnsScope& p);
  37. public:
  38. ~CXmlnsScope() {}
  39. CXmlnsScope()
  40. : m_cRef(1)
  41. {
  42. }
  43. VOID ScopeNamespace(CNmspc* pns)
  44. {
  45. // Set the current top of the sibling chain as a sibling
  46. // to this namespace.
  47. //
  48. pns->SetSibling (m_pns.get());
  49. // Set this new namespace as the top of the sibling chain.
  50. //
  51. m_pns = pns;
  52. }
  53. VOID LeaveScope(CNmspcCache* pnsc)
  54. {
  55. auto_ref_ptr<CNmspc> pns;
  56. while (m_pns.get())
  57. {
  58. // Unhook the namespace
  59. //
  60. pns = m_pns;
  61. m_pns = m_pns->PnsSibling();
  62. // Remove it from the indexes
  63. //
  64. pnsc->RemovePersisted (pns);
  65. }
  66. }
  67. };
  68. // class CXMLNodeFactory -----------------------------------------------------
  69. //
  70. class CNodeFactory :
  71. public EXO,
  72. public IXMLNodeFactory,
  73. public CParseNmspcCache
  74. {
  75. StringBuffer<WCHAR> m_sbValue;
  76. // State tracking
  77. //
  78. typedef enum {
  79. ST_NODOC,
  80. ST_PROLOGUE,
  81. ST_INDOC,
  82. ST_INATTR,
  83. ST_INATTRDATA,
  84. ST_XMLERROR
  85. } PARSE_STATE;
  86. PARSE_STATE m_state;
  87. HRESULT m_hrParserError;
  88. // Unhandled nodes -------------------------------------------------------
  89. //
  90. UINT m_cUnhandled;
  91. VOID PushUnhandled()
  92. {
  93. ++m_cUnhandled;
  94. XmlTrace ("Xml: incrementing unhandled node depth\n"
  95. " m_cUnhandled: %ld\n",
  96. m_cUnhandled);
  97. }
  98. VOID PopUnhandled()
  99. {
  100. --m_cUnhandled;
  101. XmlTrace ("Xml: decrementing unhandled node depth\n"
  102. " m_cUnhandled: %ld\n",
  103. m_cUnhandled);
  104. }
  105. // non-implemented
  106. //
  107. CNodeFactory(const CNodeFactory& p);
  108. CNodeFactory& operator=(const CNodeFactory& p);
  109. protected:
  110. // FIsTag() --------------------------------------------------------------
  111. //
  112. // FIsTag() can be used in XML parsing code as a shortcut to see if
  113. // the str from a xml element matches a fully qualified tagname. An
  114. // important distinction here, is that FIsTag() will allow for non-
  115. // qualified short-names. So, FIsTag() should never be used in any
  116. // place where the tag is not scoped by the standard dav namespace.
  117. //
  118. // ie. "DAV:foo" and "foo" will match.
  119. //
  120. inline BOOL FIsTag (LPCWSTR pwszTag, LPCWSTR pwszExpected)
  121. {
  122. Assert (wcslen(pwszExpected) > CchConstString(gc_wszDav));
  123. return (!_wcsicmp (pwszTag, pwszExpected) ||
  124. !_wcsicmp (pwszTag, pwszExpected + CchConstString(gc_wszDav)));
  125. }
  126. public:
  127. virtual ~CNodeFactory() {}
  128. CNodeFactory()
  129. : m_state(ST_NODOC),
  130. m_hrParserError(S_OK),
  131. m_cUnhandled(0)
  132. {
  133. INIT_TRACE(Xml);
  134. }
  135. // EXO support
  136. //
  137. EXO_INCLASS_DECL(CNodeFactory);
  138. // INodeFactory ----------------------------------------------------------
  139. //
  140. virtual HRESULT STDMETHODCALLTYPE NotifyEvent(
  141. /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
  142. /* [in] */ XML_NODEFACTORY_EVENT iEvt);
  143. virtual HRESULT STDMETHODCALLTYPE BeginChildren(
  144. /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
  145. /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo);
  146. virtual HRESULT STDMETHODCALLTYPE EndChildren(
  147. /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
  148. /* [in] */ BOOL fEmpty,
  149. /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo);
  150. virtual HRESULT STDMETHODCALLTYPE Error(
  151. /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
  152. /* [in] */ HRESULT hrErrorCode,
  153. /* [in] */ USHORT cNumRecs,
  154. /* [in] */ XML_NODE_INFO __RPC_FAR *__RPC_FAR *apNodeInfo);
  155. virtual HRESULT STDMETHODCALLTYPE CreateNode(
  156. /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
  157. /* [in] */ PVOID pNodeParent,
  158. /* [in] */ USHORT cNumRecs,
  159. /* [in] */ XML_NODE_INFO __RPC_FAR *__RPC_FAR *pNodeInfo);
  160. // CNodeFactory specific methods -----------------------------------------
  161. //
  162. virtual SCODE ScCompleteAttribute (void) = 0;
  163. virtual SCODE ScCompleteChildren (
  164. /* [in] */ BOOL fEmptyNode,
  165. /* [in] */ DWORD dwType,
  166. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  167. /* [in] */ ULONG ulLen) = 0;
  168. virtual SCODE ScHandleNode (
  169. /* [in] */ DWORD dwType,
  170. /* [in] */ DWORD dwSubType,
  171. /* [in] */ BOOL fTerminal,
  172. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  173. /* [in] */ ULONG ulLen,
  174. /* [in] */ ULONG ulNamespaceLen,
  175. /* [in] */ const WCHAR __RPC_FAR *pwcNamespace,
  176. /* [in] */ const ULONG ulNsPrefixLen) = 0;
  177. // Most implementation do not need this method, lock requires it for
  178. // proper processing of the owner node.
  179. //
  180. virtual SCODE ScCompleteCreateNode (
  181. /* [in] */ DWORD)
  182. {
  183. return S_OK;
  184. }
  185. // Parser errors ---------------------------------------------------------
  186. //
  187. BOOL FParserError(SCODE sc) const
  188. {
  189. return (FAILED (m_hrParserError) ||
  190. ((sc & 0xFFFFFF00) == XML_E_PARSEERRORBASE));
  191. }
  192. };
  193. // ScInstatiateParser() ------------------------------------------------------
  194. //
  195. // Raid X5:136451
  196. // The XML parser in the version of MSXML.DLL released with Windows 2000
  197. // doesn't fail properly when given a XML document shorter than a certain
  198. // length. CB_XML_PARSER_MIN is the minimum length of an XML document, in
  199. // bytes, required to avoid this bug. One must explicitly check that a
  200. // document is at least this long before feeding it to the XML parser.
  201. //
  202. enum { CB_XML_PARSER_MIN = 2 };
  203. SCODE ScNewXMLParser (CNodeFactory* pnf, IStream * pstm, IXMLParser ** ppxprs);
  204. SCODE ScParseXML (IXMLParser * pxprs, CNodeFactory * pnf);
  205. SCODE ScParseXMLBuffer (CNodeFactory* pnf, LPCWSTR pwszXML);
  206. // Parsers -------------------------------------------------------------------
  207. //
  208. // CPropContext --------------------------------------------------------------
  209. //
  210. // The property context is used specifically in <DAV:prop> node processing.
  211. // The components of the property are constructed across multiple calls and
  212. // are implementation dependant.
  213. //
  214. class CPropContext
  215. {
  216. private:
  217. // Ref' counting.
  218. //
  219. // !!! Please note that this is NON-THREADSAFE !!!
  220. //
  221. // CXNodes should be operated on a single thread at
  222. // any given time.
  223. //
  224. LONG m_cRef;
  225. public:
  226. void AddRef() { m_cRef++; }
  227. void Release() { if (0 == --m_cRef) delete this; }
  228. private:
  229. // non-implemented operators
  230. //
  231. CPropContext( const CPropContext& );
  232. CPropContext& operator=( const CPropContext& );
  233. public:
  234. virtual ~CPropContext() {}
  235. CPropContext()
  236. : m_cRef(1) // com-style refcounting
  237. {
  238. }
  239. virtual SCODE ScSetType(
  240. /* [in] */ LPCWSTR pwszType) = 0;
  241. virtual SCODE ScSetValue(
  242. /* [in] */ LPCWSTR pwszValue,
  243. /* [in] */ UINT cmvValues) = 0;
  244. virtual SCODE ScComplete(
  245. /* [in] */ BOOL fEmpty) = 0;
  246. virtual BOOL FMultiValued( void ) = 0;
  247. virtual SCODE ScSetFlags(DWORD dw) { return S_OK; }
  248. };
  249. // CValueContext -------------------------------------------------------------
  250. //
  251. // When a parser encounters a property, a context is needed such that
  252. // construction of the property value is possible.
  253. //
  254. class CValueContext
  255. {
  256. // non-implemented operators
  257. //
  258. CValueContext( const CValueContext& );
  259. CValueContext& operator=( const CValueContext& );
  260. public:
  261. CValueContext() {}
  262. virtual ~CValueContext() {}
  263. // When the parser finds an item that the client wants operated on,
  264. // the item is added to the context via the following set context
  265. // methods. Each request is qualified by the resource on which the
  266. // request is made.
  267. //
  268. virtual SCODE ScSetProp(
  269. /* [in] */ LPCWSTR pwszPath,
  270. /* [in] */ LPCWSTR pwszProp,
  271. /* [in] */ auto_ref_ptr<CPropContext>& pPropCtx) = 0;
  272. };
  273. #endif // _EX_XPRS_H_