Source code of Windows XP (NT5)
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.

674 lines
16 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. tsunamip.hxx
  5. Abstract:
  6. This module defines private structures and functions for
  7. tsunami module
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 13-Jan-1995
  10. Project:
  11. Tsuanmi Library ( caching and logging module for InternetServices)
  12. Revision History:
  13. MuraliK 20-Feb-1995 Added File System Types.
  14. MuraliK 22-Jan-1996 Cache UNC Impersonation Token
  15. --*/
  16. #ifndef _TSUNAMIP_HXX_
  17. #define _TSUNAMIP_HXX_
  18. /************************************************************
  19. * Include Headers
  20. ************************************************************/
  21. # if defined ( __cplusplus)
  22. extern "C" {
  23. # endif
  24. #include <nt.h>
  25. #include <ntrtl.h>
  26. #include <nturtl.h>
  27. #include <windows.h>
  28. #include <basetyps.h>
  29. #include <lmcons.h>
  30. # if defined ( __cplusplus)
  31. }
  32. # endif
  33. #include <inetinfo.h>
  34. #include "iperfctr.hxx"
  35. #include <refb.hxx>
  36. #include "dbgutil.h"
  37. #include <iistypes.hxx>
  38. #include <tsvroot.hxx>
  39. #include <tsunami.hxx>
  40. #include <reftrace.h>
  41. #include "tsmemp.hxx"
  42. #include "globals.hxx"
  43. #include "dbgmacro.hxx"
  44. //
  45. // Setting TSUNAMI_REF_DEBUG to a non-zero value will enable reference
  46. // count logging.
  47. //
  48. #if DBG
  49. #define TSUNAMI_REF_DEBUG 1
  50. #else // !DBG
  51. #define TSUNAMI_REF_DEBUG 0
  52. #endif // DBG
  53. //
  54. // Tracing support.
  55. //
  56. #if TSUNAMI_REF_DEBUG
  57. extern PTRACE_LOG RefTraceLog;
  58. #define TSUNAMI_TRACE( refcount, context ) \
  59. if( RefTraceLog != NULL ) { \
  60. WriteRefTraceLog( \
  61. RefTraceLog, \
  62. (refcount), \
  63. (context) \
  64. ); \
  65. } else
  66. #else // !TSUNAMI_REF_DEBUG
  67. #define TSUNAMI_TRACE( refcount, context )
  68. #endif // TSUNAMI_REF_DEBUG
  69. //
  70. // Special values passed as a "refcount" for interesting events
  71. // that really have nothing to do with refcounts.
  72. //
  73. #define TRACE_CACHE_DECACHE -1000
  74. #define TRACE_CACHE_REMOVE -1001
  75. #define TRACE_OPENFILE_CREATE -2000
  76. #define TRACE_OPENFILE_REFERENCE -2001
  77. #define TRACE_OPENFILE_CLOSE -2002
  78. #define TRACE_PHYS_CREATE -3000
  79. #define TRACE_PHYS_REMOVE -3001
  80. #define TRACE_PHYS_DISPOSE -3002
  81. /************************************************************
  82. * Type Definitions
  83. ************************************************************/
  84. struct _CACHE_OBJECT;
  85. //
  86. // Memory allocation related structures
  87. //
  88. //
  89. // SomeDay the BLOB_HEADER should be the base class for all items that are
  90. // cached. - MuraliK 3/10/97
  91. //
  92. typedef struct {
  93. BOOL IsCached;
  94. struct _CACHE_OBJECT * pCache;
  95. LIST_ENTRY PFList;
  96. PUSER_FREE_ROUTINE pfnFreeRoutine;
  97. } BLOB_HEADER, * PBLOB_HEADER;
  98. #define BLOB_IS_OR_WAS_CACHED( pvBlob ) \
  99. ( (((PBLOB_HEADER)pvBlob)-1)->IsCached )
  100. #define BLOB_IS_EJECTATE( pvBlob ) \
  101. ( IsListEmpty(&(((PBLOB_HEADER)pvBlob)-1)->pCache->BinList) )
  102. #define BLOB_IS_OR_WAS_CACHED( pvBlob ) \
  103. ( (((PBLOB_HEADER)pvBlob)-1)->IsCached )
  104. #define BLOB_IS_EJECTATE( pvBlob ) \
  105. ( IsListEmpty(&(((PBLOB_HEADER)pvBlob)-1)->pCache->BinList) )
  106. #define BLOB_GET_SVC_ID( pvBlob ) \
  107. ( (((PBLOB_HEADER)pvBlob)-1)->pCache->dwService )
  108. #define BLOB_IS_UNC( pvBlob ) \
  109. ( (((PBLOB_HEADER)pvBlob)-1)->pCache->szPath[1] == '\\' )
  110. #define STRONG_ETAG_DELTA 30000000
  111. #define FORMAT_ETAG(buffer, time, mdchange) \
  112. sprintf((buffer), "\"%x%x%x%x%x%x%x%x:%x\"", \
  113. (DWORD)(((PUCHAR)&(time))[0]), \
  114. (DWORD)(((PUCHAR)&(time))[1]), \
  115. (DWORD)(((PUCHAR)&(time))[2]), \
  116. (DWORD)(((PUCHAR)&(time))[3]), \
  117. (DWORD)(((PUCHAR)&(time))[4]), \
  118. (DWORD)(((PUCHAR)&(time))[5]), \
  119. (DWORD)(((PUCHAR)&(time))[6]), \
  120. (DWORD)(((PUCHAR)&(time))[7]), \
  121. (mdchange) \
  122. );
  123. // Cache Related Private Structures
  124. //
  125. typedef DWORD HASH_TYPE;
  126. typedef struct _CACHE_OBJECT {
  127. DWORD Signature;
  128. HASH_TYPE hash;
  129. ULONG cchLength;
  130. ULONG iDemux;
  131. DWORD dwService;
  132. DWORD dwInstance;
  133. LIST_ENTRY BinList;
  134. LIST_ENTRY MruList;
  135. LIST_ENTRY DirChangeList;
  136. PBLOB_HEADER pbhBlob;
  137. ULONG references;
  138. DWORD TTL;
  139. PSECURITY_DESCRIPTOR pSecDesc;
  140. HANDLE hLastSuccessAccessToken;
  141. CHAR szPath[ 1 ];
  142. } CACHE_OBJECT, *PCACHE_OBJECT;
  143. //
  144. // HASH_TO_BIN can return a range of 0 to HASH_VALUE (inclusive)
  145. //
  146. #define HASH_VALUE 223
  147. #define HASH_TO_BIN( hash ) ( ((hash)%(HASH_VALUE)))
  148. #define MAX_BINS (HASH_VALUE+1)
  149. #define CACHE_OBJ_SIGNATURE ((DWORD)'HCAC')
  150. #define CACHE_OBJ_SIGNATURE_X ((DWORD)'cacX')
  151. #define REFERENCE_CACHE_OBJ( pcache ) \
  152. (pfnInterlockedIncrement)( (LPLONG)&((pcache)->references) )
  153. #define DEREFERENCE_CACHE_OBJ( pcache ) \
  154. (pfnInterlockedDecrement)( (LPLONG)&((pcache)->references) )
  155. typedef struct _OPLOCK_OBJECT {
  156. DWORD Signature;
  157. PPHYS_OPEN_FILE_INFO lpPFInfo;
  158. HANDLE hOplockInitComplete;
  159. } OPLOCK_OBJECT, *POPLOCK_OBJECT;
  160. #define OPLOCK_OBJ_SIGNATURE ((DWORD)'KLPO')
  161. #define OPLOCK_OBJ_SIGNATURE_X ((DWORD)'lpoX')
  162. //
  163. // bogus win95 handle
  164. //
  165. #define BOGUS_WIN95_DIR_HANDLE ((HANDLE)0x88888888)
  166. //
  167. // This is the maximum number of UNC file handles to cache. The SMB
  168. // protocol limits the server to 2048 open files per client. Currently,
  169. // this count includes *all* UNC connections regardles of the remote
  170. // server
  171. //
  172. #define MAX_CACHED_UNC_HANDLES 1200
  173. typedef struct {
  174. CRITICAL_SECTION CriticalSection;
  175. LIST_ENTRY Items[ MAX_BINS ];
  176. LIST_ENTRY MruList;
  177. ULONG OpenFileInUse;
  178. ULONG MaxOpenFileInUse;
  179. } CACHE_TABLE, *PCACHE_TABLE;
  180. extern CACHE_TABLE CacheTable;
  181. extern DWORD cCachedUNCHandles;
  182. //
  183. // Disables Tsunami Caching
  184. //
  185. extern BOOL DisableTsunamiCaching;
  186. //
  187. // Disables SPUD
  188. //
  189. extern BOOL DisableSPUD;
  190. //
  191. // Allows us to mask the invalid flags
  192. //
  193. extern DWORD TsValidCreateFileOptions;
  194. //
  195. // flags for create file
  196. //
  197. extern BOOL TsNoDirOpenSupport;
  198. extern DWORD TsCreateFileFlags;
  199. extern DWORD TsCreateFileShareMode;
  200. //
  201. // function prototypes
  202. //
  203. BOOL
  204. Cache_Initialize(
  205. IN DWORD MaxOpenFile
  206. );
  207. BOOL
  208. MetaCache_Initialize(
  209. VOID
  210. );
  211. BOOL
  212. MetaCache_Terminate(
  213. VOID
  214. );
  215. HASH_TYPE
  216. CalculateHashAndLengthOfPathName(
  217. LPCSTR pszPathName,
  218. PULONG pcbLength
  219. );
  220. BOOL
  221. DeCache(
  222. PCACHE_OBJECT pCacheObject,
  223. BOOL fLockCacheTable = TRUE
  224. );
  225. VOID
  226. TsDereferenceCacheObj(
  227. PCACHE_OBJECT pCacheObject,
  228. BOOL fLockCacheTable
  229. );
  230. BOOL
  231. TsCheckOutCachedPhysFile(
  232. IN const TSVC_CACHE &TSvcCache,
  233. IN PCSTR pszDirectoryName,
  234. IN PVOID * ppvBlob
  235. );
  236. VOID
  237. InsertHeadPhysFile(
  238. IN PPHYS_OPEN_FILE_INFO lpPFInfo,
  239. IN PVOID pvBlob
  240. );
  241. //
  242. // This function converts a service ID into an index for statistics
  243. // gathering
  244. //
  245. inline
  246. DWORD
  247. MaskIndex( DWORD dwService )
  248. {
  249. if ( dwService > 0 && dwService <= LAST_PERF_CTR_SVC )
  250. return dwService - 1;
  251. else
  252. return CACHE_STATS_UNUSED_INDEX;
  253. }
  254. #define INC_COUNTER( dwServiceId, CounterName ) \
  255. IP_INCREMENT_COUNTER( Configuration.Stats[MaskIndex(dwServiceId)].CounterName )
  256. #define DEC_COUNTER( dwServiceId, CounterName ) \
  257. IP_DECREMENT_COUNTER( Configuration.Stats[MaskIndex(dwServiceId)].CounterName )
  258. #define SET_COUNTER( dwServiceId, CounterName, Val ) \
  259. IP_SET_COUNTER( Configuration.Stats[MaskIndex(dwServiceId)].CounterName, Val )
  260. //
  261. // Open File Handles related functions
  262. //
  263. BOOL DisposeOpenFileInfo( PVOID pvOldBlock );
  264. BOOL DisposePhysOpenFileInfo( PVOID pvOldBlock );
  265. //
  266. // Virtual roots related data and structures.
  267. //
  268. extern LIST_ENTRY GlobalVRootList;
  269. extern CRITICAL_SECTION csVirtualRoots;
  270. extern HANDLE g_hNewItem;
  271. extern HANDLE g_hQuit;
  272. typedef struct {
  273. DWORD Signature;
  274. LONG cRef;
  275. LIST_ENTRY TableListEntry;
  276. LIST_ENTRY GlobalListEntry;
  277. BOOLEAN fDeleted; // Waiting for the APC to
  278. // complete before freeing
  279. BOOLEAN fCachingAllowed;
  280. BOOLEAN fUNC;
  281. DWORD dwServiceID;
  282. DWORD dwInstanceID;
  283. DWORD dwFileSystem;
  284. DWORD dwAccessMask;
  285. HANDLE hImpersonationToken;
  286. DWORD cchRootA;
  287. DWORD cchDirectoryA;
  288. CHAR pszRootA[ MAX_LENGTH_VIRTUAL_ROOT + 1 ];
  289. CHAR pszDirectoryA[ MAX_PATH + 1 ];
  290. CHAR pszAccountName[ UNLEN + 1 ];
  291. } VIRTUAL_ROOT_MAPPING, *PVIRTUAL_ROOT_MAPPING;
  292. #define VIRT_ROOT_SIGNATURE 0x544F4F52 // 'ROOT'
  293. VOID
  294. DereferenceRootMapping(
  295. IN OUT VIRTUAL_ROOT_MAPPING * pVrm
  296. );
  297. //
  298. // Directory Change Manager Functions
  299. //
  300. extern HANDLE g_hChangeWaitThread;
  301. DWORD
  302. WINAPI
  303. ChangeWaitThread(
  304. PVOID pvParam
  305. );
  306. typedef struct {
  307. HANDLE hDirectoryFile;
  308. BOOL fOnSystemNotifyList;
  309. // Handle been added to Notify Change Dir?
  310. LIST_ENTRY listCacheObjects;
  311. HANDLE hEventCompletion; // Completion event handle
  312. OVERLAPPED Overlapped;
  313. FILE_NOTIFY_INFORMATION NotifyInfo;
  314. WCHAR szPathNameBuffer[ sizeof(FILE_NOTIFY_INFORMATION)*2 + MAX_PATH*2 ];
  315. } DIRECTORY_CACHING_INFO, *PDIRECTORY_CACHING_INFO;
  316. //
  317. // Use this macro to close the hDirectoryFile member of the above structure
  318. //
  319. #define CLOSE_DIRECTORY_HANDLE( pDCI ) \
  320. { HANDLE __hTemp = (HANDLE) InterlockedExchange( (LPLONG) &pDCI->hDirectoryFile, NULL ); \
  321. if ( __hTemp && __hTemp != INVALID_HANDLE_VALUE ) \
  322. DBG_REQUIRE( CloseHandle( __hTemp )); \
  323. }
  324. BOOL
  325. DcmInitialize(
  326. VOID
  327. );
  328. BOOL
  329. DcmAddNewItem(
  330. IN PIIS_SERVER_INSTANCE pInstance,
  331. IN PCHAR pszFileName,
  332. PCACHE_OBJECT pCacheObject
  333. );
  334. VOID
  335. DcmRemoveItem(
  336. PCACHE_OBJECT pCacheObject
  337. );
  338. BOOL
  339. DcmAddRoot(
  340. PVIRTUAL_ROOT_MAPPING pVrm
  341. );
  342. VOID
  343. DcmRemoveRoot(
  344. PVIRTUAL_ROOT_MAPPING pVrm
  345. );
  346. BOOL
  347. TsDecacheVroot(
  348. DIRECTORY_CACHING_INFO * pDci
  349. );
  350. //
  351. // Directory Listing related objects and functions
  352. //
  353. # define MAX_DIR_ENTRIES_PER_BLOCK (25)
  354. typedef struct _TS_DIR_BUFFERS {
  355. LIST_ENTRY listEntry;
  356. int nEntries;
  357. WIN32_FIND_DATA rgFindData[MAX_DIR_ENTRIES_PER_BLOCK];
  358. } TS_DIR_BUFFERS, * PTS_DIR_BUFFERS;
  359. class TS_DIRECTORY_HEADER {
  360. public:
  361. TS_DIRECTORY_HEADER( VOID)
  362. : m_hListingUser ( INVALID_HANDLE_VALUE),
  363. m_nEntries ( 0),
  364. m_ppFileInfo ( NULL)
  365. { InitializeListHead( & m_listDirectoryBuffers); }
  366. ~TS_DIRECTORY_HEADER( VOID) {}
  367. BOOL
  368. IsValid( VOID) const
  369. { return ( TRUE); }
  370. int
  371. QueryNumEntries( VOID) const
  372. { return ( m_nEntries); }
  373. HANDLE
  374. QueryListingUser( VOID) const
  375. { return ( m_hListingUser); }
  376. const PWIN32_FIND_DATA *
  377. QueryArrayOfFileInfoPointers(VOID) const
  378. { return ( m_ppFileInfo); }
  379. PLIST_ENTRY
  380. QueryDirBuffersListEntry( VOID)
  381. { return ( & m_listDirectoryBuffers); }
  382. VOID
  383. ReInitialize( VOID)
  384. {
  385. //
  386. // this function provided to initialize, when we allocate using
  387. // malloc or GlobalAlloc()
  388. m_hListingUser = INVALID_HANDLE_VALUE;
  389. m_nEntries = 0;
  390. m_ppFileInfo = NULL;
  391. InitializeListHead( &m_listDirectoryBuffers);
  392. }
  393. VOID
  394. SetListingUser( IN HANDLE hListingUser)
  395. { m_hListingUser = hListingUser; }
  396. VOID
  397. IncrementDirEntries( VOID)
  398. { m_nEntries++; }
  399. VOID
  400. InsertBufferInTail( IN PLIST_ENTRY pEntry)
  401. { InsertTailList( &m_listDirectoryBuffers, pEntry); }
  402. VOID
  403. CleanupThis( VOID);
  404. BOOL
  405. ReadWin32DirListing(IN LPCSTR pszDirectoryName,
  406. IN OUT DWORD * pcbMemUsed );
  407. BOOL
  408. BuildFileInfoPointers( IN OUT DWORD * pcbMemUsed );
  409. # if DBG
  410. VOID Print( VOID) const;
  411. #else
  412. VOID Print( VOID) const
  413. { ; }
  414. # endif // DBG
  415. private:
  416. HANDLE m_hListingUser;
  417. int m_nEntries;
  418. // contains array of pointers indirected into buffers in m_listDirBuffers
  419. PWIN32_FIND_DATA * m_ppFileInfo;
  420. LIST_ENTRY m_listDirectoryBuffers; // ptr to DIR_BUFFERS
  421. }; // class TS_DIRECTORY_HEADER
  422. typedef TS_DIRECTORY_HEADER * PTS_DIRECTORY_HEADER;
  423. //
  424. // Virtual roots and directories always have their trailing slashes
  425. // stripped. This macro is used disambiguate the "/root1/" from "/root/"
  426. // case where "/root/" is an existing root (i.e., matching prefix).
  427. //
  428. extern BOOL
  429. IsCharTermA(
  430. IN LPCSTR lpszString,
  431. IN INT cch
  432. );
  433. #define IS_CHAR_TERM_A( psz, cch ) IsCharTermA(psz,cch)
  434. extern
  435. dllexp
  436. BOOL
  437. TsGetDirectoryListing(
  438. IN const TSVC_CACHE &TSvcCache,
  439. IN PCSTR pszDirectoryName,
  440. IN HANDLE ListingUser,
  441. OUT PTS_DIRECTORY_HEADER* ppDirectoryHeader
  442. );
  443. extern
  444. dllexp
  445. BOOL
  446. TsFreeDirectoryListing
  447. (
  448. IN const TSVC_CACHE & TSvcCache,
  449. IN OUT PTS_DIRECTORY_HEADER pTsDirectoryHeader
  450. );
  451. extern
  452. BOOL
  453. SortInPlaceFileInfoPointers(
  454. IN OUT PWIN32_FIND_DATA * prgFileInfo,
  455. IN int nFiles,
  456. IN PFN_CMP_WIN32_FIND_DATA pfnCompare
  457. );
  458. extern
  459. BOOL
  460. RegExpressionMatch( IN LPCSTR pszName, IN LPCSTR pszRegExp);
  461. //
  462. // Little helper function for taking a cache object off the relevant lists
  463. // The return code indicates if the cache object was on any lists indicating
  464. // it hadn't been decached yet.
  465. //
  466. inline
  467. BOOL
  468. RemoveCacheObjFromLists(
  469. PCACHE_OBJECT pCacheObject,
  470. BOOL fLockCacheTable
  471. )
  472. {
  473. BOOL fOnLists = TRUE;
  474. if ( fLockCacheTable ) {
  475. EnterCriticalSection( &CacheTable.CriticalSection );
  476. }
  477. //
  478. // Remove the cache object from the cache table list, if it hasn't
  479. // already been so removed.
  480. //
  481. if ( !IsListEmpty( &pCacheObject->BinList ) ) {
  482. TSUNAMI_TRACE( TRACE_CACHE_REMOVE, pCacheObject );
  483. RemoveEntryList( &pCacheObject->BinList );
  484. InitializeListHead( &pCacheObject->BinList );
  485. RemoveEntryList( &pCacheObject->MruList );
  486. InitializeListHead( &pCacheObject->MruList );
  487. if (pCacheObject->iDemux != RESERVED_DEMUX_PHYSICAL_OPEN_FILE) {
  488. DcmRemoveItem( pCacheObject );
  489. }
  490. } else {
  491. fOnLists = FALSE;
  492. }
  493. if ( fLockCacheTable ) {
  494. LeaveCriticalSection( &CacheTable.CriticalSection );
  495. }
  496. return fOnLists;
  497. }
  498. #pragma hdrstop
  499. #endif // _TSUNAMIP_HXX_