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.

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