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.

356 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. utils.cpp
  5. Abstract:
  6. Utilities for the BITS server extensions
  7. --*/
  8. #include "precomp.h"
  9. const char *LookupHTTPStatusCodeText(
  10. DWORD HttpCode
  11. )
  12. {
  13. switch( HttpCode )
  14. {
  15. case 100: return "100 Continue";
  16. case 101: return "101 Switching Protocols";
  17. case 200: return "200 OK";
  18. case 201: return "201 Created";
  19. case 202: return "202 Accepted";
  20. case 203: return "203 Non-Authoritative Information";
  21. case 204: return "204 No Content";
  22. case 205: return "205 Reset Content";
  23. case 206: return "206 Partial Content";
  24. case 300: return "300 Multiple Choices";
  25. case 301: return "301 Moved Permanently";
  26. case 302: return "302 Found";
  27. case 303: return "303 See Other";
  28. case 304: return "304 Not Modified";
  29. case 305: return "305 Use Proxy";
  30. case 306: return "306 (Unused)";
  31. case 307: return "307 Temporary Redirect";
  32. case 400: return "400 Bad Request";
  33. case 401: return "401 Unauthorized";
  34. case 402: return "402 Payment Required";
  35. case 403: return "403 Forbidden";
  36. case 404: return "404 Not Found";
  37. case 405: return "405 Method Not Allowed";
  38. case 406: return "406 Not Acceptable";
  39. case 407: return "407 Proxy Authentication Required";
  40. case 408: return "408 Request Timeout";
  41. case 409: return "409 Conflict";
  42. case 410: return "410 Gone";
  43. case 411: return "411 Length Required";
  44. case 412: return "412 Precondition Failed";
  45. case 413: return "413 Request Entity Too Large";
  46. case 414: return "414 Request-URI Too Long";
  47. case 415: return "415 Unsupported Media Type";
  48. case 416: return "416 Requested Range Not Satisfiable";
  49. case 417: return "417 Expectation Failed";
  50. case 500: return "500 Internal Server Error";
  51. case 501: return "501 Not Implemented";
  52. case 502: return "502 Bad Gateway";
  53. case 503: return "503 Service Unavailable";
  54. case 504: return "504 Gateway Timeout";
  55. case 505: return "505 HTTP Version Not Supported";
  56. default:
  57. return "";
  58. }
  59. }
  60. void
  61. ServerException::SendErrorResponse(
  62. EXTENSION_CONTROL_BLOCK * ExtensionControlBlock
  63. ) const
  64. {
  65. char Headers[255];
  66. StringCbPrintfA(
  67. Headers,
  68. sizeof( Headers ),
  69. "Pragma: no-cache\r\n"
  70. "BITS-packet-type: Ack\r\n"
  71. "BITS-Error: 0x%8.8X\r\n"
  72. "\r\n",
  73. m_Code );
  74. ExtensionControlBlock->dwHttpStatusCode = m_HttpCode;
  75. BOOL Result;
  76. BOOL KeepConnection;
  77. Result =
  78. (ExtensionControlBlock->ServerSupportFunction)(
  79. ExtensionControlBlock->ConnID,
  80. HSE_REQ_IS_KEEP_CONN,
  81. &KeepConnection,
  82. NULL,
  83. NULL );
  84. if ( !Result )
  85. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  86. // IIS5.0(Win2k) has a bug where KeepConnect is returned as -1
  87. // to keep the connection alive. Apparently, this confuses the
  88. // HSE_REQ_SEND_RESPONSE_HEADER_EX call. Bash the value into a real bool.
  89. KeepConnection = KeepConnection ? 1 : 0;
  90. HSE_SEND_HEADER_EX_INFO HeaderInfo;
  91. HeaderInfo.pszStatus = LookupHTTPStatusCodeText( m_HttpCode );
  92. HeaderInfo.cchStatus = strlen( HeaderInfo.pszStatus );
  93. HeaderInfo.pszHeader = Headers;
  94. HeaderInfo.cchHeader = strlen( Headers );
  95. HeaderInfo.fKeepConn = KeepConnection;
  96. Result =
  97. (ExtensionControlBlock->ServerSupportFunction)(
  98. ExtensionControlBlock->ConnID,
  99. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  100. &HeaderInfo,
  101. NULL,
  102. NULL );
  103. if ( !Result )
  104. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  105. }
  106. DWORD
  107. ServerException::MapStatus( HRESULT Hr ) const
  108. {
  109. switch( Hr )
  110. {
  111. case E_INVALIDARG: return 400;
  112. // case HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ): return 400;
  113. case HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ): return 404;
  114. case HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ): return 404;
  115. case HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ): return 403;
  116. // case E_ACCESSDENIED: return 401;
  117. default: return 500;
  118. }
  119. }
  120. void * _cdecl ::operator new( size_t Size )
  121. {
  122. void *Memory = HeapAlloc( GetProcessHeap(), 0, Size );
  123. if ( !Memory )
  124. {
  125. Log( LOG_ERROR, "Out of memory!\n" );
  126. throw ServerException( ERROR_NOT_ENOUGH_MEMORY );
  127. }
  128. return Memory;
  129. }
  130. void _cdecl ::operator delete( void *Memory )
  131. {
  132. if ( !Memory )
  133. return;
  134. HeapFree( GetProcessHeap(), 0, Memory );
  135. }
  136. StringHandle
  137. GetMetaDataString(
  138. IMSAdminBase *IISAdminBase,
  139. METADATA_HANDLE Handle,
  140. LPCWSTR Path,
  141. DWORD dwIdentifier,
  142. LPCSTR DefaultValue )
  143. {
  144. HRESULT Hr;
  145. DWORD BufferRequired = 0;
  146. StringHandleW Data;
  147. METADATA_RECORD MdRecord;
  148. MdRecord.dwMDAttributes = METADATA_INHERIT;
  149. MdRecord.dwMDUserType = ALL_METADATA;
  150. MdRecord.dwMDDataType = STRING_METADATA;
  151. MdRecord.dwMDIdentifier = dwIdentifier;
  152. MdRecord.dwMDDataLen = 0;
  153. MdRecord.pbMDData = (PBYTE)NULL;
  154. MdRecord.dwMDDataTag = 0;
  155. Hr =
  156. IISAdminBase->GetData(
  157. Handle,
  158. Path,
  159. &MdRecord,
  160. &BufferRequired );
  161. if ( SUCCEEDED( Hr ) )
  162. return (StringHandle)Data;
  163. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  164. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  165. return (StringHandle)DefaultValue;
  166. if ( Hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) )
  167. throw ServerException( Hr );
  168. MdRecord.pbMDData = (PBYTE)Data.AllocBuffer( BufferRequired / 2 );
  169. MdRecord.dwMDDataLen = BufferRequired;
  170. Hr =
  171. IISAdminBase->GetData(
  172. Handle,
  173. Path,
  174. &MdRecord,
  175. &BufferRequired );
  176. if ( FAILED( Hr ) )
  177. throw ServerException( Hr );
  178. Data.SetStringSize();
  179. return (StringHandle)Data;
  180. }
  181. DWORD
  182. GetMetaDataDWORD(
  183. IMSAdminBase *IISAdminBase,
  184. METADATA_HANDLE Handle,
  185. LPCWSTR Path,
  186. DWORD dwIdentifier,
  187. DWORD DefaultValue )
  188. {
  189. DWORD BufferRequired;
  190. DWORD MetabaseValue;
  191. METADATA_RECORD MdRecord;
  192. memset( &MdRecord, 0, sizeof( MdRecord ) );
  193. MdRecord.dwMDAttributes = METADATA_INHERIT;
  194. MdRecord.dwMDUserType = ALL_METADATA;
  195. MdRecord.dwMDDataType = DWORD_METADATA;
  196. MdRecord.dwMDIdentifier = dwIdentifier;
  197. MdRecord.dwMDDataLen = sizeof(MetabaseValue);
  198. MdRecord.pbMDData = (PBYTE)&MetabaseValue;
  199. HRESULT Hr =
  200. IISAdminBase->GetData(
  201. Handle,
  202. Path,
  203. &MdRecord,
  204. &BufferRequired );
  205. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  206. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  207. return DefaultValue;
  208. if ( FAILED( Hr ) )
  209. throw ServerException( Hr );
  210. return MetabaseValue;
  211. }
  212. StringHandle
  213. BITSUnicodeToStringHandle( const WCHAR *pStr )
  214. {
  215. StringHandle RetValString;
  216. int RetVal =
  217. WideCharToMultiByte(
  218. CP_ACP,
  219. 0,
  220. pStr,
  221. -1,
  222. NULL,
  223. 0,
  224. NULL,
  225. NULL );
  226. if ( !RetVal )
  227. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  228. char *pRetBuffer = RetValString.AllocBuffer( RetVal );
  229. RetVal =
  230. WideCharToMultiByte(
  231. CP_ACP,
  232. 0,
  233. pStr,
  234. -1,
  235. pRetBuffer,
  236. RetVal,
  237. NULL,
  238. NULL );
  239. if ( !RetVal )
  240. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  241. RetValString.SetStringSize();
  242. return RetValString;
  243. }
  244. StringHandle
  245. BITSUrlCombine(
  246. const char *Base,
  247. const char *Relative,
  248. DWORD dwFlags )
  249. {
  250. DWORD dwCombined = 0;
  251. HRESULT Hr =
  252. UrlCombine(
  253. Base,
  254. Relative,
  255. NULL,
  256. &dwCombined,
  257. dwFlags );
  258. if ( FAILED(Hr) && ( Hr != E_POINTER ) )
  259. throw ServerException( Hr );
  260. StringHandle RetVal;
  261. char *Buffer = RetVal.AllocBuffer( dwCombined + 1 );
  262. Hr =
  263. UrlCombine(
  264. Base,
  265. Relative,
  266. Buffer,
  267. &dwCombined,
  268. dwFlags );
  269. if ( FAILED(Hr) )
  270. throw ServerException( Hr );
  271. RetVal.SetStringSize();
  272. return RetVal;
  273. }
  274. StringHandle
  275. BITSUrlCanonicalize(
  276. const char *URL,
  277. DWORD dwFlags )
  278. {
  279. return
  280. BITSUrlCombine(
  281. "",
  282. URL,
  283. dwFlags );
  284. }