Source code of Windows XP (NT5)
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.

164 lines
5.1 KiB

  1. /*****************************************************************************\
  2. FILE: proxycache.cpp
  3. DESCRIPTION:
  4. FTP Folder uses WININET which doesn't work thru CERN proxies. In that
  5. case, we need to hand control of the FTP URL back to the browser to do the
  6. old URLMON handling of it. The problem is that testing for a CERN proxy
  7. blocking access is expensive.
  8. \*****************************************************************************/
  9. #include "priv.h"
  10. #include "util.h"
  11. #define PROXY_CACHE_SIZE 15
  12. typedef struct
  13. {
  14. TCHAR szServerName[INTERNET_MAX_HOST_NAME_LENGTH];
  15. BOOL fIsBlocking;
  16. } PROXYCACHEENTRY;
  17. static int g_nLastIndex = 0;
  18. static BOOL g_fInited = FALSE;
  19. static TCHAR g_szProxyServer[MAX_URL_STRING] = {0};
  20. static PROXYCACHEENTRY g_ProxyCache[PROXY_CACHE_SIZE];
  21. /////////////////////////////////////////////////////////////////////////
  22. /////// Private helpers /////////////////////////////////////////////
  23. /////////////////////////////////////////////////////////////////////////
  24. void ProxyCache_Init(void)
  25. {
  26. g_nLastIndex = 0;
  27. for (int nIndex = 0; nIndex < ARRAYSIZE(g_ProxyCache); nIndex++)
  28. {
  29. g_ProxyCache[nIndex].fIsBlocking = FALSE;
  30. g_ProxyCache[nIndex].szServerName[0] = 0;
  31. }
  32. g_fInited = TRUE;
  33. }
  34. /****************************************************\
  35. FUNCTION: ProxyCache_WasProxyChanged
  36. DESCRIPTION:
  37. See if someone changed the proxy settings via
  38. the inetcpl. This is important because it is
  39. frustration to find FTP fails because of the proxy
  40. settings, fix the proxy settings, and then it still
  41. doesn't work because we cached the results.
  42. \****************************************************/
  43. BOOL ProxyCache_WasProxyChanged(void)
  44. {
  45. BOOL fWasChanged = FALSE;
  46. TCHAR szCurrProxyServer[MAX_URL_STRING];
  47. DWORD cbSize = SIZEOF(szCurrProxyServer);
  48. // PERF: If I wanted to be really fast, I would cache the hkey
  49. // so this would be faster. But since my DLL can be loaded/unloaded
  50. // serveral times in a process, I would leak each instance unless I
  51. // released the hkey in DLL_PROCESS_DETACH
  52. if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_SETTINGS_LAN, SZ_REGVALUE_PROXY_SERVER, NULL, szCurrProxyServer, &cbSize))
  53. {
  54. // Is this the first time? (Is g_szProxyServer empty?)
  55. if (!g_szProxyServer[0])
  56. StrCpyN(g_szProxyServer, szCurrProxyServer, ARRAYSIZE(g_szProxyServer));
  57. // Did it change?
  58. if (StrCmp(szCurrProxyServer, g_szProxyServer))
  59. fWasChanged = TRUE;
  60. }
  61. return fWasChanged;
  62. }
  63. /////////////////////////////////////////////////////////////////////////
  64. /////// APIs helpers /////////////////////////////////////////////
  65. /////////////////////////////////////////////////////////////////////////
  66. /****************************************************\
  67. FUNCTION: ProxyCache_IsProxyBlocking
  68. DESCRIPTION:
  69. Look in the cache with the FTP server in pidl
  70. and see if we have a cached value that indicates
  71. if it's blocked by the proxy.
  72. PARAMETERS:
  73. *pfIsBlocking - Is the proxy blocking.
  74. return - Is the value cached
  75. \****************************************************/
  76. BOOL ProxyCache_IsProxyBlocking(LPCITEMIDLIST pidl, BOOL * pfIsBlocking)
  77. {
  78. BOOL fIsInCache = FALSE;
  79. if (ProxyCache_WasProxyChanged())
  80. ProxyCache_Init(); // Purge the results
  81. *pfIsBlocking = FALSE; // Assume we don't know.
  82. if (!g_fInited)
  83. {
  84. ProxyCache_Init();
  85. }
  86. else
  87. {
  88. int nCount = ARRAYSIZE(g_ProxyCache);
  89. TCHAR szNewServer[INTERNET_MAX_HOST_NAME_LENGTH];
  90. // Is this the same server we tried last time? If so,
  91. // let's just cache the return value.
  92. FtpPidl_GetServer(pidl, szNewServer, ARRAYSIZE(szNewServer));
  93. for (int nIndex = g_nLastIndex; nCount && g_ProxyCache[nIndex].szServerName[0]; nCount--, nIndex--)
  94. {
  95. if (nIndex < 0)
  96. nIndex = (PROXY_CACHE_SIZE - 1);
  97. if (!StrCmp(szNewServer, g_ProxyCache[nIndex].szServerName))
  98. {
  99. // Yes, so bail.
  100. *pfIsBlocking = g_ProxyCache[nIndex].fIsBlocking;
  101. fIsInCache = TRUE;
  102. break;
  103. }
  104. }
  105. }
  106. return fIsInCache;
  107. }
  108. /****************************************************\
  109. FUNCTION: ProxyCache_SetProxyBlocking
  110. DESCRIPTION:
  111. PARAMETERS:
  112. *pfIsBlocking - Is the proxy blocking.
  113. return - Is the value cached
  114. \****************************************************/
  115. void ProxyCache_SetProxyBlocking(LPCITEMIDLIST pidl, BOOL fIsBlocking)
  116. {
  117. TCHAR szNewServer[INTERNET_MAX_HOST_NAME_LENGTH];
  118. // Add it to the cache because our caller will hit the server to
  119. // verify and we can be ready for next time.
  120. g_nLastIndex++;
  121. if (g_nLastIndex >= PROXY_CACHE_SIZE)
  122. g_nLastIndex = 0;
  123. FtpPidl_GetServer(pidl, szNewServer, ARRAYSIZE(szNewServer));
  124. StrCpyN(g_ProxyCache[g_nLastIndex].szServerName, szNewServer, ARRAYSIZE(g_ProxyCache[g_nLastIndex].szServerName));
  125. g_ProxyCache[g_nLastIndex].fIsBlocking = fIsBlocking;
  126. }