/*++ Copyright (c) 1989 Microsoft Corporation Module Name: msstruc.h Abstract: This module defines the data structures that make up the major internal part of the mailslot file system. Author: Manny Weiser (mannyw) 7-Jan-1991 Revision History: --*/ #ifndef _MSSTRUC_ #define _MSSTRUC_ // // The VCB record is the top record in the mailslot file system in-memory // data structure. This structure must be allocated from non-paged pool // and immediately follows (in memory) the Device object for the mailslot // Structurally the layout of the data structure is as follows // // +------------+ // |MSDO | // | | // +------------+ // |Vcb | // | | // | | // +------------+ // | ^ // | | // | | // v | // +-------------+ // |RootDcb | // | |<-+ // +-------------+ | // : | // : | // : | // v | // +----------------+ +-------------------+ // |Fcb | |Ccb | // | |<---| | // | | | | // +----------------+ +-------------------+ // ^ ^ // | | // +---------+ +---------+ // |Server FO| |Client FO| // | | | | // +---------+ +---------+ // // // Where there is only one VCB for the entire mailslot file system, and // it contains a single pointer to the root DCB for the file system. Off // of the DCB is a queue of FCB's. There is one FCB for every mailslot. // There are also two additional CCB types for the VCB and the root DCB, // and notify records for the notify change operations. // // A newly initialized mailslot file system only contains the VCB and // the root DCB. A new FCB is created when a new mailslot is created // The file object for the creater (i.e., server end) points to the FCB // and indicates that it is the server end. When a user does an open on // the mailslot its file object is set to point to a CCB which belongs // to the FCB. // // A file object with a null pointer to the FsContext field is a closed or // disconnected mailslot. // // // Each Fcb has a data queues for holding the outstanding // read/write requests. The following type is used to determine // if the data queue contains read requests, write requests, or is empty. // typedef enum _QUEUE_STATE { ReadEntries, WriteEntries, Empty } QUEUE_STATE; // // The node state. // // Currently only 2 states are defined. When a node is created it's state // is NodeStateActive. When a cleanup IRP is processed, it set the node // state of the corresponding node to NodeStateClosing. Only the close // IRP can get processed on this node. // typedef enum _NODE_STATE { NodeStateActive, NodeStateClosing } NODE_STATE; // // The types of data entry there are. Each corresponds to an IRP // that can be added to a data queue. // typedef enum _ENTRY_TYPE { Read, ReadMailslot, Write, WriteMailslot, Peek } ENTRY_TYPE; // // The data queue is a structure that contains the queue state, quota // information, and the list head. The quota information is used to // maintain mailslot quota. // typedef struct _DATA_QUEUE { // // The current state of what is contained in this data queue, // how many bytes of read/write data there are, and how many individual // requests there are in the queue that contain data (includes // close or flush requests). // QUEUE_STATE QueueState; ULONG BytesInQueue; ULONG EntriesInQueue; // // The following two fields denote who much quota was reserved for // this mailslot and how much we've used up. This is only // the creator quota and not the user quota. // ULONG Quota; ULONG QuotaUsed; // // The size of the largest message that can be written to // this data queue. // ULONG MaximumMessageSize; // // The queue of data entries. // LIST_ENTRY DataEntryList; } DATA_QUEUE, *PDATA_QUEUE; // // The following type is used to denote where we got the memory for the // data entry and possibly the data buffer. We either got the memory // from the mailslot quota, the user quota, or it is part of the next IRP // stack location. // typedef enum _FROM { MailslotQuota, UserQuota, InIrp } FROM; // // Each entry in the data queue is a data entry. Processing an IRP // has the potential of creating and inserting a new data entry. If the // memory for the entry is taken from the IRP we use the current stack // location. // typedef struct _DATA_ENTRY { // // Where the data buffer came from // UCHAR From; CHAR Spare1; USHORT Spare2; // // The following field is how we connect into the queue of data entries // LIST_ENTRY ListEntry; // // The following field indicates if we still have an IRP associated // with this data entry that need to be completed when the remove // the data entry. Note that if From is InIrp that this IRP field // must not be null. // PIRP Irp; // // The following two fields describe the size and location of the data // buffer described by this entry. These fields are only used if the // type is buffered, and are ignored otherwise. // ULONG DataSize; PVOID DataPointer; // // Used for read data entries only. A pointer to the work context // of the time out. // struct _WORK_CONTEXT *TimeoutWorkContext; } DATA_ENTRY, *PDATA_ENTRY; // // The node header is used to manage standard nodes within MSFS. // typedef struct _NODE_HEADER { NODE_TYPE_CODE NodeTypeCode; // The node type NODE_BYTE_SIZE NodeByteSize; // The size of the node NODE_STATE NodeState; // The current node state ULONG ReferenceCount; // Number of active references to the node } NODE_HEADER, *PNODE_HEADER; typedef struct _VCB { NODE_HEADER Header; // // The filesystem name // UNICODE_STRING FileSystemName; // // The time we created the volume // LARGE_INTEGER CreationTime; // // A pointer to the root DCB for this volume // struct _FCB *RootDcb; // // A prefix table that is used for quick, prefix directed, lookup of // FCBs/DCBs that are part of this volume // UNICODE_PREFIX_TABLE PrefixTable; // // A resource variable to control access to the volume specific data // structures // ERESOURCE Resource; // // The following field is used to check share access people who want // to open the mailslot driver // SHARE_ACCESS ShareAccess; } VCB, *PVCB; // // The Mailslot Device Object is an I/O system device object with // additional workqueue parameters appended to the end. There is only // one of these records created for the entire system during system // initialization. The workqueue is used by the FSD to post requests to // the filesystem. // typedef struct _MSFS_DEVICE_OBJECT { DEVICE_OBJECT DeviceObject; // // This is the file system specific volume control block. // VCB Vcb; } MSFS_DEVICE_OBJECT, *PMSFS_DEVICE_OBJECT; // // The Fcb/Dcb record corresponds to every opened mailslot and directory, // and to every directory on an opened path. // typedef struct _FCB { // // Header.NodeTypeCode of this record (must be MSFS_NTC_FCB, or // MSFS_NTC_ROOT_DCB) // NODE_HEADER Header; // // The links for the queue of all fcbs for a specific DCB off of // Dcb.ParentDcbQueue. For the root directory this queue is empty. // LIST_ENTRY ParentDcbLinks; // // A pointer to the Dcb that is the parent directory containing // this FCB. If this record itself is the root dcb then this field // is null. // struct _FCB *ParentDcb; // // A pointer to the VCB containing this FCB. // PVCB Vcb; // // Back pointer to the server's file object. // PFILE_OBJECT FileObject; // // A pointer to the security descriptor for this mailslot. // PSECURITY_DESCRIPTOR SecurityDescriptor; // // The following union is cased off of the node type code for the FCB. // is a seperate case for the directory versus file FCBs. // union { // // A Directory Control Block (DCB) // struct { // // A queue of the notify IRPs that will be completed when any // change is made to a file in the directory. Queued using // the Tail.Overlay.ListEntry of the IRP. // LIST_ENTRY NotifyFullQueue; // // A queue of the notify IRPs that will be completed only if a // file is added, deleted, or renamed in the directory. Queued // using the Tail.Overlay.ListEntry of the IRP. // LIST_ENTRY NotifyPartialQueue; // // A queue of all the FCBs/DCBs that are opened under this // DCB. // LIST_ENTRY ParentDcbQueue; // // Spinlock to protect the queues above that contain cancelable IRPs. We can't // synchronize with a resource because IoCancelIrp can be called at DISPATCH_LEVEL. // KSPIN_LOCK SpinLock; } Dcb; // // A File Control Block (FCB) // struct { // // The following field is a queue head for a list of CCBs // that are opened under us. // LIST_ENTRY CcbQueue; // // The default read timeout. This is always a relative value. // LARGE_INTEGER ReadTimeout; // // File timestamps. // LARGE_INTEGER CreationTime; LARGE_INTEGER LastModificationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastChangeTime; } Fcb; } Specific; // // The following field is used to check share access for // clients that want to open the file/directory. // SHARE_ACCESS ShareAccess; // // The following field is the fully qualified file name for this FCB/DCB // starting from the root of the volume, and last file name in the // fully qualified name. // UNICODE_STRING FullFileName; UNICODE_STRING LastFileName; // // The following field contains a prefix table entry that is used when // searching a volume for a name (or longest matching prefix) // UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry; // // The following field is used to remember the process that created this // mailslot. It is needed to allocate quota and return quota. // PEPROCESS CreatorProcess; // // The following data queue is used to contain the buffered information // for the mailslot. // DATA_QUEUE DataQueue; // // A resource variable to control access to the File specific data // structures // ERESOURCE Resource; } FCB, DCB, ROOT_DCB, *PFCB, *PDCB, *PROOT_DCB; // // The CCB record is allocated for every cliennt side open of a mailslot. // typedef struct _CCB { // // Header.NodeTypeCode of this record (must be MSFS_NTC_CCB). // NODE_HEADER Header; // // The following field is a list entry for the list of ccb that we // are a member of. // LIST_ENTRY CcbLinks; // // A pointer to the FCB, or VCB that we are tied to // PFCB Fcb; // // Pointers to the file object of the client has opened this file. // PFILE_OBJECT FileObject; // // A resource to control access to the CCB. // ERESOURCE Resource; } CCB, *PCCB; // // The root DCB CCB record is allocated for every opened instance of the // root dcb. This record is pointed at by FsContext2. // typedef struct _ROOT_DCB_CCB { // // Header.NodeTypeCode of this record (must be MSFS_NTC_ROOT_DCB_CCB). // NODE_HEADER Header; // // A pointer to the VCB containing this CCB. // PVCB Vcb; // // Pointer to the DCB for this CCB // PROOT_DCB Dcb; // // The following field is a count of the last index returned // by query directory. // ULONG IndexOfLastCcbReturned; // // The following string is used as a query template for directory // query operations // PUNICODE_STRING QueryTemplate; } ROOT_DCB_CCB, *PROOT_DCB_CCB; // // A work context contains the information needed to do read timeouts. // typedef struct _WORK_CONTEXT { // // Pointer to unload safe work item. // PIO_WORKITEM WorkItem; // // A pointer to the IRP for this operation. // PIRP Irp; // // A referenced pointer to the FCB that will process this operation. // PFCB Fcb; // // A timer and dpc tourine to accomplish the timeout. // KTIMER Timer; KDPC Dpc; } WORK_CONTEXT, *PWORK_CONTEXT; #endif // _MSSTRUC_