NT4/private/ntos/npfs/npstruc.h
2020-09-30 17:12:29 +02:00

811 lines
22 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
NpStruc.h
Abstract:
This module defines the data structures that make up the major internal
part of the Named Pipe file system.
Author:
Gary Kimura [GaryKi] 20-Aug-1990
Revision History:
--*/
#ifndef _NPSTRUC_
#define _NPSTRUC_
//
// The VCB record is the top record in the Named Pipe 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 named
// pipe. Structurally the layout of the data structure is as follows
//
// +------------+
// |NPDO |
// | |
// +------------+
// |Vcb |
// | |
// | EventTable |
// | WaitQueue |
// | |
// +------------+
// | ^
// | |
// | |
// v |
// +-------------+
// |RootDcb |
// | |<-+
// +-------------+ |
// | |
// v |
// +-------------+ |
// |NonPaged | |
// | | |
// +-------------+ |
// : |
// : |
// : |
// v |
// +----------------+ +-------------------+ +---------+
// |Fcb | |Ccb | |ServerFO |
// | |<---| | | |
// | MaxInstances | | ServerFO |<-------|- 1|
// | CurrentInst | | ClientFO | | |
// | DefaultTimeOut |...>| |<-+ +--|- |
// | | | | | | | |
// +----------------+ +-------------------+ | | +---------+
// | | | |
// v v | |
// +----------------+ +-------------------+ | | +---------+
// |NonPagedFcb | |NonPagedCcb |<-|--+ |ClientFO |
// | |<---| | | | |
// | PipeConfig | | PipeState | +-----|- 0|
// | PipeType | | ReadMode[2] | | |
// | | | CompletionMode[2] |<-------|- |
// | | | CreatorProcess | | |
// | | | EventTabEnt[2] | +---------+
// | | | DataQueue[2] |
// | | | | (low bit determines
// +----------------+ +-------------------+ server/client)
//
//
// Where there is only one Vcb for the entire Named Pipe 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 named pipe.
// There is one Ccb for every instance of a named pipe. 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 named pipe file system only contains the Vcb and
// the root dcb. A new Fcb is created when a new named pipe is created
// and then a ccb must also be created. The file object for the creater
// (i.e., server end) points to the ccb and indicates that it is the server
// end. When a user does an open on the named pipe its file object is
// set to point to the same ccb and is also set to indicate that it is the
// client end. This is denoted by using the last bit of the FsContext pointer
// if the bit is 1 it is a server end file object, if the bit is 0 it is
// the client end.
//
// A file object with a null pointer to the FsContext field is a closed or
// disconnected pipe.
//
// The Ccb also contains back pointer to the file objects that have it opened
//
//
// The following types are used to help during development by keeping the
// data types distinct. The manifest contants that go in each is declared
// in the ntioapi.h file
//
typedef ULONG NAMED_PIPE_TYPE;
typedef NAMED_PIPE_TYPE *PNAMED_PIPE_TYPE;
typedef ULONG READ_MODE;
typedef READ_MODE *PREAD_MODE;
typedef ULONG COMPLETION_MODE;
typedef COMPLETION_MODE *PCOMPLETION_MODE;
typedef ULONG NAMED_PIPE_CONFIGURATION;
typedef NAMED_PIPE_CONFIGURATION *PNAMED_PIPE_CONFIGURATION;
typedef ULONG NAMED_PIPE_STATE;
typedef NAMED_PIPE_STATE *PNAMED_PIPE_STATE;
typedef ULONG NAMED_PIPE_END;
typedef NAMED_PIPE_END *PNAMED_PIPE_END;
//
// The following two types are used by the event table package. The first
// is the event table itself which is just a generic table. It is protected
// by the vcb resource, and the second structure is an event table entry.
//
typedef struct _EVENT_TABLE {
RTL_GENERIC_TABLE Table;
} EVENT_TABLE;
typedef EVENT_TABLE *PEVENT_TABLE;
//
// The event table is a generic table of event table entries. Each Ccb
// optionally contains a pointer to an event table entry for each direction.
// The entries are part of the global event table defined off of the Vcb
//
typedef struct _EVENT_TABLE_ENTRY {
//
// The first two fields are used as keys in the generic table's
// comparison routines. The pipe end will either be FILE_PIPE_CLIENT_END
// or FILE_PIPE_SERVER_END.
//
struct _CCB *Ccb;
NAMED_PIPE_END NamedPipeEnd;
//
// The following three fields are used to identify the event entry
// to the named pipe user
//
HANDLE EventHandle;
PVOID Event;
ULONG KeyValue;
PEPROCESS Process;
} EVENT_TABLE_ENTRY;
typedef EVENT_TABLE_ENTRY *PEVENT_TABLE_ENTRY;
//
// Each Ccb has two data queues for holding the outstanding in-bound and
// out-bound 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 data queue is a structure that contains the queue state, quota
// information, and the list head. The quota information is used to
// maintain pipe 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 pipe direction and how much we've used up. This is only
// the creator quota and not the user quota.
//
ULONG Quota;
ULONG QuotaUsed;
//
// This is the head of a queue of data entries (singly linked)
//
struct _DATA_ENTRY *FrontOfQueue;
struct _DATA_ENTRY *EndOfQueue;
//
// The following field indicates how far we've already processed
// into the first entry in the data queue
//
ULONG NextByteOffset;
} DATA_QUEUE;
typedef DATA_QUEUE *PDATA_QUEUE;
//
// Each data entry has a type field that tells us if the operation
// for the entry is buffered, unbuffered, flush, or a close entry.
//
typedef enum _DATA_ENTRY_TYPE {
Buffered,
Unbuffered,
Flush,
Close
} DATA_ENTRY_TYPE;
//
// 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 pipe quota, the user quota, or it is part of the next IRP stack
// location.
//
typedef enum _FROM {
PipeQuota,
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 next stack
// location.
//
typedef struct _DATA_ENTRY {
//
// The following field is how we connect into the queue of data entries
//
struct _DATA_ENTRY *Next;
//
// The following two fields describe the type of data entry and where
// we got its memory from. If the type is buffered then the From field
// also denotes where we got the memory for the data buffer, otherwise
// the data buffer has been supplied by the IRP
//
DATA_ENTRY_TYPE DataEntryType : 8;
FROM From : 8;
//
// 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 buffer, or unbuffered, and are ignored otherwise.
//
ULONG DataSize;
PVOID DataPointer;
//
// The following field is used to point to the client context if dynamic
// impersonation is being used
//
PSECURITY_CLIENT_CONTEXT SecurityClientContext;
} DATA_ENTRY;
typedef DATA_ENTRY *PDATA_ENTRY;
//
// The following type is used by the wait queue package
//
typedef struct _WAIT_QUEUE {
LIST_ENTRY Queue;
KSPIN_LOCK SpinLock;
} WAIT_QUEUE;
typedef WAIT_QUEUE *PWAIT_QUEUE;
typedef struct _VCB {
//
// The type and size of this record (must be NPFS_NTC_VCB)
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
//
// A pointer to the root DCB for this volume
//
struct _FCB *RootDcb;
//
// A count of the number of file objects that have opened the \NamedPipe
// object directly, and also a count of the number of file objects
// that have opened a name pipe or the root directory.
//
CLONG OpenCount;
CLONG OpenUnderlingCount;
//
// 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 table is used to hold the named pipe events
//
EVENT_TABLE EventTable;
//
// The following field is a queue of waiting IRPS of type WaitForNamedPipe
//
WAIT_QUEUE WaitQueue;
//
// The following field is used to check share access people who want
// to open the named pipe driver
//
SHARE_ACCESS ShareAccess;
} VCB;
typedef VCB *PVCB;
//
// The Named Pipe 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.
//
typedef struct _NPFS_DEVICE_OBJECT {
DEVICE_OBJECT DeviceObject;
//
// This is the file system specific volume control block.
//
VCB Vcb;
} NPFS_DEVICE_OBJECT;
typedef NPFS_DEVICE_OBJECT *PNPFS_DEVICE_OBJECT;
//
// The Fcb/Dcb record corresponds to every opened named pipe and directory,
// and to every directory on an opened path.
//
// The structure is really divided into two parts. FCB can be allocated
// from paged pool which the NONPAGED_FCB must be allocated from non-paged
// pool.
//
typedef struct _FCB {
//
// Type and size of this record (must be NPFS_NTC_FCB, or
// NPFS_NTC_ROOT_DCB)
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
//
// 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;
//
// A count of the number of file objects that have opened
// this file/directory. For a pipe this is also the number of instances
// created for the pipe.
//
CLONG OpenCount;
//
// A count of the number of server end file objects that have opened
// this pipe. ServerOpenCount is incremented when OpenCount is
// incremented (when the server end creates an instance), but is
// decremented when the server end handle is closed, where OpenCount
// isn't decremented until both side's handles are closed. When
// ServerOpenCount is 0, a client's attempt to open a named pipe is
// met with STATUS_OBJECT_NAME_NOT_FOUND, not STATUS_PIPE_NOT_AVAILABLE,
// based on an assumption that since the server doesn't think it has
// any instances open, the pipe really doesn't exist anymore. An
// example of when this distinction is useful is when the server
// process exits, but the client processes haven't closed their
// handles yet.
//
CLONG ServerOpenCount;
//
// The following field points to the security descriptor for this named pipe
//
PSECURITY_DESCRIPTOR SecurityDescriptor;
//
// The following union is cased off of the node type code for the fcb.
// There 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. Enqueued 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. Enqueued
// 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;
//
// The following field is used to check share access people
// who want to open the directory.
//
SHARE_ACCESS ShareAccess;
} Dcb;
//
// An File Control Block (Fcb)
//
struct {
//
// This is the maximum number of instances we can have for the
// named pipe and the current number of instances is the open
// count for the fcb (note that the current number also
// correspondsto the number of Ccbs)
//
ULONG MaximumInstances;
//
// The assigned pipe configuration (FILE_PIPE_INBOUND,
// FILE_PIPE_OUTBOUND, or FILE_PIPE_FULL_DUPLEX) and pipe
// type (FILE_PIPE_MESSAGE_TYPE or
// FILE_PIPE_BYTE_STREAM_TYPE).
//
NAMED_PIPE_CONFIGURATION NamedPipeConfiguration : 16;
NAMED_PIPE_TYPE NamedPipeType : 16;
//
// The following field is the default timeout assigned to the
// named pipe
//
LARGE_INTEGER DefaultTimeOut;
//
// The Following field is a queue head for a list of ccbs
// that are opened under us
//
LIST_ENTRY CcbQueue;
} Fcb;
} Specific;
//
// 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;
//
// A pointer to the specific non-paged data for the Fcb.
//
struct _NONPAGED_FCB *NonpagedFcb;
} FCB, DCB, ROOT_DCB;
typedef FCB *PFCB;
typedef DCB *PDCB;
typedef ROOT_DCB *PROOT_DCB;
typedef struct _NONPAGED_FCB {
//
// Type and size of this record (must be NPFS_NTC_NONPAGED_FCB, or
// NPFS_NTC_NONPAGED_ROOT_DCB)
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
} NONPAGED_FCB, NONPAGED_DCB, NONPAGED_ROOT_DCB;
typedef NONPAGED_FCB *PNONPAGED_FCB;
typedef NONPAGED_DCB *PNONPAGED_DCB;
typedef NONPAGED_ROOT_DCB *PNONPAGED_ROOT_DCB;
//
// The Ccb record is allocated for every opened instance of a named pipe.
// There are two parts to a ccb a paged part and a Nonpaged part. Both
// parts are pointed at by the FsContext and FsContext2 field of a file
// object.
//
typedef struct _CCB {
//
// Type and size of this record (must be NPFS_NTC_CCB).
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
//
// 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 paged Fcb, or Vcb that we are tied to
//
PFCB Fcb;
//
// Back pointers to the server and client file objects that have us
// opened. This is indexed by either FILE_PIPE_CLIENT_END or
// FILE_PIPE_SERVER_END.
//
PFILE_OBJECT FileObject[2];
//
// The internal state of the Ccb. This is the shared access for each
// time this pipe/directory is opened.
//
SHARE_ACCESS ShareAccess;
//
// The following fields contain the session and process IDs of the
// client side of the named pipe instance. They are originally set
// to NULL (indicating local session) and the real client process
// ID but can be changed via FsCtl calls.
//
PVOID ClientSession;
PVOID ClientProcess;
//
// A pointer to the Nonpaged part of the ccb
//
struct _NONPAGED_CCB *NonpagedCcb;
//
// A pointer to the paged Fcb, or Vcb that we are tied to
//
PNONPAGED_FCB NonpagedFcb;
//
// Pipe state indicates the current state of the pipe
// (FILE_PIPE_DISCONNECTED_STATE, FILE_PIPE_LISTENING_STATE,
// FILE_PIPE_CONNECTED_STATE, or FILE_PIPE_CLOSING_STATE).
//
NAMED_PIPE_STATE NamedPipeState;
//
// read mode (FILE_PIPE_MESSAGE_MODE or FILE_PIPE_BYTE_STREAM_MODE),
// and completion mode (FILE_PIPE_QUEUE_OPERATION or
// FILE_PIPE_COMPLETE_OPERATION) describe how to handle requests to the
// pipe. Both of these fields are indexed by either FILE_PIPE_SERVER_END
// or FILE_PIPE_CLIENT_END.
//
READ_MODE ReadMode[2];
COMPLETION_MODE CompletionMode[2];
//
// The following field is used to remember the process that created this
// instance of the named pipe. It is needed to allocate quota and
// return quota
//
PEPROCESS CreatorProcess;
//
// The following data queues are used to contain the buffered information
// for each direction in the pipe. They array is indexed by
// PIPE_DIRECTION.
//
DATA_QUEUE DataQueue[2];
//
// The following fields are used for security impersonation
// Only the server end can impersonate and only for the inbound path
// (i.e., client writes then server reads and impersonates).
//
// If it is static tracking (SecurityQos contains the type of tracking)
// then we set the quality of service and the client context in the
// nonpaged ccb on open and we never change anything.
//
// If it is dynamic tracking then we set the quality of service in the
// nonpaged ccb and on every write by the client we set the client
// context in the data entry and when read by the server we update the
// client context field of the nonpaged ccb to value stored in the data
// entry.
//
// On impersonation we use the client context stored in the nonpaged ccb
//
SECURITY_QUALITY_OF_SERVICE SecurityQos;
PSECURITY_CLIENT_CONTEXT SecurityClientContext;
} CCB;
typedef CCB *PCCB;
typedef struct _NONPAGED_CCB {
//
// Type and size of this record (must be NPFS_NTC_NONPAGED_CCB)
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
//
// The following pointers denote the events we are to signal for the
// server and client ends of the named pipe. The actual entry
// is stored in the event table, and referenced here for easy access.
// The client end is signaled if ever a read/write occurs to the client
// of the pipe, and likewise for the server end. The array is
// indexed by either FILE_PIPE_SERVER_END or FILE_PIPE_CLIENT_END.
//
PEVENT_TABLE_ENTRY EventTableEntry[2];
//
// A queue of waiting listening IRPs. They are linked into the
// Tail.Overlay.ListEntry field in the Irp.
//
LIST_ENTRY ListeningQueue;
//
// Resource for synchronizing access
//
ERESOURCE Resource;
} NONPAGED_CCB;
typedef NONPAGED_CCB *PNONPAGED_CCB;
//
// 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 {
//
// Type and size of this record (must be NPFS_NTC_ROOT_DCB_CCB).
//
NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
//
// 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;
typedef ROOT_DCB_CCB *PROOT_DCB_CCB;
#endif // _NPSTRUC_