/* Copyright (c) 1992 Microsoft Corporation Module Name: volume.h Abstract: This module contains volume related data structures. Author: Jameel Hyder (microsoft!jameelh) Revision History: 25 Apr 1992 Initial Version Notes: Tab stop: 4 --*/ #ifndef _VOLUME_ #define _VOLUME_ #define IDINDEX_BUCKETS_DIR_MIN 16 #define IDINDEX_BUCKETS_FILE_MIN 32 #define IDINDEX_BUCKETS_DIR_INIT 64 // no index info? assume ~1000 dirs #define IDINDEX_BUCKETS_FILE_INIT 1024 // no index info? assume ~20000 files #define IDINDEX_BUCKETS_32K 32768 #define IDINDEX_BUCKETS_MAX 65536 #define IDINDEX_CACHE_ENTRIES 512 #define APPL_BUCKETS 16 #define ICON_BUCKETS 16 #define AFP_VOLUME_FIXED_DIR 2 // Volume Signature // These flags should be consistent with AFP // The UI (registry) visible definitions are in macfile.h // #define AFP_VOLUME_READONLY 0x00000001 // #define VOLUME_GUESTACCESS 0x00008000 // #define VOLUME_EXCLUSIVE 0x00010000 // #define AFP_VOLUME_HAS_CUSTOM_ICON 0x00020000 // #define AFP_VOLUME_4GB 0x00040000 // #define AFP_VOLUME_AGE_DFES 0x00080000 #define AFP_VOLUME_HASPASSWORD 0x00000002 #define AFP_VOLUME_SUPPORTS_FILEID 0x00000004 #define AFP_VOLUME_SUPPORTS_CATSRCH 0x00000008 #define AFP_VOLUME_SUPPORTS_BLANKPRV 0x00000010 #define AFP_VOLUME_MASK_AFP 0x0000001F // This is all AFP can see #define VOLUME_PROCESSING_NOTIFY 0x00000020 // Notify processing under way #define VOLUME_NOTIFY_POSTED 0x00000040 // Notify has been posted #define VOLUME_STOPPED 0x00000080 // The volume is about to stop // Set when server is stopping #define VOLUME_DELETED 0x00000100 // This volume is about to be // deleted, set when volume is // deleted by admin #define VOLUME_IDDBHDR_DIRTY 0x00000200 // The header needs to be written ASAP #define VOLUME_NTFS 0x00000400 // Volume is an NTFS volume #define VOLUME_INTRANSITION 0x00000800 // VolumeAdd is in progress // Is not usable still. #define VOLUME_SCAVENGER_RUNNING 0x00001000 // Volume is referenced for scavenger #define VOLUME_CDFS_INVALID 0x00002000 // If this is set, then no go #define VOLUME_INITIAL_CACHE 0x00004000 // Set initially when caching #define VOLUME_CD_HFS 0x00200000 // volume is a CD with HFS support #define VOLUME_DISKQUOTA_ENABLED 0x00400000 // diskquota is enabled on this volume #define VOLUME_NEW_FIRST_PASS 0x00800000 // first pass of id db building #define VOLUME_SRVR_NOTIF_PENDING 0x01000000 // server notification is pending // Values for scavenger routines #define VOLUME_NTFS_SCAVENGER_INTERVAL 60 // # of seconds #define VOLUME_CDFS_SCAVENGER_INTERVAL 60 // # of seconds //#define VOLUME_IDDB_UPDATE_INTERVAL 600 // # of seconds //#define MAX_INVOCATIONS_TO_SKIP 60 // # of passes //#define MAX_CHANGES_BEFORE_WRITE 1000 // # of changes #define VOLUME_OURCHANGE_AGE 30 // # of seconds #define OURCHANGE_AGE 10 // # of seconds // // The ChangeNotify delay is introduced to prevent the problem where // the PC side is doing a copyfile or forkize of a macfile, and as // soon as we receive the notification of the initial create we will // slap on our AFPInfo stream. Then when the CopyFile or forkize operation // gets around to writing its AFPInfo, we do not get notified and will not // reread the information. In this case, a mac file copied from one volume // to another (e.g.) will not show up with the correct finder info. // #define VOLUME_NTFY_DELAY 3 // # of seconds #define VOLUME_IDDB_AGE_DELAY 60*60 // # of seconds #define VOLUME_IDDB_AGE_GRANULARITY 30 // # of invocations #define VOLUME_STARTUP_WAIT 5 // # of seconds to wait // make sure there is enough room to hold a change notification for a // rename operation on a maximum length win32 path (which is 260 chars) #define AFP_VOLUME_NOTIFY_STARTING_BUFSIZE (2048 - POOL_OVERHEAD) #define AFP_VOLUME_NOTIFY_MAX_BUFSIZE 8*16384 // List of these structures hangs off the volume descriptor to list the // changes initiated by us that should be filtered from the ChangeNotify // list of changes. typedef struct _OurChange { LIST_ENTRY oc_Link; UNICODE_STRING oc_Path; AFPTIME oc_Time; // Time when this was queued. } OUR_CHANGE, *POUR_CHANGE; // defines for indices into vds_OurChangeList #define AFP_CHANGE_ACTION_ADDED 0 #define AFP_CHANGE_ACTION_REMOVED 1 #define AFP_CHANGE_ACTION_MODIFIED 2 #define AFP_CHANGE_ACTION_RENAMED 3 #define AFP_CHANGE_ACTION_MODIFIED_STREAM 4 #define AFP_CHANGE_ACTION_MAX AFP_CHANGE_ACTION_MODIFIED_STREAM #define NUM_AFP_CHANGE_ACTION_LISTS (AFP_CHANGE_ACTION_MAX + 1) // Convert an NT FILE_ACTION_xxx (ntioapi.h) to an array index into // vds_OurChangeList array. Note the close tie between the first 4 // AFP_CHANGE_ACTION_xxx and the values of FILE_ACTION_xxx in ntioapi.h #define AFP_CHANGE_ACTION(NTAction) \ (NTAction == FILE_ACTION_MODIFIED_STREAM ? AFP_CHANGE_ACTION_MODIFIED_STREAM : (NTAction - 1)) /* * All changes to the volume descriptor should be protected by vds_VolLock * Changes to the Id Db and the desktop Db should be protected by their * respective locks. * * NOTE: The volume path and name (unicode) must be uppercased, since when * looking up or adding a volume, we will be holding a spinlock, and * case insensitive string compares cannot be done at DPC level since * the codepages are kept in paged memory, and we can't take a page * fault at DPC level. */ #if DBG #define VOLDESC_SIGNATURE *(DWORD *)"VDS" #define VALID_VOLDESC(pVolDesc) (((pVolDesc) != NULL) && \ ((pVolDesc)->Signature == VOLDESC_SIGNATURE)) #else #define VALID_VOLDESC(pVolDesc) ((pVolDesc) != NULL) #endif typedef struct _VolDesc { #if DBG DWORD Signature; DWORD QuadAlign1; #endif struct _VolDesc * vds_Next; // Pointer to next volume DWORD vds_UseCount; // Number of active connections DWORD vds_RefCount; // Number of references. // Cannot be freed till both of the // above go to ZERO. Of course there // is a RefCount for every UseCount // Configuration information. DWORD vds_Flags; // Volume flags LONG vds_VolId; // Volume Id for FPOpenVol DWORD vds_MaxUses; // Maximum opens on a volume UNICODE_STRING vds_Name; // Volume name in unicode UNICODE_STRING vds_UpCaseName; // Volume name in UPPER CASE unicode ANSI_STRING vds_MacName; // Volume name in Mac Ansi ANSI_STRING vds_MacPassword; // Volume password in Mac Ansi UNICODE_STRING vds_Path; // File system path to the volume root; // Path is always upper cased LARGE_INTEGER vds_VolumeSize; // Size of volume LARGE_INTEGER vds_FreeBytes; // Free space on the volume #define vds_pFileObject vds_hRootDir.fsh_FileObject FILESYSHANDLE vds_hRootDir; // Handle to open root directory // in the servers context. All // subsequent opens are relative // to this handle FILESYSHANDLE vds_hNWT; // Handle to Network Trash so it can't // be deleted from under us (NTFS) DWORD vds_AllocationBlockSize; // Bytes per sector // The following fields are used by the Id database code and are copied // to/from the on-disk idDb header. Protected by vds_VolLock. DWORD vds_LastId; // Highest id that is assigned AFPTIME vds_CreateTime; // Creation time for this volume AFPTIME vds_ModifiedTime; // Modified time for this volume AFPTIME vds_BackupTime; // Backup time for this volume #ifdef AGE_DFES DWORD vds_ScavengerInvocationCnt; // Used by the volume scavenger to fire off // AfpAgeDfEntries #endif DWORD vds_RequiredNotifyBufLen; // How deep is the tree. This is used by // the afpVolumePostnotify to allocate an // appropriate buffer. #ifdef BLOCK_MACS_DURING_NOTIFYPROC DWORD vds_QueuedNotifyCount; // How many change notify buffers // have moved into the global queue // for this volume -- This value is // ONLY touched by the Change // Notify thread. #endif SWMR vds_IdDbAccessLock; // Access cookie for the id db // Protects the vds_pDfexxxBuckets. LONG vds_cScvgrIdDb; // # of times the update to the Id // database was passed up DWORD vds_NumDirDfEntries;// Number of directory DfEntries in this volume DWORD vds_NumFileDfEntries;// Number of file DfEntries in this volume struct _DirFileEntry * vds_pDfeRoot; // Pointer to DFE of root DWORD vds_DirHashTableSize; DWORD vds_FileHashTableSize; struct _DirFileEntry ** vds_pDfeDirBucketStart; struct _DirFileEntry ** vds_pDfeFileBucketStart; // IdDb DfEntry hash buckets struct _DirFileEntry * vds_pDfeCache[IDINDEX_CACHE_ENTRIES]; // IdDb DfEntry cache // The following fields are used by the desktop database code LONG vds_cScvgrDt; // # of times the update to the desktop // database was passed up SWMR vds_DtAccessLock; // Access cookie for the desktop db // Protects the following FIVE fields // The following fields are copied to/from the on-disk Desktop header. // Protected by vds_VolLock. LONG vds_cApplEnts; // Number of APPL entries LONG vds_cIconEnts; // Number of ICON entries struct _ApplInfo2 * vds_pApplBuckets[APPL_BUCKETS]; // APPL hash buckets struct _IconInfo * vds_pIconBuckets[ICON_BUCKETS]; // ICON hash buckets SWMR vds_ExchangeFilesLock; // Access to the FileId stored // in an OpenForkDesc, used by // FpExchangeFiles and fork APIs LIST_ENTRY vds_OurChangeList[NUM_AFP_CHANGE_ACTION_LISTS]; // ^^^ // Lists of create/delete/move/rename // operations initiated by this server LIST_ENTRY vds_ChangeNotifyLookAhead; // ^^^ // List of all completed (but not yet // processed) DELETE or RENAME changes // on this Volume. LIST_ENTRY vds_DelayedNotifyList; struct _OpenForkDesc * vds_pOpenForkDesc; // List of open forks for this volume LONG vds_cPrivateNotifies; // Count of private notifies LONG vds_maxPrivateNotifies; // Keep track of max private notifies PBYTE vds_EnumBuffer; // Used during notify processing to cache in the tree LONG vds_cOutstandingNotifies; // Used in conjunction with above PIRP vds_pIrp; // Irp used by Notify, we never // free this until its time to // delete or stop DWORD vds_TimeMustSendNotify; // time at which we *must* send the notif DWORD vds_TimeToSendNotify; // when to send the next notification AFP_SPIN_LOCK vds_VolLock; // Lock for this volume BOOLEAN MacLimitExceeded; // True if # folders or volume size exceeds Apple limits LARGE_INTEGER vds_IndxStTime; } VOLDESC, *PVOLDESC; // AppleShare limit for files+folders in a volume: 65535 #define APLIMIT_MAX_FOLDERS 0xffff #define IS_VOLUME_NTFS(pVolDesc) (((pVolDesc)->vds_Flags & VOLUME_NTFS) ? True : False) #define IS_VOLUME_RO(pVolDesc) (((pVolDesc)->vds_Flags & AFP_VOLUME_READONLY) ? True : False) #define IS_VOLUME_CD_HFS(pVolDesc) (((pVolDesc)->vds_Flags & VOLUME_CD_HFS) ? True : False) #define EXCLUSIVE_VOLUME(pVolDesc) (((pVolDesc)->vds_Flags & AFP_VOLUME_EXCLUSIVE) ? True : False) #define IS_VOLUME_AGING_DFES(pVolDesc) (((pVolDesc)->vds_Flags & AFP_VOLUME_AGE_DFES) ? True : False) #define CONN_DESKTOP_CLOSED 0x0000 #define CONN_DESKTOP_OPENED 0x0001 #define CONN_CLOSING 0x8000 #if DBG #define CONNDESC_SIGNATURE *(DWORD *)"CDS" #define VALID_CONNDESC(pConnDesc) \ (((pConnDesc) != NULL) && \ ((pConnDesc)->Signature == CONNDESC_SIGNATURE)) #else #define VALID_CONNDESC(pConnDesc) ((pConnDesc) != NULL) #endif typedef struct _ConnDesc { #if DBG DWORD Signature; #endif LONG cds_RefCount; // Number of references to the open volume DWORD cds_Flags; // One or more of the bits defined above struct _ConnDesc * cds_Next; // Link to next open volume for this // session. Starts from the SDA struct _ConnDesc * cds_NextGlobal; // Link to next for global list. // Starts from AfpConnList struct _VolDesc * cds_pVolDesc; // Pointer to volume structure PSDA cds_pSda; // Session that opened this volume LARGE_INTEGER cds_QuotaLimit; // how much is the DiskQuota limit LARGE_INTEGER cds_QuotaAvl; // how much DiskQuota is available DWORD cds_ConnId; // Connection Id assigned by the server AFPTIME cds_TimeOpened; // Time stamp when volume opened // in macintosh time LONG cds_cOpenForks; // Number of open forks from this conn PENUMDIR cds_pEnumDir; // Current enumerated directory AFP_SPIN_LOCK cds_ConnLock; // Lock for this connection } CONNDESC, *PCONNDESC; #define IS_CONN_NTFS(pConnDesc) IS_VOLUME_NTFS((pConnDesc)->cds_pVolDesc) #define IS_CONN_CD_HFS(pConnDesc) IS_VOLUME_CD_HFS((pConnDesc)->cds_pVolDesc) // Volume parameters bitmap definitions #define VOL_BITMAP_ATTR 0x0001 #define VOL_BITMAP_SIGNATURE 0x0002 #define VOL_BITMAP_CREATETIME 0x0004 #define VOL_BITMAP_MODIFIEDTIME 0x0008 #define VOL_BITMAP_BACKUPTIME 0x0010 #define VOL_BITMAP_VOLUMEID 0x0020 #define VOL_BITMAP_BYTESFREE 0x0040 #define VOL_BITMAP_VOLUMESIZE 0x0080 #define VOL_BITMAP_VOLUMENAME 0x0100 #define VOL_BITMAP_EXTBYTESFREE 0x0200 #define VOL_BITMAP_EXTBYTESTOTAL 0x0400 #define VOL_BITMAP_ALLOCBLKSIZE 0x0800 #define VOL_BITMAP_MASK 0x0FFF typedef VOID (FASTCALL *NOTIFYPROCESSOR)(IN PVOID); // Structure of a notify buffer. The Mdl describes only the Buffer following the struct. typedef struct _VolumeNotify { #define Notify_NextFree Notify_NextOverflow struct _VolumeNotify * Notify_NextOverflow; // Overflow links LIST_ENTRY vn_List; // Chained from AfpVolumeNotifyQueue[i] union { LIST_ENTRY vn_DelRenLink; // Chained from vds_ChangeNotifyLookAhead // - VALID ONLY IFF THE ACTION HAS THE PRIVATE BIT CLEAR struct { DWORD vn_ParentId; // Afp Id of the parent // - VALID ONLY IFF THE ACTION HAS THE PRIVATE BIT SET DWORD vn_TailLength; // Length in bytes of the last component of the path // - VALID ONLY IFF THE ACTION HAS THE PRIVATE BIT SET }; }; NOTIFYPROCESSOR vn_Processor; // Routine that processes the notification AFPTIME vn_TimeStamp; // When the notify came in PVOLDESC vn_pVolDesc; // Volume being watched DWORD vn_StreamId; // Stream Id LONG vn_VariableLength; // followed by FILE_NOTIFY_INFORMATION } VOL_NOTIFY, *PVOL_NOTIFY; // Notify's 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 NOTIFY_INDEX_TINY 0 #define NOTIFY_INDEX_SMALL 1 #define NOTIFY_INDEX_MEDIUM 2 #define NOTIFY_INDEX_LARGE 3 // // Make sure each of the sizes below (XXX_U) are multiple of 8 // #define NOTIFY_SIZE_TINY 128 // These are lengths for ANSI names #define NOTIFY_SIZE_SMALL 256 // - ditto - #define NOTIFY_SIZE_MEDIUM 512 // - ditto - #define NOTIFY_SIZE_LARGE 1024 // - ditto - corres. to AFP_FILENAME_LEN #define NOTIFY_SIZE_TINY_U NOTIFY_SIZE_TINY*sizeof(WCHAR) // These are lengths for UNICODE names #define NOTIFY_SIZE_SMALL_U NOTIFY_SIZE_SMALL*sizeof(WCHAR) // - ditto - #define NOTIFY_SIZE_MEDIUM_U NOTIFY_SIZE_MEDIUM*sizeof(WCHAR) // - ditto - #define NOTIFY_SIZE_LARGE_U NOTIFY_SIZE_LARGE*sizeof(WCHAR) // - ditto - corres. to AFP_FILENAME_LEN #define NOTIFY_USIZE_TO_INDEX(_Size) \ (((_Size) <= NOTIFY_SIZE_TINY_U) ? NOTIFY_INDEX_TINY : \ (((_Size) <= NOTIFY_SIZE_SMALL_U) ? NOTIFY_INDEX_SMALL : \ (((_Size) <= NOTIFY_SIZE_MEDIUM_U) ? NOTIFY_INDEX_MEDIUM : NOTIFY_INDEX_LARGE))) // Notify Blocks are aged after NOTIFY_MAX_BLOCK_AGE*NOTIFY_DIR_BLOCK_AGE_TIME seconds (currently 1 min/s) #define NOTIFY_MAX_BLOCK_AGE 1 #define NOTIFY_DIR_BLOCK_AGE_TIME 60 // # of seconds #define NOTIFY_MAX_BLOCK_TYPE 4 // For TINY, SMALL, MEDIUM & LARGE #define VALID_NOTIFY_BLOCK(pDfeBlock) ((pDfeBlock) != NULL) typedef struct _Notify_Block { struct _Notify_Block * dfb_Next; // Link to next struct _Notify_Block ** 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 PVOL_NOTIFY dfb_FreeHead; // Head of the list of free DFEs } VOL_NOTIFY_BLOCK, *PVOL_NOTIFY_BLOCK, **PPVOL_NOTIFY_BLOCK; GLOBAL PVOL_NOTIFY_BLOCK afpDirNotifyFreeBlockHead[NOTIFY_MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; GLOBAL PVOL_NOTIFY_BLOCK afpDirNotifyPartialBlockHead[NOTIFY_MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; GLOBAL PVOL_NOTIFY_BLOCK afpDirNotifyUsedBlockHead[NOTIFY_MAX_BLOCK_TYPE] EQU { NULL, NULL, NULL }; GLOBAL SHORT afpNotifyUnicodeBufSize[NOTIFY_MAX_BLOCK_TYPE] EQU \ { \ NOTIFY_SIZE_TINY_U, NOTIFY_SIZE_SMALL_U, \ NOTIFY_SIZE_MEDIUM_U, NOTIFY_SIZE_LARGE_U \ }; GLOBAL USHORT afpNotifyDirBlockSize[NOTIFY_MAX_BLOCK_TYPE] EQU \ { \ (USHORT)(sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_TINY_U), \ (USHORT)(sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_SMALL_U), \ (USHORT)(sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_MEDIUM_U), \ (USHORT)(sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_LARGE_U) \ }; GLOBAL USHORT afpNotifyNumDirBlocks[NOTIFY_MAX_BLOCK_TYPE] EQU \ { \ (PAGE_SIZE - sizeof(VOL_NOTIFY_BLOCK))/ \ (sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_TINY_U), \ (PAGE_SIZE - sizeof(VOL_NOTIFY_BLOCK))/ \ (sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_SMALL_U),\ (PAGE_SIZE - sizeof(VOL_NOTIFY_BLOCK))/ \ (sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_MEDIUM_U),\ (PAGE_SIZE - sizeof(VOL_NOTIFY_BLOCK))/ \ (sizeof(VOL_NOTIFY) + sizeof(FILE_NOTIFY_INFORMATION) + (AFP_LONGNAME_LEN+1)*sizeof(WCHAR) + NOTIFY_SIZE_LARGE_U) \ }; GLOBAL SWMR afpNotifyBlockLock EQU { 0 }; GLOBAL LONG afpNotifyAllocCount EQU 0; GLOBAL LONG afpNotifyBlockAllocCount EQU 0; GLOBAL LONG afpMaxNotifyBlockAllocCount EQU 0; GLOBAL LONG afpNotify64kBlockCount EQU 0; // For maintaining track of delayed transactions typedef struct _DELAYED_NOTIFY { LIST_ENTRY dn_List; UNICODE_STRING filename; } DELAYED_NOTIFY, *PDELAYED_NOTIFY; // largest volume id that's currently in use. GLOBAL LONG afpLargestVolIdInUse EQU 0; GLOBAL LONG AfpVolCount EQU 0; // Total number of volumes GLOBAL PVOLDESC AfpVolumeList EQU NULL; // List of volumes GLOBAL AFP_SPIN_LOCK AfpVolumeListLock EQU {0}; // Lock for AfpVolumeList, GLOBAL SWMR AfpVolumeListSwmr; // Access cookie VolumeNotifyList // AfpVolCount, // AfpVolumeNotifyList, // AfpVolumeNotifyCount GLOBAL PCONNDESC AfpConnList EQU NULL; // Global connection list GLOBAL AFP_SPIN_LOCK AfpConnLock EQU { 0 }; // Lock for AfpConnList GLOBAL UNICODE_STRING AfpNetworkTrashNameU EQU { 0 }; GLOBAL KQUEUE AfpVolumeNotifyQueue[NUM_NOTIFY_QUEUES] EQU { 0 }; GLOBAL LIST_ENTRY AfpVolumeNotifyList[NUM_NOTIFY_QUEUES] EQU { 0 }; GLOBAL LIST_ENTRY AfpVirtualMemVolumeNotifyList[NUM_NOTIFY_QUEUES] EQU { 0 }; // Count of change notification buffers that are in the list GLOBAL LONG AfpNotifyListCount[NUM_NOTIFY_QUEUES] EQU { 0 }; // Count of change notification buffers that have transitioned into the queue. GLOBAL LONG AfpNotifyQueueCount[NUM_NOTIFY_QUEUES] EQU { 0 }; GLOBAL VOL_NOTIFY AfpTerminateNotifyThread EQU { 0 }; GLOBAL LONG ChangeNotifyQueueLimit EQU 200000; #define AfpVolumeQueueChangeNotify(pVolNotify, pNotifyQueue) \ { \ KeInsertQueue(pNotifyQueue, \ &(pVolNotify)->vn_List); \ } // Used for PRIVATE notifies of directory ADDED #define AFP_QUEUE_NOTIFY_IMMEDIATELY BEGINNING_OF_TIME #define AfpVolumeInsertChangeNotifyList(pVolNotify, pVolDesc) \ { \ PLIST_ENTRY pListHead; \ \ pListHead = &AfpVolumeNotifyList[(pVolDesc)->vds_VolId % NUM_NOTIFY_QUEUES]; \ if (pVolNotify->vn_TimeStamp != AFP_QUEUE_NOTIFY_IMMEDIATELY) \ { \ ExInterlockedInsertTailList(pListHead, \ &(pVolNotify)->vn_List, \ &(AfpVolumeListLock.SpinLock)); \ } \ else \ { \ ExInterlockedInsertHeadList(pListHead, \ &(pVolNotify)->vn_List, \ &(AfpVolumeListLock.SpinLock)); \ } \ INTERLOCKED_ADD_ULONG(&AfpNotifyListCount[(pVolDesc)->vds_VolId % NUM_NOTIFY_QUEUES], \ 1, \ &AfpVolumeListLock); \ } #define AfpIdDbHdrToVolDesc(_pIdDbHdr, _pVolDesc) \ { \ (_pVolDesc)->vds_LastId = (_pIdDbHdr)->idh_LastId; \ (_pVolDesc)->vds_CreateTime = (_pIdDbHdr)->idh_CreateTime; \ (_pVolDesc)->vds_ModifiedTime = (_pIdDbHdr)->idh_ModifiedTime; \ (_pVolDesc)->vds_BackupTime = (_pIdDbHdr)->idh_BackupTime; \ } #define AfpVolDescToIdDbHdr(_pVolDesc, _pIdDbHdr) \ { \ (_pIdDbHdr)->idh_Signature = AFP_SERVER_SIGNATURE; \ (_pIdDbHdr)->idh_Version = AFP_IDDBHDR_VERSION; \ (_pIdDbHdr)->idh_LastId = (_pVolDesc)->vds_LastId; \ (_pIdDbHdr)->idh_CreateTime = (_pVolDesc)->vds_CreateTime; \ (_pIdDbHdr)->idh_ModifiedTime = (_pVolDesc)->vds_ModifiedTime; \ (_pIdDbHdr)->idh_BackupTime = (_pVolDesc)->vds_BackupTime; \ } #define AfpDtHdrToVolDesc(_pDtHdr, _pVolDesc) \ { \ (_pVolDesc)->vds_cApplEnts = (_pDtHdr)->dtp_cApplEnts; \ (_pVolDesc)->vds_cIconEnts = (_pDtHdr)->dtp_cIconEnts; \ } #define AfpVolDescToDtHdr(_pVolDesc, _pDtHdr) \ { \ (_pDtHdr)->dtp_Signature = AFP_SERVER_SIGNATURE; \ (_pDtHdr)->dtp_Version = AFP_DESKTOP_VERSION; \ (_pDtHdr)->dtp_cApplEnts = (_pVolDesc)->vds_cApplEnts; \ (_pDtHdr)->dtp_cIconEnts = (_pVolDesc)->vds_cIconEnts; \ } extern NTSTATUS AfpVolumeInit( VOID ); extern PCONNDESC FASTCALL AfpConnectionReference( IN PSDA pSda, IN LONG VolId ); extern PCONNDESC FASTCALL AfpConnectionReferenceAtDpc( IN PSDA pSda, IN LONG VolId ); extern PCONNDESC FASTCALL AfpConnectionReferenceByPointer( IN PCONNDESC pConnDesc ); extern PCONNDESC FASTCALL AfpReferenceConnectionById( IN DWORD ConnId ); extern VOID FASTCALL AfpConnectionDereference( IN PCONNDESC pConnDesc ); extern BOOLEAN FASTCALL AfpVolumeReference( IN PVOLDESC pVolDesc ); extern PVOLDESC FASTCALL AfpVolumeReferenceByUpCaseName( IN PUNICODE_STRING pTargetName ); extern AFPSTATUS FASTCALL AfpVolumeReferenceByPath( IN PUNICODE_STRING pFDPath, OUT PVOLDESC * ppVolDesc ); extern VOID FASTCALL AfpVolumeDereference( IN PVOLDESC pVolDesc ); extern BOOLEAN AfpVolumeMarkDt( IN PSDA pSda, IN PCONNDESC pConnDesc, IN DWORD OpenState ); extern VOID FASTCALL AfpVolumeSetModifiedTime( IN PVOLDESC pVolDesc ); extern AFPSTATUS FASTCALL AfpSendServerNotification( IN PVOLDESC pVolDesc ); extern AFPSTATUS AfpConnectionOpen( IN PSDA pSda, IN PANSI_STRING pVolName, IN PANSI_STRING pVolPass, IN DWORD Bitmap, OUT PBYTE pVolParms ); extern VOID FASTCALL AfpConnectionClose( IN PCONNDESC pConnDesc ); extern USHORT FASTCALL AfpVolumeGetParmsReplyLength( IN DWORD Bitmap, IN USHORT NameLen ); extern VOID AfpVolumePackParms( IN PSDA pSda, IN PVOLDESC pVolDesc, IN DWORD Bitmap, IN PBYTE pVolParms ); extern AFPSTATUS AfpAdmWVolumeAdd( IN OUT PVOID Inbuf OPTIONAL, IN LONG OutBufLen OPTIONAL, OUT PVOID Outbuf OPTIONAL ); extern AFPSTATUS AfpAdmWVolumeDelete( IN OUT PVOID InBuf OPTIONAL, IN LONG OutBufLen OPTIONAL, OUT PVOID OutBuf OPTIONAL ); extern AFPSTATUS AfpAdmWConnectionClose( IN OUT PVOID InBuf OPTIONAL, IN LONG OutBufLen OPTIONAL, OUT PVOID OutBuf OPTIONAL ); extern VOID AfpVolumeStopAllVolumes( VOID ); extern AFPSTATUS FASTCALL AfpVolumeBeginIndexing( IN PVOLDESC pVolDesc ); extern NTSTATUS FASTCALL AfpVolumePostChangeNotify( IN PVOLDESC pVolDesc ); extern VOID FASTCALL AfpUpdateVolFreeSpaceAndModTime( IN PVOLDESC pVolDesc, IN BOOLEAN fUpdateModTime ); extern AFPSTATUS FASTCALL AfpVolumeScavenger( IN PVOLDESC pVolDesc ); extern BOOLEAN FASTCALL AfpVolumeAbortIndexing( IN PVOLDESC pVolDesc ); extern BOOLEAN FASTCALL AfpVolumeStopIndexing( IN PVOLDESC pVolDesc, IN PVOL_NOTIFY pVolNotify ); extern PVOL_NOTIFY afpAllocNotify( IN LONG Index, IN BOOLEAN fDir ); extern VOID afpFreeNotify( IN PVOID pDfEntry ); extern AFPSTATUS FASTCALL afpNotifyBlockAge( IN PPVOL_NOTIFY_BLOCK pBlockHead ); extern VOID afpFreeNotifyBlockMemory( ); VOID AfpVolumeUpdateIdDbAndDesktop( IN PVOLDESC pVolDesc, IN BOOLEAN WriteDt, IN BOOLEAN WriteIdDb, IN PIDDBHDR pIdDbHdr OPTIONAL ); extern VOID FASTCALL afpActivateVolume( IN struct _VolDesc * pVolDesc ); #ifdef VOLUME_LOCALS // // private routines // LOCAL AFPSTATUS FASTCALL afpVolumeCloseHandleAndFreeDesc( IN PVOLDESC pVolDesc ); LOCAL AFPSTATUS FASTCALL afpVolumeAdd( IN PVOLDESC pVolDesc ); LOCAL AFPSTATUS FASTCALL afpVolumeCheckForDuplicate( IN PVOLDESC pNewVol ); LOCAL VOID FASTCALL afpVolumeGetNewIdAndLinkToList( IN PVOLDESC pVolDesc ); LOCAL VOID FASTCALL afpNudgeCdfsVolume( IN PVOLDESC pVolDesc ); LOCAL PCONNDESC FASTCALL afpConnectionReferenceById( IN DWORD ConnId ); LOCAL VOID FASTCALL afpConnectionGetNewIdAndLinkToList( IN PCONNDESC pConnDesc ); LOCAL NTSTATUS afpVolumeChangeNotifyComplete( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOLDESC pVolDesc ); LOCAL DWORD afpNextConnId = 1; // Next conn id to assign to an open volume LOCAL LONG afpNumPostedNotifies = 0; // This is the smallest free volume id that is guaranteed to be free. Access // to this is via the AfpVolumeListLock. LOCAL LONG afpSmallestFreeVolId = 1; #endif // VOLUME_LOCALS #endif // _VOLUME_