|
|
/*
Copyright (c) 1992 Microsoft Corporation
Module Name:
idindex.h
Abstract:
This module contains the file and directory id structures.
Author:
Jameel Hyder (microsoft!jameelh)
Revision History: 25 Apr 1992 Initial Version
Notes: Tab stop: 4 --*/
#ifndef _IDINDEX_
#define _IDINDEX_
// AFP_IDDBHDR_VERSION2 was an experimental version.
#define AFP_IDDBHDR_VERSION1 0x00010000
#define AFP_IDDBHDR_VERSION2 0x00020000
#define AFP_IDDBHDR_VERSION3 0x00030000
#define AFP_IDDBHDR_VERSION4 0x00040000
#define AFP_IDDBHDR_VERSION5 0x00050000
#define AFP_IDDBHDR_VERSION AFP_IDDBHDR_VERSION5
typedef struct _IdDbHeader // Database header
{ DWORD idh_Signature; // Signature
DWORD idh_Version; // Version number
DWORD idh_LastId; // Highest id that is assigned
AFPTIME idh_CreateTime; // Creation time for this volume
AFPTIME idh_ModifiedTime; // Modified time for this volume
AFPTIME idh_BackupTime; // Backup time for this volume
} IDDBHDR, *PIDDBHDR; // IdDb header is followed by a ULONG count of entries, then the DISKENTRies
#define VALID_DFE(pDfe) ((pDfe) != NULL)
struct _DfeBlock; struct _DirFileEntry;
#define MAX_CHILD_HASH_BUCKETS 6
typedef struct _DirEntry { // NOTE: Keep the ChildDir and ChildFile entries together and in this order
// The code in AfpAddDfEntry depends on this to efficiently zero it out
// Also de_ChildDir is accessed as de_ChildFile[-1] !!!
struct _DirFileEntry * de_ChildDir; // First child in the dir list
struct _DirFileEntry * de_ChildFile[MAX_CHILD_HASH_BUCKETS]; // File 'children' are hashed for faster lookup
DWORD de_Access; // Combined access bits
#ifdef AGE_DFES
AFPTIME de_LastAccessTime; // Time when this DFE was last accessed
// Valid for directories only
LONG de_ChildForkOpenCount;// Count of open forks within this directory
#endif
} DIRENTRY, *PDIRENTRY;
// Owner access mask (SFI vs. SFO)
#define DE_OWNER_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 0)
// Group access mask (SFI vs. SFO)
#define DE_GROUP_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 1)
// World access mask (SFI vs. SFO)
#define DE_WORLD_ACCESS(_pDE) *((PBYTE)(&(_pDE)->de_Access) + 2)
typedef struct _DirFileEntry { // The dfe_Overflow is overloaded with dfe_NextFree for use by the block
// allocation package for the DFEs.
#define dfe_NextFree dfe_NextOverflow
struct _DirFileEntry * dfe_NextOverflow; // Overflow links
struct _DirFileEntry ** dfe_PrevOverflow; // Overflow links
struct _DirFileEntry * dfe_NextSibling; // Next sibling.
struct _DirFileEntry ** dfe_PrevSibling; // Previous sibling.
struct _DirFileEntry * dfe_Parent; // Parent entry
DWORD dfe_AfpId; // Afp FileId or DirId (from AfpInfo)
AFPTIME dfe_BackupTime; // Backup time for the file/dir (from AfpInfo)
// (Volume backup time is stored
// in the AFP_IdIndex stream)
AFPTIME dfe_CreateTime; // Creation time
TIME dfe_LastModTime; // Last modify time (as a LARGE_INTEGER)
SHORT dfe_DirDepth; // Parent of root at -1, root at 0
USHORT dfe_Flags; // file, dir or file with id
USHORT dfe_NtAttr; // NT Attributes (FILE_ATTRIBUTE_VALID_FLAGS)
USHORT dfe_AfpAttr; // Attributes mask (From AfpInfo)
union { // File specific information
struct // For Files Only
{ DWORD dfe_DataLen; // Data fork length
DWORD dfe_RescLen; // Resource fork length
}; // Directory specific information
struct // For Directories Only
{ DWORD dfe_DirOffspring; // count of dir offspring
DWORD dfe_FileOffspring; // count of file offspring
}; }; FINDERINFO dfe_FinderInfo; // Finder Info (32 bytes) (from AfpInfo)
// NOTE: When Dfes are copied as a structure, the fields below are NOT TO BE COPIED.
// The fields above should be.
#define dfe_CopyUpto dfe_UnicodeName
UNICODE_STRING dfe_UnicodeName; // 'Munged' Unicode Name of the entity
DWORD dfe_NameHash; // Hash value for the upcased munged Unicode name
// For directories, the DirEntry structure follows this structure. The space for
// this is allocated immediately after the DFENTRY structure and before the space
// for the name strings. For files it is NULL. This pointer should not be copied
// as well !!!
PDIRENTRY dfe_pDirEntry; // Directory related fields
// NULL for files
} DFENTRY, *PDFENTRY;
// Owner access mask (SFI vs. SFO)
#define DFE_OWNER_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 0)
// Group access mask (SFI vs. SFO)
#define DFE_GROUP_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 1)
// World access mask (SFI vs. SFO)
#define DFE_WORLD_ACCESS(_pDFE) *((PBYTE)(&(_pDFE)->dfe_pDirEntry->de_Access) + 2)
typedef struct _EnumIdAndType { DWORD eit_Id; DWORD eit_Flags; } EIT, *PEIT;
// There is the result of enumeration of a directory for this session and is stored
// within the connection descriptor. This is purely for performance reasons. This is
// deleted whenever an api other than AfpEnumerate is called and a result is around.
typedef struct _EnumDir { DWORD ed_ParentDirId; // Anchor point
DWORD ed_Bitmap; // Combination of file & dir bitmaps
LONG ed_ChildCount; // Count of children of the dir being enumerated
AFPTIME ed_TimeStamp; // Time at which created
PEIT ed_pEit; // list of actual entries
ANSI_STRING ed_PathName; // This is the name as passed by the client
// and is not normalised.
USHORT ed_BadCount; // Count of failed entities
BYTE ed_PathType; // Long name or short name
} ENUMDIR, *PENUMDIR;
typedef struct _CatSearchSpec { BYTE __StructLength; BYTE __FillerOrFileDir; // The rest of the parameters follow
} CATSEARCHSPEC, *PCATSEARCHSPEC;
// Must be 16 bytes as per AfpCatSearch API
typedef struct _CatalogPosition { USHORT cp_Flags; // if zero, then start search from beginning
USHORT cp_usPad1; DWORD cp_CurParentId; DWORD cp_NextFileId; AFPTIME cp_TimeStamp; } CATALOGPOSITION, *PCATALOGPOSITION;
#define CATFLAGS_SEARCHING_FILES 0x0001
#define CATFLAGS_SEARCHING_DIRCHILD 0x0002
#define CATFLAGS_SEARCHING_SIBLING 0x0004
#define CATFLAGS_WRITELOCK_REQUIRED 0x0008
#define CATFLAGS_VALID (CATFLAGS_SEARCHING_FILES | \
CATFLAGS_SEARCHING_DIRCHILD | \ CATFLAGS_SEARCHING_SIBLING | \ CATFLAGS_WRITELOCK_REQUIRED)
// Maximum time that a mac can hold onto a catsearch position and still
// have the search pickup from there instead of the beginning of the catalog
#define MAX_CATSEARCH_TIME 3600 // In seconds
// DFE_FLAGS_xxxx values for dfe_Flags field of DFENTRY structure
#define DFE_FLAGS_FILE_WITH_ID 0x0100
#define DFE_FLAGS_FILE_NO_ID 0x0200
#define DFE_FLAGS_DIR 0x0400
#define DFE_FLAGS_DFBITS (DFE_FLAGS_FILE_WITH_ID | \
DFE_FLAGS_FILE_NO_ID | \ DFE_FLAGS_DIR | \ DFE_FLAGS_HAS_COMMENT) #define DFE_FLAGS_HAS_COMMENT 0x0800
#define DFE_FLAGS_INIT_COMPLETED 0x20
#define DFE_FLAGS_ENUMERATED 0x8000
// Encode the child and sibling pointers
#define DFE_FLAGS_HAS_CHILD 0x1000 // Used for reading in IdDb from disk
#define DFE_FLAGS_HAS_SIBLING 0x2000 // Used for reading in IdDb from disk
#define DFE_FLAGS_CSENCODEDBITS (DFE_FLAGS_HAS_CHILD | DFE_FLAGS_HAS_SIBLING | DFE_FLAGS_HAS_COMMENT)
#define DFE_FLAGS_NAMELENBITS 0x001F // Encodes the length of the longname
// which is 31 *characters* max
#define DFE_FLAGS_VALID_DSKBITS (DFE_FLAGS_CSENCODEDBITS | \
DFE_FLAGS_NAMELENBITS | \ DFE_FLAGS_HAS_COMMENT)
// Valid only for directories when their files have been enumerated from disk
// and now all have cached DFEs in the IDDB tree structure
#define DFE_FLAGS_FILES_CACHED 0x4000
// DAlreadyOpen and RAlreadyOpen flags for a File
#define DFE_FLAGS_R_ALREADYOPEN 0x0040
#define DFE_FLAGS_D_ALREADYOPEN 0x0080
#define DFE_FLAGS_OPEN_BITS (DFE_FLAGS_D_ALREADYOPEN | \
DFE_FLAGS_R_ALREADYOPEN)
typedef struct _DiskEntry { DWORD dsk_AfpId; AFPTIME dsk_CreateTime; // File Creation time
TIME dsk_LastModTime; // Last modify time
FINDERINFO dsk_FinderInfo; // Finder Info (32 bytes) (from AfpInfo)
AFPTIME dsk_BackupTime; // Backup time for the file/dir (from AfpInfo)
// (Volume backup time is stored
// in the AFP_IdIndex stream)
union { DWORD dsk_DataLen; // Data fork length
DWORD dsk_Access; // Combined access rights
}; DWORD dsk_RescLen; // Resource fork length
USHORT dsk_Flags; // DFE_FLAGS_XXXX
USHORT dsk_AfpAttr; // Attributes mask (From AfpInfo)
USHORT dsk_NtAttr; // From FileAttributes
USHORT dsk_Signature; // AFP_DISKENTRY_SIGNATURE
WCHAR dsk_Name[2]; // Longname in 'munged' Unicode will follow and be padded
// out, if necessary, to DWORD boundry (max 64 bytes)
} DISKENTRY, *PDISKENTRY;
// "::" = 0x3a3a illegal name character
#define AFP_DISKENTRY_SIGNATURE 0x3a3a // illegal name character
// size of buffer used to read-in/write-out the IdDb entries from/to disk
#define IDDB_UPDATE_BUFLEN (16*1024)
// Round the length to 4*N
#define DWLEN(_b) (((_b) + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1))
// #define DFE_IS_DIRECTORY(_pDFE) (((_pDFE)->dfe_Flags & DFE_FLAGS_DIR) ? True : False)
#define DFE_IS_DIRECTORY(_pDFE) ((_pDFE)->dfe_pDirEntry != NULL)
// #define DFE_IS_FILE(_pDFE) (((_pDFE)->dfe_Flags & (DFE_FLAGS_FILE_NO_ID | DFE_FLAGS_FILE_WITH_ID)) ? True : False)
#define DFE_IS_FILE(_pDFE) ((_pDFE)->dfe_pDirEntry == NULL)
#define DFE_IS_FILE_WITH_ID(_pDFE) (((_pDFE)->dfe_Flags & DFE_FLAGS_FILE_WITH_ID) ? True : False)
#define DFE_IS_ROOT(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_ROOT)
#define DFE_IS_PARENT_OF_ROOT(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_PARENT_OF_ROOT)
#define DFE_IS_NWTRASH(_pDFE) ((_pDFE)->dfe_AfpId == AFP_ID_NETWORK_TRASH)
#define DFE_SET_DIRECTORY(_pDFE, _ParentDepth) \
{ \ ((_pDFE)->dfe_DirDepth = _ParentDepth + 1); \ ((_pDFE)->dfe_Flags |= DFE_FLAGS_DIR); \ }
#define DFE_SET_FILE(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILE_NO_ID)
#define DFE_SET_FILE_ID(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILE_WITH_ID)
#define DFE_CLR_FILE_ID(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_FILE_WITH_ID)
// update just the AFPinfo in the dfentry
#define DFE_UPDATE_CACHED_AFPINFO(_pDFE, pAfpInfo) \
{ \ (_pDFE)->dfe_BackupTime = (pAfpInfo)->afpi_BackupTime; \ (_pDFE)->dfe_FinderInfo = (pAfpInfo)->afpi_FinderInfo; \ (_pDFE)->dfe_AfpAttr = (pAfpInfo)->afpi_Attributes; \ if ((_pDFE)->dfe_Flags & DFE_FLAGS_DIR) \ { \ DFE_OWNER_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessOwner; \ DFE_GROUP_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessGroup; \ DFE_WORLD_ACCESS(_pDFE) = (pAfpInfo)->afpi_AccessWorld; \ } \ }
#define DFE_SET_COMMENT(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_HAS_COMMENT)
#define DFE_CLR_COMMENT(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_HAS_COMMENT)
// Check to see if this entry was enumerated on an NTFS directory
#define DFE_HAS_BEEN_SEEN(_pDFE) ((_pDFE)->dfe_Flags & DFE_FLAGS_ENUMERATED)
#define DFE_MARK_UNSEEN(_pDFE) ((_pDFE)->dfe_Flags &= ~DFE_FLAGS_ENUMERATED)
#define DFE_MARK_AS_SEEN(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_ENUMERATED)
// Directories only
#define DFE_CHILDREN_ARE_PRESENT(_pDFE) ((_pDFE)->dfe_Flags & DFE_FLAGS_FILES_CACHED)
// Directories only
#define DFE_MARK_CHILDREN_PRESENT(_pDFE) ((_pDFE)->dfe_Flags |= DFE_FLAGS_FILES_CACHED)
#define DFE_FILE_HAS_SIBLING(_pDFE, _fbi, _pfHasSibling) \
{ \ DWORD _i; \ PDIRENTRY _pDirEntry; \ \ *(_pfHasSibling) = False; \ if (((_pDFE)->dfe_NextSibling != NULL) || \ ((_pDFE)->dfe_Parent->dfe_pDirEntry->de_ChildDir != NULL)) \ { \ *(_pfHasSibling) = True; \ } \ else \ { \ _pDirEntry = (_pDFE)->dfe_Parent->dfe_pDirEntry; \ ASSERT(_pDirEntry != NULL); \ for (_i = (_fbi) + 1; \ _i < MAX_CHILD_HASH_BUCKETS; \ _i++) \ { \ if (_pDirEntry->de_ChildFile[_i] != NULL) \ { \ *(_pfHasSibling) = True; \ break; \ } \ } \ } \ }
#define HASH_DIR_ID(Id, _pVolDesc) ((Id) & ((_pVolDesc)->vds_DirHashTableSize-1))
#define HASH_FILE_ID(Id, _pVolDesc) ((Id) & ((_pVolDesc)->vds_FileHashTableSize-1))
#define HASH_CACHE_ID(Id) ((Id) & (IDINDEX_CACHE_ENTRIES-1))
#define QUAD_SIZED(_X_) (((_X_) % 8) == 0)
// Values for access checking
#define ACCESS_READ 1
#define ACCESS_WRITE 2
extern NTSTATUS AfpDfeInit( VOID );
extern VOID AfpDfeDeInit( VOID );
extern PDFENTRY AfpFindDfEntryById( IN struct _VolDesc * pVolDesc, IN DWORD Id, IN DWORD EntityMask );
extern PDFENTRY AfpFindEntryByUnicodeName( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pName, IN DWORD PathType, IN PDFENTRY pDfeParent, IN DWORD EntityMask );
extern PDFENTRY AfpAddDfEntry( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfeParent, IN PUNICODE_STRING pUName, IN BOOLEAN Directory, IN DWORD AfpId OPTIONAL );
extern PDFENTRY AfpRenameDfEntry( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfEntry, IN PUNICODE_STRING pNewName );
extern PDFENTRY AfpMoveDfEntry( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfEntry, IN PDFENTRY pNewParentDfE, IN PUNICODE_STRING pNewName OPTIONAL );
extern VOID FASTCALL AfpDeleteDfEntry( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfE );
extern VOID AfpExchangeIdEntries( IN struct _VolDesc * pVolDesc, IN DWORD AfpId1, IN DWORD AfpId2 );
extern VOID FASTCALL AfpPruneIdDb( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfeTarget );
extern NTSTATUS FASTCALL AfpInitIdDb( IN struct _VolDesc * pVolDesc, OUT BOOLEAN * pfNewVolume, OUT BOOLEAN * pfVerifyIndex );
extern VOID FASTCALL AfpFreeIdIndexTables( IN struct _VolDesc * pVolDesc );
extern AFPSTATUS AfpEnumerate( IN struct _ConnDesc * pConnDesc, IN DWORD ParentDirId, IN PANSI_STRING pPath, IN DWORD BitmapF, IN DWORD BitmapD, IN BYTE PathType, IN DWORD DFFlags, OUT PENUMDIR * ppEnumDir );
extern AFPSTATUS AfpSetDFFileFlags( IN struct _VolDesc * pVolDesc, IN DWORD AfpId, IN DWORD FlagSet OPTIONAL, IN BOOLEAN SetFileId, IN BOOLEAN ClrFileId );
extern VOID AfpChangeNotifyThread( IN PVOID pContext );
extern VOID FASTCALL AfpProcessChangeNotify( IN struct _VolumeNotify * pVolNotify );
extern VOID AfpQueuePrivateChangeNotify( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pName, IN PUNICODE_STRING pPath, IN DWORD ParentId );
extern BOOLEAN FASTCALL AfpShouldWeIgnoreThisNotification( IN struct _VolumeNotify * pVolNotify );
extern VOID AfpQueueOurChange( IN struct _VolDesc * pVolDesc, IN DWORD Action, IN PUNICODE_STRING pPath, IN PUNICODE_STRING pParentPath OPTIONAL );
extern VOID AfpDequeueOurChange( IN struct _VolDesc * pVolDesc, IN DWORD Action, IN PUNICODE_STRING pPath, IN PUNICODE_STRING pParentPath OPTIONAL );
extern NTSTATUS FASTCALL AddToDelayedNotifyList( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pUName );
extern NTSTATUS RemoveFromDelayedNotifyList( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pUName, IN PFILE_NOTIFY_INFORMATION pFNInfo );
extern NTSTATUS CheckAndProcessDelayedNotify( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pUName, IN PUNICODE_STRING pUNewname, IN PUNICODE_STRING pUParent );
extern VOID AfpCacheParentModTime( IN struct _VolDesc * pVolDesc, IN PFILESYSHANDLE pHandle OPTIONAL, // if pPath not supplied
IN PUNICODE_STRING pPath OPTIONAL, // if pHandle not supplied
IN PDFENTRY pDfeParent OPTIONAL, // if ParentId not supplied
IN DWORD ParentId OPTIONAL // if pDfeParent not supplied
);
extern AFPSTATUS AfpCatSearch( IN struct _ConnDesc * pConnDesc, IN PCATALOGPOSITION pCatPosition, IN DWORD Bitmap, IN DWORD FileBitmap, IN DWORD DirBitmap, IN struct _FileDirParms * pFDParm1, IN struct _FileDirParms * pFDParm2, IN PUNICODE_STRING pMatchString OPTIONAL, IN OUT PDWORD pCount, IN SHORT Buflen, OUT PSHORT pSizeLeft, OUT PBYTE pResults, OUT PCATALOGPOSITION pNewCatPosition );
#ifdef AGE_DFES
extern VOID FASTCALL AfpAgeDfEntries( IN struct _VolDesc * pVolDesc );
#endif
#define REENUMERATE 0x0001
#define GETDIRSKELETON 0x0002
#define GETFILES 0x0004
#define GETENTIRETREE 0x0008
extern NTSTATUS AfpCacheDirectoryTree( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDFETreeRoot, IN DWORD Method, IN PFILESYSHANDLE phRootDir OPTIONAL, IN PUNICODE_STRING pDirPath OPTIONAL );
extern AFPSTATUS FASTCALL AfpOurChangeScavenger( IN struct _VolDesc * pVolDesc );
extern VOID FASTCALL AfpFlushIdDb( IN struct _VolDesc * pVolDesc, IN PFILESYSHANDLE phIdDb );
extern VOID AfpGetDirFileHashSizes( IN struct _VolDesc * pVolDesc, OUT PDWORD pdwDirHashSz, OUT PDWORD pdwFileHashSz );
#ifdef IDINDEX_LOCALS
#define afpConvertBasicToBothDirInfo(_pFBasInfo, _pFBDInfo) \
{ \ (_pFBDInfo)->CreationTime = (_pFBasInfo)->CreationTime; \ (_pFBDInfo)->LastWriteTime = (_pFBasInfo)->LastWriteTime; \ (_pFBDInfo)->ChangeTime = (_pFBasInfo)->ChangeTime; \ (_pFBDInfo)->FileAttributes = (_pFBasInfo)->FileAttributes; \ (_pFBDInfo)->EndOfFile.QuadPart = 0; \ }
#undef EQU
#ifdef _IDDB_GLOBALS_
#define IDDBGLOBAL
#define EQU =
#else
#define IDDBGLOBAL extern
#define EQU ; / ## /
#endif
// This bit on a Notify action indicates it is a simulated notify. Volume
// modified time is not updated when such a notify comes in
#define AFP_ACTION_PRIVATE 0x80000000
// DFEs come in four sizes. This helps in efficiently managing them in a block
// package (see later). THESE SIZES NEED TO BE 4*N, else we run into alignment
// faults on architectures that require it.
#define DFE_INDEX_TINY 0
#define DFE_INDEX_SMALL 1
#define DFE_INDEX_MEDIUM 2
#define DFE_INDEX_LARGE 3
//
// Make sure each of the sizes below (XXX_U) are multiple of 8
//
#define DFE_SIZE_TINY 8 // These are lengths for ANSI names
#define DFE_SIZE_SMALL 12 // - ditto -
#define DFE_SIZE_MEDIUM 20 // - ditto -
#define DFE_SIZE_LARGE 32 // - ditto - corres. to AFP_FILENAME_LEN
#define DFE_SIZE_TINY_U DFE_SIZE_TINY*sizeof(WCHAR) // These are lengths for UNICODE names
#define DFE_SIZE_SMALL_U DFE_SIZE_SMALL*sizeof(WCHAR) // - ditto -
#define DFE_SIZE_MEDIUM_U DFE_SIZE_MEDIUM*sizeof(WCHAR) // - ditto -
#define DFE_SIZE_LARGE_U DFE_SIZE_LARGE*sizeof(WCHAR) // - ditto - corres. to AFP_FILENAME_LEN
#define ASIZE_TO_INDEX(_Size) \
(((_Size) <= DFE_SIZE_TINY) ? DFE_INDEX_TINY : \ (((_Size) <= DFE_SIZE_SMALL) ? DFE_INDEX_SMALL : \ (((_Size) <= DFE_SIZE_MEDIUM) ? DFE_INDEX_MEDIUM : DFE_INDEX_LARGE)))
#define USIZE_TO_INDEX(_Size) \
(((_Size) <= DFE_SIZE_TINY_U) ? DFE_INDEX_TINY : \ (((_Size) <= DFE_SIZE_SMALL_U) ? DFE_INDEX_SMALL : \ (((_Size) <= DFE_SIZE_MEDIUM_U) ? DFE_INDEX_MEDIUM : DFE_INDEX_LARGE)))
#define ALLOC_DFE(Index, fDir) afpAllocDfe(Index, fDir)
#define FREE_DFE(pDfEntry) afpFreeDfe(pDfEntry)
LOCAL DWORD FASTCALL afpGetNextId( IN struct _VolDesc * pVolDesc );
LOCAL NTSTATUS FASTCALL afpSeedIdDb( IN struct _VolDesc * pVolDesc );
LOCAL VOID afpPackSearchParms( IN PDFENTRY pDfe, IN DWORD Bitmap, IN PBYTE pBuf );
LOCAL NTSTATUS FASTCALL afpReadIdDb( IN struct _VolDesc * pVolDesc, IN PFILESYSHANDLE pfshIdDb, OUT BOOLEAN * pfVerifyIndex );
VOID afpAddDfEntryAndCacheInfo( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfeParent, IN PUNICODE_STRING pUName, // munged unicode name
IN PFILESYSHANDLE pfshParentDir, // open handle to parent directory
IN PFILE_BOTH_DIR_INFORMATION pFBDInfo, // from enumerate
IN PUNICODE_STRING pNotifyPath, // to filter out our own AFP_AfpInfo change notifies
IN PDFENTRY * ppDfEntry, IN BOOLEAN CheckDuplicate );
VOID afpVerifyDFE( IN struct _VolDesc * pVolDesc, IN PDFENTRY pDfeParent, IN PUNICODE_STRING pUName, // munged unicode name
IN PFILESYSHANDLE pfshParentDir, // open handle to parent directory
IN PFILE_BOTH_DIR_INFORMATION pFBDInfo, // from enumerate
IN PUNICODE_STRING pNotifyPath, // to filter out our own AFP_AfpInfo change notifies
IN PDFENTRY * ppDfEntry );
PDFENTRY afpFindEntryByNtPath( IN struct _VolDesc * pVolDesc, IN DWORD ChangeAction, // if ADDED then lookup parent DFE
IN PUNICODE_STRING pPath, OUT PUNICODE_STRING pParent, OUT PUNICODE_STRING pTail );
PDFENTRY afpFindEntryByNtName( IN struct _VolDesc * pVolDesc, IN PUNICODE_STRING pName, IN PDFENTRY pDfeParent // pointer to parent DFENTRY
);
VOID FASTCALL afpProcessPrivateNotify( IN struct _VolumeNotify * pVolNotify );
VOID FASTCALL afpActivateVolume( IN struct _VolDesc * pVolDesc );
VOID afpRenameInvalidWin32Name( IN PFILESYSHANDLE phRootDir, IN BOOLEAN IsDir, IN PUNICODE_STRING pName );
#define afpInitializeIdDb(_pVolDesc) \
{ \ AFPTIME CurrentTime; \ PDFENTRY pDfEntry; \ \ /* RO volumes don't use the network trash folder at all */ \ (_pVolDesc)->vds_LastId = AFP_ID_NETWORK_TRASH; \ \ AfpGetCurrentTimeInMacFormat(&CurrentTime); \ (_pVolDesc)->vds_CreateTime = CurrentTime; \ (_pVolDesc)->vds_ModifiedTime = CurrentTime; \ (_pVolDesc)->vds_BackupTime = BEGINNING_OF_TIME; \ \ /* Create a DFE for the root directory */ \ afpCreateParentOfRoot(_pVolDesc, &pDfEntry); \ }
#ifdef AGE_DFES
#define afpCreateParentOfRoot(_pVolDesc, _ppDfEntry) \
{ \ PDFENTRY pDFE; \ struct _DirFileEntry ** _DfeDirBucketStart; \ \ /* \
* add the parent of root to the id index. \ * This has to be done here \ * (i.e. cannot call AfpAddDfEntry for parentofroot). \ */ \ \ if ((*(_ppDfEntry) = ALLOC_DFE(0, True)) != NULL) \ { \ pDFE = *(_ppDfEntry); \ \ (_pVolDesc)->vds_NumFileDfEntries = 0; \ (_pVolDesc)->vds_NumDirDfEntries = 0; \ pDFE->dfe_Flags = DFE_FLAGS_DIR | DFE_FLAGS_FILES_CACHED; \ pDFE->dfe_DirDepth = -1; \ pDFE->dfe_Parent = NULL; \ pDFE->dfe_NextOverflow = NULL; \ \ /* Initialize the DirEntry for ParentOfRoot */ \ ASSERT((FIELD_OFFSET(DIRENTRY, de_ChildFile) - \ FIELD_OFFSET(DIRENTRY, de_ChildDir)) == sizeof(PVOID));\ \ /* These fields are relevant to directories only */ \ pDFE->dfe_pDirEntry->de_LastAccessTime = BEGINNING_OF_TIME; \ pDFE->dfe_pDirEntry->de_ChildForkOpenCount = 0; \ \ /* \
* The parent of root has no siblings and this should \ * never be referenced \ */ \ pDFE->dfe_NameHash = 0; \ pDFE->dfe_NextSibling = NULL; \ pDFE->dfe_PrevSibling = NULL; \ pDFE->dfe_AfpId = AFP_ID_PARENT_OF_ROOT; \ pDFE->dfe_DirOffspring = pDFE->dfe_FileOffspring = 0; \ \ /* link it into the hash buckets */ \ _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \ AfpLinkDoubleAtHead(_DfeDirBucketStart[HASH_DIR_ID(AFP_ID_PARENT_OF_ROOT,_pVolDesc)],\ pDFE, \ dfe_NextOverflow, \ dfe_PrevOverflow); \ } \ }
#else
#define afpCreateParentOfRoot(_pVolDesc, _ppDfEntry) \
{ \ PDFENTRY pDfEntry; \ struct _DirFileEntry ** _DfeDirBucketStart; \ \ /* \
* add the parent of root to the id index. \ * This has to be done here \ * (i.e. cannot call AfpAddDfEntry for parentofroot). \ */ \ \ if ((*(_ppDfEntry) = ALLOC_DFE(0, True)) != NULL) \ { \ pDfEntry = *(_ppDfEntry); \ \ (_pVolDesc)->vds_NumFileDfEntries = 0; \ (_pVolDesc)->vds_NumDirDfEntries = 0; \ pDfEntry->dfe_Flags = DFE_FLAGS_DIR | DFE_FLAGS_FILES_CACHED;\ pDfEntry->dfe_DirDepth = -1; \ pDfEntry->dfe_Parent = NULL; \ pDfEntry->dfe_NextOverflow = NULL; \ \ /* Initialize the DirEntry for ParentOfRoot */ \ ASSERT((FIELD_OFFSET(DIRENTRY, de_ChildFile) - \ FIELD_OFFSET(DIRENTRY, de_ChildDir)) == sizeof(PVOID));\ \ /* The parent of root has no siblings and this should never be referenced */ \ pDfEntry->dfe_NameHash = 0; \ pDfEntry->dfe_NextSibling = NULL; \ pDfEntry->dfe_PrevSibling = NULL; \ pDfEntry->dfe_AfpId = AFP_ID_PARENT_OF_ROOT; \ pDfEntry->dfe_DirOffspring = pDfEntry->dfe_FileOffspring = 0;\ \ /* link it into the hash buckets */ \ _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \ AfpLinkDoubleAtHead(_DfeDirBucketStart[HASH_DIR_ID(AFP_ID_PARENT_OF_ROOT,_pVolDesc)],\ pDfEntry, \ dfe_NextOverflow, \ dfe_PrevOverflow); \ } \ }
#endif
#define afpHashUnicodeName(_pUnicodeName, _pHashValue) \
{ \ DWORD j; \ UNICODE_STRING upcaseName; \ WCHAR buffer[AFP_LONGNAME_LEN+1]; \ PDWORD pbuf = NULL; \ \ AfpSetEmptyUnicodeString(&upcaseName, sizeof(buffer), buffer); \ RtlUpcaseUnicodeString(&upcaseName, _pUnicodeName, False); \ j = upcaseName.Length/sizeof(WCHAR); \ buffer[j] = UNICODE_NULL; \ pbuf = (PDWORD)buffer; \ j /= (sizeof(DWORD)/sizeof(WCHAR)); \ \ for (*(_pHashValue) = 0; j > 0; j--, pbuf++) \ { \ *(_pHashValue) = (*(_pHashValue) << 3) + *pbuf; \ } \ }
#ifdef SORT_DFE_BY_HASH
#define afpFindDFEByUnicodeNameInSiblingList(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
{ \ DWORD NameHash; \ PDFENTRY pD, pF; \ BOOLEAN Found, fFiles; \ \ afpHashUnicodeName(_pName, &NameHash); \ \ pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \ if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \ pD = NULL; \ \ pF = NULL; \ if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \ pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\ \ *(_ppDfEntry) = pD; \ Found = fFiles = False; \ do \ { \ for (NOTHING; \ *(_ppDfEntry) != NULL; \ *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \ { \ if ((*(_ppDfEntry))->dfe_NameHash < NameHash) \ { \ *(_ppDfEntry) = NULL; \ break; \ } \ \ if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \ EQUAL_UNICODE_STRING(&((*(_ppDfEntry))->dfe_UnicodeName), \ _pName, \ True)) \ { \ afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \ Found = True; \ break; \ } \ } \ if (Found) \ break; \ \ fFiles ^= True; \ if (fFiles) \ { \ *(_ppDfEntry) = pF; \ } \ } while (fFiles); \ }
#define afpFindDFEByUnicodeNameInSiblingList_CS(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
{ \ DWORD NameHash; \ PDFENTRY pD, pF; \ BOOLEAN Found, fFiles; \ \ afpHashUnicodeName(_pName, &NameHash); \ \ pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \ if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \ pD = NULL; \ \ pF = NULL; \ if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \ pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\ \ *(_ppDfEntry) = pD; \ Found = fFiles = False; \ do \ { \ for (NOTHING; \ *(_ppDfEntry) != NULL; \ *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \ { \ if ((*(_ppDfEntry))->dfe_NameHash < NameHash) \ { \ *(_ppDfEntry) = NULL; \ break; \ } \ \ if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \ EQUAL_UNICODE_STRING_CS(&((*(_ppDfEntry))->dfe_UnicodeName), _pName)) \ { \ afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \ Found = True; \ break; \ } \ } \ if (Found) \ break; \ \ fFiles ^= True; \ if (fFiles) \ { \ *(_ppDfEntry) = pF; \ } \ } while (fFiles); \ } #else
#define afpFindDFEByUnicodeNameInSiblingList(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
{ \ DWORD NameHash; \ PDFENTRY pD, pF; \ BOOLEAN Found, fFiles; \ \ afpHashUnicodeName(_pName, &NameHash); \ \ pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \ if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \ pD = NULL; \ \ pF = NULL; \ if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \ pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\ \ *(_ppDfEntry) = pD; \ Found = fFiles = False; \ do \ { \ for (NOTHING; \ *(_ppDfEntry) != NULL; \ *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \ { \ if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \ EQUAL_UNICODE_STRING(&((*(_ppDfEntry))->dfe_UnicodeName), \ _pName, \ True)) \ { \ afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \ Found = True; \ break; \ } \ } \ if (Found) \ break; \ \ fFiles ^= True; \ if (fFiles) \ { \ *(_ppDfEntry) = pF; \ } \ } while (fFiles); \ }
#define afpFindDFEByUnicodeNameInSiblingList_CS(_pVolDesc, _pDfeParent, _pName, _ppDfEntry, _EntityMask) \
{ \ DWORD NameHash; \ PDFENTRY pD, pF; \ BOOLEAN Found, fFiles; \ \ afpHashUnicodeName(_pName, &NameHash); \ \ pD = (_pDfeParent)->dfe_pDirEntry->de_ChildDir; \ if (((_EntityMask) & (DFE_ANY | DFE_DIR)) == 0) \ pD = NULL; \ \ pF = NULL; \ if ((_EntityMask) & (DFE_ANY | DFE_FILE)) \ pF = (_pDfeParent)->dfe_pDirEntry->de_ChildFile[NameHash % MAX_CHILD_HASH_BUCKETS];\ \ *(_ppDfEntry) = pD; \ Found = fFiles = False; \ do \ { \ for (NOTHING; \ *(_ppDfEntry) != NULL; \ *(_ppDfEntry) = (*(_ppDfEntry))->dfe_NextSibling) \ { \ if (((*(_ppDfEntry))->dfe_NameHash == NameHash) && \ EQUAL_UNICODE_STRING_CS(&((*(_ppDfEntry))->dfe_UnicodeName), _pName)) \ { \ afpUpdateDfeAccessTime(_pVolDesc, *(_ppDfEntry)); \ Found = True; \ break; \ } \ } \ if (Found) \ break; \ \ fFiles ^= True; \ if (fFiles) \ { \ *(_ppDfEntry) = pF; \ } \ } while (fFiles); \ } #endif
#define afpInsertDFEInSiblingList(_pDfeParent, _pDfEntry, _fDirectory) \
{ \ if (fDirectory) \ { \ afpInsertDirDFEInSiblingList(_pDfeParent, _pDfEntry); \ } \ else \ { \ afpInsertFileDFEInSiblingList(_pDfeParent, _pDfEntry); \ } \ }
#define afpInsertFileDFEInSiblingList(_pDfeParent, _pDfEntry) \
{ \ DWORD Index; \ PDFENTRY * ppDfEntry; \ \ Index = (_pDfEntry)->dfe_NameHash % MAX_CHILD_HASH_BUCKETS; \ ppDfEntry = &(_pDfeParent)->dfe_pDirEntry->de_ChildFile[Index]; \ afpInsertInSiblingList(ppDfEntry, \ (_pDfEntry)); \ }
#define afpInsertDirDFEInSiblingList(_pDfeParent, _pDfEntry) \
{ \ PDFENTRY * ppDfEntry; \ \ ppDfEntry = &(_pDfeParent)->dfe_pDirEntry->de_ChildDir; \ afpInsertInSiblingList(ppDfEntry, \ (_pDfEntry)); \ }
#ifdef SORT_DFE_BY_HASH
#define afpInsertInSiblingList(_ppHead, _pDfEntry) \
{ \ for (NOTHING; \ *(_ppHead) != NULL; \ (_ppHead) = &(*(_ppHead))->dfe_NextSibling) \ { \ if ((_pDfEntry)->dfe_NameHash > (*(_ppHead))->dfe_NameHash) \ { \ break; \ } \ } \ if (*(_ppHead) != NULL) \ { \ AfpInsertDoubleBefore(_pDfEntry, \ *(_ppHead), \ dfe_NextSibling, \ dfe_PrevSibling); \ } \ else \ { \ *(_ppHead) = (_pDfEntry); \ (_pDfEntry)->dfe_NextSibling = NULL; \ (_pDfEntry)->dfe_PrevSibling = (_ppHead); \ } \ } #else
#define afpInsertInSiblingList(_ppHead, _pDfEntry) \
{ \ AfpLinkDoubleAtHead(*(_ppHead), \ (_pDfEntry), \ dfe_NextSibling, \ dfe_PrevSibling); \ } #endif
#define afpInsertDFEInHashBucket(_pVolDesc, _pDfEntry, _fDirectory, _pfS)\
{ \ PDFENTRY *ppTmp; \ struct _DirFileEntry ** _DfeDirBucketStart; \ struct _DirFileEntry ** _DfeFileBucketStart; \ \ afpUpdateDfeAccessTime(_pVolDesc, _pDfEntry); \ *(_pfS) = True; /* Assume success */ \ \ retry: \ \ if (_fDirectory) \ { \ _DfeDirBucketStart = (_pVolDesc)->vds_pDfeDirBucketStart; \ ppTmp = &_DfeDirBucketStart[HASH_DIR_ID((_pDfEntry)->dfe_AfpId,_pVolDesc)]; \ } \ else \ { \ _DfeFileBucketStart = (_pVolDesc)->vds_pDfeFileBucketStart; \ ppTmp = &_DfeFileBucketStart[HASH_FILE_ID((_pDfEntry)->dfe_AfpId,_pVolDesc)]; \ } \ \ for (NOTHING; \ *ppTmp != NULL; \ ppTmp = &(*ppTmp)->dfe_NextOverflow) \ { \ ASSERT(VALID_DFE(*ppTmp)); \ if ((_pDfEntry)->dfe_AfpId > (*ppTmp)->dfe_AfpId) \ { \ /* Found our slot */ \ break; \ } \ if ((_pDfEntry)->dfe_AfpId == (*ppTmp)->dfe_AfpId) \ { \ /* Found a collision. Assign a new id and proceed */ \ (_pDfEntry)->dfe_AfpId = afpGetNextId(_pVolDesc); \ if ((_pDfEntry)->dfe_AfpId == 0) \ { \ /* Uh-oh */ \ *(_pfS) = False; \ DBGPRINT(DBG_COMP_IDINDEX, DBG_LEVEL_ERR, \ ("afpInsertDFEInHashBucket: Collision & Id Overflow\n"));\ break; \ } \ /* Write back the afpinfo stream with the new id */ \ AfpUpdateIdInAfpInfo(_pVolDesc, _pDfEntry); \ goto retry; \ } \ } \ if (*(_pfS)) \ { \ if (*ppTmp != NULL) \ { \ AfpInsertDoubleBefore((_pDfEntry), \ *ppTmp, \ dfe_NextOverflow, \ dfe_PrevOverflow); \ } \ else \ { \ *ppTmp = _pDfEntry; \ (_pDfEntry)->dfe_PrevOverflow = ppTmp; \ } \ (_pVolDesc)->vds_pDfeCache[HASH_CACHE_ID((_pDfEntry)->dfe_AfpId)] = (_pDfEntry); \ } \ }
#define afpValidateDFEType(_pDfEntry, _EntityMask) \
{ \ if (((_EntityMask) & DFE_ANY) || \ (((_EntityMask) & DFE_DIR) && DFE_IS_DIRECTORY(_pDfEntry)) || \ (((_EntityMask) & DFE_FILE) && DFE_IS_FILE(_pDfEntry))) \ NOTHING; \ else \ { \ _pDfEntry = NULL; \ } \ }
/*** afpCheckDfEntry
* * When enumerating the disk during volume add, if a file/directory * has an AfpId associated with it, then it is validated to see if it is * within range as well as unique. If there is a collision between AFPIds, * a PC user must have copied (or restored) something from * this volume, or a different volume (or server) that had the same AFPId, * in which case we will give the new entity a different AFP Id; * If there is not a collision between AFPIds, and the Id is larger than the * last Id we know we assigned, then the new entity gets added with a new * AFPId; else if the Id is within the range, we will just use its existing * Id. * * Discovered AFPId is: Action for discovered entity in IdDb is: * -------------------- ---------------------------------------- * 1) > last Id Add a new entry, assign a new AFPId * * 2) Collides with existing Id: * * Host copy occurred Add a new entry, assign a new AFPId * * 3) < last Id Insert this entity using same AFPId * * * LOCKS_ASSUMED: vds_idDbAccessLock (SWMR, Exclusive) * VOID * afpCheckDfEntry( * IN PVOLDESC pVolDesc, * IN PAFPINFO pAfpInfo, // AFP Info of the discovered entity
* IN PUNICODE_STRING pUName, // Munged unicode name
* IN BOOLEAN IsDir, // is this thing a file or a directory?
* IN PDFENTRY pParent, // parent DFE of the discovered thing
* OUT PDFENTRY * ppDfEntry * ); */ #define afpCheckDfEntry(_pVolDesc, _AfpId, _pUName, _IsDir, _pParent, _ppDfEntry) \
{ \ PDFENTRY pDfeNew; \ \ if (((_AfpId) > (_pVolDesc)->vds_LastId) || \ ((_AfpId) <= AFP_ID_NETWORK_TRASH) || \ (AfpFindDfEntryById(_pVolDesc, _AfpId, DFE_ANY) != NULL)) \ { \ /* add the item to the DB but assign it a new AFP Id */ \ _AfpId = 0; \ } \ \ pDfeNew = AfpAddDfEntry(_pVolDesc, \ _pParent, \ _pUName, \ _IsDir, \ _AfpId); \ \ *(_ppDfEntry) = pDfeNew; \ }
#ifdef AGE_DFES
#define afpUpdateDfeAccessTime(_pVolDesc, _pDfEntry) \
{ \ if (IS_VOLUME_AGING_DFES(_pVolDesc)) \ { \ if (DFE_IS_DIRECTORY(_pDfEntry)) \ AfpGetCurrentTimeInMacFormat(&(_pDfEntry)->dfe_pDirEntry->de_LastAccessTime);\ else AfpGetCurrentTimeInMacFormat(&(_pDfEntry)->dfe_Parent->dfe_pDirEntry->de_LastAccessTime);\ } \ } #else
#define afpUpdateDfeAccessTime(pVolDesc, pDfEntry)
#endif
#define afpMarkAllChildrenUnseen(_pDFETree) \
{ \ LONG i = -1; \ PDFENTRY pDFE; \ \ /* \
* Even if this dir has not had its file children cached in \ * yet, we still want to prune out any dead directory children \ */ \ for (pDFE = (_pDFETree)->dfe_pDirEntry->de_ChildDir; \ True; \ pDFE = (_pDFETree)->dfe_pDirEntry->de_ChildFile[i]) \ { \ for (NOTHING; \ pDFE != NULL; \ pDFE = pDFE->dfe_NextSibling) \ { \ DFE_MARK_UNSEEN(pDFE); \ } \ if (++i == MAX_CHILD_HASH_BUCKETS) \ break; \ } \ }
#define afpPruneUnseenChildren(_pVolDesc, _pDFETree) \
{ \ PDFENTRY pDFE, *ppDfEntry; \ LONG i; \ \ /* \
* Go thru the list of children for this parent, and if there \ * are any left that are not marked as seen, get rid of them. \ */ \ ppDfEntry = &(_pDFETree)->dfe_pDirEntry->de_ChildDir; \ i = -1; \ while (True) \ { \ while ((pDFE = *ppDfEntry) != NULL) \ { \ if (!DFE_HAS_BEEN_SEEN(pDFE)) \ { \ DBGPRINT(DBG_COMP_IDINDEX, DBG_LEVEL_INFO, \ ("afpPruneUnseenChildren: deleting nonexistant IdDb entry\n")); \ \ AfpDeleteDfEntry(_pVolDesc, pDFE); \ continue; /* make sure we don't skip any */ \ } \ ppDfEntry = &pDFE->dfe_NextSibling; \ } \ if (++i == MAX_CHILD_HASH_BUCKETS) \ { \ break; \ } \ ppDfEntry = &(_pDFETree)->dfe_pDirEntry->de_ChildFile[i]; \ } \ }
#define afpUpdateDfeWithSavedData(_pDfe, _pDiskEnt) \
{ \ (_pDfe)->dfe_Flags |= (_pDiskEnt)->dsk_Flags & DFE_FLAGS_CSENCODEDBITS;\ (_pDfe)->dfe_AfpAttr = (_pDiskEnt)->dsk_AfpAttr; \ (_pDfe)->dfe_NtAttr = (_pDiskEnt)->dsk_NtAttr; \ (_pDfe)->dfe_CreateTime = (_pDiskEnt)->dsk_CreateTime; \ (_pDfe)->dfe_LastModTime = (_pDiskEnt)->dsk_LastModTime; \ (_pDfe)->dfe_BackupTime = (_pDiskEnt)->dsk_BackupTime; \ (_pDfe)->dfe_FinderInfo = (_pDiskEnt)->dsk_FinderInfo; \ if (DFE_IS_DIRECTORY((_pDfe))) \ { \ (_pDfe)->dfe_pDirEntry->de_Access = (_pDiskEnt)->dsk_Access;\ } \ else \ { \ (_pDfe)->dfe_DataLen = (_pDiskEnt)->dsk_DataLen; \ (_pDfe)->dfe_RescLen = (_pDiskEnt)->dsk_RescLen; \ } \ }
#define afpSaveDfeData(_pDfe, _pDiskEnt) \
{ \ /* Write a signature for sanity checking */ \ (_pDiskEnt)->dsk_Signature = AFP_DISKENTRY_SIGNATURE; \ \ (_pDiskEnt)->dsk_AfpId = (_pDfe)->dfe_AfpId; \ (_pDiskEnt)->dsk_AfpAttr = (_pDfe)->dfe_AfpAttr; \ (_pDiskEnt)->dsk_NtAttr = (_pDfe)->dfe_NtAttr; \ (_pDiskEnt)->dsk_BackupTime = (_pDfe)->dfe_BackupTime; \ (_pDiskEnt)->dsk_CreateTime = (_pDfe)->dfe_CreateTime; \ (_pDiskEnt)->dsk_LastModTime = (_pDfe)->dfe_LastModTime; \ (_pDiskEnt)->dsk_FinderInfo = (_pDfe)->dfe_FinderInfo; \ \ /* Encode the number of characters (not bytes) in the name */ \ (_pDiskEnt)->dsk_Flags = \ ((_pDfe)->dfe_Flags & DFE_FLAGS_DFBITS) | \ ((_pDfe)->dfe_UnicodeName.Length/sizeof(WCHAR)); \ \ /* Copy the name over */ \ RtlCopyMemory(&(_pDiskEnt)->dsk_Name[0], \ (_pDfe)->dfe_UnicodeName.Buffer, \ (_pDfe)->dfe_UnicodeName.Length); \ }
// File DFEs are aged after MAX_BLOCK_AGE*FILE_BLOCK_AGE_TIME seconds (currently 2 mins)
// File DFEs are aged after MAX_BLOCK_AGE*DIR_BLOCK_AGE_TIME seconds (currently 6 mins)
#define MAX_BLOCK_AGE 6
#define FILE_BLOCK_AGE_TIME 600 // # of seconds
#define DIR_BLOCK_AGE_TIME 3600 // # of seconds
#define BLOCK_64K_ALLOC 64*1024 // Virtual mem allocates 64K chunks
#define MAX_BLOCK_TYPE 4 // For TINY, SMALL, MEDIUM & LARGE
#define VALID_DFB(pDfeBlock) ((pDfeBlock) != NULL)
typedef struct _Block64K { struct _Block64K *b64_Next; PBYTE b64_BaseAddress; DWORD b64_PagesFree; BYTE b64_PageInUse[BLOCK_64K_ALLOC/PAGE_SIZE]; } BLOCK64K, *PBLOCK64K;
typedef struct _DfeBlock { struct _DfeBlock * dfb_Next; // Link to next
struct _DfeBlock ** dfb_Prev; // Link to previous
USHORT dfb_NumFree; // # of free DFEs in this block
BYTE dfb_Age; // Age of the Block if all are free
BOOLEAN dfb_fDir; // TRUE if it is a Dir DFB - else a file DFB
PDFENTRY dfb_FreeHead; // Head of the list of free DFEs
} DFEBLOCK, *PDFEBLOCK, **PPDFEBLOCK;
LOCAL PDFENTRY FASTCALL afpAllocDfe( IN LONG Index, IN BOOLEAN fDir );
LOCAL VOID FASTCALL afpFreeDfe( IN PDFENTRY pDfEntry );
LOCAL AFPSTATUS FASTCALL afpDfeBlockAge( IN PPDFEBLOCK pBlockHead );
#if DBG
VOID FASTCALL afpDisplayDfe( IN PDFENTRY pDfEntry );
NTSTATUS FASTCALL afpDumpDfeTree( IN PVOID Context );
#endif
IDDBGLOBAL PBLOCK64K afp64kBlockHead EQU NULL;
IDDBGLOBAL PDFEBLOCK afpDirDfeFreeBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; IDDBGLOBAL PDFEBLOCK afpDirDfePartialBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; IDDBGLOBAL PDFEBLOCK afpDirDfeUsedBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; IDDBGLOBAL PDFEBLOCK afpFileDfeFreeBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; IDDBGLOBAL PDFEBLOCK afpFileDfePartialBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; IDDBGLOBAL PDFEBLOCK afpFileDfeUsedBlockHead[MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL };
IDDBGLOBAL USHORT afpDfeUnicodeBufSize[MAX_BLOCK_TYPE] EQU \ { \ DFE_SIZE_TINY_U, DFE_SIZE_SMALL_U, \ DFE_SIZE_MEDIUM_U, DFE_SIZE_LARGE_U \ };
IDDBGLOBAL USHORT afpDfeFileBlockSize[MAX_BLOCK_TYPE] EQU \ { \ sizeof(DFENTRY) + DFE_SIZE_TINY_U, \ sizeof(DFENTRY) + DFE_SIZE_SMALL_U, \ sizeof(DFENTRY) + DFE_SIZE_MEDIUM_U, \ sizeof(DFENTRY) + DFE_SIZE_LARGE_U \ };
IDDBGLOBAL USHORT afpDfeDirBlockSize[MAX_BLOCK_TYPE] EQU \ { \ (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_TINY_U), \ (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_SMALL_U), \ (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_MEDIUM_U), \ (USHORT)(sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_LARGE_U) \ };
IDDBGLOBAL USHORT afpDfeNumFileBlocks[MAX_BLOCK_TYPE] EQU \ { \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + DFE_SIZE_TINY_U), \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + DFE_SIZE_SMALL_U), \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + DFE_SIZE_MEDIUM_U), \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + DFE_SIZE_LARGE_U) \ };
IDDBGLOBAL USHORT afpDfeNumDirBlocks[MAX_BLOCK_TYPE] EQU \ { \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_TINY_U), \ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_SMALL_U),\ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_MEDIUM_U),\ (PAGE_SIZE - sizeof(DFEBLOCK))/ \ (sizeof(DFENTRY) + sizeof(DIRENTRY) + DFE_SIZE_LARGE_U) \ };
IDDBGLOBAL SWMR afpDfeBlockLock EQU { 0 };
#if DBG
IDDBGLOBAL LONG afpDfeAllocCount EQU 0; IDDBGLOBAL LONG afpDfbAllocCount EQU 0; IDDBGLOBAL LONG afpDfe64kBlockCount EQU 0; IDDBGLOBAL BOOLEAN afpDumpDfeTreeFlag EQU 0; IDDBGLOBAL PDFENTRY afpDfeStack[4096] EQU { 0 };
#endif
#undef EQU
#ifdef _GLOBALS_
#define EQU =
#else
#define EQU ; / ## /
#endif
#endif // IDINDEX_LOCALS
#endif // _IDINDEX_
|