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.

2000 lines
48 KiB

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