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.

1540 lines
48 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. idindex.h
  5. Abstract:
  6. This module contains the file and directory id structures.
  7. Author:
  8. Jameel Hyder (microsoft!jameelh)
  9. Revision History:
  10. 25 Apr 1992 Initial Version
  11. Notes: Tab stop: 4
  12. --*/
  13. #ifndef _IDINDEX_
  14. #define _IDINDEX_
  15. // AFP_IDDBHDR_VERSION2 was an experimental version.
  16. #define AFP_IDDBHDR_VERSION1 0x00010000
  17. #define AFP_IDDBHDR_VERSION2 0x00020000
  18. #define AFP_IDDBHDR_VERSION3 0x00030000
  19. #define AFP_IDDBHDR_VERSION4 0x00040000
  20. #define AFP_IDDBHDR_VERSION5 0x00050000
  21. #define AFP_IDDBHDR_VERSION AFP_IDDBHDR_VERSION5
  22. typedef struct _IdDbHeader // Database header
  23. {
  24. DWORD idh_Signature; // Signature
  25. DWORD idh_Version; // Version number
  26. DWORD idh_LastId; // Highest id that is assigned
  27. AFPTIME idh_CreateTime; // Creation time for this volume
  28. AFPTIME idh_ModifiedTime; // Modified time for this volume
  29. AFPTIME idh_BackupTime; // Backup time for this volume
  30. } IDDBHDR, *PIDDBHDR;
  31. // IdDb header is followed by a ULONG count of entries, then the DISKENTRies
  32. #define VALID_DFE(pDfe) ((pDfe) != NULL)
  33. struct _DfeBlock;
  34. struct _DirFileEntry;
  35. #define MAX_CHILD_HASH_BUCKETS 6
  36. typedef struct _DirEntry
  37. {
  38. // NOTE: Keep the ChildDir and ChildFile entries together and in this order
  39. // The code in AfpAddDfEntry depends on this to efficiently zero it out
  40. // Also de_ChildDir is accessed as de_ChildFile[-1] !!!
  41. struct _DirFileEntry * de_ChildDir; // First child in the dir list
  42. struct _DirFileEntry * de_ChildFile[MAX_CHILD_HASH_BUCKETS];
  43. // File 'children' are hashed for faster lookup
  44. DWORD de_Access; // Combined access bits
  45. #ifdef AGE_DFES
  46. AFPTIME de_LastAccessTime; // Time when this DFE was last accessed
  47. // Valid for directories only
  48. LONG de_ChildForkOpenCount;// Count of open forks within this directory
  49. #endif
  50. } DIRENTRY, *PDIRENTRY;
  51. // Owner access mask (SFI vs. SFO)
  52. #define DE_OWNER_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 0)
  53. // Group access mask (SFI vs. SFO)
  54. #define DE_GROUP_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 1)
  55. // World access mask (SFI vs. SFO)
  56. #define DE_WORLD_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 2)
  57. typedef struct _DirFileEntry
  58. {
  59. // The dfe_Overflow is overloaded with dfe_NextFree for use by the block
  60. // allocation package for the DFEs.
  61. #define dfe_NextFree dfe_NextOverflow
  62. struct _DirFileEntry * dfe_NextOverflow; // Overflow links
  63. struct _DirFileEntry ** dfe_PrevOverflow; // Overflow links
  64. struct _DirFileEntry * dfe_NextSibling; // Next sibling.
  65. struct _DirFileEntry ** dfe_PrevSibling; // Previous sibling.
  66. struct _DirFileEntry * dfe_Parent; // Parent entry
  67. DWORD dfe_AfpId; // Afp FileId or DirId (from AfpInfo)
  68. AFPTIME dfe_BackupTime; // Backup time for the file/dir (from AfpInfo)
  69. // (Volume backup time is stored
  70. // in the AFP_IdIndex stream)
  71. AFPTIME dfe_CreateTime; // Creation time
  72. TIME dfe_LastModTime; // Last modify time (as a LARGE_INTEGER)
  73. SHORT dfe_DirDepth; // Parent of root at -1, root at 0
  74. USHORT dfe_Flags; // file, dir or file with id
  75. USHORT dfe_NtAttr; // NT Attributes (FILE_ATTRIBUTE_VALID_FLAGS)
  76. USHORT dfe_AfpAttr; // Attributes mask (From AfpInfo)
  77. union
  78. {
  79. // File specific information
  80. struct // For Files Only
  81. {
  82. DWORD dfe_DataLen; // Data fork length
  83. DWORD dfe_RescLen; // Resource fork length
  84. };
  85. // Directory specific information
  86. struct // For Directories Only
  87. {
  88. DWORD dfe_DirOffspring; // count of dir offspring
  89. DWORD dfe_FileOffspring; // count of file offspring
  90. };
  91. };
  92. FINDERINFO dfe_FinderInfo; // Finder Info (32 bytes) (from AfpInfo)
  93. // NOTE: When Dfes are copied as a structure, the fields below are NOT TO BE COPIED.
  94. // The fields above should be.
  95. #define dfe_CopyUpto dfe_UnicodeName
  96. UNICODE_STRING dfe_UnicodeName; // 'Munged' Unicode Name of the entity
  97. DWORD dfe_NameHash; // Hash value for the upcased munged Unicode name
  98. // For directories, the DirEntry structure follows this structure. The space for
  99. // this is allocated immediately after the DFENTRY structure and before the space
  100. // for the name strings. For files it is NULL. This pointer should not be copied
  101. // as well !!!
  102. PDIRENTRY dfe_pDirEntry; // Directory related fields
  103. // NULL for files
  104. } DFENTRY, *PDFENTRY;
  105. // Owner access mask (SFI vs. SFO)
  106. #define DFE_OWNER_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 0)
  107. // Group access mask (SFI vs. SFO)
  108. #define DFE_GROUP_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 1)
  109. // World access mask (SFI vs. SFO)
  110. #define DFE_WORLD_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 2)
  111. typedef struct _EnumIdAndType
  112. {
  113. DWORD eit_Id;
  114. DWORD eit_Flags;
  115. } EIT, *PEIT;
  116. // There is the result of enumeration of a directory for this session and is stored
  117. // within the connection descriptor. This is purely for performance reasons. This is
  118. // deleted whenever an api other than AfpEnumerate is called and a result is around.
  119. typedef struct _EnumDir
  120. {
  121. DWORD ed_ParentDirId; // Anchor point
  122. DWORD ed_Bitmap; // Combination of file & dir bitmaps
  123. LONG ed_ChildCount; // Count of children of the dir being enumerated
  124. AFPTIME ed_TimeStamp; // Time at which created
  125. PEIT ed_pEit; // list of actual entries
  126. ANSI_STRING ed_PathName; // This is the name as passed by the client
  127. // and is not normalised.
  128. USHORT ed_BadCount; // Count of failed entities
  129. BYTE ed_PathType; // Long name or short name
  130. } ENUMDIR, *PENUMDIR;
  131. typedef struct _CatSearchSpec
  132. {
  133. BYTE __StructLength;
  134. BYTE __FillerOrFileDir;
  135. // The rest of the parameters follow
  136. } CATSEARCHSPEC, *PCATSEARCHSPEC;
  137. // Must be 16 bytes as per AfpCatSearch API
  138. typedef struct _CatalogPosition
  139. {
  140. USHORT cp_Flags; // if zero, then start search from beginning
  141. USHORT cp_usPad1;
  142. DWORD cp_CurParentId;
  143. DWORD cp_NextFileId;
  144. AFPTIME cp_TimeStamp;
  145. } CATALOGPOSITION, *PCATALOGPOSITION;
  146. #define CATFLAGS_SEARCHING_FILES 0x0001
  147. #define CATFLAGS_SEARCHING_DIRCHILD 0x0002
  148. #define CATFLAGS_SEARCHING_SIBLING 0x0004
  149. #define CATFLAGS_WRITELOCK_REQUIRED 0x0008
  150. #define CATFLAGS_VALID (CATFLAGS_SEARCHING_FILES | \
  151. CATFLAGS_SEARCHING_DIRCHILD | \
  152. CATFLAGS_SEARCHING_SIBLING | \
  153. CATFLAGS_WRITELOCK_REQUIRED)
  154. // Maximum time that a mac can hold onto a catsearch position and still
  155. // have the search pickup from there instead of the beginning of the catalog
  156. #define MAX_CATSEARCH_TIME 3600 // In seconds
  157. // DFE_FLAGS_xxxx values for dfe_Flags field of DFENTRY structure
  158. #define DFE_FLAGS_FILE_WITH_ID 0x0100
  159. #define DFE_FLAGS_FILE_NO_ID 0x0200
  160. #define DFE_FLAGS_DIR 0x0400
  161. #define DFE_FLAGS_DFBITS (DFE_FLAGS_FILE_WITH_ID | \
  162. DFE_FLAGS_FILE_NO_ID | \
  163. DFE_FLAGS_DIR | \
  164. DFE_FLAGS_HAS_COMMENT)
  165. #define DFE_FLAGS_HAS_COMMENT 0x0800
  166. #define DFE_FLAGS_INIT_COMPLETED 0x20
  167. #define DFE_FLAGS_ENUMERATED 0x8000
  168. // Encode the child and sibling pointers
  169. #define DFE_FLAGS_HAS_CHILD 0x1000 // Used for reading in IdDb from disk
  170. #define DFE_FLAGS_HAS_SIBLING 0x2000 // Used for reading in IdDb from disk
  171. #define DFE_FLAGS_CSENCODEDBITS (DFE_FLAGS_HAS_CHILD | DFE_FLAGS_HAS_SIBLING | DFE_FLAGS_HAS_COMMENT)
  172. #define DFE_FLAGS_NAMELENBITS 0x001F // Encodes the length of the longname
  173. // which is 31 *characters* max
  174. #define DFE_FLAGS_VALID_DSKBITS (DFE_FLAGS_CSENCODEDBITS | \
  175. DFE_FLAGS_NAMELENBITS | \
  176. DFE_FLAGS_HAS_COMMENT)
  177. // Valid only for directories when their files have been enumerated from disk
  178. // and now all have cached DFEs in the IDDB tree structure
  179. #define DFE_FLAGS_FILES_CACHED 0x4000
  180. // DAlreadyOpen and RAlreadyOpen flags for a File
  181. #define DFE_FLAGS_R_ALREADYOPEN 0x0040
  182. #define DFE_FLAGS_D_ALREADYOPEN 0x0080
  183. #define DFE_FLAGS_OPEN_BITS (DFE_FLAGS_D_ALREADYOPEN | \
  184. DFE_FLAGS_R_ALREADYOPEN)
  185. typedef struct _DiskEntry
  186. {
  187. DWORD dsk_AfpId;
  188. AFPTIME dsk_CreateTime; // File Creation time
  189. TIME dsk_LastModTime; // Last modify time
  190. FINDERINFO dsk_FinderInfo; // Finder Info (32 bytes) (from AfpInfo)
  191. AFPTIME dsk_BackupTime; // Backup time for the file/dir (from AfpInfo)
  192. // (Volume backup time is stored
  193. // in the AFP_IdIndex stream)
  194. union
  195. {
  196. DWORD dsk_DataLen; // Data fork length
  197. DWORD dsk_Access; // Combined access rights
  198. };
  199. DWORD dsk_RescLen; // Resource fork length
  200. USHORT dsk_Flags; // DFE_FLAGS_XXXX
  201. USHORT dsk_AfpAttr; // Attributes mask (From AfpInfo)
  202. USHORT dsk_NtAttr; // From FileAttributes
  203. USHORT dsk_Signature; // AFP_DISKENTRY_SIGNATURE
  204. WCHAR dsk_Name[2]; // Longname in 'munged' Unicode will follow and be padded
  205. // out, if necessary, to DWORD boundry (max 64 bytes)
  206. } DISKENTRY, *PDISKENTRY;
  207. #define AFP_DISKENTRY_SIGNATURE *(PUSHORT)"::" // illegal name character
  208. // size of buffer used to read-in/write-out the IdDb entries from/to disk
  209. #define IDDB_UPDATE_BUFLEN (16*1024)
  210. // Round the length to 4*N
  211. #define DWLEN(_b) (((_b) + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1))
  212. // #define DFE_IS_DIRECTORY(_pDFE) (((_pDFE)->dfe_Flags & DFE_FLAGS_DIR) ? True : False)
  213. #define DFE_IS_DIRECTORY(_pDFE) ((_pDFE)->dfe_pDirEntry != NULL)
  214. // #define DFE_IS_FILE(_pDFE) (((_pDFE)->dfe_Flags & (DFE_FLAGS_FILE_NO_ID | DFE_FLAGS_FILE_WITH_ID)) ? True : False)
  215. #define DFE_IS_FILE(_pDFE) ((_pDFE)->dfe_pDirEntry == NULL)
  216. #define DFE_IS_FILE_WITH_ID(_pDFE) (((_pDFE)->dfe_Flags & DFE_FLAGS_FILE_WITH_ID) ? True : False)
  217. #define DFE_IS_ROOT(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_ROOT)
  218. #define DFE_IS_PARENT_OF_ROOT(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_PARENT_OF_ROOT)
  219. #define DFE_IS_NWTRASH(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_NETWORK_TRASH)
  220. #define DFE_SET_DIRECTORY(_pDFE, _ParentDepth) \
  221. { \
  222. ((_pDFE)->dfe_DirDepth = _ParentDepth + 1); \
  223. ((_pDFE)->dfe_Flags |= DFE_FLAGS_DIR); \
  224. }
  225. #define DFE_SET_FILE(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILE_NO_ID)
  226. #define DFE_SET_FILE_ID(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILE_WITH_ID)
  227. #define DFE_CLR_FILE_ID(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_FILE_WITH_ID)
  228. // update just the AFPinfo in the dfentry
  229. #define DFE_UPDATE_CACHED_AFPINFO(_pDFE, pAfpInfo) \
  230. { \
  231. (_pDFE)->dfe_BackupTime = (pAfpInfo)->afpi_BackupTime; \
  232. (_pDFE)->dfe_FinderInfo = (pAfpInfo)->afpi_FinderInfo; \
  233. (_pDFE)->dfe_AfpAttr = (pAfpInfo)->afpi_Attributes; \
  234. if ((_pDFE)->dfe_Flags & DFE_FLAGS_DIR) \
  235. { \
  236. DFE_OWNER_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessOwner; \
  237. DFE_GROUP_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessGroup; \
  238. DFE_WORLD_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessWorld; \
  239. } \
  240. }
  241. #define DFE_SET_COMMENT(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_HAS_COMMENT)
  242. #define DFE_CLR_COMMENT(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_HAS_COMMENT)
  243. // Check to see if this entry was enumerated on an NTFS directory
  244. #define DFE_HAS_BEEN_SEEN(_pDFE) ((_pDFE)->dfe_Flags & DFE_FLAGS_ENUMERATED)
  245. #define DFE_MARK_UNSEEN(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_ENUMERATED)
  246. #define DFE_MARK_AS_SEEN(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_ENUMERATED)
  247. // Directories only
  248. #define DFE_CHILDREN_ARE_PRESENT(_pDFE) ((_pDFE)->dfe_Flags & DFE_FLAGS_FILES_CACHED)
  249. // Directories only
  250. #define DFE_MARK_CHILDREN_PRESENT(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILES_CACHED)
  251. #define DFE_FILE_HAS_SIBLING(_pDFE, _fbi, _pfHasSibling) \
  252. { \
  253. DWORD _i; \
  254. PDIRENTRY _pDirEntry; \
  255. \
  256. *(_pfHasSibling) = False; \
  257. if (((_pDFE)->dfe_NextSibling != NULL) || \
  258. ((_pDFE)->dfe_Parent->dfe_pDirEntry->de_ChildDir != NULL)) \
  259. { \
  260. *(_pfHasSibling) = True; \
  261. } \
  262. else \
  263. { \
  264. _pDirEntry = (_pDFE)->dfe_Parent->dfe_pDirEntry; \
  265. ASSERT(_pDirEntry != NULL); \
  266. for (_i = (_fbi) + 1; \
  267. _i < MAX_CHILD_HASH_BUCKETS; \
  268. _i++) \
  269. { \
  270. if (_pDirEntry->de_ChildFile[_i] != NULL) \
  271. { \
  272. *(_pfHasSibling) = True; \
  273. break; \
  274. } \
  275. } \
  276. } \
  277. }
  278. #define HASH_DIR_ID(Id, _pVolDesc) ((Id) & ((_pVolDesc)->vds_DirHashTableSize-1))
  279. #define HASH_FILE_ID(Id, _pVolDesc) ((Id) & ((_pVolDesc)->vds_FileHashTableSize-1))
  280. #define HASH_CACHE_ID(Id) ((Id) & (IDINDEX_CACHE_ENTRIES-1))
  281. #define QUAD_SIZED(_X_) (((_X_) % 8) == 0)
  282. // Values for access checking
  283. #define ACCESS_READ 1
  284. #define ACCESS_WRITE 2
  285. extern
  286. NTSTATUS
  287. AfpDfeInit(
  288. VOID
  289. );
  290. extern
  291. VOID
  292. AfpDfeDeInit(
  293. VOID
  294. );
  295. extern
  296. PDFENTRY
  297. AfpFindDfEntryById(
  298. IN struct _VolDesc * pVolDesc,
  299. IN DWORD Id,
  300. IN DWORD EntityMask
  301. );
  302. extern
  303. PDFENTRY
  304. AfpFindEntryByUnicodeName(
  305. IN struct _VolDesc * pVolDesc,
  306. IN PUNICODE_STRING pName,
  307. IN DWORD PathType,
  308. IN PDFENTRY pDfeParent,
  309. IN DWORD EntityMask
  310. );
  311. extern
  312. PDFENTRY
  313. AfpAddDfEntry(
  314. IN struct _VolDesc * pVolDesc,
  315. IN PDFENTRY pDfeParent,
  316. IN PUNICODE_STRING pUName,
  317. IN BOOLEAN Directory,
  318. IN DWORD AfpId OPTIONAL
  319. );
  320. extern
  321. PDFENTRY
  322. AfpRenameDfEntry(
  323. IN struct _VolDesc * pVolDesc,
  324. IN PDFENTRY pDfEntry,
  325. IN PUNICODE_STRING pNewName
  326. );
  327. extern
  328. PDFENTRY
  329. AfpMoveDfEntry(
  330. IN struct _VolDesc * pVolDesc,
  331. IN PDFENTRY pDfEntry,
  332. IN PDFENTRY pNewParentDfE,
  333. IN PUNICODE_STRING pNewName OPTIONAL
  334. );
  335. extern
  336. VOID FASTCALL
  337. AfpDeleteDfEntry(
  338. IN struct _VolDesc * pVolDesc,
  339. IN PDFENTRY pDfE
  340. );
  341. extern
  342. VOID
  343. AfpExchangeIdEntries(
  344. IN struct _VolDesc * pVolDesc,
  345. IN DWORD AfpId1,
  346. IN DWORD AfpId2
  347. );
  348. extern
  349. VOID FASTCALL
  350. AfpPruneIdDb(
  351. IN struct _VolDesc * pVolDesc,
  352. IN PDFENTRY pDfeTarget
  353. );
  354. extern
  355. NTSTATUS FASTCALL
  356. AfpInitIdDb(
  357. IN struct _VolDesc * pVolDesc,
  358. OUT BOOLEAN * pfNewVolume,
  359. OUT BOOLEAN * pfVerifyIndex
  360. );
  361. extern
  362. VOID FASTCALL
  363. AfpFreeIdIndexTables(
  364. IN struct _VolDesc * pVolDesc
  365. );
  366. extern
  367. AFPSTATUS
  368. AfpEnumerate(
  369. IN struct _ConnDesc * pConnDesc,
  370. IN DWORD ParentDirId,
  371. IN PANSI_STRING pPath,
  372. IN DWORD BitmapF,
  373. IN DWORD BitmapD,
  374. IN BYTE PathType,
  375. IN DWORD DFFlags,
  376. OUT PENUMDIR * ppEnumDir
  377. );
  378. extern
  379. AFPSTATUS
  380. AfpSetDFFileFlags(
  381. IN struct _VolDesc * pVolDesc,
  382. IN DWORD AfpId,
  383. IN DWORD FlagSet OPTIONAL,
  384. IN BOOLEAN SetFileId,
  385. IN BOOLEAN ClrFileId
  386. );
  387. extern
  388. VOID
  389. AfpChangeNotifyThread(
  390. IN PVOID pContext
  391. );
  392. extern
  393. VOID FASTCALL
  394. AfpProcessChangeNotify(
  395. IN struct _VolumeNotify * pVolNotify
  396. );
  397. extern
  398. VOID
  399. AfpQueuePrivateChangeNotify(
  400. IN struct _VolDesc * pVolDesc,
  401. IN PUNICODE_STRING pName,
  402. IN PUNICODE_STRING pPath,
  403. IN DWORD ParentId
  404. );
  405. extern
  406. BOOLEAN FASTCALL
  407. AfpShouldWeIgnoreThisNotification(
  408. IN struct _VolumeNotify * pVolNotify
  409. );
  410. extern
  411. VOID
  412. AfpQueueOurChange(
  413. IN struct _VolDesc * pVolDesc,
  414. IN DWORD Action,
  415. IN PUNICODE_STRING pPath,
  416. IN PUNICODE_STRING pParentPath OPTIONAL
  417. );
  418. extern
  419. VOID
  420. AfpDequeueOurChange(
  421. IN struct _VolDesc * pVolDesc,
  422. IN DWORD Action,
  423. IN PUNICODE_STRING pPath,
  424. IN PUNICODE_STRING pParentPath OPTIONAL
  425. );
  426. extern
  427. NTSTATUS FASTCALL
  428. AddToDelayedNotifyList(
  429. IN struct _VolDesc * pVolDesc,
  430. IN PUNICODE_STRING pUName
  431. );
  432. extern
  433. NTSTATUS
  434. RemoveFromDelayedNotifyList(
  435. IN struct _VolDesc * pVolDesc,
  436. IN PUNICODE_STRING pUName,
  437. IN PFILE_NOTIFY_INFORMATION pFNInfo
  438. );
  439. extern
  440. NTSTATUS
  441. CheckAndProcessDelayedNotify(
  442. IN struct _VolDesc * pVolDesc,
  443. IN PUNICODE_STRING pUName,
  444. IN PUNICODE_STRING pUNewname,
  445. IN PUNICODE_STRING pUParent
  446. );
  447. extern
  448. VOID
  449. AfpCacheParentModTime(
  450. IN struct _VolDesc * pVolDesc,
  451. IN PFILESYSHANDLE pHandle OPTIONAL, // if pPath not supplied
  452. IN PUNICODE_STRING pPath OPTIONAL, // if pHandle not supplied
  453. IN PDFENTRY pDfeParent OPTIONAL, // if ParentId not supplied
  454. IN DWORD ParentId OPTIONAL // if pDfeParent not supplied
  455. );
  456. extern
  457. AFPSTATUS
  458. AfpCatSearch(
  459. IN struct _ConnDesc * pConnDesc,
  460. IN PCATALOGPOSITION pCatPosition,
  461. IN DWORD Bitmap,
  462. IN DWORD FileBitmap,
  463. IN DWORD DirBitmap,
  464. IN struct _FileDirParms * pFDParm1,
  465. IN struct _FileDirParms * pFDParm2,
  466. IN PUNICODE_STRING pMatchString OPTIONAL,
  467. IN OUT PDWORD pCount,
  468. IN SHORT Buflen,
  469. OUT PSHORT pSizeLeft,
  470. OUT PBYTE pResults,
  471. OUT PCATALOGPOSITION pNewCatPosition
  472. );
  473. #ifdef AGE_DFES
  474. extern
  475. VOID FASTCALL
  476. AfpAgeDfEntries(
  477. IN struct _VolDesc * pVolDesc
  478. );
  479. #endif
  480. #define REENUMERATE 0x0001
  481. #define GETDIRSKELETON 0x0002
  482. #define GETFILES 0x0004
  483. #define GETENTIRETREE 0x0008
  484. extern
  485. NTSTATUS
  486. AfpCacheDirectoryTree(
  487. IN struct _VolDesc * pVolDesc,
  488. IN PDFENTRY pDFETreeRoot,
  489. IN DWORD Method,
  490. IN PFILESYSHANDLE phRootDir OPTIONAL,
  491. IN PUNICODE_STRING pDirPath OPTIONAL
  492. );
  493. extern
  494. AFPSTATUS FASTCALL
  495. AfpOurChangeScavenger(
  496. IN struct _VolDesc * pVolDesc
  497. );
  498. extern
  499. VOID FASTCALL
  500. AfpFlushIdDb(
  501. IN struct _VolDesc * pVolDesc,
  502. IN PFILESYSHANDLE phIdDb
  503. );
  504. extern
  505. VOID
  506. AfpGetDirFileHashSizes(
  507. IN struct _VolDesc * pVolDesc,
  508. OUT PDWORD pdwDirHashSz,
  509. OUT PDWORD pdwFileHashSz
  510. );
  511. #ifdef IDINDEX_LOCALS
  512. #define afpConvertBasicToBothDirInfo(_pFBasInfo, _pFBDInfo) \
  513. { \
  514. (_pFBDInfo)->CreationTime = (_pFBasInfo)->CreationTime; \
  515. (_pFBDInfo)->LastWriteTime = (_pFBasInfo)->LastWriteTime; \
  516. (_pFBDInfo)->ChangeTime = (_pFBasInfo)->ChangeTime; \
  517. (_pFBDInfo)->FileAttributes = (_pFBasInfo)->FileAttributes; \
  518. (_pFBDInfo)->EndOfFile.QuadPart = 0; \
  519. }
  520. #undef EQU
  521. #ifdef _IDDB_GLOBALS_
  522. #define IDDBGLOBAL
  523. #define EQU =
  524. #else
  525. #define IDDBGLOBAL extern
  526. #define EQU ; / ## /
  527. #endif
  528. // This bit on a Notify action indicates it is a simulated notify. Volume
  529. // modified time is not updated when such a notify comes in
  530. #define AFP_ACTION_PRIVATE 0x80000000
  531. // DFEs come in four sizes. This helps in efficiently managing them in a block
  532. // package (see later). THESE SIZES NEED TO BE 4*N, else we run into alignment
  533. // faults on architectures that require it.
  534. #define DFE_INDEX_TINY 0
  535. #define DFE_INDEX_SMALL 1
  536. #define DFE_INDEX_MEDIUM 2
  537. #define DFE_INDEX_LARGE 3
  538. //
  539. // Make sure each of the sizes below (XXX_U) are multiple of 8
  540. //
  541. #define DFE_SIZE_TINY 8 // These are lengths for ANSI names
  542. #define DFE_SIZE_SMALL 12 // - ditto -
  543. #define DFE_SIZE_MEDIUM 20 // - ditto -
  544. #define DFE_SIZE_LARGE 32 // - ditto - corres. to AFP_FILENAME_LEN
  545. #define DFE_SIZE_TINY_U DFE_SIZE_TINY*sizeof(WCHAR) // These are lengths for UNICODE names
  546. #define DFE_SIZE_SMALL_U DFE_SIZE_SMALL*sizeof(WCHAR) // - ditto -
  547. #define DFE_SIZE_MEDIUM_U DFE_SIZE_MEDIUM*sizeof(WCHAR) // - ditto -
  548. #define DFE_SIZE_LARGE_U DFE_SIZE_LARGE*sizeof(WCHAR) // - ditto - corres. to AFP_FILENAME_LEN
  549. #define ASIZE_TO_INDEX(_Size) \
  550. (((_Size) <= DFE_SIZE_TINY) ? DFE_INDEX_TINY : \
  551. (((_Size) <= DFE_SIZE_SMALL) ? DFE_INDEX_SMALL : \
  552. (((_Size) <= DFE_SIZE_MEDIUM) ? DFE_INDEX_MEDIUM : DFE_INDEX_LARGE)))
  553. #define USIZE_TO_INDEX(_Size) \
  554. (((_Size) <= DFE_SIZE_TINY_U) ? DFE_INDEX_TINY : \
  555. (((_Size) <= DFE_SIZE_SMALL_U) ? DFE_INDEX_SMALL : \
  556. (((_Size) <= DFE_SIZE_MEDIUM_U) ? DFE_INDEX_MEDIUM : DFE_INDEX_LARGE)))
  557. #define ALLOC_DFE(Index, fDir) afpAllocDfe(Index, fDir)
  558. #define FREE_DFE(pDfEntry) afpFreeDfe(pDfEntry)
  559. LOCAL DWORD FASTCALL
  560. afpGetNextId(
  561. IN struct _VolDesc * pVolDesc
  562. );
  563. LOCAL
  564. NTSTATUS FASTCALL
  565. afpSeedIdDb(
  566. IN struct _VolDesc * pVolDesc
  567. );
  568. LOCAL
  569. VOID
  570. afpPackSearchParms(
  571. IN PDFENTRY pDfe,
  572. IN DWORD Bitmap,
  573. IN PBYTE pBuf
  574. );
  575. LOCAL
  576. NTSTATUS FASTCALL
  577. afpReadIdDb(
  578. IN struct _VolDesc * pVolDesc,
  579. IN PFILESYSHANDLE pfshIdDb,
  580. OUT BOOLEAN * pfVerifyIndex
  581. );
  582. VOID
  583. afpAddDfEntryAndCacheInfo(
  584. IN struct _VolDesc * pVolDesc,
  585. IN PDFENTRY pDfeParent,
  586. IN PUNICODE_STRING pUName, // munged unicode name
  587. IN PFILESYSHANDLE pfshParentDir, // open handle to parent directory
  588. IN PFILE_BOTH_DIR_INFORMATION pFBDInfo, // from enumerate
  589. IN PUNICODE_STRING pNotifyPath, // to filter out our own AFP_AfpInfo change notifies
  590. IN PDFENTRY * ppDfEntry,
  591. IN BOOLEAN CheckDuplicate
  592. );
  593. VOID
  594. afpVerifyDFE(
  595. IN struct _VolDesc * pVolDesc,
  596. IN PDFENTRY pDfeParent,
  597. IN PUNICODE_STRING pUName, // munged unicode name
  598. IN PFILESYSHANDLE pfshParentDir, // open handle to parent directory
  599. IN PFILE_BOTH_DIR_INFORMATION pFBDInfo, // from enumerate
  600. IN PUNICODE_STRING pNotifyPath, // to filter out our own AFP_AfpInfo change notifies
  601. IN PDFENTRY * ppDfEntry
  602. );
  603. PDFENTRY
  604. afpFindEntryByNtPath(
  605. IN struct _VolDesc * pVolDesc,
  606. IN DWORD ChangeAction, // if ADDED then lookup parent DFE
  607. IN PUNICODE_STRING pPath,
  608. OUT PUNICODE_STRING pParent,
  609. OUT PUNICODE_STRING pTail
  610. );
  611. PDFENTRY
  612. afpFindEntryByNtName(
  613. IN struct _VolDesc * pVolDesc,
  614. IN PUNICODE_STRING pName,
  615. IN PDFENTRY pDfeParent // pointer to parent DFENTRY
  616. );
  617. VOID FASTCALL
  618. afpProcessPrivateNotify(
  619. IN struct _VolumeNotify * pVolNotify
  620. );
  621. VOID FASTCALL
  622. afpActivateVolume(
  623. IN struct _VolDesc * pVolDesc
  624. );
  625. VOID
  626. afpRenameInvalidWin32Name(
  627. IN PFILESYSHANDLE phRootDir,
  628. IN BOOLEAN IsDir,
  629. IN PUNICODE_STRING pName
  630. );
  631. #define afpInitializeIdDb(_pVolDesc) \
  632. { \
  633. AFPTIME CurrentTime; \
  634. PDFENTRY pDfEntry; \
  635. \
  636. /* RO volumes don't use the network trash folder at all */ \
  637. (_pVolDesc)->vds_LastId = AFP_ID_NETWORK_TRASH; \
  638. \
  639. AfpGetCurrentTimeInMacFormat(&CurrentTime); \
  640. (_pVolDesc)->vds_CreateTime = CurrentTime; \
  641. (_pVolDesc)->vds_ModifiedTime = CurrentTime; \
  642. (_pVolDesc)->vds_BackupTime = BEGINNING_OF_TIME; \
  643. \
  644. /* Create a DFE for the root directory */ \
  645. afpCreateParentOfRoot(_pVolDesc, &pDfEntry); \
  646. }
  647. #ifdef AGE_DFES
  648. #define afpCreateParentOfRoot(_pVolDesc, _ppDfEntry) \
  649. { \
  650. PDFENTRY pDFE; \
  651. struct _DirFileEntry ** _DfeDirBucketStart; \
  652. \
  653. /* \
  654. * add the parent of root to the id index. \
  655. * This has to be done here \
  656. * (i.e. cannot call AfpAddDfEntry for parentofroot). \
  657. */ \
  658. \
  659. if ((*(_ppDfEntry) = ALLOC_DFE(0, True)) != NULL) \
  660. { \
  661. pDFE = *(_ppDfEntry); \
  662. \
  663. (_pVolDesc)->vds_NumFileDfEntries = 0; \
  664. (_pVolDesc)->vds_NumDirDfEntries = 0; \
  665. pDFE->dfe_Flags = DFE_FLAGS_DIR | DFE_FLAGS_FILES_CACHED; \
  666. pDFE->dfe_DirDepth = -1; \
  667. pDFE->dfe_Parent = NULL; \
  668. pDFE->dfe_NextOverflow = NULL; \
  669. \
  670. /* Initialize the DirEntry for ParentOfRoot */ \
  671. ASSERT((FIELD_OFFSET(DIRENTRY, de_ChildFile) - \
  672. FIELD_OFFSET(DIRENTRY, de_ChildDir)) == sizeof(PVOID));\
  673. \
  674. /* These fields are relevant to directories only */ \
  675. pDFE->dfe_pDirEntry->de_LastAccessTime = BEGINNING_OF_TIME; \
  676. pDFE->dfe_pDirEntry->de_ChildForkOpenCount = 0; \
  677. \
  678. /* \
  679. * The parent of root has no siblings and this should \
  680. * never be referenced \
  681. */ \
  682. pDFE->dfe_NameHash = 0; \
  683. pDFE->dfe_NextSibling = NULL; \
  684. pDFE->dfe_PrevSibling = NULL; \
  685. pDFE->dfe_AfpId = AFP_ID_PARENT_OF_ROOT; \
  686. pDFE->dfe_DirOffspring = pDFE->dfe_FileOffspring = 0; \
  687. \
  688. /* link it into the hash buckets */ \
  689. _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \
  690. AfpLinkDoubleAtHead(_DfeDirBucketStart[HASH_DIR_ID(AFP_ID_PARENT_OF_ROOT,_pVolDesc)],\
  691. pDFE, \
  692. dfe_NextOverflow, \
  693. dfe_PrevOverflow); \
  694. } \
  695. }
  696. #else
  697. #define afpCreateParentOfRoot(_pVolDesc, _ppDfEntry) \
  698. { \
  699. PDFENTRY pDfEntry; \
  700. struct _DirFileEntry ** _DfeDirBucketStart; \
  701. \
  702. /* \
  703. * add the parent of root to the id index. \
  704. * This has to be done here \
  705. * (i.e. cannot call AfpAddDfEntry for parentofroot). \
  706. */ \
  707. \
  708. if ((*(_ppDfEntry) = ALLOC_DFE(0, True)) != NULL) \
  709. { \
  710. pDfEntry = *(_ppDfEntry); \
  711. \
  712. (_pVolDesc)->vds_NumFileDfEntries = 0; \
  713. (_pVolDesc)->vds_NumDirDfEntries = 0; \
  714. pDfEntry->dfe_Flags = DFE_FLAGS_DIR | DFE_FLAGS_FILES_CACHED;\
  715. pDfEntry->dfe_DirDepth = -1; \
  716. pDfEntry->dfe_Parent = NULL; \
  717. pDfEntry->dfe_NextOverflow = NULL; \
  718. \
  719. /* Initialize the DirEntry for ParentOfRoot */ \
  720. ASSERT((FIELD_OFFSET(DIRENTRY, de_ChildFile) - \
  721. FIELD_OFFSET(DIRENTRY, de_ChildDir)) == sizeof(PVOID));\
  722. \
  723. /* The parent of root has no siblings and this should never be referenced */ \
  724. pDfEntry->dfe_NameHash = 0; \
  725. pDfEntry->dfe_NextSibling = NULL; \
  726. pDfEntry->dfe_PrevSibling = NULL; \
  727. pDfEntry->dfe_AfpId = AFP_ID_PARENT_OF_ROOT; \
  728. pDfEntry->dfe_DirOffspring = pDfEntry->dfe_FileOffspring = 0;\
  729. \
  730. /* link it into the hash buckets */ \
  731. _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \
  732. AfpLinkDoubleAtHead(_DfeDirBucketStart[HASH_DIR_ID(AFP_ID_PARENT_OF_ROOT,_pVolDesc)],\
  733. pDfEntry, \
  734. dfe_NextOverflow, \
  735. dfe_PrevOverflow); \
  736. } \
  737. }
  738. #endif
  739. #define afpHashUnicodeName(_pUnicodeName, _pHashValue) \
  740. { \
  741. DWORD j; \
  742. UNICODE_STRING upcaseName; \
  743. WCHAR buffer[AFP_LONGNAME_LEN+1]; \
  744. PDWORD pbuf = NULL; \
  745. \
  746. AfpSetEmptyUnicodeString(&upcaseName, sizeof(buffer), buffer); \
  747. RtlUpcaseUnicodeString(&upcaseName, _pUnicodeName, False); \
  748. j = upcaseName.Length/sizeof(WCHAR); \
  749. buffer[j] = UNICODE_NULL; \
  750. pbuf = (PDWORD)buffer; \
  751. j /= (sizeof(DWORD)/sizeof(WCHAR)); \
  752. \
  753. for (*(_pHashValue) = 0; j > 0; j--, pbuf++) \
  754. { \
  755. *(_pHashValue) = (*(_pHashValue) << 3) + *pbuf; \
  756. } \
  757. }
  758. #ifdef SORT_DFE_BY_HASH
  759. #define afpFindDFEByUnicodeNameInSiblingList(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
  760. { \
  761. DWORD NameHash; \
  762. PDFENTRY pD, pF; \
  763. BOOLEAN Found, fFiles; \
  764. \
  765. afpHashUnicodeName(_pName, &NameHash); \
  766. \
  767. pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \
  768. if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \
  769. pD = NULL; \
  770. \
  771. pF = NULL; \
  772. if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \
  773. pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\
  774. \
  775. *(_ppDfEntry) = pD; \
  776. Found = fFiles = False; \
  777. do \
  778. { \
  779. for (NOTHING; \
  780. *(_ppDfEntry) != NULL; \
  781. *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \
  782. { \
  783. if ((*(_ppDfEntry))->dfe_NameHash < NameHash) \
  784. { \
  785. *(_ppDfEntry) = NULL; \
  786. break; \
  787. } \
  788. \
  789. if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \
  790. EQUAL_UNICODE_STRING(&((*(_ppDfEntry))->dfe_UnicodeName), \
  791. _pName, \
  792. True)) \
  793. { \
  794. afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \
  795. Found = True; \
  796. break; \
  797. } \
  798. } \
  799. if (Found) \
  800. break; \
  801. \
  802. fFiles ^= True; \
  803. if (fFiles) \
  804. { \
  805. *(_ppDfEntry) = pF; \
  806. } \
  807. } while (fFiles); \
  808. }
  809. #define afpFindDFEByUnicodeNameInSiblingList_CS(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
  810. { \
  811. DWORD NameHash; \
  812. PDFENTRY pD, pF; \
  813. BOOLEAN Found, fFiles; \
  814. \
  815. afpHashUnicodeName(_pName, &NameHash); \
  816. \
  817. pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \
  818. if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \
  819. pD = NULL; \
  820. \
  821. pF = NULL; \
  822. if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \
  823. pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\
  824. \
  825. *(_ppDfEntry) = pD; \
  826. Found = fFiles = False; \
  827. do \
  828. { \
  829. for (NOTHING; \
  830. *(_ppDfEntry) != NULL; \
  831. *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \
  832. { \
  833. if ((*(_ppDfEntry))->dfe_NameHash < NameHash) \
  834. { \
  835. *(_ppDfEntry) = NULL; \
  836. break; \
  837. } \
  838. \
  839. if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \
  840. EQUAL_UNICODE_STRING_CS(&((*(_ppDfEntry))->dfe_UnicodeName), _pName)) \
  841. { \
  842. afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \
  843. Found = True; \
  844. break; \
  845. } \
  846. } \
  847. if (Found) \
  848. break; \
  849. \
  850. fFiles ^= True; \
  851. if (fFiles) \
  852. { \
  853. *(_ppDfEntry) = pF; \
  854. } \
  855. } while (fFiles); \
  856. }
  857. #else
  858. #define afpFindDFEByUnicodeNameInSiblingList(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
  859. { \
  860. DWORD NameHash; \
  861. PDFENTRY pD, pF; \
  862. BOOLEAN Found, fFiles; \
  863. \
  864. afpHashUnicodeName(_pName, &NameHash); \
  865. \
  866. pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \
  867. if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \
  868. pD = NULL; \
  869. \
  870. pF = NULL; \
  871. if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \
  872. pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\
  873. \
  874. *(_ppDfEntry) = pD; \
  875. Found = fFiles = False; \
  876. do \
  877. { \
  878. for (NOTHING; \
  879. *(_ppDfEntry) != NULL; \
  880. *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \
  881. { \
  882. if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \
  883. EQUAL_UNICODE_STRING(&((*(_ppDfEntry))->dfe_UnicodeName), \
  884. _pName, \
  885. True)) \
  886. { \
  887. afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \
  888. Found = True; \
  889. break; \
  890. } \
  891. } \
  892. if (Found) \
  893. break; \
  894. \
  895. fFiles ^= True; \
  896. if (fFiles) \
  897. { \
  898. *(_ppDfEntry) = pF; \
  899. } \
  900. } while (fFiles); \
  901. }
  902. #define afpFindDFEByUnicodeNameInSiblingList_CS(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
  903. { \
  904. DWORD NameHash; \
  905. PDFENTRY pD, pF; \
  906. BOOLEAN Found, fFiles; \
  907. \
  908. afpHashUnicodeName(_pName, &NameHash); \
  909. \
  910. pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \
  911. if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \
  912. pD = NULL; \
  913. \
  914. pF = NULL; \
  915. if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \
  916. pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\
  917. \
  918. *(_ppDfEntry) = pD; \
  919. Found = fFiles = False; \
  920. do \
  921. { \
  922. for (NOTHING; \
  923. *(_ppDfEntry) != NULL; \
  924. *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \
  925. { \
  926. if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \
  927. EQUAL_UNICODE_STRING_CS(&((*(_ppDfEntry))->dfe_UnicodeName), _pName)) \
  928. { \
  929. afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \
  930. Found = True; \
  931. break; \
  932. } \
  933. } \
  934. if (Found) \
  935. break; \
  936. \
  937. fFiles ^= True; \
  938. if (fFiles) \
  939. { \
  940. *(_ppDfEntry) = pF; \
  941. } \
  942. } while (fFiles); \
  943. }
  944. #endif
  945. #define afpInsertDFEInSiblingList(_pDfeParent, _pDfEntry, _fDirectory) \
  946. { \
  947. if (fDirectory) \
  948. { \
  949. afpInsertDirDFEInSiblingList(_pDfeParent, _pDfEntry); \
  950. } \
  951. else \
  952. { \
  953. afpInsertFileDFEInSiblingList(_pDfeParent, _pDfEntry); \
  954. } \
  955. }
  956. #define afpInsertFileDFEInSiblingList(_pDfeParent, _pDfEntry) \
  957. { \
  958. DWORD Index; \
  959. PDFENTRY * ppDfEntry; \
  960. \
  961. Index = (_pDfEntry)->dfe_NameHash % MAX_CHILD_HASH_BUCKETS; \
  962. ppDfEntry = &(_pDfeParent)->dfe_pDirEntry->de_ChildFile[Index]; \
  963. afpInsertInSiblingList(ppDfEntry, \
  964. (_pDfEntry)); \
  965. }
  966. #define afpInsertDirDFEInSiblingList(_pDfeParent, _pDfEntry) \
  967. { \
  968. PDFENTRY * ppDfEntry; \
  969. \
  970. ppDfEntry = &(_pDfeParent)->dfe_pDirEntry->de_ChildDir; \
  971. afpInsertInSiblingList(ppDfEntry, \
  972. (_pDfEntry)); \
  973. }
  974. #ifdef SORT_DFE_BY_HASH
  975. #define afpInsertInSiblingList(_ppHead, _pDfEntry) \
  976. { \
  977. for (NOTHING; \
  978. *(_ppHead) != NULL; \
  979. (_ppHead) = &(*(_ppHead))->dfe_NextSibling) \
  980. { \
  981. if ((_pDfEntry)->dfe_NameHash > (*(_ppHead))->dfe_NameHash) \
  982. { \
  983. break; \
  984. } \
  985. } \
  986. if (*(_ppHead) != NULL) \
  987. { \
  988. AfpInsertDoubleBefore(_pDfEntry, \
  989. *(_ppHead), \
  990. dfe_NextSibling, \
  991. dfe_PrevSibling); \
  992. } \
  993. else \
  994. { \
  995. *(_ppHead) = (_pDfEntry); \
  996. (_pDfEntry)->dfe_NextSibling = NULL; \
  997. (_pDfEntry)->dfe_PrevSibling = (_ppHead); \
  998. } \
  999. }
  1000. #else
  1001. #define afpInsertInSiblingList(_ppHead, _pDfEntry) \
  1002. { \
  1003. AfpLinkDoubleAtHead(*(_ppHead), \
  1004. (_pDfEntry), \
  1005. dfe_NextSibling, \
  1006. dfe_PrevSibling); \
  1007. }
  1008. #endif
  1009. #define afpInsertDFEInHashBucket(_pVolDesc, _pDfEntry, _fDirectory, _pfS)\
  1010. { \
  1011. PDFENTRY *ppTmp; \
  1012. struct _DirFileEntry ** _DfeDirBucketStart; \
  1013. struct _DirFileEntry ** _DfeFileBucketStart; \
  1014. \
  1015. afpUpdateDfeAccessTime(_pVolDesc, _pDfEntry); \
  1016. *(_pfS) = True; /* Assume success */ \
  1017. \
  1018. retry: \
  1019. \
  1020. if (_fDirectory) \
  1021. { \
  1022. _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \
  1023. ppTmp = &_DfeDirBucketStart[HASH_DIR_ID((_pDfEntry)->dfe_AfpId,_pVolDesc)]; \
  1024. } \
  1025. else \
  1026. { \
  1027. _DfeFileBucketStart = (_pVolDesc)->vds_pDfeFileBucketStart; \
  1028. ppTmp = &_DfeFileBucketStart[HASH_FILE_ID((_pDfEntry)->dfe_AfpId,_pVolDesc)]; \
  1029. } \
  1030. \
  1031. for (NOTHING; \
  1032. *ppTmp != NULL; \
  1033. ppTmp = &(*ppTmp)->dfe_NextOverflow) \
  1034. { \
  1035. ASSERT(VALID_DFE(*ppTmp)); \
  1036. if ((_pDfEntry)->dfe_AfpId > (*ppTmp)->dfe_AfpId) \
  1037. { \
  1038. /* Found our slot */ \
  1039. break; \
  1040. } \
  1041. if ((_pDfEntry)->dfe_AfpId == (*ppTmp)->dfe_AfpId) \
  1042. { \
  1043. /* Found a collision. Assign a new id and proceed */ \
  1044. (_pDfEntry)->dfe_AfpId = afpGetNextId(_pVolDesc); \
  1045. if ((_pDfEntry)->dfe_AfpId == 0) \
  1046. { \
  1047. /* Uh-oh */ \
  1048. *(_pfS) = False; \
  1049. DBGPRINT(DBG_COMP_IDINDEX, DBG_LEVEL_ERR, \
  1050. ("afpInsertDFEInHashBucket: Collision & Id Overflow\n"));\
  1051. break; \
  1052. } \
  1053. /* Write back the afpinfo stream with the new id */ \
  1054. AfpUpdateIdInAfpInfo(_pVolDesc, _pDfEntry); \
  1055. goto retry; \
  1056. } \
  1057. } \
  1058. if (*(_pfS)) \
  1059. { \
  1060. if (*ppTmp != NULL) \
  1061. { \
  1062. AfpInsertDoubleBefore((_pDfEntry), \
  1063. *ppTmp, \
  1064. dfe_NextOverflow, \
  1065. dfe_PrevOverflow); \
  1066. } \
  1067. else \
  1068. { \
  1069. *ppTmp = _pDfEntry; \
  1070. (_pDfEntry)->dfe_PrevOverflow = ppTmp; \
  1071. } \
  1072. (_pVolDesc)->vds_pDfeCache[HASH_CACHE_ID((_pDfEntry)->dfe_AfpId)] = (_pDfEntry); \
  1073. } \
  1074. }
  1075. #define afpValidateDFEType(_pDfEntry, _EntityMask) \
  1076. { \
  1077. if (((_EntityMask) & DFE_ANY) || \
  1078. (((_EntityMask) & DFE_DIR) && DFE_IS_DIRECTORY(_pDfEntry)) || \
  1079. (((_EntityMask) & DFE_FILE) && DFE_IS_FILE(_pDfEntry))) \
  1080. NOTHING; \
  1081. else \
  1082. { \
  1083. _pDfEntry = NULL; \
  1084. } \
  1085. }
  1086. /*** afpCheckDfEntry
  1087. *
  1088. * When enumerating the disk during volume add, if a file/directory
  1089. * has an AfpId associated with it, then it is validated to see if it is
  1090. * within range as well as unique. If there is a collision between AFPIds,
  1091. * a PC user must have copied (or restored) something from
  1092. * this volume, or a different volume (or server) that had the same AFPId,
  1093. * in which case we will give the new entity a different AFP Id;
  1094. * If there is not a collision between AFPIds, and the Id is larger than the
  1095. * last Id we know we assigned, then the new entity gets added with a new
  1096. * AFPId; else if the Id is within the range, we will just use its existing
  1097. * Id.
  1098. *
  1099. * Discovered AFPId is: Action for discovered entity in IdDb is:
  1100. * -------------------- ----------------------------------------
  1101. * 1) > last Id Add a new entry, assign a new AFPId
  1102. *
  1103. * 2) Collides with existing Id:
  1104. * * Host copy occurred Add a new entry, assign a new AFPId
  1105. *
  1106. * 3) < last Id Insert this entity using same AFPId
  1107. *
  1108. *
  1109. * LOCKS_ASSUMED: vds_idDbAccessLock (SWMR, Exclusive)
  1110. * VOID
  1111. * afpCheckDfEntry(
  1112. * IN PVOLDESC pVolDesc,
  1113. * IN PAFPINFO pAfpInfo, // AFP Info of the discovered entity
  1114. * IN PUNICODE_STRING pUName, // Munged unicode name
  1115. * IN BOOLEAN IsDir, // is this thing a file or a directory?
  1116. * IN PDFENTRY pParent, // parent DFE of the discovered thing
  1117. * OUT PDFENTRY * ppDfEntry
  1118. * );
  1119. */
  1120. #define afpCheckDfEntry(_pVolDesc, _AfpId, _pUName, _IsDir, _pParent, _ppDfEntry) \
  1121. { \
  1122. PDFENTRY pDfeNew; \
  1123. \
  1124. if (((_AfpId) > (_pVolDesc)->vds_LastId) || \
  1125. ((_AfpId) <= AFP_ID_NETWORK_TRASH) || \
  1126. (AfpFindDfEntryById(_pVolDesc, _AfpId, DFE_ANY) != NULL)) \
  1127. { \
  1128. /* add the item to the DB but assign it a new AFP Id */ \
  1129. _AfpId = 0; \
  1130. } \
  1131. \
  1132. pDfeNew = AfpAddDfEntry(_pVolDesc, \
  1133. _pParent, \
  1134. _pUName, \
  1135. _IsDir, \
  1136. _AfpId); \
  1137. \
  1138. *(_ppDfEntry) = pDfeNew; \
  1139. }
  1140. #ifdef AGE_DFES
  1141. #define afpUpdateDfeAccessTime(_pVolDesc, _pDfEntry) \
  1142. { \
  1143. if (IS_VOLUME_AGING_DFES(_pVolDesc)) \
  1144. { \
  1145. if (DFE_IS_DIRECTORY(_pDfEntry)) \
  1146. AfpGetCurrentTimeInMacFormat(&(_pDfEntry)->dfe_pDirEntry->de_LastAccessTime);\
  1147. else AfpGetCurrentTimeInMacFormat(&(_pDfEntry)->dfe_Parent->dfe_pDirEntry->de_LastAccessTime);\
  1148. } \
  1149. }
  1150. #else
  1151. #define afpUpdateDfeAccessTime(pVolDesc, pDfEntry)
  1152. #endif
  1153. #define afpMarkAllChildrenUnseen(_pDFETree) \
  1154. { \
  1155. LONG i = -1; \
  1156. PDFENTRY pDFE; \
  1157. \
  1158. /* \
  1159. * Even if this dir has not had its file children cached in \
  1160. * yet, we still want to prune out any dead directory children \
  1161. */ \
  1162. for (pDFE = (_pDFETree)->dfe_pDirEntry->de_ChildDir; \
  1163. True; \
  1164. pDFE = (_pDFETree)->dfe_pDirEntry->de_ChildFile[i]) \
  1165. { \
  1166. for (NOTHING; \
  1167. pDFE != NULL; \
  1168. pDFE = pDFE->dfe_NextSibling) \
  1169. { \
  1170. DFE_MARK_UNSEEN(pDFE); \
  1171. } \
  1172. if (++i == MAX_CHILD_HASH_BUCKETS) \
  1173. break; \
  1174. } \
  1175. }
  1176. #define afpPruneUnseenChildren(_pVolDesc, _pDFETree) \
  1177. { \
  1178. PDFENTRY pDFE, *ppDfEntry; \
  1179. LONG i; \
  1180. \
  1181. /* \
  1182. * Go thru the list of children for this parent, and if there \
  1183. * are any left that are not marked as seen, get rid of them. \
  1184. */ \
  1185. ppDfEntry = &(_pDFETree)->dfe_pDirEntry->de_ChildDir; \
  1186. i = -1; \
  1187. while (True) \
  1188. { \
  1189. while ((pDFE = *ppDfEntry) != NULL) \
  1190. { \
  1191. if (!DFE_HAS_BEEN_SEEN(pDFE)) \
  1192. { \
  1193. DBGPRINT(DBG_COMP_IDINDEX, DBG_LEVEL_INFO, \
  1194. ("afpPruneUnseenChildren: deleting nonexistant IdDb entry\n")); \
  1195. \
  1196. AfpDeleteDfEntry(_pVolDesc, pDFE); \
  1197. continue; /* make sure we don't skip any */ \
  1198. } \
  1199. ppDfEntry = &pDFE->dfe_NextSibling; \
  1200. } \
  1201. if (++i == MAX_CHILD_HASH_BUCKETS) \
  1202. { \
  1203. break; \
  1204. } \
  1205. ppDfEntry = &(_pDFETree)->dfe_pDirEntry->de_ChildFile[i]; \
  1206. } \
  1207. }
  1208. #define afpUpdateDfeWithSavedData(_pDfe, _pDiskEnt) \
  1209. { \
  1210. (_pDfe)->dfe_Flags |= (_pDiskEnt)->dsk_Flags & DFE_FLAGS_CSENCODEDBITS;\
  1211. (_pDfe)->dfe_AfpAttr = (_pDiskEnt)->dsk_AfpAttr; \
  1212. (_pDfe)->dfe_NtAttr = (_pDiskEnt)->dsk_NtAttr; \
  1213. (_pDfe)->dfe_CreateTime = (_pDiskEnt)->dsk_CreateTime; \
  1214. (_pDfe)->dfe_LastModTime = (_pDiskEnt)->dsk_LastModTime; \
  1215. (_pDfe)->dfe_BackupTime = (_pDiskEnt)->dsk_BackupTime; \
  1216. (_pDfe)->dfe_FinderInfo = (_pDiskEnt)->dsk_FinderInfo; \
  1217. if (DFE_IS_DIRECTORY((_pDfe))) \
  1218. { \
  1219. (_pDfe)->dfe_pDirEntry->de_Access = (_pDiskEnt)->dsk_Access;\
  1220. } \
  1221. else \
  1222. { \
  1223. (_pDfe)->dfe_DataLen = (_pDiskEnt)->dsk_DataLen; \
  1224. (_pDfe)->dfe_RescLen = (_pDiskEnt)->dsk_RescLen; \
  1225. } \
  1226. }
  1227. #define afpSaveDfeData(_pDfe, _pDiskEnt) \
  1228. { \
  1229. /* Write a signature for sanity checking */ \
  1230. (_pDiskEnt)->dsk_Signature = AFP_DISKENTRY_SIGNATURE; \
  1231. \
  1232. (_pDiskEnt)->dsk_AfpId = (_pDfe)->dfe_AfpId; \
  1233. (_pDiskEnt)->dsk_AfpAttr = (_pDfe)->dfe_AfpAttr; \
  1234. (_pDiskEnt)->dsk_NtAttr = (_pDfe)->dfe_NtAttr; \
  1235. (_pDiskEnt)->dsk_BackupTime = (_pDfe)->dfe_BackupTime; \
  1236. (_pDiskEnt)->dsk_CreateTime = (_pDfe)->dfe_CreateTime; \
  1237. (_pDiskEnt)->dsk_LastModTime = (_pDfe)->dfe_LastModTime; \
  1238. (_pDiskEnt)->dsk_FinderInfo = (_pDfe)->dfe_FinderInfo; \
  1239. \
  1240. /* Encode the number of characters (not bytes) in the name */ \
  1241. (_pDiskEnt)->dsk_Flags = \
  1242. ((_pDfe)->dfe_Flags & DFE_FLAGS_DFBITS) | \
  1243. ((_pDfe)->dfe_UnicodeName.Length/sizeof(WCHAR)); \
  1244. \
  1245. /* Copy the name over */ \
  1246. RtlCopyMemory(&(_pDiskEnt)->dsk_Name[0], \
  1247. (_pDfe)->dfe_UnicodeName.Buffer, \
  1248. (_pDfe)->dfe_UnicodeName.Length); \
  1249. }
  1250. // File DFEs are aged after MAX_BLOCK_AGE*FILE_BLOCK_AGE_TIME seconds (currently 2 mins)
  1251. // File DFEs are aged after MAX_BLOCK_AGE*DIR_BLOCK_AGE_TIME seconds (currently 6 mins)
  1252. #define MAX_BLOCK_AGE 6
  1253. #define FILE_BLOCK_AGE_TIME 600 // # of seconds
  1254. #define DIR_BLOCK_AGE_TIME 3600 // # of seconds
  1255. #define BLOCK_64K_ALLOC 64*1024 // Virtual mem allocates 64K chunks
  1256. #define MAX_BLOCK_TYPE 4 // For TINY, SMALL, MEDIUM & LARGE
  1257. #define VALID_DFB(pDfeBlock) ((pDfeBlock) != NULL)
  1258. typedef struct _Block64K
  1259. {
  1260. struct _Block64K *b64_Next;
  1261. PBYTE b64_BaseAddress;
  1262. DWORD b64_PagesFree;
  1263. BYTE b64_PageInUse[BLOCK_64K_ALLOC/PAGE_SIZE];
  1264. } BLOCK64K, *PBLOCK64K;
  1265. typedef struct _DfeBlock
  1266. {
  1267. struct _DfeBlock * dfb_Next; // Link to next
  1268. struct _DfeBlock ** dfb_Prev; // Link to previous
  1269. USHORT dfb_NumFree; // # of free DFEs in this block
  1270. BYTE dfb_Age; // Age of the Block if all are free
  1271. BOOLEAN dfb_fDir; // TRUE if it is a Dir DFB - else a file DFB
  1272. PDFENTRY dfb_FreeHead; // Head of the list of free DFEs
  1273. } DFEBLOCK, *PDFEBLOCK, **PPDFEBLOCK;
  1274. LOCAL PDFENTRY FASTCALL
  1275. afpAllocDfe(
  1276. IN LONG Index,
  1277. IN BOOLEAN fDir
  1278. );
  1279. LOCAL VOID FASTCALL
  1280. afpFreeDfe(
  1281. IN PDFENTRY pDfEntry
  1282. );
  1283. LOCAL AFPSTATUS FASTCALL
  1284. afpDfeBlockAge(
  1285. IN PPDFEBLOCK pBlockHead
  1286. );
  1287. #if DBG
  1288. VOID FASTCALL
  1289. afpDisplayDfe(
  1290. IN PDFENTRY pDfEntry
  1291. );
  1292. NTSTATUS FASTCALL
  1293. afpDumpDfeTree(
  1294. IN PVOID Context
  1295. );
  1296. #endif
  1297. IDDBGLOBAL PBLOCK64K afp64kBlockHead EQU NULL;
  1298. IDDBGLOBAL PDFEBLOCK afpDirDfeFreeBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1299. IDDBGLOBAL PDFEBLOCK afpDirDfePartialBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1300. IDDBGLOBAL PDFEBLOCK afpDirDfeUsedBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1301. IDDBGLOBAL PDFEBLOCK afpFileDfeFreeBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1302. IDDBGLOBAL PDFEBLOCK afpFileDfePartialBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1303. IDDBGLOBAL PDFEBLOCK afpFileDfeUsedBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
  1304. IDDBGLOBAL USHORT afpDfeUnicodeBufSize[MAX_BLOCK_TYPE] EQU \
  1305. { \
  1306. DFE_SIZE_TINY_U, DFE_SIZE_SMALL_U, \
  1307. DFE_SIZE_MEDIUM_U, DFE_SIZE_LARGE_U \
  1308. };
  1309. IDDBGLOBAL USHORT afpDfeFileBlockSize[MAX_BLOCK_TYPE] EQU \
  1310. { \
  1311. sizeof(DFENTRY) + DFE_SIZE_TINY_U, \
  1312. sizeof(DFENTRY) + DFE_SIZE_SMALL_U, \
  1313. sizeof(DFENTRY) + DFE_SIZE_MEDIUM_U, \
  1314. sizeof(DFENTRY) + DFE_SIZE_LARGE_U \
  1315. };
  1316. IDDBGLOBAL USHORT afpDfeDirBlockSize[MAX_BLOCK_TYPE] EQU \
  1317. { \
  1318. (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_TINY_U), \
  1319. (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_SMALL_U), \
  1320. (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_MEDIUM_U), \
  1321. (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_LARGE_U) \
  1322. };
  1323. IDDBGLOBAL USHORT afpDfeNumFileBlocks[MAX_BLOCK_TYPE] EQU \
  1324. { \
  1325. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1326. (sizeof(DFENTRY) + DFE_SIZE_TINY_U), \
  1327. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1328. (sizeof(DFENTRY) + DFE_SIZE_SMALL_U), \
  1329. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1330. (sizeof(DFENTRY) + DFE_SIZE_MEDIUM_U), \
  1331. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1332. (sizeof(DFENTRY) + DFE_SIZE_LARGE_U) \
  1333. };
  1334. IDDBGLOBAL USHORT afpDfeNumDirBlocks[MAX_BLOCK_TYPE] EQU \
  1335. { \
  1336. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1337. (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_TINY_U), \
  1338. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1339. (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_SMALL_U),\
  1340. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1341. (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_MEDIUM_U),\
  1342. (PAGE_SIZE - sizeof(DFEBLOCK))/ \
  1343. (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_LARGE_U) \
  1344. };
  1345. IDDBGLOBAL SWMR afpDfeBlockLock EQU { 0 };
  1346. #if DBG
  1347. IDDBGLOBAL LONG afpDfeAllocCount EQU 0;
  1348. IDDBGLOBAL LONG afpDfbAllocCount EQU 0;
  1349. IDDBGLOBAL LONG afpDfe64kBlockCount EQU 0;
  1350. IDDBGLOBAL BOOLEAN afpDumpDfeTreeFlag EQU 0;
  1351. IDDBGLOBAL PDFENTRY afpDfeStack[4096] EQU { 0 };
  1352. #endif
  1353. #undef EQU
  1354. #ifdef _GLOBALS_
  1355. #define EQU =
  1356. #else
  1357. #define EQU ; / ## /
  1358. #endif
  1359. #endif // IDINDEX_LOCALS
  1360. #endif // _IDINDEX_