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.

1995 lines
49 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. hinet.cxx
  5. Abstract:
  6. contains methods for INTERNET_HANDLE_BASE class
  7. Contents:
  8. HANDLE_OBJECT::HANDLE_OBJECT()
  9. HANDLE_OBJECT::HANDLE_OBJECT()
  10. HANDLE_OBJECT::Reference()
  11. HANDLE_OBJECT::Dereference()
  12. HANDLE_OBJECT::IsValid()
  13. INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE(LPCSTR, ...)
  14. INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE(INTERNET_HANDLE_BASE*)
  15. INTERNET_HANDLE_BASE::~INTERNET_HANDLE_BASE()
  16. INTERNET_HANDLE_BASE::SetAbortHandle(ICSocket)
  17. INTERNET_HANDLE_BASE::ResetAbortHandle()
  18. INTERNET_HANDLE_BASE::AbortSocket()
  19. INTERNET_HANDLE_BASE::SetProxyInfo()
  20. INTERNET_HANDLE_BASE::GetProxyInfo(LPVOID, LPDWORD)
  21. INTERNET_HANDLE_BASE::GetProxyInfo(INTERNET_SCHEME, LPINTERNET_SCHEME, LPSTR *, LPDWORD, LPINTERNET_PORT)
  22. Author:
  23. Madan Appiah (madana) 16-Nov-1994
  24. Environment:
  25. User Mode - Win32
  26. Revision History:
  27. Sophia Chung (sophiac) 14-Feb-1995 (added FTP and Archie class impl.)
  28. (code adopted from madana)
  29. --*/
  30. #include <wininetp.h>
  31. #include <perfdiag.hxx>
  32. #include "../http/cookiejar.h"
  33. //
  34. // private manifests
  35. //
  36. #define PROXY_REGISTRY_STRING_LENGTH (4 K)
  37. //
  38. // methods
  39. //
  40. HANDLE_OBJECT::HANDLE_OBJECT(
  41. IN HANDLE_OBJECT * Parent
  42. )
  43. /*++
  44. Routine Description:
  45. HANDLE_OBJECT constructor
  46. Arguments:
  47. Parent - pointer to parent HANDLE_OBJECT
  48. Return Value:
  49. None.
  50. --*/
  51. {
  52. DEBUG_ENTER((DBG_OBJECTS,
  53. None,
  54. "HANDLE_OBJECT",
  55. "%#x",
  56. this
  57. ));
  58. //InitializeListHead(&_List);
  59. _Parent = Parent;
  60. if (_Parent)
  61. _Parent->Reference();
  62. _Status = AllocateHandle(this, &_Handle);
  63. _ObjectType = TypeGenericHandle;
  64. _ReferenceCount = 1;
  65. _Invalid = FALSE;
  66. _Error = ERROR_SUCCESS;
  67. _Signature = OBJECT_SIGNATURE;
  68. _Context = NULL;
  69. #if INET_DEBUG
  70. if (!InsertAtTailOfSerializedList(&GlobalObjectList, &_List))
  71. _Status = ERROR_NOT_ENOUGH_MEMORY;
  72. #endif
  73. //
  74. // if AllocateHandle() failed then we cannot create this handle object.
  75. // Invalidate it ready for the destructor
  76. //
  77. if (_Status != ERROR_SUCCESS) {
  78. _Invalid = TRUE;
  79. _ReferenceCount = 0;
  80. }
  81. DEBUG_PRINT(OBJECTS,
  82. INFO,
  83. ("handle %#x created; address %#x; %d objects\n",
  84. _Handle,
  85. this,
  86. ElementsOnSerializedList(&GlobalObjectList)
  87. ));
  88. DEBUG_LEAVE(0);
  89. }
  90. HANDLE_OBJECT::~HANDLE_OBJECT(VOID)
  91. /*++
  92. Routine Description:
  93. HANDLE_OBJECT destructor. Virtual function
  94. Arguments:
  95. None.
  96. Return Value:
  97. None.
  98. --*/
  99. {
  100. DEBUG_ENTER((DBG_OBJECTS,
  101. None,
  102. "~HANDLE_OBJECT",
  103. "%#x",
  104. this
  105. ));
  106. #if INET_DEBUG
  107. //
  108. // remove this object from global object list
  109. //
  110. if (LockSerializedList(&GlobalObjectList))
  111. {
  112. // should always succeed since we already have the lock
  113. RemoveFromSerializedList(&GlobalObjectList, &_List);
  114. UnlockSerializedList(&GlobalObjectList);
  115. }
  116. #endif
  117. INET_DEBUG_ASSERT((_List.Flink == NULL) && (_List.Blink == NULL));
  118. //
  119. // inform the app that this handle is completely closed
  120. //
  121. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  122. if (lpThreadInfo != NULL)
  123. {
  124. HINTERNET hCurrent = _InternetGetObjectHandle(lpThreadInfo);
  125. HINTERNET hCurrentMapped = _InternetGetMappedObjectHandle(lpThreadInfo);
  126. _InternetSetObjectHandle(lpThreadInfo, _Handle, (HINTERNET)this);
  127. HINTERNET hTemp = _Handle;
  128. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING,
  129. (LPVOID)&hTemp,
  130. sizeof(hTemp)
  131. );
  132. _InternetSetObjectHandle(lpThreadInfo, hCurrent, hCurrentMapped);
  133. }
  134. if (_Parent != NULL)
  135. _Parent->Dereference();
  136. //
  137. // now we can free up the API handle value
  138. //
  139. if (_Handle != NULL) {
  140. _Status = FreeHandle(_Handle);
  141. INET_ASSERT(_Status == ERROR_SUCCESS);
  142. }
  143. //
  144. // set the signature to a value that indicates the handle has been
  145. // destroyed (not useful in debug builds)
  146. //
  147. _Signature = DESTROYED_OBJECT_SIGNATURE;
  148. INET_ASSERT((_ReferenceCount == 0) && _Invalid);
  149. DEBUG_PRINT(OBJECTS,
  150. INFO,
  151. ("handle %#x destroyed; type %s; address %#x; %d objects\n",
  152. _Handle,
  153. InternetMapHandleType(_ObjectType),
  154. this,
  155. ElementsOnSerializedList(&GlobalObjectList)
  156. ));
  157. DEBUG_LEAVE(0);
  158. }
  159. DWORD
  160. HANDLE_OBJECT::Reference(
  161. VOID
  162. )
  163. /*++
  164. Routine Description:
  165. Increases the reference count on the HANDLE_OBJECT
  166. Arguments:
  167. None.
  168. Return Value:
  169. DWORD
  170. Success - ERROR_SUCCESS
  171. Failure - ERROR_INVALID_HANDLE
  172. Handle has already been invalidated
  173. ERROR_ACCESS_DENIED
  174. Handle object is being destroyed, cannot use it
  175. --*/
  176. {
  177. DEBUG_ENTER((DBG_OBJECTS,
  178. Dword,
  179. "HANDLE_OBJECT::Reference",
  180. "{%#x}",
  181. _Handle
  182. ));
  183. DWORD error;
  184. if (_Invalid) {
  185. DEBUG_PRINT(OBJECTS,
  186. INFO,
  187. ("handle object %#x [%#x] is invalid\n",
  188. _Handle,
  189. this
  190. ));
  191. error = ERROR_INVALID_HANDLE;
  192. } else {
  193. error = ERROR_SUCCESS;
  194. }
  195. //
  196. // even if the handle has been invalidated (i.e. closed), we allow it
  197. // to continue to be referenced. The caller should return the fact
  198. // that the handle has been invalidated, but may require information
  199. // from the object in order to do so (e.g. in async thread)
  200. //
  201. do
  202. {
  203. LONG lRefCountBeforeIncrement = _ReferenceCount;
  204. //
  205. // refcount is > 0 means that the object's destructor has not been called yet
  206. //
  207. if (lRefCountBeforeIncrement > 0)
  208. {
  209. //
  210. // try to increment the refcount using compare-exchange
  211. //
  212. #ifndef _WIN64
  213. LONG lRefCountCurrent = (LONG)SHInterlockedCompareExchange((LPVOID*)&_ReferenceCount,
  214. (LPVOID)(lRefCountBeforeIncrement + 1),
  215. (LPVOID)lRefCountBeforeIncrement);
  216. #else
  217. //
  218. // can't use SHInterlockedCompareExchange on win64 because the values are really LONG's (32-bits) but they
  219. // are treated as pointers (64-bits) because SHInterlockedCompareExchange should really be called
  220. // SHInterlockedCompareExchangePointer (sigh...).
  221. //
  222. LONG lRefCountCurrent = InterlockedCompareExchange(&_ReferenceCount,
  223. lRefCountBeforeIncrement + 1,
  224. lRefCountBeforeIncrement);
  225. #endif
  226. if (lRefCountCurrent == lRefCountBeforeIncrement)
  227. {
  228. //
  229. // since SHInterlockedCompareExchange returns the value in _ReferenceCount
  230. // before the exchange, we know the exchange sucessfully took place (i.e. we
  231. // sucessfully incremented the refrence count of the object by one)
  232. //
  233. INET_ASSERT(lRefCountCurrent > 0);
  234. break;
  235. }
  236. }
  237. else
  238. {
  239. //
  240. // the refcount dropped to zero before we could increment it,
  241. // so the object is being destroyed.
  242. //
  243. error = ERROR_ACCESS_DENIED;
  244. break;
  245. }
  246. } while (TRUE);
  247. DEBUG_PRINT(REFCOUNT,
  248. INFO,
  249. ("handle object %#x [%#x] ReferenceCount = %d\n",
  250. _Handle,
  251. this,
  252. _ReferenceCount
  253. ));
  254. DEBUG_LEAVE(error);
  255. return error;
  256. }
  257. BOOL
  258. HANDLE_OBJECT::Dereference(
  259. VOID
  260. )
  261. /*++
  262. Routine Description:
  263. Reduces the reference count on the HANDLE_OBJECT, and if it goes to zero,
  264. the object is deleted
  265. Arguments:
  266. None.
  267. Return Value:
  268. BOOL
  269. TRUE - this object was deleted
  270. FALSE - this object is still valid
  271. --*/
  272. {
  273. DEBUG_ENTER((DBG_OBJECTS,
  274. Bool,
  275. "HANDLE_OBJECT::Dereference",
  276. "{%#x}",
  277. _Handle
  278. ));
  279. //
  280. // by the time we get here, the reference count should not be 0. There
  281. // should be 1 call to Dereference() for each call to Reference()
  282. //
  283. INET_ASSERT(_ReferenceCount != 0);
  284. BOOL deleted = FALSE;
  285. if (InterlockedDecrement(&_ReferenceCount) == 0)
  286. {
  287. deleted = TRUE;
  288. }
  289. if (deleted)
  290. {
  291. //
  292. // if we are calling the destructor, the handle had better be invalid!
  293. //
  294. INET_ASSERT(_Invalid);
  295. //
  296. // this handle has now been closed. If there is no activity on it
  297. // then it will be destroyed
  298. //
  299. DEBUG_PRINT(REFCOUNT,
  300. INFO,
  301. ("handle object %#x [%#x] ReferenceCount = %d\n",
  302. _Handle,
  303. this,
  304. _ReferenceCount
  305. ));
  306. delete this;
  307. } else {
  308. DEBUG_PRINT(REFCOUNT,
  309. INFO,
  310. ("handle object %#x [%#x] ReferenceCount = %d\n",
  311. _Handle,
  312. this,
  313. _ReferenceCount
  314. ));
  315. }
  316. DEBUG_LEAVE(deleted);
  317. return deleted;
  318. }
  319. DWORD
  320. HANDLE_OBJECT::IsValid(
  321. IN HINTERNET_HANDLE_TYPE ExpectedHandleType
  322. )
  323. /*++
  324. Routine Description:
  325. Checks a HANDLE_OBJECT for validity
  326. Arguments:
  327. ExpectedHandleType - type of object we are testing for. Can be
  328. TypeWildHandle which matches any valid handle
  329. Return Value:
  330. DWORD
  331. Success - ERROR_SUCCESS
  332. Failure - ERROR_INVALID_HANDLE
  333. The handle object is invalid
  334. ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
  335. The handle object is valid, but not the type we want
  336. --*/
  337. {
  338. DWORD error;
  339. //
  340. // test handle object within try..except in case we are given a bad address
  341. //
  342. __try {
  343. if (_Signature == OBJECT_SIGNATURE) {
  344. error = ERROR_SUCCESS;
  345. //
  346. // check handle type if we are asked to do so.
  347. //
  348. if (ExpectedHandleType != TypeWildHandle) {
  349. if (ExpectedHandleType != this->GetHandleType()) {
  350. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  351. }
  352. }
  353. } else {
  354. error = ERROR_INVALID_HANDLE;
  355. }
  356. } __except (EXCEPTION_EXECUTE_HANDLER) {
  357. error = ERROR_INVALID_HANDLE;
  358. }
  359. ENDEXCEPT
  360. return error;
  361. }
  362. INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE(
  363. LPCSTR UserAgent,
  364. DWORD AccessMethod,
  365. LPSTR ProxyServerList,
  366. LPSTR ProxyBypassList,
  367. DWORD Flags
  368. ) : HANDLE_OBJECT(NULL)
  369. /*++
  370. Routine Description:
  371. Creates the handle object for InternetOpen()
  372. Arguments:
  373. UserAgent - name of agent (user-agent string for HTTP)
  374. AccessMethod - DIRECT, PROXY or PRECONFIG
  375. ProxyServerList - one or more proxy servers. The string has the form:
  376. [<scheme>=][<scheme>"://"]<server>[":"<port>][";"*]
  377. ProxyBypassList - zero or more addresses which if matched will result in
  378. requests NOT going via the proxy (only if PROXY access).
  379. The string has the form:
  380. bp_entry ::= [<scheme>"://"]<server>[":"<port>]
  381. bp_macro ::= "<local>"
  382. bp_list ::= [<> | bp_entry bp_macro][";"*]
  383. Flags - various open flags:
  384. WINHTTP_FLAG_ASYNC - not support in WinHttpX
  385. Return Value:
  386. None.
  387. --*/
  388. {
  389. DEBUG_ENTER((DBG_OBJECTS,
  390. None,
  391. "INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE",
  392. NULL
  393. ));
  394. //
  395. // if the HANDLE_OBJECT constructor failed then bail out now
  396. //
  397. if (_Status != ERROR_SUCCESS) {
  398. DEBUG_PRINT(OBJECTS,
  399. ERROR,
  400. ("early-exit: _Status = %d\n",
  401. _Status
  402. ));
  403. DEBUG_LEAVE(0);
  404. return;
  405. }
  406. _PPContext = 0;
  407. _fDisableTweener = TRUE;
  408. _fDisableKeyring = TRUE;
  409. _ThreadToken = 0;
  410. _IsCopy = FALSE;
  411. _UserAgent = (LPSTR)UserAgent;
  412. _ProxyInfo = NULL;
  413. _dwInternetOpenFlags = Flags;
  414. _WinsockLoaded = FALSE;
  415. _Context = NULL;
  416. _MaxConnectionsPerServer = WINHTTP_CONNS_PER_SERVER_UNLIMITED;
  417. _MaxConnectionsPer1_0Server = WINHTTP_CONNS_PER_SERVER_UNLIMITED;
  418. //
  419. // set _Async based on the WINHTTP_FLAG_ASYNC supplied to InternetOpen()
  420. //
  421. _dwCodePage = CP_UTF8;
  422. _Async = (Flags & WINHTTP_FLAG_ASYNC) ? TRUE : FALSE;
  423. //
  424. // no data available yet
  425. //
  426. SetAvailableDataLength(0);
  427. //
  428. // not yet end of file
  429. //
  430. ResetEndOfFile();
  431. //
  432. // no status callback by default
  433. //
  434. _StatusCallback = NULL;
  435. _StatusCallbackType = FALSE;
  436. _dwStatusCallbackFlags = 0;
  437. SetObjectType(TypeInternetHandle);
  438. _ProxyInfoResourceLock.Initialize();
  439. _Status = SetProxyInfo(AccessMethod, ProxyServerList, ProxyBypassList);
  440. //
  441. // if _pICSocket is not NULL then this is the socket that this object handle
  442. // is currently working on. We close it to cancel the operation
  443. //
  444. _pICSocket = NULL;
  445. if (::OpenThreadToken(
  446. GetCurrentThread(),
  447. TOKEN_READ | TOKEN_IMPERSONATE,
  448. FALSE,
  449. &_ThreadToken
  450. ) == FALSE)
  451. {
  452. _ThreadToken = 0;
  453. }
  454. //
  455. // load winsock now.
  456. //
  457. if (_Status == ERROR_SUCCESS) {
  458. _Status = LoadWinsock();
  459. _WinsockLoaded = (_Status == ERROR_SUCCESS);
  460. if ( _Status == ERROR_SUCCESS )
  461. {
  462. LONG lOpenHandleCnt;
  463. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  464. if ( lpThreadInfo )
  465. {
  466. lOpenHandleCnt = InterlockedIncrement((LPLONG)&GlobalInternetOpenHandleCount);
  467. if ( lOpenHandleCnt == 0 )
  468. {
  469. DWORD fAlreadyInInit = (DWORD) InterlockedExchange((LPLONG) &GlobalAutoProxyInInit, TRUE);
  470. UNREFERENCED_PARAMETER(fAlreadyInInit);
  471. INET_ASSERT (! fAlreadyInInit );
  472. g_pGlobalProxyInfo->ReleaseQueuedRefresh();
  473. InterlockedExchange((LPLONG)&GlobalAutoProxyInInit, FALSE);
  474. }
  475. }
  476. }
  477. }
  478. DEBUG_LEAVE(0);
  479. }
  480. INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE(
  481. INTERNET_HANDLE_BASE *INetObj
  482. ) : HANDLE_OBJECT((HANDLE_OBJECT*)INetObj)
  483. /*++
  484. Routine Description:
  485. Constructor for derived handle object. We are creating this handle as part
  486. of an INTERNET_CONNECT_HANDLE_OBJECT
  487. Arguments:
  488. INetObj - pointer to INTERNET_HANDLE_BASE to copy
  489. Return Value:
  490. None.
  491. --*/
  492. {
  493. DEBUG_ENTER((DBG_OBJECTS,
  494. None,
  495. "INTERNET_HANDLE_BASE::INTERNET_HANDLE_BASE",
  496. "{IsCopy}"
  497. ));
  498. _PPContext = INetObj->_PPContext;
  499. _fDisableTweener = INetObj->_fDisableTweener;
  500. _fDisableKeyring = INetObj->_fDisableKeyring;
  501. _ThreadToken = INetObj->_ThreadToken;
  502. _IsCopy = TRUE;
  503. //
  504. // copy user agent string
  505. //
  506. //
  507. // BUGBUG - compiler generated copy constructor (no new string)
  508. //
  509. _UserAgent = INetObj->_UserAgent;
  510. //
  511. // do not inherit the proxy info - code must go to parent handle
  512. //
  513. _ProxyInfo = NULL;
  514. _ProxyInfoResourceLock.Initialize();
  515. _dwInternetOpenFlags = INetObj->_dwInternetOpenFlags;
  516. //
  517. // creating this handle didn't load winsock
  518. //
  519. _WinsockLoaded = FALSE;
  520. //
  521. // inherit the context, async flag and status callback from
  522. // the parent object handle
  523. //
  524. _Context = INetObj->_Context;
  525. _MaxConnectionsPerServer = INetObj->_MaxConnectionsPerServer;
  526. _MaxConnectionsPer1_0Server = INetObj->_MaxConnectionsPer1_0Server;
  527. _dwCodePage = INetObj->_dwCodePage;
  528. _Async = INetObj->_Async;
  529. //
  530. // inherit callback function
  531. //
  532. SetAvailableDataLength(0);
  533. ResetEndOfFile();
  534. _StatusCallback = INetObj->_StatusCallback;
  535. _StatusCallbackType = INetObj->_StatusCallbackType;
  536. _dwStatusCallbackFlags = INetObj->_dwStatusCallbackFlags;
  537. //
  538. // no socket operation to abort yet
  539. //
  540. _pICSocket = NULL;
  541. //
  542. // BUGBUG - this overwrites status set above?
  543. //
  544. _Status = INetObj->_Status;
  545. DEBUG_LEAVE(0);
  546. }
  547. INTERNET_HANDLE_BASE::~INTERNET_HANDLE_BASE(
  548. VOID
  549. )
  550. /*++
  551. Routine Description:
  552. INTERNET_HANDLE_BASE destructor
  553. Arguments:
  554. None.
  555. Return Value:
  556. None.
  557. --*/
  558. {
  559. DEBUG_ENTER((DBG_OBJECTS,
  560. None,
  561. "INTERNET_HANDLE_BASE::~INTERNET_HANDLE_BASE",
  562. ""
  563. ));
  564. if (_ProxyInfo && !IsProxyGlobal() && (_ProxyInfo != PROXY_INFO_DIRECT))
  565. {
  566. DEBUG_PRINT(OBJECTS,
  567. INFO,
  568. ("Free-ing ProxyInfo\n"
  569. ));
  570. delete _ProxyInfo;
  571. _ProxyInfo = NULL;
  572. }
  573. //
  574. // if this handle is not a copy (i.e., it is a Session handle), then delete
  575. // the Passport context
  576. //
  577. if (!IsCopy()) {
  578. DEBUG_PRINT(OBJECTS,
  579. INFO,
  580. ("Not a Copy...\n"
  581. ));
  582. if (_PPContext)
  583. {
  584. ::PP_FreeContext(_PPContext);
  585. }
  586. //
  587. // don't unload winsock. There really is no need to unload separately
  588. // from process detach and if we do unload, we first have to terminate
  589. // async support. Dynaloading and unloading winsock is vestigial
  590. //
  591. //if (_WinsockLoaded) {
  592. // UnloadWinsock();
  593. //}
  594. if (_ThreadToken)
  595. {
  596. ::CloseHandle(_ThreadToken);
  597. _ThreadToken = NULL;
  598. }
  599. }
  600. DEBUG_LEAVE(0);
  601. }
  602. DWORD
  603. INTERNET_HANDLE_BASE::ExchangeStatusCallback(
  604. LPWINHTTP_STATUS_CALLBACK lpStatusCallback,
  605. BOOL fType,
  606. DWORD dwFlags
  607. )
  608. {
  609. DWORD error;
  610. WINHTTP_STATUS_CALLBACK callback;
  611. // exchange new and current callbacks
  612. callback = _StatusCallback;
  613. _StatusCallback = *lpStatusCallback;
  614. *lpStatusCallback = callback;
  615. _StatusCallbackType = fType;
  616. _dwStatusCallbackFlags = dwFlags;
  617. error = ERROR_SUCCESS;
  618. return error;
  619. }
  620. VOID
  621. INTERNET_HANDLE_BASE::SetAbortHandle(
  622. IN ICSocket * Socket
  623. )
  624. /*++
  625. Routine Description:
  626. Associates with this request handle the ICSocket object currently being used
  627. for network I/O
  628. Arguments:
  629. Socket - pointer to ICSocket
  630. Return Value:
  631. None.
  632. --*/
  633. {
  634. DEBUG_ENTER((DBG_OBJECTS | DBG_SOCKETS,
  635. None,
  636. "INTERNET_HANDLE_BASE::SetAbortHandle",
  637. "{%#x} %#x [sock=%#x ref=%d]",
  638. GetPseudoHandle(),
  639. Socket,
  640. Socket ? Socket->GetSocket() : 0,
  641. Socket ? Socket->ReferenceCount() : 0
  642. ));
  643. INET_ASSERT(Socket != NULL);
  644. //
  645. // first off, increase the socket reference count to stop any other threads
  646. // killing it whilst we are performing the socket operation. The only way
  647. // another thread can dereference the socket is by calling our AbortSocket()
  648. // method
  649. //
  650. Socket->Reference();
  651. //
  652. // now associate the socket object with this handle object. We should not
  653. // have a current association
  654. //
  655. ICSocket * pSocket;
  656. pSocket = (ICSocket *) InterlockedExchangePointer((PVOID*)&_pICSocket, Socket);
  657. //
  658. // because ConnectSocket() can call this method multiple times without
  659. // intervening calls to ResetAbortHandle(), pSocket can legitimately be
  660. // non-NULL at this point
  661. //
  662. //INET_ASSERT(pSocket == NULL);
  663. //
  664. // if the handle was invalidated on another thread before we got
  665. // chance to set the socket to close, then abort the request now
  666. //
  667. //
  668. // BUGBUG - screws up normal FTP close handle processing - we
  669. // have to communicate with the server in order to
  670. // drop the connection
  671. //
  672. //if (IsInvalidated()) {
  673. // AbortSocket();
  674. //}
  675. DEBUG_LEAVE(0);
  676. }
  677. VOID
  678. INTERNET_HANDLE_BASE::ResetAbortHandle(
  679. VOID
  680. )
  681. /*++
  682. Routine Description:
  683. Disassociates this request handle and the ICSocket object when the network
  684. operation has completed
  685. Arguments:
  686. None.
  687. Return Value:
  688. None.
  689. --*/
  690. {
  691. DEBUG_ENTER((DBG_OBJECTS | DBG_SOCKETS,
  692. None,
  693. "INTERNET_HANDLE_BASE::ResetAbortHandle",
  694. "{%#x}",
  695. GetPseudoHandle()
  696. ));
  697. //
  698. // there really should be a ICSocket associated with this object, otherwise
  699. // our handle close/invalidation logic is broken
  700. //
  701. //
  702. // however, we can call ResetAbortHandle() from paths where we completed
  703. // early, not having called SetAbortHandle()
  704. //
  705. //INET_ASSERT(pSocket != NULL);
  706. //
  707. // so if there was a ICSocket associated with this object then remove the
  708. // reference added in SetAbortHandle()
  709. //
  710. ICSocket * pICSocket;
  711. pICSocket = (ICSocket *)InterlockedExchangePointer((PVOID*)&_pICSocket, NULL);
  712. if (pICSocket != NULL) {
  713. DEBUG_PRINT(SOCKETS,
  714. INFO,
  715. ("socket=%#x ref=%d\n",
  716. pICSocket->GetSocket(),
  717. pICSocket->ReferenceCount()
  718. ));
  719. pICSocket->Dereference();
  720. }
  721. DEBUG_LEAVE(0);
  722. }
  723. VOID
  724. INTERNET_HANDLE_BASE::AbortSocket(
  725. VOID
  726. )
  727. /*++
  728. Routine Description:
  729. If there is a ICSocket associated with this handle object then abort it. This
  730. forces the current network operation aborted and the request to complete
  731. with ERROR_WINHTTP_OPERATION_CANCELLED
  732. Arguments:
  733. None.
  734. Return Value:
  735. None.
  736. --*/
  737. {
  738. DEBUG_ENTER((DBG_OBJECTS | DBG_SOCKETS,
  739. None,
  740. "INTERNET_HANDLE_BASE::AbortSocket",
  741. "{%#x, %#x [sock=%#x, ref=%d]}",
  742. GetPseudoHandle(),
  743. (_pICSocket != NULL)
  744. ? (LPVOID)_pICSocket
  745. : (LPVOID)_pICSocket,
  746. _pICSocket
  747. ? _pICSocket->GetSocket()
  748. : (_pICSocket
  749. ? _pICSocket->GetSocket()
  750. : 0),
  751. _pICSocket
  752. ? _pICSocket->ReferenceCount()
  753. : (_pICSocket
  754. ? _pICSocket->ReferenceCount()
  755. : 0)
  756. ));
  757. //
  758. // get the associated ICSocket. It may have already been removed by a call
  759. // to ResetAbortHandle()
  760. //
  761. //
  762. // if there is an associated ICSocket then abort it (close the socket handle)
  763. // which will complete the current network I/O (if active) with an error.
  764. // Once the ICSocket is aborted, we reduce the reference count that was added
  765. // in SetAbortHandle(). This may cause the ICSocket to be deleted
  766. //
  767. LPVOID pAddr;
  768. pAddr = (LPVOID)InterlockedExchangePointer((PVOID*)&_pICSocket, NULL);
  769. if (pAddr != NULL) {
  770. ICSocket * pSocket = (ICSocket *)pAddr;
  771. //dprintf(">>>>>>>> %#x AbortSocket %#x [%#x]\n", GetCurrentThreadId(), pSocket, pSocket->GetSocket());
  772. pSocket->Abort();
  773. pSocket->Dereference();
  774. }
  775. DEBUG_LEAVE(0);
  776. }
  777. DWORD
  778. INTERNET_HANDLE_BASE::Refresh()
  779. /*++
  780. Routine Description:
  781. Refreshes the proxy info on an InternetOpen() HINTERNET based on the parameters
  782. Assumes: 1. The parameters have already been validated in the API that calls
  783. this method (i.e. InternetOpen(), InternetSetOption())
  784. Return Value:
  785. DWORD
  786. Success - ERROR_SUCCESS
  787. --*/
  788. {
  789. //
  790. // Reload the proxy info from registry into the GlobalProxyInfo object,
  791. // unless it was changed in-process to something else.
  792. //
  793. if (!g_pGlobalProxyInfo->IsModifiedInProcess()) {
  794. return LoadProxySettings();
  795. } else {
  796. //
  797. // not using global proxy or it has been set to something other
  798. // than the registry contents. Just return success
  799. //
  800. return ERROR_SUCCESS;
  801. }
  802. }
  803. DWORD
  804. INTERNET_HANDLE_BASE::SetProxyInfo(
  805. IN DWORD dwAccessType,
  806. IN LPCSTR lpszProxy OPTIONAL,
  807. IN LPCSTR lpszProxyBypass OPTIONAL
  808. )
  809. /*++
  810. Routine Description:
  811. Sets the proxy info on an InternetOpen() HINTERNET based on the parameters
  812. Assumes: 1. The parameters have already been validated in the API that calls
  813. this method (i.e. InternetOpen(), InternetSetOption())
  814. Arguments:
  815. dwAccessType - type of proxy access required
  816. lpszProxy - pointer to proxy server list
  817. lpszProxyBypass - pointer to proxy bypass list
  818. Return Value:
  819. DWORD
  820. Success - ERROR_SUCCESS
  821. Failure - ERROR_INVALID_PARAMETER
  822. The lpszProxy or lpszProxyBypass list was bad
  823. ERROR_NOT_ENOUGH_MEMORY
  824. Failed to create an object or allocate space for a list,
  825. etc.
  826. --*/
  827. {
  828. DEBUG_ENTER((DBG_INET,
  829. Dword,
  830. "INTERNET_HANDLE_BASE::SetProxyInfo",
  831. "%s (%d), %#x (%q), %#x (%q)",
  832. InternetMapOpenType(dwAccessType),
  833. dwAccessType,
  834. lpszProxy,
  835. lpszProxy,
  836. lpszProxyBypass,
  837. lpszProxyBypass
  838. ));
  839. //
  840. // Session and HTTP Request objects can have proxy information
  841. //
  842. INET_ASSERT((GetHandleType()==TypeInternetHandle) || (GetHandleType()==TypeHttpRequestHandle));
  843. /*
  844. We are setting the proxy information for an InternetOpen() handle. Based on
  845. the current and new settings we do the following (Note: the handle is
  846. initialized to DIRECT operation):
  847. current access
  848. +---------------------------------------------------------------
  849. new | DIRECT | PROXY | PRECONFIG
  850. access | | |
  851. +-----------+--------------------+--------------------+---------------------
  852. | DIRECT | No action | Delete proxy info | Remove reference to
  853. | | | | global proxy info
  854. +-----------+--------------------+--------------------+---------------------
  855. | PROXY | Set new proxy info | Delete proxy info. | Remove reference to
  856. | | | Set new proxy info | global proxy info.
  857. | | | | Set new proxy info
  858. +-----------+--------------------+--------------------+---------------------
  859. | PRECONFIG | Set proxy info to | Delete proxy info. | No action
  860. | | global proxy info | Set proxy info to |
  861. | | | global proxy info |
  862. +-----------+--------------------+--------------------+---------------------
  863. */
  864. DWORD error = ERROR_SUCCESS;
  865. PROXY_INFO * proxyInfo = NULL;
  866. //
  867. // acquire proxy info for exclusive access
  868. //
  869. if (!AcquireProxyInfo(TRUE))
  870. {
  871. error = ERROR_NOT_ENOUGH_MEMORY;
  872. goto quit;
  873. }
  874. if (IsProxy()) {
  875. //
  876. // delete private proxy info, or unlink from global proxy info
  877. //
  878. SafeDeleteProxyInfo();
  879. }
  880. switch (dwAccessType)
  881. {
  882. case WINHTTP_ACCESS_TYPE_NO_PROXY:
  883. proxyInfo = PROXY_INFO_DIRECT;
  884. break;
  885. case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
  886. {
  887. INET_ASSERT(!IsProxy());
  888. INTERNET_HANDLE_OBJECT * pSession;
  889. if (IsCopy())
  890. {
  891. pSession = GetRootHandle(this);
  892. }
  893. else
  894. {
  895. pSession = static_cast<INTERNET_HANDLE_OBJECT *>(this);
  896. INET_ASSERT(pSession->IsValid(TypeInternetHandle) == ERROR_SUCCESS);
  897. }
  898. proxyInfo = New PROXY_INFO;
  899. if (proxyInfo != NULL) {
  900. proxyInfo->InitializeProxySettings();
  901. proxyInfo->SetSessionObject(pSession);
  902. error = proxyInfo->GetError();
  903. if (error == ERROR_SUCCESS &&
  904. lpszProxy )
  905. {
  906. INTERNET_PROXY_INFO_EX info;
  907. memset(&info, 0, sizeof(info));
  908. info.dwStructSize = sizeof(info);
  909. info.dwFlags = (PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY);
  910. info.lpszProxy = lpszProxy;
  911. info.lpszProxyBypass = lpszProxyBypass;
  912. error = proxyInfo->SetProxySettings(&info, TRUE /*modified*/);
  913. }
  914. if (error != ERROR_SUCCESS) {
  915. delete proxyInfo;
  916. proxyInfo = NULL;
  917. }
  918. } else {
  919. error = ERROR_NOT_ENOUGH_MEMORY;
  920. }
  921. break;
  922. }
  923. case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY:
  924. {
  925. INTERNET_HANDLE_OBJECT * pSession;
  926. if (IsCopy())
  927. {
  928. pSession = GetRootHandle(this);
  929. }
  930. else
  931. {
  932. pSession = static_cast<INTERNET_HANDLE_OBJECT *>(this);
  933. INET_ASSERT(pSession->IsValid(TypeInternetHandle) == ERROR_SUCCESS);
  934. }
  935. // Refresh global proxy info.
  936. Refresh();
  937. proxyInfo = New PROXY_INFO;
  938. if (proxyInfo != NULL) {
  939. proxyInfo->InitializeProxySettings();
  940. proxyInfo->SetSessionObject(pSession);
  941. error = proxyInfo->GetError();
  942. if (error == ERROR_SUCCESS)
  943. {
  944. INTERNET_PROXY_INFO_EX info;
  945. memset(&info, 0, sizeof(info));
  946. info.dwStructSize = sizeof(info);
  947. INET_ASSERT(g_pGlobalProxyInfo != NULL);
  948. error = g_pGlobalProxyInfo->GetProxySettings(&info, FALSE);
  949. if (error == ERROR_SUCCESS)
  950. {
  951. error = proxyInfo->SetProxySettings(&info, TRUE /*modified*/);
  952. if (info.lpszProxy)
  953. {
  954. FREE_MEMORY(info.lpszProxy);
  955. }
  956. if (info.lpszProxyBypass)
  957. {
  958. FREE_MEMORY(info.lpszProxyBypass);
  959. }
  960. }
  961. }
  962. if (error != ERROR_SUCCESS)
  963. {
  964. delete proxyInfo;
  965. proxyInfo = NULL;
  966. }
  967. } else {
  968. error = ERROR_NOT_ENOUGH_MEMORY;
  969. }
  970. break;
  971. }
  972. default:
  973. proxyInfo = NULL;
  974. break;
  975. }
  976. SetProxyInfo(proxyInfo);
  977. ReleaseProxyInfo();
  978. quit:
  979. DEBUG_LEAVE(error);
  980. return error;
  981. }
  982. DWORD
  983. INTERNET_HANDLE_BASE::GetProxyStringInfo(
  984. OUT LPVOID lpBuffer,
  985. IN OUT LPDWORD lpdwBufferLength
  986. )
  987. /*++
  988. Routine Description:
  989. Returns the current proxy information for this INTERNET_HANDLE_BASE
  990. Arguments:
  991. lpBuffer - pointer to buffer where WINHTTP_PROXY_INFOA will be
  992. written, and any proxy strings (if sufficient space)
  993. lpdwBufferLength - IN: number of bytes in lpBuffer
  994. OUT: number of bytes returned in lpBuffer
  995. Return Value:
  996. DWORD
  997. Success - ERROR_SUCCESS
  998. Failure - ERROR_INSUFFICIENT_BUFFER
  999. lpBuffer doesn't have enough space to hold the proxy
  1000. information. *lpdwBufferLength has the required size
  1001. --*/
  1002. {
  1003. DEBUG_ENTER((DBG_INET,
  1004. Dword,
  1005. "INTERNET_HANDLE_BASE::GetProxyStringInfo",
  1006. "%#x, %#x [%d]",
  1007. lpBuffer,
  1008. lpdwBufferLength,
  1009. lpdwBufferLength ? *lpdwBufferLength : 0
  1010. ));
  1011. INET_ASSERT(!IsCopy());
  1012. AcquireProxyInfo(FALSE);
  1013. DWORD error;
  1014. if (IsProxy()) {
  1015. error = _ProxyInfo->GetProxyStringInfo(lpBuffer, lpdwBufferLength);
  1016. } else {
  1017. if (*lpdwBufferLength >= sizeof(WINHTTP_PROXY_INFOA)) {
  1018. WINHTTP_PROXY_INFOA * lpInfo = (WINHTTP_PROXY_INFOA *)lpBuffer;
  1019. lpInfo->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
  1020. lpInfo->lpszProxy = NULL;
  1021. lpInfo->lpszProxyBypass = NULL;
  1022. error = ERROR_SUCCESS;
  1023. } else {
  1024. error = ERROR_INSUFFICIENT_BUFFER;
  1025. }
  1026. *lpdwBufferLength = sizeof(WINHTTP_PROXY_INFOA);
  1027. }
  1028. ReleaseProxyInfo();
  1029. DEBUG_LEAVE(error);
  1030. return error;
  1031. }
  1032. DWORD
  1033. INTERNET_HANDLE_BASE::GetProxyInfo(
  1034. IN AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. Returns all proxy information based on a protocol scheme
  1039. Arguments:
  1040. tProtocol - protocol to get proxy info for
  1041. lptScheme - returned scheme
  1042. lplpszHostName - returned proxy name
  1043. lpdwHostNameLength - returned length of proxy name
  1044. lpHostPort - returned proxy port
  1045. Return Value:
  1046. BOOL
  1047. Success - TRUE
  1048. Failure - FALSE
  1049. --*/
  1050. {
  1051. DEBUG_ENTER((DBG_INET,
  1052. Dword,
  1053. "INTERNET_HANDLE_BASE::GetProxyInfo",
  1054. "%#x",
  1055. ppQueryForProxyInfo
  1056. ));
  1057. INET_ASSERT((GetHandleType() == TypeInternetHandle) ||
  1058. (GetHandleType() == TypeHttpRequestHandle));
  1059. DWORD error;
  1060. AcquireProxyInfo(FALSE);
  1061. if ( _ProxyInfo && _ProxyInfo != PROXY_INFO_DIRECT )
  1062. {
  1063. error = _ProxyInfo->QueryProxySettings(ppQueryForProxyInfo);
  1064. }
  1065. else
  1066. {
  1067. error = ERROR_SUCCESS;
  1068. (*ppQueryForProxyInfo)->SetUseProxy(FALSE);
  1069. }
  1070. ReleaseProxyInfo();
  1071. DEBUG_LEAVE(error);
  1072. return error;
  1073. }
  1074. BOOL
  1075. INTERNET_HANDLE_BASE::RedoSendRequest(
  1076. IN OUT LPDWORD lpdwError,
  1077. IN DWORD dwSecureStatus,
  1078. IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo,
  1079. IN CServerInfo *pOriginServer,
  1080. IN CServerInfo *pProxyServer
  1081. )
  1082. {
  1083. INET_ASSERT(!IsCopy());
  1084. BOOL rc;
  1085. AcquireProxyInfo(FALSE);
  1086. if ( _ProxyInfo )
  1087. {
  1088. rc = _ProxyInfo->RedoSendRequest(
  1089. lpdwError,
  1090. dwSecureStatus,
  1091. pQueryForProxyInfo,
  1092. pOriginServer,
  1093. pProxyServer
  1094. );
  1095. }
  1096. else
  1097. {
  1098. rc = FALSE;
  1099. }
  1100. ReleaseProxyInfo();
  1101. return rc;
  1102. }
  1103. INTERNET_HANDLE_OBJECT::INTERNET_HANDLE_OBJECT
  1104. (LPCSTR ua, DWORD access, LPSTR proxy, LPSTR bypass, DWORD flags)
  1105. : INTERNET_HANDLE_BASE (ua, access, proxy, bypass, flags)
  1106. {
  1107. DEBUG_ENTER((DBG_OBJECTS,
  1108. None,
  1109. "INTERNET_HANDLE_OBJECT::INTERNET_HANDLE_OBJECT",
  1110. NULL
  1111. ));
  1112. InterlockedIncrement(&g_cSessionCount);
  1113. if (g_pAsyncCount)
  1114. {
  1115. if (flags & WINHTTP_FLAG_ASYNC)
  1116. {
  1117. _Status = g_pAsyncCount->AddRef();
  1118. }
  1119. }
  1120. else
  1121. {
  1122. RIP(FALSE);
  1123. }
  1124. InitializeSerializedList(&_ServerInfoList);
  1125. //
  1126. // WinHttpX supports session cookies. Each session has it's own
  1127. // cookie jar, instead of a shared global cookie jar as in WinInet.
  1128. //
  1129. _CookieJar = NULL;
  1130. _pOptionalParams = NULL;
  1131. _pSessionCertCache = NULL;
  1132. _pAutoProxy = NULL;
  1133. _hAPBinding = NULL;
  1134. _pResolverCache = New CResolverCache(&_Status);
  1135. if (!_pResolverCache)
  1136. {
  1137. _Status = ERROR_NOT_ENOUGH_MEMORY;
  1138. }
  1139. if (_Status == ERROR_SUCCESS)
  1140. {
  1141. _CookieJar = CreateCookieJar();
  1142. if (_CookieJar == NULL)
  1143. _Status = ERROR_NOT_ENOUGH_MEMORY;
  1144. }
  1145. if (_Status == ERROR_SUCCESS)
  1146. {
  1147. _pSessionCertCache = New SECURITY_CACHE_LIST;
  1148. if (!_pSessionCertCache || !_pSessionCertCache->Initialize())
  1149. {
  1150. _Status = ERROR_NOT_ENOUGH_MEMORY;
  1151. if (_pSessionCertCache)
  1152. {
  1153. delete _pSessionCertCache;
  1154. _pSessionCertCache = NULL;
  1155. }
  1156. }
  1157. }
  1158. if (_Status == ERROR_SUCCESS)
  1159. {
  1160. _pAutoProxy = New CAutoProxy(this);
  1161. if (!_pAutoProxy || !_pAutoProxy->Initialize())
  1162. {
  1163. _Status = ERROR_NOT_ENOUGH_MEMORY;
  1164. }
  1165. }
  1166. DEBUG_LEAVE(0);
  1167. };
  1168. INTERNET_HANDLE_OBJECT::~INTERNET_HANDLE_OBJECT ( )
  1169. {
  1170. DEBUG_ENTER((DBG_OBJECTS,
  1171. None,
  1172. "INTERNET_HANDLE_OBJECT::~INTERNET_HANDLE_OBJECT",
  1173. NULL
  1174. ));
  1175. PurgeServerInfoList(TRUE);
  1176. TerminateSerializedList(&_ServerInfoList);
  1177. if (_pResolverCache)
  1178. {
  1179. _pResolverCache->EmptyHandlesList();
  1180. delete _pResolverCache;
  1181. }
  1182. delete _pOptionalParams;
  1183. _pOptionalParams = NULL;
  1184. // Delete Cookie Jar
  1185. CloseCookieJar(_CookieJar);
  1186. _CookieJar = NULL;
  1187. if (_hAPBinding)
  1188. {
  1189. ::RpcBindingFree(&_hAPBinding);
  1190. _hAPBinding = NULL;
  1191. }
  1192. if (_pSessionCertCache)
  1193. _pSessionCertCache->Release();
  1194. if (_pAutoProxy)
  1195. delete _pAutoProxy;
  1196. if (g_pAsyncCount)
  1197. {
  1198. if (_Async)
  1199. g_pAsyncCount->Release();
  1200. }
  1201. else
  1202. {
  1203. RIP(FALSE);
  1204. }
  1205. DEBUG_LEAVE(0);
  1206. }
  1207. //
  1208. // This function walks up to the InternetOpen handle from either
  1209. // a connect handle (child) or a request handle (grandchild).
  1210. // We only go one or two hops rather than recurse.
  1211. //
  1212. INTERNET_HANDLE_OBJECT* GetRootHandle (HANDLE_OBJECT* pHandle)
  1213. {
  1214. pHandle = (HANDLE_OBJECT*) pHandle->GetParent();
  1215. INET_ASSERT (pHandle);
  1216. if (pHandle->GetHandleType() == TypeInternetHandle)
  1217. return (INTERNET_HANDLE_OBJECT*) pHandle;
  1218. pHandle = (HANDLE_OBJECT*) pHandle->GetParent();
  1219. INET_ASSERT (pHandle);
  1220. INET_ASSERT (pHandle->GetHandleType() == TypeInternetHandle);
  1221. return (INTERNET_HANDLE_OBJECT*) pHandle;
  1222. }
  1223. BOOL INTERNET_HANDLE_OBJECT::ClearPassportCookies(PSTR pszUrl)
  1224. {
  1225. BOOL fRetVal = FALSE;
  1226. char * pchRDomain = NULL;
  1227. char * pchPath = NULL;
  1228. BOOL fSecure;
  1229. if (!PathAndRDomainFromURL(pszUrl, &pchRDomain, &pchPath, &fSecure, FALSE))
  1230. {
  1231. return fRetVal;
  1232. }
  1233. CCookieJar* pcj = _CookieJar;
  1234. if (pcj->_csCookieJar.Lock())
  1235. {
  1236. FILETIME ftNow;
  1237. GetSystemTimeAsFileTime(&ftNow);
  1238. CCookieLocation *pLocation = pcj->GetCookies(pchRDomain, pchPath, NULL, &ftNow);
  1239. while (pLocation)
  1240. {
  1241. CCookie *pCookie = NULL;
  1242. if (NULL != (pCookie = pLocation->GetCookie("MSPAuth", FALSE)))
  1243. {
  1244. pCookie->SetValue(NULL);
  1245. }
  1246. if (NULL != (pCookie = pLocation->GetCookie("MSPProf", FALSE)))
  1247. {
  1248. pCookie->SetValue(NULL);
  1249. }
  1250. if (NULL != (pCookie = pLocation->GetCookie("MSPProfC", FALSE)))
  1251. {
  1252. pCookie->SetValue(NULL);
  1253. }
  1254. if (NULL != (pCookie = pLocation->GetCookie("MSPSec", FALSE)))
  1255. {
  1256. pCookie->SetValue(NULL);
  1257. }
  1258. pLocation = pcj->GetCookies(pchRDomain, pchPath, pLocation, &ftNow);
  1259. } // while (pLocation)
  1260. pcj->_csCookieJar.Unlock();
  1261. } // if pcj->_csCookieJar.Lock()
  1262. fRetVal = TRUE;
  1263. if (pchRDomain)
  1264. {
  1265. FREE_MEMORY(pchRDomain);
  1266. }
  1267. if (pchPath)
  1268. {
  1269. FREE_MEMORY(pchPath);
  1270. }
  1271. return fRetVal;
  1272. }
  1273. //
  1274. //
  1275. //INTERNET_HANDLE_BASE::SetDwordOption() and HTTP_REQUEST_HANDLE_OBJECT::SetDwordOption()
  1276. //maintain DWORD options with the following semantics:
  1277. // 1) Settings affect behavior of request and are per-request configureable.
  1278. // 2) Defaults for new requests are stored in the session and those defaults are per-session configureable.
  1279. //
  1280. //
  1281. /*
  1282. * When called from API functions,
  1283. * caller should SetLastError() in case of failure
  1284. */
  1285. BOOL
  1286. INTERNET_HANDLE_OBJECT::SetDwordOption(
  1287. IN DWORD dwDwordOption,
  1288. IN DWORD dwDwordValue
  1289. )
  1290. {
  1291. BOOL bRetval = TRUE;
  1292. if (!_pOptionalParams)
  1293. {
  1294. _pOptionalParams = New OPTIONAL_SESSION_PARAMS();
  1295. if (!_pOptionalParams)
  1296. {
  1297. bRetval = FALSE;
  1298. goto quit;
  1299. }
  1300. }
  1301. switch (dwDwordOption)
  1302. {
  1303. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  1304. _pOptionalParams->dwResolveTimeout = dwDwordValue;
  1305. break;
  1306. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  1307. _pOptionalParams->dwConnectTimeout = dwDwordValue;
  1308. break;
  1309. case WINHTTP_OPTION_CONNECT_RETRIES:
  1310. _pOptionalParams->dwConnectRetries = dwDwordValue;
  1311. break;
  1312. case WINHTTP_OPTION_SEND_TIMEOUT:
  1313. _pOptionalParams->dwSendTimeout = dwDwordValue;
  1314. break;
  1315. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  1316. _pOptionalParams->dwReceiveTimeout = dwDwordValue;
  1317. // Ensure that the ReceiveResponse timeout is not less than the Receive timeout
  1318. _pOptionalParams->dwReceiveResponseTimeout = max(dwDwordValue, _pOptionalParams->dwReceiveResponseTimeout);
  1319. break;
  1320. case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
  1321. // Ensure that the ReceiveResponse timeout is not less than the Receive timeout
  1322. _pOptionalParams->dwReceiveResponseTimeout = max(dwDwordValue, _pOptionalParams->dwReceiveTimeout);
  1323. break;
  1324. case WINHTTP_OPTION_REDIRECT_POLICY:
  1325. _pOptionalParams->dwRedirectPolicy = dwDwordValue;
  1326. break;
  1327. case WINHTTP_OPTION_AUTOLOGON_POLICY:
  1328. _pOptionalParams->dwAutoLogonPolicy = dwDwordValue;
  1329. break;
  1330. case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
  1331. _pOptionalParams->dwMaxHttpAutomaticRedirects = dwDwordValue;
  1332. break;
  1333. case WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE:
  1334. _pOptionalParams->dwMaxHttpStatusContinues = dwDwordValue;
  1335. break;
  1336. case WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE:
  1337. _pOptionalParams->dwMaxResponseHeaderSize = dwDwordValue;
  1338. break;
  1339. case WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE:
  1340. _pOptionalParams->dwMaxResponseDrainSize = dwDwordValue;
  1341. break;
  1342. default:
  1343. INET_ASSERT(0);
  1344. bRetval = FALSE;
  1345. }
  1346. quit:
  1347. return bRetval;
  1348. }
  1349. /*
  1350. * When called from API functions,
  1351. * caller should SetLastError() in case of failure
  1352. */
  1353. BOOL
  1354. INTERNET_HANDLE_OBJECT::SetTimeout(
  1355. IN DWORD dwTimeoutOption,
  1356. IN DWORD dwTimeoutValue
  1357. )
  1358. {
  1359. switch (dwTimeoutOption)
  1360. {
  1361. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  1362. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  1363. case WINHTTP_OPTION_CONNECT_RETRIES:
  1364. case WINHTTP_OPTION_SEND_TIMEOUT:
  1365. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  1366. case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
  1367. return SetDwordOption( dwTimeoutOption, dwTimeoutValue);
  1368. default:
  1369. INET_ASSERT(0);
  1370. return FALSE;
  1371. }
  1372. }
  1373. /*
  1374. * When called from API functions,
  1375. * caller should SetLastError() in case of failure
  1376. */
  1377. BOOL
  1378. INTERNET_HANDLE_OBJECT::SetTimeouts(
  1379. IN DWORD dwResolveTimeout,
  1380. IN DWORD dwConnectTimeout,
  1381. IN DWORD dwSendTimeout,
  1382. IN DWORD dwReceiveTimeout
  1383. )
  1384. {
  1385. BOOL bRetval = TRUE;
  1386. if (!_pOptionalParams)
  1387. {
  1388. _pOptionalParams = New OPTIONAL_SESSION_PARAMS();
  1389. if (!_pOptionalParams)
  1390. {
  1391. bRetval = FALSE;
  1392. goto quit;
  1393. }
  1394. }
  1395. _pOptionalParams->dwResolveTimeout = dwResolveTimeout;
  1396. _pOptionalParams->dwConnectTimeout = dwConnectTimeout;
  1397. _pOptionalParams->dwSendTimeout = dwSendTimeout;
  1398. _pOptionalParams->dwReceiveTimeout = dwReceiveTimeout;
  1399. // Ensure that the ReceiveResponse timeout is not less than the Receive timeout
  1400. _pOptionalParams->dwReceiveResponseTimeout = max(dwReceiveTimeout, _pOptionalParams->dwReceiveResponseTimeout);
  1401. quit:
  1402. return bRetval;
  1403. }
  1404. /*
  1405. * When called from API functions,
  1406. * caller should SetLastError() in case of failure
  1407. */
  1408. BOOL
  1409. INTERNET_HANDLE_OBJECT::GetDwordOption(
  1410. IN DWORD dwDwordOption,
  1411. OUT DWORD* pdwDwordValue
  1412. )
  1413. {
  1414. BOOL bRetval = TRUE;
  1415. if (!_pOptionalParams)
  1416. {
  1417. _pOptionalParams = New OPTIONAL_SESSION_PARAMS();
  1418. if (!_pOptionalParams)
  1419. {
  1420. bRetval = FALSE;
  1421. goto quit;
  1422. }
  1423. }
  1424. switch (dwDwordOption)
  1425. {
  1426. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  1427. *pdwDwordValue = _pOptionalParams->dwResolveTimeout;
  1428. break;
  1429. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  1430. *pdwDwordValue = _pOptionalParams->dwConnectTimeout;
  1431. break;
  1432. case WINHTTP_OPTION_CONNECT_RETRIES:
  1433. *pdwDwordValue = _pOptionalParams->dwConnectRetries;
  1434. break;
  1435. case WINHTTP_OPTION_SEND_TIMEOUT:
  1436. *pdwDwordValue = _pOptionalParams->dwSendTimeout;
  1437. break;
  1438. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  1439. *pdwDwordValue = _pOptionalParams->dwReceiveTimeout;
  1440. break;
  1441. case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
  1442. *pdwDwordValue = _pOptionalParams->dwReceiveResponseTimeout;
  1443. break;
  1444. case WINHTTP_OPTION_REDIRECT_POLICY:
  1445. *pdwDwordValue = _pOptionalParams->dwRedirectPolicy;
  1446. break;
  1447. case WINHTTP_OPTION_AUTOLOGON_POLICY:
  1448. *pdwDwordValue = _pOptionalParams->dwAutoLogonPolicy;
  1449. break;
  1450. case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
  1451. *pdwDwordValue = _pOptionalParams->dwMaxHttpAutomaticRedirects;
  1452. break;
  1453. case WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE:
  1454. *pdwDwordValue = _pOptionalParams->dwMaxHttpStatusContinues;
  1455. break;
  1456. case WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE:
  1457. *pdwDwordValue = _pOptionalParams->dwMaxResponseHeaderSize;
  1458. break;
  1459. case WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE:
  1460. *pdwDwordValue = _pOptionalParams->dwMaxResponseDrainSize;
  1461. break;
  1462. default:
  1463. INET_ASSERT(0);
  1464. bRetval = FALSE;
  1465. break;
  1466. }
  1467. quit:
  1468. return bRetval;
  1469. }
  1470. /*
  1471. * When called from API functions,
  1472. * caller should SetLastError() in case of failure
  1473. */
  1474. BOOL
  1475. INTERNET_HANDLE_OBJECT::GetTimeout(
  1476. IN DWORD dwTimeoutOption,
  1477. OUT DWORD* pdwTimeoutValue
  1478. )
  1479. {
  1480. switch (dwTimeoutOption)
  1481. {
  1482. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  1483. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  1484. case WINHTTP_OPTION_CONNECT_RETRIES:
  1485. case WINHTTP_OPTION_SEND_TIMEOUT:
  1486. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  1487. case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
  1488. return GetDwordOption( dwTimeoutOption, pdwTimeoutValue);
  1489. default:
  1490. INET_ASSERT(0);
  1491. return FALSE;
  1492. }
  1493. }