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.

1980 lines
59 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name: conmgr.cxx
  4. Abstract:
  5. Manages list of containers (CConList)
  6. Author:
  7. Adriaan Canter (adriaanc) 04-02-97
  8. --*/
  9. #include <cache.hxx>
  10. #define FAILSAFE_TIMEOUT (60000)
  11. /*--------------------- Private Functions -----------------------------------*/
  12. /*-----------------------------------------------------------------------------
  13. DWORD CConMgr::Init
  14. ----------------------------------------------------------------------------*/
  15. DWORD CConMgr::Init()
  16. {
  17. DWORD dwError = ConfigureCache();
  18. if (dwError==ERROR_SUCCESS)
  19. {
  20. // Get the extensible cache config info.
  21. // These containers are delay-initialized.
  22. dwError = GetExtensibleCacheConfigInfo(TRUE);
  23. }
  24. else
  25. {
  26. INET_ASSERT(FALSE);
  27. }
  28. return dwError;
  29. }
  30. #ifdef CHECKLOCK_PARANOID
  31. void CConMgr::CheckNoLocks(DWORD dwThreadId)
  32. {
  33. URL_CONTAINER *co;
  34. DWORD idx;
  35. LOCK_CACHE();
  36. for (idx = 0; idx < ConList.Size(); idx++)
  37. {
  38. URL_CONTAINER *co;
  39. co = ConList.Get(idx);
  40. if (co)
  41. {
  42. co->CheckNoLocks(dwThreadId);
  43. co->Release(FALSE);
  44. }
  45. }
  46. UNLOCK_CACHE();
  47. }
  48. #endif
  49. /*-----------------------------------------------------------------------------
  50. BOOL CConMgr::WasModified
  51. ----------------------------------------------------------------------------*/
  52. BOOL CConMgr::WasModified(BOOL fUpdateMemory)
  53. {
  54. DWORD dwOldCount = _dwModifiedCount;
  55. return dwOldCount != ReadModifiedCount(fUpdateMemory);
  56. }
  57. /*-----------------------------------------------------------------------------
  58. DWORD CConMgr::ReadModifiedCount
  59. ----------------------------------------------------------------------------*/
  60. DWORD CConMgr::ReadModifiedCount(BOOL fUpdateMemory)
  61. {
  62. DWORD dwChangeCount;
  63. DWORD *pdwChangeCount = fUpdateMemory ? &_dwModifiedCount : &dwChangeCount;
  64. _coContent->GetHeaderData(CACHE_HEADER_DATA_CONLIST_CHANGE_COUNT,
  65. pdwChangeCount);
  66. return *pdwChangeCount;
  67. }
  68. /*-----------------------------------------------------------------------------
  69. DWORD CConMgr::IncrementModifiedCount
  70. ----------------------------------------------------------------------------*/
  71. void CConMgr::IncrementModifiedCount()
  72. {
  73. DWORD dwLocModified;
  74. _coContent->IncrementHeaderData(CACHE_HEADER_DATA_CONLIST_CHANGE_COUNT,
  75. &dwLocModified);
  76. }
  77. /*-----------------------------------------------------------------------------
  78. DWORD CConMgr::InitFixedContainers
  79. ----------------------------------------------------------------------------*/
  80. DWORD CConMgr::InitFixedContainers()
  81. {
  82. DWORD idx;
  83. DWORD dwError = ERROR_SUCCESS;
  84. BOOL fInitSucceeded = TRUE;
  85. // Create and init
  86. _hMutexExtensible = OpenMutex(SYNCHRONIZE, FALSE, TEXT("_!MSFTHISTORY!_"));
  87. if (_hMutexExtensible == NULL && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME))
  88. {
  89. SECURITY_ATTRIBUTES* psa = SHGetAllAccessSA();
  90. if (psa)
  91. {
  92. _hMutexExtensible = CreateMutex(psa, FALSE, TEXT("_!MSFTHISTORY!_"));
  93. }
  94. }
  95. if (_hMutexExtensible == NULL)
  96. {
  97. dwError = GetLastError();
  98. fInitSucceeded = FALSE;
  99. goto exit;
  100. }
  101. _dwLastUnmap = GetTickCountWrap();
  102. LOCK_CACHE();
  103. // Containers are configured. Attempt to initialize.
  104. for (idx = CONTENT; idx < ConList.Size(); idx++)
  105. {
  106. URL_CONTAINER *co;
  107. co = ConList.Get(idx);
  108. if (co)
  109. {
  110. dwError = co->Init();
  111. // NOTE - URL_CONTAINER::Init() returns ERROR_ALREADY_EXISTS
  112. // only if the the existing memory mapped file has been opened
  113. // successfully. If the memory mapped file was created, upgraded
  114. // or corrupted (in both cases the mem mapped file will be reinited)
  115. // the return value will be ERROR_SUCCESS.
  116. if(dwError != ERROR_SUCCESS && dwError != ERROR_ALREADY_EXISTS)
  117. {
  118. fInitSucceeded = FALSE;
  119. goto unlock_exit;
  120. }
  121. // Has the container been created, upgrade or corrupted?
  122. if (dwError == ERROR_SUCCESS)
  123. {
  124. if(idx==CONTENT)
  125. {
  126. // Preload the content container.
  127. LoadContent();
  128. }
  129. else if (idx==COOKIE)
  130. {
  131. CCookieLoader cl;
  132. cl.LoadCookies(co);
  133. }
  134. }
  135. co->Release(FALSE);
  136. }
  137. }
  138. // Enable cachevu for CONTENT and HISTORY.
  139. EnableCacheVu(_coContent->GetCachePath(), CONTENT);
  140. EnableCacheVu(_coHistory->GetCachePath(), HISTORY);
  141. unlock_exit:
  142. UNLOCK_CACHE();
  143. exit:
  144. dwError = (fInitSucceeded ? ERROR_SUCCESS : ERROR_INTERNAL_ERROR);
  145. if (!fInitSucceeded && _hMutexExtensible)
  146. {
  147. CloseHandle(_hMutexExtensible);
  148. _hMutexExtensible = NULL;
  149. }
  150. INET_ASSERT(dwError == ERROR_SUCCESS);
  151. return dwError;
  152. }
  153. /*-----------------------------------------------------------------------------
  154. DWORD CConMgr::LoadContent()
  155. ----------------------------------------------------------------------------*/
  156. DWORD CConMgr::LoadContent()
  157. {
  158. DWORD cbFile, dwError = ERROR_FILE_NOT_FOUND;
  159. CHAR szPreloadKey[MAX_PATH],
  160. szUrl[MAX_PATH],
  161. szFile[MAX_PATH];
  162. // Preload registry key string.
  163. memcpy(szPreloadKey, OLD_CACHE_KEY, sizeof(OLD_CACHE_KEY) - 1);
  164. szPreloadKey[sizeof(OLD_CACHE_KEY)-1] = '\\';
  165. memcpy(szPreloadKey + sizeof(OLD_CACHE_KEY), "Preload", sizeof("PreLoad"));
  166. // Construct preload registry object.
  167. REGISTRY_OBJ roPreload(HKEY_CURRENT_USER, szPreloadKey);
  168. REGISTRY_OBJ roIE5Preload;
  169. if (roPreload.GetStatus() != ERROR_SUCCESS)
  170. goto exit;
  171. // Get the storage directory (cdf preload) to compare against to determine if we
  172. // need to set EDITED_CACHE_ENTRY or not. We assume any preload entry not in the
  173. // store dir IS and ECE.
  174. DWORD cb;
  175. CHAR szStorePath[MAX_PATH];
  176. // Store dir is hardwired to "%windir%\Web\"
  177. if ((cb = GetWindowsDirectory(szStorePath, MAX_PATH)))
  178. {
  179. AppendSlashIfNecessary(szStorePath, &cb);
  180. memcpy(szStorePath + cb, WEBDIR_STRING, sizeof(WEBDIR_STRING));
  181. cb += sizeof(WEBDIR_STRING) - 1; //cb now equals size of szStorePath.
  182. }
  183. // Enum the registry url/file values and commit them
  184. // to the cache.
  185. while (roPreload.FindNextValue(szUrl, MAX_PATH,
  186. (LPBYTE) szFile, &(cbFile = MAX_PATH)) == ERROR_SUCCESS)
  187. {
  188. // Strip off any file:// off the file path/name.
  189. CHAR* ptr = szFile;
  190. if (!strnicmp(ptr, "file://", sizeof("file://") - 1))
  191. ptr += sizeof("file://") - 1;
  192. AddUrlArg Args;
  193. memset(&Args, 0, sizeof(Args));
  194. Args.pszUrl = szUrl;
  195. Args.pszFilePath = ptr;
  196. // If this is a Store entry, set the type to 0 else ECE
  197. if (!strnicmp(ptr, szStorePath, cb))
  198. Args.dwEntryType = 0;
  199. else
  200. Args.dwEntryType = EDITED_CACHE_ENTRY;
  201. _coContent->AddUrl(&Args);
  202. }
  203. if (roIE5Preload.WorkWith(&roPreload, "IE5Preload")!=ERROR_SUCCESS)
  204. goto exit;
  205. DWORD cbMaxUrl, cbMaxEntry, cbEntry;
  206. LPSTR pszUrl;
  207. URL_FILEMAP_ENTRY *pEntry;
  208. KEY_QUERY_INFO QueryInfo;
  209. if (ERROR_SUCCESS != roIE5Preload.GetKeyInfo(&QueryInfo))
  210. goto exit;
  211. cbMaxUrl = QueryInfo.MaxValueNameLen + 1;
  212. cbMaxEntry = QueryInfo.MaxValueLen + 1;
  213. pszUrl = new CHAR[cbMaxUrl];
  214. pEntry = (URL_FILEMAP_ENTRY*) new CHAR[cbMaxEntry];
  215. if (!(pszUrl && pEntry))
  216. goto exit;
  217. __try
  218. {
  219. while ((dwError = roIE5Preload.FindNextValue(pszUrl, cbMaxUrl,
  220. (LPBYTE) pEntry, &(cbEntry = cbMaxEntry))) == ERROR_SUCCESS)
  221. {
  222. FILETIME ft;
  223. AddUrlArg Args;
  224. memset(&Args, 0, sizeof(Args));
  225. // Url
  226. Args.pszUrl = pEntry->UrlNameOffset ?
  227. (LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->UrlNameOffset) : NULL;
  228. // File path
  229. Args.pszFilePath = pEntry->InternalFileNameOffset ?
  230. (LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->InternalFileNameOffset) : NULL;
  231. // Header info
  232. Args.pbHeaders = pEntry->HeaderInfoOffset ?
  233. (LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->HeaderInfoOffset) : NULL;
  234. Args.cbHeaders = pEntry->HeaderInfoSize;
  235. // Last modified.
  236. Args.qwLastMod = pEntry->LastModifiedTime;
  237. // Expires time.
  238. DosTime2FileTime(pEntry->dostExpireTime, &ft);
  239. Args.qwExpires = FT2LL(ft);
  240. // Post check time.
  241. DosTime2FileTime(pEntry->dostPostCheckTime, &ft);
  242. Args.qwPostCheck = FT2LL(ft);
  243. // File creation time.
  244. DosTime2FileTime(pEntry->dostFileCreationTime, &ft);
  245. Args.ftCreate = ft;
  246. // File extension.
  247. Args.pszFileExt = pEntry->FileExtensionOffset ?
  248. (LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->FileExtensionOffset) : NULL;
  249. // Entry type.
  250. Args.dwEntryType = pEntry->CacheEntryType;
  251. // File size
  252. Args.dwFileSize = pEntry->dwFileSize;
  253. // Add the url.
  254. _coContent->AddUrl(&Args);
  255. }
  256. } // __try
  257. __except(EXCEPTION_EXECUTE_HANDLER)
  258. {
  259. INET_ASSERT(FALSE);
  260. dwError = GetLastError();
  261. }
  262. ENDEXCEPT
  263. dwError = ERROR_SUCCESS;
  264. if (pszUrl)
  265. delete pszUrl;
  266. if (pEntry)
  267. delete pEntry;
  268. exit:
  269. return dwError;
  270. }
  271. /*-----------------------------------------------------------------------------
  272. HANDLE CConMgr::FindFirstContainer
  273. ----------------------------------------------------------------------------*/
  274. HANDLE CConMgr::FindFirstContainer(DWORD *pdwModified, LPINTERNET_CACHE_CONTAINER_INFOA lpContainerInfo, LPDWORD lpdwContainerInfoBufferSize, DWORD dwOptions)
  275. {
  276. DWORD dwError = ERROR_SUCCESS;
  277. CONTAINER_FIND_FIRST_HANDLE *pFind;
  278. DWORD dwContainers = 0;
  279. DWORD dwNames = 0;
  280. DWORD dwPrefixes = 0;
  281. DWORD dwLabels = 0;
  282. DWORD dwTitles = 0;
  283. DWORD dwTotal;
  284. HANDLE hFind = NULL;
  285. DWORD dwModified;
  286. GetExtensibleCacheConfigInfo(FALSE);
  287. LOCK_CACHE();
  288. dwModified = *pdwModified;
  289. *pdwModified = _dwModifiedCount;
  290. if ((CACHE_FIND_CONTAINER_RETURN_NOCHANGE & dwOptions) == 0 ||
  291. dwModified != *pdwModified)
  292. {
  293. for (DWORD i = NCONTAINERS; i < ConList.Size(); i++)
  294. {
  295. URL_CONTAINER *co = ConList.Get(i);
  296. if (co)
  297. {
  298. if (co->IsVisible())
  299. {
  300. dwContainers++;
  301. dwNames += strlen(co->GetCacheName()) + 1;
  302. dwPrefixes += strlen(co->GetCachePrefix()) + 1;
  303. dwLabels += strlen(co->GetVolumeLabel()) + 1;
  304. dwTitles += strlen(co->GetVolumeTitle()) + 1;
  305. }
  306. co->Release(TRUE);
  307. }
  308. }
  309. dwTotal = sizeof(CONTAINER_FIND_FIRST_HANDLE)+
  310. dwContainers*(4 * sizeof(LPSTR)) +
  311. (dwNames+dwPrefixes+dwLabels+dwTitles) * sizeof(char);
  312. hFind = HandleMgr.Alloc (dwTotal);
  313. if (hFind)
  314. {
  315. LPSTR ps;
  316. pFind = (CONTAINER_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
  317. pFind->dwSignature = SIGNATURE_CONTAINER_FIND;
  318. pFind->dwContainer = 0;
  319. pFind->dwNumContainers = dwContainers;
  320. if (dwContainers)
  321. {
  322. pFind->ppNames = (LPTSTR *) (((LPBYTE) pFind) + sizeof(CONTAINER_FIND_FIRST_HANDLE));
  323. pFind->ppPrefixes = pFind->ppNames + dwContainers;
  324. pFind->ppLabels = pFind->ppPrefixes + dwContainers;
  325. pFind->ppTitles = pFind->ppLabels + dwContainers;
  326. ps = (LPSTR) (((LPBYTE) pFind) +
  327. sizeof(CONTAINER_FIND_FIRST_HANDLE)+
  328. dwContainers*(4 * sizeof(LPSTR)));
  329. dwContainers = 0;
  330. for (DWORD i = NCONTAINERS; i < ConList.Size(); i++)
  331. {
  332. URL_CONTAINER *co = ConList.Get(i);
  333. if (co)
  334. {
  335. if (co->IsVisible())
  336. {
  337. pFind->ppNames[dwContainers] = ps;
  338. strcpy(ps, co->GetCacheName());
  339. ps += strlen(co->GetCacheName()) + 1;
  340. pFind->ppPrefixes[dwContainers] = ps;
  341. strcpy(ps, co->GetCachePrefix());
  342. ps += strlen(co->GetCachePrefix()) + 1;
  343. pFind->ppLabels[dwContainers] = ps;
  344. strcpy(ps, co->GetVolumeLabel());
  345. ps += strlen(co->GetVolumeLabel()) + 1;
  346. pFind->ppTitles[dwContainers] = ps;
  347. strcpy(ps, co->GetVolumeTitle());
  348. ps += strlen(co->GetVolumeTitle()) + 1;
  349. dwContainers++;
  350. }
  351. co->Release(TRUE);
  352. }
  353. }
  354. }
  355. }
  356. else
  357. {
  358. dwError = ERROR_NOT_ENOUGH_MEMORY;
  359. }
  360. }
  361. else
  362. {
  363. dwError = ERROR_INTERNET_NO_NEW_CONTAINERS;
  364. }
  365. UNLOCK_CACHE();
  366. if (hFind)
  367. {
  368. if (FindNextContainer(hFind, lpContainerInfo, lpdwContainerInfoBufferSize))
  369. dwError = ERROR_SUCCESS;
  370. else
  371. dwError = GetLastError();
  372. }
  373. if( dwError != ERROR_SUCCESS )
  374. {
  375. FreeFindHandle(hFind);
  376. SetLastError(dwError);
  377. return NULL;
  378. }
  379. return hFind;
  380. }
  381. /*-----------------------------------------------------------------------------
  382. BOOL CConMgr::FindNextContainer
  383. ----------------------------------------------------------------------------*/
  384. BOOL CConMgr::FindNextContainer(HANDLE hFind, LPINTERNET_CACHE_CONTAINER_INFOA lpContainerInfo, LPDWORD lpdwContainerInfoBufferSize)
  385. {
  386. // BUGBUG - this logic is borrowed from the original cachapia.cxx.
  387. DWORD dwError;
  388. CONTAINER_FIND_FIRST_HANDLE* pFind;
  389. // Map and validate the handle.
  390. LOCK_CACHE();
  391. pFind = (CONTAINER_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
  392. UNLOCK_CACHE();
  393. if (!pFind || pFind->dwSignature != SIGNATURE_CONTAINER_FIND ||
  394. !lpContainerInfo ||
  395. *lpdwContainerInfoBufferSize < sizeof(INTERNET_CACHE_CONTAINER_INFOA))
  396. {
  397. dwError = ERROR_INVALID_PARAMETER;
  398. goto exit;
  399. }
  400. // Continue the enumeration.
  401. if (pFind->dwContainer < pFind->dwNumContainers)
  402. {
  403. DWORD cbName = strlen(pFind->ppNames[pFind->dwContainer])+1;
  404. DWORD cbPrefix = strlen(pFind->ppPrefixes[pFind->dwContainer])+1;
  405. DWORD cbLabel = strlen(pFind->ppLabels[pFind->dwContainer])+1;
  406. DWORD cbTitle = strlen(pFind->ppTitles[pFind->dwContainer])+1;
  407. DWORD cbTotal = cbName+cbPrefix+cbLabel+cbTitle+sizeof(INTERNET_CACHE_CONTAINER_INFOA);
  408. if (cbTotal > *lpdwContainerInfoBufferSize)
  409. {
  410. dwError = ERROR_INSUFFICIENT_BUFFER;
  411. }
  412. else
  413. {
  414. lpContainerInfo->lpszName = (LPSTR) (((LPBYTE) lpContainerInfo) +
  415. sizeof(INTERNET_CACHE_CONTAINER_INFOA));
  416. lpContainerInfo->lpszCachePrefix = lpContainerInfo->lpszName + cbName;
  417. lpContainerInfo->lpszVolumeLabel = lpContainerInfo->lpszCachePrefix + cbPrefix;
  418. lpContainerInfo->lpszVolumeTitle = lpContainerInfo->lpszVolumeLabel + cbLabel;
  419. strcpy(lpContainerInfo->lpszName, pFind->ppNames[pFind->dwContainer]);
  420. strcpy(lpContainerInfo->lpszCachePrefix, pFind->ppPrefixes[pFind->dwContainer]);
  421. strcpy(lpContainerInfo->lpszVolumeLabel, pFind->ppLabels[pFind->dwContainer]);
  422. strcpy(lpContainerInfo->lpszVolumeTitle, pFind->ppTitles[pFind->dwContainer]);
  423. lpContainerInfo->dwCacheVersion = URL_CACHE_VERSION_NUM;
  424. pFind->dwContainer++;
  425. dwError = ERROR_SUCCESS;
  426. }
  427. *lpdwContainerInfoBufferSize = cbTotal;
  428. }
  429. else
  430. {
  431. dwError = ERROR_NO_MORE_ITEMS;
  432. }
  433. exit:
  434. if (dwError != ERROR_SUCCESS)
  435. {
  436. SetLastError(dwError);
  437. return FALSE;
  438. }
  439. return TRUE;
  440. }
  441. /*-----------------------------------------------------------------------------
  442. DWORD CConMgr::GetContainerInfo
  443. ----------------------------------------------------------------------------*/
  444. DWORD CConMgr::GetContainerInfo(LPSTR szUrl,
  445. LPINTERNET_CACHE_CONTAINER_INFOA pCI,
  446. LPDWORD pcbCI)
  447. {
  448. URL_CONTAINER *co;
  449. DWORD dwError;
  450. // Find the associated container.
  451. DWORD idx;
  452. LOCK_CACHE();
  453. idx = FindIndexFromPrefix(szUrl);
  454. co = ConList.Get(idx);
  455. if (co)
  456. {
  457. DWORD cbName = strlen(co->GetCacheName()) + 1;
  458. DWORD cbPrefix = strlen(co->GetCachePrefix()) + 1;
  459. DWORD cbLabel = strlen(co->GetVolumeLabel()) + 1;
  460. DWORD cbTitle = strlen(co->GetVolumeTitle()) + 1;
  461. DWORD cbReq = cbName + cbPrefix + cbLabel + cbTitle;
  462. if (cbReq > *pcbCI)
  463. {
  464. *pcbCI = cbReq;
  465. dwError = ERROR_INSUFFICIENT_BUFFER;
  466. }
  467. else
  468. {
  469. pCI->lpszName = (LPSTR) (((LPBYTE) pCI) +
  470. sizeof(INTERNET_CACHE_CONTAINER_INFOA));
  471. pCI->lpszCachePrefix = pCI->lpszName + cbName;
  472. pCI->lpszVolumeLabel = pCI->lpszName + cbName + cbPrefix;
  473. pCI->lpszVolumeTitle = pCI->lpszName + cbName + cbPrefix + cbLabel;
  474. memcpy(pCI->lpszName, co->GetCacheName(), cbName);
  475. memcpy(pCI->lpszCachePrefix, co->GetCachePrefix(), cbPrefix);
  476. memcpy(pCI->lpszVolumeLabel, co->GetVolumeLabel(), cbLabel);
  477. memcpy(pCI->lpszVolumeTitle, co->GetVolumeTitle(), cbTitle);
  478. pCI->dwCacheVersion = URL_CACHE_VERSION_NUM;
  479. *pcbCI = cbReq;
  480. dwError = ERROR_SUCCESS;
  481. }
  482. co->Release(TRUE);
  483. }
  484. else
  485. {
  486. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  487. }
  488. UNLOCK_CACHE();
  489. return dwError;
  490. }
  491. VOID CompressPath(PTSTR pszPath, PTSTR pszScratch);
  492. /*-----------------------------------------------------------------------------
  493. DWORD CConMgr::CreateContainer
  494. ----------------------------------------------------------------------------*/
  495. DWORD CConMgr::CreateContainer(LPCSTR Name, LPCSTR CachePrefix, LPCSTR CachePath, DWORD KBCacheLimit, DWORD dwOptions)
  496. {
  497. BOOL fInsertOk = TRUE;
  498. DWORD dwError = ERROR_SUCCESS;
  499. CHAR szVendorKey[MAX_PATH];
  500. CHAR szDefaultPath[MAX_PATH];
  501. CHAR szCachePath[MAX_PATH];
  502. LONGLONG CacheStartUpLimit;
  503. HKEY hKey;
  504. DWORD cbKeyLen;
  505. hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
  506. REGISTRY_OBJ* pro = NULL;
  507. MUTEX_HOLDER mh;
  508. if (!Name || !*Name)
  509. {
  510. dwError = ERROR_INVALID_PARAMETER;
  511. goto exit;
  512. }
  513. if (!CachePath || !*CachePath)
  514. {
  515. LPSTR p = _coHistory->GetCachePath();
  516. int len = _coHistory->GetCachePathLen();
  517. int clen = lstrlen(Name);
  518. if (len + clen + sizeof(DIR_SEPARATOR_STRING) > sizeof(szDefaultPath))
  519. {
  520. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  521. goto exit;
  522. }
  523. memcpy(szDefaultPath, p, len);
  524. memcpy(&szDefaultPath[len], Name, clen);
  525. memcpy(&szDefaultPath[len + clen], DIR_SEPARATOR_STRING, sizeof(DIR_SEPARATOR_STRING));
  526. }
  527. else
  528. {
  529. INET_ASSERT((CachePrefix && *CachePrefix));
  530. // For non-history containers, we need to stuff into the appropriate subcontainer
  531. // Assumption: Content cache never falls here.
  532. if (!GenerateStringWithOrdinal(CachePath,
  533. GlobalIdentity,
  534. szDefaultPath,
  535. ARRAY_ELEMENTS(szDefaultPath)))
  536. {
  537. INET_ASSERT(FALSE);
  538. dwError = ERROR_INTERNET_INTERNAL_ERROR;
  539. goto exit;
  540. }
  541. }
  542. CachePath = szDefaultPath;
  543. if (KBCacheLimit == 0)
  544. {
  545. CacheStartUpLimit = _coHistory->GetCacheStartUpLimit();
  546. KBCacheLimit = (DWORD) (CacheStartUpLimit / 1024);
  547. }
  548. if (!CachePrefix || !*CachePrefix || !CachePath || !*CachePath)
  549. {
  550. dwError = ERROR_INVALID_PARAMETER;
  551. goto exit;
  552. }
  553. pro = CreateExtensiRegObj(hKey);
  554. if (!pro)
  555. {
  556. dwError = ERROR_ACCESS_DENIED;
  557. goto exit;
  558. }
  559. {
  560. REGISTRY_OBJ& roExtensibleCache = *pro;
  561. mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
  562. // Get the container paths, prefixes (if any) and default limit values.
  563. while (roExtensibleCache.FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
  564. {
  565. REGISTRY_OBJ roVendor(&roExtensibleCache, szVendorKey);
  566. if (roVendor.GetStatus()==ERROR_SUCCESS)
  567. {
  568. // Path.
  569. TCHAR szScratch[MAX_PATH];
  570. cbKeyLen = MAX_PATH;
  571. if (roVendor.GetValue(CACHE_PATH_VALUE,(LPBYTE) szScratch,&cbKeyLen) != ERROR_SUCCESS)
  572. continue;
  573. ExpandEnvironmentStrings(szScratch, szCachePath, sizeof(szCachePath)-1); // don't count the NULL
  574. if (!stricmp(szVendorKey, Name) || !stricmp(CachePath, szCachePath))
  575. {
  576. fInsertOk = FALSE;
  577. break;
  578. }
  579. }
  580. }
  581. if (fInsertOk)
  582. {
  583. REGISTRY_OBJ roNewVendor(&roExtensibleCache, (LPSTR)Name, CREATE_KEY_IF_NOT_EXISTS);
  584. if (roNewVendor.GetStatus() == ERROR_SUCCESS)
  585. {
  586. CHAR szScratch[MAX_PATH];
  587. CompressPath((LPTSTR)CachePath, szScratch);
  588. // Path.
  589. if ((dwError = roNewVendor.SetValue(CACHE_PATH_VALUE, (LPSTR)szScratch, REG_EXPAND_SZ)) != ERROR_SUCCESS)
  590. goto exit;
  591. // Prefix.
  592. if ((dwError = roNewVendor.SetValue(CACHE_PREFIX_VALUE, (LPSTR)CachePrefix, REG_SZ)) != ERROR_SUCCESS)
  593. goto exit;
  594. // Limit.
  595. if ((dwError = roNewVendor.SetValue(CACHE_LIMIT_VALUE, &KBCacheLimit)) != ERROR_SUCCESS)
  596. goto exit;
  597. // Options.
  598. if ((dwError = roNewVendor.SetValue(CACHE_OPTIONS_VALUE, &dwOptions)) != ERROR_SUCCESS)
  599. goto exit;
  600. }
  601. }
  602. else
  603. {
  604. dwError = ERROR_ALREADY_EXISTS;
  605. }
  606. }
  607. if (fInsertOk)
  608. {
  609. IncrementModifiedCount();
  610. }
  611. exit:
  612. if (pro)
  613. {
  614. delete pro;
  615. }
  616. mh.Release();
  617. if (fInsertOk)
  618. {
  619. GetExtensibleCacheConfigInfo(TRUE);
  620. }
  621. return dwError;
  622. }
  623. /*-----------------------------------------------------------------------------
  624. DWORD CConMgr::FindExtensibleContainer
  625. ----------------------------------------------------------------------------*/
  626. // THIS FUNCTION MUST BE CALLED WITH THE CACHE CRIT SECTION
  627. DWORD CConMgr::FindExtensibleContainer(LPCSTR Name)
  628. {
  629. DWORD n = NOT_AN_INDEX;
  630. DWORD i;
  631. URL_CONTAINER *co;
  632. for (i = NCONTAINERS; i < ConList.Size(); i++)
  633. {
  634. co = ConList.Get(i);
  635. if (co)
  636. {
  637. if (!stricmp(Name, co->GetCacheName()) && co->IsVisible())
  638. {
  639. // Found a match
  640. n = i;
  641. co->Release(FALSE);
  642. break;
  643. }
  644. co->Release(FALSE);
  645. }
  646. }
  647. return n;
  648. }
  649. /*-----------------------------------------------------------------------------
  650. DWORD CConMgr::DeleteContainer
  651. ----------------------------------------------------------------------------*/
  652. DWORD CConMgr::DeleteContainer(LPCSTR Name, DWORD dwOptions)
  653. {
  654. DWORD dwError = ERROR_SUCCESS;
  655. URL_CONTAINER *co = NULL;
  656. DWORD n = NOT_AN_INDEX;
  657. HKEY hKey;
  658. if (!Name || !*Name)
  659. {
  660. dwError = ERROR_INVALID_PARAMETER;
  661. goto exit;
  662. }
  663. LOCK_CACHE();
  664. n = FindExtensibleContainer(Name);
  665. if (n != NOT_AN_INDEX)
  666. {
  667. co = ConList.Get(n);
  668. if (co)
  669. {
  670. co->SetDeletePending(TRUE);
  671. // Don't release here, hold it pending until we've updated registry
  672. }
  673. }
  674. UNLOCK_CACHE();
  675. if (n!= NOT_AN_INDEX)
  676. {
  677. hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
  678. REGISTRY_OBJ* pro = CreateExtensiRegObj(hKey);
  679. if (!pro)
  680. {
  681. dwError = ERROR_ACCESS_DENIED;
  682. goto exit;
  683. }
  684. {
  685. REGISTRY_OBJ& roExtensibleCache = *pro;
  686. MUTEX_HOLDER mh;
  687. mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
  688. dwError = roExtensibleCache.DeleteKey((LPSTR)Name);
  689. mh.Release();
  690. IncrementModifiedCount();
  691. }
  692. delete pro;
  693. }
  694. exit:
  695. LOCK_CACHE();
  696. SAFERELEASE(co, TRUE);
  697. UNLOCK_CACHE();
  698. return dwError;
  699. }
  700. /*-----------------------------------------------------------------------------
  701. DWORD CConMgr::DeleteFileIfNotRegistered
  702. ----------------------------------------------------------------------------*/
  703. BOOL CConMgr::DeleteFileIfNotRegistered(URL_CONTAINER *coDelete)
  704. {
  705. BOOL fDelete = TRUE;
  706. BOOL fFound = FALSE;
  707. CHAR szCachePath[MAX_PATH];
  708. CHAR szCachePrefix[MAX_PATH];
  709. DWORD dwOptions;
  710. LONGLONG cbCacheLimit;
  711. HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
  712. DWORD cbKeyLen, cbKBLimit, dwError;
  713. CHAR szVendorKey[MAX_PATH];
  714. hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
  715. REGISTRY_OBJ* pro = CreateExtensiRegObj(hKey);
  716. MUTEX_HOLDER mh;
  717. if (!pro)
  718. {
  719. dwError = ERROR_ACCESS_DENIED;
  720. goto exit;
  721. }
  722. if (!WasModified(FALSE))
  723. {
  724. // If our internal cache is up to date, it can't
  725. // have been deleted unless DeletePending or Deleted
  726. fFound = !(coDelete->GetDeletePending()||coDelete->GetDeleted());
  727. if (fFound)
  728. {
  729. goto exit;
  730. }
  731. // If not found, need to look at registry to make sure we're not
  732. // deleting a path that has been reused
  733. }
  734. mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
  735. {
  736. REGISTRY_OBJ& roExtensibleCache = *pro;
  737. // Get the container paths, prefixes.
  738. while (roExtensibleCache.FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
  739. {
  740. BOOL fPathMatch;
  741. REGISTRY_OBJ roVendor(&roExtensibleCache, szVendorKey);
  742. if (roVendor.GetStatus()==ERROR_SUCCESS)
  743. {
  744. // Path.
  745. TCHAR szScratch[MAX_PATH];
  746. cbKeyLen = MAX_PATH;
  747. if (roVendor.GetValue(CACHE_PATH_VALUE,(LPBYTE) szScratch, &cbKeyLen) != ERROR_SUCCESS)
  748. continue;
  749. ExpandEnvironmentStrings(szScratch, szCachePath, sizeof(szCachePath)-1); // don't count the NULL
  750. // Prefix.
  751. cbKeyLen = MAX_PATH;
  752. if (roVendor.GetValue(CACHE_PREFIX_VALUE,(LPBYTE) szCachePrefix, &cbKeyLen) != ERROR_SUCCESS)
  753. continue;
  754. // Options.
  755. if (roVendor.GetValue(CACHE_OPTIONS_VALUE,&dwOptions) != ERROR_SUCCESS)
  756. continue;
  757. fPathMatch = !stricmp(coDelete->GetCachePath(), szCachePath);
  758. if (!stricmp(coDelete->GetCacheName(), szVendorKey) && fPathMatch &&
  759. !stricmp(coDelete->GetCachePrefix(), szCachePrefix) &&
  760. coDelete->GetOptions() != dwOptions)
  761. {
  762. fFound = TRUE;
  763. }
  764. if (fPathMatch)
  765. fDelete = FALSE;
  766. }
  767. }
  768. }
  769. if (fDelete)
  770. {
  771. // This will fail if another process still has the container mapped,
  772. // that's ok. They will check on exit if container needs to be
  773. // deleted
  774. if (coDelete->GetOptions() & INTERNET_CACHE_CONTAINER_AUTODELETE)
  775. {
  776. CFileMgr::DeleteCache(coDelete->GetCachePath());
  777. }
  778. }
  779. exit:
  780. if (pro)
  781. {
  782. delete pro;
  783. }
  784. mh.Release();
  785. return !fFound;
  786. }
  787. /*-----------------------------------------------------------------------------
  788. DWORD CConMgr::FindIndexFromPrefix
  789. ----------------------------------------------------------------------------*/
  790. // THIS FUNCTION MUST BE CALLED WITH THE CACHE CRIT SEC
  791. DWORD CConMgr::FindIndexFromPrefix(LPCSTR szUrl)
  792. {
  793. // Unless we find a matching prefix, CONTENT is the default.
  794. DWORD n = szUrl[0]==EXTENSIBLE_FIRST ? NOT_AN_INDEX : CONTENT;
  795. URL_CONTAINER *co = NULL;
  796. // NOTE: if deleting a container is supported, ConList.Get(i) can
  797. // return NULL, if list shrinks after getting size.
  798. // NOTE: if deleting containers is supported, it is not safe to
  799. // assume CONTENT if prefix is not found. client may be trying to
  800. // insert into a container that has been deleted, but once existed.
  801. // proper response is to return an error. the simplest way to do this
  802. // is to insist that all Extensible cache prefixes start with an illegal
  803. // URL character, EXTENSIBLE_FIRST
  804. GetExtensibleCacheConfigInfo(FALSE);
  805. for (DWORD i = COOKIE; i < ConList.Size(); i++)
  806. {
  807. co = ConList.Get(i);
  808. if (co)
  809. {
  810. if (co->PrefixMatch(szUrl))
  811. {
  812. // For content container, strnicmp (szUrl, "", 0) returns nonzero
  813. if (co->IsVisible())
  814. {
  815. // Found a match
  816. n = i;
  817. if (!co->IsInitialized())
  818. {
  819. // Init the container. If this fails,
  820. // Mark it as DELETED and return CONTENT.
  821. switch (co->Init())
  822. {
  823. case ERROR_SUCCESS:
  824. case ERROR_ALREADY_EXISTS:
  825. if (!(co->GetOptions() & INTERNET_CACHE_CONTAINER_NODESKTOPINIT))
  826. EnableCacheVu(co->GetCachePath(), n);
  827. break;
  828. default:
  829. INET_ASSERT(FALSE);
  830. co->SetDeleted(TRUE);
  831. n = szUrl[0]==EXTENSIBLE_FIRST ? NOT_AN_INDEX : CONTENT;
  832. break;
  833. }
  834. }
  835. co->Release(FALSE);
  836. break;
  837. }
  838. }
  839. co->Release(FALSE);
  840. }
  841. }
  842. return n;
  843. }
  844. /*-----------------------------------------------------------------------------
  845. BOOL CConMgr::PathPrefixMatch
  846. ----------------------------------------------------------------------------*/
  847. BOOL CConMgr::PathPrefixMatch(LPCSTR szPath, LPCSTR szPathRef)
  848. {
  849. // BUGBUG - logic borrowed from original cacheapi.cxx
  850. INT len;
  851. // TRUE if the passed in path is NULL
  852. if (!szPath)
  853. return TRUE;
  854. len = lstrlen(szPath);
  855. // TRUE if it is 0 length.
  856. if (!len)
  857. return TRUE;
  858. // stripout the trailing slash
  859. if (szPath[len-1] == DIR_SEPARATOR_CHAR)
  860. --len;
  861. // Compare paths.
  862. if (!strnicmp(szPath, szPathRef, len))
  863. if (szPathRef[len] == DIR_SEPARATOR_CHAR || szPathRef[len] == 0)
  864. return TRUE;
  865. return FALSE;
  866. }
  867. /*--------------------- Public Functions -----------------------------------*/
  868. /*-----------------------------------------------------------------------------
  869. CConMgr::CConMgr
  870. Default Constructor
  871. ----------------------------------------------------------------------------*/
  872. CConMgr::CConMgr()
  873. : ConList()
  874. {
  875. _coContent = NULL;
  876. _coCookies = NULL;
  877. _coHistory = NULL;
  878. _hMutexExtensible = 0;
  879. // Assume this is a profiles-capable machine. Later on, we'll make sure this is
  880. // the case.
  881. _fProfilesCapable = TRUE;
  882. // Assume that we'll be using the regular containers, instead of the backup
  883. _fUsingBackupContainers = FALSE;
  884. _dwStatus = Init();
  885. }
  886. /*-----------------------------------------------------------------------------
  887. CConMgr::~CConMgr
  888. Default Destructor
  889. ----------------------------------------------------------------------------*/
  890. CConMgr::~CConMgr()
  891. {
  892. ConList.Free();
  893. if (_hMutexExtensible)
  894. {
  895. CloseHandle(_hMutexExtensible);
  896. }
  897. }
  898. /*-----------------------------------------------------------------------------
  899. DWORD CConMgr::GetStatus()
  900. ----------------------------------------------------------------------------*/
  901. DWORD CConMgr::GetStatus()
  902. {
  903. return _dwStatus;
  904. }
  905. /*-----------------------------------------------------------------------------
  906. DWORD CConMgr::UnlockUrl
  907. ----------------------------------------------------------------------------*/
  908. DWORD CConMgr::UnlockUrl(LPCSTR szUrl)
  909. {
  910. URL_CONTAINER *co;
  911. DWORD dwError = ERROR_FILE_NOT_FOUND;
  912. // Find the associated container.
  913. DWORD idx;
  914. LOCK_CACHE();
  915. idx = FindIndexFromPrefix(szUrl);
  916. co = ConList.Get(idx);
  917. if (co)
  918. {
  919. UNLOCK_CACHE();
  920. // Call UnlockUrl on the appropriate container.
  921. dwError = co->UnlockUrl(szUrl); // may be expensive
  922. LOCK_CACHE();
  923. co->Release(TRUE);
  924. }
  925. UNLOCK_CACHE();
  926. return dwError;
  927. }
  928. /*-----------------------------------------------------------------------------
  929. DWORD CConMgr::DeleteUrl
  930. ----------------------------------------------------------------------------*/
  931. DWORD CConMgr::DeleteUrl(LPCSTR szUrl)
  932. {
  933. URL_CONTAINER *co;
  934. DWORD dwError = ERROR_FILE_NOT_FOUND;
  935. // Find the associated container.
  936. DWORD idx;
  937. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  938. LOCK_CACHE();
  939. idx = FindIndexFromPrefix(szUrl);
  940. co = ConList.Get(idx);
  941. if (co)
  942. {
  943. UNLOCK_CACHE();
  944. // Call DeleteUrl on the appropriate container.
  945. dwError = co->DeleteUrl(szUrl); // may be expensive.
  946. LOCK_CACHE();
  947. co->Release(TRUE);
  948. // Update the change count for the cookies container.
  949. if (idx == COOKIE)
  950. {
  951. DWORD dwChange = 0;
  952. _coContent->IncrementHeaderData(CACHE_HEADER_DATA_COOKIE_CHANGE_COUNT, &dwChange);
  953. }
  954. }
  955. UNLOCK_CACHE();
  956. return dwError;
  957. }
  958. /*-----------------------------------------------------------------------------
  959. BOOL CConMgr::GetHeaderData
  960. ----------------------------------------------------------------------------*/
  961. BOOL CConMgr::GetHeaderData(DWORD nIdx, LPDWORD pdwData)
  962. {
  963. return _coContent->GetHeaderData(nIdx, pdwData);
  964. }
  965. /*-----------------------------------------------------------------------------
  966. BOOL CConMgr::SetHeaderData
  967. ----------------------------------------------------------------------------*/
  968. BOOL CConMgr::SetHeaderData(DWORD nIdx, DWORD dwData)
  969. {
  970. UNIX_RETURN_ERR_IF_READONLY_CACHE(FALSE);
  971. return _coContent->SetHeaderData(nIdx, dwData);
  972. }
  973. /*-----------------------------------------------------------------------------
  974. BOOL CConMgr::IncrementHeaderData
  975. ----------------------------------------------------------------------------*/
  976. BOOL CConMgr::IncrementHeaderData(DWORD nIdx, LPDWORD pdwData)
  977. {
  978. UNIX_RETURN_ERR_IF_READONLY_CACHE(FALSE);
  979. return _coContent->IncrementHeaderData(nIdx, pdwData);
  980. }
  981. /*-----------------------------------------------------------------------------
  982. DWORD CConMgr::SetUrlGroup
  983. ----------------------------------------------------------------------------*/
  984. DWORD CConMgr::SetUrlGroup(
  985. IN LPCSTR szUrl,
  986. IN DWORD dwFlags,
  987. IN GROUPID GroupId
  988. )
  989. {
  990. URL_CONTAINER *co;
  991. DWORD dwError = ERROR_FILE_NOT_FOUND;
  992. // Find the associated container.
  993. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  994. LOCK_CACHE();
  995. DWORD idx = FindIndexFromPrefix(szUrl);
  996. co = ConList.Get(idx);
  997. if (co)
  998. {
  999. UNLOCK_CACHE();
  1000. // Call SetUrlInGroup on the appropriate container.
  1001. dwError = co->SetUrlGroup
  1002. (szUrl, dwFlags, GroupId);
  1003. LOCK_CACHE();
  1004. co->Release(TRUE);
  1005. }
  1006. UNLOCK_CACHE();
  1007. return dwError;
  1008. }
  1009. /*-----------------------------------------------------------------------------
  1010. DWORD CConMgr::CreateUniqueFile
  1011. ----------------------------------------------------------------------------*/
  1012. DWORD CConMgr::CreateUniqueFile(LPCSTR szUrl, DWORD dwExpectedSize,
  1013. LPCSTR szFileExtension, LPTSTR szFileName,
  1014. HANDLE *phfHandle,
  1015. BOOL fCreatePerUser)
  1016. {
  1017. URL_CONTAINER *co;
  1018. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1019. // Find the associated container.
  1020. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  1021. LOCK_CACHE();
  1022. DWORD idx = FindIndexFromPrefix(szUrl);
  1023. co = ConList.Get(idx);
  1024. if (co)
  1025. {
  1026. UNLOCK_CACHE();
  1027. // Call CreateUniqueFile on the appropriate container.
  1028. dwError = co->CreateUniqueFile(szUrl, dwExpectedSize,
  1029. szFileExtension, szFileName, phfHandle, fCreatePerUser); // expensive call
  1030. LOCK_CACHE();
  1031. co->Release(TRUE);
  1032. }
  1033. UNLOCK_CACHE();
  1034. return dwError;
  1035. }
  1036. /*-----------------------------------------------------------------------------
  1037. DWORD CConMgr::AddUrl
  1038. ----------------------------------------------------------------------------*/
  1039. DWORD CConMgr::AddUrl(AddUrlArg* pArgs)
  1040. {
  1041. URL_CONTAINER *co;
  1042. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1043. // Find the associated container.
  1044. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  1045. LOCK_CACHE();
  1046. DWORD idx = FindIndexFromPrefix(pArgs->pszUrl);
  1047. co = ConList.Get(idx);
  1048. if (co)
  1049. {
  1050. UNLOCK_CACHE();
  1051. // Call AddUrl on the appropriate container.
  1052. dwError = co->AddUrl(pArgs); // may be expensive
  1053. LOCK_CACHE();
  1054. co->Release(TRUE);
  1055. // Update the change count for the cookies container.
  1056. if (idx == COOKIE)
  1057. {
  1058. DWORD dwChange = 0;
  1059. _coContent->IncrementHeaderData(CACHE_HEADER_DATA_COOKIE_CHANGE_COUNT, &dwChange);
  1060. }
  1061. }
  1062. UNLOCK_CACHE();
  1063. return dwError;
  1064. }
  1065. /*-----------------------------------------------------------------------------
  1066. DWORD CConMgr::RetrieveUrl
  1067. ----------------------------------------------------------------------------*/
  1068. DWORD CConMgr::RetrieveUrl( LPCSTR szUrl,
  1069. LPCACHE_ENTRY_INFOA* ppCacheEntryInfo,
  1070. LPDWORD pcbCacheEntryInfoBufferSize,
  1071. DWORD dwLookupFlags,
  1072. DWORD dwRetrievalFlags)
  1073. {
  1074. URL_CONTAINER *co;
  1075. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1076. // Find the associated container.
  1077. LOCK_CACHE();
  1078. DWORD idx = FindIndexFromPrefix(szUrl);
  1079. co = ConList.Get(idx);
  1080. if (co)
  1081. {
  1082. UNLOCK_CACHE();
  1083. // Call RetrieveUrl on the appropriate container.
  1084. dwError = co->RetrieveUrl(szUrl,
  1085. ppCacheEntryInfo,
  1086. pcbCacheEntryInfoBufferSize,
  1087. dwLookupFlags, dwRetrievalFlags); // expensive?
  1088. LOCK_CACHE();
  1089. co->Release(TRUE);
  1090. }
  1091. UNLOCK_CACHE();
  1092. return dwError;
  1093. }
  1094. /*-----------------------------------------------------------------------------
  1095. DWORD CConMgr::GetUrlInfo
  1096. ----------------------------------------------------------------------------*/
  1097. DWORD CConMgr::GetUrlInfo( LPCSTR szUrl,
  1098. LPCACHE_ENTRY_INFOA* ppCacheEntryInfo,
  1099. LPDWORD pcbCacheEntryInfoBufferSize,
  1100. DWORD dwLookupFlags,
  1101. DWORD dwEntryFlags,
  1102. DWORD dwRetrievalFlags)
  1103. {
  1104. URL_CONTAINER *co;
  1105. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1106. // Find the associated container.
  1107. LOCK_CACHE();
  1108. DWORD idx = FindIndexFromPrefix(szUrl);
  1109. co = ConList.Get(idx);
  1110. if (co)
  1111. {
  1112. // Call GetUrlInfo on the appropriate container.
  1113. dwError = co->GetUrlInfo(szUrl,
  1114. ppCacheEntryInfo,
  1115. pcbCacheEntryInfoBufferSize,
  1116. dwLookupFlags,
  1117. dwEntryFlags,
  1118. dwRetrievalFlags);
  1119. co->Release(TRUE);
  1120. }
  1121. UNLOCK_CACHE();
  1122. return dwError;
  1123. }
  1124. DWORD CConMgr::GetUrlInfo(LPCSTR szUrl,
  1125. LPCACHE_ENTRY_INFOA pCacheEntryInfo,
  1126. LPDWORD pcbCacheEntryInfoBufferSize,
  1127. DWORD dwLookupFlags,
  1128. DWORD dwEntryFlags)
  1129. {
  1130. return GetUrlInfo(szUrl,
  1131. (pCacheEntryInfo) ? &pCacheEntryInfo : NULL,
  1132. pcbCacheEntryInfoBufferSize,
  1133. dwLookupFlags,
  1134. dwEntryFlags,
  1135. 0);
  1136. }
  1137. /*-----------------------------------------------------------------------------
  1138. DWORD CConMgr::SetUrlInfo
  1139. ----------------------------------------------------------------------------*/
  1140. DWORD CConMgr::SetUrlInfo(LPCSTR szUrl,
  1141. LPCACHE_ENTRY_INFOA pCacheEntryInfo,
  1142. DWORD dwFieldControl)
  1143. {
  1144. URL_CONTAINER *co;
  1145. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1146. // Find the associated container.
  1147. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  1148. LOCK_CACHE();
  1149. DWORD idx = FindIndexFromPrefix(szUrl);
  1150. co = ConList.Get(idx);
  1151. if (co)
  1152. {
  1153. // Call SetUrlInfo on the appropriate container.
  1154. dwError = co->SetUrlInfo(szUrl,
  1155. pCacheEntryInfo,
  1156. dwFieldControl);
  1157. co->Release(TRUE);
  1158. }
  1159. UNLOCK_CACHE();
  1160. return dwError;
  1161. }
  1162. DWORD CConMgr::FreeFindHandle(HANDLE hFind)
  1163. {
  1164. DWORD dwError = ERROR_INVALID_HANDLE;
  1165. if (hFind)
  1166. {
  1167. LOCK_CACHE();
  1168. LPCACHE_FIND_FIRST_HANDLE pFind;
  1169. pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
  1170. if (pFind)
  1171. {
  1172. // NOTHING SPECIAL TO DO FOR SIGNATURE_CONTAINER_FIND
  1173. if (pFind->dwSig == SIG_CACHE_FIND && !pFind->fFixed)
  1174. {
  1175. URL_CONTAINER *co = ConList.Get(pFind->nIdx);
  1176. if (co)
  1177. {
  1178. // It now has 2 AddRefs to balance
  1179. co->Release(FALSE);
  1180. co->Release(TRUE);
  1181. }
  1182. }
  1183. HandleMgr.Free (hFind);
  1184. dwError = ERROR_SUCCESS;
  1185. }
  1186. UNLOCK_CACHE();
  1187. }
  1188. return dwError;
  1189. }
  1190. /*-----------------------------------------------------------------------------
  1191. DWORD CConMgr::FindNextEntry
  1192. ----------------------------------------------------------------------------*/
  1193. DWORD CConMgr::FindNextEntry(
  1194. HANDLE *phFind,
  1195. LPCSTR szPrefix,
  1196. LPCACHE_ENTRY_INFOA* ppInfo,
  1197. LPDWORD pcbInfo,
  1198. DWORD dwFilter,
  1199. GROUPID GroupId,
  1200. DWORD dwFlags,
  1201. DWORD dwRetrievalFlags)
  1202. {
  1203. DWORD idx, dwError;
  1204. URL_CONTAINER *co = NULL;
  1205. LPCACHE_FIND_FIRST_HANDLE pFind = NULL;
  1206. LOCK_CACHE();
  1207. // Null handle initiates enumeration.
  1208. if (!*phFind)
  1209. {
  1210. // Allocate a handle.
  1211. //LOCK_CACHE();
  1212. *phFind = HandleMgr.Alloc (sizeof(CACHE_FIND_FIRST_HANDLE));
  1213. if (*phFind)
  1214. pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
  1215. //UNLOCK_CACHE();
  1216. if (!*phFind)
  1217. {
  1218. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1219. goto exit;
  1220. }
  1221. if (!pFind)
  1222. {
  1223. dwError = ERROR_INVALID_HANDLE;
  1224. goto exit;
  1225. }
  1226. // Set signature and initial hash table find
  1227. // handle in the newly allocated find handle.
  1228. pFind->dwSig = SIG_CACHE_FIND;
  1229. pFind->dwHandle = 0;
  1230. pFind->dwFlags = dwFlags;
  1231. // Find the associated container. NULL prefix
  1232. // results in enumeration over fixed containers.
  1233. if (!szPrefix)
  1234. {
  1235. pFind->fFixed = TRUE;
  1236. pFind->nIdx = CONTENT;
  1237. }
  1238. else
  1239. {
  1240. idx = FindIndexFromPrefix(szPrefix);
  1241. if (idx == NOT_AN_INDEX)
  1242. {
  1243. dwError = ERROR_NO_MORE_ITEMS;
  1244. goto exit;
  1245. }
  1246. // Under old semantics prefix resolving to CONTENT
  1247. // container implies that an enumeration over all
  1248. // the fixed containers is desired. Enumeration then
  1249. // begins with the CONTENT container. We do not keep
  1250. // a refcount on any fixed containers in this case.
  1251. if (idx == CONTENT && (dwFlags & FIND_FLAGS_OLD_SEMANTICS))
  1252. {
  1253. pFind->fFixed = TRUE;
  1254. pFind->nIdx = CONTENT;
  1255. }
  1256. else
  1257. {
  1258. // Otherwise only enumeration over the found container
  1259. // is implied. Retrieve this container. Set fFixed to FALSE.
  1260. // NO RELEASE: hold RefCnt until handle is closed
  1261. co = ConList.Get(idx);
  1262. if (co)
  1263. {
  1264. pFind->fFixed = FALSE;
  1265. pFind->nIdx = idx;
  1266. pFind->dwHandle = co->GetInitialFindHandle();
  1267. }
  1268. else
  1269. {
  1270. dwError = ERROR_NO_MORE_ITEMS;
  1271. goto exit;
  1272. }
  1273. }
  1274. }
  1275. // Set filter and group id in handle.
  1276. pFind->dwFilter = dwFilter;
  1277. pFind->GroupId = GroupId;
  1278. }
  1279. else
  1280. {
  1281. // Valid handle passed in - map it.
  1282. //LOCK_CACHE();
  1283. pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
  1284. //UNLOCK_CACHE();
  1285. if (!pFind)
  1286. {
  1287. dwError = ERROR_INVALID_HANDLE;
  1288. goto exit;
  1289. }
  1290. }
  1291. // -------------------------------------------------------------------------
  1292. // The handle is initialized or was created via a previous FindNextEntry.
  1293. //--------------------------------------------------------------------------
  1294. dwError = ERROR_NO_MORE_ITEMS;
  1295. // Are we only enumerating over one container?
  1296. if (!pFind->fFixed)
  1297. {
  1298. // Get the associated container.
  1299. co = ConList.Get(pFind->nIdx);
  1300. if (co)
  1301. {
  1302. // Enum on the container and release.
  1303. dwError = co->FindNextEntry(&pFind->dwHandle, ppInfo, pcbInfo, pFind->dwFilter, pFind->GroupId, pFind->dwFlags, dwRetrievalFlags);
  1304. co->Release(TRUE);
  1305. }
  1306. else
  1307. {
  1308. // Getting container failed.
  1309. dwError = ERROR_NO_MORE_ITEMS;
  1310. goto exit;
  1311. }
  1312. }
  1313. else
  1314. {
  1315. // fFixed is TRUE - enumerate over the fixed containers.
  1316. while (pFind->nIdx < NCONTAINERS)
  1317. {
  1318. // Get the associated container.
  1319. co = ConList.Get(pFind->nIdx);
  1320. if (co)
  1321. {
  1322. // Get the initial hash find handle if not already done so.
  1323. if (!pFind->dwHandle)
  1324. pFind->dwHandle = co->GetInitialFindHandle();
  1325. // Enum on the container and release.
  1326. dwError = co->FindNextEntry(&pFind->dwHandle, ppInfo, pcbInfo, pFind->dwFilter, pFind->GroupId, pFind->dwFlags, dwRetrievalFlags);
  1327. co->Release(TRUE);
  1328. // Goto exit only if ERROR_NO_MORE_ITEMS.
  1329. // This handles ERROR_SUCCESS correctly.
  1330. if (dwError != ERROR_NO_MORE_ITEMS)
  1331. goto exit;
  1332. // ERROR_NO_MORE_ITEMS: Go to next container
  1333. // and begin enum anew.
  1334. pFind->nIdx++;
  1335. pFind->dwHandle = 0;
  1336. }
  1337. else
  1338. {
  1339. // Getting container failed.
  1340. dwError = ERROR_NO_MORE_ITEMS;
  1341. goto exit;
  1342. }
  1343. }
  1344. }
  1345. exit:
  1346. UNLOCK_CACHE();
  1347. INET_ASSERT(*phFind != 0);
  1348. INET_ASSERT(pFind != NULL);
  1349. return dwError;
  1350. }
  1351. DWORD CConMgr::FindNextEntry(
  1352. HANDLE *phFind,
  1353. LPCSTR szPrefix,
  1354. LPCACHE_ENTRY_INFOA pInfo,
  1355. LPDWORD pcbInfo,
  1356. DWORD dwFilter,
  1357. GROUPID GroupId,
  1358. DWORD dwFlags)
  1359. {
  1360. return FindNextEntry(
  1361. phFind,
  1362. szPrefix,
  1363. (pInfo ? &pInfo : NULL),
  1364. pcbInfo,
  1365. dwFilter,
  1366. GroupId,
  1367. dwFlags,
  1368. 0);
  1369. }
  1370. /*-----------------------------------------------------------------------------
  1371. DWORD CConMgr::CleanupUrls
  1372. ----------------------------------------------------------------------------*/
  1373. DWORD CConMgr::CleanupUrls
  1374. (LPCTSTR szCachePath, DWORD dwFactor, DWORD dwFilter)
  1375. {
  1376. DWORD dwError = ERROR_SUCCESS;
  1377. UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
  1378. // Bad cleanup parameter.
  1379. if (dwFactor <= 0 || dwFactor > 100)
  1380. {
  1381. dwError = ERROR_INVALID_PARAMETER;
  1382. goto exit;
  1383. }
  1384. // For null or empty path, clean up content container.
  1385. if (!szCachePath || !*szCachePath)
  1386. {
  1387. _coContent->CleanupUrls(dwFactor, dwFilter);
  1388. }
  1389. else
  1390. {
  1391. LOCK_CACHE();
  1392. // Find the container with the matching cache path and clean it up.
  1393. for (DWORD idx = CONTENT; idx < NCONTAINERS; idx++)
  1394. {
  1395. URL_CONTAINER *co = ConList.Get(idx);
  1396. if (co)
  1397. {
  1398. if (PathPrefixMatch(szCachePath, co->GetCachePath()))
  1399. {
  1400. UNLOCK_CACHE();
  1401. co->CleanupUrls(dwFactor, dwFilter); // expensive?
  1402. LOCK_CACHE();
  1403. co->Release(TRUE);
  1404. break;
  1405. }
  1406. co->Release(TRUE);
  1407. }
  1408. }
  1409. UNLOCK_CACHE();
  1410. }
  1411. exit:
  1412. return dwError;
  1413. }
  1414. /*-----------------------------------------------------------------------------
  1415. DWORD CConMgr::GetUrlInGroup
  1416. ----------------------------------------------------------------------------*/
  1417. DWORD CConMgr::GetUrlInGroup(LPCSTR szUrl, GROUPID* pGroupId, LPDWORD pdwExemptDelta)
  1418. {
  1419. URL_CONTAINER *co;
  1420. DWORD dwError = ERROR_FILE_NOT_FOUND;
  1421. // Find the associated container.
  1422. LOCK_CACHE();
  1423. DWORD idx = FindIndexFromPrefix(szUrl);
  1424. co = ConList.Get(idx);
  1425. if (co)
  1426. {
  1427. UNLOCK_CACHE();
  1428. // Call GetUrlInGroup on the appropriate container.
  1429. dwError = co->GetUrlInGroup(szUrl, pGroupId, pdwExemptDelta);
  1430. LOCK_CACHE();
  1431. co->Release(TRUE);
  1432. }
  1433. UNLOCK_CACHE();
  1434. return dwError;
  1435. }
  1436. /*-----------------------------------------------------------------------------
  1437. DWORD CConMgr::CreateGroup()
  1438. ----------------------------------------------------------------------------*/
  1439. DWORD CConMgr::CreateGroup(DWORD dwFlags, GROUPID* pGID)
  1440. {
  1441. INET_ASSERT(_coContent);
  1442. LOCK_CACHE();
  1443. GroupMgr gm;
  1444. DWORD dwError = ERROR_INTERNET_INTERNAL_ERROR;
  1445. if( gm.Init(_coContent) )
  1446. {
  1447. dwError = gm.CreateGroup(dwFlags, pGID);
  1448. }
  1449. UNLOCK_CACHE();
  1450. return dwError;
  1451. }
  1452. /*-----------------------------------------------------------------------------
  1453. DWORD CConMgr::CreateDefaultGroups()
  1454. ----------------------------------------------------------------------------*/
  1455. DWORD CConMgr::CreateDefaultGroups()
  1456. {
  1457. INET_ASSERT(_coContent);
  1458. LOCK_CACHE();
  1459. GroupMgr gm;
  1460. DWORD dwError = ERROR_INTERNET_INTERNAL_ERROR;
  1461. if( gm.Init(_coContent) )
  1462. {
  1463. dwError = gm.CreateDefaultGroups();
  1464. }
  1465. UNLOCK_CACHE();
  1466. return dwError;
  1467. }
  1468. /*-----------------------------------------------------------------------------
  1469. DWORD CConMgr::DeleteGroup()
  1470. ----------------------------------------------------------------------------*/
  1471. DWORD CConMgr::DeleteGroup(GROUPID gid, DWORD dwFlags)
  1472. {
  1473. INET_ASSERT(_coContent);
  1474. LOCK_CACHE();
  1475. GroupMgr gm;
  1476. DWORD dwError = ERROR_INTERNET_INTERNAL_ERROR;
  1477. if( gm.Init(_coContent) )
  1478. {
  1479. dwError = gm.DeleteGroup(gid, dwFlags);
  1480. }
  1481. UNLOCK_CACHE();
  1482. return dwError;
  1483. }
  1484. /*-----------------------------------------------------------------------------
  1485. DWORD CConMgr::FindNextGroup()
  1486. ----------------------------------------------------------------------------*/
  1487. DWORD CConMgr::FindNextGroup(
  1488. HANDLE* phFind,
  1489. DWORD dwFlags,
  1490. GROUPID* pGroupId
  1491. )
  1492. {
  1493. DWORD dwError;
  1494. GROUP_FIND_FIRST_HANDLE* pFind = NULL;
  1495. GroupMgr gm;
  1496. INET_ASSERT(_coContent);
  1497. LOCK_CACHE();
  1498. // Null handle initiates enumeration.
  1499. if (!*phFind)
  1500. {
  1501. // BUGBUG currently only supports SEARCH_ALL option
  1502. if( dwFlags )
  1503. {
  1504. dwError = ERROR_INVALID_PARAMETER;
  1505. goto exit;
  1506. }
  1507. // Allocate a handle.
  1508. *phFind = HandleMgr.Alloc (sizeof(GROUP_FIND_FIRST_HANDLE));
  1509. if (*phFind)
  1510. pFind = (GROUP_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
  1511. if (!*phFind)
  1512. {
  1513. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1514. goto exit;
  1515. }
  1516. if (!pFind)
  1517. {
  1518. dwError = ERROR_INVALID_HANDLE;
  1519. goto exit;
  1520. }
  1521. // Set signature and initial hash table find
  1522. // handle in the newly allocated find handle.
  1523. pFind->dwSig = SIG_GROUP_FIND;
  1524. pFind->fFixed = TRUE;
  1525. pFind->nIdx = CONTENT;
  1526. pFind->dwLastItemOffset = 0;
  1527. }
  1528. else
  1529. {
  1530. // Valid handle passed in - map it.
  1531. pFind = (GROUP_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
  1532. if (!pFind)
  1533. {
  1534. dwError = ERROR_INVALID_HANDLE;
  1535. goto exit;
  1536. }
  1537. }
  1538. //
  1539. // The handle is initialized or was created via a previous FindNextEntry.
  1540. //
  1541. dwError = ERROR_FILE_NOT_FOUND;
  1542. // Enum on the container and release.
  1543. if( gm.Init(_coContent) )
  1544. {
  1545. DWORD dwLastItemOffset = pFind->dwLastItemOffset;
  1546. dwError = gm.GetNextGroup(&dwLastItemOffset, pGroupId);
  1547. // update offset field of the find handle
  1548. pFind->dwLastItemOffset = dwLastItemOffset;
  1549. }
  1550. exit:
  1551. UNLOCK_CACHE();
  1552. INET_ASSERT(*phFind != 0);
  1553. INET_ASSERT(pFind != NULL);
  1554. return dwError;
  1555. }
  1556. /*-----------------------------------------------------------------------------
  1557. DWORD CConMgr::GetGroupAttributes()
  1558. ----------------------------------------------------------------------------*/
  1559. DWORD CConMgr::GetGroupAttributes(
  1560. GROUPID gid,
  1561. DWORD dwAttrib,
  1562. LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,
  1563. LPDWORD lpdwGroupInfo
  1564. )
  1565. {
  1566. INET_ASSERT(_coContent);
  1567. DWORD dwError = ERROR_INTERNET_INTERNAL_ERROR;
  1568. LOCK_CACHE();
  1569. GroupMgr gm;
  1570. if( gm.Init(_coContent) )
  1571. {
  1572. dwError = gm.GetGroup(gid, dwAttrib, lpGroupInfo, lpdwGroupInfo);
  1573. }
  1574. UNLOCK_CACHE();
  1575. return dwError;
  1576. }
  1577. /*-----------------------------------------------------------------------------
  1578. DWORD CConMgr::SetGroupAttributes()
  1579. ----------------------------------------------------------------------------*/
  1580. DWORD CConMgr::SetGroupAttributes(
  1581. GROUPID gid,
  1582. DWORD dwAttrib,
  1583. LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo
  1584. )
  1585. {
  1586. INET_ASSERT(_coContent);
  1587. DWORD dwError = ERROR_INTERNET_INTERNAL_ERROR;
  1588. LOCK_CACHE();
  1589. GroupMgr gm;
  1590. if( gm.Init(_coContent))
  1591. {
  1592. dwError = gm.SetGroup(gid, dwAttrib, lpGroupInfo);
  1593. }
  1594. UNLOCK_CACHE();
  1595. return dwError;
  1596. }
  1597. DWORD CConMgr::RegisterCacheNotify(
  1598. HWND hWnd,
  1599. UINT uMsg,
  1600. GROUPID gid,
  1601. DWORD dwFilter
  1602. )
  1603. {
  1604. DWORD dwError;
  1605. INET_ASSERT(_coContent);
  1606. dwError = _coContent->RegisterCacheNotify(hWnd, uMsg, gid, dwFilter);
  1607. return dwError;
  1608. }
  1609. DWORD CConMgr::SendCacheNotification( DWORD dwOp)
  1610. {
  1611. DWORD dwError;
  1612. INET_ASSERT(_coContent);
  1613. _coContent->SendCacheNotification(dwOp);
  1614. return ERROR_SUCCESS;
  1615. }
  1616. /*-----------------------------------------------------------------------------
  1617. VOID CConMgr::GetCacheInfo
  1618. ----------------------------------------------------------------------------*/
  1619. VOID CConMgr::GetCacheInfo(LPCSTR szPrefix, LPSTR szCachePath, LONGLONG *cbLimit)
  1620. {
  1621. URL_CONTAINER *co;
  1622. // Find the associated container.
  1623. LOCK_CACHE();
  1624. DWORD idx = FindIndexFromPrefix(szPrefix);
  1625. co = ConList.Get(idx);
  1626. if (co)
  1627. {
  1628. // Call GetCacheInfo on the appropriate container.
  1629. co->GetCacheInfo(szCachePath, cbLimit);
  1630. co->Release(TRUE);
  1631. }
  1632. UNLOCK_CACHE();
  1633. }
  1634. /*-----------------------------------------------------------------------------
  1635. VOID CConMgr::SetCacheLimit
  1636. ----------------------------------------------------------------------------*/
  1637. VOID CConMgr::SetCacheLimit(LONGLONG cbLimit, DWORD idx)
  1638. {
  1639. URL_CONTAINER *co;
  1640. // Find the associated container.
  1641. UNIX_RETURN_IF_READONLY_CACHE;
  1642. LOCK_CACHE();
  1643. co = ConList.Get(idx);
  1644. if (co)
  1645. {
  1646. // Call SetCacheLimit on the container.
  1647. co->SetCacheLimit(cbLimit);
  1648. co->Release(TRUE);
  1649. }
  1650. UNLOCK_CACHE();
  1651. }