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.

671 lines
13 KiB

  1. #ifndef _FILECACHE_HXX_
  2. #define _FILECACHE_HXX_
  3. #include "datetime.hxx"
  4. #include "usercache.hxx"
  5. //
  6. // Users of the file cache can associate (1) object with a cache entry which
  7. // will get cleaned up (by calling the Cleanup() method) when the object
  8. // is flushed
  9. //
  10. class ASSOCIATED_FILE_OBJECT
  11. {
  12. public:
  13. virtual
  14. VOID
  15. Cleanup(
  16. VOID
  17. ) = 0;
  18. };
  19. class W3_FILE_INFO_KEY : public CACHE_KEY
  20. {
  21. public:
  22. W3_FILE_INFO_KEY()
  23. : _strFileKey( _achFileKey, sizeof( _achFileKey ) ),
  24. _pszFileKey( NULL ),
  25. _cchFileKey( 0 )
  26. {
  27. }
  28. virtual ~W3_FILE_INFO_KEY()
  29. {
  30. }
  31. WCHAR *
  32. QueryHintKey(
  33. VOID
  34. )
  35. {
  36. return _pszFileKey;
  37. }
  38. HRESULT
  39. CreateCacheKey(
  40. WCHAR * pszFileKey,
  41. DWORD cchFileKey,
  42. BOOL fCopy
  43. );
  44. DWORD
  45. QueryKeyHash(
  46. VOID
  47. ) const
  48. {
  49. return HashString( _pszFileKey );
  50. }
  51. BOOL
  52. QueryIsEqual(
  53. const CACHE_KEY * pCacheCompareKey
  54. ) const
  55. {
  56. W3_FILE_INFO_KEY * pFileKey = (W3_FILE_INFO_KEY*) pCacheCompareKey;
  57. return _cchFileKey == pFileKey->_cchFileKey &&
  58. !wcscmp( _pszFileKey, pFileKey->_pszFileKey );
  59. }
  60. WCHAR _achFileKey[ 64 ];
  61. STRU _strFileKey;
  62. WCHAR * _pszFileKey;
  63. DWORD _cchFileKey;
  64. };
  65. // The maximum length of an ETag is 16 chars for the last modified time plus
  66. // one char for the colon plus 2 chars for the quotes plus 8 chars for the
  67. // system change notification number plus two for the optional prefix W/ and
  68. // one for the trailing NULL, for a total of 30 chars.
  69. #define MAX_ETAG_BUFFER_LENGTH 30
  70. //
  71. // Embedded security descriptor used for cache hits
  72. //
  73. #define SECURITY_DESC_DEFAULT_SIZE 256
  74. class W3_FILE_INFO;
  75. //
  76. // The context used for async file reads
  77. //
  78. typedef VOID (* W3_CACHE_CALLBACK_FUNCTION)(PVOID pContext,
  79. HRESULT hr);
  80. typedef struct
  81. {
  82. //
  83. // Callback function to be notified
  84. //
  85. W3_CACHE_CALLBACK_FUNCTION pfnCallback;
  86. //
  87. // Overlapped for async file read
  88. //
  89. OVERLAPPED Overlapped;
  90. //
  91. // The file-info for which this async IO is being done
  92. //
  93. W3_FILE_INFO *pFileInfo;
  94. } FILE_CACHE_ASYNC_CONTEXT;
  95. //
  96. // File cache entry object
  97. //
  98. #define W3_FILE_INFO_SIGNATURE ((DWORD)'IF3W')
  99. #define W3_FILE_INFO_SIGNATURE_FREE ((DWORD)'if3w')
  100. class W3_FILE_INFO : public CACHE_ENTRY
  101. {
  102. public:
  103. W3_FILE_INFO( OBJECT_CACHE * pObjectCache )
  104. : CACHE_ENTRY( pObjectCache ),
  105. _hFile( INVALID_HANDLE_VALUE ),
  106. _pFileBuffer( NULL ),
  107. _dwFileAttributes( 0 ),
  108. _nFileSizeLow( 0 ),
  109. _nFileSizeHigh( 0 ),
  110. _bufSecDesc( _abSecDesc, sizeof( _abSecDesc ) ),
  111. _cchETag( 0 ),
  112. _pAssociatedObject( NULL ),
  113. _pLastSid( NULL ),
  114. _fUlCacheAllowed( FALSE ),
  115. _msLastAttributeCheckTime( 0 )
  116. {
  117. _dwSignature = W3_FILE_INFO_SIGNATURE;
  118. }
  119. virtual ~W3_FILE_INFO(
  120. VOID
  121. );
  122. VOID *
  123. operator new(
  124. #if DBG
  125. size_t size
  126. #else
  127. size_t
  128. #endif
  129. )
  130. {
  131. DBG_ASSERT( size == sizeof( W3_FILE_INFO ) );
  132. DBG_ASSERT( sm_pachW3FileInfo != NULL );
  133. return sm_pachW3FileInfo->Alloc();
  134. }
  135. VOID
  136. operator delete(
  137. VOID * pW3FileInfo
  138. )
  139. {
  140. DBG_ASSERT( pW3FileInfo != NULL );
  141. DBG_ASSERT( sm_pachW3FileInfo != NULL );
  142. DBG_REQUIRE( sm_pachW3FileInfo->Free( pW3FileInfo ) );
  143. }
  144. CACHE_KEY *
  145. QueryCacheKey(
  146. VOID
  147. ) const
  148. {
  149. return (CACHE_KEY*) &_cacheKey;
  150. }
  151. BOOL
  152. QueryIsOkToFlushDirmon(
  153. WCHAR * pszPath,
  154. DWORD cchPath
  155. );
  156. BOOL
  157. CheckSignature(
  158. VOID
  159. ) const
  160. {
  161. return _dwSignature == W3_FILE_INFO_SIGNATURE;
  162. }
  163. virtual
  164. BOOL
  165. Checkout(
  166. CACHE_USER *pOpeningUser
  167. );
  168. HRESULT
  169. GetFileHandle(
  170. HANDLE * phHandle
  171. );
  172. PBYTE
  173. QueryFileBuffer(
  174. VOID
  175. ) const
  176. {
  177. return _pFileBuffer;
  178. }
  179. VOID
  180. QuerySize(
  181. ULARGE_INTEGER * pliSize
  182. ) const
  183. {
  184. DBG_ASSERT( pliSize != NULL );
  185. pliSize->LowPart = _nFileSizeLow;
  186. pliSize->HighPart = _nFileSizeHigh;
  187. }
  188. WCHAR *
  189. QueryPhysicalPath(
  190. VOID
  191. )
  192. {
  193. return _cacheKey._pszFileKey;
  194. }
  195. DWORD
  196. QueryAttributes(
  197. VOID
  198. ) const
  199. {
  200. return _dwFileAttributes;
  201. }
  202. PSECURITY_DESCRIPTOR
  203. QuerySecDesc(
  204. VOID
  205. );
  206. PSID
  207. QueryLastSid(
  208. VOID
  209. )
  210. {
  211. return _pLastSid;
  212. }
  213. VOID
  214. QueryLastWriteTime(
  215. FILETIME * pFileTime
  216. ) const
  217. {
  218. DBG_ASSERT( pFileTime != NULL );
  219. memcpy( pFileTime,
  220. &_CastratedLastWriteTime,
  221. sizeof( *pFileTime ) );
  222. }
  223. CHAR *
  224. QueryLastModifiedString(
  225. VOID
  226. )
  227. {
  228. return _achLastModified;
  229. }
  230. BOOL
  231. QueryIsWeakETag(
  232. VOID
  233. ) const
  234. {
  235. return _achETag[ 0 ] == 'W' && _achETag[ 1 ] == '/';
  236. }
  237. HANDLE
  238. QueryFileHandle(
  239. VOID
  240. )
  241. {
  242. return _hFile;
  243. }
  244. CHAR *
  245. QueryETag(
  246. VOID
  247. )
  248. {
  249. return _achETag;
  250. }
  251. USHORT
  252. QueryETagSize(
  253. VOID
  254. ) const
  255. {
  256. return _cchETag;
  257. }
  258. DWORD
  259. QueryLastAttributeCheckTime(
  260. VOID
  261. ) const
  262. {
  263. return _msLastAttributeCheckTime;
  264. }
  265. dllexp
  266. BOOL
  267. SetAssociatedObject(
  268. ASSOCIATED_FILE_OBJECT * pObject
  269. );
  270. ASSOCIATED_FILE_OBJECT *
  271. QueryAssociatedObject(
  272. VOID
  273. )
  274. {
  275. return _pAssociatedObject;
  276. }
  277. HRESULT
  278. OpenFile(
  279. STRU & strFileName,
  280. CACHE_USER * pOpeningUser,
  281. BOOL fBufferFile
  282. );
  283. HRESULT
  284. DoAccessCheck(
  285. CACHE_USER * pOpeningUser
  286. );
  287. HRESULT
  288. MakeCacheable(
  289. CACHE_USER * pOpeningUser,
  290. FILE_CACHE_ASYNC_CONTEXT *pAsyncContext,
  291. BOOL *pfHandledSync,
  292. BOOL fCheckForExistenceOnly
  293. );
  294. VOID
  295. AllowUlCache(
  296. VOID
  297. )
  298. {
  299. _fUlCacheAllowed = TRUE;
  300. }
  301. BOOL
  302. QueryUlCacheAllowed(
  303. VOID
  304. ) const
  305. {
  306. return _fUlCacheAllowed;
  307. }
  308. BOOL
  309. IsUlCacheable(
  310. VOID
  311. ) const;
  312. BOOL
  313. IsCacheable(
  314. VOID
  315. ) const;
  316. HRESULT
  317. CheckIfFileHasChanged(
  318. BOOL * pfHasChanged,
  319. CACHE_USER * pOpeningUser
  320. );
  321. static
  322. HRESULT
  323. Initialize(
  324. VOID
  325. );
  326. static
  327. VOID
  328. Terminate(
  329. VOID
  330. );
  331. static
  332. VOID
  333. CALLBACK
  334. FileReadCompletion(
  335. DWORD dwErrorCode,
  336. DWORD dwNumberOfBytesTransfered,
  337. LPOVERLAPPED lpOverlapped);
  338. private:
  339. W3_FILE_INFO(const W3_FILE_INFO &);
  340. void operator=(const W3_FILE_INFO &);
  341. HRESULT
  342. ReadSecurityDescriptor(
  343. VOID
  344. );
  345. HRESULT
  346. GenerateETag(
  347. VOID
  348. );
  349. HRESULT
  350. GenerateLastModifiedTimeString(
  351. VOID
  352. );
  353. DWORD _dwSignature;
  354. W3_FILE_INFO_KEY _cacheKey;
  355. //
  356. // File info data
  357. //
  358. HANDLE _hFile;
  359. PBYTE _pFileBuffer;
  360. FILETIME _ftLastWriteTime;
  361. FILETIME _CastratedLastWriteTime;
  362. DWORD _dwFileAttributes;
  363. ULONG _nFileSizeLow;
  364. ULONG _nFileSizeHigh;
  365. //
  366. // Security descriptor stuff
  367. //
  368. BYTE _abSecDesc[ SECURITY_DESC_DEFAULT_SIZE ];
  369. BUFFER _bufSecDesc;
  370. //
  371. // ETag
  372. //
  373. CHAR _achETag[ MAX_ETAG_BUFFER_LENGTH ];
  374. USHORT _cchETag;
  375. //
  376. // Last modified time
  377. //
  378. CHAR _achLastModified[ GMT_STRING_SIZE ];
  379. //
  380. // Last SID to access the file
  381. //
  382. BYTE _abLastSid[ 64 ];
  383. PSID _pLastSid;
  384. //
  385. // UL cache status
  386. //
  387. BOOL _fUlCacheAllowed;
  388. //
  389. // Associated object (only one is allowed)
  390. //
  391. ASSOCIATED_FILE_OBJECT* _pAssociatedObject;
  392. //
  393. // TickCount since file was last checked for change
  394. //
  395. DWORD _msLastAttributeCheckTime;
  396. //
  397. // Lookaside
  398. //
  399. static ALLOC_CACHE_HANDLER * sm_pachW3FileInfo;
  400. };
  401. //
  402. // The file cache itself
  403. //
  404. #define DEFAULT_FILE_SIZE_THRESHOLD (256*1024)
  405. #define DEFAULT_FILE_ATTRIBUTE_CHECK_THRESHOLD (5) // in seconds
  406. #define DEFAULT_W3_FILE_INFO_CACHE_TTL (30)
  407. #define DEFAULT_W3_FILE_INFO_CACHE_ACTIVITY (10)
  408. class W3_FILE_INFO_CACHE : public OBJECT_CACHE
  409. {
  410. public:
  411. W3_FILE_INFO_CACHE();
  412. virtual ~W3_FILE_INFO_CACHE();
  413. dllexp
  414. HRESULT
  415. GetFileInfo(
  416. STRU & strFileName,
  417. DIRMON_CONFIG * pDirmonConfig,
  418. CACHE_USER * pOpeningUser,
  419. BOOL fDoCache,
  420. W3_FILE_INFO ** ppFileInfo,
  421. FILE_CACHE_ASYNC_CONTEXT *pAsyncContext = NULL,
  422. BOOL *pfHandledSync = NULL,
  423. BOOL fAllowNoBuffering = FALSE,
  424. BOOL fCheckForExistanceOnly = FALSE
  425. );
  426. WCHAR *
  427. QueryName(
  428. VOID
  429. ) const
  430. {
  431. return L"W3_FILE_INFO_CACHE";
  432. }
  433. HRESULT
  434. ReadFileIntoMemoryCache(
  435. HANDLE hFile,
  436. DWORD cbFile,
  437. VOID ** ppvFileBuffer,
  438. FILE_CACHE_ASYNC_CONTEXT *pAsyncContext,
  439. BOOL *pfHandledSync
  440. );
  441. HRESULT
  442. ReleaseFromMemoryCache(
  443. VOID * pFileBuffer,
  444. DWORD cbFileBuffer
  445. );
  446. VOID
  447. DoDirmonInvalidationSpecific(
  448. WCHAR * pszPath
  449. );
  450. ULONGLONG
  451. QueryFileSizeThreshold(
  452. VOID
  453. ) const
  454. {
  455. return _cbFileSizeThreshold;
  456. }
  457. DWORD
  458. QueryFileAttributeCheckThreshold(
  459. VOID
  460. ) const
  461. {
  462. return _cmsecFileAttributeCheckThreshold;
  463. }
  464. BOOL
  465. QueryCacheEnabled(
  466. VOID
  467. ) const
  468. {
  469. return _fEnableCache;
  470. }
  471. BOOL
  472. QueryElementLimitExceeded(
  473. VOID
  474. )
  475. {
  476. return _cMaxFileEntries && _cMaxFileEntries <= PerfQueryCurrentEntryCount();
  477. }
  478. ULONGLONG
  479. PerfQueryCurrentMemCacheSize(
  480. VOID
  481. ) const
  482. {
  483. return _cbMemCacheCurrentSize;
  484. }
  485. ULONGLONG
  486. PerfQueryMaxMemCacheSize(
  487. VOID
  488. ) const
  489. {
  490. return _cbMaxMemCacheSize;
  491. }
  492. HRESULT
  493. Initialize(
  494. VOID
  495. );
  496. VOID
  497. Terminate(
  498. VOID
  499. );
  500. dllexp
  501. static
  502. W3_FILE_INFO_CACHE *
  503. GetFileCache(
  504. VOID
  505. );
  506. BOOL
  507. QueryDoDirmonForUnc()
  508. {
  509. return _fDoDirmonForUnc;
  510. }
  511. private:
  512. W3_FILE_INFO_CACHE(const W3_FILE_INFO_CACHE &);
  513. void operator=(const W3_FILE_INFO_CACHE &);
  514. HRESULT
  515. InitializeMemoryCache(
  516. VOID
  517. );
  518. VOID
  519. TerminateMemoryCache(
  520. VOID
  521. );
  522. static
  523. VOID
  524. MemoryCacheAdjustor(
  525. PVOID pFileCache,
  526. BOOLEAN TimerOrWaitFired
  527. );
  528. ULONGLONG _cbFileSizeThreshold;
  529. ULONGLONG _cbMemoryCacheSize;
  530. DWORD _cMaxFileEntries;
  531. BOOL _fEnableCache;
  532. //
  533. // Memcache stuff
  534. //
  535. CRITICAL_SECTION _csMemCache;
  536. ULONGLONG _cbMemCacheLimit;
  537. ULONGLONG _cbMemCacheCurrentSize;
  538. ULONGLONG _cbMaxMemCacheSize;
  539. HANDLE _hMemCacheHeap;
  540. HANDLE _hTimer;
  541. //
  542. // Do we do dirmonitoring for UNC files?
  543. //
  544. BOOL _fDoDirmonForUnc;
  545. //
  546. // Threshold for attribute checking
  547. //
  548. DWORD _cmsecFileAttributeCheckThreshold;
  549. };
  550. #endif