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.

1413 lines
32 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. public:
  290. PROXY_BYPASS_LIST_ENTRY(
  291. IN INTERNET_SCHEME tScheme,
  292. IN LPSTR lpszHostName,
  293. IN DWORD dwHostNameLength,
  294. IN INTERNET_PORT nPort
  295. ) {
  296. DEBUG_ENTER((DBG_OBJECTS,
  297. None,
  298. "PROXY_BYPASS_LIST_ENTRY",
  299. "%s, %q, %d, %d",
  300. InternetMapScheme(tScheme),
  301. lpszHostName,
  302. dwHostNameLength,
  303. nPort
  304. ));
  305. InitializeListHead(&_List);
  306. _Scheme = tScheme;
  307. if (IsLocalMacro(lpszHostName, dwHostNameLength)) {
  308. DEBUG_PRINT(PROXY,
  309. INFO,
  310. ("<local>\n"
  311. ));
  312. _Name = NULL;
  313. _LocalSemantics = TRUE;
  314. } else {
  315. _Name.MakeCopy(lpszHostName, dwHostNameLength);
  316. _Name.MakeLowerCase();
  317. _LocalSemantics = FALSE;
  318. }
  319. _Port = nPort;
  320. DEBUG_LEAVE(0);
  321. }
  322. ~PROXY_BYPASS_LIST_ENTRY() {
  323. DEBUG_ENTER((DBG_OBJECTS,
  324. None,
  325. "~PROXY_BYPASS_LIST_ENTRY",
  326. _Name.StringAddress()
  327. ));
  328. DEBUG_LEAVE(0);
  329. }
  330. BOOL IsLocal(VOID) const {
  331. return _LocalSemantics;
  332. }
  333. BOOL
  334. WriteEntry(
  335. OUT LPSTR lpszBuffer,
  336. IN OUT LPDWORD lpdwBufferLength
  337. );
  338. };
  339. //
  340. // PROXY_BYPASS_LIST - contains the list of proxy bypass entries
  341. //
  342. class PROXY_BYPASS_LIST {
  343. private:
  344. //
  345. // _List - serialized list of PROXY_BYPASS_LIST_ENTRY objects
  346. //
  347. SERIALIZED_LIST _List;
  348. //
  349. // _Error - errors stored here from initialization
  350. //
  351. DWORD _Error;
  352. //
  353. // _lpszBypassString - unparsed input string that we're passed,
  354. // sometime when I have time this should take over as our stored structure
  355. //
  356. LPSTR _lpszBypassString;
  357. public:
  358. PROXY_BYPASS_LIST(LPCSTR BypassList) {
  359. DEBUG_ENTER((DBG_OBJECTS,
  360. None,
  361. "PROXY_BYPASS_LIST",
  362. "%q",
  363. BypassList
  364. ));
  365. InitializeSerializedList(&_List);
  366. if (BypassList == NULL) {
  367. BypassList = "";
  368. }
  369. _Error = ERROR_SUCCESS;
  370. _lpszBypassString = NewString(BypassList);
  371. if ( _lpszBypassString == NULL ) {
  372. _Error = ERROR_NOT_ENOUGH_MEMORY;
  373. }
  374. if ( _Error == ERROR_SUCCESS ) {
  375. _Error = AddList(_lpszBypassString);
  376. }
  377. DEBUG_LEAVE(0);
  378. }
  379. ~PROXY_BYPASS_LIST() {
  380. DEBUG_ENTER((DBG_OBJECTS,
  381. None,
  382. "~PROXY_BYPASS_LIST",
  383. NULL
  384. ));
  385. if (LockSerializedList(&_List))
  386. {
  387. while (!IsSerializedListEmpty(&_List)) {
  388. //
  389. // remove the PROXY_BYPASS_LIST_ENTRY at the head of the serialized
  390. // list
  391. //
  392. LPVOID entry = SlDequeueHead(&_List);
  393. //
  394. // entry should not be NULL - IsSerializedListEmpty() told us we
  395. // could expect something
  396. //
  397. INET_ASSERT(entry != NULL);
  398. //
  399. // get the address of the object (should be the same as entry) and
  400. // delete it
  401. //
  402. delete CONTAINING_RECORD(entry, PROXY_BYPASS_LIST_ENTRY, _List);
  403. }
  404. if ( _lpszBypassString ) {
  405. FREE_MEMORY(_lpszBypassString);
  406. }
  407. UnlockSerializedList(&_List);
  408. }
  409. // delete critsec even if we couldn't free the data.
  410. TerminateSerializedList(&_List);
  411. DEBUG_LEAVE(0);
  412. }
  413. DWORD
  414. AddList(
  415. IN LPSTR lpszList
  416. );
  417. BOOL
  418. Find(
  419. IN INTERNET_SCHEME tScheme,
  420. IN LPSTR lpszHostName,
  421. IN DWORD dwHostNameLength,
  422. IN INTERNET_PORT nPort
  423. );
  424. DWORD
  425. Add(
  426. IN INTERNET_SCHEME tScheme,
  427. IN LPSTR lpszHostName,
  428. IN DWORD dwHostNameLength,
  429. IN INTERNET_PORT nPort
  430. );
  431. BOOL
  432. IsBypassed(
  433. IN INTERNET_HANDLE_OBJECT* pSessionObject,
  434. IN INTERNET_SCHEME tScheme,
  435. IN LPSTR lpszHostName,
  436. IN DWORD dwHostNameLength,
  437. IN INTERNET_PORT nPort
  438. );
  439. // This function just checks the bypass list.
  440. BOOL
  441. IsHostInBypassList(
  442. IN INTERNET_SCHEME tScheme,
  443. IN LPSTR lpszHostName,
  444. IN DWORD dwHostNameLength,
  445. IN INTERNET_PORT nPort,
  446. IN BOOL isAddress
  447. );
  448. DWORD GetError(VOID) const {
  449. return _Error;
  450. }
  451. LPSTR CopyString(VOID) {
  452. return (_lpszBypassString != NULL) ? NewString(_lpszBypassString) : NULL;
  453. }
  454. VOID
  455. GetList(
  456. OUT LPSTR * lplpszList,
  457. IN DWORD dwBufferLength,
  458. IN OUT LPDWORD lpdwRequiredLength
  459. );
  460. };
  461. //
  462. // PROXY_SERVER_LIST_ENTRY - describes a proxy server and the scheme that uses
  463. // it
  464. //
  465. class PROXY_SERVER_LIST_ENTRY {
  466. friend class PROXY_SERVER_LIST;
  467. private:
  468. //
  469. // _List - there may be a variable number of proxies
  470. //
  471. LIST_ENTRY _List;
  472. //
  473. // _Protocol - which protocol scheme this proxy information is for (e.g.
  474. // INTERNET_SCHEME_FTP in ftp=http://proxy:80)
  475. //
  476. INTERNET_SCHEME _Protocol;
  477. //
  478. // _Scheme - which protocol scheme we use to get the data (e.g.
  479. // INTERNET_SCHEME_HTTP in ftp=http://proxy:80)
  480. //
  481. INTERNET_SCHEME _Scheme;
  482. //
  483. // _ProxyName - the name of the proxy server we use for this scheme
  484. //
  485. ICSTRING _ProxyName;
  486. //
  487. // _ProxyPort - port number at proxy host
  488. //
  489. INTERNET_PORT _ProxyPort;
  490. //
  491. // _AddressList - the list of socket addresses for this proxy. Keeping this
  492. // information here allows us not have to resolve the proxy name each time
  493. // if DNS caching has been disabled
  494. //
  495. //ADDRESS_INFO_LIST _AddressList;
  496. public:
  497. PROXY_SERVER_LIST_ENTRY(
  498. IN INTERNET_SCHEME tProtocol,
  499. IN INTERNET_SCHEME tScheme,
  500. IN LPSTR lpszHostName,
  501. IN DWORD dwHostNameLength,
  502. IN INTERNET_PORT nPort
  503. ) {
  504. DEBUG_ENTER((DBG_OBJECTS,
  505. None,
  506. "PROXY_SERVER_LIST_ENTRY",
  507. "%s, %s, %q, %d, %d",
  508. InternetMapScheme(tProtocol),
  509. InternetMapScheme(tScheme),
  510. lpszHostName,
  511. dwHostNameLength,
  512. nPort
  513. ));
  514. InitializeListHead(&_List);
  515. _Protocol = tProtocol;
  516. _Scheme = tScheme;
  517. _ProxyName.MakeCopy(lpszHostName, dwHostNameLength);
  518. _ProxyPort = nPort;
  519. //InitializeAddressList(&_AddressList);
  520. DEBUG_LEAVE(0);
  521. }
  522. ~PROXY_SERVER_LIST_ENTRY() {
  523. DEBUG_ENTER((DBG_OBJECTS,
  524. None,
  525. "~PROXY_SERVER_LIST_ENTRY",
  526. _ProxyName.StringAddress()
  527. ));
  528. //FreeAddressList(&_AddressList);
  529. DEBUG_LEAVE(0);
  530. }
  531. //DWORD ResolveAddress(VOID) {
  532. // return GetServiceAddress(_ProxyName.StringAddress(),
  533. // NULL,
  534. // NULL,
  535. // NS_DEFAULT,
  536. // _ProxyPort,
  537. // 0,
  538. // &_AddressList
  539. // );
  540. //}
  541. BOOL
  542. WriteEntry(
  543. OUT LPSTR lpszBuffer,
  544. IN OUT LPDWORD lpdwBufferLength
  545. );
  546. };
  547. //
  548. // PROXY_SERVER_LIST - need one of these for each PROXY_INFO list. This class
  549. // contains the proxy list and performs all operations on it
  550. //
  551. class PROXY_SERVER_LIST {
  552. private:
  553. //
  554. // _List - serialized list of PROXY_SERVER_LIST_ENTRY objects
  555. //
  556. SERIALIZED_LIST _List;
  557. //
  558. // _Error - errors stored here from initialization
  559. //
  560. DWORD _Error;
  561. //
  562. // _lpszServerListString - A copy of the input string, sometime this should be
  563. // shared so that other structures use the same strings
  564. //
  565. LPSTR _lpszServerListString;
  566. public:
  567. PROXY_SERVER_LIST(LPCSTR ServerList) {
  568. DEBUG_ENTER((DBG_OBJECTS,
  569. None,
  570. "PROXY_SERVER_LIST",
  571. "%q",
  572. ServerList
  573. ));
  574. _lpszServerListString = NULL;
  575. _Error = ERROR_SUCCESS;
  576. InitializeSerializedList(&_List);
  577. if (ServerList == NULL) {
  578. ServerList = "";
  579. }
  580. _lpszServerListString = NewString(ServerList);
  581. if ( _lpszServerListString == NULL ) {
  582. _Error = ERROR_NOT_ENOUGH_MEMORY;
  583. }
  584. if ( _Error == ERROR_SUCCESS ) {
  585. _Error = AddList(_lpszServerListString);
  586. }
  587. DEBUG_LEAVE(0);
  588. }
  589. ~PROXY_SERVER_LIST() {
  590. DEBUG_ENTER((DBG_OBJECTS,
  591. None,
  592. "~PROXY_SERVER_LIST",
  593. NULL
  594. ));
  595. if (LockSerializedList(&_List))
  596. {
  597. while (!IsSerializedListEmpty(&_List)) {
  598. //
  599. // remove the PROXY_SERVER_LIST_ENTRY at the head of the serialized
  600. // list
  601. //
  602. LPVOID entry = SlDequeueHead(&_List);
  603. //
  604. // entry should not be NULL - IsSerializedListEmpty() told us we
  605. // could expect something
  606. //
  607. INET_ASSERT(entry != NULL);
  608. //
  609. // get the address of the object (should be the same as entry) and
  610. // delete it
  611. //
  612. delete CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
  613. }
  614. if ( _lpszServerListString) {
  615. FREE_MEMORY(_lpszServerListString);
  616. }
  617. UnlockSerializedList(&_List);
  618. }
  619. // delete critsec even if we couldn't free the data.
  620. TerminateSerializedList(&_List);
  621. DEBUG_LEAVE(0);
  622. }
  623. DWORD
  624. AddList(
  625. IN LPSTR lpszList
  626. );
  627. BOOL
  628. Find(
  629. IN INTERNET_SCHEME tScheme
  630. );
  631. DWORD
  632. Add(
  633. IN INTERNET_SCHEME tProtocol,
  634. IN INTERNET_SCHEME tScheme,
  635. IN LPSTR lpszHostName,
  636. IN DWORD dwHostNameLength,
  637. IN INTERNET_PORT nPort
  638. );
  639. INTERNET_SCHEME
  640. ProxyScheme(
  641. IN INTERNET_SCHEME tProtocol
  642. );
  643. BOOL
  644. GetProxyHostName(
  645. IN INTERNET_SCHEME tProtocol,
  646. IN OUT LPINTERNET_SCHEME lptScheme,
  647. OUT LPSTR * lplpszHostName,
  648. OUT LPBOOL lpbFreeHostName,
  649. OUT LPDWORD lpdwHostNameLength,
  650. OUT LPINTERNET_PORT lpHostPort
  651. );
  652. DWORD
  653. AddToBypassList(
  654. IN PROXY_BYPASS_LIST * lpBypassList
  655. );
  656. DWORD GetError(VOID) const {
  657. return _Error;
  658. }
  659. LPSTR CopyString(VOID) {
  660. return (_lpszServerListString != NULL ) ? NewString(_lpszServerListString) : NULL;
  661. }
  662. VOID
  663. GetList(
  664. OUT LPSTR * lplpszList,
  665. IN DWORD dwBufferLength,
  666. IN OUT LPDWORD lpdwRequiredLength
  667. );
  668. };
  669. //
  670. // PROXY_INFO - maintains both PROXY_SERVER_LIST and PROXY_BYPASS_LIST,
  671. // provides base class for overall Proxy Management
  672. //
  673. class PROXY_INFO {
  674. private:
  675. //
  676. // _ProxyServerList - pointer to list of proxy servers. We create this from
  677. // free store because all other handles derived from INTERNET_HANDLE_OBJECT
  678. // don't need to unnecessarily allocate a SERIALIZED_LIST (& therefore a
  679. // CRITICAL_SECTION)
  680. //
  681. PROXY_SERVER_LIST * _ProxyServerList;
  682. //
  683. // _ProxyBypassList - pointer to list of targets which will not go via
  684. // proxy. From free store because of same reason as PROXY_SERVER_LIST
  685. //
  686. PROXY_BYPASS_LIST * _ProxyBypassList;
  687. //
  688. // _Error - errors returned from creating proxy server & bypass lists
  689. //
  690. DWORD _Error;
  691. //
  692. // _Lock - acquire this before accessing the proxy info
  693. //
  694. RESOURCE_LOCK _Lock;
  695. //
  696. // _fDisableDirect - Disable direct connections on failure of proxy connections
  697. //
  698. BOOL _fDisableDirect;
  699. //
  700. // _fModifiedInProcess - TRUE if the proxy info is set to something other than the
  701. // registry contents
  702. //
  703. BOOL _fModifiedInProcess;
  704. //
  705. // _dwSettingsVersion - passed in settings version used to track changes
  706. // made while we're off in processing.
  707. //
  708. DWORD _dwSettingsVersion;
  709. // _pSessionObject - we need this, so this can be passed into Proxy_Bypass_list functions
  710. // so that they can use it to look up the appropriate hostent cache.
  711. INTERNET_HANDLE_OBJECT* _pSessionObject;
  712. protected:
  713. //
  714. // _BadProxyList - Keep a listing of what proxies recently failed, so
  715. // we can prevent reusing them.
  716. //
  717. BAD_PROXY_LIST _BadProxyList;
  718. //
  719. // IsGlobal() - TRUE if this is a global object used as a
  720. // standard proxy info object.
  721. //
  722. BOOL IsGlobal(VOID) const {
  723. INET_ASSERT(g_pGlobalProxyInfo != NULL);
  724. return ((this == (PROXY_INFO *) g_pGlobalProxyInfo) ? TRUE : FALSE );
  725. }
  726. BOOL IsDisableDirect(VOID) const {
  727. return _fDisableDirect;
  728. }
  729. VOID SetDisableDirect(BOOL fDisableDirect) {
  730. _fDisableDirect = fDisableDirect;
  731. }
  732. INTERNET_SCHEME
  733. ProxyScheme(
  734. IN INTERNET_SCHEME tProtocol
  735. ) {
  736. if (_ProxyServerList != NULL) {
  737. return _ProxyServerList->ProxyScheme(tProtocol);
  738. }
  739. return INTERNET_SCHEME_UNKNOWN;
  740. }
  741. BOOL
  742. GetProxyHostName(
  743. IN INTERNET_SCHEME tProtocol,
  744. IN OUT LPINTERNET_SCHEME lptScheme,
  745. OUT LPSTR * lplpszHostName,
  746. OUT LPBOOL lpbFreeHostName,
  747. OUT LPDWORD lpdwHostNameLength,
  748. OUT LPINTERNET_PORT lpHostPort
  749. ) {
  750. if (_ProxyServerList != NULL) {
  751. return _ProxyServerList->GetProxyHostName(tProtocol,
  752. lptScheme,
  753. lplpszHostName,
  754. lpbFreeHostName,
  755. lpdwHostNameLength,
  756. lpHostPort
  757. );
  758. }
  759. return FALSE;
  760. }
  761. BOOL
  762. IsBypassed(
  763. IN INTERNET_SCHEME tScheme,
  764. IN LPSTR lpszHostName,
  765. IN DWORD dwHostNameLength,
  766. IN INTERNET_PORT nPort
  767. ) {
  768. //
  769. // Prevent proxing of the loop-address, to allow us to work with
  770. // Pointcast, local Web servers that run on the client machine
  771. //
  772. if (lpszHostName &&
  773. dwHostNameLength == (sizeof("127.0.0.1")-1) &&
  774. strncmp( lpszHostName, "127.0.0.1", sizeof("127.0.0.1")-1 ) == 0 )
  775. {
  776. return TRUE;
  777. }
  778. if (_ProxyBypassList != NULL) {
  779. return _ProxyBypassList->IsBypassed(_pSessionObject,
  780. tScheme,
  781. lpszHostName,
  782. dwHostNameLength,
  783. nPort
  784. );
  785. }
  786. return FALSE;
  787. }
  788. BOOL
  789. IsHostInBypassList(
  790. IN LPSTR lpszHostName,
  791. IN DWORD dwHostNameLength
  792. ) {
  793. if (_ProxyBypassList != NULL) {
  794. return _ProxyBypassList->IsHostInBypassList(INTERNET_SCHEME_DEFAULT,
  795. lpszHostName,
  796. dwHostNameLength,
  797. INTERNET_INVALID_PORT_NUMBER,
  798. FALSE
  799. );
  800. }
  801. return FALSE;
  802. }
  803. VOID
  804. CleanOutLists(
  805. VOID
  806. );
  807. public:
  808. PROXY_INFO() {
  809. DEBUG_ENTER((DBG_OBJECTS,
  810. None,
  811. "PROXY_INFO::PROXY_INFO",
  812. ""
  813. ));
  814. _pSessionObject = NULL;
  815. DEBUG_LEAVE(0);
  816. }
  817. ~PROXY_INFO() {
  818. if (_Lock.IsInitialized()) {
  819. TerminateProxySettings();
  820. }
  821. }
  822. VOID Lock(BOOL bExclusiveMode) {
  823. _Lock.Acquire(bExclusiveMode);
  824. }
  825. VOID SetSessionObject(INTERNET_HANDLE_OBJECT * pSessionObject);
  826. INTERNET_HANDLE_OBJECT* GetSessionObject()
  827. {
  828. return _pSessionObject;
  829. }
  830. VOID Unlock(VOID) {
  831. _Lock.Release();
  832. }
  833. DWORD GetError(VOID) const {
  834. return _Error;
  835. }
  836. BOOL IsModifiedInProcess(VOID) const {
  837. return _fModifiedInProcess;
  838. }
  839. DWORD
  840. GetProxyStringInfo(
  841. OUT LPVOID lpBuffer,
  842. IN OUT LPDWORD lpdwBufferLength
  843. );
  844. BOOL
  845. RedoSendRequest(
  846. IN OUT LPDWORD lpdwError,
  847. IN DWORD dwSecureStatus,
  848. IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo,
  849. IN CServerInfo *pOriginServer,
  850. IN CServerInfo *pProxyServer
  851. );
  852. //
  853. // Virtual Interface APIs
  854. //
  855. // InitializeProxySettings
  856. // TerminateProxySettings - destroys our internal vars
  857. // SetProxySettings - update proxy settings
  858. // GetProxySettings - get current proxy settings
  859. // RefreshProxySettings - force proxy settings to be reprocessed (auto-proxy, auto-detect)
  860. // QueryProxySettings - ask proxy objects for proxy info
  861. // IsProxySettingsConfigured
  862. //
  863. virtual
  864. VOID
  865. InitializeProxySettings(
  866. VOID
  867. );
  868. virtual
  869. VOID
  870. TerminateProxySettings(
  871. VOID
  872. );
  873. virtual
  874. DWORD
  875. SetProxySettings(
  876. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  877. IN BOOL fModifiedInProcess
  878. );
  879. virtual
  880. DWORD
  881. GetProxySettings(
  882. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  883. IN BOOL fCheckVersion
  884. );
  885. virtual
  886. DWORD
  887. RefreshProxySettings(
  888. IN BOOL fForceRefresh
  889. );
  890. virtual
  891. DWORD
  892. QueryProxySettings(
  893. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  894. );
  895. virtual BOOL IsProxySettingsConfigured(VOID) {
  896. return (_ProxyServerList != NULL) ? TRUE : FALSE;
  897. }
  898. };
  899. //
  900. // PROXY_INFO_GLOBAL - global proxy information for settings
  901. //
  902. class PROXY_INFO_GLOBAL : public PROXY_INFO {
  903. private:
  904. //
  905. // _dwProxyFlags - set to control the various proxy modes that we support
  906. //
  907. DWORD _dwProxyFlags;
  908. //
  909. // _dwConnectionName - set to new connection name associated with this proxy info
  910. //
  911. LPSTR _lpszConnectionName;
  912. //
  913. // _fRefreshDisabled - TRUE at initalization, we're not allowed
  914. // to refresh until InternetOpen
  915. //
  916. BOOL _fRefreshDisabled;
  917. //
  918. // _fQueuedRefresh - A refresh has been queued up,
  919. // ready to take place after InternetOpen
  920. //
  921. BOOL _fQueuedRefresh;
  922. public:
  923. PROXY_INFO_GLOBAL() {
  924. _lpszConnectionName = NULL;
  925. _dwProxyFlags = 0;
  926. _fQueuedRefresh = FALSE;
  927. _fRefreshDisabled = TRUE;
  928. }
  929. ~PROXY_INFO_GLOBAL() {
  930. }
  931. // This function determines if a host bypasses the proxy.
  932. // Will use autoproxy if it is enabled, else it will just
  933. // consult the bypass list.
  934. BOOL
  935. HostBypassesProxy(
  936. IN INTERNET_SCHEME tScheme,
  937. IN LPSTR lpszHostName,
  938. IN DWORD dwHostNameLength
  939. );
  940. VOID
  941. ClearBadProxyList(
  942. VOID
  943. )
  944. {
  945. Lock(TRUE);
  946. _BadProxyList.ClearList();
  947. Unlock();
  948. }
  949. VOID
  950. CheckForExpiredEntries(
  951. VOID
  952. )
  953. {
  954. Lock(TRUE);
  955. _BadProxyList.CheckForExpiredEntries();
  956. Unlock();
  957. }
  958. BOOL IsRefreshDisabled(VOID) {
  959. return (_fRefreshDisabled);
  960. }
  961. VOID SetRefreshDisabled(BOOL fDisable) {
  962. _fRefreshDisabled = fDisable;
  963. }
  964. VOID QueueRefresh(VOID) {
  965. _fQueuedRefresh = TRUE;
  966. }
  967. VOID
  968. ReleaseQueuedRefresh(
  969. VOID
  970. );
  971. // Virtual Interface APIs
  972. //
  973. // TerminateProxySettings - destroys our internal vars
  974. // SetProxySettings - update proxy settings
  975. // GetProxySettings - get current proxy settings
  976. // RefreshProxySettings - force proxy settings to be reprocessed (auto-proxy, auto-detect)
  977. // QueryProxySettings - ask proxy objects for proxy info
  978. // IsProxySettingsConfigured
  979. //
  980. VOID
  981. TerminateProxySettings(
  982. VOID
  983. );
  984. DWORD
  985. SetProxySettings(
  986. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  987. IN BOOL fModifiedInProcess
  988. );
  989. DWORD
  990. GetProxySettings(
  991. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  992. IN BOOL fCheckVersion
  993. );
  994. DWORD
  995. RefreshProxySettings(
  996. IN BOOL fForceRefresh
  997. );
  998. DWORD
  999. QueryProxySettings(
  1000. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  1001. );
  1002. BOOL IsProxySettingsConfigured(VOID) {
  1003. return PROXY_INFO::IsProxySettingsConfigured();
  1004. }
  1005. LPSTR GetConnectionName(VOID) {
  1006. return _lpszConnectionName;
  1007. }
  1008. };
  1009. //
  1010. // PROXY_INFO_GLOBAL_WRAPPER - wraps the global proxy information
  1011. // so that we can avoid using, auto-proxy and auto-detect
  1012. //
  1013. class PROXY_INFO_GLOBAL_WRAPPER : public PROXY_INFO {
  1014. public:
  1015. PROXY_INFO_GLOBAL_WRAPPER() {
  1016. }
  1017. ~PROXY_INFO_GLOBAL_WRAPPER() {
  1018. DEBUG_ENTER((DBG_OBJECTS,
  1019. None,
  1020. "PROXY_INFO_GLOBAL_WRAPPER::~PROXY_INFO_GLOBAL_WRAPPER",
  1021. ""
  1022. ));
  1023. DEBUG_LEAVE(0);
  1024. }
  1025. //
  1026. // Virtual Interface APIs
  1027. //
  1028. VOID
  1029. InitializeProxySettings(
  1030. VOID
  1031. )
  1032. {
  1033. }
  1034. VOID
  1035. TerminateProxySettings(
  1036. VOID
  1037. )
  1038. {
  1039. }
  1040. DWORD
  1041. SetProxySettings(
  1042. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  1043. IN BOOL fModifiedInProcess
  1044. )
  1045. {
  1046. return ERROR_SUCCESS; // do nothing
  1047. }
  1048. DWORD
  1049. GetProxySettings(
  1050. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  1051. IN BOOL fCheckVersion
  1052. )
  1053. {
  1054. return ERROR_SUCCESS; // do nothing
  1055. }
  1056. DWORD
  1057. RefreshProxySettings(
  1058. IN BOOL fForceRefresh
  1059. )
  1060. {
  1061. return ERROR_SUCCESS; // do nothing
  1062. }
  1063. DWORD
  1064. QueryProxySettings(
  1065. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForProxyInfo
  1066. )
  1067. {
  1068. return g_pGlobalProxyInfo->PROXY_INFO::QueryProxySettings(ppQueryForProxyInfo);
  1069. }
  1070. BOOL IsProxySettingsConfigured(VOID) {
  1071. return g_pGlobalProxyInfo->PROXY_INFO::IsProxySettingsConfigured();
  1072. }
  1073. };