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.

2619 lines
88 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cachecfg.cxx
  5. Abstract:
  6. This module contains the functions to get and set disk cache
  7. configuration parameters.
  8. Contents:
  9. GetCacheConfigInfoA
  10. SetCacheConfigInfoA
  11. Author:
  12. Sophia Chung (sophiac) 1-May-1995
  13. Environment:
  14. User Mode - Win32
  15. Revision History:
  16. Mucho rewritten by Akabir 1Q 98
  17. To understand how the new registration code works, it might be better for you to start with ConfigureCache,
  18. GetCacheConfigInfo, etc. for a high level acquaintance; _then_ start poring over the actual registry sets code.
  19. --*/
  20. #include <wininetp.h>
  21. #include <cache.hxx>
  22. #include <conmgr.hxx>
  23. #include <time.h>
  24. #include <shlobj.h>
  25. #define CACHE_TAG "Cache"
  26. // Cache path keys.
  27. CHAR* g_szSubKey[] = {CONTENT_PATH_KEY, COOKIE_PATH_KEY, HISTORY_PATH_KEY};
  28. CHAR* g_szOldSubKey[] = {CACHE_TAG, COOKIE_PATH_KEY, HISTORY_PATH_KEY};
  29. INT g_iContainerCSIDL[] = { CSIDL_INTERNET_CACHE, CSIDL_COOKIES, CSIDL_HISTORY };
  30. // Top level cache paths resource IDs
  31. #ifndef UNIX
  32. CHAR* g_dwCachePathResourceID[] = {IDS_CACHE_DEFAULT_SUBDIR, IDS_COOKIES_DEFAULT_SUBDIR, IDS_HISTORY_DEFAULT_SUBDIR};
  33. #else
  34. CHAR* g_dwCachePathResourceID[] = {IDS_CACHE_DEFAULT_SUBDIR_UNIX, IDS_COOKIES_DEFAULT_SUBDIR, IDS_HISTORY_DEFAULT_SUBDIR};
  35. #endif /* UNIX */
  36. // Cache prefixes.
  37. CHAR* g_szCachePrefix[] = {CONTENT_PREFIX, COOKIE_PREFIX, HISTORY_PREFIX};
  38. CHAR* g_szVersionName[] = { CONTENT_VERSION_SUBDIR, "", "History.IE5" };
  39. #define OLD_CACHE_PATH "Path1"
  40. #define OLD_CACHE_SUBKEY DIR_SEPARATOR_STRING##"Cache1"
  41. typedef BOOL (WINAPI *PFNGETDISKFREESPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
  42. void FlushShellFolderCache()
  43. {
  44. SHFlushSFCacheWrap( );
  45. return;
  46. }
  47. typedef HRESULT (*PFNSHGETFOLDERPATH)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath);
  48. VOID CheckCacheLocationConsistency();
  49. //#define DEBUG_CACHE_UPGRADE
  50. #ifdef DEBUG_CACHE_UPGRADE
  51. VOID LOG_UPGRADE_DATA(PTSTR pszData)
  52. {
  53. CHAR szFileName[MAX_PATH];
  54. DWORD dwSize = MAX_PATH;
  55. CHAR szComputerName[MAX_PATH];
  56. HANDLE hResultsFile = NULL;
  57. strcpy(szFileName, "\\\\BANYAN\\IPTD\\AKABIR\\cacheupgrade\\");
  58. if (!GetComputerNameA(szComputerName, &dwSize))
  59. {
  60. goto exit;
  61. }
  62. lstrcatA(szFileName, szComputerName);
  63. hResultsFile = CreateFileA( szFileName,
  64. GENERIC_WRITE,
  65. FILE_SHARE_WRITE | FILE_SHARE_READ,
  66. NULL,
  67. OPEN_ALWAYS,
  68. 0,
  69. NULL);
  70. if (hResultsFile != INVALID_HANDLE_VALUE)
  71. {
  72. if (SetFilePointer(hResultsFile, 0, NULL, FILE_END)==0xFFFFFFFF)
  73. {
  74. goto exit;
  75. }
  76. DWORD dwFoo;
  77. if (0==WriteFile(hResultsFile, (PVOID)pszData, lstrlenA(pszData), &dwFoo, NULL))
  78. {
  79. DWORD dwE = GetLastError();
  80. }
  81. }
  82. exit:
  83. if (hResultsFile)
  84. {
  85. CloseHandle(hResultsFile);
  86. }
  87. }
  88. #else
  89. #define LOG_UPGRADE_DATA(x)
  90. #endif
  91. #undef SHGetFolderPath
  92. HRESULT SHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath)
  93. {
  94. HRESULT hr = E_POINTER;
  95. static PFNSHGETFOLDERPATH pfn = NULL;
  96. if (NULL == pfn)
  97. {
  98. if (NULL == g_HMODShell32)
  99. g_HMODShell32 = LoadLibrary("shell32.dll");
  100. if (NULL != g_HMODShell32)
  101. pfn = (PFNSHGETFOLDERPATH)GetProcAddress(g_HMODShell32, "SHGetFolderPathA");
  102. if (NULL == pfn)
  103. {
  104. if (NULL == g_HMODSHFolder)
  105. g_HMODSHFolder = LoadLibrary("shfolder.dll");
  106. if (NULL != g_HMODSHFolder)
  107. pfn = (PFNSHGETFOLDERPATH)GetProcAddress(g_HMODSHFolder, "SHGetFolderPathA");
  108. }
  109. if (NULL != pfn)
  110. hr = pfn(hwnd, csidl, hToken, dwFlags, pszPath);
  111. }
  112. else
  113. hr = pfn(hwnd, csidl, hToken, dwFlags, pszPath);
  114. return hr;
  115. }
  116. #define CACHE_SIZE_CAP 32000000
  117. DWORD
  118. GetDefaultCacheQuota(
  119. LPSTR pszCachePath,
  120. DWORD dwFraction
  121. )
  122. {
  123. DWORDLONG cKBLimit = 0, cbTotal;
  124. if (GetDiskInfo(pszCachePath, NULL, NULL, &cbTotal))
  125. {
  126. cKBLimit = (cbTotal / (DWORDLONG)(1024*dwFraction));
  127. }
  128. if (cKBLimit<1024)
  129. {
  130. cKBLimit = DEF_CACHE_LIMIT;
  131. }
  132. else if (cKBLimit > CACHE_SIZE_CAP)
  133. {
  134. cKBLimit = CACHE_SIZE_CAP;
  135. }
  136. return (DWORD)cKBLimit;
  137. }
  138. VOID CleanPath(PTSTR pszPath);
  139. /*-----------------------------------------------------------------------------
  140. NormalisePath
  141. (code swiped from shell32\folder.c: UnexpandEnvironmentstring)
  142. Collapses paths of the form C:\foobar\dir1\...\dirn to
  143. %FOOBAR%\dir1\...\dirn
  144. where %FOOBAR% = "C:\foobar".
  145. storing result in pszOut.
  146. If collapse is not possible, returns FALSE and path is unchanged.
  147. If the given environment variable exists as the first part of the path,
  148. then the environment variable is inserted into the output buffer.
  149. Returns TRUE if pszResult is filled in.
  150. Example: Input -- C:\WINNT\SYSTEM32\FOO.TXT -and- lpEnvVar = %SystemRoot%
  151. Output -- %SystemRoot%\SYSTEM32\FOO.TXT
  152. ---------------------------------------------------------------------------*/
  153. BOOL NormalisePath(LPCTSTR pszPath, LPCTSTR pszEnvVar, LPTSTR pszResult, UINT cbResult)
  154. {
  155. TCHAR szEnvVar[MAX_PATH];
  156. // DWORD dwEnvVar = ExpandEnvironmentStrings(pszEnvVar, szEnvVar, sizeof(szEnvVar)) - 1; // don't count the NULL
  157. // akabir: a curious bug? causes ExpandEnvironmentStrings to return twice the number of characters.
  158. ExpandEnvironmentStrings(pszEnvVar, szEnvVar, sizeof(szEnvVar)-1); // don't count the NULL
  159. DWORD dwEnvVar = lstrlen(szEnvVar);
  160. if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, szEnvVar, dwEnvVar, pszPath, dwEnvVar) == 2)
  161. {
  162. if (lstrlen(pszPath) + dwEnvVar < cbResult)
  163. {
  164. strncpy(pszResult, pszEnvVar, MAX_PATH);
  165. strncat(pszResult, pszPath + dwEnvVar, MAX_PATH);
  166. return TRUE;
  167. }
  168. }
  169. return FALSE;
  170. }
  171. VOID CompressPath(LPTSTR pszSrc, LPTSTR pszDest)
  172. {
  173. if (!NormalisePath(pszSrc, TEXT("%USERPROFILE%"), pszDest, MAX_PATH))
  174. {
  175. if (!NormalisePath(pszSrc, TEXT("%SystemRoot%"), pszDest, MAX_PATH))
  176. {
  177. strncpy(pszDest, pszSrc, MAX_PATH);
  178. }
  179. }
  180. }
  181. // ------------------------------------------------------------------------------------------------
  182. // IE 3, 4 and 5 have different registry settings. These classes help ensure they all stay in sync.
  183. // -- IE5's registry set ------------------------------------------------------------------------------------------------
  184. // *** If using multiple registry sets, use InitialiseKeys for IE5 first.***
  185. // This is to ensure that profiles-capabilities are noted.
  186. class IE5_REGISTRYSET
  187. {
  188. protected:
  189. REGISTRY_OBJ m_roHKLMCache, m_roHKCUCache, m_roShellFolder, m_roUserShellFolder, m_roWorking;
  190. BOOL m_fProfiles;
  191. BOOL m_fWorkingPerUser;
  192. TCHAR m_szSharedPath[MAX_PATH];
  193. TCHAR m_szProfilePath[MAX_PATH];
  194. DWORD cbP, cbS, m_dwWorking;
  195. BOOL m_fInitialised;
  196. DWORD InitCommonKeys(BOOL fProfilesCapable, LPSTR pszReg)
  197. {
  198. DWORD dwError, dwFlag = CREATE_KEY_IF_NOT_EXISTS;
  199. m_fProfiles = fProfilesCapable;
  200. // Shared item info are located in HKLM/[...]/Internet Settings/5.0/Cache/*
  201. m_roHKLMCache.WorkWith(HKEY_LOCAL_MACHINE, pszReg, dwFlag);
  202. if (dwError = m_roHKLMCache.GetStatus()!=ERROR_SUCCESS)
  203. {
  204. m_roHKLMCache.WorkWith(HKEY_LOCAL_MACHINE, pszReg, dwFlag, BASIC_ACCESS);
  205. if (dwError = m_roHKLMCache.GetStatus()!=ERROR_SUCCESS)
  206. goto exit;
  207. }
  208. m_roShellFolder.WorkWith(HKEY_CURRENT_USER, SHELL_FOLDER_KEY, dwFlag);
  209. if (dwError = m_roShellFolder.GetStatus()!=ERROR_SUCCESS)
  210. goto exit;
  211. if (fProfilesCapable)
  212. {
  213. m_roHKCUCache.WorkWith(HKEY_CURRENT_USER, pszReg, dwFlag);
  214. if (dwError = m_roHKCUCache.GetStatus()!=ERROR_SUCCESS)
  215. goto exit;
  216. }
  217. m_roUserShellFolder.WorkWith(HKEY_CURRENT_USER, USER_SHELL_FOLDER_KEY, dwFlag);
  218. dwError = m_roUserShellFolder.GetStatus();
  219. if (dwError==ERROR_SUCCESS)
  220. {
  221. m_fInitialised = TRUE;
  222. }
  223. // Per-user items are located in HKCU/[...]/Explorer/Shell Folders and /Internet Settings/[5.0/]Cache/*
  224. exit:
  225. return dwError;
  226. }
  227. virtual BOOL DetermineKeyPlacing(DWORD dwWhich)
  228. {
  229. // Determine if this is a per-user item
  230. // HKCU overrides HKLM
  231. // If any of the following fail, for content, we'll default to shared.
  232. if (!m_fProfiles)
  233. {
  234. return FALSE;
  235. }
  236. DWORD dwTemp;
  237. REGISTRY_OBJ roCUContainer(&m_roHKCUCache, g_szSubKey[dwWhich], CREATE_KEY_IF_NOT_EXISTS);
  238. if ((roCUContainer.GetStatus()==ERROR_SUCCESS)
  239. &&
  240. (roCUContainer.GetValue(PER_USER_KEY, &dwTemp)==ERROR_SUCCESS))
  241. {
  242. return dwTemp;
  243. }
  244. REGISTRY_OBJ roLMContainer(&m_roHKLMCache, g_szSubKey[dwWhich], CREATE_KEY_IF_NOT_EXISTS);
  245. BOOL fPerUser = FALSE;
  246. if ((roLMContainer.GetStatus()==ERROR_SUCCESS)
  247. &&
  248. (roLMContainer.GetValue(PER_USER_KEY, &dwTemp)==ERROR_SUCCESS))
  249. {
  250. return dwTemp;
  251. }
  252. // On NT, the default will be a per-user container.
  253. #ifndef UNIX
  254. dwTemp = (GlobalPlatformType == PLATFORM_TYPE_WINNT) ? TRUE : (dwWhich!=CONTENT);
  255. #else
  256. dwTemp = (GlobalPlatformType == PLATFORM_TYPE_UNIX) ? TRUE : (dwWhich!=CONTENT);
  257. #endif /* UNIX */
  258. roLMContainer.SetValue(PER_USER_KEY, &dwTemp);
  259. roCUContainer.SetValue(PER_USER_KEY, &dwTemp);
  260. return (BOOL)dwTemp;
  261. }
  262. // -- ValidatePath ------
  263. // We always assume we've been given a valid path, but we have to test that it's there
  264. // and available.
  265. BOOL ValidatePath(PSTR pszPath)
  266. {
  267. DWORD dwAttribute = GetFileAttributes(pszPath);
  268. if (dwAttribute==0xFFFFFFFF)
  269. {
  270. // We assume that the directory just isn't there. So we create it.
  271. hConstructSubDirs(pszPath);
  272. dwAttribute = GetFileAttributes(pszPath);
  273. }
  274. if ((dwAttribute==0xFFFFFFFF)
  275. ||
  276. (dwAttribute & FILE_ATTRIBUTE_READONLY)
  277. ||
  278. (!(dwAttribute & FILE_ATTRIBUTE_DIRECTORY)))
  279. {
  280. // BUG BUG BUG We probably want to make sure that the old path gets deleted on other machines....
  281. // We'll use the system path
  282. // BUG BUG BUG BUG BUG We are *NOT* recording this default location in the registry. Thus, on another
  283. // machine, the user might still be able to use the set cache location.
  284. memcpy(pszPath, m_szSharedPath, cbS);
  285. #if 0
  286. LoadString(GlobalDllHandle, g_dwCachePathResourceID[m_dwWorking], pszPath+cbS, MAX_PATH - cbS);
  287. #endif
  288. memcpy(pszPath+cbS, g_dwCachePathResourceID[m_dwWorking],
  289. strlen(g_dwCachePathResourceID[m_dwWorking]) + 1);
  290. SetPerUserStatus(FALSE);
  291. }
  292. return ERROR_SUCCESS;
  293. }
  294. public:
  295. IE5_REGISTRYSET()
  296. {
  297. m_fInitialised = FALSE;
  298. }
  299. virtual DWORD InitialiseKeys(BOOL& fProfilesCapable)
  300. {
  301. if (m_fInitialised)
  302. {
  303. fProfilesCapable = m_fProfiles;
  304. return ERROR_SUCCESS;
  305. }
  306. DWORD dwError = ERROR_SUCCESS;
  307. fProfilesCapable = TRUE;
  308. #ifndef UNIX
  309. cbS = GetWindowsDirectory(m_szSharedPath, sizeof(m_szSharedPath));
  310. #else
  311. /* On Unix, GetWindowsDirectory points to <install dir>/common
  312. * And, we don't want to put the cache here.
  313. */
  314. lstrcpy(m_szSharedPath, UNIX_SHARED_CACHE_PATH);
  315. cbS = lstrlen(m_szSharedPath);
  316. #endif /* UNIX */
  317. if (!cbS || (cbS>sizeof(m_szSharedPath)))
  318. return ERROR_PATH_NOT_FOUND;
  319. AppendSlashIfNecessary(m_szSharedPath, &cbS);
  320. cbP = 0;
  321. // We think that profiles are enabled, so we want to get some info before
  322. // proceeding. If any of this fails, though, we'll default to no profiles.
  323. switch (GlobalPlatformType)
  324. {
  325. #ifndef UNIX
  326. case PLATFORM_TYPE_WIN95:
  327. {
  328. REGISTRY_OBJ roProfilesEnabled(HKEY_LOCAL_MACHINE, PROFILES_ENABLED_VALUE);
  329. DWORD dwProfilesEnabled = 0;
  330. if ( (roProfilesEnabled.GetStatus() == ERROR_SUCCESS)
  331. &&
  332. ((roProfilesEnabled.GetValue(PROFILES_ENABLED, &dwProfilesEnabled))==ERROR_SUCCESS)
  333. &&
  334. dwProfilesEnabled)
  335. {
  336. // Windows 95 sets the profiles path in the registry.
  337. CHAR szProfilesRegValue[MAX_PATH];
  338. memcpy(szProfilesRegValue, PROFILES_PATH_VALUE, sizeof(PROFILES_PATH_VALUE)-1);
  339. cbP = sizeof(PROFILES_PATH_VALUE)-1;
  340. AppendSlashIfNecessary(szProfilesRegValue, &cbP);
  341. cbP = MAX_PATH-sizeof(PROFILES_PATH_VALUE);
  342. if (GetUserName(szProfilesRegValue + sizeof(PROFILES_PATH_VALUE), &cbP))
  343. {
  344. cbP = MAX_PATH;
  345. REGISTRY_OBJ roProfilesDirKey(HKEY_LOCAL_MACHINE, szProfilesRegValue);
  346. if (!(((dwError = roProfilesDirKey.GetStatus()) != ERROR_SUCCESS)
  347. ||
  348. ((dwError = roProfilesDirKey.GetValue(PROFILES_PATH, (LPBYTE) m_szProfilePath,
  349. &cbP)) != ERROR_SUCCESS)))
  350. {
  351. m_szProfilePath[cbP-1] = DIR_SEPARATOR_CHAR;
  352. m_szProfilePath[cbP] = '\0';
  353. break;
  354. }
  355. }
  356. }
  357. // Either
  358. // (a) Couldn't get the profiles path from the registry.
  359. // (b) Couldn't get the user name!
  360. // Make the directory the windows directory
  361. fProfilesCapable = FALSE;
  362. break;
  363. }
  364. case PLATFORM_TYPE_WINNT:
  365. // Windows NT sets the USERPROFILE environment
  366. // string which contains the user's profile path
  367. if (cbP = GetEnvironmentVariable("USERPROFILE", m_szProfilePath, MAX_PATH))
  368. {
  369. m_szProfilePath[cbP++] = DIR_SEPARATOR_CHAR;
  370. m_szProfilePath[cbP] = '\0';
  371. }
  372. else
  373. {
  374. INET_ASSERT(FALSE);
  375. // Getting the user profiles dir from the environment
  376. // failed. Set the profiles directory to default.
  377. memcpy(m_szProfilePath, m_szSharedPath, cbS);
  378. memcpy(m_szProfilePath + cbS, DEFAULT_PROFILES_DIRECTORY, sizeof(DEFAULT_PROFILES_DIRECTORY));
  379. cbP = cbS + sizeof(DEFAULT_PROFILES_DIRECTORY) - 1;
  380. DWORD cbUser = MAX_PATH - cbP;;
  381. GetUserName(m_szProfilePath + cbP, &cbUser);
  382. cbP += cbUser;
  383. }
  384. break;
  385. #else /* UNIX */
  386. case PLATFORM_TYPE_UNIX:
  387. lstrcpy(m_szProfilePath,TEXT("%USERPROFILE%"));
  388. lstrcat(m_szProfilePath,DIR_SEPARATOR_STRING);
  389. cbP = lstrlen(m_szProfilePath);
  390. break;
  391. #endif /* UNIX */
  392. default:
  393. // This should never happen.
  394. INET_ASSERT(FALSE);
  395. }
  396. if (dwError==ERROR_SUCCESS)
  397. {
  398. dwError = InitCommonKeys(fProfilesCapable, CACHE5_KEY);
  399. }
  400. return dwError;
  401. }
  402. DWORD SetWorkingContainer(DWORD dwWhich)
  403. {
  404. m_dwWorking = dwWhich;
  405. m_fWorkingPerUser = DetermineKeyPlacing(dwWhich);
  406. return m_roWorking.WorkWith((m_fWorkingPerUser ? &m_roHKCUCache : &m_roHKLMCache), g_szSubKey[dwWhich], CREATE_KEY_IF_NOT_EXISTS);
  407. }
  408. // VOID AttemptToUseSharedCache(PTSTR pszPath, DWORD ckbLimit);
  409. // Path --------------------------------------------------------------------------
  410. virtual DWORD GetPath(PTSTR pszPath)
  411. {
  412. if ((S_OK==SHGetFolderPath(NULL, g_iContainerCSIDL[m_dwWorking] | CSIDL_FLAG_CREATE, NULL, 0, pszPath))
  413. && (*pszPath!='\0'))
  414. {
  415. DWORD dwErr = ValidatePath(pszPath);
  416. if (dwErr==ERROR_SUCCESS)
  417. {
  418. DWORD ccPath = lstrlen(pszPath);
  419. // We check the lengths of the strings only when we're moving the containers. No need to do the check every
  420. // time (assume a valid path)
  421. if (m_dwWorking!=COOKIE)
  422. {
  423. EnableCacheVu(pszPath, m_dwWorking);
  424. }
  425. AppendSlashIfNecessary(pszPath, &ccPath);
  426. #ifdef UNIX
  427. /* On Unix, it is possible that IE4 and IE5 co-exist on a user's
  428. * installation. So, we need to keep the IE4 cookies which are
  429. * different from the IE5 cookies. For IE5, we have the following
  430. * configuration for the caches -
  431. *
  432. * cookies - %HOME%/.microsoft/ie5/Cookies
  433. * content - %HOME%/.microsoft/ie5/TempInternetFiles/Content.IE5
  434. * history - %HOME%/.microsoft/ie5/History/History.IE5
  435. */
  436. CHAR szIE5Dir[] = "ie5/";
  437. int index = ccPath-2; // skip the last slash
  438. int lenIE5Dir = lstrlen(szIE5Dir);
  439. while(index >= 0 && pszPath[index] != FILENAME_SEPARATOR)
  440. index--;
  441. index++;
  442. memmove(&pszPath[index+lenIE5Dir],&pszPath[index],ccPath-index+2);
  443. memcpy(&pszPath[index],szIE5Dir,lenIE5Dir);
  444. ccPath += lenIE5Dir;
  445. #endif /* UNIX */
  446. memcpy(pszPath+ccPath, g_szVersionName[m_dwWorking], lstrlen(g_szVersionName[m_dwWorking])+1);
  447. if (GlobalIdentity && (m_dwWorking!=CONTENT))
  448. {
  449. if (!GenerateStringWithOrdinal(NULL, GlobalIdentity, pszPath, MAX_PATH))
  450. {
  451. dwErr = ERROR_WINHTTP_INTERNAL_ERROR;
  452. }
  453. }
  454. }
  455. return dwErr;
  456. }
  457. return ERROR_WINHTTP_INTERNAL_ERROR;
  458. }
  459. virtual DWORD SetPath(PTSTR pszPath)
  460. {
  461. INET_ASSERT(m_roWorking.GetStatus()==ERROR_SUCCESS);
  462. DWORD dwError;
  463. /* Try to preserve the environment variables on Unix */
  464. UNIX_NORMALIZE_PATH_ALWAYS(pszPath, TEXT("%USERPROFILE%"));
  465. if (m_fProfiles)
  466. {
  467. CHAR szScratch[MAX_PATH];
  468. CompressPath(pszPath, szScratch);
  469. if ((dwError = m_roUserShellFolder.SetValue(g_szOldSubKey[m_dwWorking], szScratch, REG_EXPAND_SZ))==ERROR_SUCCESS)
  470. {
  471. #ifndef UNIX
  472. DWORD dwType = REG_SZ;
  473. dwError = m_roShellFolder.SetValue(g_szOldSubKey[m_dwWorking],pszPath, dwType);
  474. #else
  475. dwError = m_roShellFolder.SetValue(g_szOldSubKey[m_dwWorking],szScratch, REG_EXPAND_SZ);
  476. #endif /* UNIX */
  477. }
  478. // Possible BUG: If we move from the profiled path to the shared path, we still record it as a peruseritem.
  479. SetPerUserStatus(TRUE);
  480. }
  481. // Non-profiles-enabled machine
  482. // On Win9x machines, with profiles disabled, we need to write the path to the
  483. // HKEY_USERS/.default/blah blah/Explorer/User Shell Folders to ensure that SHGetFolderPath returns
  484. // the proper value for other users.
  485. else
  486. {
  487. REGISTRY_OBJ roProfilesLessPath(HKEY_USERS, PROFILELESS_USF_KEY);
  488. dwError = roProfilesLessPath.GetStatus();
  489. if (dwError==ERROR_SUCCESS)
  490. {
  491. if ((dwError = roProfilesLessPath.SetValue(g_szOldSubKey[m_dwWorking],pszPath, REG_EXPAND_SZ))==ERROR_SUCCESS)
  492. {
  493. #ifndef UNIX
  494. DWORD dwType = REG_SZ;
  495. #else
  496. DWORD dwType = REG_EXPAND_SZ;
  497. #endif /* UNIX */
  498. dwError = m_roUserShellFolder.SetValue(g_szOldSubKey[m_dwWorking],pszPath, dwType);
  499. }
  500. }
  501. // For IE4 compatibility, we might have to adjust the old cache location here, as well.
  502. }
  503. return dwError;
  504. }
  505. // Prefix ------------------------------------------------------------------------
  506. virtual DWORD GetPrefix(LPSTR szPrefix)
  507. {
  508. DWORD dwError, cbKeyLen = MAX_PATH;
  509. if ((dwError = m_roWorking.GetValue(CACHE_PREFIX_VALUE, (LPBYTE) szPrefix, &cbKeyLen))==ERROR_SUCCESS)
  510. {
  511. if (cbKeyLen > 0)
  512. {
  513. // Strip trailing whitespace.
  514. cbKeyLen--;
  515. StripTrailingWhiteSpace(szPrefix, &cbKeyLen);
  516. }
  517. }
  518. else
  519. {
  520. // If no prefix found in registry create via
  521. // defaults and write back to registry.
  522. strncpy(szPrefix, g_szCachePrefix[m_dwWorking], MAX_PATH);
  523. SetPrefix(szPrefix);
  524. dwError = ERROR_SUCCESS;
  525. }
  526. return dwError;
  527. }
  528. virtual DWORD SetPrefix(PTSTR pszPrefix)
  529. {
  530. INET_ASSERT(m_roWorking.GetStatus()==ERROR_SUCCESS);
  531. return m_roWorking.SetValue(CACHE_PREFIX_VALUE, (pszPrefix) ? pszPrefix : g_szCachePrefix[m_dwWorking], REG_SZ);
  532. }
  533. // Limit -------------------------------------------------------------------------
  534. virtual DWORD GetLimit(PTSTR pszCachePath, DWORD& cbLimit)
  535. {
  536. if ((m_roWorking.GetValue(CACHE_LIMIT_VALUE, &cbLimit)!=ERROR_SUCCESS) || (cbLimit < 512))
  537. {
  538. cbLimit = 0;
  539. return SetLimit(pszCachePath, cbLimit);
  540. }
  541. return ERROR_SUCCESS;
  542. }
  543. // virtual DWORD SetLimit(PTSTR pszCachePath, DWORD& cbLimit);
  544. virtual DWORD SetLimit(PTSTR pszCachePath, DWORD& cbLimit)
  545. {
  546. INET_ASSERT(m_roWorking.GetStatus()==ERROR_SUCCESS);
  547. // If no limit found in registry create via
  548. // defaults and write back to registry.
  549. // Cache limit - for the content cache we calculate the cache limit
  550. // as being max(DEF_CACHE_LIMIT, 1/32 of the disk size) All others caches
  551. // are set to DEF_CACHE_LIMIT.
  552. if (cbLimit==0)
  553. {
  554. cbLimit = (m_dwWorking==CONTENT)
  555. ? GetDefaultCacheQuota(pszCachePath, NEW_CONTENT_QUOTA_DEFAULT_DISK_FRACTION)
  556. : DEF_CACHE_LIMIT;
  557. }
  558. DWORD dwError = m_roWorking.SetValue(CACHE_LIMIT_VALUE, &cbLimit);
  559. /*
  560. if (dwError==ERROR_SUCCESS)
  561. {
  562. // Hack so that apps that read the cache quota from the registry are
  563. // still able to do so.
  564. IE4_REGISTRYSET ie4;
  565. dwError = ie4.InitialiseKeys(m_fProfiles);
  566. if (dwError==ERROR_SUCCESS)
  567. {
  568. ie4.SetWorkingContainer(m_dwWorking);
  569. ie4.SetLimit(pszCachePath, cbLimit);
  570. }
  571. }
  572. */
  573. return dwError;
  574. }
  575. // Use IsFirstTime* to figure out if this is the first time for this install of wininet and for marking it so ------------
  576. private:
  577. BOOL IsFirstTimeFor(HKEY hKey)
  578. {
  579. DWORD cb = MAX_PATH;
  580. CHAR szSigKey[MAX_PATH];
  581. REGISTRY_OBJ roSig(hKey, CACHE5_KEY);
  582. return roSig.GetValue(CACHE_SIGNATURE_VALUE, (LPBYTE) szSigKey, &cb)==ERROR_SUCCESS ?
  583. strcmp(szSigKey, CACHE_SIGNATURE) : TRUE;
  584. }
  585. public:
  586. BOOL IsFirstTimeForUser()
  587. {
  588. return IsFirstTimeFor((m_fProfiles ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE));
  589. }
  590. BOOL IsFirstTimeForMachine()
  591. {
  592. return IsFirstTimeFor(HKEY_LOCAL_MACHINE);
  593. }
  594. VOID SetIfFirstTime()
  595. {
  596. DWORD cb = MAX_PATH;
  597. CHAR szSigKey[MAX_PATH];
  598. // On a profiles-not-enabled machine, store the signature in HKLM so we don't have to research for values
  599. // On a profiles-enabled machine, store there to notify IE of previous installation of IE5.
  600. REGISTRY_OBJ roSig(HKEY_LOCAL_MACHINE, CACHE5_KEY);
  601. roSig.SetValue(CACHE_SIGNATURE_VALUE, CACHE_SIGNATURE, REG_SZ);
  602. // On profiles-enabled machines, we store a signature in HKCU so that we don't have to do
  603. // much hunting for registry values
  604. if (m_fProfiles)
  605. {
  606. REGISTRY_OBJ roSig(HKEY_CURRENT_USER, CACHE5_KEY);
  607. roSig.SetValue(CACHE_SIGNATURE_VALUE, CACHE_SIGNATURE, REG_SZ);
  608. }
  609. }
  610. // PerUserItem ---------------------------------------------------------------------
  611. virtual VOID SetPerUserStatus(BOOL fState)
  612. {
  613. DWORD flState = fState;
  614. if (m_fProfiles && fState!=m_fWorkingPerUser)
  615. {
  616. REGISTRY_OBJ roTemp(&m_roHKCUCache, g_szSubKey[m_dwWorking], CREATE_KEY_IF_NOT_EXISTS);
  617. if (roTemp.GetStatus()==ERROR_SUCCESS)
  618. {
  619. roTemp.SetValue(PER_USER_KEY, &flState);
  620. m_roWorking.WorkWith((fState ? &m_roHKCUCache
  621. : &m_roHKLMCache), g_szSubKey[m_dwWorking], CREATE_KEY_IF_NOT_EXISTS);
  622. m_fWorkingPerUser = fState;
  623. }
  624. }
  625. }
  626. virtual DWORD GetPerUserStatus()
  627. {
  628. return m_fWorkingPerUser;
  629. }
  630. /*
  631. DWORD UpdateContentPath(PSTR pszNewPath)
  632. {
  633. TCHAR szOldPath[MAX_PATH];
  634. DWORD dwError;
  635. dwError = ERROR_SUCCESS;
  636. if ((dwError=SetWorkingContainer(CONTENT))==ERROR_SUCCESS)
  637. {
  638. INTERNET_CACHE_CONFIG_INFOA icci;
  639. icci.dwContainer = CONTENT;
  640. GetUrlCacheConfigInfoA(&icci, NULL, CACHE_CONFIG_DISK_CACHE_PATHS_FC);
  641. strncpy(szOldPath, icci.CachePath, ARRAY_ELEMENTS(szOldPath));
  642. if (((dwError=MoveCachedFiles(szOldPath, pszNewPath))==ERROR_SUCCESS)
  643. &&
  644. ((dwError=SetPath(pszNewPath))==ERROR_SUCCESS))
  645. {
  646. EnableCacheVu(pszNewPath);
  647. // Right now, we're adding entries so that once we restart, we'll delete any
  648. // stray files.
  649. // BUT, there's a case that Move will be interrupted; in that case, we ought
  650. // to finish the move on start up -- pop up a dialog notifying user of such
  651. // and then delete.
  652. // Also, if the Move's interrupted, then this info never will get written. OTOH,
  653. // we can argue that the user can just move from the old location to the new.
  654. CHAR szRunOnce [2 * MAX_PATH];
  655. CHAR szSystemPath [MAX_PATH];
  656. // Add a RunOnce entry to be run on reboot.
  657. REGISTRY_OBJ roRunOnce((m_fWorkingPerUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE), RUN_ONCE_KEY, CREATE_KEY_IF_NOT_EXISTS);
  658. if ((dwError=roRunOnce.GetStatus())!=ERROR_SUCCESS)
  659. return dwError;
  660. // create RunOnce string in the form:
  661. // "rundll32.exe <system dir>\wininet.dll,RunOnceUrlCache C:\Windows\NewCacheLocation"
  662. if (!GetSystemDirectory(szSystemPath, MAX_PATH))
  663. return ERROR_INTERNAL_ERROR;
  664. DisableCacheVu(szOldPath);
  665. // Get rid of content.ie5.
  666. PathRemoveBackslash(szOldPath);
  667. PathRemoveFileSpec(szOldPath);
  668. DisableCacheVu(szOldPath);
  669. GetShortPathName(szOldPath, szOldPath, ARRAY_ELEMENTS(szOldPath));
  670. wnsprintf(szRunOnce, sizeof(szRunOnce),
  671. "rundll32.exe %s\\wininet.dll,RunOnceUrlCache %s",
  672. szSystemPath, szOldPath);
  673. // Set the RunOnce command in registry for wininet.
  674. roRunOnce.SetValue(TEXT("MovingCacheA Wininet Settings"), (LPSTR)szRunOnce, REG_SZ);
  675. }
  676. }
  677. return dwError;
  678. }
  679. */
  680. // DWORD GetIEVersion();
  681. // -- AttemptToUseSharedCache
  682. // Given a path (and limit) attempt to use the path for a shared location.
  683. // If the path is null, then try to use any value if present, else invent one.
  684. VOID AttemptToUseSharedCache(PTSTR pszPath, DWORD ckbLimit)
  685. {
  686. TCHAR szSharedPath[MAX_PATH];
  687. DWORD cc = ARRAY_ELEMENTS(szSharedPath);
  688. REGISTRY_OBJ roContent(&m_roHKLMCache, g_szSubKey[CONTENT], CREATE_KEY_IF_NOT_EXISTS);
  689. if ((roContent.GetStatus()==ERROR_SUCCESS)
  690. &&
  691. (roContent.GetValue(CACHE_PATH_VALUE, (LPBYTE)szSharedPath, &cc)==ERROR_SUCCESS))
  692. {
  693. LOG_UPGRADE_DATA("Found a shared cache location...\n");
  694. goto write_value;
  695. }
  696. if (pszPath!=NULL)
  697. {
  698. LOG_UPGRADE_DATA(pszPath);
  699. LOG_UPGRADE_DATA("\n is ");
  700. GetUserName(szSharedPath, &cc);
  701. // We're going to ignore just the user name, during this comparison. And
  702. // if it's in the profiles directory, fuhgedaboutit.
  703. if (m_fProfiles && !StrCmpNI(m_szProfilePath, pszPath, cbP-cc))
  704. {
  705. pszPath = NULL;
  706. LOG_UPGRADE_DATA("not okay \n");
  707. goto carryon;
  708. }
  709. LOG_UPGRADE_DATA("okay \n");
  710. strcpy(szSharedPath, pszPath);
  711. }
  712. carryon:
  713. if (pszPath==NULL)
  714. {
  715. memcpy(szSharedPath, m_szSharedPath, (cbS+1)*sizeof(TCHAR));
  716. CleanPath(szSharedPath);
  717. LOG_UPGRADE_DATA("Using a constructed shared path\n");
  718. }
  719. // We've finally decided on the path. Now let's write the value into the registry.
  720. roContent.SetValue(CACHE_PATH_VALUE, szSharedPath, REG_SZ);
  721. SetWorkingContainer(CONTENT);
  722. SetPerUserStatus(FALSE);
  723. SetLimit(szSharedPath, ckbLimit);
  724. write_value:
  725. LOG_UPGRADE_DATA("The shared cache will be located at ");
  726. LOG_UPGRADE_DATA(szSharedPath);
  727. LOG_UPGRADE_DATA("\n");
  728. // This will take care of HKCU
  729. CHAR szScratch[MAX_PATH];
  730. #ifndef UNIX
  731. if (!NormalisePath(szSharedPath, TEXT("%SystemRoot%"), szScratch, sizeof(szScratch)))
  732. #else
  733. if (!NormalisePath(szSharedPath, TEXT("%USERPROFILE%"), szScratch, sizeof(szScratch)))
  734. #endif /* UNIX */
  735. {
  736. strncpy(szScratch, szSharedPath, MAX_PATH);
  737. }
  738. if (m_roUserShellFolder.SetValue(g_szOldSubKey[CONTENT], szScratch, REG_EXPAND_SZ)==ERROR_SUCCESS)
  739. {
  740. #ifndef UNIX
  741. DWORD dwType = REG_SZ;
  742. m_roShellFolder.SetValue(g_szOldSubKey[CONTENT], szSharedPath, dwType);
  743. #else
  744. m_roShellFolder.SetValue(g_szOldSubKey[CONTENT], szScratch, REG_EXPAND_SZ);
  745. #endif /* UNIX */
  746. }
  747. }
  748. };
  749. #define m_roPaths m_roShellFolder
  750. #define m_roSpecialPaths m_roHKCUCache
  751. #if 0
  752. class IE3_REGISTRYSET : public IE5_REGISTRYSET
  753. {
  754. // Registry keys shipped with IE 3:
  755. //
  756. // Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\Paths
  757. //
  758. // Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\Paths\path1
  759. // \path2
  760. // \path3
  761. // \path4
  762. //
  763. // Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\Special Paths
  764. //
  765. // Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\Special Paths\Cookies
  766. // \History
  767. //
  768. // Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\Url History
  769. private:
  770. REGISTRY_OBJ m_roPath[DEF_NUM_PATHS];
  771. public:
  772. // Initialise the IE3 keys that we might work with.
  773. DWORD InitialiseKeys()
  774. {
  775. DWORD dwError, i;
  776. TCHAR szScratch[MAX_PATH];
  777. TCHAR pszBase[MAX_PATH];
  778. DWORD dwBaseLen;
  779. if (m_fInitialised)
  780. {
  781. return ERROR_SUCCESS;
  782. }
  783. m_roHKLMCache.WorkWith(HKEY_LOCAL_MACHINE, OLD_CACHE_KEY, CREATE_KEY_IF_NOT_EXISTS);
  784. if ((dwError=m_roHKLMCache.GetStatus())!=ERROR_SUCCESS)
  785. goto exit;
  786. m_roPaths.WorkWith(&m_roHKLMCache, CACHE_PATHS_KEY, CREATE_KEY_IF_NOT_EXISTS);
  787. if ((dwError=m_roPaths.GetStatus())!=ERROR_SUCCESS)
  788. goto exit;
  789. memcpy(pszBase, OLD_CACHE_PATH, sizeof(OLD_CACHE_PATH));
  790. dwBaseLen = sizeof(OLD_CACHE_PATH) - 1;
  791. for (i = 0; i < DEF_NUM_PATHS; i++)
  792. {
  793. pszBase[dwBaseLen-1] = (TCHAR)('1' + i);
  794. m_roPath[i].WorkWith(&m_roPaths, pszBase, CREATE_KEY_IF_NOT_EXISTS);
  795. if ((dwError=m_roPath[i].GetStatus())!=ERROR_SUCCESS)
  796. goto exit;
  797. }
  798. m_roSpecialPaths.WorkWith(&m_roHKLMCache, CACHE_SPECIAL_PATHS_KEY);
  799. m_fInitialised = TRUE;
  800. exit:
  801. return dwError;
  802. }
  803. BOOL GetContentDetails(LPSTR szPath, DWORD& cbLimit)
  804. {
  805. DWORD cbKey = MAX_PATH;
  806. if (m_roPaths.GetValue(CACHE_DIRECTORY_VALUE, (LPBYTE)szPath, &cbKey)!=ERROR_SUCCESS)
  807. return FALSE;
  808. cbLimit = 0;
  809. for (int i=0; i<DEF_NUM_PATHS; i++)
  810. {
  811. if (m_roPath[i].GetValue(CACHE_LIMIT_VALUE, &cbKey)!=ERROR_SUCCESS)
  812. {
  813. cbLimit = GetDefaultCacheQuota(szPath, NEW_CONTENT_QUOTA_DEFAULT_DISK_FRACTION);
  814. break;
  815. }
  816. cbLimit += cbKey;
  817. }
  818. return TRUE;
  819. }
  820. DWORD SetPath(PTSTR pszPath)
  821. {
  822. DWORD i, nPaths, dwError;
  823. DWORD cb = strlen((LPSTR)pszPath);
  824. TCHAR szBase[MAX_PATH];
  825. #ifndef UNIX
  826. DWORD dwType = REG_SZ;
  827. #else
  828. DWORD dwType = REG_EXPAND_SZ;
  829. #endif /* UNIX */
  830. /* On Unix, try to preserve the Environment variables if possible */
  831. UNIX_NORMALIZE_PATH_ALWAYS(pszPath, TEXT("%USERPROFILE%"));
  832. // Cache content path.
  833. if ((dwError = m_roPaths.SetValue(CACHE_DIRECTORY_VALUE, (LPSTR)pszPath, dwType)) != ERROR_SUCCESS)
  834. goto exit;
  835. // Number of subdirectories (optional).
  836. nPaths = DEF_NUM_PATHS;
  837. if ((dwError = m_roPaths.SetValue(CACHE_PATHS_KEY, &nPaths)) != ERROR_SUCCESS)
  838. goto exit;
  839. memcpy(szBase, pszPath, cb);
  840. memcpy(szBase + cb, OLD_CACHE_SUBKEY, sizeof(OLD_CACHE_SUBKEY));
  841. cb += sizeof(OLD_CACHE_SUBKEY) - 2;
  842. // Subdirectories' paths and limits from CONTENT.
  843. for (i = 0; i < DEF_NUM_PATHS; i++)
  844. {
  845. szBase[cb] = (TCHAR)('1' + i);
  846. if ((dwError = m_roPath[i].SetValue(CACHE_PATH_VALUE, szBase, REG_SZ)) != ERROR_SUCCESS)
  847. goto exit;
  848. }
  849. exit:
  850. INET_ASSERT(dwError == ERROR_SUCCESS);
  851. return dwError;
  852. }
  853. DWORD SetLimit(DWORD dwLimit)
  854. {
  855. DWORD i, nPaths, dwError;
  856. for (i = 0; i < DEF_NUM_PATHS; i++)
  857. {
  858. DWORD cbCacheLimitPerSubCache = (DWORD) (dwLimit/ DEF_NUM_PATHS);
  859. if ((dwError = m_roPath[i].SetValue(CACHE_LIMIT_VALUE, &cbCacheLimitPerSubCache)) != ERROR_SUCCESS)
  860. goto exit;
  861. }
  862. exit:
  863. INET_ASSERT(dwError == ERROR_SUCCESS);
  864. return dwError;
  865. }
  866. // Restore key IE3 values. *snicker* --------------------------------------------
  867. VOID FixLegacySettings(PTSTR pszPath, DWORD cbLimit)
  868. {
  869. if (InitialiseKeys()==ERROR_SUCCESS)
  870. {
  871. SetPath(pszPath);
  872. SetLimit(cbLimit);
  873. }
  874. }
  875. };
  876. class IE4_REGISTRYSET : public IE5_REGISTRYSET
  877. {
  878. private:
  879. BOOL DetermineKeyPlacing(DWORD dwWhich)
  880. {
  881. DWORD dwValue;
  882. if (m_fProfiles && (dwWhich==CONTENT))
  883. {
  884. if (m_roHKLMCache.GetValue(PROFILES_ENABLED, &dwValue)==ERROR_SUCCESS)
  885. {
  886. return dwValue;
  887. }
  888. #ifndef UNIX
  889. if (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  890. #else
  891. if (GlobalPlatformType == PLATFORM_TYPE_UNIX)
  892. #endif /* !UNIX */
  893. {
  894. return m_fProfiles;
  895. }
  896. // On Win9x we have to go through the following contortions to decide whether or not the
  897. // user is using a per-user cache or a shared cache.
  898. TCHAR szPath[MAX_PATH];
  899. DWORD cbPath = sizeof(szPath);
  900. if (m_roShellFolder.GetValue(g_szOldSubKey[m_dwWorking],(LPBYTE)szPath, &cbPath)==ERROR_SUCCESS)
  901. {
  902. cbPath = sizeof(szPath);
  903. return (m_roUserShellFolder.GetValue(g_szOldSubKey[m_dwWorking],(LPBYTE)szPath, &cbPath)==ERROR_SUCCESS);
  904. }
  905. }
  906. return m_fProfiles;
  907. }
  908. public:
  909. DWORD InitialiseKeys(BOOL& fProfiles)
  910. {
  911. if (m_fInitialised)
  912. {
  913. return ERROR_SUCCESS;
  914. }
  915. return InitCommonKeys(fProfiles, OLD_CACHE_KEY);
  916. }
  917. DWORD GetPath(PTSTR pszCachePath)
  918. {
  919. DWORD cbKeyLen = MAX_PATH;
  920. LOG_UPGRADE_DATA("Getting IE4 cache location...\n");
  921. DWORD dwError = m_fProfiles ? m_roShellFolder.GetValue(g_szOldSubKey[m_dwWorking],(LPBYTE)pszCachePath, &cbKeyLen)
  922. : m_roWorking.GetValue(CACHE_PATH_VALUE, (LPBYTE)pszCachePath, &cbKeyLen);
  923. #ifndef UNIX
  924. if (m_fProfiles && (GlobalPlatformType == PLATFORM_TYPE_WINNT) && (dwError==ERROR_SUCCESS))
  925. #else
  926. if (m_fProfiles && (GlobalPlatformType == PLATFORM_TYPE_UNIX) && (dwError==ERROR_SUCCESS))
  927. #endif /* UNIX */
  928. {
  929. LOG_UPGRADE_DATA("Correcting IE4 cache location...\n");
  930. LOG_UPGRADE_DATA(pszCachePath);
  931. LOG_UPGRADE_DATA("\n");
  932. TCHAR szPath[MAX_PATH];
  933. DWORD cbPath = ARRAY_ELEMENTS(szPath);
  934. if (m_roUserShellFolder.GetValue(g_szOldSubKey[m_dwWorking],(LPBYTE)szPath, &cbPath)!=ERROR_SUCCESS)
  935. {
  936. CompressPath(pszCachePath, szPath);
  937. dwError = m_roUserShellFolder.SetValue(g_szOldSubKey[m_dwWorking], szPath, REG_EXPAND_SZ);
  938. }
  939. }
  940. return dwError;
  941. }
  942. BOOL WasIE4Present(BOOL& fProfilesCapable)
  943. {
  944. DWORD cb = MAX_PATH;
  945. CHAR szSigKey[MAX_PATH];
  946. REGISTRY_OBJ roSig((fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE), OLD_CACHE_KEY);
  947. return (roSig.GetValue(CACHE_SIGNATURE_VALUE, (LPBYTE) szSigKey, &cb)==ERROR_SUCCESS);
  948. }
  949. DWORD SetLimit(PTSTR pszCachePath, DWORD& cbLimit)
  950. {
  951. INET_ASSERT(m_roWorking.GetStatus()==ERROR_SUCCESS);
  952. // If no limit found in registry create via
  953. // defaults and write back to registry.
  954. // Cache limit - for the content cache we calculate the cache limit
  955. // as being max(DEF_CACHE_LIMIT, 1/32 of the disk size) All others caches
  956. // are set to DEF_CACHE_LIMIT.
  957. if (cbLimit==0)
  958. {
  959. cbLimit = (m_dwWorking==CONTENT)
  960. ? GetDefaultCacheQuota(pszCachePath, NEW_CONTENT_QUOTA_DEFAULT_DISK_FRACTION)
  961. : DEF_CACHE_LIMIT;
  962. }
  963. // Dumb hack for back compat. *sigh*
  964. if (m_dwWorking==CONTENT)
  965. {
  966. REGISTRY_OBJ roLimit(&m_roHKLMCache, g_szSubKey[CONTENT]);
  967. if (roLimit.GetStatus()==ERROR_SUCCESS)
  968. {
  969. roLimit.SetValue(CACHE_LIMIT_VALUE, &cbLimit);
  970. }
  971. }
  972. return m_roWorking.SetValue(CACHE_LIMIT_VALUE, &cbLimit);
  973. }
  974. };
  975. #endif
  976. #define IsFieldSet(fc, bitFlag) (((fc) & (bitFlag)) != 0)
  977. #define FAILSAFE_TIMEOUT (60000)
  978. #define UNMAP_TIME (120000)
  979. // ----------------------------------------------------------------------------
  980. // The following functions deal with keeping the cache containers all up and ready
  981. // -- ConfigureCache() --------------------------------------------------------
  982. // Get the cache info from registry and try to init.
  983. // In general, GetCacheConfigInfo should only rarely fail -- mostly whenever HKCU
  984. // is expected but not available. In that case, we use the system root cache.
  985. // If _that_ fails, we panic.
  986. DWORD CConMgr::ConfigureCache()
  987. {
  988. for (DWORD iter = 0; ; iter++)
  989. {
  990. DWORD dwError;
  991. switch (iter)
  992. {
  993. case 0:
  994. dwError = GetCacheConfigInfo();
  995. break;
  996. case 1:
  997. dwError = GetSysRootCacheConfigInfo();
  998. break;
  999. default:
  1000. INET_ASSERT(FALSE);
  1001. return dwError;
  1002. }
  1003. if (dwError==ERROR_SUCCESS && (dwError=InitFixedContainers())==ERROR_SUCCESS)
  1004. break;
  1005. // If InitFixedContainers has failed, it is possible that the container list
  1006. // (ConList) is not empty. Make sure it has no entries.
  1007. LOCK_CACHE();
  1008. if (ConList.Size() != 0)
  1009. ConList.Free();
  1010. UNLOCK_CACHE();
  1011. }
  1012. return ERROR_SUCCESS;
  1013. }
  1014. /*-----------------------------------------------------------------------------
  1015. DWORD CConMgr::GetCacheConfigInfo
  1016. ----------------------------------------------------------------------------*/
  1017. DWORD CConMgr::GetCacheConfigInfo()
  1018. {
  1019. DWORD dwError, i;
  1020. // Prepare and initialise a registry set for every version of IE available.
  1021. // IE5 must be initialised first because it determines whether profiles are
  1022. // enabled on this machine and set ConMgr's _fProfilesCapable for future
  1023. // reference. Then IE4 and IE3 can be called in whatever order.
  1024. IE5_REGISTRYSET ie5rs;
  1025. if ((dwError=ie5rs.InitialiseKeys(_fProfilesCapable))!=ERROR_SUCCESS)
  1026. {
  1027. goto exit;
  1028. }
  1029. #ifdef WININET6
  1030. GlobalCacheHKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
  1031. #endif
  1032. // In WinHttp we don't care if the user had been using IE4 or whatever,
  1033. // thus the code commented out above
  1034. #if 0
  1035. // Look for a signature to indicate that this cache has been placed before.
  1036. if (ie5rs.IsFirstTimeForUser())
  1037. {
  1038. LOG_UPGRADE_DATA("Install 1st time for user\n");
  1039. DiscoverRegistrySettings(&ie5rs);
  1040. } else {
  1041. // If the user is roaming across machines that include IE4,
  1042. // then safeguard against IE4 writing REG_SZ values that
  1043. // be REG_EXPAND_SZ.
  1044. CheckCacheLocationConsistency();
  1045. }
  1046. #endif
  1047. // If the user is roaming across machines that include IE4,
  1048. // then safeguard against IE4 writing REG_SZ values that
  1049. // be REG_EXPAND_SZ.
  1050. // CheckCacheLocationConsistency();
  1051. // -----------------------------------------------------------------------------------
  1052. // Get the container paths, prefixes (if any) and default limit values.
  1053. for (i = CONTENT; i < NCONTAINERS; i++)
  1054. {
  1055. CHAR szCachePath[MAX_PATH];
  1056. CHAR szCachePrefix[MAX_PATH];
  1057. DWORD cbCacheLimit;
  1058. BOOL fPerUser;
  1059. // This should only rarely fail.
  1060. if ((dwError=ie5rs.SetWorkingContainer(i))!=ERROR_SUCCESS)
  1061. {
  1062. goto exit;
  1063. }
  1064. fPerUser = ie5rs.GetPerUserStatus();
  1065. dwError = ie5rs.GetPath(szCachePath);
  1066. LOG_UPGRADE_DATA("GetCacheConfigInfo/ie5rs.GetPath for user: ");
  1067. LOG_UPGRADE_DATA(szCachePath);
  1068. LOG_UPGRADE_DATA("\n");
  1069. if (dwError==ERROR_SUCCESS)
  1070. {
  1071. ie5rs.GetPrefix(szCachePrefix);
  1072. ie5rs.GetLimit(szCachePath, cbCacheLimit);
  1073. }
  1074. else
  1075. {
  1076. break;
  1077. }
  1078. // Got info, now create the container --------------------------------------
  1079. _coContainer[i] = new URL_CONTAINER(g_szSubKey[i],
  1080. szCachePath,
  1081. szCachePrefix,
  1082. (LONGLONG)cbCacheLimit*1024,
  1083. 0);
  1084. if (_coContainer[i])
  1085. {
  1086. dwError = _coContainer[i]->GetStatus();
  1087. if (dwError!=ERROR_SUCCESS)
  1088. {
  1089. delete _coContainer[i];
  1090. break;
  1091. }
  1092. ConList.Add(_coContainer[i]);
  1093. _coContainer[i]->SetPerUserItem(fPerUser);
  1094. }
  1095. else
  1096. {
  1097. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1098. break;
  1099. }
  1100. // Maintain values for backwards compatibility
  1101. /* We don't care in WinHTTP
  1102. if (i==CONTENT)
  1103. {
  1104. // If repairing IE3's settings fails, well, who cares? IE5 is still going.
  1105. IE3_REGISTRYSET ie3rs;
  1106. ie3rs.FixLegacySettings(szCachePath, cbCacheLimit);
  1107. }
  1108. */
  1109. }
  1110. exit:
  1111. return dwError;
  1112. }
  1113. /*-----------------------------------------------------------------------------
  1114. DWORD CConMgr::GetSysRootCacheConfigInfo
  1115. ----------------------------------------------------------------------------*/
  1116. DWORD CConMgr::GetSysRootCacheConfigInfo()
  1117. {
  1118. CHAR szParentPath[MAX_PATH];
  1119. DWORD cb = ARRAY_ELEMENTS(szParentPath);
  1120. #ifndef UNIX
  1121. {
  1122. // In case of failure to create containers in the regular location,
  1123. // we should put the cache in a user-specifiable location HKLM\* REG_EXPAND_SZ
  1124. // Otherwise in the temp directory
  1125. // Otherwise in the Windows directory
  1126. REGISTRY_OBJ roCache(HKEY_LOCAL_MACHINE, CACHE5_KEY);
  1127. BOOL fResult = FALSE;
  1128. if (roCache.GetStatus()==ERROR_SUCCESS)
  1129. {
  1130. TCHAR szTemp[MAX_PATH];
  1131. if (roCache.GetValue(TEXT("SystemCache"), (LPBYTE)szTemp, &cb)==ERROR_SUCCESS)
  1132. {
  1133. cb = ExpandEnvironmentStrings(szTemp,szParentPath,ARRAY_ELEMENTS(szParentPath)) - 1;
  1134. if (cb && (cb < ARRAY_ELEMENTS(szParentPath)))
  1135. {
  1136. fResult = TRUE;
  1137. }
  1138. }
  1139. }
  1140. if (!fResult)
  1141. {
  1142. cb = ExpandEnvironmentStrings(TEXT("%TEMP%"),szParentPath,ARRAY_ELEMENTS(szParentPath)) - 1;
  1143. if (!cb || (cb > ARRAY_ELEMENTS(szParentPath)))
  1144. {
  1145. cb = GetWindowsDirectory(szParentPath, ARRAY_ELEMENTS(szParentPath));
  1146. }
  1147. }
  1148. }
  1149. #else
  1150. /* On Unix, GetWindowsDirectory will point to <install dir>/common
  1151. * and the cache should not be created here in any case
  1152. */
  1153. lstrcpy(szParentPath,UNIX_SHARED_CACHE_PATH);
  1154. cb = lstrlen(szParentPath);
  1155. #endif /* UNIX */
  1156. if (!cb || (cb>sizeof(szParentPath)))
  1157. {
  1158. return ERROR_PATH_NOT_FOUND;
  1159. }
  1160. AppendSlashIfNecessary(szParentPath, &cb);
  1161. for (DWORD idx = CONTENT; idx < NCONTAINERS; idx++)
  1162. {
  1163. CHAR szCachePath[MAX_PATH];
  1164. CHAR szCachePrefix[MAX_PATH];
  1165. LONGLONG cbCacheLimit;
  1166. // Get cache paths out of dll resource and form absolute
  1167. // paths to top level cache directories.
  1168. memcpy(szCachePath, szParentPath, cb);
  1169. #if 0
  1170. if (!LoadString(GlobalDllHandle, g_dwCachePathResourceID[idx], szCachePath + cb, MAX_PATH - cb))
  1171. {
  1172. return GetLastError();
  1173. }
  1174. #endif
  1175. memcpy(szCachePath+cb, g_dwCachePathResourceID[idx],
  1176. strlen(g_dwCachePathResourceID[idx]) + 1);
  1177. DWORD ccPath = lstrlen(szCachePath);
  1178. AppendSlashIfNecessary(szCachePath, &ccPath);
  1179. memcpy(szCachePath+ccPath, g_szVersionName[idx], lstrlen(g_szVersionName[idx])+1);
  1180. // Cache prefix.
  1181. memcpy(szCachePrefix, g_szCachePrefix[idx], strlen(g_szCachePrefix[idx]) + 1);
  1182. // Cache limit - for the content cache we calculate the cache limit
  1183. // as being max(DEF_CACHE_LIMIT, 1/32 of the disk size) All others caches
  1184. // are set to DEF_CACHE_LIMIT.
  1185. if (idx == CONTENT)
  1186. {
  1187. REGISTRY_OBJ roCache(HKEY_LOCAL_MACHINE, CACHE5_KEY);
  1188. BOOL fResult = (roCache.GetStatus()==ERROR_SUCCESS);
  1189. if (fResult)
  1190. {
  1191. REGISTRY_OBJ roLimit(&roCache, CONTENT_PATH_KEY);
  1192. fResult = FALSE;
  1193. if (roLimit.GetStatus()==ERROR_SUCCESS)
  1194. {
  1195. DWORD cKBLimit;
  1196. if (roLimit.GetValue(CACHE_LIMIT_VALUE, &cKBLimit)==ERROR_SUCCESS)
  1197. {
  1198. cbCacheLimit = cKBLimit * (LONGLONG)1024;
  1199. fResult = TRUE;
  1200. }
  1201. }
  1202. }
  1203. if (!fResult)
  1204. {
  1205. cbCacheLimit =
  1206. (DWORDLONG)GetDefaultCacheQuota(szCachePath, NEW_CONTENT_QUOTA_DEFAULT_DISK_FRACTION)
  1207. * (DWORDLONG)1024;
  1208. }
  1209. }
  1210. else
  1211. {
  1212. // Non-CONTENT cache; use default.
  1213. cbCacheLimit = DEF_CACHE_LIMIT * (LONGLONG)1024;
  1214. }
  1215. _coContainer[idx] = new URL_CONTAINER(g_szSubKey[idx], szCachePath, szCachePrefix, cbCacheLimit, 0);
  1216. if (_coContainer[idx])
  1217. {
  1218. DWORD dwError = _coContainer[idx]->GetStatus();
  1219. if (dwError!=ERROR_SUCCESS)
  1220. {
  1221. delete _coContainer[idx];
  1222. return dwError;
  1223. }
  1224. ConList.Add(_coContainer[idx]);
  1225. _coContainer[idx]->SetPerUserItem(FALSE);
  1226. }
  1227. else
  1228. {
  1229. return ERROR_NOT_ENOUGH_MEMORY;
  1230. }
  1231. }
  1232. _fUsingBackupContainers = TRUE;
  1233. return ERROR_SUCCESS;
  1234. }
  1235. /*-----------------------------------------------------------------------------
  1236. BOOL CConMgr::GetUrlCacheConfigInfo
  1237. ----------------------------------------------------------------------------*/
  1238. /*
  1239. BOOL CConMgr::GetUrlCacheConfigInfo(LPCACHE_CONFIG_INFO lpCacheConfigInfo,
  1240. LPDWORD lpdwCacheConfigInfoBufferSize, DWORD dwFieldControl)
  1241. {
  1242. LOCK_CACHE();
  1243. BOOL fIE5Struct = (lpCacheConfigInfo->dwStructSize == sizeof(INTERNET_CACHE_CONFIG_INFO));
  1244. if(IsFieldSet( dwFieldControl, CACHE_CONFIG_SYNC_MODE_FC))
  1245. {
  1246. lpCacheConfigInfo->dwSyncMode = GlobalUrlCacheSyncMode;
  1247. }
  1248. if (IsFieldSet(dwFieldControl, CACHE_CONFIG_QUOTA_FC))
  1249. {
  1250. lpCacheConfigInfo->dwQuota = (DWORD) (_coContainer[lpCacheConfigInfo->dwContainer]->GetCacheLimit()/1024L);
  1251. }
  1252. if (fIE5Struct && IsFieldSet(dwFieldControl, CACHE_CONFIG_CONTENT_USAGE_FC))
  1253. {
  1254. lpCacheConfigInfo->dwNormalUsage = (DWORD) (_coContainer[lpCacheConfigInfo->dwContainer]->GetCacheSize()/1024L);
  1255. }
  1256. if (fIE5Struct && IsFieldSet(dwFieldControl, CACHE_CONFIG_STICKY_CONTENT_USAGE_FC) && (lpCacheConfigInfo->dwContainer==CONTENT))
  1257. {
  1258. lpCacheConfigInfo->dwExemptUsage = (DWORD) (_coContainer[CONTENT]->GetExemptUsage()/1024L);
  1259. }
  1260. lpCacheConfigInfo->fPerUser = IsFieldSet( dwFieldControl, CACHE_CONFIG_USER_MODE_FC)
  1261. ? _coContainer[lpCacheConfigInfo->dwContainer]->IsPerUserItem()
  1262. : _coContent->IsPerUserItem();
  1263. if (IsFieldSet(dwFieldControl, CACHE_CONFIG_CONTENT_PATHS_FC))
  1264. {
  1265. lpCacheConfigInfo->dwContainer = CONTENT;
  1266. }
  1267. else if (IsFieldSet(dwFieldControl, CACHE_CONFIG_HISTORY_PATHS_FC))
  1268. {
  1269. lpCacheConfigInfo->dwContainer = HISTORY;
  1270. }
  1271. else if (IsFieldSet(dwFieldControl, CACHE_CONFIG_COOKIES_PATHS_FC))
  1272. {
  1273. lpCacheConfigInfo->dwContainer = COOKIE;
  1274. }
  1275. // These are the actual field codes that should be sent for cache paths.
  1276. // Note that the path returned *does not* contain subdirs (cache1..N).
  1277. if (lpCacheConfigInfo->dwContainer <= HISTORY)
  1278. {
  1279. memcpy(lpCacheConfigInfo->CachePath,
  1280. _coContainer[lpCacheConfigInfo->dwContainer]->GetCachePath(),
  1281. _coContainer[lpCacheConfigInfo->dwContainer]->GetCachePathLen() + 1);
  1282. lpCacheConfigInfo->dwQuota = (DWORD)
  1283. (_coContainer[lpCacheConfigInfo->dwContainer]->GetCacheLimit() / 1024);
  1284. lpCacheConfigInfo->dwNumCachePaths = (DWORD) 1;
  1285. }
  1286. UNLOCK_CACHE();
  1287. return TRUE;
  1288. }
  1289. */
  1290. /*-----------------------------------------------------------------------------
  1291. BOOL CConMgr::SetUrlCacheConfigInfo
  1292. ----------------------------------------------------------------------------*/
  1293. /*
  1294. BOOL CConMgr::SetUrlCacheConfigInfo(LPCACHE_CONFIG_INFO pConfig,
  1295. DWORD dwFieldControl)
  1296. {
  1297. DWORD i, dwError = ERROR_SUCCESS;
  1298. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  1299. LOCK_CACHE();
  1300. // Check FieldControl bits and set the values for set fields
  1301. if( IsFieldSet( dwFieldControl, CACHE_CONFIG_SYNC_MODE_FC ))
  1302. {
  1303. INET_ASSERT(pConfig->dwSyncMode <= WININET_SYNC_MODE_AUTOMATIC);
  1304. InternetWriteRegistryDword(vszSyncMode, pConfig->dwSyncMode);
  1305. GlobalUrlCacheSyncMode = pConfig->dwSyncMode;
  1306. // set a new version and simultaneously
  1307. // increment copy for this process, so we don't
  1308. // read registry for this process
  1309. IncrementHeaderData(CACHE_HEADER_DATA_CURRENT_SETTINGS_VERSION,
  1310. &GlobalSettingsVersion);
  1311. }
  1312. if ( IsFieldSet( dwFieldControl, CACHE_CONFIG_DISK_CACHE_PATHS_FC ))
  1313. {
  1314. dwError = ERROR_INVALID_PARAMETER;
  1315. goto exit;
  1316. }
  1317. if ( IsFieldSet( dwFieldControl, CACHE_CONFIG_QUOTA_FC ) && pConfig->dwContainer==CONTENT)
  1318. {
  1319. DWORD cbSize = pConfig->dwQuota;
  1320. INET_ASSERT(cbSize);
  1321. if (!_fUsingBackupContainers)
  1322. {
  1323. IE5_REGISTRYSET ie5;
  1324. IE3_REGISTRYSET ie3;
  1325. if ((dwError=ie5.InitialiseKeys(_fProfilesCapable))!=ERROR_SUCCESS)
  1326. {
  1327. goto exit;
  1328. }
  1329. ie5.SetWorkingContainer(CONTENT);
  1330. TCHAR szTemp[MAX_PATH];
  1331. ie5.GetPath(szTemp);
  1332. ie5.SetLimit(szTemp, cbSize);
  1333. if (ie3.InitialiseKeys()==ERROR_SUCCESS)
  1334. {
  1335. ie3.FixLegacySettings(szTemp, cbSize);
  1336. }
  1337. }
  1338. else
  1339. {
  1340. REGISTRY_OBJ roCache(HKEY_LOCAL_MACHINE, CACHE5_KEY, CREATE_KEY_IF_NOT_EXISTS);
  1341. BOOL fResult = (roCache.GetStatus()==ERROR_SUCCESS);
  1342. if (fResult)
  1343. {
  1344. REGISTRY_OBJ roLimit(&roCache, CONTENT_PATH_KEY, CREATE_KEY_IF_NOT_EXISTS);
  1345. if (roLimit.GetStatus()==ERROR_SUCCESS)
  1346. {
  1347. roLimit.SetValue(CACHE_LIMIT_VALUE, &cbSize);
  1348. }
  1349. }
  1350. }
  1351. if ((((LONGLONG)cbSize * 1024) < _coContent->GetCacheSize()))
  1352. _coContent->CleanupUrls (DEFAULT_CLEANUP_FACTOR, 0);
  1353. _coContent->SetCacheLimit(cbSize* (LONGLONG)1024);
  1354. }
  1355. exit:
  1356. UNLOCK_CACHE();
  1357. BOOL fRet = (dwError==ERROR_SUCCESS);
  1358. if (!fRet)
  1359. {
  1360. SetLastError(dwError);
  1361. DEBUG_ERROR(INET, dwError);
  1362. }
  1363. return fRet;
  1364. }
  1365. */
  1366. /*-----------------------------------------------------------------------------
  1367. DWORD CConMgr::SetContentPath
  1368. UpdateUrlCacheContentPath leads to this function.
  1369. This initiates the cache move. Should be called just before shutdown.
  1370. ----------------------------------------------------------------------------*/
  1371. /*
  1372. BOOL CConMgr::SetContentPath(PTSTR pszNewPath)
  1373. {
  1374. IE5_REGISTRYSET ie5rs;
  1375. DWORD dwError;
  1376. BOOL fLock;
  1377. if (_coContent->LockContainer(&fLock)
  1378. && (dwError=ie5rs.InitialiseKeys(_fProfilesCapable))==ERROR_SUCCESS)
  1379. {
  1380. dwError = ie5rs.UpdateContentPath(pszNewPath);
  1381. }
  1382. if (fLock)
  1383. {
  1384. _coContent->UnlockContainer();
  1385. }
  1386. if (dwError==ERROR_SUCCESS)
  1387. {
  1388. return TRUE;
  1389. }
  1390. SetLastError(dwError);
  1391. return FALSE;
  1392. }
  1393. */
  1394. /*-----------------------------------------------------------------------------
  1395. DWORD CConMgr::GetExtensibleCacheConfigInfo
  1396. ----------------------------------------------------------------------------*/
  1397. DWORD CConMgr::GetExtensibleCacheConfigInfo(BOOL fAlways)
  1398. {
  1399. CHAR szCachePath[MAX_PATH];
  1400. CHAR szCachePrefix[MAX_PATH];
  1401. CHAR szPrefixMap[MAX_PATH];
  1402. CHAR szVolumeLabel[MAX_PATH];
  1403. CHAR szVolumeTitle[MAX_PATH];
  1404. LONGLONG cbCacheLimit;
  1405. HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
  1406. DWORD cbKeyLen, cbKBLimit, dwError = ERROR_SUCCESS;
  1407. CHAR szVendorKey[MAX_PATH];
  1408. URL_CONTAINER* pNewContainer;
  1409. URL_CONTAINER* co;
  1410. MUTEX_HOLDER mh;
  1411. DWORD idx;
  1412. DWORD idxPrefix;
  1413. DWORD dwNow;
  1414. DWORD dwOptions;
  1415. BOOL fModified;
  1416. BOOL fCDContainer;
  1417. REGISTRY_OBJ* pro = NULL;
  1418. LOCK_CACHE();
  1419. fModified = WasModified(TRUE);
  1420. hKey = _fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
  1421. // WasModified MUST come first, so that we update our cached count!
  1422. if (!fModified && !fAlways)
  1423. {
  1424. // Unmap every container that hasn't be referenced in UNMAP_TIME
  1425. dwNow = GetTickCountWrap();
  1426. if ((dwNow - _dwLastUnmap) > UNMAP_TIME)
  1427. {
  1428. for (idx = ConList.Size()-1; idx >= NCONTAINERS; idx--)
  1429. {
  1430. co = ConList.Get(idx);
  1431. if (co)
  1432. {
  1433. if (co->GetDeletePending() ||
  1434. ((dwNow - co->GetLastReference()) > UNMAP_TIME))
  1435. {
  1436. co->TryToUnmap(1); // RefCount should be 1 == Us
  1437. }
  1438. co->Release(FALSE);
  1439. }
  1440. }
  1441. _dwLastUnmap = dwNow;
  1442. }
  1443. goto exit;
  1444. }
  1445. // Create registry object and entry.
  1446. pro = CreateExtensiRegObj(hKey);
  1447. if (!pro)
  1448. {
  1449. dwError = ERROR_ACCESS_DENIED;
  1450. goto exit;
  1451. }
  1452. {
  1453. REGISTRY_OBJ& roExtensibleCache = *pro;
  1454. for (idx = NCONTAINERS; idx < ConList.Size(); idx++)
  1455. {
  1456. URL_CONTAINER *co = ConList.Get(idx);
  1457. if (co)
  1458. {
  1459. co->Mark(FALSE);
  1460. co->Release(FALSE);
  1461. }
  1462. }
  1463. mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
  1464. idx = NCONTAINERS;
  1465. // Get the container paths, prefixes (if any) and default limit values.
  1466. while (roExtensibleCache.FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
  1467. {
  1468. REGISTRY_OBJ roVendor(&roExtensibleCache, szVendorKey);
  1469. if (roVendor.GetStatus()==ERROR_SUCCESS)
  1470. {
  1471. // Path.
  1472. cbKeyLen = MAX_PATH;
  1473. DWORD dwRepair = TRUE;
  1474. CHAR szScratch[MAX_PATH];
  1475. roVendor.GetValue(CACHE_PATCH_VALUE, &dwRepair);
  1476. if (roVendor.GetValue(CACHE_PATH_VALUE, (LPBYTE) szScratch, &cbKeyLen) != ERROR_SUCCESS)
  1477. continue;
  1478. if (!*szScratch)
  1479. {
  1480. roExtensibleCache.DeleteKey(szVendorKey);
  1481. continue;
  1482. }
  1483. if (dwRepair)
  1484. {
  1485. CompressPath(szScratch, szCachePath);
  1486. cbKeyLen = lstrlen(szCachePath)+1;
  1487. roVendor.SetValue(CACHE_PATH_VALUE, szCachePath, REG_EXPAND_SZ);
  1488. dwRepair = FALSE;
  1489. roVendor.SetValue(CACHE_PATCH_VALUE, &dwRepair);
  1490. }
  1491. ExpandEnvironmentStrings(szScratch, szCachePath, sizeof(szCachePath)-1); // don't count the NULL
  1492. // Prefix.
  1493. cbKeyLen = MAX_PATH;
  1494. if (roVendor.GetValue(CACHE_PREFIX_VALUE, (LPBYTE) szCachePrefix, &cbKeyLen) != ERROR_SUCCESS)
  1495. continue;
  1496. // Limit.
  1497. if (roVendor.GetValue(CACHE_LIMIT_VALUE, &cbKBLimit) != ERROR_SUCCESS)
  1498. continue;
  1499. // Options.
  1500. if (roVendor.GetValue(CACHE_OPTIONS_VALUE, &dwOptions) != ERROR_SUCCESS)
  1501. continue;
  1502. if (dwOptions & INTERNET_CACHE_CONTAINER_MAP_ENABLED)
  1503. {
  1504. fCDContainer = TRUE;
  1505. // PrefixMap
  1506. cbKeyLen = MAX_PATH;
  1507. if ((roVendor.GetValue(CACHE_PREFIX_MAP_VALUE, (LPBYTE) szPrefixMap, &cbKeyLen) != ERROR_SUCCESS)
  1508. || (*szPrefixMap == '\0'))
  1509. continue;
  1510. // Volume label.
  1511. cbKeyLen = MAX_PATH;
  1512. if ((roVendor.GetValue(CACHE_VOLUME_LABLE_VALUE, (LPBYTE) szVolumeLabel, &cbKeyLen) != ERROR_SUCCESS)
  1513. || (*szVolumeLabel == '\0'))
  1514. continue;
  1515. // Volume title.
  1516. cbKeyLen = MAX_PATH;
  1517. if ((roVendor.GetValue(CACHE_VOLUME_TITLE_VALUE, (LPBYTE) szVolumeTitle, &cbKeyLen) != ERROR_SUCCESS)
  1518. || (*szVolumeTitle == '\0'))
  1519. continue;
  1520. }
  1521. else
  1522. {
  1523. fCDContainer = FALSE;
  1524. *szPrefixMap = '\0';
  1525. dwOptions &= ~INTERNET_CACHE_CONTAINER_PREFIXMAP;
  1526. }
  1527. cbCacheLimit = ((LONGLONG) cbKBLimit) * 1024;
  1528. idxPrefix = FindExtensibleContainer(szVendorKey);
  1529. if (idxPrefix != NOT_AN_INDEX)
  1530. {
  1531. co = ConList.Get(idxPrefix);
  1532. if (co)
  1533. {
  1534. // what if the container has been added
  1535. // with the same name but a different path, prefix, or options!
  1536. if (stricmp(co->GetCachePath(), szCachePath) ||
  1537. stricmp(co->GetCachePrefix(), szCachePrefix) ||
  1538. co->GetOptions() != dwOptions)
  1539. {
  1540. idxPrefix = NOT_AN_INDEX;
  1541. }
  1542. else if (fCDContainer && stricmp(co->GetPrefixMap(), szPrefixMap))
  1543. {
  1544. idxPrefix = NOT_AN_INDEX;
  1545. }
  1546. else
  1547. {
  1548. co->Mark(TRUE);
  1549. }
  1550. co->Release(FALSE);
  1551. }
  1552. }
  1553. if (idxPrefix == NOT_AN_INDEX)
  1554. {
  1555. // Construct either a normal container, or a CD container.
  1556. if (!fCDContainer)
  1557. {
  1558. pNewContainer = new URL_CONTAINER(szVendorKey, szCachePath, szCachePrefix,
  1559. cbCacheLimit, dwOptions);
  1560. }
  1561. else
  1562. {
  1563. // We'll never run into CD containers in WinHTTP, so we'll force an error
  1564. // if some strange things happen which leads to this codepath
  1565. #if 0
  1566. pNewContainer = new CInstCon(szVendorKey, szVolumeLabel, szVolumeTitle,
  1567. szCachePath, szCachePrefix, szPrefixMap,
  1568. cbCacheLimit, dwOptions);
  1569. #endif
  1570. pNewContainer = NULL;
  1571. }
  1572. if (pNewContainer)
  1573. {
  1574. dwError = pNewContainer->GetStatus();
  1575. if (dwError!=ERROR_SUCCESS)
  1576. {
  1577. delete pNewContainer;
  1578. pNewContainer = NULL;
  1579. }
  1580. else
  1581. {
  1582. pNewContainer->Mark(TRUE);
  1583. ConList.Add(pNewContainer);
  1584. }
  1585. }
  1586. else
  1587. {
  1588. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1589. }
  1590. }
  1591. idx++;
  1592. }
  1593. }
  1594. mh.Release();
  1595. // Mark every container that's no longer in the registry for pending delete
  1596. // Unmap every container that hasn't be referenced in UNMAP_TIME
  1597. dwNow = GetTickCountWrap();
  1598. idx = ConList.Size() - 1;
  1599. while (idx >= NCONTAINERS)
  1600. {
  1601. co = ConList.Get(idx);
  1602. if (co)
  1603. {
  1604. if (!co->GetMarked() && !co->GetDeleted())
  1605. {
  1606. co->SetDeletePending(TRUE);
  1607. }
  1608. if (co->GetDeletePending() ||
  1609. ((dwNow - co->GetLastReference()) > UNMAP_TIME))
  1610. {
  1611. co->TryToUnmap(1); // RefCount should be 1 == Us, unless enumerator
  1612. // is still open
  1613. }
  1614. co->Release(FALSE);
  1615. }
  1616. idx--;
  1617. }
  1618. _dwLastUnmap = dwNow;
  1619. }
  1620. delete pro;
  1621. exit:
  1622. UNLOCK_CACHE();
  1623. return dwError;
  1624. }
  1625. //
  1626. // Mixed environment of IE4 and IE5 sharing a server causes HKCU keys to get resaved as REG_SZ incorrectly
  1627. // so we repair it here
  1628. /*
  1629. VOID CheckCacheLocationConsistency()
  1630. {
  1631. // Read user shell folders (necessary only in HKCU) and write back as REG_EXPAND_SZ if necessary
  1632. REGISTRY_OBJ roUserShellFolders(HKEY_CURRENT_USER, USER_SHELL_FOLDER_KEY);
  1633. if (roUserShellFolders.GetStatus()!=ERROR_SUCCESS)
  1634. {
  1635. return;
  1636. }
  1637. for (int i=0; i<NCONTAINERS; i++)
  1638. {
  1639. TCHAR szPath[MAX_PATH];
  1640. DWORD cc = ARRAY_ELEMENTS(szPath);
  1641. DWORD ValueSize;
  1642. DWORD ValueType;
  1643. // speed things up a bit by checking if we don't need to do this
  1644. if (roUserShellFolders.GetValueSizeAndType(g_szOldSubKey[i], &ValueSize, &ValueType ) != ERROR_SUCCESS
  1645. || ValueType != REG_SZ)
  1646. {
  1647. continue;
  1648. }
  1649. if (roUserShellFolders.GetValue(g_szOldSubKey[i], (LPBYTE)szPath, &cc)!=ERROR_SUCCESS)
  1650. {
  1651. continue;
  1652. }
  1653. // First reconcile path to whatever it should be
  1654. // and rename the containers accordingly.
  1655. TCHAR szRealPath[MAX_PATH];
  1656. // Expand string
  1657. ExpandEnvironmentStrings(szPath, szRealPath, ARRAY_ELEMENTS(szRealPath));
  1658. // Contract string
  1659. if (!NormalisePath(szRealPath, TEXT("%USERPROFILE%"), szPath, sizeof(szPath)))
  1660. {
  1661. NormalisePath(szRealPath, TEXT("%SystemRoot%"), szPath, sizeof(szPath));
  1662. }
  1663. // Then write it back
  1664. roUserShellFolders.DeleteValue(g_szOldSubKey[i]);
  1665. roUserShellFolders.SetValue(g_szOldSubKey[i], szPath, REG_EXPAND_SZ);
  1666. }
  1667. }
  1668. VOID MakeCacheLocationsConsistent()
  1669. {
  1670. // Delete any 5.0 cache signatures from previous installs
  1671. REGISTRY_OBJ roHKCU(HKEY_CURRENT_USER, CACHE5_KEY);
  1672. if (roHKCU.GetStatus()==ERROR_SUCCESS)
  1673. {
  1674. roHKCU.DeleteValue(CACHE_SIGNATURE_VALUE);
  1675. }
  1676. // Read user shell folders (necessary only in HKCU) and write back as REG_EXPAND_SZ
  1677. REGISTRY_OBJ roUserShellFolders(HKEY_CURRENT_USER, USER_SHELL_FOLDER_KEY);
  1678. if (roUserShellFolders.GetStatus()!=ERROR_SUCCESS)
  1679. {
  1680. return;
  1681. }
  1682. roUserShellFolders.DeleteValue(TEXT("Content"));
  1683. for (int i=0; i<NCONTAINERS; i++)
  1684. {
  1685. TCHAR szPath[MAX_PATH];
  1686. DWORD cc = ARRAY_ELEMENTS(szPath);
  1687. if (roUserShellFolders.GetValue(g_szOldSubKey[i], (LPBYTE)szPath, &cc)!=ERROR_SUCCESS)
  1688. {
  1689. continue;
  1690. }
  1691. // First reconcile path to whatever it should be
  1692. // and rename the containers accordingly.
  1693. // i. Get rid of all the trailing content.ie5 (History.IE5)
  1694. // ii. Get rid of any trailing Temporary Internet Files (History)
  1695. // iii. Append Temporary Internet Files (History)
  1696. // We want to skip this for cookies, though.
  1697. // PROBLEM: When we have upgrade on top of 0901+, we started appending content.ie5
  1698. // internally. Thus, files start getting misplaced. How do I work around this?
  1699. // Idea: We append Content.ie5 to the USF path, and test for existence. If it's there,
  1700. // then we'll use that. (We won't bother with anymore detective work. Though we could also
  1701. // verify that the index dat there is newer than the index.dat in the parent directory.)
  1702. TCHAR szRealPath[MAX_PATH];
  1703. // Expand string
  1704. ExpandEnvironmentStrings(szPath, szRealPath, ARRAY_ELEMENTS(szRealPath));
  1705. DisableCacheVu(szRealPath);
  1706. if (i!=1)
  1707. {
  1708. }
  1709. // Contract string
  1710. if (!NormalisePath(szRealPath, TEXT("%USERPROFILE%"), szPath, sizeof(szPath)))
  1711. {
  1712. NormalisePath(szRealPath, TEXT("%SystemRoot%"), szPath, sizeof(szPath));
  1713. }
  1714. // Then write it back
  1715. roUserShellFolders.DeleteValue(g_szOldSubKey[i]);
  1716. roUserShellFolders.SetValue(g_szOldSubKey[i], szPath, REG_EXPAND_SZ);
  1717. // Then append Content.IE5 and move the files to this subdirectory
  1718. // Ideally, we should rename this to an intermediate folder,
  1719. // delete the old location (UNLESS THIS IS THE ROOT OR SYSTEM DIRECTORY),
  1720. // and then move intermediate folder to its new location
  1721. }
  1722. FlushShellFolderCache();
  1723. }
  1724. */
  1725. // External hooks -------------------------------------------------------------------------------------------------------
  1726. // -- RunOnceUrlCache -------------------------
  1727. // This code is called on reboot to clean up moving the cache.
  1728. // If the shutdown was successful, this will move only the few files that were open
  1729. // at that point; we assume that we'll move quickly enough to prevent collisions.
  1730. // The old index.dat is erased.
  1731. DWORD
  1732. WINAPI
  1733. RunOnceUrlCache( HWND hwnd, HINSTANCE hinst, PSTR pszCmd, int nCmdShow)
  1734. {
  1735. // This will clean up the move, especially important if the move was interrupted. (Not too likely.)
  1736. if (pszCmd && *pszCmd)
  1737. {
  1738. CFileMgr::DeleteCache(pszCmd);
  1739. }
  1740. return ERROR_SUCCESS;
  1741. }
  1742. #ifdef __URLCACHE_JUNK__
  1743. DWORD
  1744. WINAPI
  1745. DeleteIE3Cache( HWND hwnd, HINSTANCE hinst, PSTR lpszCmd, int nCmdShow)
  1746. {
  1747. IE3_REGISTRYSET ie3rs;
  1748. if (ie3rs.InitialiseKeys()==ERROR_SUCCESS)
  1749. {
  1750. TCHAR szTemp[MAX_PATH];
  1751. DWORD cbLimit;
  1752. // This fragment will look for a cache location, and test for its share-ability. If it is,
  1753. // we'll use the location; otherwise, we'll use our own shared location.
  1754. if (ie3rs.GetContentDetails(szTemp, cbLimit))
  1755. {
  1756. DWORD cb = lstrlen(szTemp);
  1757. AppendSlashIfNecessary(szTemp, &cb);
  1758. PTSTR psz = szTemp+cb-2;
  1759. while (*psz!='\\' && psz>szTemp)
  1760. {
  1761. psz--;
  1762. }
  1763. if ((psz>szTemp) && !StrCmpNI(psz+1, TEXT("content."), ARRAY_ELEMENTS("content.")-1))
  1764. {
  1765. *(psz+1) = TEXT('\0');
  1766. }
  1767. StrCatBuff(szTemp, TEXT("cache1"), MAX_PATH);
  1768. cb = lstrlen(szTemp) - 1;
  1769. for (int i=0; i<4; i++)
  1770. {
  1771. szTemp[cb] = TEXT('1')+i;
  1772. DeleteCachedFilesInDir(szTemp);
  1773. RemoveDirectory(szTemp);
  1774. }
  1775. }
  1776. }
  1777. return ERROR_SUCCESS;
  1778. }
  1779. // -- Externally available apis
  1780. URLCACHEAPI
  1781. BOOL
  1782. WINAPI
  1783. SetUrlCacheConfigInfoA(
  1784. LPCACHE_CONFIG_INFO pConfig,
  1785. DWORD dwFieldControl
  1786. )
  1787. /*++
  1788. Routine Description:
  1789. This function sets the cache configuration parameters.
  1790. Arguments:
  1791. lpCacheConfigInfo - place holding cache configuration information to be set
  1792. dwFieldControl - items to get
  1793. Return Value:
  1794. Error Code
  1795. --*/
  1796. {
  1797. // Initialize globals
  1798. if (!InitGlobals())
  1799. {
  1800. SetLastError (ERROR_WINHTTP_INTERNAL_ERROR);
  1801. return FALSE;
  1802. }
  1803. return GlobalUrlContainers->SetUrlCacheConfigInfo(pConfig,dwFieldControl);
  1804. }
  1805. URLCACHEAPI
  1806. BOOL
  1807. WINAPI
  1808. GetUrlCacheConfigInfoA(
  1809. LPCACHE_CONFIG_INFO lpCacheConfigInfo,
  1810. IN OUT LPDWORD lpdwCacheConfigInfoBufferSize,
  1811. DWORD dwFieldControl
  1812. )
  1813. /*++
  1814. Routine Description:
  1815. This function retrieves cache configuration values from globals
  1816. Arguments:
  1817. pConfig - pointer to a location where configuration information
  1818. is stored on a successful return
  1819. lpdwCacheConfigInfoBufferSize : pointer to a location where length of
  1820. the above buffer is passed in. On return, this contains the length
  1821. of the above buffer that is fulled in.
  1822. dwFieldControl - items to get
  1823. Return Value:
  1824. Error Code
  1825. --*/
  1826. {
  1827. ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheConfigInfoA", "%#x, %#x, %#x",
  1828. lpCacheConfigInfo, lpdwCacheConfigInfoBufferSize, dwFieldControl ));
  1829. BOOL fError;
  1830. // Initialize globals
  1831. if (!InitGlobals())
  1832. {
  1833. SetLastError (ERROR_WINHTTP_INTERNAL_ERROR);
  1834. DEBUG_ERROR(API, ERROR_WINHTTP_INTERNAL_ERROR);
  1835. fError = FALSE;
  1836. }
  1837. else
  1838. {
  1839. fError = GlobalUrlContainers->GetUrlCacheConfigInfo(lpCacheConfigInfo,
  1840. lpdwCacheConfigInfoBufferSize, dwFieldControl);
  1841. }
  1842. DEBUG_LEAVE_API (fError);
  1843. return fError;
  1844. }
  1845. #endif // __URLCACHE_JUNK__
  1846. // declared in wininet\inc\urlcache.h
  1847. BOOL GetIE5ContentPath( LPSTR szPath)
  1848. {
  1849. BOOL retVal = FALSE;
  1850. IE5_REGISTRYSET ie5rs;
  1851. BOOL fProfilesCapable;
  1852. if( ie5rs.InitialiseKeys(fProfilesCapable) != ERROR_SUCCESS)
  1853. goto doneGetContentPath;
  1854. if( ie5rs.SetWorkingContainer(CONTENT) != ERROR_SUCCESS)
  1855. goto doneGetContentPath;
  1856. if( ie5rs.GetPath( szPath) != ERROR_SUCCESS)
  1857. goto doneGetContentPath;
  1858. retVal = TRUE;
  1859. doneGetContentPath:
  1860. return retVal;
  1861. }
  1862. // SHDOCVW needs to know whether profiles are enabled, to determine whether
  1863. // or not it needs to filter out user names. This function will help keep things simple.
  1864. // And minimise perf impact.
  1865. #ifdef UNIX
  1866. extern "C"
  1867. #endif
  1868. BOOL IsProfilesEnabled()
  1869. {
  1870. IE5_REGISTRYSET ie5rs;
  1871. BOOL fProfilesEnabled;
  1872. if (ie5rs.InitialiseKeys(fProfilesEnabled) != ERROR_SUCCESS)
  1873. {
  1874. fProfilesEnabled = FALSE;
  1875. }
  1876. return fProfilesEnabled;
  1877. }
  1878. #if 0
  1879. BOOL CConMgr::DiscoverIE4Settings(IE5_REGISTRYSET* pie5rs)
  1880. {
  1881. IE4_REGISTRYSET ie4rs;
  1882. CHAR szTemp[MAX_PATH+1], szPrefix[MAX_PATH+1];
  1883. DWORD cbLimit, dwTemp;
  1884. BOOL fPerUser, fCaughtIE4;
  1885. // Try to find IE4 settings. If any paths are found, we will not look for IE3 settings
  1886. fCaughtIE4 = FALSE;
  1887. if (ie4rs.WasIE4Present(_fProfilesCapable))
  1888. {
  1889. if (ie4rs.InitialiseKeys(_fProfilesCapable)!=ERROR_SUCCESS)
  1890. {
  1891. LOG_UPGRADE_DATA("IE4 initialisation failed...\n");
  1892. return FALSE;
  1893. }
  1894. for (dwTemp=0;dwTemp < NCONTAINERS; dwTemp++)
  1895. {
  1896. ie4rs.SetWorkingContainer(dwTemp);
  1897. if (ie4rs.GetPath(szTemp)!=ERROR_SUCCESS)
  1898. {
  1899. continue;
  1900. }
  1901. LOG_UPGRADE_DATA("DIE4Settings: ");
  1902. LOG_UPGRADE_DATA(szTemp);
  1903. LOG_UPGRADE_DATA("\n");
  1904. DisableCacheVu(szTemp);
  1905. pie5rs->SetWorkingContainer(dwTemp);
  1906. // Because SHGetFolderPath uses shell folders to determine where the items are, we have to accomodate this
  1907. // on no-profiles machines.
  1908. if (!_fProfilesCapable)
  1909. {
  1910. pie5rs->SetPath(szTemp);
  1911. }
  1912. else if (dwTemp==CONTENT)
  1913. {
  1914. #ifndef UNIX
  1915. if (ie4rs.GetPerUserStatus() || GlobalPlatformVersion5)
  1916. #else
  1917. if (ie4rs.GetPerUserStatus() || GlobalPlatformType == PLATFORM_TYPE_UNIX)
  1918. #endif /* UNIX */
  1919. {
  1920. // If it's NT5, we want to go to a per-user, non-roaming location
  1921. // which is the NT5 default anyway
  1922. LOG_UPGRADE_DATA("DIE4Settings: If NT5, ignore shared cache. Else this isn't shared anyway.");
  1923. pie5rs->SetPerUserStatus(TRUE);
  1924. }
  1925. else
  1926. {
  1927. // Because IE4 locates a shared cache differently from IE5, we need to
  1928. // save the path and status.
  1929. LOG_UPGRADE_DATA("DIE4Settings: Will try to use shared cache");
  1930. pie5rs->AttemptToUseSharedCache(szTemp, 0);
  1931. }
  1932. }
  1933. fCaughtIE4 = TRUE;
  1934. // We don't need to check return values since we come up with
  1935. // reasonable values on our own.
  1936. ie4rs.GetLimit(szTemp, cbLimit);
  1937. pie5rs->SetLimit(szTemp, cbLimit);
  1938. ie4rs.GetPrefix(szPrefix);
  1939. pie5rs->SetPrefix(szPrefix);
  1940. }
  1941. }
  1942. if (!fCaughtIE4)
  1943. {
  1944. LOG_UPGRADE_DATA("No IE4 settings...\n");
  1945. }
  1946. else
  1947. {
  1948. FlushShellFolderCache();
  1949. }
  1950. return fCaughtIE4;
  1951. }
  1952. VOID CConMgr::DiscoverIE3Settings(IE5_REGISTRYSET* pie5rs)
  1953. {
  1954. IE3_REGISTRYSET ie3rs;
  1955. if (ie3rs.InitialiseKeys()!=ERROR_SUCCESS)
  1956. {
  1957. return;
  1958. }
  1959. TCHAR szTemp[MAX_PATH];
  1960. DWORD cbLimit;
  1961. // This fragment will look for a cache location, and test for its share-ability. If it is,
  1962. // we'll use the location; otherwise, we'll use our own shared location.
  1963. if (ie3rs.GetContentDetails(szTemp, cbLimit))
  1964. {
  1965. DeleteCachedFilesInDir(szTemp);
  1966. // No IE4. Steal IE3's settings? We only care about content cache.
  1967. // Is that a good idea? There's no UI for modifying the cookies/history path;
  1968. // if someone plumbs into the registry, do we want to support that? *sigh*
  1969. // BUG? We're moving the cache one level deeper. We probably want to be a
  1970. // bit more intelligent about this.
  1971. CleanPath(szTemp);
  1972. pie5rs->AttemptToUseSharedCache(szTemp, cbLimit);
  1973. }
  1974. // This fragment deletes the shared history. It should happen ONLY ONCE.
  1975. DWORD cbKeyLen = ARRAY_ELEMENTS(szTemp);
  1976. REGISTRY_OBJ roHist(HKEY_LOCAL_MACHINE, IE3_HISTORY_PATH_KEY);
  1977. if ((roHist.GetStatus()==ERROR_SUCCESS)
  1978. &&
  1979. (roHist.GetValue(NULL,(LPBYTE)szTemp, &cbKeyLen)==ERROR_SUCCESS))
  1980. {
  1981. REGISTRY_OBJ roUrlHist(HKEY_LOCAL_MACHINE, szTemp);
  1982. cbKeyLen = ARRAY_ELEMENTS(szTemp);
  1983. if ((roUrlHist.GetStatus()==ERROR_SUCCESS)
  1984. &&
  1985. (roUrlHist.GetValue(CACHE_DIRECTORY_VALUE, (LPBYTE)szTemp, &cbKeyLen)==ERROR_SUCCESS))
  1986. {
  1987. DeleteCachedFilesInDir(szTemp);
  1988. }
  1989. }
  1990. }
  1991. // Logic for determining the location of the cache -------------------------------------------------------------
  1992. // PROFILES ENABLED --------------------------
  1993. // [on logon]
  1994. // If profiles are enabled, look in HKCU/Software/Microsoft/Windows/Internet Settings/5.0/Cache
  1995. // for a signature.
  1996. // If a signature is present, [carry on]
  1997. // Look in HKLM/Software/Microsoft/Windows/Internet Settings/5.0/Cache
  1998. // for a signature.
  1999. // If a signature is not present, jump to [over IE4 install]
  2000. // For history and cookies, the containers will be located in the profiles directory
  2001. // For content,
  2002. // if it's marked per user,
  2003. // and there isn't a shell folder/user shell folder value, construct and put it in
  2004. // otherwise feed the HKLM shared location into (user) shell folder.
  2005. // Insert signature and [carry on].
  2006. // [over IE4 install]
  2007. // If a signature is not present in HKCU/Software/Microsoft/Windows/Internet Settings/Cache,
  2008. // jump to [over IE3 install]
  2009. // Determine if the content cache is per-user or not.
  2010. // [over IE3 install]
  2011. // For history and cookies, the containers will be located in the profiles directory
  2012. // Examine HKLM/Software/Microsoft/Windows/Internet Settings/Cache/Paths
  2013. // If not present, go to [clean install]
  2014. // If the cache path is located in a user's profiles directory, ignore and [clean install]
  2015. // Otherwise, adopt the values and [carry on]
  2016. // [clean install]
  2017. // Set up history/cookies to be per user.
  2018. // Set up the content cache to be shared.
  2019. // Write in default values.
  2020. // PROFILES NOT ENABLED --------------------------
  2021. // * If profiles are _not_ enabled, we'll look in HKLM/Software/Microsoft/Windows/Internet Settings/5.0/Cache
  2022. // for a signature.
  2023. // If a signature is present, go ahead and gather information for the paths
  2024. // [carry on]
  2025. // Get info from the registry, and create the container
  2026. // -- DiscoverAnyIE5Settings
  2027. // We're going to call this function if we haven't any IE4 settings to upgrade,
  2028. // but _before_ we check for IE3,
  2029. BOOL CConMgr::DiscoverAnyIE5Settings(IE5_REGISTRYSET* pie5rs)
  2030. {
  2031. // Let's consider the following scenario:
  2032. // User A logs on to the machine with IE4 installed; installs IE5, and then shuts down
  2033. // the machine. User B comes along, but IE5 hasn't been installed yet. If User B has
  2034. // admin privileges, install will continue, BUT still not have any IE4/5 settings.
  2035. // Which resulted in skipping DiscoverIE4Settings. However, we don't want to look
  2036. // at IE3's settings.
  2037. // If we're installing over IE4/2/5, but we don't have any settings for this user,
  2038. // we must avoid an IE3 upgrade. Instead, short circuit to use last-minute info-gathering
  2039. // For IE3, use a shared cache
  2040. DWORD dwVer = GetIEVersion();
  2041. // We're going to use a shared cache for IE3 and Win9x users.
  2042. // Upgrading over IE4 and 5 -- for users who have logged in before,
  2043. // their signatures shoudl be in place already. In those cases, we shouldn't
  2044. // be in this function anyway. For other users, we'll use the shared cache.
  2045. // This is the first time for the machine.
  2046. if ((dwVer==3) && pie5rs->IsFirstTimeForMachine())
  2047. {
  2048. return FALSE;
  2049. }
  2050. pie5rs->AttemptToUseSharedCache(NULL, 0);
  2051. return TRUE;
  2052. }
  2053. VOID CConMgr::DiscoverRegistrySettings(IE5_REGISTRYSET* pie5rs)
  2054. {
  2055. LOG_UPGRADE_DATA("Attempting to discover IE4 settings...\n");
  2056. if (DiscoverIE4Settings(pie5rs))
  2057. {
  2058. goto exit;
  2059. }
  2060. #ifndef UNIX
  2061. if (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  2062. #else
  2063. if (GlobalPlatformType == PLATFORM_TYPE_UNIX)
  2064. #endif /* UNIX */
  2065. {
  2066. LOG_UPGRADE_DATA("This is NT. Fuhgedabout IE3 et al settings...\n");
  2067. // This will override NT's default behaviour to use per-user containers.
  2068. pie5rs->SetWorkingContainer(CONTENT);
  2069. if (!pie5rs->GetPerUserStatus())
  2070. {
  2071. pie5rs->AttemptToUseSharedCache(NULL, 0);
  2072. }
  2073. // Suppose this is an install over NT. Each user should get a per-user, non-roaming
  2074. // path by default. The values we'd pick up from SHFolderGetPath will be okay; but, we need to make
  2075. // sure that we treat this as a per-user container.
  2076. // Suppose we upgraded from some previous version of Win9x to NT5. There are eight scenarios:
  2077. // nothing : in which case, we do as above
  2078. // IE3 : same; need to delete old cache
  2079. // IE4 -- single-user machine:same as fresh install; need to delete old cache.
  2080. // -- shared cache : same as fresh install
  2081. // -- per user cache : preserve path
  2082. // -- moved cache : preserve path
  2083. // IE5 -- single-user machine:same as fresh install; need to delete old cache.
  2084. // -- shared cache : preserve shared path
  2085. // -- per user cache : preserve path
  2086. // -- moved cache : preserve path
  2087. // If an admin wants to use a shared cache under NT5, s/he will have to set
  2088. // HKCU/Shell Folders and User Shell Folders to point to the common path
  2089. // AND {HKCU|HKLM}/blah/PerUserItem to 0 (or delete the HKCU value).
  2090. if ((GetIEVersion()==3) && pie5rs->IsFirstTimeForMachine())
  2091. {
  2092. IE3_REGISTRYSET ie3rs;
  2093. TCHAR szTemp[MAX_PATH];
  2094. DWORD cbLimit;
  2095. if ((ie3rs.InitialiseKeys()==ERROR_SUCCESS)
  2096. &&
  2097. (ie3rs.GetContentDetails(szTemp, cbLimit)))
  2098. {
  2099. DeleteCachedFilesInDir(szTemp);
  2100. }
  2101. }
  2102. goto exit;
  2103. }
  2104. LOG_UPGRADE_DATA("Attempting to discover any IE5 settings...\n");
  2105. if (DiscoverAnyIE5Settings(pie5rs))
  2106. {
  2107. goto exit;
  2108. }
  2109. LOG_UPGRADE_DATA("Attempting to discover any IE3 settings...\n");
  2110. DiscoverIE3Settings(pie5rs);
  2111. exit:
  2112. LOG_UPGRADE_DATA("Flushing shell folders cache...\n");
  2113. pie5rs->SetIfFirstTime();
  2114. FlushShellFolderCache();
  2115. }
  2116. #endif
  2117. // -- CleanPath
  2118. // Given a path, strip away any trailing content.ie5's, and if necessary, add a trailing brand mark,
  2119. // i.e. "Temporary Internet Files" or localised version.
  2120. VOID CleanPath(PTSTR pszPath)
  2121. {
  2122. DWORD ccPath = strlen(pszPath);
  2123. PTSTR pszLastSep = pszPath + ccPath;
  2124. // Now we're at the null terminator, but if the last character is also a separator, we want
  2125. // to skip that too.
  2126. if (*(pszLastSep-1)==DIR_SEPARATOR_CHAR)
  2127. {
  2128. pszLastSep--;
  2129. }
  2130. BOOL fSlash;
  2131. // Strip away any "content.ie5"'s from the path
  2132. for (;(fSlash = ScanToLastSeparator(pszPath, &pszLastSep));)
  2133. {
  2134. if (StrCmpNI((pszLastSep+1), TEXT("content.ie"), ARRAY_ELEMENTS(TEXT("content.ie"))-1))
  2135. {
  2136. break;
  2137. }
  2138. *pszLastSep = '\0';
  2139. }
  2140. // Load temp int files
  2141. TCHAR szBrand[MAX_PATH];
  2142. DWORD ccBrand = 0;
  2143. #if 0
  2144. ccBrand = LoadString(GlobalDllHandle, g_dwCachePathResourceID[CONTENT], szBrand, ARRAY_ELEMENTS(szBrand));
  2145. #endif
  2146. memcpy(szBrand, g_dwCachePathResourceID[CONTENT],
  2147. strlen(g_dwCachePathResourceID[CONTENT]) + 1);
  2148. // The following fragment should never happen, but just in case...
  2149. if (!ccBrand)
  2150. {
  2151. ccBrand = sizeof(TEXT("Temporary Internet Files"));
  2152. memcpy(szBrand, TEXT("Temporary Internet Files"), ccBrand);
  2153. ccBrand /= sizeof(TCHAR);
  2154. ccBrand--;
  2155. }
  2156. // If "Temporary Internet Files" doesn't trail the path, add it.
  2157. if (!fSlash)
  2158. {
  2159. *pszLastSep++ = DIR_SEPARATOR_CHAR;
  2160. *pszLastSep = '\0';
  2161. }
  2162. else
  2163. {
  2164. pszLastSep++;
  2165. }
  2166. if (StrCmpNI((pszLastSep), szBrand, ccBrand))
  2167. {
  2168. while (*pszLastSep && *pszLastSep!=DIR_SEPARATOR_CHAR)
  2169. {
  2170. pszLastSep++;
  2171. }
  2172. if (!*pszLastSep && (*(pszLastSep-1)!=DIR_SEPARATOR_CHAR))
  2173. {
  2174. *pszLastSep = DIR_SEPARATOR_CHAR;
  2175. pszLastSep++;
  2176. }
  2177. else if (*pszLastSep)
  2178. {
  2179. pszLastSep++;
  2180. }
  2181. memcpy(pszLastSep, szBrand, ccBrand*sizeof(TCHAR));
  2182. }
  2183. *(pszLastSep+ccBrand)='\0';
  2184. }
  2185. /*
  2186. DWORD GetIEVersion()
  2187. {
  2188. DWORD dwVer = 0;
  2189. REGISTRY_OBJ roVersion(HKEY_LOCAL_MACHINE, OLD_VERSION_KEY);
  2190. TCHAR szKey[MAX_PATH];
  2191. DWORD cb = ARRAY_ELEMENTS(szKey);
  2192. if ((roVersion.GetStatus()!=ERROR_SUCCESS)
  2193. ||
  2194. (roVersion.GetValue(OLD_VERSION_VALUE, (LPBYTE)szKey, &cb)!=ERROR_SUCCESS))
  2195. {
  2196. // This should never happen during a proper setup.
  2197. // In case it does, however, we'll just use construct IE5's default settings.
  2198. return 0;
  2199. }
  2200. PTSTR psz = szKey;
  2201. PTSTR pszFirst = szKey;
  2202. // Get the major version number
  2203. while (*psz!='.')
  2204. {
  2205. psz++;
  2206. }
  2207. *psz = '\0';
  2208. dwVer = (DWORD)StrToInt(pszFirst);
  2209. if (dwVer==4)
  2210. {
  2211. psz++;
  2212. // Skip the second number
  2213. while (*psz!='.')
  2214. {
  2215. psz++;
  2216. }
  2217. pszFirst = psz;
  2218. psz++;
  2219. while (*psz!='.')
  2220. {
  2221. psz++;
  2222. }
  2223. *psz = '\0';
  2224. dwVer = ((DWORD)StrToInt(pszFirst))==0 ? 3 : 4;
  2225. }
  2226. return dwVer;
  2227. }
  2228. */