Source code of Windows XP (NT5)
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.

912 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: V A L I D A T E S O A P . C P P
  7. //
  8. // Contents: Implementation of SOAP request validation.
  9. //
  10. // Notes:
  11. //
  12. // Author: spather 2000/11/8
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include <httpext.h>
  18. #include "hostp.h"
  19. #include "ncxml.h"
  20. #include "ncbase.h"
  21. #include "ValidateSOAP.h"
  22. const WCHAR CSZ_SOAP_NAMESPACE_URI[] =
  23. L"http://schemas.xmlsoap.org/soap/envelope/";
  24. const WCHAR CSZ_SOAP_ENCODING_STYLE_URI[] =
  25. L"http://schemas.xmlsoap.org/soap/encoding/";
  26. HRESULT
  27. HrValidateArguments(
  28. IN IXMLDOMNode * pxdnAction,
  29. IN IXMLDOMNodeList * pxdnlArgs,
  30. IN IUPnPServiceDescriptionInfo * pServiceDescInfo)
  31. {
  32. HRESULT hr = S_OK;
  33. BSTR bstrActionName = NULL;
  34. hr = pxdnAction->get_baseName(&bstrActionName);
  35. if (SUCCEEDED(hr))
  36. {
  37. BOOL fIsQueryStateVariable = FALSE;
  38. DWORD cInArgs = 0;
  39. BSTR * rgbstrNames = NULL;
  40. BSTR * rgbstrTypes = NULL;
  41. Assert(bstrActionName);
  42. if (0 == lstrcmpW(bstrActionName, L"QueryStateVariable"))
  43. {
  44. fIsQueryStateVariable = TRUE;
  45. cInArgs = 1;
  46. }
  47. else
  48. {
  49. fIsQueryStateVariable = FALSE;
  50. hr = pServiceDescInfo->GetInputArgumentNamesAndTypes(bstrActionName,
  51. &cInArgs,
  52. &rgbstrNames,
  53. &rgbstrTypes);
  54. }
  55. if (SUCCEEDED(hr))
  56. {
  57. long listLength = 0;
  58. hr = pxdnlArgs->get_length(&listLength);
  59. if (SUCCEEDED(hr))
  60. {
  61. if ((DWORD)listLength == cInArgs)
  62. {
  63. if (cInArgs > 0)
  64. {
  65. for (DWORD i = 0; i < cInArgs; i++)
  66. {
  67. IXMLDOMNode * pxdnArg = NULL;
  68. hr = pxdnlArgs->get_item(i, &pxdnArg);
  69. if (SUCCEEDED(hr))
  70. {
  71. BSTR bstrArgName = NULL;
  72. // Check that the name matches.
  73. Assert(pxdnArg);
  74. hr = pxdnArg->get_baseName(&bstrArgName);
  75. if (SUCCEEDED(hr))
  76. {
  77. Assert(bstrArgName);
  78. if (fIsQueryStateVariable)
  79. {
  80. if (0 == lstrcmpiW(bstrArgName,
  81. L"varName"))
  82. {
  83. hr = S_OK;
  84. }
  85. else
  86. {
  87. hr = E_FAIL;
  88. TraceError("HrValidateArguments(): "
  89. "Invalid argument name",
  90. hr);
  91. }
  92. }
  93. else
  94. {
  95. if (0 == lstrcmpiW(bstrArgName,
  96. rgbstrNames[i]))
  97. {
  98. hr = S_OK;
  99. }
  100. else
  101. {
  102. hr = E_FAIL;
  103. TraceError("HrValidateArguments(): "
  104. "Invalid argument name",
  105. hr);
  106. }
  107. }
  108. SysFreeString(bstrArgName);
  109. }
  110. pxdnArg->Release();
  111. }
  112. else
  113. {
  114. TraceError("HrValidateArguments(): "
  115. "Failed to get item",
  116. hr);
  117. }
  118. }
  119. }
  120. }
  121. else
  122. {
  123. hr = E_FAIL;
  124. TraceError("HrValidateArguments(): "
  125. "Wrong number of input arguments in request",
  126. hr);
  127. }
  128. }
  129. else
  130. {
  131. TraceError("HrValidateArguments(): "
  132. "Failed to get list length",
  133. hr);
  134. }
  135. if (FALSE == fIsQueryStateVariable)
  136. {
  137. if (cInArgs > 0)
  138. {
  139. for (DWORD i = 0; i < cInArgs; i++)
  140. {
  141. SysFreeString(rgbstrNames[i]);
  142. rgbstrNames[i] = NULL;
  143. SysFreeString(rgbstrTypes[i]);
  144. rgbstrTypes[i] = NULL;
  145. }
  146. CoTaskMemFree(rgbstrNames);
  147. rgbstrNames = NULL;
  148. CoTaskMemFree(rgbstrTypes);
  149. rgbstrTypes = NULL;
  150. }
  151. }
  152. }
  153. SysFreeString(bstrActionName);
  154. }
  155. else
  156. {
  157. TraceError("HrValidateArguments(): "
  158. "Failed to get action name",
  159. hr);
  160. }
  161. TraceError("HrValidateArguments(): "
  162. "Exiting",
  163. hr);
  164. return hr;
  165. }
  166. HRESULT
  167. HrValidateActionName(
  168. IN IXMLDOMNode * pxdnAction,
  169. IN LPWSTR szSOAPActionHeader)
  170. {
  171. HRESULT hr = S_OK;
  172. LPWSTR szStrippedHeader = NULL;
  173. DWORD cchSOAPActionHeader = 0;
  174. LPWSTR szActionName = NULL;
  175. cchSOAPActionHeader = lstrlenW(szSOAPActionHeader);
  176. // Due to bugs in some SOAP implementations (specifically, the URT, not us)
  177. // the SOAPActionHeader may or may not have double-quotes around it. We'll
  178. // just remove them here if they are there (they should be, according to
  179. // the SOAP spec).
  180. if ((L'"' == szSOAPActionHeader[0]) &&
  181. (L'"' == szSOAPActionHeader[cchSOAPActionHeader-1]))
  182. {
  183. // Modify the string in place - insert a NULL where the close
  184. // quote is, and start the string 1 character from the beginning.
  185. // Doing it this way, rather than copying the string saves us 1
  186. // memory allocation.
  187. szSOAPActionHeader[cchSOAPActionHeader-1] = UNICODE_NULL;
  188. szStrippedHeader = szSOAPActionHeader+1;
  189. }
  190. else
  191. {
  192. szStrippedHeader = szSOAPActionHeader;
  193. }
  194. // Check that the action name matches the SOAPAction header.
  195. // SOAPAction header is of the form servicetype#actionName.
  196. szActionName = wcsstr(szStrippedHeader, L"#");
  197. if (szActionName)
  198. {
  199. BSTR bstrActionName = NULL;
  200. szActionName++; // Advance to the character after the "#"
  201. hr = pxdnAction->get_baseName(&bstrActionName);
  202. if (S_OK == hr)
  203. {
  204. if (0 == lstrcmpiW(bstrActionName, szActionName))
  205. {
  206. hr = S_OK;
  207. TraceTag(ttidValidate,
  208. "HrValidateActionName(): "
  209. "Action node name and SOAPAction header value match!");
  210. }
  211. else
  212. {
  213. hr = E_FAIL;
  214. TraceError("HrValidateActionName(): "
  215. "Action node name did not match SOAPAction header",
  216. hr);
  217. }
  218. SysFreeString(bstrActionName);
  219. }
  220. else
  221. {
  222. TraceError("HrValidateActionName(): "
  223. "Failed to get node name",
  224. hr);
  225. }
  226. }
  227. else
  228. {
  229. hr = E_FAIL;
  230. TraceError("HrValidateActionName(): "
  231. "SOAPActionHeader did not contain \"#\" character",
  232. hr);
  233. }
  234. TraceError("HrValidateActionName(): "
  235. "Exiting",
  236. hr);
  237. return hr;
  238. }
  239. HRESULT
  240. HrValidateBody(
  241. IN IXMLDOMNode * pxdnBody,
  242. IN IUPnPServiceDescriptionInfo * pServiceDescInfo,
  243. IN LPWSTR szSOAPActionHeader)
  244. {
  245. HRESULT hr = S_OK;
  246. IXMLDOMNode * pxdnAction = NULL;
  247. hr = pxdnBody->get_firstChild(&pxdnAction);
  248. if (SUCCEEDED(hr))
  249. {
  250. if (pxdnAction)
  251. {
  252. hr = HrValidateActionName(pxdnAction, szSOAPActionHeader);
  253. if (SUCCEEDED(hr))
  254. {
  255. IXMLDOMNodeList * pxdnlArgs = NULL;
  256. hr = pxdnAction->get_childNodes(&pxdnlArgs);
  257. if (SUCCEEDED(hr))
  258. {
  259. Assert(pxdnlArgs);
  260. hr = HrValidateArguments(pxdnAction,
  261. pxdnlArgs,
  262. pServiceDescInfo);
  263. pxdnlArgs->Release();
  264. }
  265. }
  266. // Finally, if all the above succeeded, check that the
  267. // action element does not have a sibling (there should
  268. // only be one child of the body element).
  269. if (SUCCEEDED(hr))
  270. {
  271. IXMLDOMNode * pxdnSibling = NULL;
  272. hr = pxdnAction->get_nextSibling(&pxdnSibling);
  273. if (S_FALSE == hr)
  274. {
  275. Assert(NULL == pxdnSibling);
  276. hr = S_OK;
  277. TraceTag(ttidValidate,
  278. "HrValidateBody(): "
  279. "Body is valid!");
  280. }
  281. else
  282. {
  283. if (SUCCEEDED(hr))
  284. {
  285. Assert(pxdnSibling);
  286. pxdnSibling->Release();
  287. hr = E_FAIL;
  288. TraceError("HrValidateBody(): "
  289. "Body element had more than one child",
  290. hr);
  291. }
  292. else
  293. {
  294. TraceError("HrValidateBody(): "
  295. "Failure trying to get next sibling",
  296. hr);
  297. }
  298. }
  299. }
  300. pxdnAction->Release();
  301. }
  302. else
  303. {
  304. hr = E_FAIL;
  305. TraceError("HrValidateBody(): "
  306. "Body element was empty",
  307. hr);
  308. }
  309. }
  310. else
  311. {
  312. TraceError("HrValidateBody(): "
  313. "Failed to get first child of body element",
  314. hr);
  315. }
  316. TraceError("HrValidateBody(): "
  317. "Exiting",
  318. hr);
  319. return hr;
  320. }
  321. HRESULT
  322. HrValidateSOAPHeader(
  323. IN IXMLDOMNode * pxdnHeader)
  324. {
  325. HRESULT hr = S_OK;
  326. IXMLDOMNode * pxdnChild = NULL;
  327. // A request may have headers as long as none of them have the
  328. // "mustUnderstand" attribute set because we don't understand any
  329. // headers.
  330. hr = pxdnHeader->get_firstChild(&pxdnChild);
  331. while (SUCCEEDED(hr) && pxdnChild)
  332. {
  333. IXMLDOMNode * pxdnNextSibling = NULL;
  334. BSTR bstrMustUnderstand = NULL;
  335. hr = HrGetTextValueFromAttribute(pxdnChild,
  336. L"mustUnderstand",
  337. &bstrMustUnderstand);
  338. if (SUCCEEDED(hr))
  339. {
  340. if (NULL == bstrMustUnderstand)
  341. {
  342. hr = S_OK;
  343. TraceTag(ttidValidate,
  344. "HrValidateSOAPHeader(): "
  345. "Found header without mustUnderstand attribute - ok!");
  346. }
  347. else
  348. {
  349. if (0 == lstrcmpW(bstrMustUnderstand, L"0"))
  350. {
  351. hr = S_OK;
  352. TraceTag(ttidValidate,
  353. "HrValidateSOAPHeader(): "
  354. "Found header with mustUnderstand "
  355. "attribute == 0 - ok!");
  356. }
  357. else if (0 == lstrcmpW(bstrMustUnderstand, L"1"))
  358. {
  359. hr = E_FAIL;
  360. TraceError("HrValidateSOAPHeader(): "
  361. "Found header with mustUnderstand attribute set",
  362. hr);
  363. }
  364. else
  365. {
  366. hr = E_FAIL;
  367. TraceError("HrValidateSOAPHeader(): "
  368. "Found header with invalid "
  369. "mustUnderstand attribute value",
  370. hr);
  371. }
  372. SysFreeString(bstrMustUnderstand);
  373. }
  374. }
  375. else
  376. {
  377. TraceError("HrValidateSOAPError(): "
  378. "Failed to get mustUnderstand attribute value",
  379. hr);
  380. }
  381. if (FAILED(hr))
  382. {
  383. pxdnChild->Release();
  384. break;
  385. }
  386. hr = pxdnChild->get_nextSibling(&pxdnNextSibling);
  387. pxdnChild->Release();
  388. pxdnChild = pxdnNextSibling;
  389. }
  390. TraceError("HrValidateSOAPHeader(): "
  391. "Exiting",
  392. hr);
  393. return hr;
  394. }
  395. HRESULT
  396. HrValidateSOAPStructure(
  397. IN IXMLDOMNode * pxdnReqEnvelope,
  398. IN IUPnPServiceDescriptionInfo * pServiceDescInfo,
  399. IN LPWSTR szSOAPActionHeader)
  400. {
  401. HRESULT hr = S_OK;
  402. if (FIsThisTheNodeNameWithNamespace(pxdnReqEnvelope,
  403. L"Envelope",
  404. CSZ_SOAP_NAMESPACE_URI))
  405. {
  406. IXMLDOMNode * pxdnChild = NULL;
  407. BOOL bFoundHeader = FALSE;
  408. BOOL bFoundBody = FALSE;
  409. hr = pxdnReqEnvelope->get_firstChild(&pxdnChild);
  410. while (SUCCEEDED(hr) && pxdnChild)
  411. {
  412. IXMLDOMNode * pxdnNextSibling = NULL;
  413. if (FIsThisTheNodeNameWithNamespace(pxdnChild,
  414. L"Header",
  415. CSZ_SOAP_NAMESPACE_URI))
  416. {
  417. if (FALSE == bFoundHeader)
  418. {
  419. bFoundHeader = TRUE;
  420. hr = HrValidateSOAPHeader(pxdnChild);
  421. }
  422. else
  423. {
  424. hr = E_FAIL;
  425. TraceError("HrValidateSOAPStructure(): "
  426. "Duplicate header element found",
  427. hr);
  428. }
  429. }
  430. else if (FIsThisTheNodeNameWithNamespace(pxdnChild,
  431. L"Body",
  432. CSZ_SOAP_NAMESPACE_URI))
  433. {
  434. if (FALSE == bFoundBody)
  435. {
  436. bFoundBody = TRUE;
  437. hr = HrValidateBody(pxdnChild,
  438. pServiceDescInfo,
  439. szSOAPActionHeader);
  440. }
  441. else
  442. {
  443. hr = E_FAIL;
  444. TraceError("HrValidateSOAPStructure(): "
  445. "Duplicate body element found",
  446. hr);
  447. }
  448. }
  449. else
  450. {
  451. hr = E_FAIL;
  452. TraceError("HrValidateSOAPStructure(): "
  453. "Unknown element found inside SOAP envelope",
  454. hr);
  455. }
  456. if (FAILED(hr))
  457. {
  458. pxdnChild->Release();
  459. break;
  460. }
  461. hr = pxdnChild->get_nextSibling(&pxdnNextSibling);
  462. pxdnChild->Release();
  463. pxdnChild = pxdnNextSibling;
  464. }
  465. if (SUCCEEDED(hr))
  466. {
  467. if (FALSE == bFoundBody)
  468. {
  469. hr = E_FAIL;
  470. TraceError("HrValidateSOAPStrucutre(): "
  471. "Request was missing body element",
  472. hr);
  473. }
  474. else
  475. {
  476. hr = S_OK;
  477. TraceTag(ttidValidate,
  478. "HrValidateSOAPStructure(): "
  479. "SOAP structure is valid!");
  480. }
  481. }
  482. }
  483. else
  484. {
  485. hr = E_FAIL;
  486. TraceError("HrValidateSOAPStructure(): "
  487. "Root element is not a SOAP envelope",
  488. hr);
  489. }
  490. TraceError("HrValidateSOAPStructure(): "
  491. "Exiting",
  492. hr);
  493. return hr;
  494. }
  495. HRESULT
  496. HrGetSOAPActionHeader(
  497. IN LPEXTENSION_CONTROL_BLOCK pecb,
  498. OUT LPWSTR * pszSOAPActionHeader)
  499. {
  500. HRESULT hr = S_OK;
  501. LPWSTR szSOAPActionHeader = NULL;
  502. CHAR * szaBuffer = NULL;
  503. DWORD cbBuffer = 0;
  504. BOOL bReturn = FALSE;
  505. // First we need to find the size of buffer we need to get all the HTTP
  506. // headers.
  507. bReturn = pecb->GetServerVariable(pecb->ConnID,
  508. "ALL_RAW",
  509. szaBuffer,
  510. &cbBuffer);
  511. if (FALSE == bReturn)
  512. {
  513. DWORD dwError = 0;
  514. // Expect to be here - we passed in a null buffer and a zero size,
  515. // in order to find what the real size should be.
  516. dwError = GetLastError();
  517. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  518. {
  519. Assert(cbBuffer > 0);
  520. szaBuffer = new CHAR[cbBuffer+1];
  521. if (szaBuffer)
  522. {
  523. bReturn = pecb->GetServerVariable(pecb->ConnID,
  524. "ALL_RAW",
  525. szaBuffer,
  526. &cbBuffer);
  527. if (bReturn)
  528. {
  529. hr = S_OK;
  530. TraceTag(ttidValidate,
  531. "HrGetSOAPActionHeader(): "
  532. "All HTTP Headers:\n%s", szaBuffer);
  533. }
  534. else
  535. {
  536. hr = HrFromLastWin32Error();
  537. TraceError("HrGetSOAPActionHeader(): "
  538. "Failed to get all HTTP headers",
  539. hr);
  540. }
  541. }
  542. else
  543. {
  544. hr = E_OUTOFMEMORY;
  545. TraceError("HrGetSOAPActionHeader(): "
  546. "Failed to allocate buffer for all HTTP headers",
  547. hr);
  548. }
  549. }
  550. else
  551. {
  552. hr = HrFromLastWin32Error();
  553. TraceError("HrGetSOAPActionHeader(): "
  554. "Failed to get buffer size for all HTTP headers",
  555. hr);
  556. }
  557. }
  558. else
  559. {
  560. // Should never be here.
  561. Assert(FALSE);
  562. }
  563. if (SUCCEEDED(hr))
  564. {
  565. CHAR * szaSOAPActionStart = NULL;
  566. // Convert the buffer to uppercase.
  567. for (DWORD i = 0; i < cbBuffer; i++)
  568. {
  569. szaBuffer[i] = (CHAR) toupper(szaBuffer[i]);
  570. }
  571. // Now we need find the SOAPAction header and get it's value.
  572. szaSOAPActionStart = strstr(szaBuffer, "SOAPACTION:");
  573. if (szaSOAPActionStart)
  574. {
  575. // Count the number of characters in the value of the header.
  576. DWORD cbSOAPActionHeader = 0;
  577. CHAR * szaSOAPActionValueStart = NULL;
  578. CHAR * szaTemp = NULL;
  579. szaSOAPActionValueStart = szaSOAPActionStart +
  580. strlen("SOAPACTION:");
  581. while (' ' == *szaSOAPActionValueStart || '\t' == *szaSOAPActionValueStart)
  582. {
  583. szaSOAPActionValueStart++;
  584. }
  585. szaTemp = szaSOAPActionValueStart;
  586. while (('\0' != *szaTemp) &&
  587. ('\r' != *szaTemp) &&
  588. ('\n' != *szaTemp))
  589. {
  590. szaTemp++;
  591. cbSOAPActionHeader++;
  592. }
  593. if (cbSOAPActionHeader > 0)
  594. {
  595. CHAR * szaSOAPActionHeader = NULL;
  596. szaSOAPActionHeader = new CHAR[cbSOAPActionHeader + 1];
  597. if (szaSOAPActionHeader)
  598. {
  599. strncpy(szaSOAPActionHeader,
  600. szaSOAPActionValueStart,
  601. cbSOAPActionHeader);
  602. szaSOAPActionHeader[cbSOAPActionHeader] = '\0';
  603. szSOAPActionHeader = WszFromSz(szaSOAPActionHeader);
  604. if (szSOAPActionHeader)
  605. {
  606. hr = S_OK;
  607. TraceTag(ttidUDHISAPI,
  608. "HrGetSOAPActionHeader(): "
  609. "SOAPAction header value is %S",
  610. szSOAPActionHeader);
  611. }
  612. else
  613. {
  614. hr = E_OUTOFMEMORY;
  615. TraceError("HrGetSOAPActionHeader(): "
  616. "Failed to allocate memory for "
  617. "wide character SOAPAction header",
  618. hr);
  619. }
  620. delete [] szaSOAPActionHeader;
  621. }
  622. else
  623. {
  624. hr = E_OUTOFMEMORY;
  625. TraceError("HrGetSOAPActionHeader(): "
  626. "Failed to allocate memory for SOAPAction header",
  627. hr);
  628. }
  629. }
  630. else
  631. {
  632. hr = E_FAIL;
  633. TraceError("HrGetSOAPActionHeader(): "
  634. "SOAPAction header had no value",
  635. hr);
  636. }
  637. }
  638. else
  639. {
  640. hr = UPNP_E_MISSING_SOAP_ACTION;
  641. TraceError("HrGetSOAPActionHeader(): "
  642. "Could not find SOAPAction header",
  643. hr);
  644. }
  645. }
  646. // Cleanup.
  647. if (szaBuffer)
  648. {
  649. delete [] szaBuffer;
  650. szaBuffer = NULL;
  651. }
  652. // Copy the string to the out parameter if succeeded, otherwise
  653. // clean it up.
  654. if (SUCCEEDED(hr))
  655. {
  656. *pszSOAPActionHeader = szSOAPActionHeader;
  657. }
  658. else
  659. {
  660. // Cleanup.
  661. if (szSOAPActionHeader)
  662. {
  663. delete [] szSOAPActionHeader;
  664. szSOAPActionHeader = NULL;
  665. }
  666. }
  667. TraceError("HrGetSOAPActionHeader(): "
  668. "Exiting",
  669. hr);
  670. return hr;
  671. }
  672. HRESULT
  673. HrValidateContentType(
  674. IN LPEXTENSION_CONTROL_BLOCK pecb)
  675. {
  676. HRESULT hr = S_OK;
  677. BOOL bReturn = FALSE;
  678. const DWORD cdwBufSize = 512;
  679. CHAR szaBuffer[cdwBufSize];
  680. DWORD cbBuffer = cdwBufSize;
  681. LPCSTR cszaExpectedContentType = "text/xml";
  682. bReturn = pecb->GetServerVariable(pecb->ConnID,
  683. "CONTENT_TYPE",
  684. szaBuffer,
  685. &cbBuffer);
  686. if (bReturn)
  687. {
  688. Assert(cbBuffer <= cdwBufSize);
  689. if (0 == strncmp(szaBuffer,
  690. cszaExpectedContentType,
  691. strlen(cszaExpectedContentType)))
  692. {
  693. hr = S_OK;
  694. TraceTag(ttidValidate,
  695. "HrValidateContentType(): "
  696. "Valid content type %s",
  697. szaBuffer);
  698. }
  699. else
  700. {
  701. hr = UPNP_E_INVALID_CONTENT_TYPE;
  702. TraceTag(ttidValidate,
  703. "HrValidateContentType(): "
  704. "Invalid content type %s",
  705. szaBuffer);
  706. }
  707. }
  708. else
  709. {
  710. hr = HrFromLastWin32Error();
  711. TraceError("HrValidateContentType(): "
  712. "Failed to get content type",
  713. hr);
  714. }
  715. TraceError("HrValidateContentType(): "
  716. "Exiting",
  717. hr);
  718. return hr;
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // Function: HrValidateSOAPRequest
  723. //
  724. // Purpose: Validates the structure of a SOAP request.
  725. //
  726. // Arguments:
  727. // pxdnReqEnvelope [in] The XML DOM Node for the SOAP envelope element
  728. // pecb [in] The extension control block for the request
  729. // pServiceDescInfo [in] The service description info object for the
  730. // service at which the request is targeted
  731. //
  732. // Returns:
  733. // If the function succeeds, the return value is S_OK. Otherwise, the
  734. // function returns one of the COM error codes defined in WinError.h.
  735. //
  736. // Author: spather 2000/11/8
  737. //
  738. // Notes:
  739. //
  740. HRESULT
  741. HrValidateSOAPRequest(
  742. IN IXMLDOMNode * pxdnReqEnvelope,
  743. IN LPEXTENSION_CONTROL_BLOCK pecb,
  744. IN IUPnPServiceDescriptionInfo * pServiceDescInfo)
  745. {
  746. HRESULT hr = S_OK;
  747. Assert(pxdnReqEnvelope);
  748. Assert(pecb);
  749. Assert(pServiceDescInfo);
  750. hr = HrValidateContentType(pecb);
  751. if (SUCCEEDED(hr))
  752. {
  753. LPWSTR szSOAPActionHeader = NULL;
  754. hr = HrGetSOAPActionHeader(pecb, &szSOAPActionHeader);
  755. if (SUCCEEDED(hr))
  756. {
  757. Assert(szSOAPActionHeader);
  758. hr = HrValidateSOAPStructure(pxdnReqEnvelope,
  759. pServiceDescInfo,
  760. szSOAPActionHeader);
  761. delete [] szSOAPActionHeader;
  762. }
  763. }
  764. if (E_FAIL == hr)
  765. {
  766. hr = UPNP_E_BAD_REQUEST;
  767. }
  768. TraceError("HrValidateSOAPRequest(): "
  769. "Exiting",
  770. hr);
  771. return hr;
  772. }