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.

262 lines
9.0 KiB

  1. // marsfact.h
  2. // header file for class CMarsXMLFactory,
  3. // a callback class for the XML Push model parser
  4. // CMarsXMLFactory is used to construct a MARS its file from the xml
  5. #pragma once
  6. #include "stack.h"
  7. #include <xmlparser.h>
  8. // forward declarations of data structures
  9. class CXMLElement;
  10. struct TagInformation;
  11. class CMarsXMLFactory : public CMarsComObject,
  12. public IXMLNodeFactory
  13. {
  14. public:
  15. CMarsXMLFactory();
  16. virtual ~CMarsXMLFactory();
  17. // IUnknown
  18. STDMETHOD_(ULONG,AddRef)();
  19. STDMETHOD_(ULONG,Release)();
  20. STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject);
  21. // CMarsComObject
  22. // This class has no back references so the passivate stuff is a noop
  23. virtual HRESULT DoPassivate() { return S_OK; }
  24. // IXMLNodeFactory - used to communicate with the IXMLParser
  25. virtual HRESULT STDMETHODCALLTYPE NotifyEvent(
  26. IXMLNodeSource *pSource, XML_NODEFACTORY_EVENT iEvt);
  27. virtual HRESULT STDMETHODCALLTYPE BeginChildren(
  28. IXMLNodeSource *pSource, XML_NODE_INFO *pNodeInfo);
  29. virtual HRESULT STDMETHODCALLTYPE EndChildren(
  30. IXMLNodeSource *pSource, BOOL fEmpty,
  31. XML_NODE_INFO *pNodeInfo);
  32. virtual HRESULT STDMETHODCALLTYPE Error(
  33. IXMLNodeSource *pSource, HRESULT hrErrorCode,
  34. USHORT cNumRecs, XML_NODE_INFO **apNodeInfo);
  35. virtual HRESULT STDMETHODCALLTYPE CreateNode(
  36. IXMLNodeSource *pSource, PVOID pNodeParent,
  37. USHORT cNumRecs, XML_NODE_INFO **apNodeInfo);
  38. // CMarsXMLFactory
  39. // Call "Run" when you want to start parsing...
  40. // Note: pisDoc must be a synchronous stream (not E_PENDING) -- so there!
  41. HRESULT Run(IStream *pisDoc);
  42. // Set the TagInformation* array used to create nodes. These
  43. // arrays should be const and live past the lifetime of the
  44. // parsing; they are not copied
  45. void SetTagInformation(TagInformation **ptiaTags);
  46. // Sets the LONG parameter passed as the last argument to all of
  47. // the nodes created in CreateNode. (See the definition of
  48. // CreationFunction below) This parameter is the way to provide
  49. // your run-time pointer/reference or whatever to the objects that
  50. // the xml is supposed to be initializing
  51. void SetLParam(LONG lParamNew);
  52. protected:
  53. HRESULT SetElementAttributes(CXMLElement *pxElem,
  54. XML_NODE_INFO **apNodeInfo, ULONG cInfoLen);
  55. HRESULT CreateElement(LPCWSTR wzTagName, ULONG cLen, CXMLElement **ppxElem);
  56. CStack<CXMLElement *> m_elemStack;
  57. TagInformation **m_ptiaTags;
  58. LONG m_lParamArgument;
  59. };
  60. // The AttributeInformation and TagInformation structs, which are used to determine syntax: what
  61. // element creation function is called for what tag name
  62. struct AttributeInformation
  63. {
  64. LPWSTR wzAttName;
  65. VARTYPE vt;
  66. };
  67. typedef CXMLElement * (*CreationFunction)(LPCWSTR, VARTYPE, TagInformation **, AttributeInformation **, LONG lParam);
  68. struct TagInformation
  69. {
  70. LPWSTR wzTagName;
  71. CreationFunction funcCreate;
  72. VARTYPE vt;
  73. TagInformation **ptiaChildren;
  74. AttributeInformation **paiaAttributes;
  75. };
  76. // The CXMLElement class, from which all the elements used by the
  77. // CMarsXMLFactory must be derived. The methods can be pick and chose
  78. // implemented; the base class implementations spew a TraceMsg error
  79. // and return S_FALSE or E_NOTIMPL as appropriate
  80. class CXMLElement
  81. {
  82. private:
  83. ULONG m_cRef;
  84. public:
  85. // CXMLElement is NOT a COM object, so these methods are
  86. // given wierd names to prevent confusion...
  87. ULONG Add_Ref() { return ++m_cRef; }
  88. ULONG Release_Ref()
  89. {
  90. if (--m_cRef == 0)
  91. {
  92. delete this;
  93. return 0;
  94. }
  95. else return m_cRef;
  96. }
  97. // these methods are used by the CMarsXMLFactory and should return S_FALSE on not impl
  98. // (to indicate an unexpected operation due to unexpected xml)
  99. virtual HRESULT OnNodeComplete();
  100. // Addchild takes ownership of the element on S_OK; otherwise CMarsXMLFactory deletes pxeChild
  101. virtual HRESULT AddChild(CXMLElement *pxeChild);
  102. virtual HRESULT SetAttribute(LPCWSTR wzName, ULONG cLenName,
  103. LPCWSTR pwzValue, ULONG cLenValue);
  104. //
  105. // HACKHACK paddywack:
  106. // The implementer of this function should be aware of the strange
  107. // semantics here: SetInnerXMLText is sometimes called multiple times
  108. // due to issues with the Push-model parser. If SetInnerXMLText is called
  109. // more than once, the subsequent called mean "AppendInnerXMLText". :)
  110. //
  111. virtual HRESULT SetInnerXMLText(LPCWSTR pwzText, ULONG cLen);
  112. // GetName can return NULL
  113. virtual LPCWSTR GetName();
  114. // The rest of these methods are generalized methods to access CXMLElements.
  115. // They should generally return E_whatever on failure or not impl.
  116. // This interface can be changed, as long as whoever changes it also makes sure
  117. // to serve up the changes in CXMLGenericElement
  118. // These methods are not used by any of the code in marsfact.cpp
  119. // The GetContent and GetAttribute methods return pointers to existing variants;
  120. // these variants should be considered const
  121. // TODO: No procedure should take VARIANT**: we need to make all of these
  122. // VARIANT*
  123. virtual HRESULT GetContent(VARIANT *pvarOut);
  124. virtual HRESULT GetAttribute(LPCWSTR wzName, VARIANT *pvarOut);
  125. virtual void FirstChild();
  126. virtual void NextChild();
  127. virtual CXMLElement *CurrentChild();
  128. virtual CXMLElement *DetachCurrentChild();
  129. virtual BOOL IsDoneChild();
  130. protected:
  131. CXMLElement() { m_cRef = 1; }
  132. virtual ~CXMLElement() { ATLASSERT(0 == m_cRef); }
  133. };
  134. struct CSimpleNode
  135. {
  136. CSimpleNode *m_psnodeNext;
  137. void *m_pvData;
  138. };
  139. // Generic implementation of the CXMLElement class.
  140. class CXMLGenericElement : public CXMLElement
  141. {
  142. public:
  143. virtual ~CXMLGenericElement();
  144. virtual HRESULT OnNodeComplete();
  145. virtual HRESULT AddChild(CXMLElement *pxeChild);
  146. virtual HRESULT SetAttribute(LPCWSTR wzName, ULONG cLenName,
  147. LPCWSTR pwzValue, ULONG cLenValue);
  148. virtual HRESULT SetInnerXMLText(LPCWSTR pwzText, ULONG cLen);
  149. virtual LPCWSTR GetName();
  150. virtual HRESULT GetContent(VARIANT *pvarOut);
  151. virtual HRESULT GetAttribute(LPCWSTR wzName, VARIANT *pvarOut);
  152. virtual void FirstChild();
  153. virtual void NextChild();
  154. // These methods return NULL if invalid
  155. // DetachCurrentChild does the same as CurrentChild, but also removes the child from the
  156. // list
  157. virtual CXMLElement *CurrentChild();
  158. virtual CXMLElement *DetachCurrentChild();
  159. virtual BOOL IsDoneChild();
  160. static CXMLElement *CreateInstance(LPCWSTR wzName,
  161. VARTYPE vt,
  162. TagInformation **ptiaChildren,
  163. AttributeInformation **paiaAttributes,
  164. LONG lParam);
  165. protected:
  166. CXMLGenericElement(LPCWSTR wzName, VARTYPE vt,
  167. TagInformation **ptiaChildren, AttributeInformation **paiaAttributes);
  168. CXMLGenericElement() {}
  169. VARTYPE m_vtData;
  170. CComVariant m_varData;
  171. CSimpleNode *m_psnodeAttributes;
  172. // The header node is a member variable.
  173. CSimpleNode m_snodeChildrenFirst;
  174. CSimpleNode *m_psnodeChildrenFirst;
  175. CSimpleNode *m_psnodeChildrenEnd;
  176. CSimpleNode *m_psnodeChildrenIter;
  177. TagInformation **m_ptiaChildren;
  178. AttributeInformation **m_paiaAttributes;
  179. CComBSTR m_bstrName;
  180. };
  181. // Some helpful functions for handling explicit length strings
  182. // Returns true if the strings are the same up to the nth char,
  183. // and the zero terminated string (third param) has a null character after that
  184. // position
  185. BOOL StrEqlNToSZ(const WCHAR *wzN, int n, const WCHAR *wzSZ);
  186. // Retunrs true if wz is L"true" or L"TRUE" and cLen is 4
  187. // Must be "bool" for CComVariant to become VT_BOOL
  188. bool StrToIsTrueNW(const WCHAR *wz, ULONG cLen);
  189. // Converts the first cLen chars to a long, returning a E_FAIL if there is a non-digit
  190. // If L'\0' is encountered, the conversion stops at that point
  191. HRESULT StrToLongNW(const WCHAR *wzString, ULONG cLen, LONG *plong);
  192. // SpewTraceMessage copies the cLen wchars to a bstr and then
  193. // calls TraceMsg(TF_XMLPARSING | TF_WARNING, L"%sstring=%s", wzDesc, wzBstr)
  194. #ifdef DEBUG
  195. void SpewUnrecognizedString(const WCHAR *wzString, ULONG cLen, const WCHAR *wzDesc);
  196. #else
  197. #define SpewUnrecognizedString(strByLength, len, strDesc)
  198. #endif
  199. // I used TraceMst(..., L"...%s...", string) all over the place without checking string;
  200. // As everyone knows (except me!) printf faults on NULL for a %s arg, hence this macro
  201. #define NULL_STRING_PROTECT(str) str ? str : L""