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