You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
16 KiB
677 lines
16 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1992, Microsoft Corporation.
|
|
//
|
|
// File: dfsstruc.h
|
|
//
|
|
// Contents:
|
|
// This module defines the data structures that make up the major internal
|
|
// part of the DFS file system.
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 12 Nov 1991 AlanW Created from CDFS souce.
|
|
// 8 May 1992 PeterCo Removed all EP related stuff
|
|
// Added stuff to support PKT
|
|
// 11 May 1992 PeterCo Added support for attached devices
|
|
// 24 April 1993 SudK Added support for KernelToUserMode calls
|
|
// Added support for timer functionality.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#ifndef _DFSSTRUC_
|
|
#define _DFSSTRUC_
|
|
|
|
typedef enum {
|
|
DFS_UNKNOWN = 0,
|
|
DFS_CLIENT = 1,
|
|
DFS_SERVER = 2,
|
|
DFS_ROOT_SERVER = 3,
|
|
} DFS_MACHINE_STATE;
|
|
|
|
typedef enum {
|
|
LV_UNINITIALIZED = 0,
|
|
LV_INITSCHEDULED,
|
|
LV_INITINPROGRESS,
|
|
LV_INITIALIZED,
|
|
LV_VALIDATED
|
|
} DFS_LV_STATE;
|
|
|
|
//
|
|
// The DFS_DATA record is the top record in the DFS file system in-memory
|
|
// data structure. This structure must be allocated from non-paged pool.
|
|
//
|
|
|
|
typedef struct _DFS_DATA {
|
|
|
|
//
|
|
// The type and size of this record (must be DSFS_NTC_DATA_HEADER)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// A queue of all the logical roots that are known by the file system.
|
|
//
|
|
|
|
LIST_ENTRY VcbQueue;
|
|
|
|
//
|
|
// A list of all the deleted logical roots that still have files open
|
|
// on them.
|
|
//
|
|
|
|
LIST_ENTRY DeletedVcbQueue;
|
|
|
|
//
|
|
// A queue of all the DRT (Deviceless roots) that are known.
|
|
//
|
|
|
|
LIST_ENTRY DrtQueue;
|
|
|
|
//
|
|
// A list of all the user-defined credentials
|
|
//
|
|
|
|
LIST_ENTRY Credentials;
|
|
|
|
//
|
|
// A list of all the deleted credentials. They will be destroyed once
|
|
// their ref count goes to 0
|
|
//
|
|
|
|
LIST_ENTRY DeletedCredentials;
|
|
|
|
//
|
|
// A list of all the offline roots
|
|
//
|
|
|
|
LIST_ENTRY OfflineRoots;
|
|
|
|
//
|
|
// A pointer to the Driver object we were initialized with
|
|
//
|
|
|
|
PDRIVER_OBJECT DriverObject;
|
|
|
|
//
|
|
// A pointer to the \Dfs device object
|
|
//
|
|
|
|
PDEVICE_OBJECT FileSysDeviceObject;
|
|
|
|
//
|
|
// A pointer to an array of provider records
|
|
//
|
|
|
|
struct _PROVIDER_DEF *pProvider;
|
|
int cProvider, maxProvider;
|
|
|
|
//
|
|
// A resource variable to control access to the global data record
|
|
//
|
|
|
|
ERESOURCE Resource;
|
|
|
|
//
|
|
// A spin lock to control access to the global data record; handy for
|
|
// Interlocked operations.
|
|
//
|
|
|
|
KSPIN_LOCK DfsLock;
|
|
|
|
//
|
|
// A pointer to our EPROCESS struct, which is a required input to the
|
|
// Cache Management subsystem. This field is simply set each time an
|
|
// FSP thread is started, since it is easiest to do while running in the
|
|
// Fsp.
|
|
//
|
|
|
|
PEPROCESS OurProcess;
|
|
|
|
//
|
|
// Lookaside list for IRP contexts
|
|
//
|
|
|
|
NPAGED_LOOKASIDE_LIST IrpContextLookaside;
|
|
|
|
//
|
|
// Device name prefix for the logical root devices.
|
|
// E.g., `\Device\WinDfs\'.
|
|
//
|
|
|
|
UNICODE_STRING LogRootDevName;
|
|
|
|
//
|
|
// The state of the machine - DC, Server, Client etc.
|
|
//
|
|
|
|
DFS_MACHINE_STATE MachineState;
|
|
|
|
//
|
|
// The system wide Partition Knowledge Table (PKT)
|
|
//
|
|
|
|
DFS_PKT Pkt;
|
|
|
|
//
|
|
// DNR has been designed so that resources (like the Pkt above) are not
|
|
// locked across network calls. This is critical to prevent inter-machine
|
|
// deadlocks and for other functionality. To regulate access to these
|
|
// resources, we use the following two events.
|
|
//
|
|
// This notify event is used to indicate that some thread is waiting to
|
|
// write into the Pkt. If this event is !RESET!, it means that a thread
|
|
// is waiting to write, and other threads trying to enter DNR should
|
|
// hold off.
|
|
//
|
|
|
|
KEVENT PktWritePending;
|
|
|
|
//
|
|
// This semaphone is used to indicate that some thread(s) have currently
|
|
// gone to get a referral. Another thread that wants to get a referral
|
|
// should wait till this semaphone is SIGNALLED before attempting to go
|
|
// get its own referral.
|
|
//
|
|
|
|
KSEMAPHORE PktReferralRequests;
|
|
|
|
//
|
|
// A hash table for associating DFS_FCBs with file objects
|
|
//
|
|
|
|
struct _FCB_HASH_TABLE *FcbHashTable;
|
|
|
|
//
|
|
// EA buffer used to diffrentiate CSC opens from others
|
|
//
|
|
|
|
PFILE_FULL_EA_INFORMATION CSCEaBuffer;
|
|
ULONG CSCEaBufferLength;
|
|
|
|
} DFS_DATA, *PDFS_DATA;
|
|
|
|
|
|
|
|
|
|
#define MAX_PROVIDERS 5 // number of pre-allocated provider records
|
|
|
|
//
|
|
// A PROVIDER_DEF is a structure that abstracts an underlying redirector.
|
|
//
|
|
|
|
typedef struct _PROVIDER_DEF {
|
|
|
|
//
|
|
// The type and size of this record (must be DSFS_NTC_PROVIDER)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// Provider ID and Capabilities, same as in the DS_REFERRAL structure.
|
|
//
|
|
|
|
USHORT eProviderId;
|
|
USHORT fProvCapability;
|
|
|
|
//
|
|
// The following field gives the name of the device for the provider.
|
|
//
|
|
|
|
UNICODE_STRING DeviceName;
|
|
|
|
//
|
|
// Referenced pointers to the associated file and device objects
|
|
//
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PFILE_OBJECT FileObject;
|
|
|
|
} PROVIDER_DEF, *PPROVIDER_DEF;
|
|
|
|
|
|
//
|
|
// The Vcb (Volume Control Block) record corresponds to every volume
|
|
// (ie, a net use) mounted by the file system. They are ordered in a
|
|
// queue off of DfsData.VcbQueue.
|
|
//
|
|
// For the DFS file system, `volumes' correspond to DFS logical roots.
|
|
// These records are an extension of a corresponding device object.
|
|
//
|
|
|
|
typedef struct _DFS_VCB {
|
|
|
|
//
|
|
// The type and size of this record (must be DSFS_NTC_VCB)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// The links for the device queue off of DfsData.VcbQueue
|
|
//
|
|
|
|
LIST_ENTRY VcbLinks;
|
|
|
|
//
|
|
// The internal state of the device. This is a collection of FSD device
|
|
// state flags.
|
|
//
|
|
|
|
USHORT VcbState;
|
|
|
|
//
|
|
// The logical root corresponding to this volume. Forms part of the
|
|
// path name in the NT object name space. This string will be something
|
|
// like L"org", or L"dom" etc.
|
|
//
|
|
|
|
UNICODE_STRING LogicalRoot;
|
|
|
|
//
|
|
// The LogRootPrefix has a prefix that needs to be prepended to file
|
|
// names being opened via this logical root before their name can
|
|
// be resolved.
|
|
//
|
|
|
|
UNICODE_STRING LogRootPrefix;
|
|
|
|
//
|
|
// The credentials associated with this logical root
|
|
//
|
|
|
|
struct _DFS_CREDENTIALS *Credentials;
|
|
|
|
//
|
|
// A count of the number of file objects that have opened the volume
|
|
// for direct access, and their share access state.
|
|
//
|
|
|
|
CLONG DirectAccessOpenCount;
|
|
SHARE_ACCESS ShareAccess;
|
|
|
|
//
|
|
// A count of the number of file objects that have any file/directory
|
|
// opened on this volume, not including direct access.
|
|
//
|
|
|
|
CLONG OpenFileCount;
|
|
PFILE_OBJECT FileObjectWithVcbLocked;
|
|
|
|
#ifdef TERMSRV
|
|
|
|
ULONG SessionID;
|
|
|
|
#endif // TERMSRV
|
|
|
|
LUID LogonID;
|
|
PDFS_PKT_ENTRY pktEntry;
|
|
} DFS_VCB;
|
|
typedef DFS_VCB *PDFS_VCB;
|
|
|
|
#define VCB_STATE_FLAG_LOCKED (0x0001)
|
|
#define VCB_STATE_FLAG_ALLOC_FCB (0x0002)
|
|
#define VCB_STATE_CSCAGENT_VOLUME (0x0004)
|
|
//#define VCB_STATE_FLAG_DEVICE_ONLY (0x0008)
|
|
|
|
#ifdef TERMSRV
|
|
|
|
//
|
|
// This SessionId indicates that the device name should not be suffixed
|
|
// with :SessionID, and that no matching on SessionID should be done.
|
|
//
|
|
|
|
#define INVALID_SESSIONID 0xffffffff
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// A CREDENTIAL_RECORD is a user-supplied set of credentials that should
|
|
// be used when accessing a particular Dfs. They are ordered in a queue
|
|
// off of DfsData.Credentials;
|
|
//
|
|
|
|
typedef struct _DFS_CREDENTIALS {
|
|
|
|
//
|
|
// The links for the credentials queue off of DfsData.Credentials
|
|
//
|
|
|
|
LIST_ENTRY Link;
|
|
|
|
//
|
|
// A flags field to keep state about this credential record.
|
|
//
|
|
|
|
ULONG Flags;
|
|
|
|
//
|
|
// A ref count to keep this credential record from going away while
|
|
// it is being used.
|
|
//
|
|
|
|
ULONG RefCount;
|
|
|
|
//
|
|
// A count of the number of net uses that refer to these credentials
|
|
//
|
|
|
|
ULONG NetUseCount;
|
|
|
|
//
|
|
// The root of the Dfs for which these credentials apply.
|
|
//
|
|
|
|
UNICODE_STRING ServerName;
|
|
UNICODE_STRING ShareName;
|
|
|
|
//
|
|
// The domain name, user name and password to use when accessing the
|
|
// Dfs rooted at ServerName\ShareName
|
|
//
|
|
|
|
UNICODE_STRING DomainName;
|
|
UNICODE_STRING UserName;
|
|
UNICODE_STRING Password;
|
|
|
|
#ifdef TERMSRV
|
|
|
|
ULONG SessionID;
|
|
|
|
#endif // TERMSRV
|
|
|
|
LUID LogonID;
|
|
//
|
|
// When setting up a Tree connect using these credentials, we'll need
|
|
// to form an EA Buffer to pass in with the ZwCreateFile call. So, we
|
|
// form one here.
|
|
//
|
|
|
|
ULONG EaLength;
|
|
PUCHAR EaBuffer[1];
|
|
|
|
} DFS_CREDENTIALS;
|
|
typedef DFS_CREDENTIALS *PDFS_CREDENTIALS;
|
|
|
|
#define CRED_HAS_DEVICE 0x1
|
|
#define CRED_IS_DEVICELESS 0x2
|
|
|
|
|
|
//
|
|
// The DFS_FCB record corresponds to every open file and directory.
|
|
//
|
|
|
|
typedef struct _DFS_FCB {
|
|
|
|
//
|
|
// Type and size of this record (must be DSFS_NTC_FCB or DSFS_NTC_DCB)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// A list entry for the hash table chain.
|
|
//
|
|
|
|
LIST_ENTRY HashChain;
|
|
|
|
//
|
|
// A pointer to the Logical root device, through which this DFS_FCB
|
|
// was opened.
|
|
//
|
|
|
|
PDFS_VCB Vcb;
|
|
|
|
//
|
|
// The following field is the fully qualified file name for this DFS_FCB/DCB
|
|
// starting from the logical root.
|
|
//
|
|
|
|
union {
|
|
UNICODE_STRING FullFileName;
|
|
DFS_NAME_CONTEXT DfsNameContext;
|
|
};
|
|
|
|
UNICODE_STRING AlternateFileName;
|
|
|
|
//
|
|
// The following fields give the file and devices on which this DFS_FCB
|
|
// have been opened. The DFS driver will pass through requests for
|
|
// the file object to the target device below.
|
|
//
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
//
|
|
// The destinatation FSD device object through which I/O will be done.
|
|
//
|
|
|
|
PDEVICE_OBJECT TargetDevice;
|
|
|
|
//
|
|
// The provider def that opened this file
|
|
//
|
|
|
|
USHORT ProviderId;
|
|
|
|
//
|
|
// The DFS_MACHINE_ENTRY through which this file was opened. We need
|
|
// to maintain a reference for each file on a DFS_MACHINE_ENTRY in
|
|
// case we have authenticated connections to the server; we don't want
|
|
// to tear down the authenticated connection if files are open.
|
|
//
|
|
|
|
PDFS_MACHINE_ENTRY DfsMachineEntry;
|
|
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
|
|
} DFS_FCB, *PDFS_FCB;
|
|
|
|
|
|
|
|
//
|
|
// The Logical Root Device Object is an I/O system device object
|
|
// created as a result of creating a DFS logical root.
|
|
// Logical roots are in many ways analogous to volumes
|
|
// for a local file system.
|
|
//
|
|
// There is a DFS_VCB record appended to the end.
|
|
//
|
|
|
|
typedef struct _LOGICAL_ROOT_DEVICE_OBJECT {
|
|
|
|
DEVICE_OBJECT DeviceObject;
|
|
|
|
//
|
|
// This is the file system specific volume control block.
|
|
//
|
|
|
|
DFS_VCB Vcb;
|
|
|
|
} LOGICAL_ROOT_DEVICE_OBJECT, *PLOGICAL_ROOT_DEVICE_OBJECT;
|
|
|
|
|
|
|
|
//
|
|
// The Irp Context record is allocated for every orginating Irp. It
|
|
// is created by the Fsd dispatch routines, and deallocated by the
|
|
// DfsCompleteRequest routine
|
|
//
|
|
|
|
typedef struct _IRP_CONTEXT {
|
|
|
|
//
|
|
// Type and size of this record (must be DSFS_NTC_IRP_CONTEXT)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// This structure is used for posting to the Ex worker threads.
|
|
//
|
|
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
|
|
//
|
|
// A pointer to the originating Irp.
|
|
//
|
|
|
|
PIRP OriginatingIrp;
|
|
|
|
//
|
|
// A pointer to function dependent context.
|
|
//
|
|
|
|
PVOID Context;
|
|
|
|
//
|
|
// Major and minor function codes copied from the Irp
|
|
//
|
|
|
|
UCHAR MajorFunction;
|
|
UCHAR MinorFunction;
|
|
|
|
//
|
|
// The following flags field indicates if we can wait/block for a resource
|
|
// or I/O, if we are to do everything write through, and if this
|
|
// entry into the Fsd is a recursive call
|
|
//
|
|
|
|
USHORT Flags;
|
|
|
|
//
|
|
// The following field contains the NTSTATUS value used when we are
|
|
// unwinding due to an exception
|
|
//
|
|
|
|
NTSTATUS ExceptionStatus;
|
|
|
|
} IRP_CONTEXT;
|
|
typedef IRP_CONTEXT *PIRP_CONTEXT;
|
|
|
|
//
|
|
// Values for the Irp context Flags field.
|
|
//
|
|
|
|
//#define IRP_CONTEXT_FLAG_FROM_POOL (0x00000001) // replaced by lookaside list
|
|
#define IRP_CONTEXT_FLAG_WAIT (0x00000002)
|
|
#define IRP_CONTEXT_FLAG_IN_FSD (0x00000004)
|
|
|
|
|
|
//
|
|
// This context is used by the DfsIoTimer routine. We can expand on this
|
|
// whenever new functionality needs to be added to the Timer function.
|
|
//
|
|
typedef struct _DFS_TIMER_CONTEXT {
|
|
|
|
//
|
|
// TickCount. To keep track of how many times the timer routine was
|
|
// called. The timer uses this to do things at a coarser granularity.
|
|
//
|
|
ULONG TickCount;
|
|
|
|
//
|
|
// InUse. This field is used to denote that this CONTEXT is in use
|
|
// by some function to which the Timer routine has passed it off. This
|
|
// is used in a simple way to control access to this context.
|
|
//
|
|
BOOLEAN InUse;
|
|
|
|
//
|
|
// ValidateLocalPartitions. This field is used to denote that the
|
|
// local volumes should be validated at this time.
|
|
//
|
|
|
|
BOOLEAN ValidateLocalPartitions;
|
|
|
|
//
|
|
// This is used to schedule DfsAgePktEntries.
|
|
//
|
|
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
|
|
//
|
|
// This is used to schedule DfsDeleteDevices.
|
|
//
|
|
|
|
WORK_QUEUE_ITEM DeleteQueueItem;
|
|
|
|
} DFS_TIMER_CONTEXT, *PDFS_TIMER_CONTEXT;
|
|
|
|
//
|
|
// The following constant is the number of seconds between any two scans
|
|
// through the PKT to get rid of old PKT entries.
|
|
//
|
|
#define DFS_MAX_TICKS 240
|
|
|
|
//
|
|
// The following constant is the number of seconds that a referral will
|
|
// remain in cache (PKT).
|
|
//
|
|
|
|
#define MAX_REFERRAL_LIFE_TIME 300
|
|
|
|
//
|
|
// The followin constants are the starting timeout (in seconds) between
|
|
// special referrals. The start value is doubled after every retry until it
|
|
// reaches the max.
|
|
//
|
|
|
|
#define SPECIAL_TIMEOUT_START (5*60) // 5 min
|
|
#define SPECIAL_TIMEOUT_MAX (60*60) // 60 min
|
|
|
|
|
|
//
|
|
// The Drt (Devless Root) record corresponds to every net use.
|
|
// They are ordered in a queue off of DfsData.VcbQueue.
|
|
//
|
|
//
|
|
|
|
typedef struct _DFS_DEVLESS_ROOT {
|
|
|
|
//
|
|
// The type and size of this record (must be DSFS_NTC_DRT)
|
|
//
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
//
|
|
// The links for the device queue off of DfsData.DrtQueue
|
|
//
|
|
|
|
LIST_ENTRY DrtLinks;
|
|
|
|
//
|
|
// The pathname corresponding to this entry.
|
|
//
|
|
|
|
UNICODE_STRING DevlessPath;
|
|
|
|
//
|
|
// The credentials associated with this logical root
|
|
//
|
|
|
|
struct _DFS_CREDENTIALS *Credentials;
|
|
|
|
#ifdef TERMSRV
|
|
|
|
ULONG SessionID;
|
|
|
|
#endif // TERMSRV
|
|
|
|
LUID LogonID;
|
|
PDFS_PKT_ENTRY pktEntry;
|
|
} DFS_DEVLESS_ROOT;
|
|
|
|
typedef DFS_DEVLESS_ROOT *PDFS_DEVLESS_ROOT;
|
|
|
|
#endif // _DFSSTRUC_
|