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.

632 lines
15 KiB

  1. #include "stdafx.h"
  2. #include "xmlutil.h"
  3. /////////////////////////////////////////////////////
  4. // helpers for encoding and decoding of C++
  5. // data structures to and from XML PCDATA fields
  6. WCHAR EncodeByteToWchar(IN BYTE b)
  7. {
  8. ASSERT(b <= 0x0f); // low nibble
  9. if(b <= 9)
  10. return static_cast<WCHAR>(b + L'0');
  11. else
  12. return static_cast<WCHAR>((b-10) + L'a');
  13. }
  14. BYTE DecodeWcharToByte(IN WCHAR ch)
  15. {
  16. BYTE byte = 0;
  17. if ((ch >= L'0') && (ch <= L'9'))
  18. {
  19. byte = static_cast<BYTE>((ch - L'0') & 0xff);
  20. }
  21. else if ((ch >= L'a') && (ch <= L'f'))
  22. {
  23. byte = static_cast<BYTE>(((ch - L'a')+10) & 0xff);
  24. }
  25. else if ((ch >= L'A') && (ch <= L'F'))
  26. {
  27. byte = static_cast<BYTE>(((ch - L'A')+10) & 0xff);
  28. }
  29. else
  30. {
  31. ASSERT(FALSE);
  32. byte = 0xFF;
  33. }
  34. return byte;
  35. }
  36. HRESULT EncodeBlobToBSTR(IN BYTE* pBlob, IN ULONG nBytes, OUT BSTR* pBstr)
  37. {
  38. ASSERT(pBstr != NULL);
  39. *pBstr = NULL;
  40. if ((pBlob == NULL) || (nBytes == 0))
  41. {
  42. return E_POINTER;
  43. }
  44. ULONG nChars = 2*nBytes;
  45. *pBstr = SysAllocStringLen(NULL, nChars);
  46. if (*pBstr == NULL)
  47. {
  48. return E_OUTOFMEMORY;
  49. }
  50. WCHAR* pCurr = *pBstr;
  51. for (ULONG k=0; k< nBytes; k++)
  52. {
  53. *pCurr = EncodeByteToWchar(static_cast<BYTE>((pBlob[k]>>4) & 0xff));
  54. pCurr++;
  55. *pCurr = EncodeByteToWchar(static_cast<BYTE>(pBlob[k] & 0x0f));
  56. pCurr++;
  57. }
  58. return S_OK;
  59. }
  60. void DecodeLoop(IN LPCWSTR lpsz, OUT BYTE* pByte, OUT ULONG nBytes)
  61. {
  62. for (ULONG k=0; k< nBytes; k++)
  63. {
  64. BYTE bHigh = DecodeWcharToByte(lpsz[2*k]);
  65. BYTE bLow = DecodeWcharToByte(lpsz[(2*k)+1]);
  66. pByte[k] = static_cast<BYTE>((bHigh<<4) | bLow);
  67. }
  68. }
  69. HRESULT DecodeBSTRtoBlob(IN BSTR bstr, OUT BYTE** ppByte, OUT ULONG* pnBytes)
  70. {
  71. *ppByte = NULL;
  72. *pnBytes = 0;
  73. if ((bstr == NULL) || (ppByte == NULL) || (pnBytes == NULL))
  74. {
  75. // bad parameters
  76. return E_POINTER;
  77. }
  78. // compute the length of the BSTR
  79. ULONG nChars = static_cast<ULONG>(wcslen(bstr));
  80. if (nChars == 0)
  81. {
  82. return E_INVALIDARG;
  83. }
  84. // must be even
  85. size_t nBytes = nChars/2;
  86. if (nBytes*2 != nChars)
  87. {
  88. return E_INVALIDARG;
  89. }
  90. // allocate memory and set the buffer length
  91. *ppByte = (BYTE*)malloc(nBytes);
  92. if (*ppByte == NULL)
  93. {
  94. return E_OUTOFMEMORY;
  95. }
  96. *pnBytes = static_cast<ULONG>(nBytes);
  97. DecodeLoop(bstr, *ppByte, static_cast<UINT>(nBytes));
  98. return TRUE;
  99. }
  100. //
  101. // given a BSTR containing the encoding of a struct
  102. // it loads it into a buffer, pByte of size nBytes
  103. //
  104. HRESULT DecodeBSTRtoStruct(IN BSTR bstr, IN BYTE* pByte, IN ULONG nBytes)
  105. {
  106. ASSERT(pByte != NULL);
  107. ASSERT(pByte != NULL);
  108. if ( (bstr == NULL) && (pByte == NULL) )
  109. {
  110. // bad parameters
  111. return E_POINTER;
  112. }
  113. // compute the length of the BSTR
  114. size_t nChars = wcslen(bstr);
  115. if (nChars == 0)
  116. {
  117. return E_INVALIDARG;
  118. }
  119. // must be even (because of encoding)
  120. ULONG nBstrBytes = static_cast<ULONG>(nChars/2);
  121. if (nBstrBytes*2 != nChars)
  122. {
  123. ASSERT(FALSE);
  124. return E_INVALIDARG;
  125. }
  126. // must match the struct length
  127. if (nBstrBytes != nBytes)
  128. {
  129. ASSERT(FALSE);
  130. return E_INVALIDARG;
  131. }
  132. DecodeLoop(bstr, pByte, nBytes);
  133. return S_OK;
  134. }
  135. HRESULT EncodeBoolToBSTR(IN BOOL b, OUT BSTR* pBstr)
  136. {
  137. if (pBstr == NULL)
  138. {
  139. return E_POINTER;
  140. }
  141. *pBstr = SysAllocString(b ? L"TRUE" : L"FALSE");
  142. if (*pBstr == NULL)
  143. {
  144. return E_OUTOFMEMORY;
  145. }
  146. return S_OK;
  147. }
  148. HRESULT DecodeBSTRtoBool(IN BSTR bstr, OUT BOOL* pb)
  149. {
  150. if (bstr == NULL)
  151. {
  152. return E_INVALIDARG;
  153. }
  154. if (pb == NULL)
  155. {
  156. return E_POINTER;
  157. }
  158. if (CompareNoCase(bstr, L"TRUE"))
  159. {
  160. *pb = TRUE;
  161. return S_OK;
  162. }
  163. if (CompareNoCase(bstr, L"FALSE"))
  164. {
  165. *pb = FALSE;
  166. return S_OK;
  167. }
  168. return E_INVALIDARG;
  169. }
  170. /*
  171. HRESULT EncodeIntToBSTR(IN int n, OUT BSTR* pBstr)
  172. {
  173. int i = n;
  174. pBstr = NULL;
  175. return E_NOTIMPL;
  176. }
  177. HRESULT DecodeIntToBool(IN BSTR bstr, OUT int* pN)
  178. {
  179. //
  180. // This doesn't do anything useful
  181. //
  182. *pN = 0;
  183. return E_NOTIMPL;
  184. }
  185. */
  186. ///////////////////////////////////////////////////////////////////////
  187. // XML SPECIFIC FUNCTIONS
  188. ///////////////////////////////////////////////////////////////////////
  189. //
  190. // given an XML node, it retrieves the node name
  191. // and compares it with the given string
  192. //
  193. BOOL XMLIsNodeName(IXMLDOMNode* pXDN, LPCWSTR lpszName)
  194. {
  195. ASSERT(lpszName != NULL);
  196. ASSERT(pXDN != NULL);
  197. CComBSTR bstrName;
  198. HRESULT hr = pXDN->get_nodeName(&bstrName);
  199. ASSERT(SUCCEEDED(hr));
  200. if (FAILED(hr))
  201. {
  202. return FALSE;
  203. }
  204. return CompareXMLTags(bstrName, lpszName);
  205. }
  206. //
  207. // given an XML node of type NODE_TEXT, it
  208. // returns its value into a BSTR
  209. //
  210. HRESULT XML_GetNodeText(IXMLDOMNode* pXDN, BSTR* pBstr)
  211. {
  212. ASSERT(pXDN != NULL);
  213. ASSERT(pBstr != NULL);
  214. // null out output value
  215. *pBstr = NULL;
  216. // assume the given node has a child node
  217. CComPtr<IXMLDOMNode> spName;
  218. HRESULT hr = pXDN->get_firstChild(&spName);
  219. if (FAILED(hr))
  220. {
  221. // unexpected failure
  222. return hr;
  223. }
  224. // if no children, the api returns S_FALSE
  225. if (spName == NULL)
  226. {
  227. return hr;
  228. }
  229. // got now a valid pointer,
  230. // check if this is the valid node type
  231. DOMNodeType nodeType;
  232. hr = spName->get_nodeType(&nodeType);
  233. ASSERT(hr == S_OK);
  234. ASSERT(nodeType == NODE_TEXT);
  235. if (nodeType != NODE_TEXT)
  236. {
  237. ASSERT(FALSE);
  238. return E_INVALIDARG;
  239. }
  240. // it is of type text
  241. // retrieve the node value into a variant
  242. CComVariant val;
  243. hr = pXDN->get_nodeTypedValue(&val);
  244. if (FAILED(hr))
  245. {
  246. // unexpected failure
  247. ASSERT(FALSE);
  248. return hr;
  249. }
  250. if (val.vt != VT_BSTR)
  251. {
  252. ASSERT(FALSE);
  253. return E_INVALIDARG;
  254. }
  255. // got the text value, package it into a BSTR
  256. *pBstr = ::SysAllocString(val.bstrVal);
  257. return S_OK;
  258. }
  259. //
  260. // given an XML node of type NODE_TEXT, containing an encoding of
  261. // a struct and given a buffer pByte of length nBytes, it decodes the
  262. // node and fills it in the buffer
  263. //
  264. HRESULT XML_GetNodeStruct(IXMLDOMNode* pXDN, BYTE* pByte, ULONG nBytes)
  265. {
  266. CComBSTR bstr;
  267. HRESULT hr = XML_GetNodeText(pXDN, &bstr);
  268. if (FAILED(hr))
  269. {
  270. return hr;
  271. }
  272. return DecodeBSTRtoStruct(bstr, pByte, nBytes);
  273. }
  274. //
  275. // given an XML node of type NODE_TEXT, containing an encoding of
  276. // a blob it decodes the string and allocates *pnBytes of memory
  277. // and fills it in the buffer
  278. //
  279. HRESULT XML_GetNodeBlob(IXMLDOMNode* pXDN, BYTE** ppByte, ULONG* pnBytes)
  280. {
  281. CComBSTR bstr;
  282. HRESULT hr = XML_GetNodeText(pXDN, &bstr);
  283. if (FAILED(hr))
  284. {
  285. return hr;
  286. }
  287. return DecodeBSTRtoBlob(bstr, ppByte, pnBytes);
  288. }
  289. //
  290. // given an XML node of type NODE_TEXT, containing an encoding of
  291. // a BOOL value it returns a value into a BOOL*
  292. //
  293. HRESULT XML_GetNodeBOOL(IXMLDOMNode* pXDN, BOOL* pb)
  294. {
  295. CComBSTR bstr;
  296. HRESULT hr = XML_GetNodeText(pXDN, &bstr);
  297. if (FAILED(hr))
  298. {
  299. return hr;
  300. }
  301. return DecodeBSTRtoBool(bstr, pb);
  302. }
  303. HRESULT XML_GetNodeDWORD(IXMLDOMNode* pXDN, DWORD* pdw)
  304. {
  305. CComBSTR bstr;
  306. HRESULT hr = XML_GetNodeText(pXDN, &bstr);
  307. if (FAILED(hr))
  308. {
  309. return hr;
  310. }
  311. long lVal = _wtol(bstr);
  312. *pdw = static_cast<DWORD>(lVal);
  313. return hr;
  314. }
  315. //
  316. // given an XML node and a tag for a node, it
  317. // searches the subtree (depth first) to find the
  318. // first occurrence and returns the associated XML node
  319. //
  320. HRESULT XML_FindSubtreeNode(IXMLDOMNode* pXMLCurrentRootNode,
  321. LPCWSTR lpszNodeTag,
  322. IXMLDOMNode** ppXMLNode)
  323. {
  324. ASSERT(pXMLCurrentRootNode != NULL);
  325. ASSERT(lpszNodeTag != NULL);
  326. ASSERT(ppXMLNode != NULL);
  327. *ppXMLNode = NULL; // null out return value
  328. // get the list of child nodes
  329. CComPtr<IXMLDOMNode> spCurrChild;
  330. HRESULT hr = pXMLCurrentRootNode->get_firstChild(&spCurrChild);
  331. if (FAILED(hr))
  332. {
  333. return hr;
  334. }
  335. if (spCurrChild == NULL)
  336. {
  337. return S_OK; // end of the recursion
  338. }
  339. // recurse down on children
  340. while (spCurrChild != NULL)
  341. {
  342. CComBSTR bstrChildName;
  343. hr = spCurrChild->get_nodeName(&bstrChildName);
  344. if (FAILED(hr))
  345. {
  346. return hr;
  347. }
  348. if (bstrChildName != NULL)
  349. {
  350. //wprintf(L"bstrChildName = %s\n", bstrChildName);
  351. if (CompareXMLTags(bstrChildName, lpszNodeTag))
  352. {
  353. // got the node we want
  354. (*ppXMLNode) = spCurrChild;
  355. (*ppXMLNode)->AddRef();
  356. return S_OK;
  357. }
  358. }
  359. // go down recursively on the current child
  360. hr = XML_FindSubtreeNode(spCurrChild, lpszNodeTag, ppXMLNode);
  361. if (FAILED(hr))
  362. {
  363. return hr;
  364. }
  365. if (*ppXMLNode != NULL)
  366. {
  367. // got it from the recursion, just return
  368. return S_OK;
  369. }
  370. // keep going to the next child node
  371. CComPtr<IXMLDOMNode> spTemp = spCurrChild;
  372. spCurrChild = NULL;
  373. spTemp->get_nextSibling(&spCurrChild);
  374. }
  375. // not found in the recursion and in the loop above
  376. // need to return S_OK, we will check the output pointer
  377. return S_OK;
  378. }
  379. //
  380. // function to walk the list of children of a node
  381. // and print some information
  382. // NOTICE: this is for debugging and learning purposes
  383. // more than for getting real info
  384. //
  385. void XML_PrintTreeRaw(IXMLDOMNode* pXDN, int nLevel)
  386. {
  387. PrintIdentation(nLevel);
  388. //
  389. // get the name and type of the node
  390. //
  391. CComBSTR bstrName;
  392. pXDN->get_nodeName(&bstrName);
  393. CComBSTR bstrType;
  394. pXDN->get_nodeTypeString(&bstrType);
  395. DOMNodeType nodeType;
  396. pXDN->get_nodeType(&nodeType);
  397. TRACE(L"Name = %s, Type = %d (%s) ", bstrName, nodeType, bstrType);
  398. if (nodeType == NODE_TEXT)
  399. {
  400. CComVariant val;
  401. pXDN->get_nodeTypedValue(&val);
  402. if (val.vt == VT_BSTR)
  403. {
  404. TRACE(L"Val = %s", val.bstrVal);
  405. }
  406. }
  407. TRACE(L"\n");
  408. // get the list of child nodes
  409. CComPtr<IXMLDOMNode> spCurrChild;
  410. pXDN->get_firstChild(&spCurrChild);
  411. if (spCurrChild == NULL)
  412. {
  413. return;
  414. }
  415. // recurse down on children
  416. while (spCurrChild != NULL)
  417. {
  418. XML_PrintTreeRaw(spCurrChild, nLevel+1);
  419. CComPtr<IXMLDOMNode> temp = spCurrChild;
  420. spCurrChild = NULL;
  421. temp->get_nextSibling(&spCurrChild);
  422. }
  423. }
  424. void PrintIdentation(int iLevel)
  425. {
  426. for (int k=0; k<iLevel;k++)
  427. {
  428. // wprintf(L" ");
  429. TRACE(L" ");
  430. }
  431. }
  432. ///////////////////////////////////////////////////////////////////
  433. ///////////////////////////////////////////////////////////////////
  434. ///////////////////////////////////////////////////////////////////
  435. //
  436. // given an XML document,it creates an XML node of the given type
  437. // and with the given name
  438. //
  439. HRESULT XML_CreateDOMNode(IXMLDOMDocument* pDoc,
  440. DOMNodeType type, LPCWSTR lpszName,
  441. IXMLDOMNode** ppXMLDOMNode)
  442. {
  443. *ppXMLDOMNode = NULL;
  444. CComVariant vtype((long)type, VT_I4);
  445. CComBSTR bstrName = lpszName;
  446. HRESULT hr = pDoc->createNode(vtype, bstrName, NULL, ppXMLDOMNode);
  447. return hr;
  448. }
  449. HRESULT XML_AppendChildDOMNode(IXMLDOMNode* pXMLContainerNode,
  450. IXMLDOMNode* pXMLChildNode)
  451. {
  452. CComPtr<IXMLDOMNode> p;
  453. CComVariant after;
  454. after.vt = VT_EMPTY;
  455. HRESULT hr = pXMLContainerNode->appendChild(pXMLChildNode, &p);
  456. return hr;
  457. }
  458. HRESULT XML_CreateTextDataNode(IXMLDOMDocument* pXMLDoc,
  459. LPCWSTR lpszNodeTag,
  460. LPCWSTR lpszNodeData,
  461. IXMLDOMNode** ppNode)
  462. {
  463. *ppNode = NULL;
  464. CComPtr<IXMLDOMNode> spXMLDOMNodeName;
  465. HRESULT hr = XML_CreateDOMNode(pXMLDoc, NODE_ELEMENT, lpszNodeTag, &spXMLDOMNodeName);
  466. RETURN_IF_FAILED(hr);
  467. CComPtr<IXMLDOMNode> spXMLDOMNodeNameval;
  468. hr = XML_CreateDOMNode(pXMLDoc, NODE_TEXT, NULL, &spXMLDOMNodeNameval);
  469. RETURN_IF_FAILED(hr);
  470. CComVariant val = lpszNodeData;
  471. spXMLDOMNodeNameval->put_nodeTypedValue(val);
  472. hr = XML_AppendChildDOMNode(spXMLDOMNodeName, spXMLDOMNodeNameval);
  473. RETURN_IF_FAILED(hr);
  474. (*ppNode) = spXMLDOMNodeName;
  475. (*ppNode)->AddRef();
  476. return hr;
  477. }
  478. HRESULT XML_CreateStructDataNode(IXMLDOMDocument* pXMLDoc,
  479. LPCWSTR lpszNodeTag,
  480. BYTE* pByte, ULONG nBytes,
  481. IXMLDOMNode** ppNode)
  482. {
  483. CComBSTR bstr;
  484. HRESULT hr = EncodeBlobToBSTR(pByte, nBytes, &bstr);
  485. RETURN_IF_FAILED(hr);
  486. return XML_CreateTextDataNode(pXMLDoc, lpszNodeTag, bstr, ppNode);
  487. }
  488. HRESULT XML_CreateBOOLDataNode(IXMLDOMDocument* pXMLDoc,
  489. LPCWSTR lpszNodeTag,
  490. BOOL b,
  491. IXMLDOMNode** ppNode)
  492. {
  493. CComBSTR bstr;
  494. HRESULT hr = EncodeBoolToBSTR(b, &bstr);
  495. RETURN_IF_FAILED(hr);
  496. return XML_CreateTextDataNode(pXMLDoc, lpszNodeTag, bstr, ppNode);
  497. }
  498. HRESULT XML_CreateDWORDDataNode(IXMLDOMDocument* pXMLDoc,
  499. LPCWSTR lpszNodeTag,
  500. DWORD dwVal,
  501. IXMLDOMNode** ppNode)
  502. {
  503. CString szTemp;
  504. szTemp.Format(L"%d", dwVal);
  505. CComBSTR bstr;
  506. bstr = szTemp.AllocSysString();
  507. return XML_CreateTextDataNode(pXMLDoc, lpszNodeTag, bstr, ppNode);
  508. }
  509. HRESULT XML_AppendStructDataNode(IXMLDOMDocument* pXMLDoc,
  510. IXMLDOMNode* pXMLNode,
  511. LPCWSTR lpszNodeTag,
  512. BYTE* pByte,
  513. ULONG nBytes)
  514. {
  515. CComPtr<IXMLDOMNode> spXMLDOMNodeName;
  516. HRESULT hr = XML_CreateStructDataNode(pXMLDoc, lpszNodeTag, pByte, nBytes, &spXMLDOMNodeName);
  517. RETURN_IF_FAILED(hr);
  518. return XML_AppendChildDOMNode(pXMLNode, spXMLDOMNodeName);
  519. }
  520. HRESULT XML_AppendTextDataNode(IXMLDOMDocument* pXMLDoc,
  521. IXMLDOMNode* pXMLNode,
  522. LPCWSTR lpszNodeTag,
  523. LPCWSTR lpszNodeData)
  524. {
  525. CComPtr<IXMLDOMNode> spXMLDOMNodeName;
  526. HRESULT hr = XML_CreateTextDataNode(pXMLDoc, lpszNodeTag, lpszNodeData, &spXMLDOMNodeName);
  527. RETURN_IF_FAILED(hr);
  528. return hr = XML_AppendChildDOMNode(pXMLNode, spXMLDOMNodeName);
  529. }
  530. HRESULT XML_AppendBOOLDataNode(IXMLDOMDocument* pXMLDoc,
  531. IXMLDOMNode* pXMLNode,
  532. LPCWSTR lpszNodeTag,
  533. BOOL b)
  534. {
  535. CComPtr<IXMLDOMNode> spXMLDOMNodeName;
  536. HRESULT hr = XML_CreateBOOLDataNode(pXMLDoc, lpszNodeTag, b, &spXMLDOMNodeName);
  537. RETURN_IF_FAILED(hr);
  538. return hr = XML_AppendChildDOMNode(pXMLNode, spXMLDOMNodeName);
  539. }
  540. HRESULT XML_AppendDWORDDataNode(IXMLDOMDocument* pXMLDoc,
  541. IXMLDOMNode* pXMLNode,
  542. LPCWSTR lpszNodeTag,
  543. DWORD dwVal)
  544. {
  545. CComPtr<IXMLDOMNode> spXMLDOMNodeName;
  546. HRESULT hr = XML_CreateDWORDDataNode(pXMLDoc, lpszNodeTag, dwVal, &spXMLDOMNodeName);
  547. RETURN_IF_FAILED(hr);
  548. return XML_AppendChildDOMNode(pXMLNode, spXMLDOMNodeName);
  549. }