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.

563 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. contain.hxx
  5. Abstract:
  6. contains class definitions for CONTAINER class objects.
  7. Author:
  8. Madan Appiah (madana) 28-Dec-1994
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #ifndef SAFERELEASE
  14. #define SAFERELEASE(p,x) if ((p) != NULL) { (p)->Release(x); (p) = NULL; };
  15. #endif
  16. // so as to easily recognize Extensible prefixes, require them to start with
  17. // a character that is illegal in URLs
  18. #define EXTENSIBLE_FIRST (':')
  19. struct SCORE_ITEM
  20. {
  21. DWORD dwScore; // score of this item
  22. DWORD dwItemOffset; // offset to hash table item
  23. DWORD dwHashValue; // masked value from hash table item
  24. DWORD dwHashOffset; // offset to url entry from hash table item
  25. };
  26. /*++
  27. Class Description:
  28. Class definition that manages the URL objects.
  29. Private Member functions:
  30. Public Member functions:
  31. URL_CONTAINER : constructs an URL container.
  32. ~URL_CONTAINER : destructs an URL container.
  33. GetStatus : Retrieves object status.
  34. CleanupUrls : Deletes unused URLs and frees up file system cache space.
  35. DeleteIndex: Deletes all files not in use and attempts to delete index file.
  36. AddUrl : Adds an URL to the container and copies the cache file.
  37. RetrieveUrl : Retrieves an url from the cache.
  38. DeleteUrl : Deletes the specified url from cache.
  39. UnlockUrl : Decrements the reference count.
  40. GetUrlInfo : Gets info of the specified url file.
  41. SetUrlInfo : Sets info of the specified url file.
  42. SetExemptDelta: Sets an exemption on the entry
  43. CreateUniqueFile : Creates a file in the cache path for the incoming url
  44. to store.
  45. GetCacheInfo : Retrieves certain container info.
  46. SetCacheLimit : Sets cache limit value.
  47. DeleteAPendingUrl : Removes and deletes an url from the pending list.
  48. Returns FALSE if the list is empty.
  49. FindNextEntry : Retrieves the next element from the container.
  50. GetCacheSize : return current size of the cache.
  51. --*/
  52. class GroupMgr;
  53. class URL_CONTAINER {
  54. protected:
  55. // This class has one vtable, so there is also one dword of alignment padding.
  56. LONGLONG _CacheStartUpLimit;
  57. DWORD _Status;
  58. MEMMAP_FILE* _UrlObjStorage;
  59. CFileMgr* _FileManager;
  60. LPTSTR _CachePath;
  61. LPTSTR _CachePrefix;
  62. DWORD _CachePrefixLen;
  63. DWORD _CacheEntryType;
  64. LPTSTR _CacheName;
  65. DWORD _CachePathLen;
  66. DWORD _ClusterSizeMinusOne;
  67. DWORD _ClusterSizeMask;
  68. DWORD _FileMapEntrySize;
  69. HANDLE _MutexHandle;
  70. BOOL _fIsInitialized;
  71. DWORD _dwRefCount;
  72. BOOL _fDeletePending;
  73. BOOL _fDeleted;
  74. BOOL _fMarked;
  75. BOOL _fMustLaunchScavenger;
  76. BOOL _fPerUserItem;
  77. DWORD _dwLastReference;
  78. DWORD _dwOptions;
  79. DWORD _dwTaken;
  80. DWORD _dwBytesDownloaded;
  81. DWORD _dwItemsDownloaded;
  82. #ifdef CHECKLOCK_NORMAL
  83. DWORD _dwThreadLocked;
  84. #endif
  85. BOOL SetHeaderFlags(DWORD dwStamp);
  86. DWORD CopyUrlInfo( LPURL_FILEMAP_ENTRY, LPCACHE_ENTRY_INFO*, LPDWORD, DWORD);
  87. DWORD CopyUrlInfoGuard( LPURL_FILEMAP_ENTRY, LPCACHE_ENTRY_INFO*, LPDWORD, DWORD);
  88. void UnlockAllItems (void);
  89. void UnlockItem (URL_FILEMAP_ENTRY* pEntry, HASH_ITEM* pItem);
  90. BOOL UpdateOfflineRedirect (DWORD, LPCSTR, DWORD, LPCSTR);
  91. BOOL DeleteIndex (void);
  92. void CloseContainerFile();
  93. DWORD SetExemptDelta (URL_FILEMAP_ENTRY*, DWORD dwExemptDelta, DWORD dwItemOffset=0);
  94. DWORD DeleteUrlEntry (URL_FILEMAP_ENTRY*, HASH_ITEM* pHash, DWORD dwSig);
  95. DWORD UpdateStickness(URL_FILEMAP_ENTRY*, DWORD dwOp, DWORD dwItemOffset=0);
  96. public:
  97. URL_CONTAINER( LPTSTR CacheName, LPTSTR CachePath, LPTSTR CachePrefix, LONGLONG CacheLimit, DWORD dwOptions );
  98. ~URL_CONTAINER( VOID );
  99. DWORD Init();
  100. DWORD GetStatus( VOID )
  101. {
  102. return( _Status );
  103. };
  104. #ifdef CHECKLOCK_PARANOID
  105. void CheckNoLocks(DWORD dwThreadId);
  106. #endif
  107. BOOL LockContainer( BOOL *fMustUnlock );
  108. VOID UnlockContainer( VOID );
  109. BOOL WalkLeakList (void);
  110. DWORD GetLastReference();
  111. BOOL IsVisible();
  112. void Mark(BOOL fMarked);
  113. BOOL GetMarked();
  114. BOOL GetDeleted();
  115. void SetDeleted(BOOL fDeleted);
  116. BOOL GetDeletePending();
  117. void SetDeletePending(BOOL fDeletePending);
  118. void AddRef();
  119. DWORD Release(BOOL fTryToUnmap);
  120. void TryToUnmap(DWORD dwAcceptableRefCount);
  121. DWORD GetOptions();
  122. //
  123. // Internal routines called by the cache management.
  124. //
  125. DWORD CleanupUrls ( DWORD Factor, DWORD dwFilter);
  126. DWORD FixupHandler (DWORD dwFactor, DWORD dwFilter);
  127. BOOL PrefixMatch( LPCSTR UrlName )
  128. {
  129. return (_CachePrefix &&
  130. (strnicmp(_CachePrefix, UrlName, _CachePrefixLen)==0) );
  131. }
  132. #ifdef CHECKLOCK_PARANOID
  133. void CheckUnlocked()
  134. {
  135. INET_ASSERT(_dwTaken==0 || GetCurrentThreadId() != _dwThreadLocked);
  136. }
  137. #endif
  138. LPSTR GetCacheName()
  139. {
  140. return _CacheName;
  141. }
  142. LPSTR GetCachePath()
  143. {
  144. return _CachePath;
  145. }
  146. LPSTR GetCachePrefix()
  147. {
  148. return _CachePrefix;
  149. }
  150. BOOL IsContentContainer()
  151. {
  152. return (_CachePrefix[0] == 0);
  153. }
  154. DWORD GetCachePathLen()
  155. {
  156. return _CachePathLen;
  157. }
  158. DWORD IsInitialized()
  159. {
  160. return _fIsInitialized;
  161. }
  162. BOOL IsPerUserItem()
  163. {
  164. return _fPerUserItem;
  165. }
  166. VOID SetPerUserItem(BOOL fFlag)
  167. {
  168. _fPerUserItem = fFlag;
  169. }
  170. VOID SetCacheSize(LONGLONG dlSize)
  171. {
  172. _UrlObjStorage->SetCacheSize(dlSize);
  173. }
  174. //
  175. // External routines called by the cache APIs.
  176. //
  177. virtual LPSTR GetPrefixMap();
  178. virtual LPSTR GetVolumeLabel();
  179. virtual LPSTR GetVolumeTitle();
  180. virtual DWORD AddUrl(AddUrlArg* args);
  181. virtual DWORD AddIdentityUrl(AddUrlArg* args);
  182. virtual DWORD RetrieveUrl(
  183. LPCSTR UrlName,
  184. LPCACHE_ENTRY_INFO* EntryInfo,
  185. LPDWORD EntryInfoSize,
  186. DWORD dwLookupFlags,
  187. DWORD dwRetrievalFlags);
  188. DWORD DeleteUrl( LPCSTR UrlName );
  189. DWORD UnlockUrl( LPCSTR UrlName );
  190. virtual DWORD GetUrlInfo(
  191. LPCSTR UrlName,
  192. LPCACHE_ENTRY_INFO* ppUrlInfo,
  193. LPDWORD UrlInfoLength,
  194. DWORD dwLookupFlags,
  195. DWORD dwEntryFlags,
  196. DWORD dwRetrievalFlags);
  197. DWORD SetUrlInfo(
  198. LPCSTR UrlName,
  199. LPCACHE_ENTRY_INFO UrlInfo,
  200. DWORD FieldControl);
  201. DWORD SetUrlGroup (LPCSTR lpszUrl, DWORD dwFlags, GROUPID GroupId);
  202. DWORD GetUrlInGroup (LPCSTR lpszUrl, GROUPID* pGroupId, LPDWORD pdwExemptDelta);
  203. DWORD CreateUniqueFile(
  204. LPCSTR UrlName,
  205. DWORD ExpectedSize,
  206. LPCSTR lpszFileExtension,
  207. LPTSTR FileName,
  208. HANDLE *phfHandle,
  209. BOOL fCreateUniqueFile = FALSE);
  210. DWORD RegisterCacheNotify(
  211. HWND hWnd,
  212. UINT uMsg,
  213. GROUPID gid,
  214. DWORD dwFilter);
  215. VOID SendCacheNotification(DWORD dwOpcode)
  216. {
  217. BOOL fUnlock;
  218. LockContainer(&fUnlock);
  219. NotifyCacheChange(dwOpcode, 0);
  220. if (fUnlock) UnlockContainer();
  221. }
  222. VOID SetCacheLimit(LONGLONG CacheLimit )
  223. {
  224. BOOL fUnlock;
  225. LockContainer(&fUnlock);
  226. _UrlObjStorage->SetCacheLimit(CacheLimit);
  227. if (fUnlock) UnlockContainer();
  228. }
  229. LONGLONG GetCacheStartUpLimit()
  230. {
  231. BOOL fUnlock;
  232. LONGLONG llResult;
  233. LockContainer(&fUnlock);
  234. llResult = _CacheStartUpLimit;
  235. if (fUnlock) UnlockContainer();
  236. return llResult;
  237. }
  238. LONGLONG GetCacheLimit()
  239. {
  240. BOOL fUnlock;
  241. LockContainer(&fUnlock);
  242. LONGLONG cbLimit = _UrlObjStorage->GetCacheLimit();
  243. if (fUnlock) UnlockContainer();
  244. return cbLimit;
  245. }
  246. LONGLONG GetCacheSize()
  247. {
  248. BOOL fUnlock;
  249. LockContainer(&fUnlock);
  250. LONGLONG CacheSize = _UrlObjStorage->GetCacheSize();
  251. if (fUnlock) UnlockContainer();
  252. return CacheSize;
  253. }
  254. LONGLONG GetExemptUsage()
  255. {
  256. BOOL fUnlock;
  257. LockContainer(&fUnlock);
  258. LONGLONG ExemptCacheUsage = _UrlObjStorage->GetExemptUsage();
  259. if (fUnlock) UnlockContainer();
  260. return ExemptCacheUsage;
  261. }
  262. VOID GetCacheInfo( LPTSTR CachePath,
  263. LONGLONG *CacheLimit )
  264. {
  265. BOOL fUnlock;
  266. LockContainer(&fUnlock);
  267. *CacheLimit = _UrlObjStorage->GetCacheLimit();
  268. memcpy(CachePath, _CachePath, _CachePathLen);
  269. if (fUnlock) UnlockContainer();
  270. }
  271. DWORD GetInitialFindHandle (void)
  272. {
  273. DWORD dwHandle;
  274. BOOL fUnlock;
  275. LockContainer(&fUnlock);
  276. dwHandle = *_UrlObjStorage->GetPtrToHashTableOffset();
  277. if (fUnlock) UnlockContainer();
  278. return dwHandle;
  279. }
  280. DWORD FindNextEntry(
  281. LPDWORD Handle,
  282. LPCACHE_ENTRY_INFO* lppCacheEntryInfo,
  283. LPDWORD lpCacheEntryInfoSize,
  284. DWORD dwFilter,
  285. GROUPID GroupId,
  286. DWORD dwFlags,
  287. DWORD dwRetrievalFlags);
  288. BOOL SetHeaderData(DWORD nIdx, DWORD dwData)
  289. {
  290. BOOL fRet, fUnlock;
  291. LockContainer(&fUnlock);
  292. fRet = _UrlObjStorage->SetHeaderData(nIdx, dwData);
  293. if (fUnlock) UnlockContainer();
  294. return fRet;
  295. }
  296. BOOL GetHeaderData(DWORD nIdx, LPDWORD pdwData)
  297. {
  298. BOOL fRet, fUnlock;
  299. LockContainer(&fUnlock);
  300. fRet = _UrlObjStorage->GetHeaderData(nIdx, pdwData);
  301. if (fUnlock) UnlockContainer();
  302. return fRet;
  303. }
  304. BOOL IncrementHeaderData(DWORD nIdx, LPDWORD pdwData)
  305. {
  306. BOOL fRet, fUnlock;
  307. LockContainer(&fUnlock);
  308. fRet = _UrlObjStorage->IncrementHeaderData(nIdx, pdwData);
  309. if (fUnlock) UnlockContainer();
  310. return fRet;
  311. }
  312. DWORD AddLeakFile (LPCSTR pszFile);
  313. // Creates a cache directory with a given name to allow existing directories
  314. // to be copied into another cache file.
  315. BOOL CreateDirWithSecureName( LPSTR szDirName)
  316. {
  317. return _FileManager->CreateDirWithSecureName( szDirName);
  318. }
  319. // Creates a redirect from TargetUrl to OriginUrl
  320. BOOL CreateRedirect( LPSTR szTargetUrl, LPSTR szOriginUrl)
  321. {
  322. BOOL retVal = FALSE;
  323. HASH_ITEM* pTargetItem;
  324. if( HashFindItem( szTargetUrl, 0, &pTargetItem) != TRUE)
  325. goto doneCreateRedirect;
  326. if( UpdateOfflineRedirect( OffsetFromPointer(pTargetItem),
  327. szTargetUrl, lstrlen( szTargetUrl),
  328. szOriginUrl) != TRUE)
  329. goto doneCreateRedirect;
  330. retVal = TRUE;
  331. doneCreateRedirect:
  332. return retVal;
  333. }
  334. private:
  335. // hash table wrapper methods
  336. DWORD OffsetFromPointer (LPVOID p)
  337. {
  338. SSIZE_T llDiff = PtrDifference(p, *_UrlObjStorage->GetHeapStart());
  339. #if defined(_AMD64_) || defined(_IA64_)
  340. return GuardedCast(llDiff);
  341. #else
  342. return llDiff;
  343. #endif
  344. }
  345. LPBYTE PointerFromOffset (DWORD dw)
  346. {
  347. return ((LPBYTE) *_UrlObjStorage->GetHeapStart()) + dw;
  348. }
  349. LPURL_FILEMAP_ENTRY HashGetEntry (HASH_ITEM *pItem)
  350. {
  351. INET_ASSERT (pItem->dwHash > HASH_END);
  352. return (URL_FILEMAP_ENTRY*) PointerFromOffset (pItem->dwOffset);
  353. }
  354. void HashSetEntry (HASH_ITEM* pItem, LPBYTE pEntry)
  355. {
  356. pItem->dwOffset = OffsetFromPointer (pEntry);
  357. }
  358. BOOL HashFindItem (LPCSTR pszUrl, DWORD dwLookupFlags, HASH_ITEM** ppItem);
  359. /////////////////////////////////////////////////////////////////////////////
  360. // WARNING: if HASH_*_CREATE set, the file might be grown and remapped //
  361. // so all pointers into the file must be recalculated from their offsets //
  362. /////////////////////////////////////////////////////////////////////////////
  363. PRIVATE HASH_ITEM* IsMatch (HASH_ITEM *pItem, LPCSTR pszKey, DWORD dwFlags);
  364. LPURL_FILEMAP_ENTRY HashFindEntry (LPCSTR pszUrl, DWORD dwLookupFlags = 0)
  365. {
  366. HASH_ITEM *pItem;
  367. if (HashFindItem (pszUrl, dwLookupFlags, &pItem))
  368. return HashGetEntry (pItem);
  369. else
  370. return NULL;
  371. }
  372. void AdjustGroupUsage(GROUP_ENTRY* pGroupEntry, LONGLONG llDelta)
  373. {
  374. if( pGroupEntry && !IsInvalidGroup(pGroupEntry->gid) )
  375. {
  376. if( pGroupEntry->llDiskUsage >= -llDelta )
  377. {
  378. pGroupEntry->llDiskUsage += llDelta;
  379. }
  380. else
  381. {
  382. INET_ASSERT(FALSE); // underflow
  383. pGroupEntry->llDiskUsage = 0;
  384. }
  385. }
  386. }
  387. VOID NotifyCacheChange(DWORD dwOpcode, DWORD dwHOffset)
  388. {
  389. //
  390. // the caller of this method has container locked, so there
  391. // no need to call (Un)LockContain here.
  392. //
  393. DWORD dwFilter = 0;
  394. _UrlObjStorage->GetHeaderData(
  395. CACHE_HEADER_DATA_NOTIFICATION_FILTER, &dwFilter);
  396. if( dwFilter & dwOpcode )
  397. {
  398. DWORD dwHWnd = 0;
  399. DWORD dwUMsg = 0;
  400. _UrlObjStorage->GetHeaderData(
  401. CACHE_HEADER_DATA_NOTIFICATION_HWND, &dwHWnd);
  402. _UrlObjStorage->GetHeaderData(
  403. CACHE_HEADER_DATA_NOTIFICATION_MESG, &dwUMsg);
  404. if( dwHWnd && dwUMsg && IsWindow((HWND)DWORD_PTR(dwHWnd)) )
  405. {
  406. // NOTE: we will not check for msg q overflow
  407. PostMessage(
  408. (HWND)DWORD_PTR(dwHWnd),
  409. (UINT)dwUMsg,
  410. (WPARAM)dwOpcode,
  411. (LPARAM)dwHOffset
  412. );
  413. }
  414. }
  415. }
  416. BOOL IsUrlEntryExemptFromScavenging
  417. (
  418. HASH_ITEM* pItem,
  419. URL_FILEMAP_ENTRY* pEntry,
  420. DWORD dwFilter,
  421. LONGLONG qwGmtTime,
  422. GroupMgr* pgm
  423. );
  424. BOOL ScavengeItem (HASH_ITEM* pItem, BOOL* pfMustUnlock);
  425. void ScavengerDebugSpew (SCORE_ITEM*, LONGLONG*);
  426. friend class GroupMgr;
  427. };