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.

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