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.

1373 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. proxysup.hxx
  5. Abstract:
  6. Contains class definition for proxy server and proxy bypass list
  7. Contents:
  8. PROXY_BYPASS_LIST_ENTRY
  9. PROXY_BYPASS_LIST
  10. PROXY_SERVER_LIST_ENTRY
  11. PROXY_SERVER_LIST
  12. PROXY_INFO
  13. PROXY_STATE
  14. BAD_PROXY_LIST_ENTRY
  15. BAD_PROXY_LIST
  16. Author:
  17. Richard L Firth (rfirth) 03-Feb-1996
  18. Revision History:
  19. 03-Feb-1996 rfirth
  20. Created
  21. 29-Nov-1996 arthurbi
  22. Added support for external Auto-Proxy Dlls
  23. --*/
  24. //
  25. // defintions
  26. //
  27. #define MAX_BAD_PROXY_ENTRIES 20
  28. #define BAD_PROXY_EXPIRES_TIME (30 * 60 * (LONGLONG)10000000) // 30 minutes
  29. #define PROXY_INFO_DIRECT (reinterpret_cast<PROXY_INFO *>(-1L))
  30. //
  31. // prototypes
  32. //
  33. BOOL
  34. IsLocalMacro(
  35. IN LPSTR lpszMetaName,
  36. IN DWORD dwMetaNameLength
  37. );
  38. //
  39. // class implementations
  40. //
  41. class CServerInfo;
  42. class PROXY_INFO_GLOBAL;
  43. class INTERNET_HANDLE_OBJECT;
  44. extern PROXY_INFO_GLOBAL * g_pGlobalProxyInfo;
  45. //
  46. // BAD_PROXY_LIST_ENTRY - represents a proxy that is has failed
  47. // while being used, for some reason, such as DNS or connection failure.
  48. //
  49. class BAD_PROXY_LIST_ENTRY {
  50. public:
  51. //
  52. // _ftLastFailed - Last time this proxy was accessed and failed
  53. //
  54. FILETIME _ftLastFailed;
  55. //
  56. // _fEntryUsed - Since these objects are initalily part of an array
  57. // this boolean tells whether its actually a valid entry
  58. //
  59. BOOL _fEntryUsed;
  60. //
  61. // _lpszProxyName - Name of the Proxy that is bad
  62. //
  63. LPSTR _lpszProxyName;
  64. //
  65. // _ipProxyPort - Port number of the proxy
  66. //
  67. INTERNET_PORT _ipProxyPort;
  68. //
  69. // destructor ...
  70. //
  71. ~BAD_PROXY_LIST_ENTRY()
  72. {
  73. if ( _fEntryUsed && _lpszProxyName )
  74. {
  75. FREE_MEMORY(_lpszProxyName);
  76. }
  77. }
  78. BOOL
  79. IsEntryExpired( FILETIME *pCurrentGmtTime )
  80. {
  81. LONGLONG ElapsedTime;
  82. ElapsedTime = (*(LONGLONG *)pCurrentGmtTime) - (*(LONGLONG *)&_ftLastFailed);
  83. if( ElapsedTime > BAD_PROXY_EXPIRES_TIME )
  84. {
  85. return TRUE;
  86. }
  87. return FALSE;
  88. }
  89. BOOL
  90. IsMatch( LPSTR lpszProxyName, INTERNET_PORT ipProxyPort )
  91. {
  92. if ( _lpszProxyName &&
  93. _ipProxyPort == ipProxyPort &&
  94. lstrcmpi(lpszProxyName, _lpszProxyName ) == 0 )
  95. {
  96. return TRUE;
  97. }
  98. return FALSE;
  99. }
  100. DWORD
  101. SetEntry( LPSTR lpszProxyName, INTERNET_PORT ipProxyPort, FILETIME ftLastFailed )
  102. {
  103. if ( _fEntryUsed )
  104. {
  105. INET_ASSERT(_lpszProxyName );
  106. FREE_MEMORY(_lpszProxyName );
  107. _fEntryUsed = FALSE;
  108. }
  109. _lpszProxyName =
  110. NewString(lpszProxyName);
  111. if ( ! _lpszProxyName )
  112. {
  113. return ERROR_NOT_ENOUGH_MEMORY;
  114. }
  115. _ipProxyPort = ipProxyPort;
  116. _ftLastFailed = ftLastFailed ;
  117. _fEntryUsed = TRUE;
  118. return ERROR_SUCCESS;
  119. }
  120. };
  121. //
  122. // BAD_PROXY_LIST - maintains a list of proxies that have are done, or not working
  123. // properly to satisfy requests.
  124. //
  125. class BAD_PROXY_LIST {
  126. private:
  127. //
  128. // rgBadEntries - Array of proxies that have failed.
  129. //
  130. BAD_PROXY_LIST_ENTRY rgBadEntries[MAX_BAD_PROXY_ENTRIES];
  131. //
  132. // _dwEntries - Number of entries
  133. //
  134. DWORD _dwEntries;
  135. public:
  136. BAD_PROXY_LIST()
  137. {
  138. _dwEntries = 0;
  139. for ( DWORD i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  140. {
  141. rgBadEntries[i]._fEntryUsed = FALSE;
  142. }
  143. }
  144. VOID
  145. CheckForExpiredEntries(VOID)
  146. {
  147. FILETIME ftCurTime;
  148. if ( _dwEntries == 0 ) {
  149. return;
  150. }
  151. GetCurrentGmtTime(&ftCurTime);
  152. for ( DWORD i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  153. {
  154. if ( rgBadEntries[i]._fEntryUsed &&
  155. rgBadEntries[i].IsEntryExpired(&ftCurTime) )
  156. {
  157. _dwEntries--;
  158. rgBadEntries[i]._fEntryUsed = FALSE;
  159. UPDATE_GLOBAL_PROXY_VERSION();
  160. }
  161. }
  162. }
  163. DWORD
  164. AddEntry( LPSTR lpszProxyHost, INTERNET_PORT ipProxyPort)
  165. {
  166. DWORD i;
  167. FILETIME ftCurTime;
  168. GetCurrentGmtTime(&ftCurTime);
  169. UPDATE_GLOBAL_PROXY_VERSION();
  170. //
  171. // BUGBUG [arthurbi] this should be combined into one loop.
  172. //
  173. //
  174. // Check to see if the new entry is already in the array,
  175. // if so use it.
  176. //
  177. for ( i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  178. {
  179. if ( rgBadEntries[i]._fEntryUsed &&
  180. rgBadEntries[i].IsMatch(lpszProxyHost, ipProxyPort) )
  181. {
  182. rgBadEntries[i]._ftLastFailed = ftCurTime;
  183. return ERROR_SUCCESS;
  184. }
  185. }
  186. //
  187. // Check to see if there is an unused entry, or an
  188. // entry that has expired.
  189. //
  190. for ( i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  191. {
  192. if ( ! rgBadEntries[i]._fEntryUsed )
  193. {
  194. break;
  195. }
  196. if ( rgBadEntries[i].IsEntryExpired(&ftCurTime) )
  197. {
  198. _dwEntries --;
  199. break;
  200. }
  201. }
  202. //
  203. // If we haven't found an array entry we can use,
  204. // Find the oldest entry in the array.
  205. //
  206. if ( i == ARRAY_ELEMENTS(rgBadEntries) )
  207. {
  208. DWORD dwOldestIndex = 0;
  209. FILETIME ftOldest = rgBadEntries[0]._ftLastFailed;
  210. for ( i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  211. {
  212. INET_ASSERT(rgBadEntries[i]._fEntryUsed);
  213. if ( (*(LONGLONG *)&rgBadEntries[i]._ftLastFailed) < (*(LONGLONG *)&ftOldest) )
  214. {
  215. ftOldest = rgBadEntries[i]._ftLastFailed;
  216. dwOldestIndex = i;
  217. _dwEntries --;
  218. }
  219. }
  220. i = dwOldestIndex;
  221. }
  222. INET_ASSERT(i != ARRAY_ELEMENTS(rgBadEntries));
  223. _dwEntries ++;
  224. return rgBadEntries[i].SetEntry(lpszProxyHost, ipProxyPort, ftCurTime);
  225. }
  226. BOOL
  227. IsBadProxyName(LPSTR lpszProxyHost, INTERNET_PORT ipProxyPort)
  228. {
  229. DWORD i;
  230. FILETIME ftCurTime;
  231. //
  232. // Try to find this proxy in our "black list" of bad
  233. // proxys. If we find return TRUE.
  234. //
  235. GetCurrentGmtTime(&ftCurTime);
  236. for ( i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  237. {
  238. if ( rgBadEntries[i]._fEntryUsed &&
  239. rgBadEntries[i].IsMatch(lpszProxyHost, ipProxyPort) &&
  240. ! rgBadEntries[i].IsEntryExpired(&ftCurTime) )
  241. {
  242. return TRUE;
  243. }
  244. }
  245. return FALSE;
  246. }
  247. VOID
  248. ClearList(
  249. VOID
  250. )
  251. {
  252. DWORD i;
  253. for ( i = 0; i < ARRAY_ELEMENTS(rgBadEntries); i++ )
  254. {
  255. rgBadEntries[i]._fEntryUsed = FALSE;
  256. }
  257. _dwEntries = 0;
  258. }
  259. };
  260. //
  261. // PROXY_BYPASS_LIST_ENTRY - describes a server or address range that should
  262. // not go via proxy
  263. //
  264. class PROXY_BYPASS_LIST_ENTRY {
  265. friend class PROXY_BYPASS_LIST;
  266. private:
  267. //
  268. // _List - there may be a variable number of bypass entries
  269. //
  270. LIST_ENTRY _List;
  271. //
  272. // _Scheme - scheme to be bypassed if significant, else 0
  273. //
  274. INTERNET_SCHEME _Scheme;
  275. //
  276. // _Name - the name of the server to bypass the proxy. May contain wildcard
  277. // characters (*)
  278. //
  279. ICSTRING _Name;
  280. //
  281. // _Port - port number if significant, else 0
  282. //
  283. INTERNET_PORT _Port;
  284. //
  285. // _LocalSemantics - TRUE if we match local addresses (non-IP address names
  286. // not containing periods)
  287. //
  288. BOOL _LocalSemantics;
  289. //
  290. // _Error - errors stored here from initialization
  291. //
  292. DWORD _Error;
  293. public:
  294. PROXY_BYPASS_LIST_ENTRY(
  295. IN INTERNET_SCHEME tScheme,
  296. IN LPSTR lpszHostName,
  297. IN DWORD dwHostNameLength,
  298. IN INTERNET_PORT nPort
  299. ) {
  300. DEBUG_ENTER((DBG_OBJECTS,
  301. None,
  302. "PROXY_BYPASS_LIST_ENTRY",
  303. "%s, %q, %d, %d",
  304. InternetMapScheme(tScheme),
  305. lpszHostName,
  306. dwHostNameLength,
  307. nPort
  308. ));
  309. InitializeListHead(&_List);
  310. _Scheme = tScheme;
  311. if (IsLocalMacro(lpszHostName, dwHostNameLength)) {
  312. DEBUG_PRINT(PROXY,
  313. INFO,
  314. ("<local>\n"
  315. ));
  316. _Name = NULL;
  317. _LocalSemantics = TRUE;
  318. _Error = ERROR_SUCCESS;
  319. } else {
  320. _Name.MakeCopy(lpszHostName, dwHostNameLength);
  321. if (!_Name.IsError()) {
  322. _Name.MakeLowerCase();
  323. _Error = ERROR_SUCCESS;
  324. }
  325. else {
  326. _Error = ERROR_NOT_ENOUGH_MEMORY;
  327. }
  328. _LocalSemantics = FALSE;
  329. }
  330. _Port = nPort;
  331. DEBUG_LEAVE(0);
  332. }
  333. ~PROXY_BYPASS_LIST_ENTRY() {
  334. DEBUG_ENTER((DBG_OBJECTS,
  335. None,
  336. "~PROXY_BYPASS_LIST_ENTRY",
  337. _Name.StringAddress()
  338. ));
  339. DEBUG_LEAVE(0);
  340. }
  341. BOOL IsLocal(VOID) const {
  342. return _LocalSemantics;
  343. }
  344. DWORD GetError(VOID) const {
  345. return _Error;
  346. }
  347. BOOL
  348. WriteEntry(
  349. OUT LPSTR lpszBuffer,
  350. IN OUT LPDWORD lpdwBufferLength
  351. );
  352. };
  353. //
  354. // PROXY_BYPASS_LIST - contains the list of proxy bypass entries
  355. //
  356. class PROXY_BYPASS_LIST {
  357. private:
  358. //
  359. // _List - serialized list of PROXY_BYPASS_LIST_ENTRY objects
  360. //
  361. SERIALIZED_LIST _List;
  362. //
  363. // _Error - errors stored here from initialization
  364. //
  365. DWORD _Error;
  366. //
  367. // _lpszBypassString - unparsed input string that we're passed,
  368. // sometime when I have time this should take over as our stored structure
  369. //
  370. LPSTR _lpszBypassString;
  371. public:
  372. PROXY_BYPASS_LIST(LPCSTR BypassList) {
  373. DEBUG_ENTER((DBG_OBJECTS,
  374. None,
  375. "PROXY_BYPASS_LIST",
  376. "%q",
  377. BypassList
  378. ));
  379. InitializeSerializedList(&_List);
  380. if (BypassList == NULL) {
  381. BypassList = "";
  382. }
  383. _Error = ERROR_SUCCESS;
  384. _lpszBypassString = NewString(BypassList);
  385. if ( _lpszBypassString == NULL ) {
  386. _Error = ERROR_NOT_ENOUGH_MEMORY;
  387. }
  388. if ( _Error == ERROR_SUCCESS ) {
  389. _Error = AddList(_lpszBypassString);
  390. }
  391. DEBUG_LEAVE(0);
  392. }
  393. ~PROXY_BYPASS_LIST() {
  394. DEBUG_ENTER((DBG_OBJECTS,
  395. None,
  396. "~PROXY_BYPASS_LIST",
  397. NULL
  398. ));
  399. if (LockSerializedList(&_List))
  400. {
  401. while (!IsSerializedListEmpty(&_List)) {
  402. //
  403. // remove the PROXY_BYPASS_LIST_ENTRY at the head of the serialized
  404. // list
  405. //
  406. LPVOID entry = SlDequeueHead(&_List);
  407. //
  408. // entry should not be NULL - IsSerializedListEmpty() told us we
  409. // could expect something
  410. //
  411. INET_ASSERT(entry != NULL);
  412. //
  413. // get the address of the object (should be the same as entry) and
  414. // delete it
  415. //
  416. delete CONTAINING_RECORD(entry, PROXY_BYPASS_LIST_ENTRY, _List);
  417. }
  418. if ( _lpszBypassString ) {
  419. FREE_MEMORY(_lpszBypassString);
  420. }
  421. UnlockSerializedList(&_List);
  422. }
  423. // delete critsec even if we couldn't free the data.
  424. TerminateSerializedList(&_List);
  425. DEBUG_LEAVE(0);
  426. }
  427. DWORD
  428. AddList(
  429. IN LPSTR lpszList
  430. );
  431. BOOL
  432. Find(
  433. IN INTERNET_SCHEME tScheme,
  434. IN LPSTR lpszHostName,
  435. IN DWORD dwHostNameLength,
  436. IN INTERNET_PORT nPort
  437. );
  438. DWORD
  439. Add(
  440. IN INTERNET_SCHEME tScheme,
  441. IN LPSTR lpszHostName,
  442. IN DWORD dwHostNameLength,
  443. IN INTERNET_PORT nPort
  444. );
  445. BOOL
  446. IsBypassed(
  447. IN INTERNET_HANDLE_OBJECT* pSessionObject,
  448. IN INTERNET_SCHEME tScheme,
  449. IN LPSTR lpszHostName,
  450. IN DWORD dwHostNameLength,
  451. IN INTERNET_PORT nPort,
  452. IN BOOL IsAddress,
  453. IN LPSOCKADDR lpSockAddr OPTIONAL
  454. );
  455. // This function just checks the bypass list.
  456. BOOL
  457. IsHostInBypassList(
  458. IN INTERNET_SCHEME tScheme,
  459. IN LPSTR lpszHostName,
  460. IN DWORD dwHostNameLength,
  461. IN INTERNET_PORT nPort,
  462. IN BOOL isAddress
  463. );
  464. DWORD GetError(VOID) const {
  465. return _Error;
  466. }
  467. LPSTR CopyString(VOID) {
  468. return (_lpszBypassString != NULL) ? NewString(_lpszBypassString) : NULL;
  469. }
  470. VOID
  471. GetList(
  472. OUT LPSTR * lplpszList,
  473. IN DWORD dwBufferLength,
  474. IN OUT LPDWORD lpdwRequiredLength
  475. );
  476. };
  477. //
  478. // PROXY_SERVER_LIST_ENTRY - describes a proxy server and the scheme that uses
  479. // it
  480. //
  481. class PROXY_SERVER_LIST_ENTRY {
  482. friend class PROXY_SERVER_LIST;
  483. private:
  484. //
  485. // _List - there may be a variable number of proxies
  486. //
  487. LIST_ENTRY _List;
  488. //
  489. // _Protocol - which protocol scheme this proxy information is for (e.g.
  490. // INTERNET_SCHEME_FTP in ftp=http://proxy:80)
  491. //
  492. INTERNET_SCHEME _Protocol;
  493. //
  494. // _Scheme - which protocol scheme we use to get the data (e.g.
  495. // INTERNET_SCHEME_HTTP in ftp=http://proxy:80)
  496. //
  497. INTERNET_SCHEME _Scheme;
  498. //
  499. // _ProxyName - the name of the proxy server we use for this scheme
  500. //
  501. ICSTRING _ProxyName;
  502. //
  503. // _ProxyPort - port number at proxy host
  504. //
  505. INTERNET_PORT _ProxyPort;
  506. //
  507. // _AddressList - the list of socket addresses for this proxy. Keeping this
  508. // information here allows us not have to resolve the proxy name each time
  509. // if DNS caching has been disabled
  510. //
  511. //ADDRESS_INFO_LIST _AddressList;
  512. //
  513. // _Error - errors stored here from initialization
  514. //
  515. DWORD _Error;
  516. public:
  517. PROXY_SERVER_LIST_ENTRY(
  518. IN INTERNET_SCHEME tProtocol,
  519. IN INTERNET_SCHEME tScheme,
  520. IN LPSTR lpszHostName,
  521. IN DWORD dwHostNameLength,
  522. IN INTERNET_PORT nPort
  523. ) {
  524. DEBUG_ENTER((DBG_OBJECTS,
  525. None,
  526. "PROXY_SERVER_LIST_ENTRY",
  527. "%s, %s, %q, %d, %d",
  528. InternetMapScheme(tProtocol),
  529. InternetMapScheme(tScheme),
  530. lpszHostName,
  531. dwHostNameLength,
  532. nPort
  533. ));
  534. InitializeListHead(&_List);
  535. _Protocol = tProtocol;
  536. _Scheme = tScheme;
  537. _ProxyName.MakeCopy(lpszHostName, dwHostNameLength);
  538. if (!_ProxyName.IsError()) {
  539. _Error = ERROR_SUCCESS;
  540. }
  541. else {
  542. _Error = ERROR_NOT_ENOUGH_MEMORY;
  543. }
  544. _ProxyPort = nPort;
  545. //InitializeAddressList(&_AddressList);
  546. DEBUG_LEAVE(0);
  547. }
  548. ~PROXY_SERVER_LIST_ENTRY() {
  549. DEBUG_ENTER((DBG_OBJECTS,
  550. None,
  551. "~PROXY_SERVER_LIST_ENTRY",
  552. _ProxyName.StringAddress()
  553. ));
  554. //FreeAddressList(&_AddressList);
  555. DEBUG_LEAVE(0);
  556. }
  557. DWORD GetError(VOID) const {
  558. return _Error;
  559. }
  560. //DWORD ResolveAddress(VOID) {
  561. // return GetServiceAddress(_ProxyName.StringAddress(),
  562. // NULL,
  563. // NULL,
  564. // NS_DEFAULT,
  565. // _ProxyPort,
  566. // 0,
  567. // &_AddressList
  568. // );
  569. //}
  570. BOOL
  571. WriteEntry(
  572. OUT LPSTR lpszBuffer,
  573. IN OUT LPDWORD lpdwBufferLength
  574. );
  575. };
  576. //
  577. // PROXY_SERVER_LIST - need one of these for each PROXY_INFO list. This class
  578. // contains the proxy list and performs all operations on it
  579. //
  580. class PROXY_SERVER_LIST {
  581. private:
  582. //
  583. // _List - serialized list of PROXY_SERVER_LIST_ENTRY objects
  584. //
  585. SERIALIZED_LIST _List;
  586. //
  587. // _Error - errors stored here from initialization
  588. //
  589. DWORD _Error;
  590. //
  591. // _lpszServerListString - A copy of the input string, sometime this should be
  592. // shared so that other structures use the same strings
  593. //
  594. LPSTR _lpszServerListString;
  595. public:
  596. PROXY_SERVER_LIST(LPCSTR ServerList) {
  597. DEBUG_ENTER((DBG_OBJECTS,
  598. None,
  599. "PROXY_SERVER_LIST",
  600. "%q",
  601. ServerList
  602. ));
  603. _lpszServerListString = NULL;
  604. _Error = ERROR_SUCCESS;
  605. InitializeSerializedList(&_List);
  606. if (ServerList == NULL) {
  607. ServerList = "";
  608. }
  609. _lpszServerListString = NewString(ServerList);
  610. if ( _lpszServerListString == NULL ) {
  611. _Error = ERROR_NOT_ENOUGH_MEMORY;
  612. }
  613. if ( _Error == ERROR_SUCCESS ) {
  614. _Error = AddList(_lpszServerListString);
  615. }
  616. DEBUG_LEAVE(0);
  617. }
  618. ~PROXY_SERVER_LIST() {
  619. DEBUG_ENTER((DBG_OBJECTS,
  620. None,
  621. "~PROXY_SERVER_LIST",
  622. NULL
  623. ));
  624. if (LockSerializedList(&_List))
  625. {
  626. while (!IsSerializedListEmpty(&_List)) {
  627. //
  628. // remove the PROXY_SERVER_LIST_ENTRY at the head of the serialized
  629. // list
  630. //
  631. LPVOID entry = SlDequeueHead(&_List);
  632. //
  633. // entry should not be NULL - IsSerializedListEmpty() told us we
  634. // could expect something
  635. //
  636. INET_ASSERT(entry != NULL);
  637. //
  638. // get the address of the object (should be the same as entry) and
  639. // delete it
  640. //
  641. delete CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
  642. }
  643. if ( _lpszServerListString) {
  644. FREE_MEMORY(_lpszServerListString);
  645. }
  646. UnlockSerializedList(&_List);
  647. }
  648. // delete critsec even if we couldn't free the data.
  649. TerminateSerializedList(&_List);
  650. DEBUG_LEAVE(0);
  651. }
  652. DWORD
  653. AddList(
  654. IN LPSTR lpszList
  655. );
  656. BOOL
  657. Find(
  658. IN INTERNET_SCHEME tScheme
  659. );
  660. DWORD
  661. Add(
  662. IN INTERNET_SCHEME tProtocol,
  663. IN INTERNET_SCHEME tScheme,
  664. IN LPSTR lpszHostName,
  665. IN DWORD dwHostNameLength,
  666. IN INTERNET_PORT nPort
  667. );
  668. INTERNET_SCHEME
  669. ProxyScheme(
  670. IN INTERNET_SCHEME tProtocol
  671. );
  672. BOOL
  673. GetProxyHostName(
  674. IN INTERNET_SCHEME tProtocol,
  675. IN OUT LPINTERNET_SCHEME lptScheme,
  676. OUT LPSTR * lplpszHostName,
  677. OUT LPBOOL lpbFreeHostName,
  678. OUT LPDWORD lpdwHostNameLength,
  679. OUT LPINTERNET_PORT lpHostPort
  680. );
  681. DWORD
  682. AddToBypassList(
  683. IN PROXY_BYPASS_LIST * lpBypassList
  684. );
  685. DWORD GetError(VOID) const {
  686. return _Error;
  687. }
  688. LPSTR CopyString(VOID) {
  689. return (_lpszServerListString != NULL ) ? NewString(_lpszServerListString) : NULL;
  690. }
  691. VOID
  692. GetList(
  693. OUT LPSTR * lplpszList,
  694. IN DWORD dwBufferLength,
  695. IN OUT LPDWORD lpdwRequiredLength
  696. );
  697. };
  698. //
  699. // PROXY_INFO - maintains both PROXY_SERVER_LIST and PROXY_BYPASS_LIST,
  700. // provides base class for overall Proxy Management
  701. //
  702. class PROXY_INFO {
  703. private:
  704. //
  705. // _ProxyServerList - pointer to list of proxy servers. We create this from
  706. // free store because all other handles derived from INTERNET_HANDLE_OBJECT
  707. // don't need to unnecessarily allocate a SERIALIZED_LIST (& therefore a
  708. // CRITICAL_SECTION)
  709. //
  710. PROXY_SERVER_LIST * _ProxyServerList;
  711. //
  712. // _ProxyBypassList - pointer to list of targets which will not go via
  713. // proxy. From free store because of same reason as PROXY_SERVER_LIST
  714. //
  715. PROXY_BYPASS_LIST * _ProxyBypassList;
  716. //
  717. // _Error - errors returned from creating proxy server & bypass lists
  718. //
  719. DWORD _Error;
  720. //
  721. // _Lock - acquire this before accessing the proxy info
  722. //
  723. RESOURCE_LOCK _Lock;
  724. //
  725. // _fDisableDirect - Disable direct connections on failure of proxy connections
  726. //
  727. BOOL _fDisableDirect;
  728. //
  729. // _fModifiedInProcess - TRUE if the proxy info is set to something other than the
  730. // registry contents
  731. //
  732. BOOL _fModifiedInProcess;
  733. //
  734. // _dwSettingsVersion - passed in settings version used to track changes
  735. // made while we're off in processing.
  736. //
  737. DWORD _dwSettingsVersion;
  738. // _pSessionObject - we need this, so this can be passed into Proxy_Bypass_list functions
  739. // so that they can use it to look up the appropriate hostent cache.
  740. INTERNET_HANDLE_OBJECT* _pSessionObject;
  741. protected:
  742. //
  743. // _BadProxyList - Keep a listing of what proxies recently failed, so
  744. // we can prevent reusing them.
  745. //
  746. BAD_PROXY_LIST _BadProxyList;
  747. //
  748. // IsGlobal() - TRUE if this is a global object used as a
  749. // standard proxy info object.
  750. //
  751. BOOL IsGlobal(VOID) const {
  752. INET_ASSERT(g_pGlobalProxyInfo != NULL);
  753. return ((this == (PROXY_INFO *) g_pGlobalProxyInfo) ? TRUE : FALSE );
  754. }
  755. BOOL IsDisableDirect(VOID) const {
  756. return _fDisableDirect;
  757. }
  758. VOID SetDisableDirect(BOOL fDisableDirect) {
  759. _fDisableDirect = fDisableDirect;
  760. }
  761. INTERNET_SCHEME
  762. ProxyScheme(
  763. IN INTERNET_SCHEME tProtocol
  764. ) {
  765. if (_ProxyServerList != NULL) {
  766. return _ProxyServerList->ProxyScheme(tProtocol);
  767. }
  768. return INTERNET_SCHEME_UNKNOWN;
  769. }
  770. BOOL
  771. GetProxyHostName(
  772. IN INTERNET_SCHEME tProtocol,
  773. IN OUT LPINTERNET_SCHEME lptScheme,
  774. OUT LPSTR * lplpszHostName,
  775. OUT LPBOOL lpbFreeHostName,
  776. OUT LPDWORD lpdwHostNameLength,
  777. OUT LPINTERNET_PORT lpHostPort
  778. ) {
  779. if (_ProxyServerList != NULL) {
  780. return _ProxyServerList->GetProxyHostName(tProtocol,
  781. lptScheme,
  782. lplpszHostName,
  783. lpbFreeHostName,
  784. lpdwHostNameLength,
  785. lpHostPort
  786. );
  787. }
  788. return FALSE;
  789. }
  790. BOOL
  791. IsBypassed(
  792. IN INTERNET_SCHEME tScheme,
  793. IN LPSTR lpszHostName,
  794. IN DWORD dwHostNameLength,
  795. IN INTERNET_PORT nPort
  796. ) {
  797. BOOL Result = FALSE;
  798. BOOL IsLiteral = FALSE;
  799. BOOL IsLocalHost = FALSE;
  800. SOCKADDR_IN6 SockAddr;
  801. // Get some hostname attributes
  802. Result = ParseHostName(lpszHostName, dwHostNameLength, &IsLiteral, &IsLocalHost, &SockAddr);
  803. //
  804. // Local loopback address always bypasses the proxy so that
  805. // Pointcast, local Web servers that run on the client machine
  806. // are always accessible
  807. //
  808. if (Result && IsLocalHost)
  809. {
  810. return TRUE;
  811. }
  812. if (_ProxyBypassList != NULL) {
  813. return _ProxyBypassList->IsBypassed(_pSessionObject,
  814. tScheme,
  815. lpszHostName,
  816. dwHostNameLength,
  817. nPort,
  818. (Result && IsLiteral),
  819. (Result && IsLiteral) ? (LPSOCKADDR)&SockAddr : NULL
  820. );
  821. }
  822. return FALSE;
  823. }
  824. BOOL
  825. IsHostInBypassList(
  826. IN LPSTR lpszHostName,
  827. IN DWORD dwHostNameLength
  828. ) {
  829. if (_ProxyBypassList != NULL) {
  830. return _ProxyBypassList->IsHostInBypassList(INTERNET_SCHEME_DEFAULT,
  831. lpszHostName,
  832. dwHostNameLength,
  833. INTERNET_INVALID_PORT_NUMBER,
  834. FALSE
  835. );
  836. }
  837. return FALSE;
  838. }
  839. VOID
  840. CleanOutLists(
  841. VOID
  842. );
  843. public:
  844. PROXY_INFO() {
  845. DEBUG_ENTER((DBG_OBJECTS,
  846. None,
  847. "PROXY_INFO::PROXY_INFO",
  848. ""
  849. ));
  850. _pSessionObject = NULL;
  851. DEBUG_LEAVE(0);
  852. }
  853. ~PROXY_INFO() {
  854. if (_Lock.IsInitialized()) {
  855. TerminateProxySettings();
  856. }
  857. }
  858. VOID Lock(BOOL bExclusiveMode) {
  859. _Lock.Acquire(bExclusiveMode);
  860. }
  861. VOID SetSessionObject(INTERNET_HANDLE_OBJECT * pSessionObject);
  862. INTERNET_HANDLE_OBJECT* GetSessionObject()
  863. {
  864. return _pSessionObject;
  865. }
  866. VOID Unlock(VOID) {
  867. _Lock.Release();
  868. }
  869. DWORD GetError(VOID) const {
  870. return _Error;
  871. }
  872. BOOL IsModifiedInProcess(VOID) const {
  873. return _fModifiedInProcess;
  874. }
  875. DWORD
  876. GetProxyStringInfo(
  877. OUT LPVOID lpBuffer,
  878. IN OUT LPDWORD lpdwBufferLength
  879. );
  880. // This function determines if a host bypasses the proxy.
  881. // Will use autoproxy if it is enabled, else it will just
  882. // consult the bypass list.
  883. BOOL
  884. HostBypassesProxy(
  885. IN INTERNET_SCHEME tScheme,
  886. IN LPSTR lpszHostName,
  887. IN DWORD dwHostNameLength
  888. );
  889. BOOL
  890. RedoSendRequest(
  891. IN OUT LPDWORD lpdwError,
  892. IN DWORD dwSecureStatus,
  893. IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo,
  894. IN CServerInfo *pOriginServer,
  895. IN CServerInfo *pProxyServer
  896. );
  897. //
  898. // Virtual Interface APIs
  899. //
  900. // InitializeProxySettings
  901. // TerminateProxySettings - destroys our internal vars
  902. // SetProxySettings - update proxy settings
  903. // GetProxySettings - get current proxy settings
  904. // RefreshProxySettings - force proxy settings to be reprocessed (auto-proxy, auto-detect)
  905. // QueryProxySettings - ask proxy objects for proxy info
  906. // IsProxySettingsConfigured
  907. //
  908. virtual
  909. VOID
  910. InitializeProxySettings(
  911. VOID
  912. );
  913. virtual
  914. VOID
  915. TerminateProxySettings(
  916. VOID
  917. );
  918. virtual
  919. DWORD
  920. SetProxySettings(
  921. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  922. IN BOOL fModifiedInProcess
  923. );
  924. virtual
  925. DWORD
  926. GetProxySettings(
  927. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  928. IN BOOL fCheckVersion
  929. );
  930. virtual
  931. DWORD
  932. RefreshProxySettings(
  933. IN BOOL fForceRefresh
  934. );
  935. virtual
  936. DWORD
  937. QueryProxySettings(
  938. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  939. );
  940. virtual BOOL IsProxySettingsConfigured(VOID) {
  941. return (_ProxyServerList != NULL) ? TRUE : FALSE;
  942. }
  943. };
  944. //
  945. // PROXY_INFO_GLOBAL - global proxy information for settings
  946. //
  947. class PROXY_INFO_GLOBAL : public PROXY_INFO {
  948. private:
  949. //
  950. // _dwProxyFlags - set to control the various proxy modes that we support
  951. //
  952. DWORD _dwProxyFlags;
  953. //
  954. // _dwConnectionName - set to new connection name associated with this proxy info
  955. //
  956. LPSTR _lpszConnectionName;
  957. //
  958. // _fRefreshDisabled - TRUE at initalization, we're not allowed
  959. // to refresh until InternetOpen
  960. //
  961. BOOL _fRefreshDisabled;
  962. //
  963. // _fQueuedRefresh - A refresh has been queued up,
  964. // ready to take place after InternetOpen
  965. //
  966. BOOL _fQueuedRefresh;
  967. public:
  968. PROXY_INFO_GLOBAL() {
  969. _lpszConnectionName = NULL;
  970. _dwProxyFlags = 0;
  971. _fQueuedRefresh = FALSE;
  972. _fRefreshDisabled = TRUE;
  973. }
  974. ~PROXY_INFO_GLOBAL() {
  975. }
  976. VOID
  977. ClearBadProxyList(
  978. VOID
  979. )
  980. {
  981. Lock(TRUE);
  982. _BadProxyList.ClearList();
  983. Unlock();
  984. }
  985. VOID
  986. CheckForExpiredEntries(
  987. VOID
  988. )
  989. {
  990. Lock(TRUE);
  991. _BadProxyList.CheckForExpiredEntries();
  992. Unlock();
  993. }
  994. BOOL IsRefreshDisabled(VOID) {
  995. return (_fRefreshDisabled);
  996. }
  997. VOID SetRefreshDisabled(BOOL fDisable) {
  998. _fRefreshDisabled = fDisable;
  999. }
  1000. VOID QueueRefresh(VOID) {
  1001. _fQueuedRefresh = TRUE;
  1002. }
  1003. VOID
  1004. ReleaseQueuedRefresh(
  1005. VOID
  1006. );
  1007. // Virtual Interface APIs
  1008. //
  1009. // TerminateProxySettings - destroys our internal vars
  1010. // SetProxySettings - update proxy settings
  1011. // GetProxySettings - get current proxy settings
  1012. // RefreshProxySettings - force proxy settings to be reprocessed (auto-proxy, auto-detect)
  1013. // QueryProxySettings - ask proxy objects for proxy info
  1014. // IsProxySettingsConfigured
  1015. //
  1016. VOID
  1017. TerminateProxySettings(
  1018. VOID
  1019. );
  1020. DWORD
  1021. SetProxySettings(
  1022. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  1023. IN BOOL fModifiedInProcess
  1024. );
  1025. DWORD
  1026. GetProxySettings(
  1027. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  1028. IN BOOL fCheckVersion
  1029. );
  1030. DWORD
  1031. RefreshProxySettings(
  1032. IN BOOL fForceRefresh
  1033. );
  1034. DWORD
  1035. QueryProxySettings(
  1036. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  1037. );
  1038. BOOL IsProxySettingsConfigured(VOID) {
  1039. return PROXY_INFO::IsProxySettingsConfigured();
  1040. }
  1041. LPSTR GetConnectionName(VOID) {
  1042. return _lpszConnectionName;
  1043. }
  1044. };