576 lines
13 KiB
C
576 lines
13 KiB
C
//+----------------------------------------------------------------------------
|
||
//
|
||
// 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 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 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;
|
||
|
||
//
|
||
// The following two fields are used to allocate IRP context structures
|
||
// using the zone allocator. The spinlock protects access to the zone
|
||
// and the zone variable denotes the zone itself
|
||
//
|
||
|
||
KSPIN_LOCK IrpContextSpinLock;
|
||
ZONE_HEADER IrpContextZone;
|
||
|
||
//
|
||
// 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;
|
||
|
||
} 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;
|
||
|
||
} DFS_VCB;
|
||
typedef DFS_VCB *PDFS_VCB;
|
||
|
||
#define VCB_STATE_FLAG_LOCKED (0x0001)
|
||
#define VCB_STATE_FLAG_ALLOC_FCB (0x0002)
|
||
//#define VCB_STATE_FLAG_DEVICE_ONLY (0x0008)
|
||
|
||
|
||
|
||
//
|
||
// 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;
|
||
|
||
//
|
||
// 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.
|
||
//
|
||
|
||
UNICODE_STRING FullFileName;
|
||
|
||
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;
|
||
|
||
} 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)
|
||
#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
|
||
|
||
#endif // _DFSSTRUC_
|