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.

306 lines
8.4 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: U D H I U T I L . C P P
  7. //
  8. // Contents: Implementation of various utility functions used by the
  9. // UPnP Device Host ISAPI extension
  10. //
  11. // Notes:
  12. //
  13. // Author: spather 2000/09/8
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include <httpext.h>
  19. #include "wininet.h"
  20. #include "udhiutil.h"
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Function: bSendResponseToClient
  24. //
  25. // Purpose: Sends an HTTP response to the originator of a request
  26. //
  27. // Arguments:
  28. // pecb [in] The extension control block for the request
  29. // pszStatus [in] HTTP status string e.g. "200 OK" or "400 Bad Request"
  30. // cchHeaders [in] Number of characters in pszHeaders string
  31. // pszHeaders [in] Headers string e.g. "Content-type: text/html\r\n\r\n"
  32. // cchBody [in] Number of bytes in pszBody
  33. // pszBody [in] Response body (may be NULL to send no body)
  34. //
  35. // Returns:
  36. // TRUE if successful
  37. // FALSE if unsuccessful (call GetLastError() to get error info)
  38. //
  39. // Author: spather 2000/09/7
  40. //
  41. // Notes:
  42. // All strings passed in must be NULL terminated.
  43. // pszHeaders string may contain multiple headers separated by \r\n pairs.
  44. // pszHeaders string must end in "\r\n\r\n" as required by HTTP
  45. // If a body is specified at pszBody, the pszHeaders string should contain
  46. // a Content-Length header.
  47. //
  48. BOOL
  49. bSendResponseToClient(
  50. IN LPEXTENSION_CONTROL_BLOCK pecb,
  51. IN LPCSTR pcszStatus,
  52. IN DWORD cchHeaders,
  53. IN LPCSTR pcszHeaders,
  54. IN DWORD cchBody,
  55. IN LPCSTR pcszBody)
  56. {
  57. BOOL bRet = TRUE;
  58. HSE_SEND_HEADER_EX_INFO HeaderExInfo;
  59. AssertSz(pecb,
  60. "bSendResponseToClient(): NULL pecb");
  61. AssertSz(pcszStatus,
  62. "bSendResponseToClient(): NULL pcszStatus");
  63. AssertSz(pcszHeaders,
  64. "bSendResponseToClient(): NULL pcszHeaders");
  65. BOOL fKeepConn = FALSE;
  66. bRet = pecb->ServerSupportFunction(
  67. pecb->ConnID,
  68. HSE_REQ_IS_KEEP_CONN,
  69. &fKeepConn,
  70. NULL,
  71. NULL);
  72. //
  73. // Prepare headers.
  74. //
  75. HeaderExInfo.pszStatus = pcszStatus;
  76. HeaderExInfo.pszHeader = pcszHeaders;
  77. HeaderExInfo.cchStatus = lstrlenA(pcszStatus);
  78. HeaderExInfo.cchHeader = cchHeaders;
  79. HeaderExInfo.fKeepConn = fKeepConn;
  80. //
  81. // Send the headers.
  82. //
  83. TraceTag(ttidUDHISAPI,
  84. "bSendResponseHeaders(): "
  85. "Sending Status \"%s\" and Headers:\n%s",
  86. pcszStatus,
  87. pcszHeaders);
  88. bRet = pecb->ServerSupportFunction(
  89. pecb->ConnID,
  90. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  91. &HeaderExInfo,
  92. NULL,
  93. NULL);
  94. if (bRet)
  95. {
  96. //
  97. // Send the body if there is one.
  98. //
  99. if (pcszBody)
  100. {
  101. DWORD dwBytesToWrite = cchBody;
  102. bRet = pecb->WriteClient(pecb->ConnID,
  103. (LPVOID) pcszBody,
  104. &dwBytesToWrite,
  105. HSE_IO_SYNC);
  106. if (bRet)
  107. {
  108. AssertSz((cchBody == dwBytesToWrite),
  109. "bSendResponseToClient(): "
  110. "Didn't write the correct number of bytes");
  111. }
  112. else
  113. {
  114. TraceLastWin32Error("bSendResponseToClient(): "
  115. "Failed to send response body");
  116. }
  117. }
  118. }
  119. else
  120. {
  121. TraceLastWin32Error("bSendResponseToClient(): "
  122. "Failed to send response headers");
  123. }
  124. TraceTag(ttidUDHISAPI,
  125. "bSendResponseToClient(): "
  126. "Exiting - returning %d",
  127. bRet);
  128. return bRet;
  129. }
  130. VOID
  131. SendSimpleResponse(
  132. IN LPEXTENSION_CONTROL_BLOCK pecb,
  133. IN DWORD dwStatusCode)
  134. {
  135. BOOL fRet;
  136. static const CHAR c_szErrorHeaders[] = "\r\n";
  137. LPSTR szaResponse;
  138. switch(dwStatusCode)
  139. {
  140. case HTTP_STATUS_OK:
  141. szaResponse = "200 OK";
  142. break;
  143. case HTTP_STATUS_CREATED:
  144. szaResponse = "201 Created";
  145. break;
  146. case HTTP_STATUS_ACCEPTED:
  147. szaResponse = "202 Accepted";
  148. break;
  149. case HTTP_STATUS_NO_CONTENT:
  150. szaResponse = "204 No Content";
  151. break;
  152. case HTTP_STATUS_AMBIGUOUS:
  153. szaResponse = "300 Multiple";
  154. break;
  155. case HTTP_STATUS_MOVED:
  156. szaResponse = "301 Moved Permanently";
  157. break;
  158. case HTTP_STATUS_REDIRECT:
  159. szaResponse = "302 Moved Temporarily";
  160. break;
  161. case HTTP_STATUS_NOT_MODIFIED:
  162. szaResponse = "304 Not Modified";
  163. break;
  164. case HTTP_STATUS_BAD_REQUEST:
  165. szaResponse = "400 Bad Request";
  166. break;
  167. case HTTP_STATUS_DENIED:
  168. szaResponse = "401 Unauthorized";
  169. break;
  170. case HTTP_STATUS_FORBIDDEN:
  171. szaResponse = "403 Forbidden";
  172. break;
  173. case HTTP_STATUS_NOT_FOUND:
  174. szaResponse = "404 Not Found";
  175. break;
  176. case HTTP_STATUS_BAD_METHOD:
  177. szaResponse = "405 Method Not Allowed";
  178. break;
  179. case HTTP_STATUS_LENGTH_REQUIRED:
  180. szaResponse = "411 The Server Refused to Accept Request Without a Length";
  181. break;
  182. case HTTP_STATUS_PRECOND_FAILED:
  183. szaResponse = "412 Precondition Failed";
  184. break;
  185. case HTTP_STATUS_UNSUPPORTED_MEDIA:
  186. szaResponse = "415 Unsupported Media Type";
  187. break;
  188. case HTTP_STATUS_SERVER_ERROR:
  189. szaResponse = "500 Internal Server Error";
  190. break;
  191. case HTTP_STATUS_NOT_SUPPORTED:
  192. szaResponse = "501 Not Implemented";
  193. break;
  194. case HTTP_STATUS_BAD_GATEWAY:
  195. szaResponse = "502 Bad Gateway";
  196. break;
  197. case HTTP_STATUS_SERVICE_UNAVAIL:
  198. szaResponse = "503 Service Unavailable";
  199. break;
  200. default:
  201. AssertSz(FALSE, "You must pass in a known HTTP status code to "
  202. "SendErrorResponse()");
  203. break;
  204. }
  205. if (bSendResponseToClient(pecb, szaResponse, lstrlenA(c_szErrorHeaders),
  206. c_szErrorHeaders, 0, NULL))
  207. {
  208. pecb->dwHttpStatusCode = dwStatusCode;
  209. }
  210. DWORD dwHseStatus;
  211. dwHseStatus = (dwStatusCode >= HTTP_STATUS_BAD_REQUEST) ?
  212. HSE_STATUS_ERROR : HSE_STATUS_SUCCESS;
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Function: DwQueryHeader
  217. //
  218. // Purpose: Queries one of the headers sent in an HTTP request
  219. //
  220. // Arguments:
  221. // pecb [in] Exetnsion control block
  222. // szaHeader [in] Header name to query
  223. // pszaResult [out] Returns value of header or NULL if not present
  224. //
  225. // Returns: ERROR_SUCCESS, ERROR_OUTOFMEMORY, or an ISAPI error code
  226. //
  227. // Author: danielwe 14 Aug 2000
  228. //
  229. // Notes:
  230. //
  231. DWORD DwQueryHeader(LPEXTENSION_CONTROL_BLOCK pecb, LPCSTR szaHeader,
  232. LPSTR *pszaResult)
  233. {
  234. DWORD cbHeader = 0;
  235. LPSTR szaBuf = NULL;
  236. DWORD dwReturn = ERROR_SUCCESS;
  237. Assert(pszaResult);
  238. *pszaResult = 0;
  239. if (!pecb->GetServerVariable(pecb->ConnID, (LPSTR)szaHeader, NULL, &cbHeader))
  240. {
  241. dwReturn = GetLastError();
  242. if (dwReturn == ERROR_INSUFFICIENT_BUFFER)
  243. {
  244. szaBuf = new CHAR[cbHeader / sizeof(CHAR)];
  245. if (szaBuf)
  246. {
  247. if (!pecb->GetServerVariable(pecb->ConnID, (LPSTR)szaHeader,
  248. (LPVOID)szaBuf, &cbHeader))
  249. {
  250. dwReturn = GetLastError();
  251. }
  252. else
  253. {
  254. *pszaResult = szaBuf;
  255. dwReturn = ERROR_SUCCESS;
  256. }
  257. }
  258. else
  259. {
  260. dwReturn = ERROR_OUTOFMEMORY;
  261. }
  262. }
  263. else
  264. {
  265. AssertSz(dwReturn != ERROR_SUCCESS, "How can it succeed if I gave"
  266. " it a NULL pointer!");
  267. }
  268. }
  269. return dwReturn;
  270. }