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.

745 lines
16 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. http.cxx
  5. Abstract:
  6. Contains methods for HTTP_REQUEST_HANDLE_OBJECT class
  7. Contents:
  8. RMakeHttpReqObjectHandle
  9. HTTP_REQUEST_HANDLE_OBJECT::HTTP_REQUEST_HANDLE_OBJECT
  10. HTTP_REQUEST_HANDLE_OBJECT::~HTTP_REQUEST_HANDLE_OBJECT
  11. HTTP_REQUEST_HANDLE_OBJECT::GetHandle
  12. HTTP_REQUEST_HANDLE_OBJECT::SetProxyName
  13. HTTP_REQUEST_HANDLE_OBJECT::GetProxyName
  14. HTTP_REQUEST_HANDLE_OBJECT::ReuseObject
  15. HTTP_REQUEST_HANDLE_OBJECT::ResetObject
  16. HTTP_REQUEST_HANDLE_OBJECT::UrlCacheUnlock
  17. HTTP_REQUEST_HANDLE_OBJECT::SetAuthenticated
  18. HTTP_REQUEST_HANDLE_OBJECT::IsAuthenticated
  19. Author:
  20. Madan Appiah (madana) 16-Nov-1994
  21. Environment:
  22. User Mode - Win32
  23. Revision History:
  24. Sophia Chung (sophiac) 14-Feb-1995 (added FTP and Archie class impl.)
  25. (code adopted from madana)
  26. --*/
  27. #include <wininetp.h>
  28. //
  29. // functions
  30. //
  31. DWORD
  32. RMakeHttpReqObjectHandle(
  33. IN HINTERNET ParentHandle,
  34. IN OUT HINTERNET * ChildHandle,
  35. IN CLOSE_HANDLE_FUNC wCloseFunc,
  36. IN DWORD dwFlags,
  37. IN DWORD_PTR dwContext
  38. )
  39. /*++
  40. Routine Description:
  41. C-callable wrapper for creating an HTTP_REQUEST_HANDLE_OBJECT
  42. Arguments:
  43. ParentHandle - mapped address of parent (connect) handle
  44. ChildHandle - IN: protocol-specific handle value associated with object
  45. *** NOT USED FOR HTTP ***
  46. OUT: mapped address of HTTP_REQUEST_HANDLE_OBJECT
  47. wCloseFunc - address of protocol-specific function to be called when
  48. object is closed
  49. *** NOT USED FOR HTTP ***
  50. dwFlags - app-supplied flags
  51. dwContext - app-supplied context value
  52. Return Value:
  53. DWORD
  54. Success - ERROR_SUCCESS
  55. Failure - ERROR_NOT_ENOUGH_MEMORY
  56. --*/
  57. {
  58. DWORD error;
  59. HTTP_REQUEST_HANDLE_OBJECT * hHttp;
  60. hHttp = new HTTP_REQUEST_HANDLE_OBJECT(
  61. (INTERNET_CONNECT_HANDLE_OBJECT *)ParentHandle,
  62. *ChildHandle,
  63. wCloseFunc,
  64. dwFlags,
  65. dwContext
  66. );
  67. if (hHttp != NULL) {
  68. error = hHttp->GetStatus();
  69. if (error == ERROR_SUCCESS) {
  70. //
  71. // inform the app of the new handle
  72. //
  73. error = InternetIndicateStatusNewHandle((LPVOID)hHttp);
  74. //
  75. // ERROR_INTERNET_OPERATION_CANCELLED is the only error that we are
  76. // expecting here. If we get this error then the app has cancelled
  77. // the operation. Either way, the handle we just generated will be
  78. // already deleted
  79. //
  80. if (error != ERROR_SUCCESS) {
  81. INET_ASSERT(error == ERROR_INTERNET_OPERATION_CANCELLED);
  82. hHttp = NULL;
  83. }
  84. } else {
  85. delete hHttp;
  86. hHttp = NULL;
  87. }
  88. } else {
  89. error = ERROR_NOT_ENOUGH_MEMORY;
  90. }
  91. *ChildHandle = (HINTERNET)hHttp;
  92. if(hHttp)
  93. {
  94. hHttp->Dereference();
  95. }
  96. return error;
  97. }
  98. //
  99. // HTTP_REQUEST_HANDLE_OBJECT class implementation
  100. //
  101. HTTP_REQUEST_HANDLE_OBJECT::HTTP_REQUEST_HANDLE_OBJECT(
  102. INTERNET_CONNECT_HANDLE_OBJECT * Parent,
  103. HINTERNET Child,
  104. CLOSE_HANDLE_FUNC wCloseFunc,
  105. DWORD dwFlags,
  106. DWORD_PTR dwContext
  107. ) : INTERNET_CONNECT_HANDLE_OBJECT(Parent)
  108. /*++
  109. Routine Description:
  110. Constructor for direct-to-net HTTP_REQUEST_HANDLE_OBJECT
  111. Arguments:
  112. Parent - parent object
  113. Child - IN: HTTPREQ structure pointer
  114. OUT: pointer to created HTTP_REQUEST_HANDLE_OBJECT
  115. wCloseFunc - address of function that closes/destroys HTTPREQ structure
  116. dwFlags - open flags (e.g. INTERNET_FLAG_RELOAD)
  117. dwContext - caller-supplied request context value
  118. Return Value:
  119. None.
  120. --*/
  121. {
  122. Reference();
  123. _Context = dwContext;
  124. _Socket = NULL;
  125. _QueryBuffer = NULL;
  126. _QueryBufferLength = 0;
  127. _QueryOffset = 0;
  128. _QueryBytesAvailable = 0;
  129. _bKeepAliveConnection = FALSE;
  130. _bNoLongerKeepAlive = FALSE;
  131. _OpenFlags = dwFlags;
  132. _State = HttpRequestStateCreating;
  133. _RequestMethod = HTTP_METHOD_TYPE_UNKNOWN;
  134. _dwOptionalSaved = 0;
  135. _lpOptionalSaved = NULL;
  136. _fOptionalSaved = FALSE;
  137. _ResponseBuffer = NULL;
  138. _ResponseBufferLength = 0;
  139. ResetResponseVariables();
  140. _RequestHeaders.SetIsRequestHeaders(TRUE);
  141. _ResponseHeaders.SetIsRequestHeaders(FALSE);
  142. _fTalkingToSecureServerViaProxy = FALSE;
  143. _fRequestUsingProxy = FALSE;
  144. _bWantKeepAlive = FALSE;
  145. _bRefresh = FALSE;
  146. _RefreshHeader = NULL;
  147. _redirectCount = GlobalMaxHttpRedirects;
  148. _redirectCountedOut = FALSE;
  149. _fIgnoreOffline = FALSE;
  150. _f3rdPartyCookies = FALSE;
  151. _fBlockedOnPrompt = FALSE;
  152. SetObjectType(TypeHttpRequestHandle);
  153. _pCacheEntryInfo = NULL;
  154. _dwCacheEntryType = 0;
  155. _pAuthCtx = NULL;
  156. _pTunnelAuthCtx = NULL;
  157. _pPWC = NULL;
  158. _lpBlockingFilter = NULL;
  159. _dwCredPolicy = 0xFFFFFFFF;
  160. _NoResetBits.Dword = 0; // only here are we ever allowed to assign to Dword.
  161. SetDisableNTLMPreauth(GlobalDisableNTLMPreAuth);
  162. _ProxyHostName = NULL;
  163. _ProxyHostNameLength = NULL;
  164. _ProxyPort = INTERNET_INVALID_PORT_NUMBER;
  165. _SocksProxyHostName = NULL;
  166. _SocksProxyHostNameLength = NULL;
  167. _SocksProxyPort = INTERNET_INVALID_PORT_NUMBER;
  168. HttpFiltOpen(); // enumerate http filters if not already active
  169. _HaveReadFileExData = FALSE;
  170. memset(&_BuffersOut, 0, sizeof(_BuffersOut));
  171. _BuffersOut.dwStructSize = sizeof(_BuffersOut);
  172. _BuffersOut.lpvBuffer = (LPVOID)&_ReadFileExData;
  173. _fAutoProxyChecked = FALSE;
  174. m_pSecurityInfo = NULL;
  175. m_AuthFlag = 0x00000000;
  176. m_fPPAbortSend = FALSE;
  177. _fSendUTF8ServerNameToProxy = FALSE;
  178. SetPriority(0);
  179. _dwSecurityZone = 0xffffffff; /* initialize to invalid zone value */
  180. #ifdef RLF_TEST_CODE
  181. static long l = 0;
  182. SetPriority(l++);
  183. #endif
  184. _RTT = 0;
  185. _CP = CP_ACP;
  186. if (_Status == ERROR_SUCCESS) {
  187. _Status = _RequestHeaders.GetError();
  188. if (_Status == ERROR_SUCCESS) {
  189. _Status = _ResponseHeaders.GetError();
  190. }
  191. }
  192. _dwSocketSendBufferLength = -1;
  193. if ((_OpenFlags & INTERNET_FLAG_SECURE) &&
  194. (_Status = LoadSecurity()) == ERROR_SUCCESS)
  195. {
  196. m_pSecurityInfo = GlobalCertCache.Find(GetHostName());
  197. if (NULL == m_pSecurityInfo)
  198. {
  199. m_pSecurityInfo = new SECURITY_CACHE_LIST_ENTRY(GetHostName());
  200. // Force a net hit, since this hasn't been fully validated.
  201. SetCacheReadDisabled();
  202. }
  203. }
  204. else
  205. {
  206. m_pSecurityInfo = NULL;
  207. }
  208. }
  209. HTTP_REQUEST_HANDLE_OBJECT::~HTTP_REQUEST_HANDLE_OBJECT(
  210. VOID
  211. )
  212. /*++
  213. Routine Description:
  214. Destructor for HTTP_REQUEST_HANDLE_OBJECT
  215. Arguments:
  216. None.
  217. Return Value:
  218. None.
  219. --*/
  220. {
  221. DEBUG_ENTER((DBG_OBJECTS,
  222. None,
  223. "~HTTP_REQUEST_HANDLE_OBJECT",
  224. "%#x",
  225. this
  226. ));
  227. //
  228. // close the socket (or free it to the pool if keep-alive)
  229. //
  230. //
  231. // Authentication Note:
  232. // The CloseConnection parameter to force the connection closed
  233. // is set if we received a challenge but didn't respond, otherwise
  234. // IIS will get confused when a subsequent request recycles the
  235. // socket from the keep-alive pool.
  236. //
  237. CloseConnection(GetAuthState() == AUTHSTATE_CHALLENGE);
  238. if (IsCacheWriteInProgress()) {
  239. LocalEndCacheWrite(IsEndOfFile());
  240. }
  241. if (IsCacheReadInProgress()) {
  242. INET_ASSERT (_pCacheEntryInfo);
  243. FREE_MEMORY (_pCacheEntryInfo);
  244. // Rest is cleaned up in INTERNET_CONNECT_HANDLE_OBJECT::EndCacheWrite
  245. } else {
  246. UrlCacheUnlock();
  247. }
  248. //
  249. // If there's an authentication context, unload the provider.
  250. //
  251. if (_pAuthCtx) {
  252. delete _pAuthCtx;
  253. }
  254. if (_pTunnelAuthCtx) {
  255. delete _pTunnelAuthCtx;
  256. }
  257. //
  258. // free the various buffers
  259. //
  260. FreeResponseBuffer();
  261. FreeQueryBuffer();
  262. SetProxyName(NULL,NULL,0);
  263. if (m_pSecurityInfo != NULL) {
  264. m_pSecurityInfo->Release();
  265. }
  266. DEBUG_LEAVE(0);
  267. }
  268. HINTERNET
  269. HTTP_REQUEST_HANDLE_OBJECT::GetHandle(
  270. VOID
  271. )
  272. /*++
  273. Routine Description:
  274. Returns child handle value. NULL for HTTP
  275. Arguments:
  276. None.
  277. Return Value:
  278. HINTERNET
  279. NULL
  280. --*/
  281. {
  282. return NULL;
  283. }
  284. VOID
  285. HTTP_REQUEST_HANDLE_OBJECT::SetProxyName(
  286. IN LPSTR lpszProxyHostName,
  287. IN DWORD dwProxyHostNameLength,
  288. IN INTERNET_PORT ProxyPort
  289. )
  290. /*++
  291. Routine Description:
  292. Set proxy name in object. If already have name, free it. Don't set name if
  293. current pointer is input
  294. Arguments:
  295. lpszProxyHostName - pointer to proxy name to add
  296. dwProxyHostNameLength - length of proxy name
  297. ProxyPort - port
  298. Return Value:
  299. None.
  300. --*/
  301. {
  302. DEBUG_ENTER((DBG_HTTP,
  303. None,
  304. "HTTP_REQUEST_HANDLE_OBJECT::SetProxyName",
  305. "{%q, %d, %d}%q, %d, %d",
  306. _ProxyHostName,
  307. _ProxyHostNameLength,
  308. _ProxyPort,
  309. lpszProxyHostName,
  310. dwProxyHostNameLength,
  311. ProxyPort
  312. ));
  313. if (lpszProxyHostName != _ProxyHostName) {
  314. if (_ProxyHostName != NULL) {
  315. _ProxyHostName = (LPSTR)FREE_MEMORY(_ProxyHostName);
  316. INET_ASSERT(_ProxyHostName == NULL);
  317. SetOverrideProxyMode(FALSE);
  318. }
  319. if (lpszProxyHostName != NULL) {
  320. _ProxyHostName = NEW_STRING(lpszProxyHostName);
  321. if (_ProxyHostName == NULL) {
  322. dwProxyHostNameLength = 0;
  323. }
  324. }
  325. _ProxyHostNameLength = dwProxyHostNameLength;
  326. _ProxyPort = ProxyPort;
  327. } else if (lpszProxyHostName != NULL) {
  328. DEBUG_PRINT(HTTP,
  329. WARNING,
  330. ("!!! lpszProxyHostName == _ProxyHostName (%#x)\n",
  331. lpszProxyHostName
  332. ));
  333. INET_ASSERT(dwProxyHostNameLength == _ProxyHostNameLength);
  334. INET_ASSERT(ProxyPort == _ProxyPort);
  335. }
  336. DEBUG_LEAVE(0);
  337. }
  338. VOID
  339. HTTP_REQUEST_HANDLE_OBJECT::GetProxyName(
  340. OUT LPSTR* lplpszProxyHostName,
  341. OUT LPDWORD lpdwProxyHostNameLength,
  342. OUT LPINTERNET_PORT lpProxyPort
  343. )
  344. /*++
  345. Routine Description:
  346. Return address & length of proxy name plus proxy port
  347. Arguments:
  348. lplpszProxyHostName - returned address of name
  349. lpdwProxyHostNameLength - returned length of name
  350. lpProxyPort - returned port
  351. Return Value:
  352. None.
  353. --*/
  354. {
  355. DEBUG_ENTER((DBG_HTTP,
  356. None,
  357. "HTTP_REQUEST_HANDLE_OBJECT::GetProxyName",
  358. "{%q, %d, %d}%#x, %#x, %#x",
  359. _ProxyHostName,
  360. _ProxyHostNameLength,
  361. _ProxyPort,
  362. lplpszProxyHostName,
  363. lpdwProxyHostNameLength,
  364. lpProxyPort
  365. ));
  366. *lplpszProxyHostName = _ProxyHostName;
  367. *lpdwProxyHostNameLength = _ProxyHostNameLength;
  368. *lpProxyPort = _ProxyPort;
  369. DEBUG_LEAVE(0);
  370. }
  371. VOID
  372. HTTP_REQUEST_HANDLE_OBJECT::ReuseObject(
  373. VOID
  374. )
  375. /*++
  376. Routine Description:
  377. Make the object re-usable: clear out any received data and headers and
  378. reset the state to open
  379. Arguments:
  380. None.
  381. Return Value:
  382. None.
  383. --*/
  384. {
  385. DEBUG_ENTER((DBG_HTTP,
  386. None,
  387. "HTTP_REQUEST_HANDLE_OBJECT::ReuseObject",
  388. NULL
  389. ));
  390. _ResponseHeaders.FreeHeaders();
  391. FreeResponseBuffer();
  392. ResetResponseVariables();
  393. _ResponseHeaders.Initialize();
  394. _dwCurrentStreamPosition = 0;
  395. SetState(HttpRequestStateOpen);
  396. ResetEndOfFile();
  397. _ctChunkInfo.Reset();
  398. _QueryOffset = 0;
  399. _QueryBytesAvailable = 0;
  400. _dwQuerySetCookieHeader = 0;
  401. if (m_pSecurityInfo) {
  402. m_pSecurityInfo->Release();
  403. }
  404. m_pSecurityInfo = NULL;
  405. DEBUG_LEAVE(0);
  406. }
  407. DWORD
  408. HTTP_REQUEST_HANDLE_OBJECT::ResetObject(
  409. IN BOOL bForce,
  410. IN BOOL bFreeRequestHeaders
  411. )
  412. /*++
  413. Routine Description:
  414. This method is called when we we are clearing out a partially completed
  415. transaction, mainly for when we have determined that an if-modified-since
  416. request, or a response that has not invalidated the cache entry can be
  417. retrieved from cache (this is a speed issue)
  418. Abort the connection and clear out the response headers and response
  419. buffer; clear the response variables (all done by AbortConnection()).
  420. If bFreeRequestHeaders, clear out the request headers.
  421. Reinitialize the response headers. We do not reset the object state, but we
  422. do reset the end-of-file status
  423. Arguments:
  424. bForce - TRUE if connection is forced closed
  425. bFreeRequestHeaders - TRUE if request headers should be freed
  426. Return Value:
  427. DWORD
  428. Success - ERROR_SUCCESS
  429. Failure -
  430. --*/
  431. {
  432. DEBUG_ENTER((DBG_HTTP,
  433. Dword,
  434. "HTTP_REQUEST_HANDLE_OBJECT::ResetObject",
  435. "%B, %B",
  436. bForce,
  437. bFreeRequestHeaders
  438. ));
  439. DWORD error;
  440. error = AbortConnection(bForce);
  441. if (error == ERROR_SUCCESS) {
  442. if (bFreeRequestHeaders) {
  443. _RequestHeaders.FreeHeaders();
  444. }
  445. _ResponseHeaders.Initialize();
  446. ResetEndOfFile();
  447. }
  448. DEBUG_LEAVE(error);
  449. return error;
  450. }
  451. VOID
  452. HTTP_REQUEST_HANDLE_OBJECT::UrlCacheUnlock(
  453. VOID
  454. )
  455. /*++
  456. Routine Description:
  457. description-of-function.
  458. Arguments:
  459. None.
  460. Return Value:
  461. None.
  462. --*/
  463. {
  464. INET_ASSERT (!_CacheReadInProgress);
  465. if (_hCacheStream)
  466. {
  467. UnlockUrlCacheEntryStream (_hCacheStream, 0);
  468. _hCacheStream = NULL;
  469. }
  470. if (_pCacheEntryInfo)
  471. {
  472. if (_pCacheEntryInfo->CacheEntryType & SPARSE_CACHE_ENTRY)
  473. {
  474. //
  475. // We can't use the partial cache entry because it is
  476. // stale, so delete the data file we got from cache.
  477. //
  478. INET_ASSERT (_CacheFileHandle != INVALID_HANDLE_VALUE);
  479. CloseHandle (_CacheFileHandle);
  480. _CacheFileHandle = INVALID_HANDLE_VALUE;
  481. DeleteFile (_pCacheEntryInfo->lpszLocalFileName);
  482. }
  483. FREE_MEMORY (_pCacheEntryInfo);
  484. _pCacheEntryInfo = NULL;
  485. }
  486. }
  487. VOID
  488. HTTP_REQUEST_HANDLE_OBJECT::SetAuthenticated(
  489. VOID
  490. )
  491. /*++
  492. Routine Description:
  493. description-of-function.
  494. Arguments:
  495. SetAuthenticated -
  496. Return Value:
  497. None.
  498. --*/
  499. {
  500. if (!_Socket)
  501. {
  502. INET_ASSERT(FALSE);
  503. }
  504. else
  505. {
  506. _Socket->SetAuthenticated();
  507. }
  508. }
  509. BOOL
  510. HTTP_REQUEST_HANDLE_OBJECT::IsAuthenticated(
  511. VOID
  512. )
  513. /*++
  514. Routine Description:
  515. description-of-function.
  516. Arguments:
  517. IsAuthenticated -
  518. Return Value:
  519. BOOL
  520. --*/
  521. {
  522. return (_Socket ? _Socket->IsAuthenticated() : FALSE);
  523. }