599 lines
13 KiB
C
599 lines
13 KiB
C
/*++
|
||
|
||
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_
|