mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 07:08:19 +00:00
493 lines
22 KiB
C
493 lines
22 KiB
C
////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
|
|
// All rights reserved
|
|
// This file was released under the GPLv2 on June 2015.
|
|
////////////////////////////////////////////////////////////////////
|
|
/*************************************************************************
|
|
*
|
|
* File: struct.h
|
|
*
|
|
* Module: UDF File System Driver (Kernel mode execution only)
|
|
*
|
|
* Description:
|
|
* This file contains structure definitions for the UDF file system
|
|
* driver. Note that all structures are prefixed with the letters
|
|
* "UDF". The structures are all aligned using normal alignment
|
|
* used by the compiler (typically quad-word aligned).
|
|
*
|
|
*************************************************************************/
|
|
|
|
#ifndef _UDF_STRUCTURES_H_
|
|
#define _UDF_STRUCTURES_H_
|
|
|
|
|
|
/**************************************************************************
|
|
some useful definitions
|
|
**************************************************************************/
|
|
|
|
#include "Include/platform.h"
|
|
|
|
/**************************************************************************
|
|
some empty typedefs defined here so we can reference them easily
|
|
**************************************************************************/
|
|
struct _UDFIdentifier;
|
|
struct _UDFObjectName;
|
|
struct _UDFContextControlBlock;
|
|
struct _UDFNTRequiredFCB;
|
|
struct _UDFDiskDependentFCB;
|
|
struct _UDFFileControlBlock;
|
|
struct _UDFVolumeControlBlock;
|
|
struct _UDFIrpContext;
|
|
struct _UDFIrpContextLite;
|
|
struct _UDF_FILE_INFO;
|
|
struct _UDFData;
|
|
struct _UDFEjectWaitContext;
|
|
struct _UDFFileIDCacheItem;
|
|
struct _SparingEntry;
|
|
struct _UDFTrackMap;
|
|
|
|
/**************************************************************************
|
|
include udf related structures *here* (because we need definition of Fcb)
|
|
**************************************************************************/
|
|
#include "udf_info/udf_rel.h"
|
|
|
|
/**************************************************************************
|
|
each structure has a unique "node type" or signature associated with it
|
|
**************************************************************************/
|
|
#define UDF_NODE_TYPE_NT_REQ_FCB ((CSHORT)(0xfcb0))
|
|
#define UDF_NODE_TYPE_OBJECT_NAME (0xfdecba01)
|
|
#define UDF_NODE_TYPE_CCB (0xfdecba02)
|
|
#define UDF_NODE_TYPE_FCB (0xfdecba03)
|
|
#define UDF_NODE_TYPE_VCB (0xfdecba04)
|
|
#define UDF_NODE_TYPE_IRP_CONTEXT (0xfdecba05)
|
|
#define UDF_NODE_TYPE_GLOBAL_DATA (0xfdecba06)
|
|
#define UDF_NODE_TYPE_FILTER_DEVOBJ (0xfdecba07)
|
|
#define UDF_NODE_TYPE_UDFFS_DEVOBJ (0xfdecba08)
|
|
#define UDF_NODE_TYPE_IRP_CONTEXT_LITE (0xfdecba09)
|
|
#define UDF_NODE_TYPE_UDFFS_DRVOBJ (0xfdecba0a)
|
|
|
|
/**************************************************************************
|
|
every structure has a node type, and a node size associated with it.
|
|
The node type serves as a signature field. The size is used for
|
|
consistency checking ...
|
|
**************************************************************************/
|
|
typedef struct _UDFIdentifier {
|
|
uint32 NodeType; // a 32 bit identifier for the structure
|
|
uint32 NodeSize; // computed as sizeof(structure)
|
|
} UDFIdentifier, *PtrUDFIdentifier;
|
|
|
|
/**************************************************************************
|
|
Every open on-disk object must have a name associated with it
|
|
This name has two components:
|
|
(a) the path-name (prefix) that leads to this on-disk object
|
|
(b) the name of the object itself
|
|
Note that with multiply linked objects, a single object might be
|
|
associated with more than one name structure.
|
|
This UDF FSD does not correctly support multiply linked objects.
|
|
|
|
This structure must be quad-word aligned because it is zone allocated.
|
|
**************************************************************************/
|
|
typedef struct _UDFObjectName {
|
|
UDFIdentifier NodeIdentifier;
|
|
uint32 ObjectNameFlags;
|
|
// an absolute pathname of the object is stored below
|
|
UNICODE_STRING ObjectName;
|
|
} UDFObjectName, *PtrUDFObjectName;
|
|
|
|
#define UDF_OBJ_NAME_NOT_FROM_ZONE (0x80000000)
|
|
|
|
/**************************************************************************
|
|
Each file open instance is represented by a context control block.
|
|
For each successful create/open request; a file object and a CCB will
|
|
be created.
|
|
For open operations performed internally by the FSD, there may not
|
|
exist file objects; but a CCB will definitely be created.
|
|
|
|
This structure must be quad-word aligned because it is zone allocated.
|
|
**************************************************************************/
|
|
typedef struct _UDFContextControlBlock {
|
|
UDFIdentifier NodeIdentifier;
|
|
// ptr to the associated FCB
|
|
struct _UDFFileControlBlock *Fcb;
|
|
// all CCB structures for a FCB are linked together
|
|
LIST_ENTRY NextCCB;
|
|
// each CCB is associated with a file object
|
|
PFILE_OBJECT FileObject;
|
|
// flags (see below) associated with this CCB
|
|
uint32 CCBFlags;
|
|
// current index in directory is required sometimes
|
|
ULONG CurrentIndex;
|
|
// if this CCB represents a directory object open, we may
|
|
// need to maintain a search pattern
|
|
PUNICODE_STRING DirectorySearchPattern;
|
|
HASH_ENTRY hashes;
|
|
ULONG TreeLength;
|
|
// Acces rights previously granted to caller's thread
|
|
ACCESS_MASK PreviouslyGrantedAccess;
|
|
} UDFCCB, *PtrUDFCCB;
|
|
|
|
|
|
/**************************************************************************
|
|
the following CCBFlags values are relevant. These flag
|
|
values are bit fields; therefore we can test whether
|
|
a bit position is set (1) or not set (0).
|
|
**************************************************************************/
|
|
|
|
// some on-disk file/directories are opened by UDF itself
|
|
// as opposed to being opened on behalf of a user process
|
|
#define UDF_CCB_OPENED_BY_UDF (0x00000001)
|
|
// the file object specified synchronous access at create/open time.
|
|
// this implies that UDF must maintain the current byte offset
|
|
#define UDF_CCB_OPENED_FOR_SYNC_ACCESS (0x00000002)
|
|
// file object specified sequential access for this file
|
|
#define UDF_CCB_OPENED_FOR_SEQ_ACCESS (0x00000004)
|
|
// the CCB has had an IRP_MJ_CLEANUP issued on it. we must
|
|
// no longer allow the file object / CCB to be used in I/O requests.
|
|
#define UDF_CCB_CLEANED (0x00000008)
|
|
// if we were invoked via the fast i/o path to perform file i/o;
|
|
// we should set the CCB access/modification time at cleanup
|
|
#define UDF_CCB_ACCESSED (0x00000010)
|
|
#define UDF_CCB_MODIFIED (0x00000020)
|
|
// if an application process set the file date time, we must
|
|
// honor that request and *not* overwrite the values at cleanup
|
|
#define UDF_CCB_ACCESS_TIME_SET (0x00000040)
|
|
#define UDF_CCB_MODIFY_TIME_SET (0x00000080)
|
|
#define UDF_CCB_CREATE_TIME_SET (0x00000100)
|
|
#define UDF_CCB_WRITE_TIME_SET (0x00000200)
|
|
#define UDF_CCB_ATTRIBUTES_SET (0x00020000)
|
|
|
|
#define UDF_CCB_CASE_SENSETIVE (0x00000400)
|
|
|
|
#ifndef UDF_READ_ONLY_BUILD
|
|
#define UDF_CCB_DELETE_ON_CLOSE (0x00000800)
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
|
|
// this CCB was allocated for a "volume open" operation
|
|
#define UDF_CCB_VOLUME_OPEN (0x00001000)
|
|
#define UDF_CCB_MATCH_ALL (0x00002000)
|
|
#define UDF_CCB_WILDCARD_PRESENT (0x00004000)
|
|
#define UDF_CCB_CAN_BE_8_DOT_3 (0x00008000)
|
|
#define UDF_CCB_READ_ONLY (0x00010000)
|
|
//#define UDF_CCB_ATTRIBUTES_SET (0x00020000) // see above
|
|
|
|
#define UDF_CCB_FLUSHED (0x20000000)
|
|
#define UDF_CCB_VALID (0x40000000)
|
|
#define UDF_CCB_NOT_FROM_ZONE (0x80000000)
|
|
|
|
|
|
/**************************************************************************
|
|
each open file/directory/volume is represented by a file control block.
|
|
|
|
Each FCB can logically be divided into two:
|
|
(a) a structure that must have a field of type FSRTL_COMMON_FCB_HEADER
|
|
as the first field in the structure.
|
|
This portion should also contain other structures/resources required
|
|
by the NT Cache Manager
|
|
We will call this structure the "NT Required" FCB. Note that this
|
|
portion of the FCB must be allocated from non-paged pool.
|
|
(b) the remainder of the FCB is dependent upon the particular FSD
|
|
requirements.
|
|
This portion of the FCB could possibly be allocated from paged
|
|
memory, though in the UDF FSD, it will always be allocated
|
|
from non-paged pool.
|
|
|
|
FCB structures are protected by the MainResource as well as the
|
|
PagingIoResource. Of course, if the FSD implementation requires
|
|
it, we can associate other syncronization structures with the
|
|
FCB.
|
|
|
|
These structures must be quad-word aligned because they are zone-allocated.
|
|
**************************************************************************/
|
|
|
|
typedef struct _UDFNTRequiredFCB {
|
|
|
|
FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
|
|
SECTION_OBJECT_POINTERS SectionObject;
|
|
FILE_LOCK FileLock;
|
|
ERESOURCE MainResource;
|
|
ERESOURCE PagingIoResource;
|
|
// we will maintain some time information here to make our life easier
|
|
LARGE_INTEGER CreationTime;
|
|
LARGE_INTEGER LastAccessTime;
|
|
LARGE_INTEGER LastWriteTime;
|
|
LARGE_INTEGER ChangeTime;
|
|
// NT requires that a file system maintain and honor the various
|
|
// SHARE_ACCESS modes ...
|
|
SHARE_ACCESS FCBShareAccess;
|
|
// This counter is used to prevent unexpected structure releases
|
|
ULONG CommonRefCount;
|
|
PSECURITY_DESCRIPTOR SecurityDesc;
|
|
ULONG NtReqFCBFlags;
|
|
// to identify the lazy writer thread(s) we will grab and store
|
|
// the thread id here when a request to acquire resource(s)
|
|
// arrives ..
|
|
uint32 LazyWriterThreadID;
|
|
UCHAR AcqSectionCount;
|
|
UCHAR AcqFlushCount;
|
|
#ifdef DBG
|
|
PFILE_OBJECT FileObject;
|
|
#endif //DBG
|
|
PETHREAD CloseThread;
|
|
} UDFNTRequiredFCB, *PtrUDFNTRequiredFCB;
|
|
|
|
#define UDF_NTREQ_FCB_SD_MODIFIED (0x00000001)
|
|
#define UDF_NTREQ_FCB_INLIST (0x00000002)
|
|
#define UDF_NTREQ_FCB_DELETED (0x00000004)
|
|
#define UDF_NTREQ_FCB_MODIFIED (0x00000008)
|
|
#define UDF_NTREQ_FCB_VALID (0x40000000)
|
|
|
|
/**************************************************************************/
|
|
|
|
#define UDF_FCB_MT NonPagedPool
|
|
|
|
/***************************************************/
|
|
/***************** W A R N I N G *****************/
|
|
/***************************************************/
|
|
|
|
/***************************************************/
|
|
/* DO NOT FORGET TO UPDATE VCB's HEADER ! */
|
|
/***************************************************/
|
|
|
|
typedef struct _UDFFileControlBlock {
|
|
UDFIdentifier NodeIdentifier;
|
|
// we will not embed the "NT Required FCB" here, 'cause we dislike
|
|
// troubles with Hard(&Symbolic) Links
|
|
PtrUDFNTRequiredFCB NTRequiredFCB;
|
|
// UDF related data
|
|
PUDF_FILE_INFO FileInfo;
|
|
// this FCB belongs to some mounted logical volume
|
|
struct _UDFVolumeControlBlock* Vcb;
|
|
// to be able to access all open file(s) for a volume, we will
|
|
// link all FCB structures for a logical volume together
|
|
LIST_ENTRY NextFCB;
|
|
// some state information for the FCB is maintained using the
|
|
// flags field
|
|
uint32 FCBFlags;
|
|
// all CCB's for this particular FCB are linked off the following
|
|
// list head.
|
|
LIST_ENTRY NextCCB;
|
|
// whenever a file stream has a create/open operation performed,
|
|
// the Reference count below is incremented AND the OpenHandle count
|
|
// below is also incremented.
|
|
// When an IRP_MJ_CLEANUP is received, the OpenHandle count below
|
|
// is decremented.
|
|
// When an IRP_MJ_CLOSE is received, the Reference count below is
|
|
// decremented.
|
|
// When the Reference count goes down to zero, the FCB can be de-allocated.
|
|
// Note that a zero Reference count implies a zero OpenHandle count.
|
|
// But when we have mapped data, we can receive no IRP_MJ_CLOSE
|
|
// In this case OpenHandleCount may reach zero, but ReferenceCount may
|
|
// be non-zero.
|
|
uint32 ReferenceCount;
|
|
uint32 OpenHandleCount;
|
|
uint32 CachedOpenHandleCount;
|
|
// for the UDF fsd, there exists a 1-1 correspondence between a
|
|
// full object pathname and a FCB
|
|
PtrUDFObjectName FCBName;
|
|
ERESOURCE CcbListResource;
|
|
|
|
struct _UDFFileControlBlock* ParentFcb;
|
|
// Pointer to IrpContextLite in delayed queue.
|
|
struct _UDFIrpContextLite* IrpContextLite;
|
|
uint32 CcbCount;
|
|
} UDFFCB, *PtrUDFFCB;
|
|
|
|
/**************************************************************************
|
|
the following FCBFlags values are relevant. These flag
|
|
values are bit fields; therefore we can test whether
|
|
a bit position is set (1) or not set (0).
|
|
**************************************************************************/
|
|
#define UDF_FCB_VALID (0x00000002)
|
|
|
|
#define UDF_FCB_PAGE_FILE (0x00000004)
|
|
#define UDF_FCB_DIRECTORY (0x00000008)
|
|
#define UDF_FCB_ROOT_DIRECTORY (0x00000010)
|
|
#define UDF_FCB_WRITE_THROUGH (0x00000020)
|
|
#define UDF_FCB_MAPPED (0x00000040)
|
|
#define UDF_FCB_FAST_IO_READ_IN_PROGESS (0x00000080)
|
|
#define UDF_FCB_FAST_IO_WRITE_IN_PROGESS (0x00000100)
|
|
#define UDF_FCB_DELETE_ON_CLOSE (0x00000200)
|
|
#define UDF_FCB_MODIFIED (0x00000400)
|
|
#define UDF_FCB_ACCESSED (0x00000800)
|
|
#define UDF_FCB_READ_ONLY (0x00001000)
|
|
#define UDF_FCB_DELAY_CLOSE (0x00002000)
|
|
#define UDF_FCB_DELETED (0x00004000)
|
|
|
|
#define UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE (0x00008000)
|
|
#define UDF_FCB_POSTED_RENAME (0x00010000)
|
|
|
|
#define UDF_FCB_DELETE_PARENT (0x10000000)
|
|
#define UDF_FCB_NOT_FROM_ZONE (0x80000000)
|
|
|
|
/**************************************************************************
|
|
A logical volume is represented with the following structure.
|
|
This structure is allocated as part of the device extension
|
|
for a device object that this FSD will create, to represent
|
|
the mounted logical volume.
|
|
|
|
**************************************************************************/
|
|
|
|
#define _BROWSE_UDF_
|
|
|
|
// Common UDF-related definitions
|
|
#include "Include/udf_common.h"
|
|
|
|
// One for root
|
|
#define UDF_RESIDUAL_REFERENCE (2)
|
|
|
|
// input flush flags
|
|
#define UDF_FLUSH_FLAGS_BREAKABLE (0x00000001)
|
|
// see also udf_rel.h
|
|
#define UDF_FLUSH_FLAGS_LITE (0x80000000)
|
|
// output flush flags
|
|
#define UDF_FLUSH_FLAGS_INTERRUPTED (0x00000001)
|
|
|
|
#define UDF_MAX_BG_WRITERS 16
|
|
|
|
typedef struct _FILTER_DEV_EXTENSION {
|
|
UDFIdentifier NodeIdentifier;
|
|
PFILE_OBJECT fileObject;
|
|
PDEVICE_OBJECT lowerFSDeviceObject;
|
|
} FILTER_DEV_EXTENSION, *PFILTER_DEV_EXTENSION;
|
|
|
|
typedef struct _UDFFS_DEV_EXTENSION {
|
|
UDFIdentifier NodeIdentifier;
|
|
} UDFFS_DEV_EXTENSION, *PUDFFS_DEV_EXTENSION;
|
|
/**************************************************************************
|
|
The IRP context encapsulates the current request. This structure is
|
|
used in the "common" dispatch routines invoked either directly in
|
|
the context of the original requestor, or indirectly in the context
|
|
of a system worker thread.
|
|
**************************************************************************/
|
|
typedef struct _UDFIrpContext {
|
|
UDFIdentifier NodeIdentifier;
|
|
uint32 IrpContextFlags;
|
|
// copied from the IRP
|
|
uint8 MajorFunction;
|
|
// copied from the IRP
|
|
uint8 MinorFunction;
|
|
// to queue this IRP for asynchronous processing
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
// the IRP for which this context structure was created
|
|
PIRP Irp;
|
|
// the target of the request (obtained from the IRP)
|
|
PDEVICE_OBJECT TargetDeviceObject;
|
|
// if an exception occurs, we will store the code here
|
|
NTSTATUS SavedExceptionCode;
|
|
// For queued close operation we save Fcb
|
|
_UDFFileControlBlock *Fcb;
|
|
ULONG TreeLength;
|
|
PMDL PtrMdl;
|
|
PCHAR TransitionBuffer;
|
|
// support for delayed close
|
|
} UDFIrpContext, *PtrUDFIrpContext;
|
|
|
|
#define UDF_IRP_CONTEXT_CAN_BLOCK (0x00000001)
|
|
#define UDF_IRP_CONTEXT_WRITE_THROUGH (0x00000002)
|
|
#define UDF_IRP_CONTEXT_EXCEPTION (0x00000004)
|
|
#define UDF_IRP_CONTEXT_DEFERRED_WRITE (0x00000008)
|
|
#define UDF_IRP_CONTEXT_ASYNC_PROCESSING (0x00000010)
|
|
#define UDF_IRP_CONTEXT_NOT_TOP_LEVEL (0x00000020)
|
|
#define UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000040)
|
|
#define UDF_IRP_CONTEXT_FLUSH_REQUIRED (0x00000080)
|
|
#define UDF_IRP_CONTEXT_FLUSH2_REQUIRED (0x00000100)
|
|
#define UDF_IRP_CONTEXT_READ_ONLY (0x00010000)
|
|
#define UDF_IRP_CONTEXT_RES1_ACQ (0x01000000)
|
|
#define UDF_IRP_CONTEXT_RES2_ACQ (0x02000000)
|
|
#define UDF_IRP_CONTEXT_FORCED_POST (0x20000000)
|
|
#define UDF_IRP_CONTEXT_BUFFER_LOCKED (0x40000000)
|
|
#define UDF_IRP_CONTEXT_NOT_FROM_ZONE (0x80000000)
|
|
|
|
/**************************************************************************
|
|
Following structure is used to queue a request to the delayed close queue.
|
|
This structure should be the minimum block allocation size.
|
|
**************************************************************************/
|
|
typedef struct _UDFIrpContextLite {
|
|
UDFIdentifier NodeIdentifier;
|
|
// Fcb for the file object being closed.
|
|
_UDFFileControlBlock *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;
|
|
ULONG TreeLength;
|
|
uint32 IrpContextFlags;
|
|
} UDFIrpContextLite, *PtrUDFIrpContextLite;
|
|
|
|
|
|
|
|
|
|
// a default size of the number of pages of non-paged pool allocated
|
|
// for each of the zones ...
|
|
|
|
// Note that the values are absolutely arbitrary, the only information
|
|
// worth using from the values themselves is that they increase for
|
|
// larger systems (i.e. systems with more memory)
|
|
#define UDF_DEFAULT_ZONE_SIZE_SMALL_SYSTEM (0x4)
|
|
#define UDF_DEFAULT_ZONE_SIZE_MEDIUM_SYSTEM (0x8)
|
|
#define UDF_DEFAULT_ZONE_SIZE_LARGE_SYSTEM (0xc)
|
|
|
|
// another simplistic (brain dead ? :-) method used is to simply double
|
|
// the values for a "server" machine
|
|
|
|
// So, for all you guys who "modified" the registry ;-) to change the
|
|
// wkstation into a server, tough luck !
|
|
#define UDF_NTAS_MULTIPLE (0x2)
|
|
|
|
typedef struct _UDFEjectWaitContext {
|
|
PVCB Vcb;
|
|
|
|
BOOLEAN SoftEjectReq;
|
|
UCHAR Padding0[3];
|
|
|
|
KEVENT StopReq;
|
|
PKEVENT WaiterStopped;
|
|
WORK_QUEUE_ITEM EjectReqWorkQueueItem;
|
|
|
|
GET_EVENT_USER_OUT EjectReqBuffer;
|
|
UCHAR PaddingEvt[(0x40 - sizeof(GET_EVENT_USER_OUT)) & 0x0f];
|
|
|
|
GET_CAPABILITIES_USER_OUT DevCap;
|
|
UCHAR PaddingDevCap[(0x40 - sizeof(GET_CAPABILITIES_USER_OUT)) & 0x0f];
|
|
|
|
GET_LAST_ERROR_USER_OUT Error;
|
|
UCHAR PaddingError[(0x40 - sizeof(GET_LAST_ERROR_USER_OUT)) & 0x0f];
|
|
|
|
ULONG Zero;
|
|
} UDFEjectWaitContext, *PUDFEjectWaitContext;
|
|
|
|
typedef struct _UDFBGWriteContext {
|
|
PVCB Vcb;
|
|
PVOID Buffer; // Target buffer
|
|
ULONG Length;
|
|
ULONG Lba;
|
|
ULONG WrittenBytes;
|
|
BOOLEAN FreeBuffer;
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
} UDFBGWriteContext, *PUDFBGWriteContext;
|
|
|
|
// Define the file system statistics struct. Vcb->Statistics points to an
|
|
// array of these (one per processor) and they must be 64 byte aligned to
|
|
// prevent cache line tearing.
|
|
typedef struct _FILE_SYSTEM_STATISTICS {
|
|
// This contains the actual data.
|
|
FILESYSTEM_STATISTICS Common;
|
|
FAT_STATISTICS Fat;
|
|
// Pad this structure to a multiple of 64 bytes.
|
|
UCHAR Pad[64-(sizeof(FILESYSTEM_STATISTICS)+sizeof(FAT_STATISTICS))%64];
|
|
} FILE_SYSTEM_STATISTICS, *PFILE_SYSTEM_STATISTICS;
|
|
|
|
//
|
|
typedef struct _UDFFileIDCacheItem {
|
|
LONGLONG Id;
|
|
UNICODE_STRING FullName;
|
|
BOOLEAN CaseSens;
|
|
} UDFFileIDCacheItem, *PUDFFileIDCacheItem;
|
|
|
|
#define DIRTY_PAGE_LIMIT 32
|
|
|
|
#endif /* _UDF_STRUCTURES_H_ */ // has this file been included?
|
|
|