1794 lines
47 KiB
C
1794 lines
47 KiB
C
/*++
|
||
|
||
Copyright (c) 1989-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
UdfStruc.h
|
||
|
||
Abstract:
|
||
|
||
This module defines the data structures that make up the major internal
|
||
parts of the Udfs file system.
|
||
|
||
In-Memory structures:
|
||
|
||
The global data structures with the UdfDataRecord. It contains a pointer
|
||
to a File System Device object and a queue of Vcb's. There is a Vcb for
|
||
every currently or previously mounted volumes. We may be in the process
|
||
of tearing down the Vcb's which have been dismounted. The Vcb's are
|
||
allocated as an extension to a volume device object.
|
||
|
||
+---------+
|
||
| UdfData | +--------+
|
||
| | --> |FilSysDo|
|
||
| | | |
|
||
| | <+ +--------+
|
||
+---------+ |
|
||
|
|
||
| +--------+ +--------+
|
||
| |VolDo | |VolDo |
|
||
| | | | |
|
||
| +--------+ +--------+
|
||
+> |Vcb | <-> |Vcb | <-> ...
|
||
| | | |
|
||
+--------+ +--------+
|
||
|
||
|
||
Each Vcb contains a table of all the Fcbs for the volume indexed by
|
||
their FileId. Each Vcb contains a pointer to the root directory of
|
||
the volume. Each directory Fcb contains a queue of child Lcb's for
|
||
its children. Each Lcb is queued onto both its parent and child Fcb.
|
||
There can also be detached subtrees due to open operations by Id where
|
||
the Fcb's are not connected to the root.
|
||
|
||
The following diagram shows the root structure.
|
||
|
||
+--------+ +--------+
|
||
| Vcb |---->| Fcb |-------------------------------------------------------------------+
|
||
| | | Table |----------------------------------------------------------------+ |
|
||
| |--+ | |-------------------------------------------------------------+ | |
|
||
+--------+ | +--------+ | | |
|
||
| | | | | | |
|
||
| | | +---------------------------------------------+ | | |
|
||
| V +-----------------------+ | | | |
|
||
| +--------+ | | | | |
|
||
| |RootFcb | V V | | |
|
||
+->| | +-----+ +--------+ +--------+ | | |
|
||
| |<-->| Lcb |<-->|Child | +-----+ |Child | | | |
|
||
+--------+ +-----+ | Fcb |<-->| Lcb |<-->| Fcb |<--> ... | | |
|
||
| | +-----+ | | | | |
|
||
+--------+ +--------+ | | |
|
||
| | |
|
||
(Freestanding sub-tree) | | |
|
||
+--------+ | | |
|
||
|OpenById|<-------------------------------------------------------------+ | |
|
||
| Dir | +--------+ | |
|
||
| |--->|OpenById|<--------------------------------------------------+ |
|
||
+--------+ | Child | +--------+ |
|
||
| Dir |--->|OpenById|<---------------------------------------+
|
||
+--------+ | Child |
|
||
| File |
|
||
+--------+
|
||
|
||
Attached to each Directory Fcb is an prefix table containing the
|
||
Lcbs pointing to children of this directory for which there is an Fcb.
|
||
|
||
+--------+ +--------+
|
||
| Dir | | Prefix |
|
||
| Fcb |----->| Table |--------------------+
|
||
| | | |-------+ |
|
||
+--------+ +--------+ | |
|
||
^ | | |
|
||
| | | |
|
||
| V V V
|
||
| +--------+ +--------+ +--------+
|
||
| | Lcb | | Lcb | | Lcb |
|
||
+---------->| |<-->| |<-->| |
|
||
+--------+ +--------+ +--------+
|
||
|
||
Each file object open on a UDF volume contains two context pointers. The
|
||
first will point back to the Fcb for the file object. The second, if present,
|
||
points to a Ccb (ContextControlBlock) which contains the per-handle information.
|
||
This includes the state of any directory enumeration and the Lcb used to open
|
||
this file object.
|
||
|
||
+--------+ +--------+ +--------+
|
||
| Fcb |<------| File | | Ccb |
|
||
| | | Object|--->| |
|
||
| | | | | |
|
||
+--------+ +--------+ +--------+
|
||
^ ^
|
||
| | +--------+ +--------+
|
||
| | | File | | Ccb |
|
||
| +---------| Object|--->| |
|
||
| | | | |
|
||
| +--------+ +--------+
|
||
|
|
||
| +--------+
|
||
| |Stream |
|
||
+--------------| File |
|
||
| Object|
|
||
+--------+
|
||
|
||
|
||
Synchronization:
|
||
|
||
1. A resource in the UdfData synchronizes access to the Vcb queue. This
|
||
is used during mount/verify/dismount operations.
|
||
|
||
2. A resource in the Vcb is used to synchronize access to Vcb for
|
||
open/close operations. Typically acquired shared, it
|
||
is acquired exclusively to lock out these operations.
|
||
|
||
3. A second resource in the Vcb is used to synchronize all file operations.
|
||
Typically acquired shared, it is acquired exclusively to lock
|
||
out all file operations. Acquiring both Vcb resources will lock
|
||
the entire volume.
|
||
|
||
4. A resource in the nonpaged Fcb will synchronize open/close operations
|
||
on an Fcb.
|
||
|
||
5. A fast mutex in the Vcb will protect access to the Fcb table and
|
||
the open counts in the Vcb. It is also used to modify the reference
|
||
counts in all Fcbs/Lcbs. This mutex cannot be acquired
|
||
exclusely and is an end resource.
|
||
|
||
6. A fast mutex in the Fcb will synchronize access to all Fcb fields
|
||
which aren't synchronized in some other way. A thread may acquire
|
||
mutexes for multiple Fcb's as long as it works it way toward the
|
||
root of the tree. This mutex can also be acquired recursively.
|
||
|
||
7. Normal locking order is UdfData/Vcb/Fcb starting at any point in this
|
||
chain. The Vcb is required prior to acquiring resources for multiple
|
||
files. Shared ownership of the Vcb is sufficient in this case.
|
||
|
||
8. Normal locking order when acquiring multiple Fcb's is from some
|
||
starting Fcb and walking towards the root of tree. Create typically
|
||
walks down the tree. In this case we will attempt to acquire the
|
||
next node optimistically and if that fails we will reference
|
||
the current node in the tree, release it and acquire the next node.
|
||
At that point it will be safe to reacquire the parent node.
|
||
|
||
9. Locking order for the Fcb (via the fast mutex) will be from leaf of
|
||
tree back towards the root. No other resource may be acquired
|
||
after locking the Vcb (other than in-page reads).
|
||
|
||
10. Cleanup operations only lock the Vcb and Fcb long enough to change the
|
||
critical counts and share access fields. No reason to synchronize
|
||
otherwise. None of the structures can go away from beneath us
|
||
in this case.
|
||
|
||
// @@BEGIN_DDKSPLIT
|
||
|
||
Author:
|
||
|
||
Dan Lovinger [DanLo] 31-May-1996
|
||
|
||
Revision History:
|
||
|
||
Tom Jolly [TomJolly] 1-March-2000 UDF 2.01 support
|
||
|
||
// @@END_DDKSPLIT
|
||
|
||
--*/
|
||
|
||
#ifndef _UDFSTRUC_
|
||
#define _UDFSTRUC_
|
||
|
||
typedef PVOID PBCB;
|
||
|
||
|
||
//
|
||
// The following structure is used to encapsulate the converted timestamps for
|
||
// straightforward referencing.
|
||
//
|
||
|
||
typedef struct _TIMESTAMP_BUNDLE {
|
||
|
||
LARGE_INTEGER CreationTime;
|
||
LARGE_INTEGER AccessTime;
|
||
LARGE_INTEGER ModificationTime;
|
||
|
||
} TIMESTAMP_BUNDLE, *PTIMESTAMP_BUNDLE;
|
||
|
||
|
||
//
|
||
// The UDF_DATA record is the top record in the UDF file system in-memory
|
||
// data structure. This structure must be allocated from non-paged pool.
|
||
//
|
||
|
||
#define NUMBER_OF_FS_OBJECTS 2
|
||
|
||
typedef struct _UDF_DATA {
|
||
|
||
//
|
||
// The type and size of this record (must be UDFS_NTC_DATA_HEADER)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// A pointer to the Driver object we were initialized with
|
||
//
|
||
|
||
PDRIVER_OBJECT DriverObject;
|
||
|
||
//
|
||
// Vcb queue.
|
||
//
|
||
|
||
LIST_ENTRY VcbQueue;
|
||
|
||
//
|
||
// The following fields are used to allocate IRP context structures
|
||
// using a lookaside list, and other fixed sized structures from a
|
||
// small cache. We use the CdData mutex to protext these structures.
|
||
//
|
||
|
||
ULONG IrpContextDepth;
|
||
ULONG IrpContextMaxDepth;
|
||
SINGLE_LIST_ENTRY IrpContextList;
|
||
|
||
//
|
||
// Filesystem device objects for UDFS.
|
||
//
|
||
|
||
PDEVICE_OBJECT FileSystemDeviceObjects[NUMBER_OF_FS_OBJECTS];
|
||
|
||
//
|
||
// Following are used to manage the async and delayed close queue.
|
||
//
|
||
// FspCloseActive - Indicates whether there is a thread processing the
|
||
// two close queues.
|
||
// ReduceDelayedClose - Indicates that we have hit the upper threshold
|
||
// for the delayed close queue and need to reduce it to lower threshold.
|
||
//
|
||
// AsyncCloseQueue - Queue of IrpContext waiting for async close operation.
|
||
// AsyncCloseCount - Number of entries on the async close queue.
|
||
//
|
||
// DelayedCloseQueue - Queue of IrpContextLite waiting for delayed close
|
||
// operation.
|
||
// MaxDelayedCloseCount - Trigger delay close work at this threshold.
|
||
// MinDelayedCloseCount - Turn off delay close work at this threshold.
|
||
// DelayedCloseCount - Number of entries on the delayted close queue.
|
||
//
|
||
// CloseItem - Workqueue item used to start FspClose thread.
|
||
//
|
||
|
||
LIST_ENTRY AsyncCloseQueue;
|
||
ULONG AsyncCloseCount;
|
||
BOOLEAN FspCloseActive;
|
||
BOOLEAN ReduceDelayedClose;
|
||
USHORT PadUshort;
|
||
|
||
//
|
||
// The following fields describe the deferred close file objects.
|
||
//
|
||
|
||
LIST_ENTRY DelayedCloseQueue;
|
||
ULONG DelayedCloseCount;
|
||
ULONG MaxDelayedCloseCount;
|
||
ULONG MinDelayedCloseCount;
|
||
|
||
//
|
||
// Fast mutex used to lock the fields of this structure.
|
||
//
|
||
|
||
PVOID UdfDataLockThread;
|
||
FAST_MUTEX UdfDataMutex;
|
||
|
||
//
|
||
// A resource variable to control access to the global UDFS data record
|
||
//
|
||
|
||
ERESOURCE DataResource;
|
||
|
||
//
|
||
// Cache manager call back structure, which must be passed on each call
|
||
// to CcInitializeCacheMap.
|
||
//
|
||
|
||
CACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
|
||
CACHE_MANAGER_CALLBACKS CacheManagerVolumeCallbacks;
|
||
|
||
//
|
||
// This is the ExWorkerItem that does both kinds of deferred closes.
|
||
//
|
||
|
||
WORK_QUEUE_ITEM CloseItem;
|
||
|
||
} UDF_DATA, *PUDF_DATA;
|
||
|
||
|
||
//
|
||
// A PARTITION will record the VSN/LSN -> PSN retrieval information for a
|
||
// partition reference. Since we do not support multi-volume 13346/UDF,
|
||
// we will omit noting the volume sequence number that would tell us which
|
||
// piece of media contained the partition.
|
||
//
|
||
// There are currently three types of partitions used during operation: physical,
|
||
// sparable and virtual. However, since sparing merely adds another last layer
|
||
// of quick indirection, we consider them as a minor extension of a physical
|
||
// partition.
|
||
//
|
||
|
||
typedef enum _PARTITION_TYPE {
|
||
Uninitialized,
|
||
Physical,
|
||
Virtual
|
||
} PARTITION_TYPE, *PPARTITION_TYPE;
|
||
|
||
//
|
||
// A Physical partition corresponds to a single extent of the volume.
|
||
//
|
||
|
||
typedef struct _PARTITION_PHYSICAL {
|
||
|
||
//
|
||
// Starting Psn and length in sectors
|
||
//
|
||
|
||
ULONG Start;
|
||
ULONG Length;
|
||
|
||
//
|
||
// The partition number is specified by the LVD, and refers to
|
||
// a specific partition descriptor on the media. We use this
|
||
// in the second pass of partition discovery.
|
||
//
|
||
|
||
ULONG PartitionNumber;
|
||
PNSR_PART PartitionDescriptor;
|
||
|
||
//
|
||
// Spared partition map, saved temporarily between
|
||
// logical volume descriptor analysis and partition
|
||
// descriptor discover/pcb completion.
|
||
//
|
||
|
||
PPARTMAP_SPARABLE SparingMap;
|
||
|
||
} PARTITION_PHYSICAL, *PPARTITION_PHYSICAL;
|
||
|
||
//
|
||
// A Virtual partition is a remapping from VSN to LSN on a given Physical
|
||
// partition. The remapping is done through the VAT FCB.
|
||
//
|
||
|
||
typedef struct _PARTITION_VIRTUAL{
|
||
|
||
//
|
||
// The maximum Vbn in the virtual partition.
|
||
//
|
||
|
||
ULONG Length;
|
||
|
||
//
|
||
// A virtual partition refers to its "host" physical partition by partition
|
||
// number, which we translate to a partition reference during the second pass
|
||
// of partition discovery.
|
||
//
|
||
// Example: if the virtual partition is reference 1, hosted on partition 156
|
||
// (which is reference 0 for this logical volume), then NSRLBA 100/1 would
|
||
// refer to the block on partition ref 0 as mapped in the VAT at entry 100.
|
||
//
|
||
|
||
USHORT RelatedReference;
|
||
|
||
} PARTITION_VIRTUAL, *PPARTITION_VIRTUAL;
|
||
|
||
//
|
||
// There is exactly one PARTITION per partition. It is responsible for mapping
|
||
// from some form of logical sector to a physical sector.
|
||
//
|
||
|
||
typedef struct _PARTITION {
|
||
|
||
//
|
||
// This is the type of partition.
|
||
//
|
||
|
||
PARTITION_TYPE Type;
|
||
|
||
union {
|
||
|
||
PARTITION_PHYSICAL Physical;
|
||
PARTITION_VIRTUAL Virtual;
|
||
};
|
||
|
||
} PARTITION, *PPARTITION;
|
||
|
||
//
|
||
// The Pcb (Partition control block) record corresponds to the partitions
|
||
// which collectively form the mounted volume. Exactly one of these is
|
||
// linked off of the Vcb.
|
||
//
|
||
|
||
typedef struct _PCB {
|
||
|
||
//
|
||
// The type and size of this record (must be UDFS_NTC_PCB)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// This is the number of partitions in the map
|
||
//
|
||
|
||
USHORT Partitions;
|
||
|
||
//
|
||
// A bitmask of flags.
|
||
//
|
||
|
||
USHORT Flags;
|
||
|
||
//
|
||
// Sparing Mcb, if this volume has sparing.
|
||
//
|
||
|
||
PLARGE_MCB SparingMcb;
|
||
|
||
//
|
||
// This is the mapping table. A PCB will be dynamically sized
|
||
// according to the number of partitions forming the volume.
|
||
//
|
||
|
||
PARTITION Partition[0];
|
||
|
||
} PCB, *PPCB;
|
||
|
||
//
|
||
// Indicate what kinds of partitions are contained for quick checks.
|
||
//
|
||
|
||
#define PCB_FLAG_PHYSICAL_PARTITION 0x0001
|
||
#define PCB_FLAG_VIRTUAL_PARTITION 0x0002
|
||
#define PCB_FLAG_SPARABLE_PARTITION 0x0004
|
||
|
||
|
||
//
|
||
// The Vmcb structure is a double mapped structure for mapping
|
||
// between VBNs and LBNs using the MCB structures. The whole structure
|
||
// is also protected by a private mutex. This record must be allocated
|
||
// from non-paged pool.
|
||
//
|
||
|
||
//
|
||
// We use an #if to snip out historical code in the Vmcb package that
|
||
// dealt with write issues, leaving it for the future.
|
||
//
|
||
|
||
#define VMCB_WRITE_SUPPORT 0
|
||
|
||
typedef struct _VMCB {
|
||
|
||
//
|
||
// The type and size of this record (must be UDFS_NTC_VMCB)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
ERESOURCE Resource;
|
||
|
||
MCB VbnIndexed; // maps VBNs to LBNs
|
||
MCB LbnIndexed; // maps LBNs to VBNs
|
||
|
||
ULONG MaximumLbn;
|
||
|
||
ULONG SectorSize;
|
||
|
||
} VMCB, *PVMCB;
|
||
|
||
#define UDF_INVALID_VSN -1
|
||
|
||
//
|
||
// The Vcb (Volume control block) record corresponds to every
|
||
// volume mounted by the file system. They are ordered in a queue off
|
||
// of UdfData.VcbQueue.
|
||
//
|
||
// The Vcb will be in several conditions during its lifespan.
|
||
//
|
||
// NotMounted - Disk is not currently mounted (i.e. removed
|
||
// from system) but cleanup and close operations are
|
||
// supported.
|
||
//
|
||
// MountInProgress - State of the Vcb from the time it is
|
||
// created until it is successfully mounted or the mount
|
||
// fails.
|
||
//
|
||
// Mounted - Volume is currently in the mounted state.
|
||
//
|
||
// Invalid - User has invalidated the volume. Only legal operations
|
||
// are cleanup and close.
|
||
//
|
||
// DismountInProgress - We have begun the process of tearing down the
|
||
// Vcb. It can be deleted when all the references to it
|
||
// have gone away.
|
||
//
|
||
|
||
typedef enum _VCB_CONDITION {
|
||
|
||
VcbNotMounted = 0,
|
||
VcbMountInProgress,
|
||
VcbMounted,
|
||
VcbInvalid,
|
||
VcbDismountInProgress
|
||
|
||
} VCB_CONDITION;
|
||
|
||
typedef struct _VCB {
|
||
|
||
//
|
||
// The type and size of this record (must be UDFS_NTC_VCB)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// Vpb for this volume.
|
||
//
|
||
|
||
PVPB Vpb;
|
||
|
||
//
|
||
// Pcb for this volume.
|
||
//
|
||
|
||
PPCB Pcb;
|
||
|
||
//
|
||
// Device object for the driver below us.
|
||
//
|
||
|
||
PDEVICE_OBJECT TargetDeviceObject;
|
||
|
||
//
|
||
// Link into queue of Vcb's in the UdfData structure. We will create a union with
|
||
// a LONGLONG to force the Vcb to be quad-aligned.
|
||
//
|
||
|
||
union {
|
||
|
||
LIST_ENTRY VcbLinks;
|
||
LONGLONG Alignment;
|
||
};
|
||
|
||
//
|
||
// State flags and condition for the Vcb.
|
||
//
|
||
|
||
ULONG VcbState;
|
||
VCB_CONDITION VcbCondition;
|
||
|
||
//
|
||
// File object used to lock the volume.
|
||
//
|
||
|
||
PFILE_OBJECT VolumeLockFileObject;
|
||
|
||
//
|
||
// Media change count from device driver for bulletproof detection
|
||
// of media movement
|
||
//
|
||
|
||
ULONG MediaChangeCount;
|
||
|
||
//
|
||
// Logical block size for this volume.
|
||
//
|
||
|
||
ULONG SectorSize;
|
||
|
||
//
|
||
// Associated shift size
|
||
//
|
||
|
||
ULONG SectorShift;
|
||
|
||
//
|
||
// LSN of the bounds that CD-UDF defines.
|
||
//
|
||
// S - start of the session that contains the AVD @ +256
|
||
// N - end of the disc, another chance to find AVD @ -256,
|
||
// and discovery of the VAT ICB.
|
||
//
|
||
// N may be unset until late in the mount sequence for a volume, since
|
||
// the device may not respond to CD-style TOC requests, and only then
|
||
// be a guess based on the partitons we find. S will be zero except in
|
||
// the case of CD-UDF. In a mounted system, S will correspond to where
|
||
// we started finding the volume descriptors that let us proceed.
|
||
//
|
||
|
||
ULONG BoundS;
|
||
ULONG BoundN;
|
||
|
||
//
|
||
// Various counts for this Vcb.
|
||
//
|
||
// VcbCleanup - Open handles left on this system.
|
||
// VcbReference - Number of reasons this Vcb is still present.
|
||
// VcbUserReference - Number of user file objects still present.
|
||
//
|
||
|
||
ULONG VcbCleanup;
|
||
ULONG VcbReference;
|
||
ULONG VcbUserReference;
|
||
|
||
//
|
||
// These are the number of times a mounted Vcb will be referenced on behalf
|
||
// of the system. See commentary in udfdata.h.
|
||
//
|
||
|
||
ULONG VcbResidualReference;
|
||
ULONG VcbResidualUserReference;
|
||
|
||
//
|
||
// Fcb for the Volume Dasd file, root directory and the Vmcb-mapped Metadata stream.
|
||
// The VAT Fcb is only created on CD UDF media, for the Virtual Allocation Table.
|
||
//
|
||
|
||
struct _FCB *VolumeDasdFcb;
|
||
struct _FCB *RootIndexFcb;
|
||
struct _FCB *MetadataFcb;
|
||
struct _FCB *VatFcb;
|
||
|
||
//
|
||
// Offset from the beginning of the VAT stream to the first entry (UDF 2.0x has a header
|
||
// at the beginning of the VAT), and number of entries in the VAT.
|
||
//
|
||
|
||
ULONG OffsetToFirstVATEntry;
|
||
ULONG VATEntryCount;
|
||
|
||
//
|
||
// Vmcb for the metadata stream
|
||
//
|
||
|
||
VMCB Vmcb;
|
||
|
||
//
|
||
// Vmcb resource. This is used to synchronize mapping/purge operations on
|
||
// the vmcb stream. Must be acquired shared around any map/unpin or ccread
|
||
// on the vmcb, and exclusive for ccpurge. All mappings made in the current
|
||
// thread must be dropped before attempting to acquire exclusive.
|
||
//
|
||
|
||
ERESOURCE VmcbMappingResource;
|
||
|
||
//
|
||
// Vcb resource. This is used to synchronize open/cleanup/close operations.
|
||
//
|
||
|
||
ERESOURCE VcbResource;
|
||
|
||
//
|
||
// File resource. This is used to synchronize all file operations except
|
||
// open/cleanup/close.
|
||
//
|
||
|
||
ERESOURCE FileResource;
|
||
|
||
//
|
||
// Vcb fast mutex. This is used to synchronize the fields in the Vcb
|
||
// when modified when the Vcb is not held exclusively. Included here
|
||
// are the count fields and Fcb table.
|
||
//
|
||
// We also use this to synchronize changes to the Fcb reference field.
|
||
//
|
||
|
||
FAST_MUTEX VcbMutex;
|
||
PVOID VcbLockThread;
|
||
|
||
//
|
||
// The following is used to synchronize the dir notify package.
|
||
//
|
||
|
||
PNOTIFY_SYNC NotifySync;
|
||
|
||
//
|
||
// The following is the head of a list of notify Irps.
|
||
//
|
||
|
||
LIST_ENTRY DirNotifyList;
|
||
|
||
//
|
||
// Fcb table. Synchronized with the Vcb fast mutex.
|
||
//
|
||
|
||
RTL_GENERIC_TABLE FcbTable;
|
||
|
||
//
|
||
// Preallocated VPB for swapout, so we are not forced to consider
|
||
// must succeed pool.
|
||
//
|
||
|
||
PVPB SwapVpb;
|
||
|
||
//
|
||
// Information telling us what version of UDF we expect this disc to
|
||
// conform to. NsrVersion will be one of VsdIdentNSR02 or VsdIdentNSR03
|
||
// UdfXXXRead will be one of UDF_VERSION_XXX.
|
||
//
|
||
|
||
USHORT NsrVersion;
|
||
USHORT UdfRevision;
|
||
|
||
} VCB, *PVCB;
|
||
|
||
#define VCB_STATE_LOCKED (0x00000001)
|
||
#define VCB_STATE_REMOVABLE_MEDIA (0x00000002)
|
||
#define VCB_STATE_NOTIFY_REMOUNT (0x00000004)
|
||
#define VCB_STATE_METHOD_2_FIXUP (0x00000008)
|
||
#define VCB_STATE_VMCB_INIT (0x00000010)
|
||
#define VCB_STATE_VPB_NOT_ON_DEVICE (0x00000020)
|
||
|
||
//
|
||
// The Volume Device Object is an I/O system device object with a
|
||
// workqueue and an VCB record appended to the end. There are multiple
|
||
// of these records, one for every mounted volume, and are created during
|
||
// a volume mount operation. The work queue is for handling an overload
|
||
// of work requests to the volume.
|
||
//
|
||
|
||
typedef struct _VOLUME_DEVICE_OBJECT {
|
||
|
||
DEVICE_OBJECT DeviceObject;
|
||
|
||
//
|
||
// The following field tells how many requests for this volume have
|
||
// either been enqueued to ExWorker threads or are currently being
|
||
// serviced by ExWorker threads. If the number goes above
|
||
// a certain threshold, put the request on the overflow queue to be
|
||
// executed later.
|
||
//
|
||
|
||
ULONG PostedRequestCount;
|
||
|
||
//
|
||
// The following field indicates the number of IRP's waiting
|
||
// to be serviced in the overflow queue.
|
||
//
|
||
|
||
ULONG OverflowQueueCount;
|
||
|
||
//
|
||
// The following field contains the queue header of the overflow queue.
|
||
// The Overflow queue is a list of IRP's linked via the IRP's ListEntry
|
||
// field.
|
||
//
|
||
|
||
LIST_ENTRY OverflowQueue;
|
||
|
||
//
|
||
// The following spinlock protects access to all the above fields.
|
||
//
|
||
|
||
KSPIN_LOCK OverflowQueueSpinLock;
|
||
|
||
//
|
||
// This is the file system specific volume control block.
|
||
//
|
||
|
||
VCB Vcb;
|
||
|
||
} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;
|
||
|
||
|
||
//
|
||
// Udfs file id is a large integer. This corresponds to the FileInternalInformation
|
||
// query type and is used for internal FCB indexing.
|
||
//
|
||
|
||
typedef LARGE_INTEGER FILE_ID, *PFILE_ID;
|
||
|
||
|
||
//
|
||
// Lcb (Link Control Block), which corresponds to a link from a directory (or in
|
||
// the future, other container objects) to a file (UDF File Identifier). There is
|
||
// one of these for each name tuple in a prefix table.
|
||
//
|
||
|
||
typedef struct _LCB {
|
||
|
||
//
|
||
// Type and size of this record (must be UDFS_NTC_LCB)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// Pointer to the Parent Fcb for this entry and queue for Parent to
|
||
// find all referencing Lcbs. Corresponds to Fcb->ChildLcbQueue.
|
||
//
|
||
|
||
LIST_ENTRY ParentFcbLinks;
|
||
struct _FCB *ParentFcb;
|
||
|
||
//
|
||
// Pointer to Child (referenced) Fcb for this entry and queue for Child
|
||
// to find all referencing Lcbs. Corresponds to Fcb->ParentLcbQueue.
|
||
//
|
||
|
||
LIST_ENTRY ChildFcbLinks;
|
||
struct _FCB *ChildFcb;
|
||
|
||
//
|
||
// Number of extra realtime references made to this Lcb.
|
||
//
|
||
|
||
ULONG Reference;
|
||
|
||
//
|
||
// Flags indicating the state of this Lcb.
|
||
//
|
||
|
||
ULONG Flags;
|
||
|
||
//
|
||
// File attributes to be merged with the child Fcb. UDF seperates interesting
|
||
// information into the FID and FE so, properly, the name link (corresponding to
|
||
// a FID) must record some extra information.
|
||
//
|
||
|
||
ULONG FileAttributes;
|
||
|
||
//
|
||
// Splay links in the prefix tree.
|
||
//
|
||
|
||
RTL_SPLAY_LINKS Links;
|
||
|
||
//
|
||
// The name of this link.
|
||
//
|
||
|
||
UNICODE_STRING FileName;
|
||
|
||
} LCB, *PLCB;
|
||
|
||
#define LCB_FLAG_IGNORE_CASE 0x00000001
|
||
#define LCB_FLAG_SHORT_NAME 0x00000002
|
||
#define LCB_FLAG_POOL_ALLOCATED 0x00000004
|
||
|
||
//
|
||
// We build a lookaside of Lcb capable of holding a reasonably sized name.
|
||
//
|
||
|
||
#define SIZEOF_LOOKASIDE_LCB ( sizeof( LCB ) + ( sizeof( WCHAR ) * 16 ))
|
||
|
||
|
||
//
|
||
// The following two structures are the separate union structures for
|
||
// data and index Fcb's.
|
||
//
|
||
|
||
typedef enum _FCB_CONDITION {
|
||
FcbGood = 1,
|
||
FcbBad,
|
||
FcbNeedsToBeVerified
|
||
} FCB_CONDITION;
|
||
|
||
typedef struct _FCB_NONPAGED {
|
||
|
||
//
|
||
// Type and size of this record must be UDFS_NTC_FCB_NONPAGED
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// The following field contains a record of special pointers used by
|
||
// MM and Cache to manipluate section objects. Note that the values
|
||
// are set outside of the file system. However the file system on an
|
||
// open/create will set the file object's SectionObject field to
|
||
// point to this field
|
||
//
|
||
|
||
SECTION_OBJECT_POINTERS SegmentObject;
|
||
|
||
//
|
||
// This is the resource structure for this Fcb.
|
||
//
|
||
|
||
ERESOURCE FcbResource;
|
||
|
||
//
|
||
// This is the FastMutex for this Fcb.
|
||
//
|
||
|
||
FAST_MUTEX FcbMutex;
|
||
|
||
//
|
||
// This is the mutex that is inserted into the FCB_ADVANCED_HEADER
|
||
// FastMutex field
|
||
//
|
||
|
||
FAST_MUTEX AdvancedFcbHeaderMutex;
|
||
|
||
} FCB_NONPAGED;
|
||
typedef FCB_NONPAGED *PFCB_NONPAGED;
|
||
|
||
typedef struct _FCB_DATA {
|
||
|
||
//
|
||
// The following field is used by the oplock module
|
||
// to maintain current oplock information.
|
||
//
|
||
|
||
OPLOCK Oplock;
|
||
|
||
//
|
||
// The following field is used by the filelock module
|
||
// to maintain current byte range locking information.
|
||
// A file lock is allocated as needed.
|
||
//
|
||
|
||
PFILE_LOCK FileLock;
|
||
|
||
} FCB_DATA, *PFCB_DATA;
|
||
|
||
typedef struct _FCB_INDEX {
|
||
|
||
//
|
||
// Internal stream file for the directory.
|
||
//
|
||
|
||
PFILE_OBJECT FileObject;
|
||
|
||
//
|
||
// Root of splay trees for exact and ignore case prefix trees.
|
||
//
|
||
|
||
PRTL_SPLAY_LINKS ExactCaseRoot;
|
||
PRTL_SPLAY_LINKS IgnoreCaseRoot;
|
||
|
||
} FCB_INDEX, *PFCB_INDEX;
|
||
|
||
//
|
||
// The Fcb/Dcb record corresponds to every open file and directory, and to
|
||
// every directory on an opened path.
|
||
//
|
||
|
||
typedef struct _FCB_CORE {
|
||
|
||
//
|
||
// The following field is used for fast I/O. It contains the node
|
||
// type code and size, indicates if fast I/O is possible, contains
|
||
// allocation, file, and valid data size, a resource, and call back
|
||
// pointers for FastIoRead and FastMdlRead.
|
||
//
|
||
//
|
||
// Node type codes for the Fcb must be one of the following.
|
||
//
|
||
// UDFS_NTC_FCB_INDEX
|
||
// UDFS_NTC_FCB_DATA
|
||
//
|
||
|
||
//
|
||
// Common Fsrtl Header. The named header is for the fieldoff.c output. We
|
||
// use the unnamed header internally.
|
||
//
|
||
|
||
union {
|
||
|
||
FSRTL_ADVANCED_FCB_HEADER Header;
|
||
FSRTL_ADVANCED_FCB_HEADER;
|
||
};
|
||
|
||
//
|
||
// Vcb for this Fcb.
|
||
//
|
||
|
||
PVCB Vcb;
|
||
|
||
//
|
||
// Queues of Lcbs that are on this Fcb: Parent - edges that lead in
|
||
// Child - edges that lead out
|
||
//
|
||
// We anticipate supporting the streaming extension to UDF 2.0, so we
|
||
// leave the ChildLcbQueue here which in the case of a stream-rich file
|
||
// will contain a solitary Lcb leading to the stream directory.
|
||
//
|
||
|
||
LIST_ENTRY ParentLcbQueue;
|
||
LIST_ENTRY ChildLcbQueue;
|
||
|
||
//
|
||
// Length of Root ICB Extent for this object. Coupled with the information
|
||
// in the FileId, this will allow discovery of the active File Entry for this
|
||
// Fcb at any time.
|
||
//
|
||
|
||
ULONG RootExtentLength;
|
||
|
||
//
|
||
// FileId for this file.
|
||
//
|
||
|
||
FILE_ID FileId;
|
||
|
||
//
|
||
// Counts on this Fcb. Cleanup count represents the number of open handles
|
||
// on this Fcb. Reference count represents the number of reasons this Fcb
|
||
// is still present. It includes file objects, children Fcb and anyone
|
||
// who wants to prevent this Fcb from going away. Cleanup count is synchronized
|
||
// with the FcbResource. The reference count is synchronized with the
|
||
// VcbMutex.
|
||
//
|
||
|
||
ULONG FcbCleanup;
|
||
ULONG FcbReference;
|
||
ULONG FcbUserReference;
|
||
|
||
//
|
||
// State flags for this Fcb.
|
||
//
|
||
|
||
ULONG FcbState;
|
||
|
||
//
|
||
// NT style attributes for the Fcb.
|
||
//
|
||
|
||
ULONG FileAttributes;
|
||
|
||
//
|
||
// This is the thread and count for the thread which has locked this
|
||
// Fcb.
|
||
//
|
||
|
||
PVOID FcbLockThread;
|
||
ULONG FcbLockCount;
|
||
|
||
//
|
||
// Information for Lsn->Psn mapping. If the file data is embedded, we have a
|
||
// lookup into the metadata stream for the single logical block and an offset
|
||
// of the data within that block. If the file data is is external, we have a
|
||
// regular Mapping Control Block.
|
||
//
|
||
// Metadata structures are mapped through the volume-level Metadata Fcb which
|
||
// uses the volume's VMCB.
|
||
//
|
||
|
||
union {
|
||
|
||
LARGE_MCB Mcb;
|
||
|
||
struct EMBEDDED_MAPPING {
|
||
|
||
ULONG EmbeddedVsn;
|
||
ULONG EmbeddedOffset;
|
||
};
|
||
};
|
||
|
||
//
|
||
// This is the nonpaged data for the Fcb
|
||
//
|
||
|
||
PFCB_NONPAGED FcbNonpaged;
|
||
|
||
//
|
||
// Share access structure.
|
||
//
|
||
|
||
SHARE_ACCESS ShareAccess;
|
||
|
||
//
|
||
// We cache a few fields from the FE so that various operations do not have to
|
||
// hit the disk (query, etc.).
|
||
//
|
||
|
||
//
|
||
// Time stamps for this file.
|
||
//
|
||
|
||
TIMESTAMP_BUNDLE Timestamps;
|
||
|
||
//
|
||
// Link count on this file.
|
||
//
|
||
|
||
USHORT LinkCount;
|
||
|
||
//
|
||
// Icb.Icbtag.Filetype
|
||
//
|
||
|
||
UCHAR UdfIcbFileType;
|
||
} FCB_CORE, *PFCB_CORE;
|
||
|
||
|
||
//
|
||
// Split the Fcb into Core / Type specific structures, for the benefit of debugger
|
||
// extensions. which try and read the largest possible size of a union...
|
||
//
|
||
|
||
typedef struct _FCB {
|
||
|
||
FCB_CORE;
|
||
|
||
union {
|
||
|
||
ULONG FcbType;
|
||
FCB_INDEX;
|
||
FCB_DATA;
|
||
};
|
||
|
||
} FCB, *PFCB;
|
||
|
||
|
||
#define FCB_STATE_INITIALIZED (0x00000001)
|
||
#define FCB_STATE_IN_FCB_TABLE (0x00000002)
|
||
#define FCB_STATE_VMCB_MAPPING (0x00000004)
|
||
#define FCB_STATE_EMBEDDED_DATA (0x00000008)
|
||
#define FCB_STATE_MCB_INITIALIZED (0x00000010)
|
||
#define FCB_STATE_ALLOW_ONEGIG_WORKAROUND (0x00000020)
|
||
|
||
#define SIZEOF_FCB_DATA \
|
||
(FIELD_OFFSET( FCB, FcbType ) + sizeof( FCB_DATA ))
|
||
|
||
#define SIZEOF_FCB_INDEX \
|
||
(FIELD_OFFSET( FCB, FcbType ) + sizeof( FCB_INDEX ))
|
||
|
||
|
||
//
|
||
// The Ccb record is allocated for every user file object
|
||
//
|
||
|
||
typedef struct _CCB {
|
||
|
||
//
|
||
// Type and size of this record (must be UDFS_NTC_CCB)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// Flags. Indicates flags to apply for the current open.
|
||
//
|
||
|
||
ULONG Flags;
|
||
|
||
//
|
||
// Fcb for the file being opened.
|
||
//
|
||
|
||
PFCB Fcb;
|
||
|
||
//
|
||
// Lcb for the file being opened.
|
||
//
|
||
|
||
PLCB Lcb;
|
||
|
||
//
|
||
// We store state information in the Ccb for a directory
|
||
// enumeration on this handle.
|
||
//
|
||
|
||
//
|
||
// Offset in the virtual directory stream to base the next enumeration.
|
||
//
|
||
// A small number (in fact, possibly one) of file indices are reserved for
|
||
// synthesized directory entries (like '.'). Past that point, CurrentFileIndex -
|
||
// UDF_MAX_SYNTHESIZED_FILEINDEX is a byte offset in the stream.
|
||
//
|
||
|
||
LONGLONG CurrentFileIndex;
|
||
UNICODE_STRING SearchExpression;
|
||
|
||
//
|
||
// Highest ULONG-representable FileIndex so far found in the directory stream.
|
||
// This corresponds to the highest FileIndex returnable in a query structure.
|
||
//
|
||
|
||
ULONG HighestReturnableFileIndex;
|
||
|
||
} CCB, *PCCB;
|
||
|
||
#define CCB_FLAG_OPEN_BY_ID (0x00000001)
|
||
#define CCB_FLAG_OPEN_RELATIVE_BY_ID (0x00000002)
|
||
#define CCB_FLAG_IGNORE_CASE (0x00000004)
|
||
#define CCB_FLAG_DISMOUNT_ON_CLOSE (0x00000008)
|
||
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO (0x00000010)
|
||
|
||
//
|
||
// Following flags refer to index enumeration.
|
||
//
|
||
|
||
#define CCB_FLAG_ENUM_NAME_EXP_HAS_WILD (0x00010000)
|
||
#define CCB_FLAG_ENUM_MATCH_ALL (0x00020000)
|
||
#define CCB_FLAG_ENUM_RETURN_NEXT (0x00040000)
|
||
#define CCB_FLAG_ENUM_INITIALIZED (0x00080000)
|
||
#define CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY (0x00100000)
|
||
|
||
//
|
||
// The Irp Context record is allocated for every orginating Irp. It is
|
||
// created by the Fsd dispatch routines, and deallocated by the UdfComplete
|
||
// request routine
|
||
//
|
||
|
||
typedef struct _IRP_CONTEXT {
|
||
|
||
//
|
||
// Type and size of this record (must be UDFS_NTC_IRP_CONTEXT)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// Originating Irp for the request.
|
||
//
|
||
|
||
PIRP Irp;
|
||
|
||
//
|
||
// Vcb for this operation. When this is NULL it means we were called
|
||
// with our filesystem device object instead of a volume device object.
|
||
// (Mount will fill this in once the Vcb is created)
|
||
//
|
||
|
||
PVCB Vcb;
|
||
|
||
//
|
||
// Exception encountered during the request. Any error raised explicitly by
|
||
// the file system will be stored here. Any other error raised by the system
|
||
// is stored here after normalizing it.
|
||
//
|
||
|
||
NTSTATUS ExceptionStatus;
|
||
|
||
//
|
||
// Flags for this request.
|
||
//
|
||
|
||
ULONG Flags;
|
||
|
||
//
|
||
// Real device object. This represents the physical device closest to the media.
|
||
//
|
||
|
||
PDEVICE_OBJECT RealDevice;
|
||
|
||
//
|
||
// Io context for a read request.
|
||
// Address of Fcb for teardown oplock in create case.
|
||
//
|
||
|
||
union {
|
||
|
||
struct _UDF_IO_CONTEXT *IoContext;
|
||
PFCB *TeardownFcb;
|
||
};
|
||
|
||
//
|
||
// Top level irp context for this thread.
|
||
//
|
||
|
||
struct _IRP_CONTEXT *TopLevel;
|
||
|
||
//
|
||
// Major and minor function codes.
|
||
//
|
||
|
||
UCHAR MajorFunction;
|
||
UCHAR MinorFunction;
|
||
|
||
//
|
||
// Pointer to the top-level context if this IrpContext is responsible
|
||
// for cleaning it up.
|
||
//
|
||
|
||
struct _THREAD_CONTEXT *ThreadContext;
|
||
|
||
//
|
||
// This structure is used for posting to the Ex worker threads.
|
||
//
|
||
|
||
WORK_QUEUE_ITEM WorkQueueItem;
|
||
|
||
} IRP_CONTEXT, *PIRP_CONTEXT;
|
||
|
||
#define IRP_CONTEXT_FLAG_ON_STACK (0x00000001)
|
||
#define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002)
|
||
#define IRP_CONTEXT_FLAG_WAIT (0x00000004)
|
||
#define IRP_CONTEXT_FLAG_FORCE_POST (0x00000008)
|
||
#define IRP_CONTEXT_FLAG_TOP_LEVEL (0x00000010)
|
||
#define IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS (0x00000020)
|
||
#define IRP_CONTEXT_FLAG_IN_FSP (0x00000040)
|
||
#define IRP_CONTEXT_FLAG_IN_TEARDOWN (0x00000080)
|
||
#define IRP_CONTEXT_FLAG_ALLOC_IO (0x00000100)
|
||
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000200)
|
||
#define IRP_CONTEXT_FLAG_FORCE_VERIFY (0x00000400)
|
||
|
||
//
|
||
// Flags used for create.
|
||
//
|
||
|
||
#define IRP_CONTEXT_FLAG_FULL_NAME (0x10000000)
|
||
#define IRP_CONTEXT_FLAG_TRAIL_BACKSLASH (0x20000000)
|
||
|
||
//
|
||
// The following flags need to be cleared when a request is posted.
|
||
//
|
||
|
||
#define IRP_CONTEXT_FLAGS_CLEAR_ON_POST ( \
|
||
IRP_CONTEXT_FLAG_MORE_PROCESSING | \
|
||
IRP_CONTEXT_FLAG_WAIT | \
|
||
IRP_CONTEXT_FLAG_FORCE_POST | \
|
||
IRP_CONTEXT_FLAG_TOP_LEVEL | \
|
||
IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS | \
|
||
IRP_CONTEXT_FLAG_IN_FSP | \
|
||
IRP_CONTEXT_FLAG_IN_TEARDOWN | \
|
||
IRP_CONTEXT_FLAG_DISABLE_POPUPS \
|
||
)
|
||
|
||
//
|
||
// The following flags need to be cleared when a request is retried.
|
||
//
|
||
|
||
#define IRP_CONTEXT_FLAGS_CLEAR_ON_RETRY ( \
|
||
IRP_CONTEXT_FLAG_MORE_PROCESSING | \
|
||
IRP_CONTEXT_FLAG_IN_TEARDOWN | \
|
||
IRP_CONTEXT_FLAG_DISABLE_POPUPS \
|
||
)
|
||
|
||
//
|
||
// The following flags are set each time through the Fsp loop.
|
||
//
|
||
|
||
#define IRP_CONTEXT_FSP_FLAGS ( \
|
||
IRP_CONTEXT_FLAG_WAIT | \
|
||
IRP_CONTEXT_FLAG_TOP_LEVEL | \
|
||
IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS | \
|
||
IRP_CONTEXT_FLAG_IN_FSP \
|
||
)
|
||
|
||
|
||
//
|
||
// Following structure is used to queue a request to the delayed close queue.
|
||
// This structure should be the minimum block allocation size.
|
||
//
|
||
|
||
typedef struct _IRP_CONTEXT_LITE {
|
||
|
||
//
|
||
// Type and size of this record (must be UDFS_NTC_IRP_CONTEXT_LITE)
|
||
//
|
||
|
||
NODE_TYPE_CODE NodeTypeCode;
|
||
NODE_BYTE_SIZE NodeByteSize;
|
||
|
||
//
|
||
// Fcb for the file object being closed.
|
||
//
|
||
|
||
PFCB Fcb;
|
||
|
||
//
|
||
// List entry to attach to delayed close queue.
|
||
//
|
||
|
||
LIST_ENTRY DelayedCloseLinks;
|
||
|
||
//
|
||
// User reference count for the file object being closed.
|
||
//
|
||
|
||
ULONG UserReference;
|
||
|
||
//
|
||
// Real device object. This represents the physical device closest to the media.
|
||
//
|
||
|
||
PDEVICE_OBJECT RealDevice;
|
||
|
||
} IRP_CONTEXT_LITE, *PIRP_CONTEXT_LITE;
|
||
|
||
|
||
//
|
||
// Context structure for asynchronous I/O calls. Most of these fields
|
||
// are actually only required for the ReadMultiple routines, but
|
||
// the caller must allocate one as a local variable anyway before knowing
|
||
// whether there are multiple requests are not. Therefore, a single
|
||
// structure is used for simplicity.
|
||
//
|
||
|
||
typedef struct _UDF_IO_CONTEXT {
|
||
|
||
//
|
||
// These two fields are used for multiple run Io
|
||
//
|
||
|
||
LONG IrpCount;
|
||
PIRP MasterIrp;
|
||
NTSTATUS Status;
|
||
BOOLEAN AllocatedContext;
|
||
|
||
union {
|
||
|
||
//
|
||
// This element handles the asynchronous non-cached Io
|
||
//
|
||
|
||
struct {
|
||
|
||
PERESOURCE Resource;
|
||
ERESOURCE_THREAD ResourceThreadId;
|
||
ULONG RequestedByteCount;
|
||
};
|
||
|
||
//
|
||
// and this element handles the synchronous non-cached Io.
|
||
//
|
||
|
||
KEVENT SyncEvent;
|
||
};
|
||
|
||
} UDF_IO_CONTEXT, *PUDF_IO_CONTEXT;
|
||
|
||
|
||
//
|
||
// Following structure is used to track the top level request. Each Udfs
|
||
// Fsd and Fsp entry point will examine the top level irp location in the
|
||
// thread local storage to determine if this request is top level and/or
|
||
// top level Udfs. The top level Udfs request will remember the previous
|
||
// value and update that location with a stack location. This location
|
||
// can be accessed by recursive Udfs entry points.
|
||
//
|
||
|
||
typedef struct _THREAD_CONTEXT {
|
||
|
||
//
|
||
// UDFS signature. Used to confirm structure on stack is valid.
|
||
//
|
||
|
||
ULONG Udfs;
|
||
|
||
//
|
||
// Previous value in top-level thread location. We restore this
|
||
// when done.
|
||
//
|
||
|
||
PIRP SavedTopLevelIrp;
|
||
|
||
//
|
||
// Top level Udfs IrpContext. Initial Udfs entry point on stack
|
||
// will store the IrpContext for the request in this stack location.
|
||
//
|
||
|
||
PIRP_CONTEXT TopLevelIrpContext;
|
||
|
||
} THREAD_CONTEXT, *PTHREAD_CONTEXT;
|
||
|
||
|
||
//
|
||
// Following structure is used to build up static data for parse tables
|
||
//
|
||
|
||
typedef struct _PARSE_KEYVALUE {
|
||
PCHAR Key;
|
||
ULONG Value;
|
||
} PARSE_KEYVALUE, *PPARSE_KEYVALUE;
|
||
|
||
|
||
//
|
||
// Some macros for supporting the use of a Generic Table
|
||
// containing all the FCB and indexed by their FileId.
|
||
//
|
||
// The ISO 13346 lb_addr of the ICB hierarchy of the object
|
||
//
|
||
// { ULONG BlockNo; USHORT PartitionId }
|
||
//
|
||
// is encoded in the LowPart (BlockNo) and low 16 bits of the
|
||
// HighPart (PartitionId). The top 16 bits are reserved and are
|
||
// currently used to indicate the type of the object being referenced
|
||
// (file or directory).
|
||
//
|
||
// NOTE: this FileId prevents us from being able crack the name of
|
||
// object since an ICB hierarchy's contained direct File Entrys do
|
||
// not (and cannot) contain backpointers to the containing directory.
|
||
// In order to be able to crack paths, we need to be able to do a
|
||
// directory/dirent offset, which cannot fit in 64bits of FileId.
|
||
// A FileId must be 64bits since we export this in the FileInternalInforation
|
||
// query.
|
||
//
|
||
// Also, even through we are restricted to a single partition in this
|
||
// implementation, getting those "spare" 16bits isn't good enough to let us
|
||
// point directly into a directory's File Identifier. Files and by extension
|
||
// directories can exceed 2^32 bytes/entries. Once we have pointed at the
|
||
// parent dir, we are out of bits.
|
||
//
|
||
// The Id field is a LARGE_INTEGER where the High and Low parts can be
|
||
// accessed separately.
|
||
//
|
||
// The following macros are used to access the Fid fields.
|
||
//
|
||
// CdQueryFidDirentOffset - Accesses the Dirent offset field
|
||
// CdQueryFidPathTableNumber - Accesses the PathTable offset field
|
||
// CdSetFidDirentOffset - Sets the Dirent offset field
|
||
// CdSetFidPathTableNumber - Sets the PathTable ordinal field
|
||
// CdFidIsDirectory - Queries if directory bit is set
|
||
// CdFidSetDirectory - Sets directory bit
|
||
//
|
||
|
||
#define FID_DIR_MASK 0x80000000 // high order bit means directory.
|
||
|
||
#define UdfSetFidFromLbAddr(I, LBA) { (I).LowPart = (LBA).Lbn; \
|
||
(I).HighPart = (ULONG) (LBA).Partition; }
|
||
|
||
#define UdfGetFidLbn(I) ((I).LowPart)
|
||
#define UdfGetFidPartition(I) ((USHORT) (((I).HighPart & ~FID_DIR_MASK) & MAXUSHORT))
|
||
#define UdfGetFidReservedZero(I) ((I).HighPart & ~(FID_DIR_MASK|MAXUSHORT))
|
||
|
||
#define UdfSetFidFile(I) ClearFlag( (I).HighPart, FID_DIR_MASK )
|
||
#define UdfSetFidDirectory(I) SetFlag( (I).HighPart, FID_DIR_MASK )
|
||
|
||
#define UdfIsFidFile(I) BooleanFlagOff( (I).HighPart, FID_DIR_MASK )
|
||
#define UdfIsFidDirectory(I) BooleanFlagOn( (I).HighPart, FID_DIR_MASK )
|
||
|
||
#define UdfSetFidFromFidAndFe(I, FID, FE ) { \
|
||
UdfSetFidFromLbAddr((I), (FID)->Icb.Start); \
|
||
if ((FE) && ((FE)->Icbtag.FileType == ICBTAG_FILE_T_DIRECTORY)) { \
|
||
UdfSetFidDirectory((I)); \
|
||
} \
|
||
}
|
||
|
||
|
||
//
|
||
// Context structures for browsing through structures
|
||
//
|
||
|
||
//
|
||
// A mapped view is a useful bundle to hold information about a physical
|
||
// view of the disk.
|
||
//
|
||
|
||
typedef struct _MAPPED_PVIEW {
|
||
|
||
//
|
||
// A mapped extent and CC control block
|
||
//
|
||
|
||
PVOID View;
|
||
PBCB Bcb;
|
||
|
||
//
|
||
// Extent location
|
||
//
|
||
|
||
USHORT Partition;
|
||
ULONG Lbn;
|
||
ULONG Length;
|
||
|
||
//
|
||
// In the case of mappings through the metadata stream, store the Vsn currently
|
||
// mapped to the Lbn
|
||
//
|
||
|
||
ULONG Vsn;
|
||
|
||
} MAPPED_PVIEW, *PMAPPED_PVIEW;
|
||
|
||
|
||
//
|
||
// Enumeration contexts for various operations.
|
||
//
|
||
|
||
//
|
||
// The following is used for crawling ICB hierarchies searching
|
||
// for some notion of an active entry.
|
||
//
|
||
|
||
typedef struct _ICB_SEARCH_CONTEXT {
|
||
|
||
//
|
||
// Vcb the search is occuring on.
|
||
//
|
||
|
||
PVCB Vcb;
|
||
|
||
//
|
||
// Type of Icb being searched for.
|
||
//
|
||
|
||
USHORT IcbType;
|
||
|
||
//
|
||
// The Active is most prevailing ICB so far found.
|
||
//
|
||
|
||
MAPPED_PVIEW Active;
|
||
|
||
//
|
||
// The current logical block extent being read from the disk.
|
||
//
|
||
|
||
MAPPED_PVIEW Current;
|
||
|
||
} ICB_SEARCH_CONTEXT, *PICB_SEARCH_CONTEXT;
|
||
|
||
//
|
||
// The following is used for crawling Extended Attributes extending off of
|
||
// a direct ICB
|
||
//
|
||
|
||
typedef enum _EA_SEARCH_TYPE {
|
||
|
||
EaEnumBad = 0,
|
||
EaEnumISO,
|
||
EaEnumImplementation,
|
||
EaEnumApplication
|
||
|
||
} EA_SEARCH_TYPE, *PEA_SEARCH_TYPE;
|
||
|
||
typedef struct _EA_SEARCH_CONTEXT {
|
||
|
||
//
|
||
// Reference to an elaborated ICB_SEARCH_CONTEXT which gives us a handle
|
||
// onto a direct ICB to crawl.
|
||
//
|
||
|
||
PICB_SEARCH_CONTEXT IcbContext;
|
||
|
||
//
|
||
// The current Ea being looked at.
|
||
//
|
||
|
||
PVOID Ea;
|
||
|
||
//
|
||
// Bytes remaining in the EA view
|
||
//
|
||
|
||
ULONG Remaining;
|
||
|
||
//
|
||
// EA being searched for. We only support looking for ISO at this time.
|
||
//
|
||
|
||
ULONG EAType;
|
||
USHORT EASubType;
|
||
|
||
} EA_SEARCH_CONTEXT, *PEA_SEARCH_CONTEXT;
|
||
|
||
//
|
||
// The following is used to crawl the list of allocation extent descriptors attached
|
||
// to an ICB.
|
||
//
|
||
|
||
typedef struct _ALLOC_ENUM_CONTEXT {
|
||
|
||
//
|
||
// Reference to an elaborated ICB_ENUM_CONTEXT which gives us a handle
|
||
// onto a direct ICB to crawl.
|
||
//
|
||
|
||
PICB_SEARCH_CONTEXT IcbContext;
|
||
|
||
//
|
||
// The current allocation descriptor being looked at.
|
||
//
|
||
|
||
PVOID Alloc;
|
||
|
||
//
|
||
// Type of allocation descriptors in this enumeration
|
||
//
|
||
|
||
ULONG AllocType;
|
||
|
||
//
|
||
// Bytes remaining in this view.
|
||
//
|
||
|
||
ULONG Remaining;
|
||
|
||
} ALLOC_ENUM_CONTEXT, *PALLOC_ENUM_CONTEXT;
|
||
|
||
//
|
||
// The following is used to crawl a logical directory.
|
||
//
|
||
|
||
typedef struct _DIR_ENUM_CONTEXT {
|
||
|
||
//
|
||
// The current view in the enumeration.
|
||
//
|
||
|
||
PVOID View;
|
||
PBCB Bcb;
|
||
|
||
//
|
||
// Offset of the view from the beginning of the directory.
|
||
//
|
||
|
||
LARGE_INTEGER BaseOffset;
|
||
|
||
//
|
||
// Length of the view which is valid and the current
|
||
// offset in it.
|
||
//
|
||
|
||
ULONG ViewLength;
|
||
ULONG ViewOffset;
|
||
|
||
//
|
||
// Pointer to the current FID.
|
||
//
|
||
|
||
PNSR_FID Fid;
|
||
|
||
//
|
||
// Offset to the next fid from the beginning of the view.
|
||
//
|
||
|
||
ULONG NextFidOffset;
|
||
|
||
//
|
||
// Flags indicating the state of the enumeration.
|
||
//
|
||
|
||
ULONG Flags;
|
||
|
||
//
|
||
// Converted names from the FID. Case name is "case appropriate" for
|
||
// the operation.
|
||
//
|
||
|
||
UNICODE_STRING ObjectName;
|
||
UNICODE_STRING CaseObjectName;
|
||
|
||
//
|
||
// Real object name in pure form (not rendered to NT legal form)
|
||
//
|
||
|
||
UNICODE_STRING PureObjectName;
|
||
|
||
//
|
||
// Short name for the object.
|
||
//
|
||
|
||
UNICODE_STRING ShortObjectName;
|
||
|
||
//
|
||
// Currently allocated space for the name. The previous strings are
|
||
// carved out of this single buffer.
|
||
//
|
||
|
||
PVOID NameBuffer;
|
||
|
||
//
|
||
// Size of currently allocated name buffer for the lfn names.
|
||
//
|
||
|
||
USHORT AllocLength;
|
||
|
||
} DIR_ENUM_CONTEXT, *PDIR_ENUM_CONTEXT;
|
||
|
||
//
|
||
// Flags for noting where in the enumeration we are.
|
||
//
|
||
|
||
#define DIR_CONTEXT_FLAG_SEEN_NONCONSTANT 0x0001
|
||
#define DIR_CONTEXT_FLAG_SEEN_PARENT 0x0002
|
||
|
||
//
|
||
// Flag indicating current Fid was buffered into pool.
|
||
//
|
||
|
||
#define DIR_CONTEXT_FLAG_FID_BUFFERED 0x0004
|
||
|
||
#endif // _CDSTRUC_
|