test: udfprocs.h File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# udfprocs.h File Reference

`#include <ntifs.h>`
`#include <ntddcdrm.h>`
`#include <ntddcdvd.h>`
`#include <ntdddisk.h>`
`#include "nodetype.h"`
`#include "Udf.h"`
`#include "UdfStruc.h"`
`#include "UdfData.h"`

Go to the source code of this file.

## Classes

union | _UCHAR1
union | _UCHAR2
union | _UCHAR4
union | _USHORT2

## Defines

#define | INLINE __inline
#define | BugCheckFileId (UDFS_BUG_CHECK_STRUCSUP)
#define | Dbg (UDFS_DEBUG_LEVEL_STRUCSUP)
#define | Min(a, b) ((a) < (b) ? (a) : (b))
#define | Max(a, b) ((a) > (b) ? (a) : (b))
#define | FlagMask(F, SF)
#define | BooleanFlagOn(F, SF)
#define | BooleanFlagOff(F, SF)
#define | SetFlag(Flags, SingleFlag)
#define | ClearFlag(Flags, SingleFlag)
#define | Add2Ptr(PTR, INC, CAST) ((CAST)((ULONG_PTR)(PTR) + (INC)))
#define | PtrOffset(BASE, OFFSET) ((ULONG)((ULONG)(OFFSET) - (ULONG)(BASE)))
#define | GenericTruncate(B, U)
#define | GenericAlign(B, U)
#define | GenericOffset(B, U)
#define | GenericRemainder(B, U)
#define | GenericTruncatePtr(B, U)
#define | GenericAlignPtr(B, U)
#define | GenericOffsetPtr(B, U)
#define | GenericRemainderPtr(B, U)
#define | WordAlign(B) GenericAlign((B), 2)
#define | LongAlign(B) GenericAlign((B), 4)
#define | QuadAlign(B) GenericAlign((B), 8)
#define | WordOffset(B) GenericOffset((B), 2)
#define | LongOffset(B) GenericOffset((B), 4)
#define | QuadOffset(B) GenericOffset((B), 8)
#define | WordAlignPtr(P) GenericAlignPtr((P), 2)
#define | LongAlignPtr(P) GenericAlignPtr((P), 4)
#define | QuadAlignPtr(P) GenericAlignPtr((P), 8)
#define | WordOffsetPtr(P) GenericOffsetPtr((P), 2)
#define | LongOffsetPtr(P) GenericOffsetPtr((P), 4)
#define | QuadOffsetPtr(P) GenericOffsetPtr((P), 8)
#define | SectorAlignN(SECTORSIZE, L)
#define | SectorAlign(V, L)
#define | LlSectorAlign(V, L)
#define | SectorTruncate(V, L)
#define | LlSectorTruncate(V, L)
#define | BytesFromSectors(V, L)
#define | SectorsFromBytes(V, L)
#define | LlBytesFromSectors(V, L)
#define | LlSectorsFromBytes(V, L)
#define | SectorsFromBlocks(V, B) (B)
#define | SectorSize(V) ((V)->SectorSize)
#define | SectorOffset(V, L)
#define | BlockAlignN(BLOCKSIZE, L)
#define | BlockAlign(V, L)
#define | LlBlockAlign(V, L)
#define | BlockTruncate(V, L)
#define | LlBlockTruncate(V, L)
#define | BytesFromBlocks(V, L)
#define | BlocksFromBytes(V, L)
#define | LlBytesFromBlocks(V, L)
#define | LlBlocksFromBytes(V, L)
#define | BlocksFromSectors(V, S) (S)
#define | BlockSize(V) (SectorSize(V))
#define | BlockOffset(V, L)
#define | CopyUchar1(Dst, Src)
#define | CopyUchar2(Dst, Src)
#define | SwapCopyUchar2(Dst, Src)
#define | CopyUchar4(Dst, Src)
#define | SwapCopyUchar4(Dst, Src)
#define | CopyUshort2(Dst, Src)
#define | CanFsdWait(I) IoIsOperationSynchronous(I)
#define | UdfIsFastIoPossible(F)
#define | try_leave(S) { S; leave; }
#define | UdfPagedPool PagedPool
#define | UdfNonPagedPool NonPagedPool
#define | UdfNonPagedPoolCacheAligned NonPagedPoolCacheAligned
#define | UdfUnpinView(IC, V) if (((V)->Bcb) != NULL) { CcUnpinData( ((V)->Bcb) ); ((V)->Bcb) = NULL; ((V)->View) = NULL; }
#define | UdfUnpinData(IC, B) if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }
#define | UdfMapUserBuffer(IC, UB)
#define | UdfLockUserBuffer(IC, BL)
#define | UdfAcquireUdfData(IC) ExAcquireResourceExclusive( &UdfData.DataResource, TRUE )
#define | UdfReleaseUdfData(IC) ExReleaseResource( &UdfData.DataResource )
#define | UdfAcquireVcbExclusive(IC, V, I) UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )
#define | UdfAcquireVcbShared(IC, V, I) UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )
#define | UdfReleaseVcb(IC, V) ExReleaseResource( &(V)->VcbResource )
#define | UdfAcquireAllFiles(IC, V) UdfAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )
#define | UdfReleaseAllFiles(IC, V) ExReleaseResource( &(V)->FileResource )
#define | UdfAcquireFileExclusive(IC, F) UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )
#define | UdfAcquireFileShared(IC, F) UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )
#define | UdfAcquireFileSharedStarveExclusive(IC, F) UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )
#define | UdfReleaseFile(IC, F) ExReleaseResource( (F)->Resource )
#define | UdfAcquireFcbExclusive(IC, F, I) UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )
#define | UdfAcquireFcbShared(IC, F, I) UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )
#define | UdfReleaseFcb(IC, F) ExReleaseResource( &(F)->FcbNonpaged->FcbResource )
#define | UdfLockUdfData()
#define | UdfUnlockUdfData()
#define | UdfLockVcb(IC, V)
#define | UdfUnlockVcb(IC, V)
#define | UdfLockFcb(IC, F)
#define | UdfUnlockFcb(IC, F)
#define | UdfCreateIrpContextLite(IC) ExAllocatePoolWithTag( UdfNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )
#define | UdfFreeIrpContextLite(ICL) ExFreePool( ICL )
#define | UdfAllocateIoContext()
#define | UdfFreeIoContext(IO) ExFreePool( IO )
#define | UdfIncrementCleanupCounts(IC, F)
#define | UdfDecrementCleanupCounts(IC, F)
#define | UdfIncrementReferenceCounts(IC, F, C, UC)
#define | UdfDecrementReferenceCounts(IC, F, C, UC)
#define | UdfIsRawDevice(IC, S)

## Typedefs

typedef _UCHAR1 | UCHAR1
typedef _UCHAR1 * | PUCHAR1
typedef _UCHAR2 | UCHAR2
typedef _UCHAR2 * | PUCHAR2
typedef _UCHAR4 | UCHAR4
typedef _UCHAR4 * | PUCHAR4
typedef _USHORT2 | USHORT2
typedef _USHORT2 * | PUSHORT2
typedef enum _TYPE_OF_OPEN | TYPE_OF_OPEN
typedef enum _TYPE_OF_OPEN * | PTYPE_OF_OPEN
typedef enum _TYPE_OF_ACQUIRE | TYPE_OF_ACQUIRE
typedef enum _TYPE_OF_ACQUIRE * | PTYPE_OF_ACQUIRE

## Enumerations

enum | _TYPE_OF_OPEN { UnopenedFileObject = 0, StreamFileOpen, UserVolumeOpen, UserDirectoryOpen, UserFileOpen, BeyondValidType }
enum | _TYPE_OF_ACQUIRE { AcquireExclusive, AcquireShared, AcquireSharedStarveExclusive }

## Functions

INLINE DECLSPEC_NORETURN VOID | UdfRaiseStatus (IN PIRP_CONTEXT IrpContext, IN NTSTATUS Status)
INLINE VOID | UdfNormalizeAndRaiseStatus (IN PIRP_CONTEXT IrpContext, IN NTSTATUS Status)
INLINE VOID | UdfFreePool (IN PVOID *Pool)
INLINE BOOLEAN | UdfEqualCountedString (IN PSTRING String, IN PCHAR Field)
NTSTATUS | UdfFsdDispatch (IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp)
LONG | UdfExceptionFilter (IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
NTSTATUS | UdfProcessException (IN PIRP_CONTEXT IrpContext OPTIONAL, IN PIRP Irp, IN NTSTATUS ExceptionCode)
VOID | UdfCompleteRequest (IN PIRP_CONTEXT IrpContext OPTIONAL, IN PIRP Irp OPTIONAL, IN NTSTATUS Status)
VOID | UdfSetThreadContext (IN PIRP_CONTEXT IrpContext, IN PTHREAD_CONTEXT ThreadContext)
INLINE VOID | UdfRestoreThreadContext (IN PIRP_CONTEXT IrpContext)
ULONG | UdfSerial32 (IN PCHAR Buffer, IN ULONG ByteCount)
VOID | UdfInitializeCrc16 (ULONG Polynomial)
USHORT | UdfComputeCrc16 (IN PUCHAR Buffer, IN ULONG ByteCount)
USHORT | UdfComputeCrc16Uni (PWCHAR Buffer, ULONG CharCount)
ULONG | UdfHighBit (ULONG Word)
BOOLEAN | UdfFastQueryBasicInfo (IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastIoCheckIfPossible (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastLock (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastQueryNetworkInfo (IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastQueryStdInfo (IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastUnlockSingle (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastUnlockAll (IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
BOOLEAN | UdfFastUnlockAllByKey (IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
INLINE BOOLEAN | UdfIllegalFcbAccess (IN PIRP_CONTEXT IrpContext, IN TYPE_OF_OPEN TypeOfOpen, IN ACCESS_MASK DesiredAccess)
BOOLEAN | UdfLookupAllocation (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN LONGLONG FileOffset, OUT PLONGLONG DiskOffset, OUT PULONG ByteCount)
VOID | UdfDeletePcb (IN PPCB Pcb)
NTSTATUS | UdfInitializePcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN OUT PPCB *Pcb, IN PNSR_LVOL LVD)
VOID | UdfAddToPcb (IN PPCB Pcb, IN PNSR_PART PartitionDescriptor)
NTSTATUS | UdfCompletePcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PPCB Pcb)
BOOLEAN | UdfEquivalentPcb (IN PIRP_CONTEXT IrpContext, IN PPCB Pcb1, IN PPCB Pcb2)
ULONG | UdfLookupPsnOfExtent (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len)
ULONG | UdfLookupMetaVsnOfExtent (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len, IN BOOLEAN ExactEnd)
VOID | UdfCreateInternalStream (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFCB Fcb)
VOID | UdfDeleteInternalStream (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
NTSTATUS | UdfCompleteMdl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
VOID | UdfMapMetadataView (IN PIRP_CONTEXT IrpContext, IN PMAPPED_PVIEW View, IN PVCB Vcb, IN USHORT Partition, IN ULONG Lbn, IN ULONG Length)
NTSTATUS | UdfPurgeVolume (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN DismountUnderway)
NTSTATUS | UdfPerformDevIoCtrl (IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
NTSTATUS | UdfReadSectors (IN PIRP_CONTEXT IrpContext, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN BOOLEAN ReturnError, IN OUT PVOID Buffer, IN PDEVICE_OBJECT TargetDeviceObject)
NTSTATUS | UdfNonCachedRead (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN LONGLONG StartingOffset, IN ULONG ByteCount)
NTSTATUS | UdfCreateUserMdl (IN PIRP_CONTEXT IrpContext, IN ULONG BufferLength, IN BOOLEAN RaiseOnError)
INLINE ULONG | UdfRawBufferSize (IN PVCB Vcb, IN ULONG StructureSize)
INLINE ULONG | UdfRawReadSize (IN PVCB Vcb, IN ULONG StructureSize)
INLINE ULONG | UdfRawBufferSizeN (IN ULONG SectorSize, IN ULONG StructureSize)
INLINE ULONG | UdfRawReadSizeN (IN ULONG SectorSize, IN ULONG StructureSize)
VOID | UdfInitializeDirContext (IN PIRP_CONTEXT IrpContext, IN PDIR_ENUM_CONTEXT DirContext)
VOID | UdfCleanupDirContext (IN PIRP_CONTEXT IrpContext, IN PDIR_ENUM_CONTEXT DirContext)
BOOLEAN | UdfLookupInitialDirEntry (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PDIR_ENUM_CONTEXT DirContext, IN PLONGLONG InitialOffset OPTIONAL)
BOOLEAN | UdfLookupNextDirEntry (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PDIR_ENUM_CONTEXT DirContext)
VOID | UdfUpdateDirNames (IN PIRP_CONTEXT IrpContext, IN PDIR_ENUM_CONTEXT DirContext, IN BOOLEAN IgnoreCase)
BOOLEAN | UdfFindDirEntry (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN BOOLEAN ShortName, IN PDIR_ENUM_CONTEXT DirContext)
VOID | UdfSetFileObject (IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject, IN TYPE_OF_OPEN TypeOfOpen, IN PFCB Fcb OPTIONAL, IN PCCB Ccb OPTIONAL)
TYPE_OF_OPEN | UdfDecodeFileObject (IN PFILE_OBJECT FileObject, OUT PFCB *Fcb, OUT PCCB *Ccb)
TYPE_OF_OPEN | UdfFastDecodeFileObject (IN PFILE_OBJECT FileObject, OUT PFCB *Fcb)
VOID | UdfStoreVolumeDescriptorIfPrevailing (IN OUT PNSR_VD_GENERIC *StoredVD, IN OUT PNSR_VD_GENERIC NewVD)
VOID | UdfDissectName (IN PIRP_CONTEXT IrpContext, IN OUT PUNICODE_STRING RemainingName, OUT PUNICODE_STRING FinalName)
BOOLEAN | UdfIs8dot3Name (IN PIRP_CONTEXT IrpContext, IN UNICODE_STRING FileName)
BOOLEAN | UdfCandidateShortName (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING Name)
VOID | UdfGenerate8dot3Name (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING FileName, OUT PUNICODE_STRING ShortFileName)
VOID | UdfConvertCS0DstringToUnicode (IN PIRP_CONTEXT IrpContext, IN PUCHAR Dstring, IN UCHAR Length OPTIONAL, IN UCHAR FieldLength OPTIONAL, IN OUT PUNICODE_STRING Name)
BOOLEAN | UdfCheckLegalCS0Dstring (PIRP_CONTEXT IrpContext, PUCHAR Dstring, UCHAR Length OPTIONAL, UCHAR FieldLength OPTIONAL, BOOLEAN ReturnOnError)
VOID | UdfRenderNameToLegalUnicode (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING Name, IN PUNICODE_STRING RenderedName)
BOOLEAN | UdfIsNameInExpression (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING CurrentName, IN PUNICODE_STRING SearchExpression, IN BOOLEAN Wild)
FSRTL_COMPARISON_RESULT | UdfFullCompareNames (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING NameA, IN PUNICODE_STRING NameB)
INLINE VOID | UdfUpcaseName (IN PIRP_CONTEXT IrpContext, IN PUNICODE_STRING Name, IN OUT PUNICODE_STRING UpcaseName)
INLINE USHORT | UdfCS0DstringUnicodeSize (PIRP_CONTEXT IrpContext, PCHAR Dstring, UCHAR Length)
INLINE BOOLEAN | UdfIsCharacterLegal (IN WCHAR Character)
INLINE BOOLEAN | UdfCS0DstringContainsLegalCharacters (IN PCHAR Dstring, IN ULONG Length)
NTSTATUS | UdfLockVolumeInternal (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject OPTIONAL)
NTSTATUS | UdfUnlockVolumeInternal (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject OPTIONAL)
PLCB | UdfFindPrefix (IN PIRP_CONTEXT IrpContext, IN OUT PFCB *CurrentFcb, IN OUT PUNICODE_STRING RemainingName, IN BOOLEAN IgnoreCase)
VOID | UdfInitializeLcbFromDirContext (IN PIRP_CONTEXT IrpContext, IN PLCB Lcb, IN PDIR_ENUM_CONTEXT DirContext)
PLCB | UdfInsertPrefix (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PUNICODE_STRING Name, IN BOOLEAN ShortNameMatch, IN BOOLEAN IgnoreCase, IN PFCB ParentFcb)
VOID | UdfRemovePrefix (IN PIRP_CONTEXT IrpContext, IN PLCB Lcb)
BOOLEAN | UdfAcquireResource (IN PIRP_CONTEXT IrpContext, IN PERESOURCE Resource, IN BOOLEAN IgnoreWait, IN TYPE_OF_ACQUIRE Type)
BOOLEAN | UdfNoopAcquire (IN PVOID Fcb, IN BOOLEAN Wait)
VOID | UdfNoopRelease (IN PVOID Fcb)
BOOLEAN | UdfAcquireForCache (IN PFCB Fcb, IN BOOLEAN Wait)
VOID | UdfReleaseFromCache (IN PFCB Fcb)
VOID | UdfAcquireForCreateSection (IN PFILE_OBJECT FileObject)
VOID | UdfReleaseForCreateSection (IN PFILE_OBJECT FileObject)
BOOLEAN | UdfInitializeVcb (IN PIRP_CONTEXT IrpContext, IN OUT PVCB Vcb, IN PDEVICE_OBJECT TargetDeviceObject, IN PVPB Vpb, IN PDISK_GEOMETRY DiskGeometry, IN ULONG MediaChangeCount)
VOID | UdfUpdateVcbPhase0 (IN PIRP_CONTEXT IrpContext, IN OUT PVCB Vcb)
VOID | UdfUpdateVcbPhase1 (IN PIRP_CONTEXT IrpContext, IN OUT PVCB Vcb, IN PNSR_FSD Fsd)
VOID | UdfDeleteVcb (IN PIRP_CONTEXT IrpContext, IN OUT PVCB Vcb)
PIRP_CONTEXT | UdfCreateIrpContext (IN PIRP Irp, IN BOOLEAN Wait)
VOID | UdfCleanupIrpContext (IN PIRP_CONTEXT IrpContext, IN BOOLEAN Post)
VOID | UdfInitializeStackIrpContext (OUT PIRP_CONTEXT IrpContext, IN PIRP_CONTEXT_LITE IrpContextLite)
VOID | UdfTeardownStructures (IN PIRP_CONTEXT IrpContext, IN PFCB StartingFcb, IN BOOLEAN Recursive, OUT PBOOLEAN RemovedStartingFcb)
PFCB | UdfLookupFcbTable (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN FILE_ID FileId)
PFCB | UdfGetNextFcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PVOID *RestartKey)
PFCB | UdfCreateFcb (IN PIRP_CONTEXT IrpContext, IN FILE_ID FileId, IN NODE_TYPE_CODE NodeTypeCode, OUT PBOOLEAN FcbExisted OPTIONAL)
VOID | UdfDeleteFcb (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
VOID | UdfInitializeFcbFromIcbContext (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PICB_SEARCH_CONTEXT IcbContext)
PCCB | UdfCreateCcb (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PLCB Lcb OPTIONAL, IN ULONG Flags)
VOID | UdfDeleteCcb (IN PIRP_CONTEXT IrpContext, IN PCCB Ccb)
ULONG | UdfFindInParseTable (IN PPARSE_KEYVALUE ParseTable, IN PCHAR Id, IN ULONG MaxIdLen)
BOOLEAN | UdfVerifyDescriptor (IN PIRP_CONTEXT IrpContext, IN PDESTAG Descriptor, IN USHORT Tag, IN ULONG Size, IN ULONG Lbn, IN BOOLEAN ReturnError)
VOID | UdfInitializeIcbContextFromFcb (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext, IN PFCB Fcb)
VOID | UdfInitializeIcbContext (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext, IN PVCB Vcb, IN USHORT IcbType, IN USHORT Partition, IN ULONG Lbn, IN ULONG Length)
INLINE VOID | UdfFastInitializeIcbContext (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext)
VOID | UdfLookupActiveIcb (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext)
VOID | UdfCleanupIcbContext (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext)
VOID | UdfInitializeAllocations (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PICB_SEARCH_CONTEXT IcbContext)
VOID | UdfUpdateTimestampsFromIcbContext (IN PIRP_CONTEXT IrpContext, IN PICB_SEARCH_CONTEXT IcbContext, IN PTIMESTAMP_BUNDLE Timestamps)
BOOLEAN | UdfCreateFileLock (IN PIRP_CONTEXT IrpContext OPTIONAL, IN PFCB Fcb, IN BOOLEAN RaiseOnError)
INLINE VOID | UdfConvertUdfTimeToNtTime (IN PIRP_CONTEXT IrpContext, IN PTIMESTAMP UdfTime, OUT PLARGE_INTEGER NtTime)
INLINE BOOLEAN | UdfEqualEntityId (IN PREGID RegID, IN PSTRING Id, IN OPTIONAL PSTRING Suffix)
INLINE BOOLEAN | UdfDomainIdentifierContained (IN PREGID RegID, IN PSTRING Domain, IN USHORT RevisionMin, IN USHORT RevisionMax)
INLINE BOOLEAN | UdfUdfIdentifierContained (IN PREGID RegID, IN PSTRING Type, IN USHORT RevisionMin, IN USHORT RevisionMax, IN UCHAR OSClass, IN UCHAR OSIdentifier)
BOOLEAN | UdfCheckForDismount (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN Force)
BOOLEAN | UdfDismountVcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
VOID | UdfVerifyVcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
BOOLEAN | UdfVerifyFcbOperation (IN PIRP_CONTEXT IrpContext OPTIONAL, IN PFCB Fcb)
VOID | UdfInitializeVmcb (IN PVMCB Vmcb, IN POOL_TYPE PoolType, IN ULONG MaximumLbn, IN ULONG LbSize)
VOID | UdfUninitializeVmcb (IN PVMCB Vmcb)
VOID | UdfResetVmcb (IN PVMCB Vmcb)
VOID | UdfSetMaximumLbnVmcb (IN PVMCB Vmcb, IN ULONG MaximumLbn)
BOOLEAN | UdfVmcbVbnToLbn (IN PVMCB Vmcb, IN VBN Vbn, OUT PLBN Lbn, OUT PULONG SectorCount OPTIONAL)
BOOLEAN | UdfVmcbLbnToVbn (IN PVMCB Vmcb, IN LBN Lbn, OUT PVBN Vbn, OUT PULONG SectorCount OPTIONAL)
BOOLEAN | UdfAddVmcbMapping (IN PVMCB Vmcb, IN LBN Lbn, IN ULONG SectorCount, IN BOOLEAN ExactEnd, OUT PVBN Vbn, OUT PULONG AlignedSectorCount)
VOID | UdfRemoveVmcbMapping (IN PVMCB Vmcb, IN LBN Lbn, IN ULONG SectorCount)
NTSTATUS | UdfPerformVerify (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT DeviceToVerify)
NTSTATUS | UdfFsdPostRequest (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
VOID | UdfPrePostIrp (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
VOID | UdfOplockComplete (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
INLINE BOOLEAN | UdfEqualCharspec (IN PCHARSPEC Charspec, IN PSTRING Identifier, IN UCHAR Type)
VOID | UdfFspDispatch (IN PIRP_CONTEXT IrpContext)
VOID | UdfFspClose (IN PVCB Vcb OPTIONAL)
NTSTATUS | UdfCommonCleanup (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonClose (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonCreate (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonDevControl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonDirControl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonFsControl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonLockControl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonPnp (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonQueryInfo (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonQueryVolInfo (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonRead (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfCommonSetInfo (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)

## Define Documentation

#define Add2Ptr | ( | PTR,
|  | INC,
|  | CAST |  | ) | ((CAST)((ULONG_PTR)(PTR) + (INC)))

| Definition at line 103 of file udfprocs.h.

#define BlockAlign | ( | V,
|  | L |  | ) |

Value:

    (                                                      \
        SectorAlign((V), (L))                                                       \
    )

Definition at line 244 of file udfprocs.h.

#define BlockAlignN | ( | BLOCKSIZE,
|  | L |  | ) |

Value:

    (                                             \
        SectorAlighN((BLOCKSIZE), (L))                                              \
    )

Definition at line 240 of file udfprocs.h.

#define BlockOffset | ( | V,
|  | L |  | ) |

Value:

    (                                                     \
        SectorOffset((V), (L))                                                      \
    )

Definition at line 280 of file udfprocs.h.

Referenced by UdfFindFileSetDescriptor(), UdfInitializeAllocations(), and UdfLookupMetaVsnOfExtent().

#define BlocksFromBytes | ( | V,
|  | L |  | ) |

Value:

    (                                                 \
        SectorsFromBytes((V), (L))                                                  \
    )

Definition at line 264 of file udfprocs.h.

Referenced by UdfLookupMetaVsnOfExtent(), and UdfLookupPsnOfExtent().

#define BlocksFromSectors | ( | V,
|  | S |  | ) | (S)

| Definition at line 276 of file udfprocs.h. Referenced by UdfLookupMetaVsnOfExtent(), and UdfUpdateVcbPhase0().

#define BlockSize | ( | V |  | ) | (SectorSize(V))

| Definition at line 278 of file udfprocs.h. Referenced by ExInitializeRegion(), ExInitializeZone(), ExInterlockedExtendRegion(), InitLookaside(), KeCheckForTimer(), UdfFindFileSetDescriptor(), UdfGetNextAllocationPostProcessing(), UdfInitializeAllocations(), UdfInitializeFcbFromIcbContext(), UdfInitializeIcbContextFromFcb(), UdfLookupActiveIcbInExtent(), UdfLookupDirEntryPostProcessing(), UdfLookupPsnOfExtent(), UdfQueryFsSizeInfo(), and UdfUpdateVcbPhase0().

#define BlockTruncate | ( | V,
|  | L |  | ) |

Value:

    (                                                   \
        SectorTruncate((V), (L))                                                    \
    )

Definition at line 252 of file udfprocs.h.

#define BooleanFlagOff | ( | F,
|  | SF |  | ) |

Value:

    (          \
        (BOOLEAN)(FlagOn(F, SF)) == 0)      \
    )

Definition at line 76 of file udfprocs.h.

#define BooleanFlagOn | ( | F,
|  | SF |  | ) |

Value:

    (           \
        (BOOLEAN)(FlagOn(F, SF) != 0)       \
    )

Definition at line 72 of file udfprocs.h.

#define BugCheckFileId (UDFS_BUG_CHECK_STRUCSUP)

| Definition at line 44 of file udfprocs.h.

#define BytesFromBlocks | ( | V,
|  | L |  | ) |

Value:

    (                                                 \
        BytesFromSectors((V), (L))                                                  \
    )

Definition at line 260 of file udfprocs.h.

#define BytesFromSectors | ( | V,
|  | L |  | ) |

Value:

    (                                                \
        ((ULONG) (L)) << ((V)->SectorShift)                                         \
    )

Definition at line 212 of file udfprocs.h.

#define CanFsdWait | ( | I |  | ) | IoIsOperationSynchronous(I)

| Definition at line 371 of file udfprocs.h. Referenced by UdfFsdDispatch().

#define ClearFlag | ( | Flags,
|  | SingleFlag |  | ) |

Value:

    (   \
        (Flags) &= ~(SingleFlag)            \
    )

Definition at line 84 of file udfprocs.h.

#define CopyUchar1 | ( | Dst,
|  | Src |  | ) |

Value:

    {                           \
        *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src));  \
        }

Definition at line 313 of file udfprocs.h.

#define CopyUchar2 | ( | Dst,
|  | Src |  | ) |

Value:

    {                           \
        *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src));  \
        }

Definition at line 321 of file udfprocs.h.

#define CopyUchar4 | ( | Dst,
|  | Src |  | ) |

Value:

    {                           \
        *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src));  \
        }

Definition at line 339 of file udfprocs.h.

#define CopyUshort2 | ( | Dst,
|  | Src |  | ) |

Value:

    {                          \
        *((USHORT2 *)(Dst)) = *((UNALIGNED USHORT2 *)(Src));\
        }

Definition at line 360 of file udfprocs.h.

#define Dbg (UDFS_DEBUG_LEVEL_STRUCSUP)

| Definition at line 50 of file udfprocs.h.

#define FlagMask | ( | F,
|  | SF |  | ) |

Value:

    (                \
        ((F) & (SF))                        \
    )

Definition at line 68 of file udfprocs.h.

Referenced by SepAdtOpenObjectAuditAlarm().

#define GenericAlign | ( | B,
|  | U |  | ) |

Value:

    (                                                \
        GenericTruncate((B) + (U) - 1, U)                                       \
    )

Definition at line 118 of file udfprocs.h.

#define GenericAlignPtr | ( | B,
|  | U |  | ) |

Value:

    (                                             \
        GenericTruncatePtr((B) + (U) - 1, (U))                                  \
    )

Definition at line 135 of file udfprocs.h.

#define GenericOffset | ( | B,
|  | U |  | ) |

Value:

    (                                               \
        (B) & ((U) - 1)                                                         \
    )

Definition at line 122 of file udfprocs.h.

Referenced by UdfLookupInitialDirEntry().

#define GenericOffsetPtr | ( | B,
|  | U |  | ) |

Value:

    (                                            \
        (ULONG)(((ULONG_PTR)(B)) & ((U) - 1))                                   \
    )

Definition at line 139 of file udfprocs.h.

#define GenericRemainder | ( | B,
|  | U |  | ) |

Value:

    (                                            \
        GenericOffset( (U) - GenericOffset((B), (U)), (U) )                     \
    )

Definition at line 126 of file udfprocs.h.

#define GenericRemainderPtr | ( | B,
|  | U |  | ) |

Value:

    (                                         \
        (ULONG)GenericOffset( (U) - GenericOffsetPtr((B), (U)), (U) )           \
    )

Definition at line 143 of file udfprocs.h.

Referenced by UdfLookupDirEntryPostProcessing().

#define GenericTruncate | ( | B,
|  | U |  | ) |

Value:

    (                                             \
        (B) & ~((U) - 1)                                                        \
    )

Definition at line 114 of file udfprocs.h.

Referenced by UdfLookupInitialDirEntry().

#define GenericTruncatePtr | ( | B,
|  | U |  | ) |

Value:

    (                                          \
        (PVOID)(((ULONG_PTR)(B)) & ~((U) - 1))                                  \
    )

Definition at line 131 of file udfprocs.h.

Referenced by UdfLookupDirEntryPostProcessing().

#define INLINE __inline

| Definition at line 32 of file udfprocs.h.

#define LlBlockAlign | ( | V,
|  | L |  | ) |

Value:

    (                                                    \
        LlSectorAlign((V), (L))                                                     \
    )

Definition at line 248 of file udfprocs.h.

Referenced by UdfInitializeFcbFromIcbContext(), and UdfQueryDirectory().

#define LlBlocksFromBytes | ( | V,
|  | L |  | ) |

Value:

    (                                               \
        LlSectorsFromBytes((V), (L))                                                \
    )

Definition at line 272 of file udfprocs.h.

Referenced by UdfQueryFsSizeInfo().

#define LlBlockTruncate | ( | V,
|  | L |  | ) |

Value:

    (                                                 \
        LlSectorTruncate((V), (L))                                                  \
    )

Definition at line 256 of file udfprocs.h.

#define LlBytesFromBlocks | ( | V,
|  | L |  | ) |

Value:

    (                                               \
        LlBytesFromSectors((V), (L))                                                \
    )

Definition at line 268 of file udfprocs.h.

Referenced by UdfFindFileSetDescriptor().

#define LlBytesFromSectors | ( | V,
|  | L |  | ) |

Value:

    (                                              \
        Int64ShllMod32( (ULONGLONG)(L), ((V)->SectorShift) )                        \
    )

Definition at line 220 of file udfprocs.h.

Referenced by UdfDvdReadStructure(), UdfDvdTransferKey(), UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfLookupAllocation(), UdfLookupMetaVsnOfExtent(), UdfMapMetadataView(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define LlSectorAlign | ( | V,
|  | L |  | ) |

Value:

    (                                                   \
        ((((LONGLONG)(L)) + (((V)->SectorSize) - 1)) & ~(((LONGLONG)(V)->SectorSize) - 1)) \
    )

Definition at line 200 of file udfprocs.h.

Referenced by UdfUpdateVcbPhase0().

#define LlSectorsFromBytes | ( | V,
|  | L |  | ) |

Value:

    (                                              \
        Int64ShrlMod32( (ULONGLONG)(L), ((V)->SectorShift) )                        \
    )

Definition at line 224 of file udfprocs.h.

Referenced by UdfDvdReadStructure(), UdfDvdTransferKey(), UdfInitializeAllocations(), UdfLookupAllocation(), and UdfReadSectors().

#define LlSectorTruncate | ( | V,
|  | L |  | ) |

Value:

    (                                                \
        ((LONGLONG)(L)) & ~(((LONGLONG)(V)->SectorSize) - 1)                        \
    )

Definition at line 208 of file udfprocs.h.

Referenced by UdfPrepareBuffers().

#define LongAlign | ( | B |  | ) | GenericAlign((B), 4)

| Definition at line 153 of file udfprocs.h.

#define LongAlignPtr | ( | P |  | ) | GenericAlignPtr((P), 4)

| Definition at line 167 of file udfprocs.h. Referenced by NtAdjustGroupsToken(), and SeQuerySecurityDescriptorInfo().

#define LongOffset | ( | B |  | ) | GenericOffset((B), 4)

| Definition at line 160 of file udfprocs.h. Referenced by UdfInitializeFcbFromIcbContext(), and UdfUpdateVcbPhase0().

#define LongOffsetPtr | ( | P |  | ) | GenericOffsetPtr((P), 4)

| Definition at line 174 of file udfprocs.h. Referenced by UdfInitializeAllocationContext(), UdfLookupEa(), and UdfSetThreadContext().

#define Max | ( | a,
|  | b |  | ) | ((a) > (b) ? (a) : (b))

| Definition at line 62 of file udfprocs.h. Referenced by UdfInitializeEnumeration(), and UdfUpdateDirNames().

#define Min | ( | a,
|  | b |  | ) | ((a) < (b) ? (a) : (b))

| Definition at line 61 of file udfprocs.h. Referenced by UdfConvertCS0DstringToUnicode(), and UdfLoadSparingTables().

#define PtrOffset | ( | BASE,
|  | OFFSET |  | ) | ((ULONG)((ULONG)(OFFSET) - (ULONG)(BASE)))

| Definition at line 105 of file udfprocs.h.

#define QuadAlign | ( | B |  | ) | GenericAlign((B), 8)

| Definition at line 155 of file udfprocs.h.

#define QuadAlignPtr | ( | P |  | ) | GenericAlignPtr((P), 8)

| Definition at line 169 of file udfprocs.h.

#define QuadOffset | ( | B |  | ) | GenericOffset((B), 8)

| Definition at line 162 of file udfprocs.h.

#define QuadOffsetPtr | ( | P |  | ) | GenericOffsetPtr((P), 8)

| Definition at line 176 of file udfprocs.h.

#define SectorAlign | ( | V,
|  | L |  | ) |

Value:

    (                                                     \
        ((((ULONG)(L)) + (((V)->SectorSize) - 1)) & ~(((V)->SectorSize) - 1))       \
    )

Definition at line 196 of file udfprocs.h.

#define SectorAlignN | ( | SECTORSIZE,
|  | L |  | ) |

Value:

    (                                           \
        ((((ULONG)(L)) + ((SECTORSIZE) - 1)) & ~((SECTORSIZE) - 1))                 \
    )

Definition at line 192 of file udfprocs.h.

#define SectorOffset | ( | V,
|  | L |  | ) |

Value:

    (                                                    \
        ((ULONG) (L)) & (((V)->SectorSize) - 1)                                     \
    )

Definition at line 232 of file udfprocs.h.

Referenced by MiCreateImageFileMap(), UdfCommonRead(), UdfLookupAllocation(), and UdfPrepareBuffers().

#define SectorsFromBlocks | ( | V,
|  | B |  | ) | (B)

| Definition at line 228 of file udfprocs.h. Referenced by UdfLoadSparingTables(), and UdfLookupPsnOfExtent().

#define SectorsFromBytes | ( | V,
|  | L |  | ) |

Value:

    (                                                \
        ((ULONG) (L)) >> ((V)->SectorShift)                                         \
    )

Definition at line 216 of file udfprocs.h.

#define SectorSize | ( | V |  | ) | ((V)->SectorSize)

| Definition at line 230 of file udfprocs.h. Referenced by FmtFillFormatBuffer(), FmtIsFatPartition(), FmtVerifySectors(), GetGeometry(), IsUdfsVolume(), LowGetDriveGeometry(), LowGetPartitionGeometry(), LowReadSectors(), LowWriteSectors(), UdfFindVolumeDescriptors(), UdfInitializeVmcb(), UdfLoadSparingTables(), UdfPrepareBuffers(), UdfQueryFsSizeInfo(), UdfRawBufferSizeN(), UdfRawReadSizeN(), UdfReadSectors(), UdfRecognizeVolume(), UdfUpdateVcbPhase0(), xHalExamineMBR(), xHalIoClearPartitionTable(), xHalIoReadPartitionTable(), xHalIoSetPartitionInformation(), xHalIoWritePartitionTable(), and ZapSector().

#define SectorTruncate | ( | V,
|  | L |  | ) |

Value:

    (                                                  \
        ((ULONG)(L)) & ~(((V)->SectorSize) - 1)                                     \
    )

Definition at line 204 of file udfprocs.h.

Referenced by UdfPrepareBuffers().

#define SetFlag | ( | Flags,
|  | SingleFlag |  | ) |

Value:

    (     \
        (Flags) |= (SingleFlag)             \
    )

Definition at line 80 of file udfprocs.h.

#define SwapCopyUchar2 | ( | Dst,
|  | Src |  | ) |

Value:

    {                                       \
        *((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 1);    \
        *((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src));    \
    }

Definition at line 330 of file udfprocs.h.

Referenced by UdfConvertCS0DstringToUnicode(), and UdfCS0DstringContainsLegalCharacters().

#define SwapCopyUchar4 | ( | Dst,
|  | Src |  | ) |

Value:

    {                                        \
        *((UNALIGNED UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src) + 3);     \
        *((UNALIGNED UCHAR1 *)(Dst) + 1) = *((UNALIGNED UCHAR1 *)(Src) + 2); \
        *((UNALIGNED UCHAR1 *)(Dst) + 2) = *((UNALIGNED UCHAR1 *)(Src) + 1); \
        *((UNALIGNED UCHAR1 *)(Dst) + 3) = *((UNALIGNED UCHAR1 *)(Src));     \
    }

Definition at line 348 of file udfprocs.h.

Referenced by UdfDetermineVolumeBounding(), and UdfUpdateVolumeSerialNumber().

#define try_leave | ( | S |  | ) | { S; leave; }

| Definition at line 436 of file udfprocs.h. Referenced by UdfAddVmcbMapping(), UdfCommonCreate(), UdfCommonRead(), UdfCommonSetInfo(), UdfDetermineVolumeBounding(), UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfLookupDirEntryPostProcessing(), UdfLookupMetaVsnOfExtent(), UdfMountVolume(), UdfNonCachedRead(), UdfOpenObjectByFileId(), UdfQueryAlternateNameInfo(), UdfQueryDirectory(), UdfVerifyVolume(), and UdfVmcbVbnToLbn().

#define UdfAcquireAllFiles | ( | IC,
|  | V |  | ) | UdfAcquireResource( (IC), &(V)->FileResource, FALSE, AcquireExclusive )

| Definition at line 1524 of file udfprocs.h. Referenced by UdfPurgeVolume().

#define UdfAcquireFcbExclusive | ( | IC,
|  | F,
|  | I |  | ) | UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireExclusive )

| Definition at line 1542 of file udfprocs.h. Referenced by UdfCommonCleanup(), UdfCommonClosePrivate(), UdfCommonCreate(), UdfFindPrefix(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfOplockRequest(), and UdfTeardownStructures().

#define UdfAcquireFcbShared | ( | IC,
|  | F,
|  | I |  | ) | UdfAcquireResource( (IC), &(F)->FcbNonpaged->FcbResource, (I), AcquireShared )

| Definition at line 1545 of file udfprocs.h. Referenced by UdfOplockRequest().

#define UdfAcquireFileExclusive | ( | IC,
|  | F |  | ) | UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireExclusive )

| Definition at line 1530 of file udfprocs.h.

#define UdfAcquireFileShared | ( | IC,
|  | F |  | ) | UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireShared )

| Definition at line 1533 of file udfprocs.h. Referenced by UdfCommonQueryInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfQueryAlternateNameInfo(), and UdfQueryDirectory().

#define UdfAcquireFileSharedStarveExclusive | ( | IC,
|  | F |  | ) | UdfAcquireResource( (IC), (F)->Resource, FALSE, AcquireSharedStarveExclusive )

| Definition at line 1536 of file udfprocs.h. Referenced by UdfCommonRead().

#define UdfAcquireUdfData | ( | IC |  | ) | ExAcquireResourceExclusive( &UdfData.DataResource, TRUE )

| Definition at line 1509 of file udfprocs.h. Referenced by UdfCommonClose(), UdfFspClose(), UdfInvalidateVolumes(), UdfMountVolume(), UdfPerformVerify(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), and UdfVerifyVolume().

#define UdfAcquireVcbExclusive | ( | IC,
|  | V,
|  | I |  | ) | UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireExclusive )

| Definition at line 1515 of file udfprocs.h. Referenced by UdfCheckForDismount(), UdfCommonCleanup(), UdfCommonCreate(), UdfDismountVolume(), UdfLockVolume(), UdfLockVolumeInternal(), UdfMountVolume(), UdfPnpCancelRemove(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfUnlockVolume(), and UdfVerifyVolume().

#define UdfAcquireVcbShared | ( | IC,
|  | V,
|  | I |  | ) | UdfAcquireResource( (IC), &(V)->VcbResource, (I), AcquireShared )

| Definition at line 1518 of file udfprocs.h. Referenced by UdfCommonClosePrivate(), UdfCommonCreate(), UdfCommonQueryVolInfo(), UdfFspClose(), and UdfNotifyChangeDirectory().

#define UdfAllocateIoContext | (

)

Value:

    FsRtlAllocatePoolWithTag( UdfNonPagedPool,           \
                                  sizeof( UDF_IO_CONTEXT ),  \
                                  TAG_IO_CONTEXT )

Definition at line 1701 of file udfprocs.h.

Referenced by UdfCommonRead().

#define UdfCreateIrpContextLite | ( | IC |  | ) | ExAllocatePoolWithTag( UdfNonPagedPool, sizeof( IRP_CONTEXT_LITE ), TAG_IRP_CONTEXT_LITE )

| Definition at line 1684 of file udfprocs.h. Referenced by UdfQueueClose().

#define UdfDecrementCleanupCounts | ( | IC,
|  | F |  | ) |

Value:

    {        \
        ASSERT_LOCKED_VCB( (F)->Vcb );              \
        (F)->FcbCleanup -= 1;                       \
        (F)->Vcb->VcbCleanup -= 1;                  \
    }

Definition at line 1756 of file udfprocs.h.

Referenced by UdfCommonCleanup().

#define UdfDecrementReferenceCounts | ( | IC,
|  | F,
|  | C,
|  | UC |  | ) |

Value:

    { \
        ASSERT_LOCKED_VCB( (F)->Vcb );              \
        (F)->FcbReference -= (C);                   \
        (F)->FcbUserReference -= (UC);              \
        (F)->Vcb->VcbReference -= (C);              \
        (F)->Vcb->VcbUserReference -= (UC);         \
    }

Definition at line 1770 of file udfprocs.h.

Referenced by UdfCommonClosePrivate(), UdfCreateInternalStream(), and UdfTeardownStructures().

#define UdfFreeIoContext | ( | IO |  | ) | ExFreePool( IO )

| Definition at line 1706 of file udfprocs.h. Referenced by UdfCleanupIrpContext(), UdfMultiAsyncCompletionRoutine(), and UdfSingleAsyncCompletionRoutine().

#define UdfFreeIrpContextLite | ( | ICL |  | ) | ExFreePool( ICL )

| Definition at line 1687 of file udfprocs.h. Referenced by UdfFspClose().

#define UdfIncrementCleanupCounts | ( | IC,
|  | F |  | ) |

Value:

    {        \
        ASSERT_LOCKED_VCB( (F)->Vcb );              \
        (F)->FcbCleanup += 1;                       \
        (F)->Vcb->VcbCleanup += 1;                  \
    }

Definition at line 1750 of file udfprocs.h.

Referenced by UdfCompleteFcbOpen().

#define UdfIncrementReferenceCounts | ( | IC,
|  | F,
|  | C,
|  | UC |  | ) |

Value:

    { \
        ASSERT_LOCKED_VCB( (F)->Vcb );              \
        (F)->FcbReference += (C);                   \
        (F)->FcbUserReference += (UC);              \
        (F)->Vcb->VcbReference += (C);              \
        (F)->Vcb->VcbUserReference += (UC);         \
    }

Definition at line 1762 of file udfprocs.h.

Referenced by UdfCompleteFcbOpen(), UdfCreateInternalStream(), UdfOpenObjectFromDirContext(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define UdfIsFastIoPossible | ( | F |  | ) |

Value:

    ((BOOLEAN)                                           \
        ((((F)->Vcb->VcbCondition != VcbMounted ) ||                                    \
          !FsRtlOplockIsFastIoPossible( &(F)->Oplock )) ?                               \
                                                                                        \
         FastIoIsNotPossible :                                                          \
                                                                                        \
         ((((F)->FileLock != NULL) && FsRtlAreThereCurrentFileLocks( (F)->FileLock )) ? \
                                                                                        \
            FastIoIsQuestionable :                                                      \
                                                                                        \
            FastIoIsPossible))                                                          \
    )

Definition at line 385 of file udfprocs.h.

Referenced by UdfCommonCleanup(), UdfCommonLockControl(), UdfCompleteFcbOpen(), UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), and UdfOplockRequest().

#define UdfIsRawDevice | ( | IC,
|  | S |  | ) |

Value:

    (           \
        ((S) == STATUS_DEVICE_NOT_READY) ||  \
        ((S) == STATUS_NO_MEDIA_IN_DEVICE)   \
    )

Definition at line 2115 of file udfprocs.h.

Referenced by UdfRecognizeVolume(), and UdfVerifyVcb().

#define UdfLockFcb | ( | IC,
|  | F |  | ) |

Value:

    {                                                              \
        PVOID _CurrentThread = PsGetCurrentThread();                                        \
        if (_CurrentThread != (F)->FcbLockThread) {                                         \
            ExAcquireFastMutex( &(F)->FcbNonpaged->FcbMutex );                              \
            ASSERT( (F)->FcbLockCount == 0 );                                               \
            (F)->FcbLockThread = _CurrentThread;                                            \
        }                                                                                   \
        (F)->FcbLockCount += 1;                                                             \
    }

Definition at line 1567 of file udfprocs.h.

Referenced by UdfCommonCleanup(), UdfCommonLockControl(), UdfCommonSetInfo(), UdfCompleteFcbOpen(), UdfCreateFileLock(), UdfCreateInternalStream(), UdfDeleteInternalStream(), UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), UdfInitializeEnumeration(), UdfInitializeFcbFromIcbContext(), UdfLookupMetaVsnOfExtent(), UdfOplockRequest(), UdfQueryDirectory(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define UdfLockUdfData | (

)

Value:

    ExAcquireFastMutex( &UdfData.UdfDataMutex );                                        \
        UdfData.UdfDataLockThread = PsGetCurrentThread()

Definition at line 1551 of file udfprocs.h.

Referenced by UdfQueueClose(), and UdfRemoveClose().

#define UdfLockUserBuffer | ( | IC,
|  | BL |  | ) |

Value:

    {                   \
        if ((IC)->Irp->MdlAddress == NULL) {             \
            (VOID) UdfCreateUserMdl( (IC), (BL), TRUE ); \
        }                                                \
    }

Definition at line 911 of file udfprocs.h.

Referenced by UdfPrePostIrp().

#define UdfLockVcb | ( | IC,
|  | V |  | ) |

Value:

    ExAcquireFastMutex( &(V)->VcbMutex );                                               \
        (V)->VcbLockThread = PsGetCurrentThread()

Definition at line 1559 of file udfprocs.h.

Referenced by UdfCheckForDismount(), UdfCommonCleanup(), UdfCommonClosePrivate(), UdfCompleteFcbOpen(), UdfCreateInternalStream(), UdfDismountVcb(), UdfFindPrefix(), UdfInvalidateVolumes(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfPurgeVolume(), UdfTeardownStructures(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define UdfMapUserBuffer | ( | IC,
|  | UB |  | ) |

Value:

    {                                                   \
                *(UB) = ((PVOID) (((IC)->Irp->MdlAddress == NULL) ?                     \
                                 (IC)->Irp->UserBuffer :                                \
                                 MmGetSystemAddressForMdlSafe( (IC)->Irp->MdlAddress, NormalPagePriority )));   \
                if (NULL == *(UB))  {                                                    \
                    UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES);         \
                }                                                                       \
            }

Definition at line 902 of file udfprocs.h.

Referenced by UdfCommonRead(), UdfNonCachedRead(), and UdfQueryDirectory().

#define UdfNonPagedPool NonPagedPool

| Definition at line 444 of file udfprocs.h. Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfPrepareBuffers(), UdfRecognizeVolume(), and UdfStoreVolumeDescriptorIfPrevailing().

#define UdfNonPagedPoolCacheAligned NonPagedPoolCacheAligned

| Definition at line 445 of file udfprocs.h.

#define UdfPagedPool PagedPool

| Definition at line 443 of file udfprocs.h. Referenced by UdfAllocateTable(), UdfCreatePcb(), UdfDetermineVolumeBounding(), UdfEnumerateIndex(), UdfFindDirEntry(), UdfInitializeCrc16(), UdfInitializeEnumeration(), UdfInitializeFcbMcb(), UdfInsertPrefix(), UdfLookupDirEntryPostProcessing(), UdfNormalizeFileNames(), UdfUpdateDirNames(), and UdfUpdateVcbPhase0().

#define UdfReleaseAllFiles | ( | IC,
|  | V |  | ) | ExReleaseResource( &(V)->FileResource )

| Definition at line 1527 of file udfprocs.h. Referenced by UdfPurgeVolume().

#define UdfReleaseFcb | ( | IC,
|  | F |  | ) | ExReleaseResource( &(F)->FcbNonpaged->FcbResource )

| Definition at line 1548 of file udfprocs.h. Referenced by UdfCommonCleanup(), UdfCommonClosePrivate(), UdfCommonCreate(), UdfFindPrefix(), UdfOpenObjectFromDirContext(), UdfOplockComplete(), UdfOplockRequest(), UdfPrePostIrp(), and UdfTeardownStructures().

#define UdfReleaseFile | ( | IC,
|  | F |  | ) | ExReleaseResource( (F)->Resource )

| Definition at line 1539 of file udfprocs.h. Referenced by UdfCommonQueryInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfQueryAlternateNameInfo(), and UdfQueryDirectory().

#define UdfReleaseUdfData | ( | IC |  | ) | ExReleaseResource( &UdfData.DataResource )

| Definition at line 1512 of file udfprocs.h. Referenced by UdfCommonClose(), UdfFspClose(), UdfInvalidateVolumes(), UdfMountVolume(), UdfPerformVerify(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), and UdfVerifyVolume().

#define UdfReleaseVcb | ( | IC,
|  | V |  | ) | ExReleaseResource( &(V)->VcbResource )

| Definition at line 1521 of file udfprocs.h. Referenced by UdfCheckForDismount(), UdfCommonCleanup(), UdfCommonClosePrivate(), UdfCommonCreate(), UdfCommonQueryVolInfo(), UdfDismountVolume(), UdfFspClose(), UdfLockVolume(), UdfLockVolumeInternal(), UdfMountVolume(), UdfNotifyChangeDirectory(), UdfPnpCancelRemove(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfUnlockVolume(), and UdfVerifyVolume().

#define UdfUnlockFcb | ( | IC,
|  | F |  | ) |

Value:

    {                                                            \
        (F)->FcbLockCount -= 1;                                                             \
        if ((F)->FcbLockCount == 0) {                                                       \
            (F)->FcbLockThread = NULL;                                                      \
            ExReleaseFastMutex( &(F)->FcbNonpaged->FcbMutex );                              \
        }                                                                                   \
    }

Definition at line 1577 of file udfprocs.h.

Referenced by UdfCommonCleanup(), UdfCommonLockControl(), UdfCommonSetInfo(), UdfCompleteFcbOpen(), UdfCreateFileLock(), UdfCreateInternalStream(), UdfDeleteInternalStream(), UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), UdfInitializeEnumeration(), UdfInitializeFcbFromIcbContext(), UdfLookupMetaVsnOfExtent(), UdfOplockRequest(), UdfQueryDirectory(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define UdfUnlockUdfData | (

)

Value:

    UdfData.UdfDataLockThread = NULL;                                                   \
        ExReleaseFastMutex( &UdfData.UdfDataMutex )

Definition at line 1555 of file udfprocs.h.

Referenced by UdfQueueClose(), and UdfRemoveClose().

#define UdfUnlockVcb | ( | IC,
|  | V |  | ) |

Value:

    (V)->VcbLockThread = NULL;                                                          \
        ExReleaseFastMutex( &(V)->VcbMutex )

Definition at line 1563 of file udfprocs.h.

Referenced by UdfCheckForDismount(), UdfCommonCleanup(), UdfCommonClosePrivate(), UdfCompleteFcbOpen(), UdfCreateInternalStream(), UdfDismountVcb(), UdfFindPrefix(), UdfInvalidateVolumes(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfPurgeVolume(), UdfTeardownStructures(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

#define UdfUnpinData | ( | IC,
|  | B |  | ) | if (*(B) != NULL) { CcUnpinData( *(B) ); *(B) = NULL; }

| Definition at line 838 of file udfprocs.h. Referenced by UdfCleanupDirContext(), UdfLookupDirEntryPostProcessing(), UdfLookupInitialDirEntry(), UdfLookupPsnOfExtent(), and UdfUpdateVcbPhase0().

#define UdfUnpinView | ( | IC,
|  | V |  | ) | if (((V)->Bcb) != NULL) { CcUnpinData( ((V)->Bcb) ); ((V)->Bcb) = NULL; ((V)->View) = NULL; }

| Definition at line 828 of file udfprocs.h. Referenced by UdfCleanupIcbContext(), UdfLookupActiveIcb(), and UdfMapMetadataView().

#define WordAlign | ( | B |  | ) | GenericAlign((B), 2)

| Definition at line 151 of file udfprocs.h.

#define WordAlignPtr | ( | P |  | ) | GenericAlignPtr((P), 2)

| Definition at line 165 of file udfprocs.h.

#define WordOffset | ( | B |  | ) | GenericOffset((B), 2)

| Definition at line 158 of file udfprocs.h.

#define WordOffsetPtr | ( | P |  | ) | GenericOffsetPtr((P), 2)

| Definition at line 172 of file udfprocs.h.

## Typedef Documentation

typedef enum _TYPE_OF_ACQUIRE * PTYPE_OF_ACQUIRE

typedef enum _TYPE_OF_OPEN * PTYPE_OF_OPEN

typedef union _UCHAR1 * PUCHAR1

typedef union _UCHAR2 * PUCHAR2

typedef union _UCHAR4 * PUCHAR4

typedef union _USHORT2 * PUSHORT2

typedef enum _TYPE_OF_ACQUIRE TYPE_OF_ACQUIRE

| Referenced by UdfAcquireResource().

typedef enum _TYPE_OF_OPEN TYPE_OF_OPEN

| Referenced by UdfCommonCleanup(), UdfCommonClose(), UdfCommonCreate(), UdfCommonDevControl(), UdfCommonLockControl(), UdfCommonQueryInfo(), UdfCommonQueryVolInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfDecodeFileObject(), UdfFastDecodeFileObject(), UdfFastLock(), UdfFastQueryBasicInfo(), UdfFastQueryNetworkInfo(), UdfFastQueryStdInfo(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), UdfIsVolumeDirty(), UdfOpenObjectByFileId(), and UdfOpenObjectFromDirContext().

typedef union _UCHAR1 UCHAR1

typedef union _UCHAR2 UCHAR2

typedef union _UCHAR4 UCHAR4

typedef union _USHORT2 USHORT2

## Enumeration Type Documentation

enum _TYPE_OF_ACQUIRE

Enumeration values:

  AcquireExclusive |
  AcquireShared |
  AcquireSharedStarveExclusive |

Definition at line 1381 of file udfprocs.h.

    01381                               {
    01382
    01383     AcquireExclusive,
    01384     AcquireShared,
    01385     AcquireSharedStarveExclusive
    01386
    01387 } TYPE_OF_ACQUIRE, *PTYPE_OF_ACQUIRE;

enum _TYPE_OF_OPEN

Enumeration values:

  UnopenedFileObject |
  StreamFileOpen |
  UserVolumeOpen |
  UserDirectoryOpen |
  UserFileOpen |
  BeyondValidType |

Definition at line 487 of file udfprocs.h.

    00487                            {
    00488
    00489     UnopenedFileObject = 0,
    00490     StreamFileOpen,
    00491     UserVolumeOpen,
    00492     UserDirectoryOpen,
    00493     UserFileOpen,
    00494     BeyondValidType
    00495
    00496 } TYPE_OF_OPEN, *PTYPE_OF_OPEN;

## Function Documentation

BOOLEAN UdfAcquireForCache | ( | IN PFCB | Fcb,
|  | IN BOOLEAN | Wait
| ) |

Definition at line 136 of file resrcsup.c.

References ASSERT, ExAcquireResourceShared, FSRTL_CACHE_TOP_LEVEL_IRP, IoGetTopLevelIrp(), IoSetTopLevelIrp(), NULL, and PAGED_CODE.

Referenced by UdfInitializeGlobalData().

    00143                    :
    00144
    00145     The address of this routine is specified when creating a CacheMap for
    00146     a file.  It is subsequently called by the Lazy Writer for synchronization.
    00147
    00148 Arguments:
    00149
    00150     Fcb -  The pointer supplied as context to the cache initialization
    00151            routine.
    00152
    00153     Wait - TRUE if the caller is willing to block.
    00154
    00155 Return Value:
    00156
    00157     None
    00158
    00159 --*/
    00160
    00161 {
    00162     PAGED_CODE();
    00163
    00164     ASSERT(IoGetTopLevelIrp() == NULL);
    00165     IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
    00166
    00167     return ExAcquireResourceShared( Fcb->Resource, Wait );
    00168 }

VOID UdfAcquireForCreateSection | ( | IN PFILE_OBJECT | FileObject | ) |

Definition at line 267 of file resrcsup.c.

References ExAcquireResourceExclusive, PAGED_CODE, and TRUE.

Referenced by UdfInitializeGlobalData().

    00273                    :
    00274
    00275     This is the callback routine for MM to use to acquire the file exclusively.
    00276
    00277 Arguments:
    00278
    00279     FileObject - File object for a Udffs stream.
    00280
    00281 Return Value:
    00282
    00283     None
    00284
    00285 --*/
    00286
    00287 {
    00288     PAGED_CODE();
    00289
    00290     //
    00291     //  Get the file resource exclusively.
    00292     //
    00293
    00294     ExAcquireResourceExclusive( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource,
    00295                                 TRUE );
    00296
    00297     return;
    00298 }

BOOLEAN UdfAcquireResource | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PERESOURCE | Resource,
|  | IN BOOLEAN | IgnoreWait,
|  | IN TYPE_OF_ACQUIRE | Type
| ) |

Definition at line 47 of file resrcsup.c.

References AcquireExclusive, AcquireShared, AcquireSharedStarveExclusive, ASSERT, ExAcquireResourceExclusive, ExAcquireResourceShared, ExAcquireSharedStarveExclusive(), FALSE, FlagOn, IRP_CONTEXT_FLAG_WAIT, PAGED_CODE, Resource, TRUE, TYPE_OF_ACQUIRE, and UdfRaiseStatus().

    00056                    :
    00057
    00058     This is the single routine used to acquire file system resources.  It
    00059     looks at the IgnoreWait flag to determine whether to try to acquire the
    00060     resource without waiting.  Returning TRUE/FALSE to indicate success or
    00061     failure.  Otherwise it is driven by the WAIT flag in the IrpContext and
    00062     will raise CANT_WAIT on a failure.
    00063
    00064 Arguments:
    00065
    00066     Resource - This is the resource to try and acquire.
    00067
    00068     IgnoreWait - If TRUE then this routine will not wait to acquire the
    00069         resource and will return a boolean indicating whether the resource was
    00070         acquired.  Otherwise we use the flag in the IrpContext and raise
    00071         if the resource is not acquired.
    00072
    00073     Type - Indicates how we should try to get the resource.
    00074
    00075 Return Value:
    00076
    00077     BOOLEAN - TRUE if the resource is acquired.  FALSE if not acquired and
    00078         IgnoreWait is specified.  Otherwise we raise CANT_WAIT.
    00079
    00080 --*/
    00081
    00082 {
    00083     BOOLEAN Wait = FALSE;
    00084     BOOLEAN Acquired;
    00085     PAGED_CODE();
    00086
    00087     //
    00088     //  We look first at the IgnoreWait flag, next at the flag in the Irp
    00089     //  Context to decide how to acquire this resource.
    00090     //
    00091
    00092     if (!IgnoreWait && FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00093
    00094         Wait = TRUE;
    00095     }
    00096
    00097     //
    00098     //  Attempt to acquire the resource either shared or exclusively.
    00099     //
    00100
    00101     switch (Type) {
    00102         case AcquireExclusive:
    00103
    00104             Acquired = ExAcquireResourceExclusive( Resource, Wait );
    00105             break;
    00106
    00107         case AcquireShared:
    00108
    00109             Acquired = ExAcquireResourceShared( Resource, Wait );
    00110             break;
    00111
    00112         case AcquireSharedStarveExclusive:
    00113
    00114             Acquired = ExAcquireSharedStarveExclusive( Resource, Wait );
    00115             break;
    00116
    00117         default:
    00118             ASSERT( FALSE );
    00119     }
    00120
    00121     //
    00122     //  If not acquired and the user didn't specifiy IgnoreWait then
    00123     //  raise CANT_WAIT.
    00124     //
    00125
    00126     if (!Acquired && !IgnoreWait) {
    00127
    00128         UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00129     }
    00130
    00131     return Acquired;
    00132 }

VOID UdfAddToPcb | ( | IN PPCB | Pcb,
|  | IN PNSR_PART | PartitionDescriptor
| ) |

Definition at line 724 of file allocsup.c.

References ASSERT, ASSERT_PCB, Dbg, DebugTrace, FALSE, PAGED_CODE, Physical, PNSR_PART, PNSR_VD_GENERIC, UdfStoreVolumeDescriptorIfPrevailing(), USHORT, and Virtual.

Referenced by UdfFindVolumeDescriptors().

    00731                    :
    00732
    00733     This routine possibly adds a partition descriptor into a Pcb if it
    00734     turns out to be of higher precendence than a descriptor already
    00735     present.  Used in building a Pcb already initialized in preperation
    00736     for UdfCompletePcb.
    00737
    00738 Arguments:
    00739
    00740     Vcb - Vcb of the volume the Pcb describes
    00741
    00742     Pcb - Pcb being filled in
    00743
    00744 Return Value:
    00745
    00746     None. An old partition descriptor may be returned in the input field.
    00747
    00748 --*/
    00749
    00750 {
    00751     USHORT Reference;
    00752
    00753     PAGED_CODE();
    00754
    00755     //
    00756     //  Check inputs
    00757     //
    00758
    00759     ASSERT_PCB( Pcb );
    00760     ASSERT( PartitionDescriptor );
    00761
    00762     for (Reference = 0;
    00763          Reference < Pcb->Partitions;
    00764          Reference++) {
    00765
    00766         DebugTrace(( 0, Dbg, "UdfAddToPcb,  considering partition reference %d (type %d)\n", (ULONG)Reference, Pcb->Partition[Reference].Type));
    00767
    00768         switch (Pcb->Partition[Reference].Type) {
    00769
    00770             case Physical:
    00771
    00772                 //
    00773                 //  Now possibly store this descriptor in the Pcb if it is
    00774                 //  the partition number for this partition reference.
    00775                 //
    00776
    00777                 if (Pcb->Partition[Reference].Physical.PartitionNumber == PartitionDescriptor->Number) {
    00778
    00779                     //
    00780                     //  It seems to be legal (if questionable) for multiple partition maps to reference
    00781                     //  the same partition descriptor.  So we make a copy of the descriptor for each
    00782                     //  referencing partitionmap to make life easier when it comes to freeing it.
    00783                     //
    00784
    00785                     UdfStoreVolumeDescriptorIfPrevailing( (PNSR_VD_GENERIC *) &Pcb->Partition[Reference].Physical.PartitionDescriptor,
    00786                                                           (PNSR_VD_GENERIC) PartitionDescriptor );
    00787                 }
    00788
    00789                 break;
    00790
    00791             case Virtual:
    00792                 break;
    00793
    00794             default:
    00795
    00796                 ASSERT(FALSE);
    00797                 break;
    00798         }
    00799     }
    00800 }

BOOLEAN UdfAddVmcbMapping | ( | IN PVMCB | Vmcb,
|  | IN LBN | Lbn,
|  | IN ULONG | SectorCount,
|  | IN BOOLEAN | ExactEnd,
|  | OUT PVBN | Vbn,
|  | OUT PULONG | AlignedSectorCount
| ) |

Definition at line 637 of file vmcbsup.c.

References ASSERT, Dbg, DebugTrace, DebugUnwind, Executive, FALSE, FsRtlAddMcbEntry(), FsRtlLookupLastMcbEntry(), FsRtlRemoveMcbEntry(), KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), LBN, NULL, PageAlign, PAGED_CODE, TRUE, try_leave, UdfRemoveVmcbMapping(), UdfVmcbLookupMcbEntry(), VBN, and VOID().

Referenced by UdfLookupMetaVsnOfExtent().

    00648                    :
    00649
    00650     This routine adds a new LBN to VBN mapping to the VMCB structure.  When
    00651     a new LBN is added to the structure it does it only on page aligned
    00652     boundaries.
    00653
    00654     If pool is not available to store the information this routine will
    00655     raise a status value indicating insufficient resources.
    00656
    00657 Arguments:
    00658
    00659     Vmcb - Supplies the VMCB being updated.
    00660
    00661     Lbn - Supplies the starting LBN to add to VMCB.
    00662
    00663     SectorCount - Supplies the number of Sectors in the run
    00664
    00665     ExactEnd - Indicates that instead of aligning to map sectors beyond
    00666         the end of the request, use a hole.  Implies trying to look at
    00667         these sectors could be undesireable.
    00668
    00669     Vbn - Receives the assigned VBN
    00670
    00671     AlignedSectorCount - Receives the actual sector count created in the
    00672         Vmcb for page alignment purposes. Vbn+AlignedSectorCount-1 == LastVbn.
    00673
    00674 Return Value:
    00675
    00676     BOOLEAN - TRUE if this is a new mapping and FALSE if the mapping
    00677         for the LBN already exists.  If it already exists then the
    00678         sector count for this new addition must already be in the
    00679         VMCB structure
    00680
    00681 --*/
    00682
    00683 {
    00684
    00685     BOOLEAN Result;
    00686
    00687     BOOLEAN VbnMcbAdded;
    00688     BOOLEAN LbnMcbAdded;
    00689
    00690     LBN LocalLbn;
    00691     VBN LocalVbn;
    00692     ULONG LocalCount;
    00693
    00694     PAGED_CODE();
    00695
    00696     DebugTrace(( +1, Dbg, "UdfAddVmcbMapping, Lbn = %08x\n", Lbn ));
    00697     DebugTrace(( 0, Dbg, " SectorCount = %08x\n", SectorCount ));
    00698
    00699     ASSERT( SectorCount != 0 );
    00700
    00701     VbnMcbAdded = FALSE;
    00702     LbnMcbAdded = FALSE;
    00703
    00704     //
    00705     //  Now grab the mutex for the vmcb
    00706     //
    00707
    00708     (VOID)KeWaitForSingleObject( &Vmcb->Mutex,
    00709                                  Executive,
    00710                                  KernelMode,
    00711                                  FALSE,
    00712                                  (PLARGE_INTEGER) NULL );
    00713
    00714     try {
    00715
    00716         //
    00717         //  Check if the Lbn is already mapped, which means we find an entry
    00718         //  with a non zero mapping Vbn value.
    00719         //
    00720
    00721         if (UdfVmcbLookupMcbEntry( &Vmcb->LbnIndexed,
    00722                                    Lbn,
    00723                                    Vbn,
    00724                                    &LocalCount,
    00725                                    NULL )) {
    00726
    00727             //
    00728             //  It is already mapped so now the sector count must not exceed
    00729             //  the count already in the run
    00730             //
    00731
    00732             if (SectorCount <= LocalCount) {
    00733
    00734                 try_leave( Result = FALSE );
    00735             }
    00736         }
    00737
    00738         //
    00739         //  At this point, we did not find a full existing mapping for the
    00740         //  Lbn and count.  But there might be some overlapping runs that we'll
    00741         //  need to now remove from the vmcb structure.  So for each Lbn in
    00742         //  the range we're after, check to see if it is mapped and remove the
    00743         //  mapping.  We only need to do this test if the sector count is less
    00744         //  than or equal to a page size.  Because those are the only
    00745         //  structures that we know we'll try an remove/overwrite.
    00746         //
    00747
    00748         if (SectorCount <= PageAlign(Vmcb, 1)) {
    00749
    00750             if (UdfVmcbLookupMcbEntry( &Vmcb->LbnIndexed,
    00751                                        Lbn,
    00752                                        Vbn,
    00753                                        &LocalCount,
    00754                                        NULL )) {
    00755
    00756                 UdfRemoveVmcbMapping( Vmcb, *Vbn, PageAlign(Vmcb, 1) );
    00757             }
    00758         }
    00759
    00760         //
    00761         //  We need to add this new run at the end of the Vbns.  To do this we
    00762         //  need to look up the last mcb entry or use a vbn for the second
    00763         //  page, if the mcb is empty.  We'll also special case the situation
    00764         //  where the last lbn of the mapping and the mapping we're adding
    00765         //  simply flow into each other in which case we'll not bother bumping
    00766         //  the vbn to a page alignment
    00767         //
    00768
    00769         if (FsRtlLookupLastMcbEntry( &Vmcb->VbnIndexed, &LocalVbn, &LocalLbn )) {
    00770
    00771             if (LocalLbn + 1 == Lbn) {
    00772
    00773                 LocalVbn = LocalVbn + 1;
    00774                 LocalLbn = LocalLbn + 1;
    00775
    00776             } else {
    00777
    00778                 //
    00779                 //  Get the next available Vbn Page, and calculate the
    00780                 //  Lbn for the page containing the Lbn
    00781                 //
    00782
    00783                 LocalVbn = PageAlign( Vmcb, LocalVbn + 1 );
    00784                 LocalLbn = PageAlign( Vmcb, Lbn + 1 ) - PageAlign( Vmcb, 1 );
    00785             }
    00786
    00787         } else {
    00788
    00789             //
    00790             //  Get the first available Vbn page, and calculate the
    00791             //  Lbn for the page containing the Lbn.
    00792             //
    00793
    00794
    00795             LocalVbn = 0;
    00796             LocalLbn = PageAlign( Vmcb, Lbn + 1 ) - PageAlign( Vmcb, 1 );
    00797         }
    00798
    00799         //
    00800         //  Calculate the number of sectors that we need to map to keep
    00801         //  everything on a page granularity.
    00802         //
    00803
    00804         LocalCount = PageAlign( Vmcb, SectorCount + (Lbn - LocalLbn) );
    00805
    00806         //
    00807         //  See if we should use a hole to map the alignment at the end of the request.
    00808         //
    00809
    00810         if (ExactEnd && Lbn + SectorCount < LocalLbn + LocalCount) {
    00811
    00812             LocalCount = SectorCount + (Lbn - LocalLbn);
    00813         }
    00814
    00815         //
    00816         //  Add the double mapping
    00817         //
    00818
    00819         FsRtlAddMcbEntry( &Vmcb->VbnIndexed,
    00820                           LocalVbn,
    00821                           LocalLbn,
    00822                           LocalCount );
    00823
    00824         VbnMcbAdded = TRUE;
    00825
    00826         FsRtlAddMcbEntry( &Vmcb->LbnIndexed,
    00827                           LocalLbn,
    00828                           LocalVbn,
    00829                           LocalCount );
    00830
    00831         LbnMcbAdded = TRUE;
    00832
    00833         *Vbn = LocalVbn + (Lbn - LocalLbn);
    00834         *AlignedSectorCount = LocalCount - (Lbn - LocalLbn);
    00835
    00836         try_leave( Result = TRUE );
    00837
    00838     } finally {
    00839
    00840         //
    00841         //  If this is an abnormal termination then clean up any mcb's that we
    00842         //  might have modified.
    00843         //
    00844
    00845         if (AbnormalTermination()) {
    00846
    00847             if (VbnMcbAdded) { FsRtlRemoveMcbEntry( &Vmcb->VbnIndexed, LocalVbn, LocalCount ); }
    00848             if (LbnMcbAdded) { FsRtlRemoveMcbEntry( &Vmcb->LbnIndexed, LocalLbn, LocalCount ); }
    00849         }
    00850
    00851         (VOID) KeReleaseMutex( &Vmcb->Mutex, FALSE );
    00852
    00853         DebugUnwind("UdfAddVmcbMapping");
    00854         DebugTrace(( 0, Dbg, " LocalVbn   = %08x\n", LocalVbn ));
    00855         DebugTrace(( 0, Dbg, " LocalLbn   = %08x\n", LocalLbn ));
    00856         DebugTrace(( 0, Dbg, " LocalCount = %08x\n", LocalCount ));
    00857         DebugTrace(( 0, Dbg, " *Vbn                = %08x\n", *Vbn ));
    00858         DebugTrace(( 0, Dbg, " *AlignedSectorCount = %08x\n", *AlignedSectorCount ));
    00859         DebugTrace((-1, Dbg, "UdfAddVmcbMapping -> %08x\n", Result ));
    00860     }
    00861
    00862     return Result;
    00863 }

BOOLEAN UdfCandidateShortName | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | Name
| ) |

Definition at line 301 of file namesup.c.

References ASSERT, ASSERT_IRP_CONTEXT, BYTE_COUNT_8_DOT_3, CRC_MARK, DOS_CRC_LEN, FALSE, Index, Name, PAGED_CODE, PERIOD, and TRUE.

Referenced by UdfCommonCreate().

    00308                    :
    00309
    00310     This routine is called to determine if the input name could be a generated
    00311     short name.
    00312
    00313 Arguments:
    00314
    00315     Name - Pointer to the name to stare at.
    00316
    00317 Return Value:
    00318
    00319     BOOLEAN True if it is possible that this is a shortname, False otherwise.
    00320
    00321 --*/
    00322
    00323 {
    00324     ULONG Index, SubIndex;
    00325     BOOLEAN LooksShort = FALSE;
    00326
    00327     PAGED_CODE();
    00328
    00329     //
    00330     //  Check inputs.
    00331     //
    00332
    00333     ASSERT_IRP_CONTEXT( IrpContext );
    00334
    00335     //
    00336     //  The length can't be larger than an 8.3 name and must be
    00337     //  at least as big as the uniqifier stamp.
    00338     //
    00339
    00340     ASSERT( Name->Length != 0 );
    00341
    00342     if (Name->Length > BYTE_COUNT_8_DOT_3 ||
    00343         Name->Length < DOS_CRC_LEN * sizeof(WCHAR)) {
    00344
    00345         return FALSE;
    00346     }
    00347
    00348     //
    00349     //  Walk across the name looking for the uniquifier stamp.  The stamp
    00350     //  is of the form #<hex><hex><hex> so if we can stop before the end
    00351     //  of the full name.
    00352     //
    00353
    00354     for ( Index = 0;
    00355           Index <= (Name->Length / sizeof(WCHAR)) - DOS_CRC_LEN;
    00356           Index++ ) {
    00357
    00358         //
    00359         //  Is the current character the stamp UDF uses to offset the stamp?
    00360         //
    00361
    00362         if (Name->Buffer[Index] == CRC_MARK) {
    00363
    00364             //
    00365             //  We may potentially have just a CRC at the end
    00366             //  of the name OR have a period following.  If we
    00367             //  do, it is reasonable to think the name may be
    00368             //  a generated shorty.
    00369             //
    00370             //  #123 (a very special case - orignal name was ".")
    00371             //  FOO#123
    00372             //  FOO#123.TXT
    00373             //
    00374
    00375             if (Index == (Name->Length / sizeof(WCHAR)) - DOS_CRC_LEN ||
    00376                 Name->Buffer[Index + DOS_CRC_LEN] == PERIOD) {
    00377
    00378                 LooksShort = TRUE;
    00379                 break;
    00380             }
    00381         }
    00382     }
    00383
    00384     return LooksShort;
    00385 }

BOOLEAN UdfCheckForDismount | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN BOOLEAN | Force
| ) |

Definition at line 236 of file udfs/verfysup.c.

References ASSERT_EXCLUSIVE_UDFDATA, ASSERT_IRP_CONTEXT, ASSERT_VCB, FALSE, IoAcquireVpbSpinLock(), IoReleaseVpbSpinLock(), TRUE, UdfAcquireVcbExclusive, UdfDeleteVcb(), UdfDismountVcb(), UdfFspClose(), UdfLockVcb, UdfReleaseVcb, UdfUnlockVcb, and VcbDismountInProgress.

Referenced by UdfCommonClose(), UdfFspClose(), UdfInvalidateVolumes(), UdfPerformVerify(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfScanForDismountedVcb(), and UdfVerifyVolume().

    00244                    :
    00245
    00246     This routine is called to check if a volume is ready for dismount.  This
    00247     occurs when only file system references are left on the volume.
    00248
    00249     If the dismount is not currently underway and the user reference count
    00250     has gone to zero then we can begin the dismount.
    00251
    00252     If the dismount is in progress and there are no references left on the
    00253     volume (we check the Vpb for outstanding references as well to catch
    00254     any create calls dispatched to the file system) then we can delete
    00255     the Vcb.
    00256
    00257 Arguments:
    00258
    00259     Vcb - Vcb for the volume to try to dismount.
    00260
    00261     Force - Whether we will force this volume to be dismounted.
    00262
    00263 Return Value:
    00264
    00265     BOOLEAN - True if the Vcb was not gone by the time this function finished,
    00266         False if it was deleted.
    00267
    00268     This is only a trustworthy indication to the caller if it had the vcb
    00269     exclusive itself.
    00270
    00271 --*/
    00272
    00273 {
    00274     BOOLEAN UnlockVcb = TRUE;
    00275     BOOLEAN VcbPresent = TRUE;
    00276     KIRQL SavedIrql;
    00277
    00278     ASSERT_IRP_CONTEXT( IrpContext );
    00279     ASSERT_VCB( Vcb );
    00280
    00281     ASSERT_EXCLUSIVE_UDFDATA;
    00282
    00283     //
    00284     //  Acquire and lock this Vcb to check the dismount state.
    00285     //
    00286
    00287     UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00288
    00289     //
    00290     //  Lets get rid of any pending closes for this volume.
    00291     //
    00292
    00293     UdfFspClose( Vcb );
    00294
    00295     UdfLockVcb( IrpContext, Vcb );
    00296
    00297     //
    00298     //  If the dismount is not already underway then check if the
    00299     //  user reference count has gone to zero or we are being forced
    00300     //  to disconnect.  If so start the teardown on the Vcb.
    00301     //
    00302
    00303     if (Vcb->VcbCondition != VcbDismountInProgress) {
    00304
    00305         if (Vcb->VcbUserReference <= Vcb->VcbResidualUserReference || Force) {
    00306
    00307             UdfUnlockVcb( IrpContext, Vcb );
    00308             UnlockVcb = FALSE;
    00309             VcbPresent = UdfDismountVcb( IrpContext, Vcb );
    00310         }
    00311
    00312     //
    00313     //  If the teardown is underway and there are absolutely no references
    00314     //  remaining then delete the Vcb.  References here include the
    00315     //  references in the Vcb and Vpb.
    00316     //
    00317
    00318     } else if (Vcb->VcbReference == 0) {
    00319
    00320         IoAcquireVpbSpinLock( &SavedIrql );
    00321
    00322         //
    00323         //  If there are no file objects and no reference counts in the
    00324         //  Vpb we can delete the Vcb.  Don't forget that we have the
    00325         //  last reference in the Vpb.
    00326         //
    00327
    00328         if (Vcb->Vpb->ReferenceCount == 1) {
    00329
    00330             IoReleaseVpbSpinLock( SavedIrql );
    00331             UdfUnlockVcb( IrpContext, Vcb );
    00332             UnlockVcb = FALSE;
    00333             UdfDeleteVcb( IrpContext, Vcb );
    00334             VcbPresent = FALSE;
    00335
    00336         } else {
    00337
    00338             IoReleaseVpbSpinLock( SavedIrql );
    00339         }
    00340     }
    00341
    00342     //
    00343     //  Unlock the Vcb if still held.
    00344     //
    00345
    00346     if (UnlockVcb) {
    00347
    00348         UdfUnlockVcb( IrpContext, Vcb );
    00349     }
    00350
    00351     //
    00352     //  Release any resources still acquired.
    00353     //
    00354
    00355     if (VcbPresent) {
    00356
    00357         UdfReleaseVcb( IrpContext, Vcb );
    00358     }
    00359
    00360     return VcbPresent;
    00361 }

BOOLEAN UdfCheckLegalCS0Dstring | ( | PIRP_CONTEXT | IrpContext,
|  | PUCHAR | Dstring,
|  | UCHAR Length | OPTIONAL,
|  | UCHAR FieldLength | OPTIONAL,
|  | BOOLEAN | ReturnOnError
| ) |

Definition at line 819 of file namesup.c.

References ASSERT, ASSERT_IRP_CONTEXT, Dbg, DebugTrace, FALSE, FlagOn, TRUE, and UdfRaiseStatus().

Referenced by UdfUpdateDirNames(), and UdfUpdateVolumeLabel().

    00829                    :
    00830
    00831     This routine inspects a CS0 Dstring for conformance.
    00832
    00833 Arguments:
    00834
    00835     Dstring - a dstring to check
    00836
    00837     Length - length of the dstring.  If unspecified, we assume that the characters come
    00838         from a proper 1/7.2.12 dstring that specifies length in the last character of the
    00839         field.
    00840
    00841     FieldLength - length of the dstring field.  If unspecified, we assume that the characters
    00842         come from an uncounted length of CS0 characters and that the Length parameter is
    00843         specified.
    00844
    00845     ReturnOnError - whether to return or raise on a discovered error
    00846
    00847 Return Value:
    00848
    00849     None. Raised status if corruption is found.
    00850
    00851 --*/
    00852
    00853 {
    00854     UCHAR NameLength;
    00855
    00856     //
    00857     //  Check input.
    00858     //
    00859
    00860     ASSERT_IRP_CONTEXT( IrpContext );
    00861
    00862     //
    00863     //  If the length is unspecified, this is a real 1/7.2.12 dstring and the length is in
    00864     //  the last character of the field.
    00865     //
    00866
    00867     ASSERT( Length || FieldLength );
    00868
    00869     if (Length) {
    00870
    00871         NameLength = FieldLength = Length;
    00872
    00873     } else {
    00874
    00875         NameLength = *(Dstring + FieldLength - 1);
    00876     }
    00877
    00878     DebugTrace(( +1, Dbg,
    00879                  "UdfCheckLegalCS0Dstring, Dstring %08x Length %02x FieldLength %02x (NameLength %02x)\n",
    00880                  Dstring,
    00881                  Length,
    00882                  FieldLength,
    00883                  NameLength ));
    00884
    00885     //
    00886     //  The string must be "compressed" in 8bit or 16bit chunks.  If it
    00887     //  is in 16bit chunks, we better have an integral number of them -
    00888     //  remember we have the compression ID, so the length will be odd.
    00889     //
    00890
    00891     if ((NameLength <= 1 &&
    00892          DebugTrace(( 0, Dbg,
    00893                       "UdfCheckLegalCS0Dstring, NameLength is too small!\n" ))) ||
    00894
    00895         (NameLength > FieldLength &&
    00896          DebugTrace(( 0, Dbg,
    00897                       "UdfCheckLegalCS0Dstring, NameLength is bigger than the field itself!\n" ))) ||
    00898
    00899         ((*Dstring != 8 && *Dstring != 16) &&
    00900          DebugTrace(( 0, Dbg,
    00901                       "UdfCheckLegalCS0Dstring, claims encoding %02x, unknown! (not 0x8 or 0x10)\n",
    00902                       *Dstring ))) ||
    00903
    00904         ((*Dstring == 16 && !FlagOn( NameLength, 1)) &&
    00905          DebugTrace(( 0, Dbg,
    00906                      "UdfCheckLegalCS0Dstring, NameLength not odd, encoding 0x10!\n" )))) {
    00907
    00908         if (ReturnOnError) {
    00909
    00910             DebugTrace(( -1, Dbg, "UdfCheckLegalCS0Dstring -> FALSE\n" ));
    00911
    00912             return FALSE;
    00913         }
    00914
    00915         DebugTrace(( -1, Dbg, "UdfCheckLegalCS0Dstring -> raised status\n" ));
    00916
    00917         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    00918     }
    00919
    00920     DebugTrace(( -1, Dbg, "UdfCheckLegalCS0Dstring -> TRUE\n" ));
    00921
    00922     return TRUE;
    00923 }

VOID UdfCleanupDirContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PDIR_ENUM_CONTEXT | DirContext
| ) |

Definition at line 99 of file dirsup.c.

References ASSERT_IRP_CONTEXT, DIR_CONTEXT_FLAG_FID_BUFFERED, FlagOn, PAGED_CODE, UdfFreePool(), and UdfUnpinData.

Referenced by UdfCleanupCompoundDirContext(), UdfCommonCreate(), UdfInitializeEnumeration(), and UdfQueryAlternateNameInfo().

    00106                    :
    00107
    00108     This routine cleans up a directory enumeration context for reuse.
    00109
    00110 Arguments:
    00111
    00112     DirContext - a context to clean.
    00113
    00114 Return Value:
    00115
    00116     None.
    00117
    00118 --*/
    00119
    00120 {
    00121     PAGED_CODE();
    00122
    00123     //
    00124     //  Check input.
    00125     //
    00126
    00127     ASSERT_IRP_CONTEXT( IrpContext );
    00128
    00129     //
    00130     //  Dump the allocation we store the triple of names in.
    00131     //
    00132
    00133     UdfFreePool( &DirContext->NameBuffer );
    00134
    00135     //
    00136     //  And the short name.
    00137     //
    00138
    00139     UdfFreePool( &DirContext->ShortObjectName.Buffer );
    00140
    00141     //
    00142     //  Unpin the view.
    00143     //
    00144
    00145     UdfUnpinData( IrpContext, &DirContext->Bcb );
    00146
    00147     //
    00148     //  Free a buffered Fid that may remain.
    00149     //
    00150
    00151     if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED )) {
    00152
    00153         UdfFreePool( &DirContext->Fid );
    00154     }
    00155
    00156     //
    00157     //  Zero everything else out.
    00158     //
    00159
    00160     RtlZeroMemory( DirContext, sizeof( DIR_ENUM_CONTEXT ) );
    00161 }

VOID UdfCleanupIcbContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext
| ) |

Definition at line 3183 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT, PAGED_CODE, and UdfUnpinView.

Referenced by UdfCleanupCompoundDirContext(), UdfLookupFileEntryInEnumeration(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

    03190                    :
    03191
    03192     This routine cleans an Icb search context for reuse/deletion.
    03193
    03194 Arguments:
    03195
    03196     IcbContext - context to clean
    03197
    03198 Return Value:
    03199
    03200     None.
    03201
    03202 --*/
    03203
    03204 {
    03205     PAGED_CODE();
    03206
    03207     //
    03208     //  Check inputs
    03209     //
    03210
    03211     ASSERT_IRP_CONTEXT( IrpContext );
    03212
    03213     UdfUnpinView( IrpContext, &IcbContext->Active );
    03214     UdfUnpinView( IrpContext, &IcbContext->Current );
    03215
    03216     RtlZeroMemory( IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
    03217 }

VOID UdfCleanupIrpContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN BOOLEAN | Post
| ) |

Definition at line 1437 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT, ClearFlag, ExFreeToNPagedLookasideList(), FlagOn, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_MORE_PROCESSING, IRP_CONTEXT_FLAG_ON_STACK, IRP_CONTEXT_FLAGS_CLEAR_ON_POST, IRP_CONTEXT_FLAGS_CLEAR_ON_RETRY, NULL, PAGED_CODE, UdfFreeIoContext, UdfIrpContextLookasideList, and UdfRestoreThreadContext().

Referenced by UdfCompleteRequest(), UdfFsdDispatch(), UdfFspDispatch(), UdfPrePostIrp(), and UdfQueueClose().

    01444                    :
    01445
    01446     This routine is called to cleanup and possibly deallocate the Irp Context.
    01447     If the request is being posted or this Irp Context is possibly on the
    01448     stack then we only cleanup any auxilary structures.
    01449
    01450 Arguments:
    01451
    01452     Post - TRUE if we are posting this request, FALSE if we are deleting
    01453         or retrying this in the current thread.
    01454
    01455 Return Value:
    01456
    01457     None.
    01458
    01459 --*/
    01460
    01461 {
    01462     PAGED_CODE();
    01463
    01464     ASSERT_IRP_CONTEXT( IrpContext );
    01465
    01466     //
    01467     //  If we aren't doing more processing then deallocate this as appropriate.
    01468     //
    01469
    01470     if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING)) {
    01471
    01472         //
    01473         //  If this context is the top level UDFS context then we need to
    01474         //  restore the top level thread context.
    01475         //
    01476
    01477         if (IrpContext->ThreadContext != NULL) {
    01478
    01479             UdfRestoreThreadContext( IrpContext );
    01480         }
    01481
    01482         //
    01483         //  Deallocate the Io context if allocated.
    01484         //
    01485
    01486         if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
    01487
    01488             UdfFreeIoContext( IrpContext->IoContext );
    01489         }
    01490
    01491         //
    01492         //  Deallocate the IrpContext if not from the stack.
    01493         //
    01494
    01495         if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ON_STACK )) {
    01496
    01497             ExFreeToNPagedLookasideList( &UdfIrpContextLookasideList, IrpContext );
    01498         }
    01499
    01500     //
    01501     //  Clear the appropriate flags.
    01502     //
    01503
    01504     } else if (Post) {
    01505
    01506         //
    01507         //  If this context is the top level UDFS context then we need to
    01508         //  restore the top level thread context.
    01509         //
    01510
    01511         if (IrpContext->ThreadContext != NULL) {
    01512
    01513             UdfRestoreThreadContext( IrpContext );
    01514         }
    01515
    01516         ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAGS_CLEAR_ON_POST );
    01517
    01518     } else {
    01519
    01520         ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAGS_CLEAR_ON_RETRY );
    01521     }
    01522
    01523     return;
    01524 }

NTSTATUS UdfCommonCleanup | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 42 of file udfs/cleanup.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, CcUninitializeCacheMap(), ClearFlag, Dbg, DebugTrace, _VCB::DirNotifyList, FALSE, _FILE_OBJECT::Flags, FO_CLEANUP_COMPLETE, FSRTL_VOLUME_UNLOCK, FsRtlCheckOplock(), FsRtlFastUnlockAll(), FsRtlNotifyCleanup(), FsRtlNotifyVolumeEvent(), IoGetCurrentIrpStackLocation, IoGetRequestorProcess(), IoRemoveShareAccess(), Irp, _VCB::NotifySync, NULL, PAGED_CODE, PCCB, SetFlag, _FCB::ShareAccess, StreamFileOpen, TRUE, TYPE_OF_OPEN, UdfAcquireFcbExclusive, UdfAcquireVcbExclusive, UdfBugCheck, UdfCompleteRequest(), UdfDecodeFileObject(), UdfDecrementCleanupCounts, UdfIsFastIoPossible, UdfLockFcb, UdfLockVcb, UdfPurgeVolume(), UdfReleaseFcb, UdfReleaseVcb, UdfUnlockFcb, UdfUnlockVcb, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, _FCB::Vcb, VCB_STATE_LOCKED, _VCB::VcbCleanup, _VCB::VcbCondition, VcbNotMounted, _VCB::VcbState, and _VCB::VolumeLockFileObject.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00049                    :
    00050
    00051     This is the common routine for cleanup of a file/directory called by both
    00052     the fsd and fsp threads.
    00053
    00054     Cleanup is invoked whenever the last handle to a file object is closed.
    00055     This is different than the Close operation which is invoked when the last
    00056     reference to a file object is deleted.
    00057
    00058     The function of cleanup is to essentially "cleanup" the file/directory
    00059     after a user is done with it.  The Fcb/Dcb remains around (because MM
    00060     still has the file object referenced) but is now available for another
    00061     user to open (i.e., as far as the user is concerned the is now closed).
    00062
    00063     See close for a more complete description of what close does.
    00064
    00065     We do no synchronization in this routine until we get to the point
    00066     where we modify the counts, share access and volume lock field.
    00067
    00068     We need to update the Fcb and Vcb to show that a user handle has been closed.
    00069     The following structures and fields are affected.
    00070
    00071     Vcb:
    00072
    00073         VolumeLockFileObject - Did the user lock the volume with this file object.
    00074         VcbState - Check if we are unlocking the volume here.
    00075         VcbCleanup - Count of outstanding handles on the volume.
    00076         DirNotifyQueue - If this file object has pending DirNotify Irps.
    00077
    00078     Fcb:
    00079
    00080         ShareAccess - If this is a user handle.
    00081         FcbCleanup - Count of outstanding handles on this Fcb.
    00082         Oplock - Any outstanding oplocks on this file object.
    00083         FileLock - Any outstanding filelocks on this file object.
    00084
    00085 Arguments:
    00086
    00087     Irp - Supplies the Irp to process
    00088
    00089 Return Value:
    00090
    00091     NTSTATUS - The return status for the operation.
    00092
    00093 --*/
    00094
    00095 {
    00096     PFILE_OBJECT FileObject;
    00097     TYPE_OF_OPEN TypeOfOpen;
    00098
    00099     BOOLEAN SendUnlockNotification = FALSE;
    00100     BOOLEAN AttemptTeardown;
    00101
    00102     PVCB Vcb;
    00103     PFCB Fcb;
    00104     PCCB Ccb;
    00105
    00106     PAGED_CODE();
    00107
    00108     ASSERT_IRP_CONTEXT( IrpContext );
    00109     ASSERT_IRP( Irp );
    00110
    00111     //
    00112     //  If we were called with our file system device object instead of a
    00113     //  volume device object, just complete this request with STATUS_SUCCESS.
    00114     //
    00115
    00116     if (IrpContext->Vcb == NULL) {
    00117
    00118         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00119         return STATUS_SUCCESS;
    00120     }
    00121
    00122     //
    00123     //  Get the file object out of the Irp and decode the type of open.
    00124     //
    00125
    00126     FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
    00127
    00128     TypeOfOpen = UdfDecodeFileObject( FileObject,
    00129                                       &Fcb,
    00130                                       &Ccb );
    00131
    00132     //
    00133     //  No work here for either an UnopenedFile object or a StreamFileObject.
    00134     //
    00135
    00136     if (TypeOfOpen <= StreamFileOpen) {
    00137
    00138         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00139
    00140         return STATUS_SUCCESS;
    00141     }
    00142
    00143     //
    00144     //  Keep a local pointer to the Vcb.
    00145     //
    00146
    00147     Vcb = Fcb->Vcb;
    00148
    00149     //
    00150     //  Acquire the current file.
    00151     //
    00152
    00153     UdfAcquireFcbExclusive( IrpContext, Fcb, FALSE );
    00154
    00155     //
    00156     //  Use a try-finally to facilitate cleanup.
    00157     //
    00158
    00159     try {
    00160
    00161         //
    00162         //  Set the flag in the FileObject to indicate that cleanup is complete.
    00163         //
    00164
    00165         SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE );
    00166
    00167         //
    00168         //  Case on the type of open that we are trying to cleanup.
    00169         //
    00170
    00171         switch (TypeOfOpen) {
    00172
    00173         case UserDirectoryOpen:
    00174
    00175             DebugTrace(( +1, Dbg,
    00176                          "UdfCommonCleanup, Fcb %08x FO %08x DIR\n",
    00177                          Fcb,
    00178                          FileObject ));
    00179
    00180             //
    00181             //  Check if we need to complete any dir notify Irps on this file object.
    00182             //
    00183
    00184             FsRtlNotifyCleanup( Vcb->NotifySync,
    00185                                 &Vcb->DirNotifyList,
    00186                                 Ccb );
    00187
    00188             break;
    00189
    00190         case UserFileOpen:
    00191
    00192             DebugTrace(( +1, Dbg,
    00193                          "UdfCommonCleanup, Fcb %08x FO %08x FILE\n",
    00194                          Fcb,
    00195                          FileObject ));
    00196
    00197             //
    00198             //  Coordinate the cleanup operation with the oplock state.
    00199             //  Oplock cleanup operations can always cleanup immediately so no
    00200             //  need to check for STATUS_PENDING.
    00201             //
    00202
    00203             FsRtlCheckOplock( &Fcb->Oplock,
    00204                               Irp,
    00205                               IrpContext,
    00206                               NULL,
    00207                               NULL );
    00208
    00209             //
    00210             //  Unlock all outstanding file locks.
    00211             //
    00212
    00213             if (Fcb->FileLock != NULL) {
    00214
    00215                 FsRtlFastUnlockAll( Fcb->FileLock,
    00216                                     FileObject,
    00217                                     IoGetRequestorProcess( Irp ),
    00218                                     NULL );
    00219             }
    00220
    00221             //
    00222             //  Cleanup the cache map.
    00223             //
    00224
    00225             CcUninitializeCacheMap( FileObject, NULL, NULL );
    00226
    00227             //
    00228             //  Check the fast io state.
    00229             //
    00230
    00231             UdfLockFcb( IrpContext, Fcb );
    00232             Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00233             UdfUnlockFcb( IrpContext, Fcb );
    00234
    00235             break;
    00236
    00237         case UserVolumeOpen :
    00238
    00239             DebugTrace(( +1, Dbg,
    00240                          "UdfCommonCleanup, Fcb %08x FO %08x VOL\n",
    00241                          Fcb,
    00242                          FileObject ));
    00243
    00244             break;
    00245
    00246         default :
    00247
    00248             UdfBugCheck( TypeOfOpen, 0, 0 );
    00249         }
    00250
    00251         //
    00252         //  Now lock the Vcb in order to modify the fields in the in-memory
    00253         //  structures.
    00254         //
    00255
    00256         UdfLockVcb( IrpContext, Vcb );
    00257
    00258         //
    00259         //  Decrement the cleanup counts in the Vcb and Fcb.
    00260         //
    00261
    00262         UdfDecrementCleanupCounts( IrpContext, Fcb );
    00263
    00264         //
    00265         //  If the cleanup count hit zero and the volume is not mounted, we
    00266         //  will want to try to spark teardown.
    00267         //
    00268
    00269         AttemptTeardown = (Vcb->VcbCleanup == 0 && Vcb->VcbCondition == VcbNotMounted);
    00270
    00271         //
    00272         //  If this file object has locked the volume then perform the unlock operation.
    00273         //
    00274
    00275         if (FileObject == Vcb->VolumeLockFileObject) {
    00276
    00277             ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
    00278             Vcb->VolumeLockFileObject = NULL;
    00279             SendUnlockNotification = TRUE;
    00280         }
    00281
    00282         UdfUnlockVcb( IrpContext, Vcb );
    00283
    00284         //
    00285         //  We must clean up the share access at this time, since we may not
    00286         //  get a Close call for awhile if the file was mapped through this
    00287         //  File Object.
    00288         //
    00289
    00290         IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
    00291
    00292     } finally {
    00293
    00294         UdfReleaseFcb( IrpContext, Fcb );
    00295
    00296         if (SendUnlockNotification) {
    00297
    00298             FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK );
    00299         }
    00300     }
    00301
    00302     DebugTrace(( -1, Dbg,
    00303                  "UdfCommonCleanup, Fcb %08x FO %08x -> SUCCESS\n",
    00304                  Fcb,
    00305                  FileObject ));
    00306
    00307     //
    00308     //  If appropriate, try to spark teardown by purging the volume.  Should
    00309     //  this very fileobject we were cleaning up be the last reason for the
    00310     //  volume to remain, teardown will commence on completion of this Irp.
    00311     //
    00312
    00313     if (AttemptTeardown) {
    00314
    00315         UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00316
    00317         try {
    00318
    00319             UdfPurgeVolume( IrpContext, Vcb, FALSE );
    00320
    00321         } finally {
    00322
    00323             UdfReleaseVcb( IrpContext, Vcb );
    00324         }
    00325     }
    00326
    00327     //
    00328     //  If this is a normal termination then complete the request
    00329     //
    00330
    00331     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00332
    00333     return STATUS_SUCCESS;
    00334 }

NTSTATUS UdfCommonClose | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 319 of file close.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, FALSE, _FCB::FcbReference, FlagOn, IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS, NULL, PAGED_CODE, TRUE, TYPE_OF_OPEN, UdfAcquireUdfData, UdfCheckForDismount(), UdfCommonClosePrivate(), UdfCompleteRequest(), UdfDecodeFileObject(), UdfDeleteCcb(), UdfQueueClose(), UdfReleaseUdfData, UnopenedFileObject, UserDirectoryOpen, UserFileOpen, _FCB::Vcb, _VCB::VcbCleanup, _VCB::VcbCondition, VcbMounted, and VcbMountInProgress.

Referenced by UdfFsdDispatch().

    00326                    :
    00327
    00328     This routine is the Fsd entry for the close operation.  We decode the file
    00329     object to find the UDFS structures and type of open.  We call our internal
    00330     worker routine to perform the actual work.  If the work wasn't completed
    00331     then we post to one of our worker queues.  The Ccb isn't needed after this
    00332     point so we delete the Ccb and return STATUS_SUCCESS to our caller in all
    00333     cases.
    00334
    00335 Arguments:
    00336
    00337     Irp - Supplies the Irp to process
    00338
    00339 Return Value:
    00340
    00341     STATUS_SUCCESS
    00342
    00343 --*/
    00344
    00345 {
    00346     TYPE_OF_OPEN TypeOfOpen;
    00347
    00348     PVCB Vcb;
    00349     PFCB Fcb;
    00350     PCCB Ccb;
    00351     ULONG UserReference = 0;
    00352
    00353     BOOLEAN DelayedClose;
    00354     BOOLEAN ReleaseUdfData = FALSE;
    00355
    00356     PAGED_CODE();
    00357
    00358     //
    00359     //  Check input.
    00360     //
    00361
    00362     ASSERT_IRP_CONTEXT( IrpContext );
    00363     ASSERT_IRP( Irp );
    00364
    00365     //
    00366     //  If we were called with our file system device object instead of a
    00367     //  volume device object, just complete this request with STATUS_SUCCESS.
    00368     //
    00369
    00370     if (IrpContext->Vcb == NULL) {
    00371
    00372         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00373         return STATUS_SUCCESS;
    00374     }
    00375
    00376     //
    00377     //  Decode the file object to get the type of open and Fcb/Ccb.
    00378     //
    00379
    00380     TypeOfOpen = UdfDecodeFileObject( IoGetCurrentIrpStackLocation( Irp )->FileObject,
    00381                                       &Fcb,
    00382                                       &Ccb );
    00383
    00384     //
    00385     //  No work to do for unopened file objects.
    00386     //
    00387
    00388     if (TypeOfOpen == UnopenedFileObject) {
    00389
    00390         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00391
    00392         return STATUS_SUCCESS;
    00393     }
    00394
    00395     Vcb = Fcb->Vcb;
    00396
    00397     //
    00398     //  Call the worker routine to perform the actual work.  This routine
    00399     //  should never raise except for a fatal error.
    00400     //
    00401
    00402     if (Ccb != NULL) {
    00403
    00404         UserReference = 1;
    00405
    00406         //
    00407         //  We can always deallocate the Ccb if present.
    00408         //
    00409
    00410         UdfDeleteCcb( IrpContext, Ccb );
    00411     }
    00412
    00413     //
    00414     //  If this is a user file or directory then check if we should post
    00415     //  this to the delayed close queue.  This has to be the last reference
    00416     //  for a user file or directory open.
    00417     //
    00418
    00419     if ((Vcb->VcbCondition == VcbMounted) &&
    00420         (Fcb->FcbReference == 1) &&
    00421         ((TypeOfOpen == UserFileOpen) ||
    00422          (TypeOfOpen == UserDirectoryOpen))) {
    00423
    00424         UdfQueueClose( IrpContext, Fcb, UserReference, TRUE );
    00425         IrpContext = NULL;
    00426
    00427     //
    00428     //  Otherwise try to process this close.  Post to the async close queue
    00429     //  if we can't acquire all of the resources.
    00430     //
    00431
    00432     } else {
    00433
    00434         //
    00435         //  If we may be dismounting this volume then acquire the UdfData
    00436         //  resource.
    00437         //
    00438         //  Since we now must make volumes go away as soon as reasonable after
    00439         //  the last user handles closes, key off of the cleanup count.  It is
    00440         //  OK to do this more than neccesary.  Since this Fcb could be holding
    00441         //  a number of other Fcbs (and thus their references), a simple check
    00442         //  on reference count is not appropriate.
    00443         //
    00444
    00445         if ((Vcb->VcbCleanup == 0) &&
    00446             (Vcb->VcbCondition != VcbMounted) &&
    00447             (Vcb->VcbCondition != VcbMountInProgress) &&
    00448             FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS )) {
    00449
    00450             UdfAcquireUdfData( IrpContext );
    00451             ReleaseUdfData = TRUE;
    00452         }
    00453
    00454         if (!UdfCommonClosePrivate( IrpContext, Vcb, Fcb, UserReference, TRUE )) {
    00455
    00456             //
    00457             //  If we didn't complete the request then post the request as needed.
    00458             //
    00459
    00460             UdfQueueClose( IrpContext, Fcb, UserReference, FALSE );
    00461             IrpContext = NULL;
    00462
    00463         //
    00464         //  Check whether we should be dismounting the volume and then complete
    00465         //  the request.
    00466         //
    00467
    00468         } else if (ReleaseUdfData) {
    00469
    00470             UdfCheckForDismount( IrpContext, Vcb, FALSE );
    00471         }
    00472     }
    00473
    00474     //
    00475     //  Always complete this request with STATUS_SUCCESS.
    00476     //
    00477
    00478     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00479
    00480     if (ReleaseUdfData) {
    00481
    00482         UdfReleaseUdfData( IrpContext );
    00483     }
    00484
    00485     //
    00486     //  Always return STATUS_SUCCESS for closes.
    00487     //
    00488
    00489     return STATUS_SUCCESS;
    00490 }

NTSTATUS UdfCommonCreate | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 108 of file udfs/create.c.

References ASSERT, BooleanFlagOn, DIR_ENUM_CONTEXT, FALSE, _DIR_ENUM_CONTEXT::Fid, _FCB::FileAttributes, _FILE_OBJECT::FileName, FileName, _IO_STACK_LOCATION::FileObject, FlagOn, NSR_FID::Flags, _IO_STACK_LOCATION::Flags, IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH, IRP_CONTEXT_FLAG_WAIT, NSR_FID_F_DIRECTORY, NT_SUCCESS, NTSTATUS(), NULL, _DIR_ENUM_CONTEXT::ObjectName, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _FILE_OBJECT::RelatedFileObject, _VCB::RootIndexFcb, SafeNodeType, SL_CASE_SENSITIVE, SL_OPEN_PAGING_FILE, SL_OPEN_TARGET_DIRECTORY, Status, TRUE, try_leave, TYPE_OF_OPEN, UdfAcquireFcbExclusive, UdfAcquireVcbExclusive, UdfAcquireVcbShared, UdfCandidateShortName(), UdfCleanupDirContext(), UdfCompleteRequest(), UdfDecodeFileObject(), UdfDissectName(), UdfFindDirEntry(), UdfFindPrefix(), UdfInitializeDirContext(), UdfNormalizeFileNames(), UdfOpenExistingFcb(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfRaiseStatus(), UdfReleaseFcb, UdfReleaseVcb, UDFS_NTC_FCB_DATA, UdfTeardownStructures(), UdfVerifyVcb(), UnopenedFileObject, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, VCB_STATE_LOCKED, _VCB::VcbState, _VCB::VolumeDasdFcb, and _FILE_OBJECT::Vpb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00115                    :
    00116
    00117     This is the common routine for opening a file called by both the
    00118     Fsp and Fsd threads.
    00119
    00120     The file can be opened either by name or by file Id either with or without
    00121     a relative name.  The file name field in the file object passed to this routine
    00122     contains either a unicode string or a 64 bit value which is the file Id.
    00123     If there is a related file object with a name then we will already have converted
    00124     that name to Oem.
    00125
    00126     We will store the full name for the file in the file object on a successful
    00127     open.  We will allocate a larger buffer if necessary and combine the
    00128     related and file object names.  The only exception is the relative open
    00129     when the related file object is for an OpenByFileId file.  If we need to
    00130     allocate a buffer for a case insensitive name then we allocate it at
    00131     the tail of the buffer we will store into the file object.  The upcased
    00132     portion will begin immediately after the name defined by the FileName
    00133     in the file object.
    00134
    00135     Once we have the full name in the file object we don't want to split the
    00136     name in the event of a retry.  We use a flag in the IrpContext to indicate
    00137     that the name has been split.
    00138
    00139 Arguments:
    00140
    00141     Irp - Supplies the Irp to process
    00142
    00143 Return Value:
    00144
    00145     NTSTATUS - This is the status from this open operation.
    00146
    00147 --*/
    00148
    00149 {
    00150     NTSTATUS Status = STATUS_SUCCESS;
    00151     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00152
    00153     PFILE_OBJECT FileObject;
    00154
    00155     DIR_ENUM_CONTEXT DirContext;
    00156     BOOLEAN CleanupDirContext = FALSE;
    00157
    00158     BOOLEAN FoundEntry;
    00159
    00160     PVCB Vcb;
    00161
    00162     BOOLEAN OpenByFileId;
    00163     BOOLEAN IgnoreCase;
    00164     ULONG CreateDisposition;
    00165
    00166     BOOLEAN ShortNameMatch;
    00167
    00168     BOOLEAN VolumeOpen = FALSE;
    00169
    00170     //
    00171     //  We will be acquiring and releasing file Fcb's as we move down the
    00172     //  directory tree during opens.  At any time we need to know the deepest
    00173     //  point we have traversed down in the tree in case we need to cleanup
    00174     //  any structures created here.
    00175     //
    00176     //  CurrentFcb - represents this point.  If non-null it means we have
    00177     //      acquired it and need to release it in finally clause.
    00178     //
    00179     //  NextFcb - represents the NextFcb to walk to but haven't acquired yet.
    00180     //
    00181     //  CurrentLcb - represents the name of the CurrentFcb.
    00182     //
    00183
    00184     TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject;
    00185     PFILE_OBJECT RelatedFileObject;
    00186     PCCB RelatedCcb = NULL;
    00187
    00188     PFCB NextFcb;
    00189     PFCB CurrentFcb = NULL;
    00190
    00191     PLCB CurrentLcb = NULL;
    00192
    00193     //
    00194     //  During the open we need to combine the related file object name
    00195     //  with the remaining name.  We also may need to upcase the file name
    00196     //  in order to do a case-insensitive name comparison.  We also need
    00197     //  to restore the name in the file object in the event that we retry
    00198     //  the request.  We use the following string variables to manage the
    00199     //  name.  We will can put these strings into either Unicode or Ansi
    00200     //  form.
    00201     //
    00202     //  FileName - Pointer to name as currently stored in the file
    00203     //      object.  We store the full name into the file object early in
    00204     //      the open operation.
    00205     //
    00206     //  RelatedFileName - Pointer to the name in the related file object.
    00207     //
    00208     //  RemainingName - String containing remaining name to parse.
    00209     //
    00210
    00211     PUNICODE_STRING FileName;
    00212     PUNICODE_STRING RelatedFileName;
    00213
    00214     UNICODE_STRING RemainingName;
    00215     UNICODE_STRING FinalName;
    00216
    00217     PAGED_CODE();
    00218
    00219     //
    00220     //  If we were called with our file system device object instead of a
    00221     //  volume device object, just complete this request with STATUS_SUCCESS.
    00222     //
    00223
    00224     if (IrpContext->Vcb == NULL) {
    00225
    00226         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00227         return STATUS_SUCCESS;
    00228     }
    00229
    00230     //
    00231     //  Get create parameters from the Irp.
    00232     //
    00233
    00234     OpenByFileId = BooleanFlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID );
    00235     IgnoreCase = !BooleanFlagOn( IrpSp->Flags, SL_CASE_SENSITIVE );
    00236     CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
    00237
    00238     //
    00239     //  Do some preliminary checks to make sure the operation is supported.
    00240     //  We fail in the following cases immediately.
    00241     //
    00242     //      - Open a paging file.
    00243     //      - Open a target directory.
    00244     //      - Open a file with Eas.
    00245     //      - Create a file.
    00246     //
    00247
    00248     if (FlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE | SL_OPEN_TARGET_DIRECTORY) ||
    00249         (IrpSp->Parameters.Create.EaLength != 0) ||
    00250         (CreateDisposition == FILE_CREATE)) {
    00251
    00252         UdfCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );
    00253         return STATUS_ACCESS_DENIED;
    00254     }
    00255
    00256     //
    00257     //  Copy the Vcb to a local.  Assume the starting directory is the root.
    00258     //
    00259
    00260     Vcb = IrpContext->Vcb;
    00261     NextFcb = Vcb->RootIndexFcb;
    00262
    00263     //
    00264     //  Reference our input parameters to make things easier
    00265     //
    00266
    00267     FileObject = IrpSp->FileObject;
    00268     RelatedFileObject = NULL;
    00269
    00270     FileName = &FileObject->FileName;
    00271
    00272     //
    00273     //  Set up the file object's Vpb pointer in case anything happens.
    00274     //  This will allow us to get a reasonable pop-up.
    00275     //
    00276
    00277     if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) {
    00278
    00279         RelatedFileObject = FileObject->RelatedFileObject;
    00280         FileObject->Vpb = RelatedFileObject->Vpb;
    00281
    00282         RelatedTypeOfOpen = UdfDecodeFileObject( RelatedFileObject, &NextFcb, &RelatedCcb );
    00283
    00284         //
    00285         //  Fail the request if this is not a user file object.
    00286         //
    00287
    00288         if (RelatedTypeOfOpen < UserVolumeOpen) {
    00289
    00290             UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00291             return STATUS_INVALID_PARAMETER;
    00292         }
    00293
    00294         //
    00295         //  Remember the name in the related file object.
    00296         //
    00297
    00298         RelatedFileName = &RelatedFileObject->FileName;
    00299     }
    00300
    00301     //
    00302     //  If we haven't initialized the names then make sure the strings are valid.
    00303     //  If this an OpenByFileId then verify the file id buffer.
    00304     //
    00305     //  After this routine returns we know that the full name is in the
    00306     //  FileName buffer and the buffer will hold the upcased portion
    00307     //  of the name yet to parse immediately after the full name in the
    00308     //  buffer.  Any trailing backslash has been removed and the flag
    00309     //  in the IrpContext will indicate whether we removed the
    00310     //  backslash.
    00311     //
    00312
    00313     Status = UdfNormalizeFileNames( IrpContext,
    00314                                     Vcb,
    00315                                     OpenByFileId,
    00316                                     IgnoreCase,
    00317                                     RelatedTypeOfOpen,
    00318                                     RelatedCcb,
    00319                                     RelatedFileName,
    00320                                     FileName,
    00321                                     &RemainingName );
    00322
    00323     //
    00324     //  Return the error code if not successful.
    00325     //
    00326
    00327     if (!NT_SUCCESS( Status )) {
    00328
    00329         UdfCompleteRequest( IrpContext, Irp, Status );
    00330         return Status;
    00331     }
    00332
    00333     //
    00334     //  We want to acquire the Vcb.  Exclusively for a volume open, shared otherwise.
    00335     //  The file name is empty for a volume open.
    00336     //
    00337
    00338     if ((FileName->Length == 0) &&
    00339         (RelatedTypeOfOpen <= UserVolumeOpen) &&
    00340         !OpenByFileId) {
    00341
    00342         VolumeOpen = TRUE;
    00343         UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00344
    00345     } else {
    00346
    00347         UdfAcquireVcbShared( IrpContext, Vcb, FALSE );
    00348     }
    00349
    00350     //
    00351     //  Use a try-finally to facilitate cleanup.
    00352     //
    00353
    00354     try {
    00355
    00356         //
    00357         //  Verify that the Vcb is not in an unusable condition.  This routine
    00358         //  will raise if not usable.
    00359         //
    00360
    00361         UdfVerifyVcb( IrpContext, Vcb );
    00362
    00363         //
    00364         //  If the Vcb is locked then we cannot open another file
    00365         //
    00366
    00367         if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
    00368
    00369             try_leave( Status = STATUS_ACCESS_DENIED );
    00370         }
    00371
    00372         //
    00373         //  If we are opening this file by FileId then process this immediately
    00374         //  and exit.
    00375         //
    00376
    00377         if (OpenByFileId) {
    00378
    00379             //
    00380             //  The only create disposition we allow is OPEN.
    00381             //
    00382
    00383             if ((CreateDisposition != FILE_OPEN) &&
    00384                 (CreateDisposition != FILE_OPEN_IF)) {
    00385
    00386                 try_leave( Status = STATUS_ACCESS_DENIED );
    00387             }
    00388
    00389             try_leave( Status = UdfOpenObjectByFileId( IrpContext,
    00390                                                        IrpSp,
    00391                                                        Vcb,
    00392                                                        &CurrentFcb ));
    00393         }
    00394
    00395         //
    00396         //  If we are opening this volume Dasd then process this immediately
    00397         //  and exit.
    00398         //
    00399
    00400         if (VolumeOpen) {
    00401
    00402             //
    00403             //  The only create disposition we allow is OPEN.
    00404             //
    00405
    00406             if ((CreateDisposition != FILE_OPEN) &&
    00407                 (CreateDisposition != FILE_OPEN_IF)) {
    00408
    00409                 try_leave( Status = STATUS_ACCESS_DENIED );
    00410             }
    00411
    00412             //
    00413             //  If they wanted to open a directory, surprise.
    00414             //
    00415
    00416             if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
    00417
    00418                 try_leave( Status = STATUS_NOT_A_DIRECTORY );
    00419             }
    00420
    00421             //
    00422             //  Acquire the Fcb first.
    00423             //
    00424
    00425             CurrentFcb = Vcb->VolumeDasdFcb;
    00426             UdfAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE );
    00427
    00428             try_leave( Status = UdfOpenExistingFcb( IrpContext,
    00429                                                     IrpSp,
    00430                                                     &CurrentFcb,
    00431                                                     NULL,
    00432                                                     UserVolumeOpen,
    00433                                                     FALSE,
    00434                                                     NULL ));
    00435         }
    00436
    00437         //
    00438         //  Acquire the Fcb at the beginning of our search to keep it from being
    00439         //  deleted beneath us.
    00440         //
    00441
    00442         UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
    00443         CurrentFcb = NextFcb;
    00444
    00445         //
    00446         //  Do a prefix search if there is more of the name to parse.
    00447         //
    00448
    00449         if (RemainingName.Length != 0) {
    00450
    00451             //
    00452             //  Do the prefix search to find the longest matching name.
    00453             //
    00454
    00455             CurrentLcb = UdfFindPrefix( IrpContext,
    00456                                         &CurrentFcb,
    00457                                         &RemainingName,
    00458                                         IgnoreCase );
    00459         }
    00460
    00461         //
    00462         //  At this point CurrentFcb points at the lowest Fcb in the tree for this
    00463         //  file name, CurrentLcb is that name, and RemainingName is the rest of the
    00464         //  name we have to do any directory traversals for.
    00465         //
    00466
    00467         //
    00468         //  If the remaining name length is zero then we have found our
    00469         //  target.
    00470         //
    00471
    00472         if (RemainingName.Length == 0) {
    00473
    00474             //
    00475             //  If this is a file so verify the user didn't want to open
    00476             //  a directory.
    00477             //
    00478
    00479             if (SafeNodeType( CurrentFcb ) == UDFS_NTC_FCB_DATA) {
    00480
    00481                 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
    00482                     FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
    00483
    00484                     try_leave( Status = STATUS_NOT_A_DIRECTORY );
    00485                 }
    00486
    00487                 //
    00488                 //  The only create disposition we allow is OPEN.
    00489                 //
    00490
    00491                 if ((CreateDisposition != FILE_OPEN) &&
    00492                     (CreateDisposition != FILE_OPEN_IF)) {
    00493
    00494                     try_leave( Status = STATUS_ACCESS_DENIED );
    00495                 }
    00496
    00497                 try_leave( Status = UdfOpenExistingFcb( IrpContext,
    00498                                                          IrpSp,
    00499                                                          &CurrentFcb,
    00500                                                          CurrentLcb,
    00501                                                          UserFileOpen,
    00502                                                          IgnoreCase,
    00503                                                          RelatedCcb ));
    00504
    00505             //
    00506             //  This is a directory.  Verify the user didn't want to open
    00507             //  as a file.
    00508             //
    00509
    00510             } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
    00511
    00512                 try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );
    00513
    00514             //
    00515             //  Open the file as a directory.
    00516             //
    00517
    00518             } else {
    00519
    00520                 //
    00521                 //  The only create disposition we allow is OPEN.
    00522                 //
    00523
    00524                 if ((CreateDisposition != FILE_OPEN) &&
    00525                     (CreateDisposition != FILE_OPEN_IF)) {
    00526
    00527                     try_leave( Status = STATUS_ACCESS_DENIED );
    00528                 }
    00529
    00530                 try_leave( Status = UdfOpenExistingFcb( IrpContext,
    00531                                                          IrpSp,
    00532                                                          &CurrentFcb,
    00533                                                          CurrentLcb,
    00534                                                          UserDirectoryOpen,
    00535                                                          IgnoreCase,
    00536                                                          RelatedCcb ));
    00537             }
    00538         }
    00539
    00540         //
    00541         //  We have more work to do.  We have a starting Fcb which we own shared.
    00542         //  We also have the remaining name to parse.  Walk through the name
    00543         //  component by component looking for the full name.
    00544         //
    00545
    00546         //
    00547         //  Our starting Fcb better be a directory.
    00548         //
    00549
    00550         if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
    00551
    00552             try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
    00553         }
    00554
    00555         //
    00556         //  If we can't wait then post this request.
    00557         //
    00558
    00559         if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00560
    00561             UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00562         }
    00563
    00564         //
    00565         //  Prepare the enumeration context for use.
    00566         //
    00567
    00568         UdfInitializeDirContext( IrpContext, &DirContext );
    00569         CleanupDirContext = TRUE;
    00570
    00571         while (TRUE) {
    00572
    00573             ShortNameMatch = FALSE;
    00574
    00575             //
    00576             //  Split off the next component from the name.
    00577             //
    00578
    00579             UdfDissectName( IrpContext,
    00580                             &RemainingName,
    00581                             &FinalName );
    00582
    00583             //
    00584             //  Go ahead and look this entry up in the directory.
    00585             //
    00586
    00587             FoundEntry = UdfFindDirEntry( IrpContext,
    00588                                           CurrentFcb,
    00589                                           &FinalName,
    00590                                           IgnoreCase,
    00591                                           FALSE,
    00592                                           &DirContext );
    00593
    00594             //
    00595             //  If we didn't find the entry then check if the current name
    00596             //  is a possible short name.
    00597             //
    00598
    00599             if (!FoundEntry && UdfCandidateShortName( IrpContext, &FinalName)) {
    00600
    00601                 //
    00602                 //  If the name looks like it could be a short name, try to find
    00603                 //  a matching real directory entry.
    00604                 //
    00605
    00606                 ShortNameMatch =
    00607                 FoundEntry = UdfFindDirEntry( IrpContext,
    00608                                               CurrentFcb,
    00609                                               &FinalName,
    00610                                               IgnoreCase,
    00611                                               TRUE,
    00612                                               &DirContext );
    00613             }
    00614
    00615             //
    00616             //  If we didn't find a match then check what the caller was trying to do to
    00617             //  determine which error code to return.
    00618             //
    00619
    00620             if (!FoundEntry) {
    00621
    00622                 if ((CreateDisposition == FILE_OPEN) ||
    00623                     (CreateDisposition == FILE_OVERWRITE)) {
    00624
    00625                     try_leave( Status = STATUS_OBJECT_NAME_NOT_FOUND );
    00626                 }
    00627
    00628                 //
    00629                 //  Any other operation return STATUS_ACCESS_DENIED.
    00630                 //
    00631
    00632                 try_leave( Status = STATUS_ACCESS_DENIED );
    00633             }
    00634
    00635             //
    00636             //  If this is an ignore case open then copy the exact case
    00637             //  in the file object name.
    00638             //
    00639
    00640             if (IgnoreCase && !ShortNameMatch) {
    00641
    00642                 ASSERT( FinalName.Length == DirContext.ObjectName.Length );
    00643
    00644                 RtlCopyMemory( FinalName.Buffer,
    00645                                DirContext.ObjectName.Buffer,
    00646                                DirContext.ObjectName.Length );
    00647             }
    00648
    00649             //
    00650             //  If we have found the last component then break out to open for the caller.
    00651             //
    00652
    00653             if (RemainingName.Length == 0) {
    00654
    00655                 break;
    00656             }
    00657
    00658             //
    00659             //  The object we just found must be a directory.
    00660             //
    00661
    00662             if (!FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
    00663
    00664                 try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
    00665             }
    00666
    00667             //
    00668             //  Now open an Fcb for this intermediate index Fcb.
    00669             //
    00670
    00671             UdfOpenObjectFromDirContext( IrpContext,
    00672                                          IrpSp,
    00673                                          Vcb,
    00674                                          &CurrentFcb,
    00675                                          ShortNameMatch,
    00676                                          IgnoreCase,
    00677                                          &DirContext,
    00678                                          FALSE,
    00679                                          NULL );
    00680         }
    00681
    00682         //
    00683         //  Make sure our opener is about to get what they expect.
    00684         //
    00685
    00686         if ((FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
    00687              FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) &&
    00688             !FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
    00689
    00690             try_leave( Status = STATUS_NOT_A_DIRECTORY );
    00691
    00692         }
    00693
    00694         if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE ) &&
    00695             FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {
    00696
    00697             try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );
    00698         }
    00699
    00700         //
    00701         //  The only create disposition we allow is OPEN.
    00702         //
    00703
    00704         if ((CreateDisposition != FILE_OPEN) &&
    00705             (CreateDisposition != FILE_OPEN_IF)) {
    00706
    00707             try_leave( Status = STATUS_ACCESS_DENIED );
    00708         }
    00709
    00710         //
    00711         //  Open the object for the caller.
    00712         //
    00713
    00714         try_leave( Status = UdfOpenObjectFromDirContext( IrpContext,
    00715                                                          IrpSp,
    00716                                                          Vcb,
    00717                                                          &CurrentFcb,
    00718                                                          ShortNameMatch,
    00719                                                          IgnoreCase,
    00720                                                          &DirContext,
    00721                                                          TRUE,
    00722                                                          RelatedCcb ));
    00723     } finally {
    00724
    00725         //
    00726         //  Cleanup the enumeration context if initialized.
    00727         //
    00728
    00729         if (CleanupDirContext) {
    00730
    00731             UdfCleanupDirContext( IrpContext, &DirContext );
    00732         }
    00733
    00734         //
    00735         //  The result of this open could be success, pending or some error
    00736         //  condition.
    00737         //
    00738
    00739         if (AbnormalTermination()) {
    00740
    00741
    00742             //
    00743             //  In the error path we start by calling our teardown routine if we
    00744             //  have a CurrentFcb.
    00745             //
    00746
    00747             if (CurrentFcb != NULL) {
    00748
    00749                 BOOLEAN RemovedFcb;
    00750
    00751                 UdfTeardownStructures( IrpContext, CurrentFcb, FALSE, &RemovedFcb );
    00752
    00753                 if (RemovedFcb) {
    00754
    00755                     CurrentFcb = NULL;
    00756                 }
    00757             }
    00758
    00759             //
    00760             //  No need to complete the request.
    00761             //
    00762
    00763             IrpContext = NULL;
    00764             Irp = NULL;
    00765
    00766         //
    00767         //  If we posted this request through the oplock package we need
    00768         //  to show that there is no reason to complete the request.
    00769         //
    00770
    00771         } else if (Status == STATUS_PENDING) {
    00772
    00773             IrpContext = NULL;
    00774             Irp = NULL;
    00775         }
    00776
    00777         //
    00778         //  Release the Current Fcb if still acquired.
    00779         //
    00780
    00781         if (CurrentFcb != NULL) {
    00782
    00783             UdfReleaseFcb( IrpContext, CurrentFcb );
    00784         }
    00785
    00786         //
    00787         //  Release the Vcb.
    00788         //
    00789
    00790         UdfReleaseVcb( IrpContext, Vcb );
    00791
    00792         //
    00793         //  Call our completion routine.  It will handle the case where either
    00794         //  the Irp and/or IrpContext are gone.
    00795         //
    00796
    00797         UdfCompleteRequest( IrpContext, Irp, Status );
    00798     }
    00799
    00800     return Status;
    00801 }

NTSTATUS UdfCommonDevControl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 69 of file udfs/devctrl.c.

References _IRP::AssociatedIrp, _IO_STACK_LOCATION::FileObject, IoCallDriver, IoCopyCurrentIrpStackLocationToNext, IoGetCurrentIrpStackLocation, IoSetCompletionRoutine, _IRP::IoStatus, Irp, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, Status, TRUE, TYPE_OF_OPEN, UdfCompleteRequest(), UdfDecodeFileObject(), UdfDevCtrlCompletionRoutine(), UdfDvdReadStructure(), UdfDvdTransferKey(), UdfVerifyVcb(), UserFileOpen, UserVolumeOpen, and _FCB::Vcb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00076                    :
    00077
    00078     This is the common routine for doing Device control operations called
    00079     by both the fsd and fsp threads
    00080
    00081 Arguments:
    00082
    00083     Irp - Supplies the Irp to process
    00084
    00085 Return Value:
    00086
    00087     NTSTATUS - The return status for the operation
    00088
    00089 --*/
    00090
    00091 {
    00092     NTSTATUS Status;
    00093
    00094     TYPE_OF_OPEN TypeOfOpen;
    00095     PFCB Fcb;
    00096     PCCB Ccb;
    00097
    00098     PIO_STACK_LOCATION IrpSp;
    00099
    00100     PVOID TargetBuffer;
    00101
    00102     PAGED_CODE();
    00103
    00104     //
    00105     //  Extract and decode the file object.
    00106     //
    00107
    00108     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00109
    00110     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject,
    00111                                       &Fcb,
    00112                                       &Ccb );
    00113
    00114     //
    00115     //  A few IOCTLs actually require some intervention on our part to
    00116     //  translate some information from file-based to device-based units.
    00117     //
    00118
    00119     if (TypeOfOpen == UserFileOpen) {
    00120
    00121         switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
    00122             case IOCTL_DVD_READ_KEY:
    00123             case IOCTL_DVD_SEND_KEY:
    00124
    00125                 Status = UdfDvdTransferKey( IrpContext, Irp, Fcb );
    00126                 break;
    00127
    00128             case IOCTL_DVD_READ_STRUCTURE:
    00129
    00130                 Status = UdfDvdReadStructure( IrpContext, Irp, Fcb );
    00131                 break;
    00132
    00133             case IOCTL_STORAGE_SET_READ_AHEAD:
    00134
    00135                 //
    00136                 //  We're just going to no-op this for now.
    00137                 //
    00138
    00139                 Status = STATUS_SUCCESS;
    00140                 UdfCompleteRequest( IrpContext, Irp, Status );
    00141                 break;
    00142
    00143             default:
    00144
    00145                 Status = STATUS_INVALID_PARAMETER;
    00146                 UdfCompleteRequest( IrpContext, Irp, Status );
    00147                 break;
    00148         }
    00149
    00150         return Status;
    00151     }
    00152
    00153     //
    00154     //  Now the only type of opens we accept are user volume opens.
    00155     //
    00156
    00157     if (TypeOfOpen != UserVolumeOpen) {
    00158
    00159         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00160         return STATUS_INVALID_PARAMETER;
    00161     }
    00162
    00163     //
    00164     //  Handle the case of the disk type ourselves.  We're really just going to
    00165     //  lie about this, but it is a good lie.
    00166     //
    00167
    00168     if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {
    00169
    00170         //
    00171         //  Verify the Vcb in this case to detect if the volume has changed.
    00172         //
    00173
    00174         UdfVerifyVcb( IrpContext, Fcb->Vcb );
    00175
    00176         //
    00177         //  Check the size of the output buffer.
    00178         //
    00179
    00180         if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {
    00181
    00182             UdfCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
    00183             return STATUS_BUFFER_TOO_SMALL;
    00184         }
    00185
    00186         //
    00187         //  Copy the data from the Vcb.
    00188         //
    00189
    00190         ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = CDROM_DISK_DATA_TRACK;
    00191
    00192         Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
    00193         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00194         return STATUS_SUCCESS;
    00195     }
    00196
    00197     //
    00198     //  Copy the arguments and set up the completion routine
    00199     //
    00200
    00201     IoCopyCurrentIrpStackLocationToNext( Irp );
    00202
    00203     IoSetCompletionRoutine( Irp,
    00204                             UdfDevCtrlCompletionRoutine,
    00205                             NULL,
    00206                             TRUE,
    00207                             TRUE,
    00208                             TRUE );
    00209
    00210     //
    00211     //  Send the request.
    00212     //
    00213
    00214     Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
    00215
    00216     //
    00217     //  Cleanup our Irp Context.  The driver has completed the Irp.
    00218     //
    00219
    00220     UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
    00221
    00222     return Status;
    00223 }

NTSTATUS UdfCommonDirControl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 255 of file dirctrl.c.

References _IO_STACK_LOCATION::FileObject, IoGetCurrentIrpStackLocation, Irp, IRP_MN_NOTIFY_CHANGE_DIRECTORY, IRP_MN_QUERY_DIRECTORY, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), PAGED_CODE, Status, UdfCompleteRequest(), UdfDecodeFileObject(), UdfNotifyChangeDirectory(), UdfQueryDirectory(), and UserDirectoryOpen.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00262                    :
    00263
    00264     This routine is the entry point for the directory control operations.  These
    00265     are directory enumerations and directory notify calls.  We verify the
    00266     user's handle is for a directory and then call the appropriate routine.
    00267
    00268 Arguments:
    00269
    00270     Irp - Irp for this request.
    00271
    00272 Return Value:
    00273
    00274     NTSTATUS - Status returned from the lower level routines.
    00275
    00276 --*/
    00277
    00278 {
    00279     NTSTATUS Status;
    00280     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00281
    00282     PFCB Fcb;
    00283     PCCB Ccb;
    00284
    00285     PAGED_CODE();
    00286
    00287     //
    00288     //  Decode the user file object and fail this request if it is not
    00289     //  a user directory.
    00290     //
    00291
    00292     if (UdfDecodeFileObject( IrpSp->FileObject,
    00293                              &Fcb,
    00294                              &Ccb ) != UserDirectoryOpen) {
    00295
    00296         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00297         return STATUS_INVALID_PARAMETER;
    00298     }
    00299
    00300     //
    00301     //  We know this is a directory control so we'll case on the
    00302     //  minor function, and call a internal worker routine to complete
    00303     //  the irp.
    00304     //
    00305
    00306     switch (IrpSp->MinorFunction) {
    00307
    00308     case IRP_MN_QUERY_DIRECTORY:
    00309
    00310         Status = UdfQueryDirectory( IrpContext, Irp, IrpSp, Fcb, Ccb );
    00311         break;
    00312
    00313     case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
    00314
    00315         Status = UdfNotifyChangeDirectory( IrpContext, Irp, IrpSp, Ccb );
    00316         break;
    00317
    00318     default:
    00319
    00320         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
    00321         Status = STATUS_INVALID_DEVICE_REQUEST;
    00322         break;
    00323     }
    00324
    00325     return Status;
    00326 }

NTSTATUS UdfCommonFsControl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 283 of file udfs/fsctrl.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, IoGetCurrentIrpStackLocation, Irp, IRP_MN_MOUNT_VOLUME, IRP_MN_USER_FS_REQUEST, IRP_MN_VERIFY_VOLUME, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), PAGED_CODE, Status, UdfCompleteRequest(), UdfMountVolume(), UdfUserFsctl(), and UdfVerifyVolume().

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00290                    :
    00291
    00292     This is the common routine for doing FileSystem control operations called
    00293     by both the fsd and fsp threads
    00294
    00295 Arguments:
    00296
    00297     Irp - Supplies the Irp to process
    00298
    00299 Return Value:
    00300
    00301     NTSTATUS - The return status for the operation
    00302
    00303 --*/
    00304
    00305 {
    00306     NTSTATUS Status;
    00307     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00308
    00309     PAGED_CODE();
    00310
    00311     //
    00312     //  Check the input parameters
    00313     //
    00314
    00315     ASSERT_IRP_CONTEXT( IrpContext );
    00316     ASSERT_IRP( Irp );
    00317
    00318     //
    00319     //  Get a pointer to the current Irp stack location
    00320     //
    00321
    00322     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00323
    00324     //
    00325     //  We know this is a file system control so we'll case on the
    00326     //  minor function, and call a internal worker routine to complete
    00327     //  the irp.
    00328     //
    00329
    00330     switch (IrpSp->MinorFunction) {
    00331
    00332     case IRP_MN_MOUNT_VOLUME:
    00333
    00334         Status = UdfMountVolume( IrpContext, Irp );
    00335         break;
    00336
    00337     case IRP_MN_VERIFY_VOLUME:
    00338
    00339         Status = UdfVerifyVolume( IrpContext, Irp );
    00340         break;
    00341
    00342     case IRP_MN_USER_FS_REQUEST:
    00343
    00344         Status = UdfUserFsctl( IrpContext, Irp );
    00345         break;
    00346
    00347     default:
    00348
    00349         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
    00350         Status = STATUS_INVALID_DEVICE_REQUEST;
    00351         break;
    00352     }
    00353
    00354     return Status;
    00355 }

NTSTATUS UdfCommonLockControl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 46 of file lockctrl.c.

References _IO_STACK_LOCATION::FileObject, FsRtlCheckOplock(), FsRtlProcessFileLock(), IoGetCurrentIrpStackLocation, Irp, NTSTATUS(), NULL, PAGED_CODE, Status, TRUE, TYPE_OF_OPEN, UdfCompleteRequest(), UdfCreateFileLock(), UdfDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfOplockComplete(), UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00053                    :
    00054
    00055     This is the common routine for Lock Control called by both the fsd and fsp
    00056     threads.
    00057
    00058 Arguments:
    00059
    00060     Irp - Supplies the Irp to process
    00061
    00062 Return Value:
    00063
    00064     NTSTATUS - The return status for the operation
    00065
    00066 --*/
    00067
    00068 {
    00069     NTSTATUS Status;
    00070     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00071
    00072     TYPE_OF_OPEN TypeOfOpen;
    00073     PFCB Fcb;
    00074     PCCB Ccb;
    00075
    00076     PAGED_CODE();
    00077
    00078     //
    00079     //  Extract and decode the type of file object we're being asked to process
    00080     //
    00081
    00082     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    00083
    00084     //
    00085     //  If the file is not a user file open then we reject the request
    00086     //  as an invalid parameter
    00087     //
    00088
    00089     if (TypeOfOpen != UserFileOpen) {
    00090
    00091         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00092         return STATUS_INVALID_PARAMETER;
    00093     }
    00094
    00095     //
    00096     //  We check whether we can proceed based on the state of the file oplocks.
    00097     //  This call might post the irp for us.
    00098     //
    00099
    00100     Status = FsRtlCheckOplock( &Fcb->Oplock,
    00101                                Irp,
    00102                                IrpContext,
    00103                                UdfOplockComplete,
    00104                                NULL );
    00105
    00106     //
    00107     //  If we don't get success then the oplock package completed the request.
    00108     //
    00109
    00110     if (Status != STATUS_SUCCESS) {
    00111
    00112         return Status;
    00113     }
    00114
    00115     //
    00116     //  Verify the Fcb.
    00117     //
    00118
    00119     UdfVerifyFcbOperation( IrpContext, Fcb );
    00120
    00121     //
    00122     //  If we don't have a file lock, then get one now.
    00123     //
    00124
    00125     if (Fcb->FileLock == NULL) { UdfCreateFileLock( IrpContext, Fcb, TRUE ); }
    00126
    00127     //
    00128     //  Now call the FsRtl routine to do the actual processing of the
    00129     //  Lock request
    00130     //
    00131
    00132     Status = FsRtlProcessFileLock( Fcb->FileLock, Irp, NULL );
    00133
    00134     //
    00135     //  Set the flag indicating if Fast I/O is possible
    00136     //
    00137
    00138     UdfLockFcb( IrpContext, Fcb );
    00139     Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00140     UdfUnlockFcb( IrpContext, Fcb );
    00141
    00142     //
    00143     //  Complete the request.
    00144     //
    00145
    00146     UdfCompleteRequest( IrpContext, NULL, Status );
    00147     return Status;
    00148 }

NTSTATUS UdfCommonPnp | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 75 of file udfs/pnp.c.

References _VOLUME_DEVICE_OBJECT::DeviceObject, _IO_STACK_LOCATION::DeviceObject, IoCallDriver, IoGetCurrentIrpStackLocation, IoSkipCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_WAIT, IRP_MN_CANCEL_REMOVE_DEVICE, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE, IRP_MN_SURPRISE_REMOVAL, _IO_STACK_LOCATION::MinorFunction, NodeType, NTSTATUS(), NULL, SetFlag, _DEVICE_OBJECT::Size, Status, _VCB::TargetDeviceObject, UdfCompleteRequest(), UdfPnpCancelRemove(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UDFS_NTC_VCB, and _VOLUME_DEVICE_OBJECT::Vcb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00082                    :
    00083
    00084     This is the common routine for doing PnP operations called
    00085     by both the fsd and fsp threads
    00086
    00087 Arguments:
    00088
    00089     Irp - Supplies the Irp to process
    00090
    00091 Return Value:
    00092
    00093     NTSTATUS - The return status for the operation
    00094
    00095 --*/
    00096
    00097 {
    00098     NTSTATUS Status;
    00099
    00100     PIO_STACK_LOCATION IrpSp;
    00101
    00102     PVOLUME_DEVICE_OBJECT OurDeviceObject;
    00103     PVCB Vcb;
    00104
    00105     //
    00106     //  Get the current Irp stack location.
    00107     //
    00108
    00109     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00110
    00111     //
    00112     //  Find our Vcb.  This is tricky since we have no file object in the Irp.
    00113     //
    00114
    00115     OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject;
    00116
    00117     //
    00118     //  Make sure this device object really is big enough to be a volume device
    00119     //  object.  If it isn't, we need to get out before we try to reference some
    00120     //  field that takes us past the end of an ordinary device object.
    00121     //
    00122
    00123     if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) ||
    00124         NodeType( &OurDeviceObject->Vcb ) != UDFS_NTC_VCB) {
    00125
    00126         //
    00127         //  We were called with something we don't understand.
    00128         //
    00129
    00130         Status = STATUS_INVALID_PARAMETER;
    00131         UdfCompleteRequest( IrpContext, Irp, Status );
    00132         return Status;
    00133     }
    00134
    00135     //
    00136     //  Force all PnP operations to be synchronous.
    00137     //
    00138
    00139     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    00140
    00141     Vcb = &OurDeviceObject->Vcb;
    00142
    00143     //
    00144     //  Case on the minor code.
    00145     //
    00146
    00147     switch ( IrpSp->MinorFunction ) {
    00148
    00149         case IRP_MN_QUERY_REMOVE_DEVICE:
    00150
    00151             Status = UdfPnpQueryRemove( IrpContext, Irp, Vcb );
    00152             break;
    00153
    00154         case IRP_MN_SURPRISE_REMOVAL:
    00155
    00156             Status = UdfPnpSurpriseRemove( IrpContext, Irp, Vcb );
    00157             break;
    00158
    00159         case IRP_MN_REMOVE_DEVICE:
    00160
    00161             Status = UdfPnpRemove( IrpContext, Irp, Vcb );
    00162             break;
    00163
    00164         case IRP_MN_CANCEL_REMOVE_DEVICE:
    00165
    00166             Status = UdfPnpCancelRemove( IrpContext, Irp, Vcb );
    00167             break;
    00168
    00169         default:
    00170
    00171             //
    00172             //  Just pass the IRP on.  As we do not need to be in the
    00173             //  way on return, ellide ourselves out of the stack.
    00174             //
    00175
    00176             IoSkipCurrentIrpStackLocation( Irp );
    00177
    00178             Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
    00179
    00180             //
    00181             //  Cleanup our Irp Context.  The driver has completed the Irp.
    00182             //
    00183
    00184             UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
    00185
    00186             break;
    00187     }
    00188
    00189     return Status;
    00190 }

NTSTATUS UdfCommonQueryInfo | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 156 of file fileinfo.c.

References ASSERT, _IRP::AssociatedIrp, Buffer, CCB_FLAG_OPEN_BY_ID, FALSE, FCB_STATE_INITIALIZED, _FCB::FcbState, _IO_STACK_LOCATION::FileObject, FlagOn, _CCB::Flags, IoGetCurrentIrpStackLocation, _IRP::IoStatus, Irp, NTSTATUS(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, Status, TRUE, TYPE_OF_OPEN, UdfAcquireFileShared, UdfCompleteRequest(), UdfDecodeFileObject(), UdfQueryAlternateNameInfo(), UdfQueryBasicInfo(), UdfQueryEaInfo(), UdfQueryInternalInfo(), UdfQueryNameInfo(), UdfQueryNetworkInfo(), UdfQueryPositionInfo(), UdfQueryStandardInfo(), UdfReleaseFile, UdfVerifyFcbOperation(), UserDirectoryOpen, and UserFileOpen.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00163                    :
    00164
    00165     This is the common routine for query file information called by both the
    00166     fsd and fsp threads.
    00167
    00168 Arguments:
    00169
    00170     Irp - Supplies the Irp to process.
    00171
    00172 Return Value:
    00173
    00174     NTSTATUS - The return status for this operation.
    00175
    00176 --*/
    00177
    00178 {
    00179     NTSTATUS Status = STATUS_SUCCESS;
    00180     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00181
    00182     ULONG Length;
    00183     FILE_INFORMATION_CLASS FileInformationClass;
    00184     PFILE_ALL_INFORMATION Buffer;
    00185
    00186     TYPE_OF_OPEN TypeOfOpen;
    00187     PFCB Fcb;
    00188     PCCB Ccb;
    00189
    00190     BOOLEAN ReleaseFcb = FALSE;
    00191
    00192     PAGED_CODE();
    00193
    00194     //
    00195     //  Reference our input parameters to make things easier
    00196     //
    00197
    00198     Length = IrpSp->Parameters.QueryFile.Length;
    00199     FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
    00200     Buffer = Irp->AssociatedIrp.SystemBuffer;
    00201
    00202     //
    00203     //  Decode the file object
    00204     //
    00205
    00206     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    00207
    00208     //
    00209     //  Use a try-finally to facilitate cleanup.
    00210     //
    00211
    00212     try {
    00213
    00214         //
    00215         //  We only support query on file and directory handles.
    00216         //
    00217
    00218         switch (TypeOfOpen) {
    00219
    00220         case UserDirectoryOpen :
    00221         case UserFileOpen :
    00222
    00223             //
    00224             //  Acquire shared access to this file.
    00225             //
    00226
    00227             UdfAcquireFileShared( IrpContext, Fcb );
    00228             ReleaseFcb = TRUE;
    00229
    00230             ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ));
    00231
    00232             //
    00233             //  Make sure the Fcb is in a usable condition.  This will raise
    00234             //  an error condition if the volume is unusable
    00235             //
    00236
    00237             UdfVerifyFcbOperation( IrpContext, Fcb );
    00238
    00239             //
    00240             //  Based on the information class we'll do different
    00241             //  actions.  Each of hte procedures that we're calling fills
    00242             //  up the output buffer, if possible.  They will raise the
    00243             //  status STATUS_BUFFER_OVERFLOW for an insufficient buffer.
    00244             //  This is considered a somewhat unusual case and is handled
    00245             //  more cleanly with the exception mechanism rather than
    00246             //  testing a return status value for each call.
    00247             //
    00248
    00249             switch (FileInformationClass) {
    00250
    00251             case FileAllInformation:
    00252
    00253                 //
    00254                 //  We don't allow this operation on a file opened by file Id.
    00255                 //
    00256
    00257                 if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
    00258
    00259                     Status = STATUS_INVALID_PARAMETER;
    00260                     break;
    00261                 }
    00262
    00263                 //
    00264                 //  In this case go ahead and call the individual routines to
    00265                 //  fill in the buffer.  Only the name routine will
    00266                 //  pointer to the output buffer and then call the
    00267                 //  individual routines to fill in the buffer.
    00268                 //
    00269
    00270                 Length -= (sizeof( FILE_ACCESS_INFORMATION ) +
    00271                            sizeof( FILE_MODE_INFORMATION ) +
    00272                            sizeof( FILE_ALIGNMENT_INFORMATION ));
    00273
    00274                 UdfQueryBasicInfo( IrpContext, Fcb, Ccb, &Buffer->BasicInformation, &Length );
    00275                 UdfQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length );
    00276                 UdfQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length );
    00277                 UdfQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length );
    00278                 UdfQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length );
    00279                 Status = UdfQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length );
    00280
    00281                 break;
    00282
    00283             case FileBasicInformation:
    00284
    00285                 UdfQueryBasicInfo( IrpContext, Fcb, Ccb, (PFILE_BASIC_INFORMATION) Buffer, &Length );
    00286                 break;
    00287
    00288             case FileStandardInformation:
    00289
    00290                 UdfQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length );
    00291                 break;
    00292
    00293             case FileInternalInformation:
    00294
    00295                 UdfQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length );
    00296                 break;
    00297
    00298             case FileEaInformation:
    00299
    00300                 UdfQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length );
    00301                 break;
    00302
    00303             case FilePositionInformation:
    00304
    00305                 UdfQueryPositionInfo( IrpContext, IrpSp->FileObject, (PFILE_POSITION_INFORMATION) Buffer, &Length );
    00306                 break;
    00307
    00308             case FileNameInformation:
    00309
    00310                 //
    00311                 //  We don't allow this operation on a file opened by file Id.
    00312                 //
    00313
    00314                 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
    00315
    00316                     Status = UdfQueryNameInfo( IrpContext, IrpSp->FileObject, (PFILE_NAME_INFORMATION) Buffer, &Length );
    00317
    00318                 } else {
    00319
    00320                     Status = STATUS_INVALID_PARAMETER;
    00321                 }
    00322
    00323                 break;
    00324
    00325             case FileAlternateNameInformation:
    00326
    00327                 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
    00328
    00329                     Status = UdfQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length );
    00330
    00331                 } else {
    00332
    00333                     Status = STATUS_INVALID_PARAMETER;
    00334                 }
    00335
    00336                 break;
    00337
    00338             case FileNetworkOpenInformation:
    00339
    00340                 UdfQueryNetworkInfo( IrpContext, Fcb, Ccb, (PFILE_NETWORK_OPEN_INFORMATION) Buffer, &Length );
    00341                 break;
    00342
    00343             default :
    00344
    00345                 Status = STATUS_INVALID_PARAMETER;
    00346             }
    00347
    00348             break;
    00349
    00350         default :
    00351
    00352             Status = STATUS_INVALID_PARAMETER;
    00353         }
    00354
    00355         //
    00356         //  Set the information field to the number of bytes actually filled in
    00357         //  and then complete the request
    00358         //
    00359
    00360         Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
    00361
    00362     } finally {
    00363
    00364         //
    00365         //  Release the file.
    00366         //
    00367
    00368         if (ReleaseFcb) {
    00369
    00370             UdfReleaseFile( IrpContext, Fcb );
    00371         }
    00372     }
    00373
    00374     //
    00375     //  Complete the request if we didn't raise.
    00376     //
    00377
    00378     UdfCompleteRequest( IrpContext, Irp, Status );
    00379
    00380     return Status;
    00381 }

NTSTATUS UdfCommonQueryVolInfo | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 82 of file volinfo.c.

References _IRP::AssociatedIrp, FALSE, _IO_STACK_LOCATION::FileObject, IoGetCurrentIrpStackLocation, _IRP::IoStatus, Irp, NTSTATUS(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, Status, TYPE_OF_OPEN, UdfAcquireVcbShared, UdfCompleteRequest(), UdfDecodeFileObject(), UdfQueryFsAttributeInfo(), UdfQueryFsDeviceInfo(), UdfQueryFsSizeInfo(), UdfQueryFsVolumeInfo(), UdfReleaseVcb, UdfVerifyVcb(), UnopenedFileObject, and _FCB::Vcb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00089                    :
    00090
    00091     This is the common routine for querying volume information called by both
    00092     the fsd and fsp threads.
    00093
    00094 Arguments:
    00095
    00096     Irp - Supplies the Irp being processed
    00097
    00098 Return Value:
    00099
    00100     NTSTATUS - The return status for the operation
    00101
    00102 --*/
    00103
    00104 {
    00105     NTSTATUS Status = STATUS_INVALID_PARAMETER;
    00106     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00107
    00108     ULONG Length;
    00109
    00110     TYPE_OF_OPEN TypeOfOpen;
    00111     PFCB Fcb;
    00112     PCCB Ccb;
    00113
    00114     PAGED_CODE();
    00115
    00116     //
    00117     //  Reference our input parameters to make things easier
    00118     //
    00119
    00120     Length = IrpSp->Parameters.QueryVolume.Length;
    00121
    00122     //
    00123     //  Decode the file object and fail if this an unopened file object.
    00124     //
    00125
    00126     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    00127
    00128     if (TypeOfOpen == UnopenedFileObject) {
    00129
    00130         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00131         return STATUS_INVALID_PARAMETER;
    00132     }
    00133
    00134     //
    00135     //  Acquire the Vcb for this volume.
    00136     //
    00137
    00138     UdfAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
    00139
    00140     //
    00141     //  Use a try-finally to facilitate cleanup.
    00142     //
    00143
    00144     try {
    00145
    00146         //
    00147         //  Verify the Vcb.
    00148         //
    00149
    00150         UdfVerifyVcb( IrpContext, Fcb->Vcb );
    00151
    00152         //
    00153         //  Based on the information class we'll do different actions.  Each
    00154         //  of the procedures that we're calling fills up the output buffer
    00155         //  if possible and returns true if it successfully filled the buffer
    00156         //  and false if it couldn't wait for any I/O to complete.
    00157         //
    00158
    00159         switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
    00160
    00161         case FileFsSizeInformation:
    00162
    00163             Status = UdfQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
    00164             break;
    00165
    00166         case FileFsVolumeInformation:
    00167
    00168             Status = UdfQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
    00169             break;
    00170
    00171         case FileFsDeviceInformation:
    00172
    00173             Status = UdfQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
    00174             break;
    00175
    00176         case FileFsAttributeInformation:
    00177
    00178             Status = UdfQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
    00179             break;
    00180         }
    00181
    00182         //
    00183         //  Set the information field to the number of bytes actually filled in
    00184         //
    00185
    00186         Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
    00187
    00188     } finally {
    00189
    00190         //
    00191         //  Release the Vcb.
    00192         //
    00193
    00194         UdfReleaseVcb( IrpContext, Fcb->Vcb );
    00195     }
    00196
    00197     //
    00198     //  Complete the request if we didn't raise.
    00199     //
    00200
    00201     UdfCompleteRequest( IrpContext, Irp, Status );
    00202
    00203     return Status;
    00204 }

NTSTATUS UdfCommonRead | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 68 of file udfs/read.c.

References Add2Ptr, ASSERT, BooleanFlagOn, BytesFromSectors, _UDF_DATA::CacheManagerCallbacks, CcCopyRead(), CcInitializeCacheMap(), CcMdlRead(), CcSetReadAheadGranularity(), ClearFlag, _FILE_OBJECT::CurrentByteOffset, DebugUnwind, _FCB::EmbeddedOffset, _FCB::EmbeddedVsn, ExGetCurrentResourceThread, FALSE, FCB_STATE_EMBEDDED_DATA, _FCB::FcbState, _IO_STACK_LOCATION::FileObject, FlagOn, _FILE_OBJECT::Flags, _IRP::Flags, FO_SYNCHRONOUS_IO, FsRtlCheckLockForReadAccess(), FsRtlCheckOplock(), FsRtlNormalizeNtstatus(), IoGetCurrentIrpStackLocation, IoIsErrorUserInduced, _IRP::IoStatus, Irp, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_WAIT, IRP_MN_MDL, IRP_NOCACHE, IRP_PAGING_IO, KeInitializeEvent, _IRP::MdlAddress, _VCB::MetadataFcb, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PCC_FILE_SIZES, _FILE_OBJECT::PrivateCacheMap, READ_AHEAD_GRANULARITY, SafeZeroMemory, SectorAlign, SectorOffset, SetFlag, Status, SynchronousIo, TRUE, try_leave, TYPE_OF_OPEN, UDF_IO_CONTEXT, UdfAcquireFileShared, UdfAcquireFileSharedStarveExclusive, UdfAllocateIoContext, UdfCompleteRequest(), UdfData, UdfDecodeFileObject(), UdfFsdPostRequest(), UdfMapUserBuffer, UdfNonCachedRead(), UdfNormalizeAndRaiseStatus(), UdfOplockComplete(), UdfPrePostIrp(), UdfRaiseStatus(), UdfReleaseFile, UdfVerifyFcbOperation(), UnopenedFileObject, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, and _FCB::Vcb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00075                    :
    00076
    00077     This is the common entry point for NtReadFile calls.  For synchronous requests,
    00078     CommonRead will complete the request in the current thread.  If not
    00079     synchronous the request will be passed to the Fsp if there is a need to
    00080     block.
    00081
    00082 Arguments:
    00083
    00084     Irp - Supplies the Irp to process
    00085
    00086 Return Value:
    00087
    00088     NTSTATUS - The result of this operation.
    00089
    00090 --*/
    00091
    00092 {
    00093     NTSTATUS Status;
    00094     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00095
    00096     TYPE_OF_OPEN TypeOfOpen;
    00097     PFCB Fcb;
    00098     PCCB Ccb;
    00099     PVCB Vcb;
    00100
    00101     BOOLEAN Wait;
    00102     ULONG PagingIo;
    00103     ULONG SynchronousIo;
    00104     ULONG NonCachedIo;
    00105
    00106     LONGLONG StartingOffset;
    00107     LONGLONG ByteRange;
    00108     ULONG ByteCount;
    00109     ULONG ReadByteCount;
    00110     ULONG OriginalByteCount;
    00111
    00112     PVOID SystemBuffer, UserBuffer;
    00113
    00114     BOOLEAN ReleaseFile = TRUE;
    00115
    00116     PFILE_OBJECT MappingFileObject;
    00117
    00118     UDF_IO_CONTEXT LocalIoContext;
    00119
    00120     PAGED_CODE();
    00121
    00122     //
    00123     //  If this is a zero length read then return SUCCESS immediately.
    00124     //
    00125
    00126     if (IrpSp->Parameters.Read.Length == 0) {
    00127
    00128         UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00129         return STATUS_SUCCESS;
    00130     }
    00131
    00132     //
    00133     //  Decode the file object and verify we support read on this.  It
    00134     //  must be a user file, stream file or volume file (for a data disk).
    00135     //
    00136
    00137     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    00138
    00139     Vcb = Fcb->Vcb;
    00140
    00141     if ((TypeOfOpen == UnopenedFileObject) || (TypeOfOpen == UserDirectoryOpen)) {
    00142
    00143         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
    00144         return STATUS_INVALID_DEVICE_REQUEST;
    00145     }
    00146
    00147     //
    00148     //  Examine our input parameters to determine if this is noncached and/or
    00149     //  a paging io operation.
    00150     //
    00151
    00152     Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    00153     PagingIo = FlagOn( Irp->Flags, IRP_PAGING_IO );
    00154     NonCachedIo = FlagOn( Irp->Flags, IRP_NOCACHE );
    00155     SynchronousIo = FlagOn( IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO );
    00156
    00157     //
    00158     //  Extract the range of the Io.
    00159     //
    00160
    00161     StartingOffset = IrpSp->Parameters.Read.ByteOffset.QuadPart;
    00162     OriginalByteCount = ByteCount = IrpSp->Parameters.Read.Length;
    00163
    00164     ByteRange = StartingOffset + ByteCount;
    00165
    00166     //
    00167     //  Make sure that Dasd access is always non-cached.
    00168     //
    00169
    00170     if (TypeOfOpen == UserVolumeOpen) {
    00171
    00172         NonCachedIo = TRUE;
    00173     }
    00174
    00175     //
    00176     //  Acquire the file shared to perform the read.  If we are doing paging IO,
    00177     //  it may be the case that we would have a deadlock imminent because we may
    00178     //  block on shared access, so starve out any exclusive waiters.  This requires
    00179     //  a degree of caution - we believe that any paging IO bursts will recede and
    00180     //  allow the exclusive waiter in.
    00181     //
    00182
    00183     if (PagingIo) {
    00184
    00185         UdfAcquireFileSharedStarveExclusive( IrpContext, Fcb );
    00186
    00187     } else {
    00188
    00189         UdfAcquireFileShared( IrpContext, Fcb );
    00190     }
    00191
    00192     //
    00193     //  Use a try-finally to facilitate cleanup.
    00194     //
    00195
    00196     try {
    00197
    00198         //
    00199         //  Verify the Fcb.
    00200         //
    00201
    00202         UdfVerifyFcbOperation( IrpContext, Fcb );
    00203
    00204         //
    00205         //  If this is a user request then verify the oplock and filelock state.
    00206         //
    00207
    00208         if (TypeOfOpen == UserFileOpen) {
    00209
    00210             //
    00211             //  We check whether we can proceed
    00212             //  based on the state of the file oplocks.
    00213             //
    00214
    00215             Status = FsRtlCheckOplock( &Fcb->Oplock,
    00216                                        Irp,
    00217                                        IrpContext,
    00218                                        UdfOplockComplete,
    00219                                        UdfPrePostIrp );
    00220
    00221             //
    00222             //  If the result is not STATUS_SUCCESS then the Irp was completed
    00223             //  elsewhere.
    00224             //
    00225
    00226             if (Status != STATUS_SUCCESS) {
    00227
    00228                 Irp = NULL;
    00229                 IrpContext = NULL;
    00230
    00231                 try_leave( Status );
    00232             }
    00233
    00234             if (!PagingIo &&
    00235                 (Fcb->FileLock != NULL) &&
    00236                 !FsRtlCheckLockForReadAccess( Fcb->FileLock, Irp )) {
    00237
    00238                 try_leave( Status = STATUS_FILE_LOCK_CONFLICT );
    00239             }
    00240         }
    00241
    00242         //
    00243         //  Complete the request if it begins beyond the end of file.
    00244         //
    00245
    00246         if (StartingOffset >= Fcb->FileSize.QuadPart) {
    00247
    00248             try_leave( Status = STATUS_END_OF_FILE );
    00249         }
    00250
    00251         //
    00252         //  Truncate the read if it extends beyond the end of the file.
    00253         //
    00254
    00255         if (ByteRange > Fcb->FileSize.QuadPart) {
    00256
    00257             ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset);
    00258             ByteRange = Fcb->FileSize.QuadPart;
    00259         }
    00260
    00261         //
    00262         //  Now if the data is embedded in the ICB, map through the metadata
    00263         //  stream to retrieve the bytes.
    00264         //
    00265
    00266         if (FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA )) {
    00267
    00268             //
    00269             //  The metadata stream better be here by now.
    00270             //
    00271
    00272             ASSERT( Vcb->MetadataFcb->FileObject != NULL );
    00273
    00274             //
    00275             //  Bias our starting offset by the offset of the ICB in the metadata
    00276             //  stream plus the offset of the data bytes in that ICB.  Obviously,
    00277             //  we aren't doing non-cached IO here.
    00278             //
    00279
    00280             StartingOffset += (BytesFromSectors( Vcb, Fcb->EmbeddedVsn ) + Fcb->EmbeddedOffset);
    00281             MappingFileObject = Vcb->MetadataFcb->FileObject;
    00282             NonCachedIo = FALSE;
    00283
    00284         //
    00285         //  We are mapping through the caller's fileobject
    00286         //
    00287
    00288         } else {
    00289
    00290             MappingFileObject = IrpSp->FileObject;
    00291         }
    00292
    00293         //
    00294         //  Handle the non-cached read first.
    00295         //
    00296
    00297         if (NonCachedIo) {
    00298
    00299             //
    00300             //  If we have an unaligned transfer then post this request if
    00301             //  we can't wait.  Unaligned means that the starting offset
    00302             //  is not on a sector boundary or the read is not integral
    00303             //  sectors.
    00304             //
    00305
    00306             ReadByteCount = SectorAlign( Vcb, ByteCount );
    00307
    00308             if (SectorOffset( Vcb,  StartingOffset ) ||
    00309                 (ReadByteCount > OriginalByteCount)) {
    00310
    00311                 if (!Wait) {
    00312
    00313                     UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00314                 }
    00315
    00316                 //
    00317                 //  Make sure we don't overwrite the buffer.
    00318                 //
    00319
    00320                 ReadByteCount = ByteCount;
    00321             }
    00322
    00323             //
    00324             //  Initialize the IoContext for the read.
    00325             //  If there is a context pointer, we need to make sure it was
    00326             //  allocated and not a stale stack pointer.
    00327             //
    00328
    00329             if (IrpContext->IoContext == NULL ||
    00330                 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
    00331
    00332                 //
    00333                 //  If we can wait, use the context on the stack.  Otherwise
    00334                 //  we need to allocate one.
    00335                 //
    00336
    00337                 if (Wait) {
    00338
    00339                     IrpContext->IoContext = &LocalIoContext;
    00340                     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00341
    00342                 } else {
    00343
    00344                     IrpContext->IoContext = UdfAllocateIoContext();
    00345                     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00346                 }
    00347             }
    00348
    00349             RtlZeroMemory( IrpContext->IoContext, sizeof( UDF_IO_CONTEXT ));
    00350
    00351             //
    00352             //  Store whether we allocated this context structure in the structure
    00353             //  itself.
    00354             //
    00355
    00356             IrpContext->IoContext->AllocatedContext =
    00357                 BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00358
    00359             if (Wait) {
    00360
    00361                 KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
    00362                                    NotificationEvent,
    00363                                    FALSE );
    00364
    00365             } else {
    00366
    00367                 IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread();
    00368                 IrpContext->IoContext->Resource = Fcb->Resource;
    00369                 IrpContext->IoContext->RequestedByteCount = ByteCount;
    00370             }
    00371
    00372             Irp->IoStatus.Information = ReadByteCount;
    00373
    00374             //
    00375             //  Call the NonCacheIo routine to perform the actual read.
    00376             //
    00377
    00378             Status = UdfNonCachedRead( IrpContext, Fcb, StartingOffset, ReadByteCount );
    00379
    00380             //
    00381             //  Don't complete this request now if STATUS_PENDING was returned.
    00382             //
    00383
    00384             if (Status == STATUS_PENDING) {
    00385
    00386                 Irp = NULL;
    00387                 ReleaseFile = FALSE;
    00388
    00389             //
    00390             //  Test is we should zero part of the buffer or update the
    00391             //  synchronous file position.
    00392             //
    00393
    00394             } else {
    00395
    00396                 //
    00397                 //  Convert any unknown error code to IO_ERROR.
    00398                 //
    00399
    00400                 if (!NT_SUCCESS( Status )) {
    00401
    00402                     //
    00403                     //  Set the information field to zero.
    00404                     //
    00405
    00406                     Irp->IoStatus.Information = 0;
    00407
    00408                     //
    00409                     //  Raise if this is a user induced error.
    00410                     //
    00411
    00412                     if (IoIsErrorUserInduced( Status )) {
    00413
    00414                         UdfRaiseStatus( IrpContext, Status );
    00415                     }
    00416
    00417                     Status = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR );
    00418
    00419                 //
    00420                 //  Check if there is any portion of the user's buffer to zero.
    00421                 //
    00422
    00423                 } else if (ReadByteCount != ByteCount) {
    00424
    00425                     UdfMapUserBuffer( IrpContext, &UserBuffer );
    00426
    00427                     SafeZeroMemory( IrpContext,
    00428                                     Add2Ptr( UserBuffer,
    00429                                              ByteCount,
    00430                                              PVOID ),
    00431                                     ReadByteCount - ByteCount );
    00432
    00433                     Irp->IoStatus.Information = ByteCount;
    00434                 }
    00435
    00436                 //
    00437                 //  Update the file position if this is a synchronous request.
    00438                 //
    00439
    00440                 if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) {
    00441
    00442                     IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
    00443                 }
    00444             }
    00445
    00446             try_leave( NOTHING );
    00447         }
    00448
    00449         //
    00450         //  Handle the cached case.  Start by initializing the private
    00451         //  cache map.
    00452         //
    00453
    00454         if (MappingFileObject->PrivateCacheMap == NULL) {
    00455
    00456             //
    00457             //  The metadata Fcb stream was fired up before any data read.  We should never
    00458             //  see it here.
    00459             //
    00460
    00461             ASSERT( MappingFileObject != Vcb->MetadataFcb->FileObject );
    00462
    00463             //
    00464             //  Now initialize the cache map.
    00465             //
    00466
    00467             CcInitializeCacheMap( IrpSp->FileObject,
    00468                                   (PCC_FILE_SIZES) &Fcb->AllocationSize,
    00469                                   FALSE,
    00470                                   &UdfData.CacheManagerCallbacks,
    00471                                   Fcb );
    00472
    00473             CcSetReadAheadGranularity( IrpSp->FileObject, READ_AHEAD_GRANULARITY );
    00474         }
    00475
    00476         //
    00477         //  Read from the cache if this is not an Mdl read.
    00478         //
    00479
    00480         if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
    00481
    00482             //
    00483             // If we are in the Fsp now because we had to wait earlier,
    00484             // we must map the user buffer, otherwise we can use the
    00485             // user's buffer directly.
    00486             //
    00487
    00488             UdfMapUserBuffer( IrpContext, &SystemBuffer);
    00489
    00490             //
    00491             // Now try to do the copy.
    00492             //
    00493
    00494             if (!CcCopyRead( MappingFileObject,
    00495                              (PLARGE_INTEGER) &StartingOffset,
    00496                              ByteCount,
    00497                              Wait,
    00498                              SystemBuffer,
    00499                              &Irp->IoStatus )) {
    00500
    00501                 try_leave( Status = STATUS_CANT_WAIT );
    00502             }
    00503
    00504             //
    00505             //  If the call didn't succeed, raise the error status
    00506             //
    00507
    00508             if (!NT_SUCCESS( Irp->IoStatus.Status )) {
    00509
    00510                 UdfNormalizeAndRaiseStatus( IrpContext, Irp->IoStatus.Status );
    00511             }
    00512
    00513             Status = Irp->IoStatus.Status;
    00514
    00515         //
    00516         //  Otherwise perform the MdlRead operation.
    00517         //
    00518
    00519         } else {
    00520
    00521             CcMdlRead( MappingFileObject,
    00522                        (PLARGE_INTEGER) &StartingOffset,
    00523                        ByteCount,
    00524                        &Irp->MdlAddress,
    00525                        &Irp->IoStatus );
    00526
    00527             Status = Irp->IoStatus.Status;
    00528         }
    00529
    00530         //
    00531         //  Update the current file position in the user file object.
    00532         //
    00533
    00534         if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) {
    00535
    00536             IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
    00537         }
    00538
    00539     } finally {
    00540
    00541         DebugUnwind( "UdfCommonRead" );
    00542
    00543         //
    00544         //  Release the Fcb.
    00545         //
    00546
    00547         if (ReleaseFile) {
    00548
    00549             UdfReleaseFile( IrpContext, Fcb );
    00550         }
    00551     }
    00552
    00553     //
    00554     //  Post the request if we got CANT_WAIT.
    00555     //
    00556
    00557     if (Status == STATUS_CANT_WAIT) {
    00558
    00559         Status = UdfFsdPostRequest( IrpContext, Irp );
    00560
    00561     //
    00562     //  Otherwise complete the request.
    00563     //
    00564
    00565     } else {
    00566
    00567         UdfCompleteRequest( IrpContext, Irp, Status );
    00568     }
    00569
    00570     return Status;
    00571 }

NTSTATUS UdfCommonSetInfo | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 385 of file fileinfo.c.

References _DEVICE_OBJECT::AlignmentRequirement, _IRP::AssociatedIrp, Buffer, _FILE_OBJECT::CurrentByteOffset, _IO_STACK_LOCATION::DeviceObject, _IO_STACK_LOCATION::FileObject, FlagOn, _FILE_OBJECT::Flags, FO_NO_INTERMEDIATE_BUFFERING, IoGetCurrentIrpStackLocation, Irp, NTSTATUS(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, Status, try_leave, TYPE_OF_OPEN, UdfAcquireFileShared, UdfCompleteRequest(), UdfDecodeFileObject(), UdfLockFcb, UdfReleaseFile, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00392                    :
    00393
    00394     This is the common routine for set file information called by both the
    00395     fsd and fsp threads.  We only support operations which set the file position.
    00396
    00397 Arguments:
    00398
    00399     Irp - Supplies the Irp to process.
    00400
    00401 Return Value:
    00402
    00403     NTSTATUS - The return status for this operation.
    00404
    00405 --*/
    00406
    00407 {
    00408     NTSTATUS Status = STATUS_INVALID_PARAMETER;
    00409
    00410     TYPE_OF_OPEN TypeOfOpen;
    00411     PFCB Fcb;
    00412     PCCB Ccb;
    00413
    00414     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00415
    00416     PFILE_POSITION_INFORMATION Buffer;
    00417
    00418     PAGED_CODE();
    00419
    00420     //
    00421     //  Decode the file object
    00422     //
    00423
    00424     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    00425
    00426     //
    00427     //  We only support a SetPositionInformation on a user file.
    00428     //
    00429
    00430     if ((TypeOfOpen != UserFileOpen) ||
    00431         (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {
    00432
    00433         UdfCompleteRequest( IrpContext, Irp, Status );
    00434         return Status;
    00435     }
    00436
    00437     //
    00438     //  Acquire shared access to this file.
    00439     //
    00440
    00441     UdfAcquireFileShared( IrpContext, Fcb );
    00442
    00443     try {
    00444
    00445         //
    00446         //  Make sure the Fcb is in a usable condition.  This
    00447         //  will raise an error condition if the fcb is unusable
    00448         //
    00449
    00450         UdfVerifyFcbOperation( IrpContext, Fcb );
    00451
    00452         Buffer = Irp->AssociatedIrp.SystemBuffer;
    00453
    00454         //
    00455         //  Check if the file does not use intermediate buffering.  If it
    00456         //  does not use intermediate buffering then the new position we're
    00457         //  supplied must be aligned properly for the device
    00458         //
    00459
    00460         if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
    00461             ((Buffer->CurrentByteOffset.LowPart & IrpSp->DeviceObject->AlignmentRequirement) != 0)) {
    00462
    00463             try_leave( NOTHING );
    00464         }
    00465
    00466         //
    00467         //  The input parameter is fine so set the current byte offset and
    00468         //  complete the request
    00469         //
    00470
    00471         //
    00472         //  Lock the Fcb to provide synchronization.
    00473         //
    00474
    00475         UdfLockFcb( IrpContext, Fcb );
    00476         IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
    00477         UdfUnlockFcb( IrpContext, Fcb );
    00478
    00479         Status = STATUS_SUCCESS;
    00480
    00481     } finally {
    00482
    00483         UdfReleaseFile( IrpContext, Fcb );
    00484     }
    00485
    00486     //
    00487     //  Complete the request if there was no raise.
    00488     //
    00489
    00490     UdfCompleteRequest( IrpContext, Irp, Status );
    00491     return Status;
    00492 }

NTSTATUS UdfCompleteMdl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 285 of file udfs/cachesup.c.

References CcMdlReadComplete(), IoGetCurrentIrpStackLocation, Irp, _IRP::MdlAddress, NULL, PAGED_CODE, and UdfCompleteRequest().

Referenced by UdfFsdDispatch().

    00292                    :
    00293
    00294     This routine performs the function of completing Mdl reads.
    00295     It should be called only from UdfCommonRead.
    00296
    00297 Arguments:
    00298
    00299     Irp - Supplies the originating Irp.
    00300
    00301 Return Value:
    00302
    00303     NTSTATUS - Will always be STATUS_SUCCESS.
    00304
    00305 --*/
    00306
    00307 {
    00308     PFILE_OBJECT FileObject;
    00309
    00310     PAGED_CODE();
    00311
    00312     //
    00313     // Do completion processing.
    00314     //
    00315
    00316     FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
    00317
    00318     CcMdlReadComplete( FileObject, Irp->MdlAddress );
    00319
    00320     //
    00321     // Mdl is now deallocated.
    00322     //
    00323
    00324     Irp->MdlAddress = NULL;
    00325
    00326     //
    00327     // Complete the request and exit right away.
    00328     //
    00329
    00330     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    00331
    00332     return STATUS_SUCCESS;
    00333 }

NTSTATUS UdfCompletePcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PPCB | Pcb
| ) |

Definition at line 804 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_PCB, ASSERT_VCB, Dbg, DebugTrace, FALSE, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Physical, Status, UdfFreePool(), UdfLoadSparingTables(), and Virtual.

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    00812                    :
    00813
    00814     This routine completes initialization of a Pcb which has been filled
    00815     in with partition descriptors.  Initialization-time data such as the
    00816     physical partition descriptors will be returned to the system.
    00817
    00818 Arguments:
    00819
    00820     Vcb - Vcb of the volume the Pcb describes
    00821
    00822     Pcb - Pcb being completed
    00823
    00824 Return Value:
    00825
    00826     NTSTATUS according to whether intialization completion was succesful
    00827
    00828 --*/
    00829
    00830 {
    00831     ULONG Reference;
    00832
    00833     NTSTATUS Status;
    00834
    00835     PAGED_CODE();
    00836
    00837     //
    00838     //  Check inputs
    00839     //
    00840
    00841     ASSERT_IRP_CONTEXT( IrpContext );
    00842     ASSERT_VCB( Vcb );
    00843     ASSERT_PCB( Pcb );
    00844
    00845     DebugTrace(( +1, Dbg, "UdfCompletePcb, Vcb %08x Pcb %08x\n", Vcb, Pcb ));
    00846
    00847     //
    00848     //  Complete intialization all physical partitions
    00849     //
    00850
    00851     for (Reference = 0;
    00852          Reference < Pcb->Partitions;
    00853          Reference++) {
    00854
    00855         DebugTrace(( 0, Dbg, "UdfCompletePcb, Examining Ref %u (type %u)!\n", Reference, Pcb->Partition[Reference].Type));
    00856
    00857         switch (Pcb->Partition[Reference].Type) {
    00858
    00859             case Physical:
    00860
    00861                 if (Pcb->Partition[Reference].Physical.PartitionDescriptor == NULL) {
    00862
    00863                     DebugTrace(( 0, Dbg,
    00864                                  "UdfCompletePcb, ... but didn't find Partition# %u!\n",
    00865                                  Pcb->Partition[Reference].Physical.PartitionNumber ));
    00866
    00867                     DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
    00868
    00869                     return STATUS_DISK_CORRUPT_ERROR;
    00870                 }
    00871
    00872                 Pcb->Partition[Reference].Physical.Start =
    00873                     Pcb->Partition[Reference].Physical.PartitionDescriptor->Start;
    00874                 Pcb->Partition[Reference].Physical.Length =
    00875                     Pcb->Partition[Reference].Physical.PartitionDescriptor->Length;
    00876
    00877
    00878                 //
    00879                 //  Retrieve the sparing information at this point if appropriate.
    00880                 //  We have to do this when we can map logical -> physical blocks.
    00881                 //
    00882
    00883                 if (Pcb->Partition[Reference].Physical.SparingMap) {
    00884
    00885                     Status = UdfLoadSparingTables( IrpContext,
    00886                                                    Vcb,
    00887                                                    Pcb,
    00888                                                    Reference );
    00889
    00890                     if (!NT_SUCCESS( Status )) {
    00891
    00892                         DebugTrace(( -1, Dbg,
    00893                                      "UdfCompletePcb -> %08x\n", Status ));
    00894                         return Status;
    00895                     }
    00896                 }
    00897
    00898                 //
    00899                 //  We will not need the descriptor or sparing map anymore, so drop them.
    00900                 //
    00901
    00902                 UdfFreePool( &Pcb->Partition[Reference].Physical.PartitionDescriptor );
    00903                 UdfFreePool( &Pcb->Partition[Reference].Physical.SparingMap );
    00904                 break;
    00905
    00906             case Virtual:
    00907                 break;
    00908
    00909             default:
    00910
    00911                 ASSERT(FALSE);
    00912                 break;
    00913         }
    00914     }
    00915
    00916     DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_SUCCESS\n" ));
    00917
    00918     return STATUS_SUCCESS;
    00919 }

VOID UdfCompleteRequest | ( | IN PIRP_CONTEXT IrpContext | OPTIONAL,
|  | IN PIRP Irp | OPTIONAL,
|  | IN NTSTATUS | Status
| ) |

Definition at line 809 of file udfdata.c.

References ASSERT_OPTIONAL_IRP, ASSERT_OPTIONAL_IRP_CONTEXT, FALSE, FlagOn, _IRP::Flags, IO_CD_ROM_INCREMENT, IoCompleteRequest, _IRP::IoStatus, Irp, IRP_INPUT_OPERATION, NT_ERROR, Status, and UdfCleanupIrpContext().

Referenced by UdfCommonCleanup(), UdfCommonClose(), UdfCommonCreate(), UdfCommonDevControl(), UdfCommonDirControl(), UdfCommonFsControl(), UdfCommonLockControl(), UdfCommonPnp(), UdfCommonQueryInfo(), UdfCommonQueryVolInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfCompleteMdl(), UdfDismountVolume(), UdfDvdReadStructure(), UdfDvdTransferKey(), UdfFsdDispatch(), UdfFspClose(), UdfFspDispatch(), UdfInvalidateVolumes(), UdfIsPathnameValid(), UdfIsVolumeDirty(), UdfIsVolumeMounted(), UdfLockVolume(), UdfMountVolume(), UdfNotifyChangeDirectory(), UdfOplockComplete(), UdfOplockRequest(), UdfPerformVerify(), UdfPnpCancelRemove(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfProcessException(), UdfQueryDirectory(), UdfQueueClose(), UdfUnlockVolume(), UdfUserFsctl(), and UdfVerifyVolume().

    00817                    :
    00818
    00819     This routine completes a Irp and cleans up the IrpContext.  Either or
    00820     both of these may not be specified.
    00821
    00822 Arguments:
    00823
    00824     Irp - Supplies the Irp being processed.
    00825
    00826     Status - Supplies the status to complete the Irp with
    00827
    00828 Return Value:
    00829
    00830     None.
    00831
    00832 --*/
    00833
    00834 {
    00835     ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
    00836     ASSERT_OPTIONAL_IRP( Irp );
    00837
    00838     //
    00839     //  Cleanup the IrpContext if passed in here.
    00840     //
    00841
    00842     if (ARGUMENT_PRESENT( IrpContext )) {
    00843
    00844         UdfCleanupIrpContext( IrpContext, FALSE );
    00845     }
    00846
    00847     //
    00848     //  If we have an Irp then complete the irp.
    00849     //
    00850
    00851     if (ARGUMENT_PRESENT( Irp )) {
    00852
    00853         //
    00854         //  Clear the information field in case we have used this Irp
    00855         //  internally.
    00856         //
    00857
    00858         if (NT_ERROR( Status ) &&
    00859             FlagOn( Irp->Flags, IRP_INPUT_OPERATION )) {
    00860
    00861             Irp->IoStatus.Information = 0;
    00862         }
    00863
    00864         Irp->IoStatus.Status = Status;
    00865         IoCompleteRequest( Irp, IO_CD_ROM_INCREMENT );
    00866     }
    00867
    00868     return;
    00869 }

USHORT UdfComputeCrc16 | ( | IN PUCHAR | Buffer,
|  | IN ULONG | ByteCount
| ) |

| Referenced by UdfVerifyDescriptor().

USHORT UdfComputeCrc16Uni | ( | PWCHAR | Buffer,
|  | ULONG | CharCount
| ) |

Definition at line 1194 of file udfdata.c.

References Buffer, UdfCrcTable, and USHORT.

Referenced by UdfGenerate8dot3Name(), and UdfRenderNameToLegalUnicode().

    01201                    :
    01202
    01203     This routine generates a 16 bit CRC of the input buffer in accordance
    01204     with the precomputed CRC table.
    01205
    01206     It performs a byte-order independent crc (hi then lo). This is a bit
    01207     suspect, but is called for in the specification.
    01208
    01209 Arguments:
    01210
    01211     Buffer - Pointer to the buffer to generate the CRC for.
    01212
    01213     ShortCount - Number of wide characters in the buffer.
    01214
    01215 Return Value:
    01216
    01217     USHORT - The 16bit CRC
    01218
    01219 --*/
    01220
    01221 {
    01222     USHORT Crc = 0;
    01223
    01224     //
    01225     //  Byte order independent CRC, hi byte to low byte per character.
    01226     //
    01227
    01228     while (CharCount-- > 0) {
    01229
    01230         Crc = UdfCrcTable[((Crc >> 8) ^ (*Buffer >> 8)) & 0xff] ^ (Crc << 8);
    01231         Crc = UdfCrcTable[((Crc >> 8) ^ (*Buffer++ & 0xff)) & 0xff] ^ (Crc << 8);
    01232     }
    01233
    01234     return Crc;
    01235 }

VOID UdfConvertCS0DstringToUnicode | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUCHAR | Dstring,
|  | IN UCHAR Length | OPTIONAL,
|  | IN UCHAR FieldLength | OPTIONAL,
|  | IN OUT PUNICODE_STRING | Name
| ) |

Definition at line 689 of file namesup.c.

References ASSERT, ASSERT_IRP_CONTEXT, CHAR, Min, Name, PAGED_CODE, SwapCopyUchar2, UdfCS0DstringUnicodeSize(), and Unicode.

Referenced by UdfUpdateDirNames(), and UdfUpdateVolumeLabel().

    00699                    :
    00700
    00701     This routine will convert the CS0 input dstring (1/7.2.12) to Unicode.  We assume that
    00702     the length is sane.
    00703
    00704     This "compression" in CS0 is really just a special case hack for ASCII.
    00705
    00706 Arguments:
    00707
    00708     Dstring - the input dstring field
    00709
    00710     Length - length of the dstring.  If unspecified, we assume that the characters come
    00711         from a proper 1/7.2.12 dstring that specifies length in the last character of the
    00712         field.
    00713
    00714     FieldLength - length of the dstring field.  If unspecified, we assume that the characters
    00715         come from an uncounted length of CS0 characters and that the Length parameter is
    00716         specified.
    00717
    00718     Name - the output Unicode string
    00719
    00720 Return Value:
    00721
    00722     None.
    00723
    00724 --*/
    00725
    00726 {
    00727     ULONG CompressID;
    00728     ULONG UnicodeIndex, ByteIndex;
    00729     PWCHAR Unicode = Name->Buffer;
    00730
    00731     UCHAR NameLength;
    00732     ULONG CopyNameLength;
    00733
    00734     PAGED_CODE();
    00735
    00736     //
    00737     //  Check input.
    00738     //
    00739
    00740     ASSERT_IRP_CONTEXT( IrpContext );
    00741
    00742     CompressID = *Dstring;
    00743
    00744     //
    00745     //  If the length is unspecified, this is a real 1/7.2.12 dstring and the length is in
    00746     //  the last character of the field.
    00747     //
    00748
    00749     ASSERT( Length || FieldLength );
    00750
    00751     if (Length) {
    00752
    00753         NameLength = FieldLength = Length;
    00754
    00755     } else {
    00756
    00757         NameLength = *(Dstring + FieldLength - 1);
    00758     }
    00759
    00760     //
    00761     //  If the caller specified a size, they should have made sure the buffer is big enough.
    00762     //  Otherwise, we will trim to fit.
    00763     //
    00764
    00765     ASSERT( Length == 0 || Name->MaximumLength >= UdfCS0DstringUnicodeSize( IrpContext, Dstring, NameLength ) );
    00766
    00767     //
    00768     //  Decide how many UNICODE bytes to "copy".
    00769     //
    00770
    00771     CopyNameLength = Min( Name->MaximumLength, UdfCS0DstringUnicodeSize( IrpContext, Dstring, NameLength ));
    00772
    00773     //
    00774     //  Reset the name length and advance over the compression ID in the dstring.
    00775     //
    00776
    00777     Name->Length = 0;
    00778     Dstring++;
    00779
    00780     //
    00781     //  Loop through all the bytes.
    00782     //
    00783
    00784     while (CopyNameLength > Name->Length) {
    00785
    00786         if (CompressID == 16) {
    00787
    00788             //
    00789             //  We're little endian, and this is the single place in the entire UDF/ISO standard
    00790             //  where they use big endian.
    00791             //
    00792             //  Thank you.  Thank you very much.
    00793             //
    00794             //  Do an unaligned swapcopy of this 16bit value.
    00795             //
    00796
    00797             SwapCopyUchar2( Unicode, Dstring );
    00798             Dstring += sizeof(WCHAR);
    00799
    00800         } else {
    00801
    00802             //
    00803             //  Drop the byte into the low bits.
    00804             //
    00805
    00806             *Unicode = *Dstring;
    00807             Dstring += sizeof(CHAR);
    00808         }
    00809
    00810         Name->Length += sizeof(WCHAR);
    00811         Unicode++;
    00812     }
    00813
    00814     return;
    00815 }

INLINE VOID UdfConvertUdfTimeToNtTime | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PTIMESTAMP | UdfTime,
|  | OUT PLARGE_INTEGER | NtTime
| ) |

Definition at line 1921 of file udfprocs.h.

References PTIMESTAMP, RtlTimeFieldsToTime(), TIMESTAMP_Z_MAX, TIMESTAMP_Z_MIN, and TIMESTAMP_Z_NONE.

Referenced by UdfUpdateTimestampsFromIcbContext().

    01926 {
    01927     TIME_FIELDS TimeField;
    01928
    01929     TimeField.Year = UdfTime->Year;
    01930     TimeField.Month = UdfTime->Month;
    01931     TimeField.Day = UdfTime->Day;
    01932     TimeField.Hour = UdfTime->Hour;
    01933     TimeField.Minute = UdfTime->Minute;
    01934     TimeField.Second = UdfTime->Second;
    01935
    01936     //
    01937     //  This is where it gets hairy.  For some unholy reason, ISO 13346 timestamps
    01938     //  carve the right of the decimal point up into three fields of precision
    01939     //  10-2, 10-4, and 10-6, each ranging from 0-99. Lawdy.
    01940     //
    01941     //  To make it easier, since they cannot cause a wrap into the next second,
    01942     //  just save it all up and add it in after the conversion.
    01943     //
    01944
    01945     TimeField.Milliseconds = 0;
    01946
    01947     if (UdfTime->Type <= 1 &&
    01948         ((UdfTime->Zone >= TIMESTAMP_Z_MIN && UdfTime->Zone <= TIMESTAMP_Z_MAX) ||
    01949          UdfTime->Zone == TIMESTAMP_Z_NONE) &&
    01950         RtlTimeFieldsToTime( &TimeField, NtTime )) {
    01951
    01952         //
    01953         //  Now fold in the remaining sub-second "precision".  Read as coversions
    01954         //  through the 10-3 units, then into our 10-7 base. (centi->milli->micro,
    01955         //  etc).
    01956         //
    01957
    01958         NtTime->QuadPart += ((UdfTime->CentiSecond * (10 * 1000)) +
    01959                              (UdfTime->Usec100 * 100) +
    01960                              UdfTime->Usec) * 10;
    01961
    01962         //
    01963         //  Perform TZ normalization if this is a local time with
    01964         //  specified timezone.
    01965         //
    01966
    01967         if (UdfTime->Type == 1 && UdfTime->Zone != TIMESTAMP_Z_NONE) {
    01968
    01969             NtTime->QuadPart += Int32x32To64( -UdfTime->Zone, (60 * 10 * 1000 * 1000) );
    01970         }
    01971
    01972     } else {
    01973
    01974         //
    01975         //  Epoch.  Malformed timestamp.
    01976         //
    01977
    01978         NtTime->QuadPart = 0;
    01979     }
    01980 }

PCCB UdfCreateCcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PLCB Lcb | OPTIONAL,
|  | IN ULONG | Flags
| ) |

Definition at line 2433 of file udfs/strucsup.c.

References ASSERT_FCB, ASSERT_IRP_CONTEXT, ASSERT_OPTIONAL_LCB, CCB, _CCB::CurrentFileIndex, _CCB::Fcb, _CCB::Flags, _CCB::HighestReturnableFileIndex, _CCB::Lcb, _CCB::NodeByteSize, _CCB::NodeTypeCode, NULL, PAGED_CODE, _CCB::SearchExpression, UdfAllocateCcb, and UDFS_NTC_CCB.

Referenced by UdfCompleteFcbOpen().

    02442                    :
    02443
    02444     This routine is called to allocate and initialize the Ccb structure.
    02445
    02446 Arguments:
    02447
    02448     Fcb - This is the Fcb for the file being opened.
    02449
    02450     Lcb - This is the Lcb the Fcb is opened by.
    02451
    02452     Flags - User flags to set in this Ccb.
    02453
    02454 Return Value:
    02455
    02456     PCCB - Pointer to the created Ccb.
    02457
    02458 --*/
    02459
    02460 {
    02461     PCCB NewCcb;
    02462
    02463     PAGED_CODE();
    02464
    02465     //
    02466     //  Check inputs.
    02467     //
    02468
    02469     ASSERT_IRP_CONTEXT( IrpContext );
    02470     ASSERT_FCB( Fcb );
    02471     ASSERT_OPTIONAL_LCB( Lcb );
    02472
    02473     //
    02474     //  Allocate and initialize the structure.
    02475     //
    02476
    02477     NewCcb = UdfAllocateCcb( IrpContext );
    02478
    02479     //
    02480     //  Set the proper node type code and node byte size
    02481     //
    02482
    02483     NewCcb->NodeTypeCode = UDFS_NTC_CCB;
    02484     NewCcb->NodeByteSize = sizeof( CCB );
    02485
    02486     //
    02487     //  Set the initial value for the flags and Fcb/Lcb
    02488     //
    02489
    02490     NewCcb->Flags = Flags;
    02491     NewCcb->Fcb = Fcb;
    02492     NewCcb->Lcb = Lcb;
    02493
    02494     //
    02495     //  Initialize the directory enumeration context
    02496     //
    02497
    02498     NewCcb->CurrentFileIndex = 0;
    02499     NewCcb->HighestReturnableFileIndex = 0;
    02500
    02501     NewCcb->SearchExpression.Length =
    02502     NewCcb->SearchExpression.MaximumLength = 0;
    02503     NewCcb->SearchExpression.Buffer = NULL;
    02504
    02505     return NewCcb;
    02506 }

PFCB UdfCreateFcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN FILE_ID | FileId,
|  | IN NODE_TYPE_CODE | NodeTypeCode,
|  | OUT PBOOLEAN FcbExisted | OPTIONAL
| ) |

Definition at line 2041 of file udfs/strucsup.c.

References _FCB::ChildLcbQueue, DebugUnwind, FALSE, _FCB::FcbNonpaged, _FCB::FileId, NULL, PAGED_CODE, _FCB::ParentLcbQueue, SIZEOF_FCB_DATA, SIZEOF_FCB_INDEX, TRUE, UdfAllocateFcbData, UdfAllocateFcbIndex, UdfBugCheck, UdfCreateFcbNonPaged(), UdfFreePool(), UdfLookupFcbTable(), UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, and _FCB::Vcb.

Referenced by UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

    02050                    :
    02051
    02052     This routine is called to find the Fcb for the given FileId.  We will
    02053     look this up first in the Fcb table and if not found we will create
    02054     an Fcb.  We don't initialize it or insert it into the FcbTable in this
    02055     routine.
    02056
    02057     This routine is called while the Vcb is locked.
    02058
    02059 Arguments:
    02060
    02061     FileId - This is the Id for the target Fcb.
    02062
    02063     NodeTypeCode - Node type for this Fcb if we need to create.
    02064
    02065     FcbExisted - If specified, we store whether the Fcb existed.
    02066
    02067 Return Value:
    02068
    02069     PFCB - The Fcb found in the table or created if needed.
    02070
    02071 --*/
    02072
    02073 {
    02074     PFCB NewFcb;
    02075     BOOLEAN LocalFcbExisted;
    02076
    02077     PAGED_CODE();
    02078
    02079     //
    02080     //  Use the local boolean if one was not passed in.
    02081     //
    02082
    02083     if (!ARGUMENT_PRESENT( FcbExisted )) {
    02084
    02085         FcbExisted = &LocalFcbExisted;
    02086     }
    02087
    02088     //
    02089     //  Maybe this is already in the table.
    02090     //
    02091
    02092     NewFcb = UdfLookupFcbTable( IrpContext, IrpContext->Vcb, FileId );
    02093
    02094     //
    02095     //  If not then create the Fcb is requested by our caller.
    02096     //
    02097
    02098     if (NewFcb == NULL) {
    02099
    02100         //
    02101         //  Use a try-finally for cleanup
    02102         //
    02103
    02104         try {
    02105
    02106             //
    02107             //  Allocate and initialize the structure depending on the
    02108             //  type code.
    02109             //
    02110
    02111             switch (NodeTypeCode) {
    02112
    02113             case UDFS_NTC_FCB_INDEX:
    02114
    02115                 NewFcb = UdfAllocateFcbIndex( IrpContext );
    02116
    02117                 RtlZeroMemory( NewFcb, SIZEOF_FCB_INDEX );
    02118
    02119                 NewFcb->NodeByteSize = SIZEOF_FCB_INDEX;
    02120
    02121                 break;
    02122
    02123             case UDFS_NTC_FCB_DATA :
    02124
    02125                 NewFcb = UdfAllocateFcbData( IrpContext );
    02126
    02127                 RtlZeroMemory( NewFcb, SIZEOF_FCB_DATA );
    02128
    02129                 NewFcb->NodeByteSize = SIZEOF_FCB_DATA;
    02130
    02131                 break;
    02132
    02133             default:
    02134
    02135                 UdfBugCheck( 0, 0, 0 );
    02136             }
    02137
    02138             //
    02139             //  Now do the common initialization.
    02140             //
    02141
    02142             NewFcb->NodeTypeCode = NodeTypeCode;
    02143
    02144             NewFcb->Vcb = IrpContext->Vcb;
    02145             NewFcb->FileId = FileId;
    02146
    02147             InitializeListHead( &NewFcb->ParentLcbQueue );
    02148             InitializeListHead( &NewFcb->ChildLcbQueue );
    02149
    02150             //
    02151             //  Now create the non-paged section object.
    02152             //
    02153
    02154             NewFcb->FcbNonpaged = UdfCreateFcbNonPaged( IrpContext );
    02155
    02156             *FcbExisted = FALSE;
    02157
    02158         } finally {
    02159
    02160             DebugUnwind( "UdfCreateFcb" );
    02161
    02162             if (AbnormalTermination()) {
    02163
    02164                 UdfFreePool( &NewFcb );
    02165             }
    02166         }
    02167
    02168     } else {
    02169
    02170         *FcbExisted = TRUE;
    02171     }
    02172
    02173     return NewFcb;
    02174 }

BOOLEAN UdfCreateFileLock | ( | IN PIRP_CONTEXT IrpContext | OPTIONAL,
|  | IN PFCB | Fcb,
|  | IN BOOLEAN | RaiseOnError
| ) |

Definition at line 3713 of file udfs/strucsup.c.

References ASSERT, FALSE, FsRtlAllocateFileLock(), NULL, PAGED_CODE, PFILE_LOCK, TRUE, UdfLockFcb, UdfRaiseStatus(), and UdfUnlockFcb.

Referenced by UdfCommonLockControl(), UdfFastLock(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), and UdfFastUnlockSingle().

    03721                    :
    03722
    03723     This routine is called when we want to attach a file lock structure to the
    03724     given Fcb.  It is possible the file lock is already attached.
    03725
    03726     This routine is sometimes called from the fast path and sometimes in the
    03727     Irp-based path.  We don't want to raise in the fast path, just return FALSE.
    03728
    03729 Arguments:
    03730
    03731     Fcb - This is the Fcb to create the file lock for.
    03732
    03733     RaiseOnError - If TRUE, we will raise on an allocation failure.  Otherwise we
    03734         return FALSE on an allocation failure.
    03735
    03736 Return Value:
    03737
    03738     BOOLEAN - TRUE if the Fcb has a filelock, FALSE otherwise.
    03739
    03740 --*/
    03741
    03742 {
    03743     BOOLEAN Result = TRUE;
    03744     PFILE_LOCK FileLock;
    03745
    03746     PAGED_CODE();
    03747
    03748     //
    03749     //  Lock the Fcb and check if there is really any work to do.
    03750     //
    03751
    03752     UdfLockFcb( IrpContext, Fcb );
    03753
    03754     if (Fcb->FileLock != NULL) {
    03755
    03756         UdfUnlockFcb( IrpContext, Fcb );
    03757         return TRUE;
    03758     }
    03759
    03760     Fcb->FileLock = FileLock =
    03761         FsRtlAllocateFileLock( NULL, NULL );
    03762
    03763     UdfUnlockFcb( IrpContext, Fcb );
    03764
    03765     //
    03766     //  Return or raise as appropriate.
    03767     //
    03768
    03769     if (FileLock == NULL) {
    03770
    03771         if (RaiseOnError) {
    03772
    03773             ASSERT( ARGUMENT_PRESENT( IrpContext ));
    03774
    03775             UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    03776         }
    03777
    03778         Result = FALSE;
    03779     }
    03780
    03781     return Result;
    03782 }

VOID UdfCreateInternalStream | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PFCB | Fcb
| ) |

Definition at line 46 of file udfs/cachesup.c.

References ASSERT_FCB_INDEX, ASSERT_IRP_CONTEXT, _UDF_DATA::CacheManagerCallbacks, CcInitializeCacheMap(), Dbg, DebugTrace, DebugUnwind, _FILE_OBJECT::DeleteAccess, FALSE, IoCreateStreamFileObject(), NULL, ObDereferenceObject, PAGED_CODE, _FILE_OBJECT::ReadAccess, _FILE_OBJECT::SectionObjectPointer, StreamFileOpen, TRUE, UdfData, UdfDecrementReferenceCounts, UdfIncrementReferenceCounts, UdfLockFcb, UdfLockVcb, UdfRaiseStatus(), UdfSetFileObject(), UdfUnlockFcb, UdfUnlockVcb, and _FILE_OBJECT::WriteAccess.

Referenced by UdfLookupInitialDirEntry(), UdfUpdateVcbPhase0(), and UdfUpdateVcbPhase1().

    00054                    :
    00055
    00056     This function creates an internal stream file for interaction
    00057     with the cache manager.  The Fcb here will be for a directory
    00058     stream.
    00059
    00060 Arguments:
    00061
    00062     Vcb - Vcb for this volume.
    00063
    00064     Fcb - Points to the Fcb for this file.  It is an Index Fcb.
    00065
    00066 Return Value:
    00067
    00068     None.
    00069
    00070 --*/
    00071
    00072 {
    00073     PFILE_OBJECT StreamFile = NULL;
    00074     BOOLEAN DecrementReference = FALSE;
    00075
    00076     PAGED_CODE();
    00077
    00078     //
    00079     //  Check inputs.
    00080     //
    00081
    00082     ASSERT_IRP_CONTEXT( IrpContext );
    00083     ASSERT_FCB_INDEX( Fcb );
    00084
    00085     //
    00086     //  We may only have the Fcb shared.  Lock the Fcb and do a
    00087     //  safe test to see if we need to really create the file object.
    00088     //
    00089
    00090     UdfLockFcb( IrpContext, Fcb );
    00091
    00092     if (Fcb->FileObject != NULL) {
    00093
    00094         UdfUnlockFcb( IrpContext, Fcb );
    00095         return;
    00096     }
    00097
    00098     //
    00099     //  Use a try-finally to facilitate cleanup.
    00100     //
    00101
    00102     try {
    00103
    00104         //
    00105         //  Create the internal stream.  The Vpb should be pointing at our volume
    00106         //  device object at this point.
    00107         //
    00108
    00109         StreamFile = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice );
    00110
    00111         if (StreamFile == NULL) {
    00112
    00113             UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    00114         }
    00115
    00116         //
    00117         //  Initialize the fields of the file object.
    00118         //
    00119
    00120         StreamFile->ReadAccess = TRUE;
    00121         StreamFile->WriteAccess = FALSE;
    00122         StreamFile->DeleteAccess = FALSE;
    00123
    00124         StreamFile->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;
    00125
    00126         //
    00127         //  Set the file object type and increment the Vcb counts.
    00128         //
    00129
    00130         UdfSetFileObject( IrpContext,
    00131                          StreamFile,
    00132                          StreamFileOpen,
    00133                          Fcb,
    00134                          NULL );
    00135
    00136         //
    00137         //  We will reference the current Fcb twice to keep it from going
    00138         //  away in the error path.  Otherwise if we dereference it
    00139         //  below in the finally clause a close could cause the Fcb to
    00140         //  be deallocated.
    00141         //
    00142
    00143         UdfLockVcb( IrpContext, Vcb );
    00144
    00145         DebugTrace(( +1, Dbg,
    00146                      "UdfCreateInternalStream, Fcb %08x Vcb %d/%d Fcb %d/%d\n",
    00147                      Fcb,
    00148                      Vcb->VcbReference,
    00149                      Vcb->VcbUserReference,
    00150                      Fcb->FcbReference,
    00151                      Fcb->FcbUserReference ));
    00152
    00153         UdfIncrementReferenceCounts( IrpContext, Fcb, 2, 0 );
    00154         UdfUnlockVcb( IrpContext, Vcb );
    00155         DecrementReference = TRUE;
    00156
    00157         //
    00158         //  Initialize the cache map for the file.
    00159         //
    00160
    00161         CcInitializeCacheMap( StreamFile,
    00162                               (PCC_FILE_SIZES)&Fcb->AllocationSize,
    00163                               TRUE,
    00164                               &UdfData.CacheManagerCallbacks,
    00165                               Fcb );
    00166
    00167         //
    00168         //  Go ahead and store the stream file into the Fcb.
    00169         //
    00170
    00171         Fcb->FileObject = StreamFile;
    00172         StreamFile = NULL;
    00173
    00174     } finally {
    00175
    00176         DebugUnwind( "UdfCreateInternalStream" );
    00177
    00178         //
    00179         //  If we raised then we need to dereference the file object.
    00180         //
    00181
    00182         if (StreamFile != NULL) {
    00183
    00184             ObDereferenceObject( StreamFile );
    00185             Fcb->FileObject = NULL;
    00186         }
    00187
    00188         //
    00189         //  Dereference and unlock the Fcb.
    00190         //
    00191
    00192         if (DecrementReference) {
    00193
    00194             UdfLockVcb( IrpContext, Vcb );
    00195             UdfDecrementReferenceCounts( IrpContext, Fcb, 1, 0 );
    00196
    00197             DebugTrace(( -1, Dbg,
    00198                          "UdfCreateInternalStream, Vcb %d/%d Fcb %d/%d\n",
    00199                          Vcb->VcbReference,
    00200                          Vcb->VcbUserReference,
    00201                          Fcb->FcbReference,
    00202                          Fcb->FcbUserReference ));
    00203
    00204             UdfUnlockVcb( IrpContext, Vcb );
    00205         }
    00206
    00207         UdfUnlockFcb( IrpContext, Fcb );
    00208     }
    00209
    00210     return;
    00211 }

PIRP_CONTEXT UdfCreateIrpContext | ( | IN PIRP | Irp,
|  | IN BOOLEAN | Wait
| ) |

Definition at line 1301 of file udfs/strucsup.c.

References ASSERT, Count, _FILE_OBJECT::DeviceObject, _IO_STACK_LOCATION::DeviceObject, ExAllocateFromNPagedLookasideList(), ExRaiseStatus(), FALSE, _IO_STACK_LOCATION::FileObject, _UDF_DATA::FileSystemDeviceObjects, _IRP_CONTEXT::Flags, IoGetCurrentIrpStackLocation, _IRP_CONTEXT::Irp, Irp, IRP_CONTEXT, IRP_CONTEXT_FLAG_FORCE_POST, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MJ_SHUTDOWN, IRP_MN_MOUNT_VOLUME, IRP_MN_USER_FS_REQUEST, _IRP_CONTEXT::MajorFunction, _IO_STACK_LOCATION::MajorFunction, _IRP_CONTEXT::MinorFunction, _IO_STACK_LOCATION::MinorFunction, _IRP_CONTEXT::NodeByteSize, _IRP_CONTEXT::NodeTypeCode, NULL, NUMBER_OF_FS_OBJECTS, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _IRP_CONTEXT::RealDevice, SetFlag, TRUE, UdfData, UdfIrpContextLookasideList, UDFS_NTC_IRP_CONTEXT, and _IRP_CONTEXT::Vcb.

Referenced by UdfFsdDispatch().

    01308                    :
    01309
    01310     This routine is called to initialize an IrpContext for the current
    01311     UDFS request.  We allocate the structure and then initialize it from
    01312     the given Irp.
    01313
    01314 Arguments:
    01315
    01316     Irp - Irp for this request.
    01317
    01318     Wait - TRUE if this request is synchronous, FALSE otherwise.
    01319
    01320 Return Value:
    01321
    01322     PIRP_CONTEXT - Allocated IrpContext.
    01323
    01324 --*/
    01325
    01326 {
    01327     PIRP_CONTEXT NewIrpContext = NULL;
    01328     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01329     BOOLEAN IsFsDo = FALSE;
    01330     ULONG Count;
    01331
    01332     PAGED_CODE();
    01333
    01334     for (Count = 0; Count < NUMBER_OF_FS_OBJECTS; Count++) {
    01335
    01336         if (IrpSp->DeviceObject == UdfData.FileSystemDeviceObjects[Count]) {
    01337
    01338             IsFsDo = TRUE;
    01339             break;
    01340         }
    01341     }
    01342
    01343     //
    01344     //  The only operations a filesystem device object should ever receive
    01345     //  are create/teardown of fsdo handles and operations which do not
    01346     //  occur in the context of fileobjects (i.e., mount).
    01347     //
    01348
    01349     if (IsFsDo) {
    01350
    01351         if (IrpSp->FileObject != NULL &&
    01352             IrpSp->MajorFunction != IRP_MJ_CREATE &&
    01353             IrpSp->MajorFunction != IRP_MJ_CLEANUP &&
    01354             IrpSp->MajorFunction != IRP_MJ_CLOSE) {
    01355
    01356             ExRaiseStatus( STATUS_INVALID_DEVICE_REQUEST );
    01357         }
    01358
    01359         ASSERT( IrpSp->FileObject != NULL ||
    01360
    01361                 (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
    01362                  IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
    01363                  IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES) ||
    01364
    01365                 (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
    01366                  IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME ) ||
    01367
    01368                 IrpSp->MajorFunction == IRP_MJ_SHUTDOWN );
    01369     }
    01370
    01371     NewIrpContext = ExAllocateFromNPagedLookasideList( &UdfIrpContextLookasideList );
    01372
    01373     RtlZeroMemory( NewIrpContext, sizeof( IRP_CONTEXT ));
    01374
    01375     //
    01376     //  Set the proper node type code and node byte size
    01377     //
    01378
    01379     NewIrpContext->NodeTypeCode = UDFS_NTC_IRP_CONTEXT;
    01380     NewIrpContext->NodeByteSize = sizeof( IRP_CONTEXT );
    01381
    01382     //
    01383     //  Set the originating Irp field
    01384     //
    01385
    01386     NewIrpContext->Irp = Irp;
    01387
    01388     //
    01389     //  Copy RealDevice for workque algorithms.  We will update this in the Mount or
    01390     //  Verify since they have no file objects to use here.
    01391     //
    01392
    01393     if (IrpSp->FileObject != NULL) {
    01394
    01395         NewIrpContext->RealDevice = IrpSp->FileObject->DeviceObject;
    01396     }
    01397
    01398     //
    01399     //  This may be one of our filesystem device objects.  In that case don't
    01400     //  initialize the Vcb field.
    01401     //
    01402
    01403     if (!IsFsDo) {
    01404
    01405         NewIrpContext->Vcb = &((PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject)->Vcb;
    01406     }
    01407
    01408     //
    01409     //  Major/Minor Function codes
    01410     //
    01411
    01412     NewIrpContext->MajorFunction = IrpSp->MajorFunction;
    01413     NewIrpContext->MinorFunction = IrpSp->MinorFunction;
    01414
    01415     //
    01416     //  Set the wait parameter
    01417     //
    01418
    01419     if (Wait) {
    01420
    01421         SetFlag( NewIrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    01422
    01423     } else {
    01424
    01425         SetFlag( NewIrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
    01426     }
    01427
    01428     //
    01429     //  return and tell the caller
    01430     //
    01431
    01432     return NewIrpContext;
    01433 }

NTSTATUS UdfCreateUserMdl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN ULONG | BufferLength,
|  | IN BOOLEAN | RaiseOnError
| ) |

Definition at line 474 of file deviosup.c.

References ASSERT, ASSERT_IRP, ASSERT_IRP_CONTEXT, EXCEPTION_EXECUTE_HANDLER, FALSE, FsRtlIsNtstatusExpected(), IoAllocateMdl(), IoFreeMdl(), IoWriteAccess, MmProbeAndLockPages(), NTSTATUS(), NULL, PAGED_CODE, Status, and UdfRaiseStatus().

Referenced by UdfNonCachedRead().

    00482                    :
    00483
    00484     This routine locks the specified buffer for read access (we only write into
    00485     the buffer).  The file system requires this routine since it does not
    00486     ask the I/O system to lock its buffers for direct I/O.  This routine
    00487     may only be called from the Fsd while still in the user context.
    00488
    00489     This routine is only called if there is not already an Mdl.
    00490
    00491 Arguments:
    00492
    00493     BufferLength - Length of user buffer.
    00494
    00495     RaiseOnError - Indicates if our caller wants this routine to raise on
    00496         an error condition.
    00497
    00498 Return Value:
    00499
    00500     NTSTATUS - Status from this routine.  Error status only returned if
    00501         RaiseOnError is FALSE.
    00502
    00503 --*/
    00504
    00505 {
    00506     NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
    00507     PMDL Mdl;
    00508
    00509     PAGED_CODE();
    00510
    00511     ASSERT_IRP_CONTEXT( IrpContext );
    00512     ASSERT_IRP( IrpContext->Irp );
    00513     ASSERT( IrpContext->Irp->MdlAddress == NULL );
    00514
    00515     //
    00516     // Allocate the Mdl, and Raise if we fail.
    00517     //
    00518
    00519     Mdl = IoAllocateMdl( IrpContext->Irp->UserBuffer,
    00520                          BufferLength,
    00521                          FALSE,
    00522                          FALSE,
    00523                          IrpContext->Irp );
    00524
    00525     if (Mdl != NULL) {
    00526
    00527         //
    00528         //  Now probe the buffer described by the Irp.  If we get an exception,
    00529         //  deallocate the Mdl and return the appropriate "expected" status.
    00530         //
    00531
    00532         try {
    00533
    00534             MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode, IoWriteAccess );
    00535
    00536             Status = STATUS_SUCCESS;
    00537
    00538         } except(EXCEPTION_EXECUTE_HANDLER) {
    00539
    00540             Status = GetExceptionCode();
    00541
    00542             IoFreeMdl( Mdl );
    00543             IrpContext->Irp->MdlAddress = NULL;
    00544
    00545             if (!FsRtlIsNtstatusExpected( Status )) {
    00546
    00547                 Status = STATUS_INVALID_USER_BUFFER;
    00548             }
    00549         }
    00550     }
    00551
    00552     //
    00553     //  Check if we are to raise or return
    00554     //
    00555
    00556     if (Status != STATUS_SUCCESS) {
    00557
    00558         if (RaiseOnError) {
    00559
    00560             UdfRaiseStatus( IrpContext, Status );
    00561         }
    00562     }
    00563
    00564     //
    00565     //  Return the status code.
    00566     //
    00567
    00568     return Status;
    00569 }

INLINE BOOLEAN UdfCS0DstringContainsLegalCharacters | ( | IN PCHAR | Dstring,
|  | IN ULONG | Length
| ) |

Definition at line 1239 of file udfprocs.h.

References CHAR, Dbg, DebugTrace, FALSE, SwapCopyUchar2, TRUE, and UdfIsCharacterLegal().

Referenced by UdfUpdateDirNames().

    01246                    :
    01247
    01248     This routine inspects a CS0 dstring for illegal characters.  The assumption is
    01249     made that the string is legal CS0.
    01250
    01251 Arguments:
    01252
    01253     Name - a name to check
    01254
    01255 Return Value:
    01256
    01257     BOOLEAN True if legal characters are found, False otherwise.
    01258
    01259 --*/
    01260
    01261 {
    01262     ULONG Step;
    01263     WCHAR Char;
    01264     PCHAR Bound = Dstring + Length;
    01265
    01266     //
    01267     //  Determine how big a step we take in the string according to the
    01268     //  "compression" applied.
    01269     //
    01270
    01271     if (*Dstring == 16) {
    01272
    01273         Step = sizeof( WCHAR );
    01274
    01275     } else {
    01276
    01277         Step = sizeof( CHAR );
    01278     }
    01279
    01280     //
    01281     //  Advance past the compression marker and loop over the string.
    01282     //
    01283
    01284     for (Dstring++; Dstring < Bound; Dstring += Step) {
    01285
    01286         //
    01287         //  Perform the endianess swapcopy to convert from UDF bigendian CS0 to our
    01288         //  little endian wide characters.
    01289         //
    01290
    01291         SwapCopyUchar2( &Char, Dstring );
    01292
    01293         if (!UdfIsCharacterLegal( Char )) {
    01294
    01295             DebugTrace(( 0, Dbg, "UdfCS0DstringContainsLegalCharacters, Char %04x @ %08x\n", (WCHAR) Char, Dstring ));
    01296
    01297             return FALSE;
    01298         }
    01299     }
    01300
    01301     return TRUE;
    01302 }

INLINE USHORT UdfCS0DstringUnicodeSize | ( | PIRP_CONTEXT | IrpContext,
|  | PCHAR | Dstring,
|  | UCHAR | Length
| ) |

Definition at line 1177 of file udfprocs.h.

Referenced by UdfConvertCS0DstringToUnicode(), and UdfUpdateDirNames().

    01185                    :
    01186
    01187     This routine computes the number of bytes required for the UNICODE representation
    01188     of a CS0 Dstring (1/7.2.12)
    01189
    01190 Arguments:
    01191
    01192     Dstring - a dstring
    01193
    01194     Length - length of the dstring
    01195
    01196 Return Value:
    01197
    01198     ULONG number of bytes.
    01199
    01200 --*/
    01201
    01202 {
    01203     return (16 / *Dstring) * (Length - 1);
    01204 }

TYPE_OF_OPEN UdfDecodeFileObject | ( | IN PFILE_OBJECT | FileObject,
|  | OUT PFCB * | Fcb,
|  | OUT PCCB * | Ccb
| ) |

Definition at line 133 of file filobsup.c.

References ClearFlag, FlagOn, NULL, PAGED_CODE, TYPE_OF_OPEN, TYPE_OF_OPEN_MASK, and UnopenedFileObject.

Referenced by UdfCommonCleanup(), UdfCommonClose(), UdfCommonCreate(), UdfCommonDevControl(), UdfCommonDirControl(), UdfCommonLockControl(), UdfCommonQueryInfo(), UdfCommonQueryVolInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfDismountVolume(), UdfFastQueryBasicInfo(), UdfFastQueryNetworkInfo(), UdfIsVolumeDirty(), UdfIsVolumeMounted(), UdfLockVolume(), UdfOplockRequest(), and UdfUnlockVolume().

    00141                    :
    00142
    00143     This routine takes a file object and extracts the Fcb and Ccb (possibly NULL)
    00144     and returns the type of open.
    00145
    00146 Arguments:
    00147
    00148     FileObject - Supplies the file object pointer being initialized.
    00149
    00150     Fcb - Address to store the Fcb contained in the file object.
    00151
    00152     Ccb - Address to store the Ccb contained in the file object.
    00153
    00154 Return Value:
    00155
    00156     TYPE_OF_OPEN - Indicates the type of file object.
    00157
    00158 --*/
    00159
    00160 {
    00161     TYPE_OF_OPEN TypeOfOpen;
    00162
    00163     PAGED_CODE();
    00164
    00165     //
    00166     //  If this is an unopened file object then return NULL for the
    00167     //  Fcb/Ccb.  Don't trust any other values in the file object.
    00168     //
    00169
    00170     TypeOfOpen = (TYPE_OF_OPEN) FlagOn( (ULONG_PTR) FileObject->FsContext2,
    00171                                         TYPE_OF_OPEN_MASK );
    00172
    00173     if (TypeOfOpen == UnopenedFileObject) {
    00174
    00175         *Fcb = NULL;
    00176         *Ccb = NULL;
    00177
    00178     } else {
    00179
    00180         //
    00181         //  The Fcb is pointed to by the FsContext field.  The Ccb is in
    00182         //  FsContext2 (after clearing the low three bits).  The low three
    00183         //  bits are the file object type.
    00184         //
    00185
    00186         *Fcb = FileObject->FsContext;
    00187         *Ccb = FileObject->FsContext2;
    00188
    00189         ClearFlag( (ULONG_PTR) *Ccb, TYPE_OF_OPEN_MASK );
    00190     }
    00191
    00192     //
    00193     //  Now return the type of open.
    00194     //
    00195
    00196     return TypeOfOpen;
    00197 }

VOID UdfDeleteCcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PCCB | Ccb
| ) |

Definition at line 2510 of file udfs/strucsup.c.

References ASSERT_CCB, ASSERT_IRP_CONTEXT, NULL, PAGED_CODE, UdfDeallocateCcb, and UdfFreePool().

Referenced by UdfCommonClose().

    02517                    :
    02518
    02519     This routine is called to cleanup and deallocate a Ccb structure.
    02520
    02521 Arguments:
    02522
    02523     Ccb - This is the Ccb to delete.
    02524
    02525 Return Value:
    02526
    02527     None
    02528
    02529 --*/
    02530
    02531 {
    02532     PAGED_CODE();
    02533
    02534     //
    02535     //  Check inputs.
    02536     //
    02537
    02538     ASSERT_IRP_CONTEXT( IrpContext );
    02539     ASSERT_CCB( Ccb );
    02540
    02541     if (Ccb->SearchExpression.Buffer != NULL) {
    02542
    02543         UdfFreePool( &Ccb->SearchExpression.Buffer );
    02544     }
    02545
    02546     UdfDeallocateCcb( IrpContext, Ccb );
    02547     return;
    02548 }

VOID UdfDeleteFcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb
| ) |

Definition at line 2178 of file udfs/strucsup.c.

References ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, FsRtlFreeFileLock(), FsRtlUninitializeOplock(), _VCB::MetadataFcb, NULL, PAGED_CODE, _VCB::RootIndexFcb, UdfDeallocateFcbData, UdfDeallocateFcbIndex, UdfDeleteFcbNonpaged(), UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, UdfUninitializeFcbMcb(), UdfUninitializeVmcb(), _VCB::VatFcb, _VCB::VcbReference, _VCB::VcbUserReference, _VCB::Vmcb, and _VCB::VolumeDasdFcb.

Referenced by UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), and UdfTeardownStructures().

    02185                    :
    02186
    02187     This routine is called to cleanup and deallocate an Fcb.  We know there
    02188     are no references remaining.  We cleanup any auxilary structures and
    02189     deallocate this Fcb.
    02190
    02191 Arguments:
    02192
    02193     Fcb - This is the Fcb to deallcoate.
    02194
    02195 Return Value:
    02196
    02197     None
    02198
    02199 --*/
    02200
    02201 {
    02202     PVCB Vcb = NULL;
    02203
    02204     PAGED_CODE();
    02205
    02206     //
    02207     //  Check inputs.
    02208     //
    02209
    02210     ASSERT_IRP_CONTEXT( IrpContext );
    02211     ASSERT_FCB( Fcb );
    02212
    02213     //
    02214     //  Sanity check the counts and Lcb lists.
    02215     //
    02216
    02217     ASSERT( Fcb->FcbCleanup == 0 );
    02218     ASSERT( Fcb->FcbReference == 0 );
    02219
    02220     ASSERT( IsListEmpty( &Fcb->ChildLcbQueue ));
    02221     ASSERT( IsListEmpty( &Fcb->ParentLcbQueue ));
    02222
    02223     //
    02224     //  Start with the common structures.
    02225     //
    02226
    02227     UdfUninitializeFcbMcb( Fcb );
    02228
    02229     UdfDeleteFcbNonpaged( IrpContext, Fcb->FcbNonpaged );
    02230
    02231     //
    02232     //  Now do the type specific structures.
    02233     //
    02234
    02235     switch (Fcb->NodeTypeCode) {
    02236
    02237     case UDFS_NTC_FCB_INDEX:
    02238
    02239         ASSERT( Fcb->FileObject == NULL );
    02240
    02241         if (Fcb == Fcb->Vcb->RootIndexFcb) {
    02242
    02243             Vcb = Fcb->Vcb;
    02244             Vcb->RootIndexFcb = NULL;
    02245
    02246         } else if (Fcb == Fcb->Vcb->MetadataFcb) {
    02247
    02248             Vcb = Fcb->Vcb;
    02249             Vcb->MetadataFcb = NULL;
    02250
    02251             UdfUninitializeVmcb( &Vcb->Vmcb );
    02252
    02253         } else if (Fcb == Fcb->Vcb->VatFcb) {
    02254
    02255             Vcb = Fcb->Vcb;
    02256             Vcb->VatFcb = NULL;
    02257         }
    02258
    02259         UdfDeallocateFcbIndex( IrpContext, Fcb );
    02260         break;
    02261
    02262     case UDFS_NTC_FCB_DATA :
    02263
    02264         if (Fcb->FileLock != NULL) {
    02265
    02266             FsRtlFreeFileLock( Fcb->FileLock );
    02267         }
    02268
    02269         FsRtlUninitializeOplock( &Fcb->Oplock );
    02270
    02271         if (Fcb == Fcb->Vcb->VolumeDasdFcb) {
    02272
    02273             Vcb = Fcb->Vcb;
    02274             Vcb->VolumeDasdFcb = NULL;
    02275         }
    02276
    02277         UdfDeallocateFcbData( IrpContext, Fcb );
    02278         break;
    02279     }
    02280
    02281     //
    02282     //  Decrement the Vcb reference count if this is a system
    02283     //  Fcb.
    02284     //
    02285
    02286     if (Vcb != NULL) {
    02287
    02288         InterlockedDecrement( &Vcb->VcbReference );
    02289         InterlockedDecrement( &Vcb->VcbUserReference );
    02290     }
    02291
    02292     return;
    02293 }

VOID UdfDeleteInternalStream | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb
| ) |

Definition at line 215 of file udfs/cachesup.c.

References ASSERT_FCB, ASSERT_IRP_CONTEXT, CcUninitializeCacheMap(), NULL, ObDereferenceObject, PAGED_CODE, _FILE_OBJECT::PrivateCacheMap, UdfLockFcb, and UdfUnlockFcb.

Referenced by UdfPurgeVolume(), and UdfTeardownStructures().

    00222                    :
    00223
    00224     This function creates an internal stream file for interaction
    00225     with the cache manager.  The Fcb here can be for either a
    00226     directory stream or for a metadata stream.
    00227
    00228 Arguments:
    00229
    00230     Fcb - Points to the Fcb for this file.  It is either an Index or
    00231         Metadata Fcb.
    00232
    00233 Return Value:
    00234
    00235     None.
    00236
    00237 --*/
    00238
    00239 {
    00240     PFILE_OBJECT FileObject;
    00241
    00242     PAGED_CODE();
    00243
    00244     ASSERT_IRP_CONTEXT( IrpContext );
    00245     ASSERT_FCB( Fcb );
    00246
    00247     //
    00248     //  Lock the Fcb.
    00249     //
    00250
    00251     UdfLockFcb( IrpContext, Fcb );
    00252
    00253     //
    00254     //  Capture the file object.
    00255     //
    00256
    00257     FileObject = Fcb->FileObject;
    00258     Fcb->FileObject = NULL;
    00259
    00260     //
    00261     //  It is now safe to unlock the Fcb.
    00262     //
    00263
    00264     UdfUnlockFcb( IrpContext, Fcb );
    00265
    00266     //
    00267     //  Dereference the file object if present.
    00268     //
    00269
    00270     if (FileObject != NULL) {
    00271
    00272         if (FileObject->PrivateCacheMap != NULL) {
    00273
    00274             CcUninitializeCacheMap( FileObject, NULL, NULL );
    00275         }
    00276
    00277         ObDereferenceObject( FileObject );
    00278     }
    00279
    00280     return;
    00281 }

VOID UdfDeletePcb | ( | IN PPCB | Pcb | ) |

Definition at line 309 of file allocsup.c.

References ASSERT, ExFreePool(), FALSE, FsRtlUninitializeLargeMcb(), Physical, PPARTITION, UdfFreePool(), Uninitialized, and Virtual.

Referenced by UdfDeleteVcb(), UdfInitializePcb(), UdfMountVolume(), and UdfVerifyVolume().

    00315                    :
    00316
    00317     This routine deallocates a Pcb and all ancilliary structures.
    00318
    00319 Arguments:
    00320
    00321     Pcb - Pcb being deleted
    00322
    00323 Return Value:
    00324
    00325     None
    00326
    00327 --*/
    00328
    00329 {
    00330     PPARTITION Partition;
    00331
    00332     if (Pcb->SparingMcb) {
    00333
    00334         FsRtlUninitializeLargeMcb( Pcb->SparingMcb );
    00335         UdfFreePool( &Pcb->SparingMcb );
    00336     }
    00337
    00338     for (Partition = Pcb->Partition;
    00339          Partition < &Pcb->Partition[Pcb->Partitions];
    00340          Partition++) {
    00341
    00342         switch (Partition->Type) {
    00343
    00344             case Physical:
    00345
    00346                 UdfFreePool( &Partition->Physical.PartitionDescriptor );
    00347                 UdfFreePool( &Partition->Physical.SparingMap );
    00348
    00349                 break;
    00350
    00351             case Virtual:
    00352             case Uninitialized:
    00353                 break;
    00354
    00355             default:
    00356
    00357                 ASSERT( FALSE );
    00358                 break;
    00359         }
    00360     }
    00361
    00362     ExFreePool( Pcb );
    00363 }

VOID UdfDeleteVcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PVCB | Vcb
| ) |

Definition at line 1210 of file udfs/strucsup.c.

References ASSERT_EXCLUSIVE_UDFDATA, ASSERT_EXCLUSIVE_VCB, ExDeleteResource, FsRtlNotifyUninitializeSync(), IoDeleteDevice(), NULL, ObDereferenceObject, PAGED_CODE, UdfDeletePcb(), and UdfFreePool().

Referenced by UdfCheckForDismount(), and UdfDismountVcb().

    01217                    :
    01218
    01219     This routine is called to delete a Vcb which failed mount or has been
    01220     dismounted.  The dismount code should have already removed all of the
    01221     open Fcb's.  We do nothing here but clean up other auxilary structures.
    01222
    01223 Arguments:
    01224
    01225     Vcb - Vcb to delete.
    01226
    01227 Return Value:
    01228
    01229     None
    01230
    01231 --*/
    01232
    01233 {
    01234     PAGED_CODE();
    01235
    01236     ASSERT_EXCLUSIVE_UDFDATA;
    01237     ASSERT_EXCLUSIVE_VCB( Vcb );
    01238
    01239     //
    01240     //  If there is a Vpb then we must delete it ourselves.
    01241     //
    01242
    01243     if (Vcb->Vpb != NULL) {
    01244
    01245         UdfFreePool( &Vcb->Vpb );
    01246     }
    01247
    01248     //
    01249     //  Drop the Pcb.
    01250     //
    01251
    01252     if (Vcb->Pcb != NULL) {
    01253
    01254         UdfDeletePcb( Vcb->Pcb );
    01255     }
    01256
    01257     //
    01258     //  Dereference our target if we haven't already done so.
    01259     //
    01260
    01261     if (Vcb->TargetDeviceObject != NULL) {
    01262
    01263         ObDereferenceObject( Vcb->TargetDeviceObject );
    01264     }
    01265
    01266     //
    01267     //  Remove this entry from the global queue.
    01268     //
    01269
    01270     RemoveEntryList( &Vcb->VcbLinks );
    01271
    01272     //
    01273     //  Delete the Vcb and File resources.
    01274     //
    01275
    01276     ExDeleteResource( &Vcb->VcbResource );
    01277     ExDeleteResource( &Vcb->FileResource );
    01278
    01279     //
    01280     //  Uninitialize the notify structures.
    01281     //
    01282
    01283     if (Vcb->NotifySync != NULL) {
    01284
    01285         FsRtlNotifyUninitializeSync( &Vcb->NotifySync );
    01286     }
    01287
    01288     //
    01289     //  Now delete the volume device object.
    01290     //
    01291
    01292     IoDeleteDevice( (PDEVICE_OBJECT) CONTAINING_RECORD( Vcb,
    01293                                                         VOLUME_DEVICE_OBJECT,
    01294                                                         Vcb ));
    01295
    01296     return;
    01297 }

BOOLEAN UdfDismountVcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb
| ) |

Definition at line 365 of file udfs/verfysup.c.

References ASSERT, ASSERT_EXCLUSIVE_UDFDATA, ASSERT_EXCLUSIVE_VCB, ClearFlag, _VPB::DeviceObject, ExAllocatePoolWithTag, FALSE, FlagOn, _VPB::Flags, IO_TYPE_VPB, IoAcquireVpbSpinLock(), IoReleaseVpbSpinLock(), NonPagedPoolMustSucceed, NULL, _VPB::RealDevice, _VPB::ReferenceCount, _VPB::Size, TAG_VPB, TRUE, _VPB::Type, UdfDeleteVcb(), UdfFreePool(), UdfFspClose(), UdfLockVcb, UdfPurgeVolume(), UdfUnlockVcb, VcbDismountInProgress, VPB, _DEVICE_OBJECT::Vpb, VPB_MOUNTED, and VPB_REMOVE_PENDING.

Referenced by UdfCheckForDismount(), and UdfMountVolume().

    00372                    :
    00373
    00374     This routine is called when all of the user references to a volume are
    00375     gone.  We will initiate all of the teardown any system resources.
    00376
    00377     If all of the references to this volume are gone at the end of this routine
    00378     then we will complete the teardown of this Vcb and mark the current Vpb
    00379     as not mounted.  Otherwise we will allocated a new Vpb for this device
    00380     and keep the current Vpb attached to the Vcb.
    00381
    00382 Arguments:
    00383
    00384     Vcb - Vcb for the volume to dismount.
    00385
    00386 Return Value:
    00387
    00388     BOOLEAN - TRUE if we didn't delete the Vcb, FALSE otherwise.
    00389
    00390 --*/
    00391
    00392 {
    00393     PVPB OldVpb;
    00394     PVPB NewVpb;
    00395     BOOLEAN VcbPresent = TRUE;
    00396     KIRQL SavedIrql;
    00397
    00398     BOOLEAN FinalReference;
    00399
    00400     ASSERT_EXCLUSIVE_UDFDATA;
    00401     ASSERT_EXCLUSIVE_VCB( Vcb );
    00402
    00403     UdfLockVcb( IrpContext, Vcb );
    00404
    00405     //
    00406     //  We should only take this path once.
    00407     //
    00408
    00409     ASSERT( Vcb->VcbCondition != VcbDismountInProgress );
    00410
    00411     //
    00412     //  Mark the Vcb as DismountInProgress.
    00413     //
    00414
    00415     Vcb->VcbCondition = VcbDismountInProgress;
    00416
    00417     //
    00418     //  Remove our reference to the internal Fcb's.  The Fcb's will then
    00419     //  be removed in the purge path below.
    00420     //
    00421
    00422     if (Vcb->RootIndexFcb != NULL) {
    00423
    00424         Vcb->RootIndexFcb->FcbReference -= 1;
    00425         Vcb->RootIndexFcb->FcbUserReference -= 1;
    00426     }
    00427
    00428     if (Vcb->MetadataFcb != NULL) {
    00429
    00430         Vcb->MetadataFcb->FcbReference -= 1;
    00431         Vcb->MetadataFcb->FcbUserReference -= 1;
    00432     }
    00433
    00434     if (Vcb->VatFcb != NULL) {
    00435
    00436         Vcb->VatFcb->FcbReference -= 1;
    00437         Vcb->VatFcb->FcbUserReference -= 1;
    00438     }
    00439
    00440     if (Vcb->VolumeDasdFcb != NULL) {
    00441
    00442         Vcb->VolumeDasdFcb->FcbReference -= 1;
    00443         Vcb->VolumeDasdFcb->FcbUserReference -= 1;
    00444     }
    00445
    00446     UdfUnlockVcb( IrpContext, Vcb );
    00447
    00448     //
    00449     //  Purge the volume.
    00450     //
    00451
    00452     UdfPurgeVolume( IrpContext, Vcb, TRUE );
    00453
    00454     //
    00455     //  Empty the delayed and async close queues.
    00456     //
    00457
    00458     UdfFspClose( Vcb );
    00459
    00460     //
    00461     //  Allocate a new Vpb in case we will need it.
    00462     //
    00463
    00464     NewVpb = ExAllocatePoolWithTag( NonPagedPoolMustSucceed, sizeof( VPB ), TAG_VPB );
    00465     RtlZeroMemory( NewVpb, sizeof( VPB ) );
    00466
    00467     OldVpb = Vcb->Vpb;
    00468
    00469     //
    00470     //  Remove the mount volume reference.
    00471     //
    00472
    00473     UdfLockVcb( IrpContext, Vcb );
    00474     Vcb->VcbReference -= 1;
    00475
    00476     //
    00477     //  Acquire the Vpb spinlock to check for Vpb references.
    00478     //
    00479
    00480     IoAcquireVpbSpinLock( &SavedIrql );
    00481
    00482     //
    00483     //  Remember if this is the last reference on this Vcb.  We incremented
    00484     //  the count on the Vpb earlier so we get one last crack it.  If our
    00485     //  reference has gone to zero but the vpb reference count is greater
    00486     //  than zero then the Io system will be responsible for deleting the
    00487     //  Vpb.
    00488     //
    00489
    00490     FinalReference = (BOOLEAN) ((Vcb->VcbReference == 0) &&
    00491                                 (OldVpb->ReferenceCount == 1));
    00492
    00493     //
    00494     //  There is a reference count in the Vpb and in the Vcb.  We have
    00495     //  incremented the reference count in the Vpb to make sure that
    00496     //  we have last crack at it.  If this is a failed mount then we
    00497     //  want to return the Vpb to the IO system to use for the next
    00498     //  mount request.
    00499     //
    00500
    00501     if (OldVpb->RealDevice->Vpb == OldVpb) {
    00502
    00503         //
    00504         //  If not the final reference then swap out the Vpb.  We must
    00505         //  preserve the REMOVE_PENDING flag so that the device is
    00506         //  not remounted in the middle of a PnP remove operation.
    00507         //
    00508
    00509         if (!FinalReference) {
    00510
    00511             NewVpb->Type = IO_TYPE_VPB;
    00512             NewVpb->Size = sizeof( VPB );
    00513             NewVpb->RealDevice = OldVpb->RealDevice;
    00514
    00515             NewVpb->RealDevice->Vpb = NewVpb;
    00516
    00517             NewVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING );
    00518
    00519             NewVpb = NULL;
    00520             IoReleaseVpbSpinLock( SavedIrql );
    00521             UdfUnlockVcb( IrpContext, Vcb );
    00522
    00523         //
    00524         //  We want to leave the Vpb for the IO system.  Mark it
    00525         //  as being not mounted.  Go ahead and delete the Vcb as
    00526         //  well.
    00527         //
    00528
    00529         } else {
    00530
    00531             //
    00532             //  Make sure to remove the last reference on the Vpb.
    00533             //
    00534
    00535             OldVpb->ReferenceCount -= 1;
    00536
    00537             OldVpb->DeviceObject = NULL;
    00538             ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED );
    00539
    00540             //
    00541             //  Clear the Vpb flag so we know not to delete it.
    00542             //
    00543
    00544             Vcb->Vpb = NULL;
    00545
    00546             IoReleaseVpbSpinLock( SavedIrql );
    00547             UdfUnlockVcb( IrpContext, Vcb );
    00548             UdfDeleteVcb( IrpContext, Vcb );
    00549             VcbPresent = FALSE;
    00550         }
    00551
    00552     //
    00553     //  Someone has already swapped in a new Vpb.  If this is the final reference
    00554     //  then the file system is responsible for deleting the Vpb.
    00555     //
    00556
    00557     } else if (FinalReference) {
    00558
    00559         //
    00560         //  Make sure to remove the last reference on the Vpb.
    00561         //
    00562
    00563         OldVpb->ReferenceCount -= 1;
    00564
    00565         IoReleaseVpbSpinLock( SavedIrql );
    00566         UdfUnlockVcb( IrpContext, Vcb );
    00567         UdfDeleteVcb( IrpContext, Vcb );
    00568         VcbPresent = FALSE;
    00569
    00570     //
    00571     //  The current Vpb is no longer the Vpb for the device (the IO system
    00572     //  has already allocated a new one).  We leave our reference in the
    00573     //  Vpb and will be responsible for deleting it at a later time.
    00574     //
    00575
    00576     } else {
    00577
    00578         OldVpb->DeviceObject = NULL;
    00579         ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED );
    00580
    00581         IoReleaseVpbSpinLock( SavedIrql );
    00582         UdfUnlockVcb( IrpContext, Vcb );
    00583     }
    00584
    00585     //
    00586     //  Deallocate the new Vpb if we don't need it.
    00587     //
    00588
    00589     if (NewVpb != NULL) {
    00590
    00591         UdfFreePool( &NewVpb );
    00592     }
    00593
    00594     //
    00595     //  Let our caller know whether the Vcb is still present.
    00596     //
    00597
    00598     return VcbPresent;
    00599 }

VOID UdfDissectName | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PUNICODE_STRING | RemainingName,
|  | OUT PUNICODE_STRING | FinalName
| ) |

Definition at line 96 of file namesup.c.

References Add2Ptr, ASSERT_IRP_CONTEXT, L, PAGED_CODE, and USHORT.

Referenced by UdfCommonCreate(), and UdfFindPrefix().

    00104                    :
    00105
    00106     This routine is called to strip off leading components of the name strings.  We search
    00107     for either the end of the string or separating characters.  The input remaining
    00108     name strings should have neither a trailing or leading backslash.
    00109
    00110 Arguments:
    00111
    00112     RemainingName - Remaining name.
    00113
    00114     FinalName - Location to store next component of name.
    00115
    00116 Return Value:
    00117
    00118     None.
    00119
    00120 --*/
    00121
    00122 {
    00123     ULONG NameLength;
    00124     PWCHAR NextWchar;
    00125
    00126     PAGED_CODE();
    00127
    00128     //
    00129     //  Check inputs.
    00130     //
    00131
    00132     ASSERT_IRP_CONTEXT( IrpContext );
    00133
    00134     //
    00135     //  Find the offset of the next component separators.
    00136     //
    00137
    00138     for (NameLength = 0, NextWchar = RemainingName->Buffer;
    00139          (NameLength < RemainingName->Length) && (*NextWchar != L'\\');
    00140          NameLength += sizeof( WCHAR) , NextWchar += 1);
    00141
    00142     //
    00143     //  Adjust all the strings by this amount.
    00144     //
    00145
    00146     FinalName->Buffer = RemainingName->Buffer;
    00147
    00148     FinalName->MaximumLength = FinalName->Length = (USHORT) NameLength;
    00149
    00150     //
    00151     //  If this is the last component then set the RemainingName lengths to zero.
    00152     //
    00153
    00154     if (NameLength == RemainingName->Length) {
    00155
    00156         RemainingName->Length = 0;
    00157
    00158     //
    00159     //  Otherwise we adjust the string by this amount plus the separating character.
    00160     //
    00161
    00162     } else {
    00163
    00164         RemainingName->MaximumLength -= (USHORT) (NameLength + sizeof( WCHAR ));
    00165         RemainingName->Length -= (USHORT) (NameLength + sizeof( WCHAR ));
    00166         RemainingName->Buffer = Add2Ptr( RemainingName->Buffer,
    00167                                          NameLength + sizeof( WCHAR ),
    00168                                          PWCHAR );
    00169     }
    00170
    00171     return;
    00172 }

INLINE BOOLEAN UdfDomainIdentifierContained | ( | IN PREGID | RegID,
|  | IN PSTRING | Domain,
|  | IN USHORT | RevisionMin,
|  | IN USHORT | RevisionMax
| ) |

Definition at line 2027 of file udfprocs.h.

References NULL, UdfEqualEntityId(), and _UDF_SUFFIX_DOMAIN::UdfRevision.

Referenced by UdfFindVolumeDescriptors(), and UdfInitializePcb().

    02033 {
    02034     PUDF_SUFFIX_DOMAIN DomainSuffix = (PUDF_SUFFIX_DOMAIN) RegID->Suffix;
    02035
    02036 #ifdef UDF_SUPPORT_NONSTANDARD_ALLSTOR
    02037
    02038     //
    02039     //  Disable checking of the UDF revision.
    02040     //
    02041     //  Reason: first drop of Allstor media recorded the version number as
    02042     //      a decimal number, not hex (102 = 0x66)
    02043     //
    02044
    02045     return (UdfEqualEntityId( RegID, Domain, NULL ));
    02046
    02047 #else
    02048
    02049     return ((DomainSuffix->UdfRevision <= RevisionMax && DomainSuffix->UdfRevision >= RevisionMin) &&
    02050             UdfEqualEntityId( RegID, Domain, NULL ));
    02051 #endif
    02052 }

INLINE BOOLEAN UdfEqualCharspec | ( | IN PCHARSPEC | Charspec,
|  | IN PSTRING | Identifier,
|  | IN UCHAR | Type
| ) |

Definition at line 2228 of file udfprocs.h.

References PCHARSPEC, and UdfEqualCountedString().

Referenced by UdfFindVolumeDescriptors().

    02233 {
    02234     return ((Charspec->Type == Type) && UdfEqualCountedString( Identifier, Charspec->Info));
    02235 }

INLINE BOOLEAN UdfEqualCountedString | ( | IN PSTRING | String,
|  | IN PCHAR | Field
| ) |

Definition at line 472 of file udfprocs.h.

References CHAR, and String.

Referenced by UdfEqualCharspec(), and UdfEqualEntityId().

    00476 {
    00477     return (RtlEqualMemory( (CHAR UNALIGNED *)String->Buffer,
    00478                             (CHAR UNALIGNED *)Field,
    00479                             String->Length )                    != 0);
    00480 }

INLINE BOOLEAN UdfEqualEntityId | ( | IN PREGID | RegID,
|  | IN PSTRING | Id,
|  | IN OPTIONAL PSTRING | Suffix
| ) |

Definition at line 1988 of file udfprocs.h.

References Dbg, DebugTrace, NULL, and UdfEqualCountedString().

Referenced by UdfDomainIdentifierContained(), UdfFindVolumeDescriptors(), and UdfUdfIdentifierContained().

    01993 {
    01994
    01995     return (UdfEqualCountedString( Id, RegID->Identifier ) &&
    01996
    01997 #ifndef UDF_SUPPORT_NONSTANDARD_ENTITY_STRINGTERM
    01998
    01999             //
    02000             //  Allow disabling of the check that the identifier
    02001             //  seems to be padded with zero.
    02002             //
    02003             //  Reason: a couple samples that are otherwise useful
    02004             //      padded some identifiers with junk.
    02005             //
    02006
    02007             ((Id->Length == sizeof(RegID->Identifier) ||
    02008               RegID->Identifier[Id->Length] == '\0') ||
    02009
    02010              !DebugTrace(( 0, Dbg,
    02011                            "UdfEqualEntityId, RegID seems to be terminated with junk!\n" ))) &&
    02012 #endif
    02013
    02014             ((Suffix == NULL) || UdfEqualCountedString( Suffix, RegID->Suffix )));
    02015 }

BOOLEAN UdfEquivalentPcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PPCB | Pcb1,
|  | IN PPCB | Pcb2
| ) |

Definition at line 923 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, FALSE, Index, PAGED_CODE, Physical, TRUE, and Virtual.

Referenced by UdfVerifyVolume().

    00931                    :
    00932
    00933     This routine compares two completed Pcbs to see if they appear equivalent.
    00934
    00935 Arguments:
    00936
    00937     Pcb1 - Pcb being compared
    00938
    00939     Pcb2 - Pcb being compared
    00940
    00941 Return Value:
    00942
    00943     BOOLEAN according to whether they are equivalent (TRUE, else FALSE)
    00944
    00945 --*/
    00946
    00947 {
    00948     ULONG Index;
    00949
    00950     PAGED_CODE();
    00951
    00952     //
    00953     //  Check input.
    00954     //
    00955
    00956     ASSERT_IRP_CONTEXT( IrpContext );
    00957
    00958     if (Pcb1->Partitions != Pcb2->Partitions) {
    00959
    00960         return FALSE;
    00961     }
    00962
    00963     for (Index = 0;
    00964          Index < Pcb1->Partitions;
    00965          Index++) {
    00966
    00967         //
    00968         //  First check that the partitions are of the same type.
    00969         //
    00970
    00971         if (Pcb1->Partition[Index].Type != Pcb2->Partition[Index].Type) {
    00972
    00973             return FALSE;
    00974         }
    00975
    00976         //
    00977         //  Now the map content must be the same ...
    00978         //
    00979
    00980         switch (Pcb1->Partition[Index].Type) {
    00981
    00982             case Physical:
    00983
    00984                 if (Pcb1->Partition[Index].Physical.PartitionNumber != Pcb2->Partition[Index].Physical.PartitionNumber ||
    00985                     Pcb1->Partition[Index].Physical.Length != Pcb2->Partition[Index].Physical.Length ||
    00986                     Pcb1->Partition[Index].Physical.Start != Pcb2->Partition[Index].Physical.Start) {
    00987
    00988                     return FALSE;
    00989                 }
    00990                 break;
    00991
    00992             case Virtual:
    00993
    00994                 if (Pcb1->Partition[Index].Virtual.RelatedReference != Pcb2->Partition[Index].Virtual.RelatedReference) {
    00995
    00996                     return FALSE;
    00997                 }
    00998                 break;
    00999
    01000             default:
    01001
    01002                 ASSERT( FALSE);
    01003                 return FALSE;
    01004                 break;
    01005         }
    01006     }
    01007
    01008     //
    01009     //  All map elements were equivalent.
    01010     //
    01011
    01012     return TRUE;
    01013 }

LONG UdfExceptionFilter | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PEXCEPTION_POINTERS | ExceptionPointer
| ) |

Definition at line 448 of file udfdata.c.

References ASSERT_OPTIONAL_IRP_CONTEXT, Dbg, DebugTrace, EXCEPTION_EXECUTE_HANDLER, FALSE, FsRtlIsNtstatusExpected(), NTSTATUS(), TRUE, and UdfBugCheck.

Referenced by UdfFindFileSetDescriptor(), UdfFsdDispatch(), UdfFspDispatch(), UdfOpenObjectByFileId(), UdfPerformVerify(), and UdfProcessException().

    00455                    :
    00456
    00457     This routine is used to decide whether we will handle a raised exception
    00458     status.  If UDFS explicitly raised an error then this status is already
    00459     in the IrpContext.  We choose which is the correct status code and
    00460     either indicate that we will handle the exception or bug-check the system.
    00461
    00462 Arguments:
    00463
    00464     ExceptionCode - Supplies the exception code to being checked.
    00465
    00466 Return Value:
    00467
    00468     ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks
    00469
    00470 --*/
    00471
    00472 {
    00473     NTSTATUS ExceptionCode;
    00474     BOOLEAN TestStatus = TRUE;
    00475
    00476     ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
    00477
    00478     ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
    00479
    00480     DebugTrace(( 0, Dbg,
    00481                  "UdfExceptionFilter: %08x (exr %08x cxr %08x)\n",
    00482                  ExceptionCode,
    00483                  ExceptionPointer->ExceptionRecord,
    00484                  ExceptionPointer->ContextRecord ));
    00485
    00486
    00487     //
    00488     // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
    00489     // from the exception record.
    00490     //
    00491
    00492     if ((ExceptionCode == STATUS_IN_PAGE_ERROR) &&
    00493         (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) {
    00494
    00495         ExceptionCode = (NTSTATUS) ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
    00496     }
    00497
    00498     //
    00499     //  If there is an Irp context then check which status code to use.
    00500     //
    00501
    00502     if (ARGUMENT_PRESENT( IrpContext )) {
    00503
    00504         if (IrpContext->ExceptionStatus == STATUS_SUCCESS) {
    00505
    00506             //
    00507             //  Store the real status into the IrpContext.
    00508             //
    00509
    00510             IrpContext->ExceptionStatus = ExceptionCode;
    00511
    00512         } else {
    00513
    00514             //
    00515             //  No need to test the status code if we raised it ourselves.
    00516             //
    00517
    00518             TestStatus = FALSE;
    00519         }
    00520     }
    00521
    00522     //
    00523     //  Bug check if this status is not supported.
    00524     //
    00525
    00526     if (TestStatus && !FsRtlIsNtstatusExpected( ExceptionCode )) {
    00527
    00528         UdfBugCheck( (ULONG_PTR) ExceptionPointer->ExceptionRecord,
    00529                      (ULONG_PTR) ExceptionPointer->ContextRecord,
    00530                      (ULONG_PTR) ExceptionPointer->ExceptionRecord->ExceptionAddress );
    00531
    00532     }
    00533
    00534     return EXCEPTION_EXECUTE_HANDLER;
    00535 }

TYPE_OF_OPEN UdfFastDecodeFileObject | ( | IN PFILE_OBJECT | FileObject,
|  | OUT PFCB * | Fcb
| ) |

Definition at line 201 of file filobsup.c.

References ASSERT_FILE_OBJECT, FlagOn, PAGED_CODE, TYPE_OF_OPEN, and TYPE_OF_OPEN_MASK.

Referenced by UdfFastLock(), UdfFastQueryStdInfo(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), and UdfFastUnlockSingle().

    00208                    :
    00209
    00210     This procedure takes a pointer to a file object, that has already been
    00211     opened by Udfs and does a quick decode operation.  It will only return
    00212     a non null value if the file object is a user file open
    00213
    00214 Arguments:
    00215
    00216     FileObject - Supplies the file object pointer being interrogated
    00217
    00218     Fcb - Address to store Fcb if this is a user file object.  NULL
    00219         otherwise.
    00220
    00221 Return Value:
    00222
    00223     TYPE_OF_OPEN - type of open of this file object.
    00224
    00225 --*/
    00226
    00227 {
    00228     PAGED_CODE();
    00229
    00230     ASSERT_FILE_OBJECT( FileObject );
    00231
    00232     //
    00233     //  The Fcb is in the FsContext field.  The type of open is in the low
    00234     //  bits of the Ccb.
    00235     //
    00236
    00237     *Fcb = FileObject->FsContext;
    00238
    00239     return (TYPE_OF_OPEN) FlagOn( (ULONG_PTR) FileObject->FsContext2, TYPE_OF_OPEN_MASK );
    00240 }

INLINE VOID UdfFastInitializeIcbContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext
| ) |

Definition at line 1872 of file udfprocs.h.

Referenced by UdfInitializeCompoundDirContext().

    01876 {
    01877
    01878     RtlZeroMemory( IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
    01879 }

BOOLEAN UdfFastIoCheckIfPossible | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN ULONG | Length,
|  | IN BOOLEAN | Wait,
|  | IN ULONG | LockKey,
|  | IN BOOLEAN | CheckForReadOperation,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 972 of file udfdata.c.

References PAGED_CODE, and TRUE.

Referenced by UdfInitializeGlobalData().

    00985                    :
    00986
    00987     This routine checks if fast i/o is possible for a read/write operation
    00988
    00989 Arguments:
    00990
    00991     FileObject - Supplies the file object used in the query
    00992
    00993     FileOffset - Supplies the starting byte offset for the read/write operation
    00994
    00995     Length - Supplies the length, in bytes, of the read/write operation
    00996
    00997     Wait - Indicates if we can wait
    00998
    00999     LockKey - Supplies the lock key
    01000
    01001     CheckForReadOperation - Indicates if this is a check for a read or write
    01002         operation
    01003
    01004     IoStatus - Receives the status of the operation if our return value is
    01005         FastIoReturnError
    01006
    01007 Return Value:
    01008
    01009     BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
    01010         to take the long route.
    01011
    01012 --*/
    01013
    01014 {
    01015     PAGED_CODE();
    01016
    01017     return TRUE;
    01018 }

BOOLEAN UdfFastLock | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN PLARGE_INTEGER | Length,
|  | PEPROCESS | ProcessId,
|  | ULONG | Key,
|  | BOOLEAN | FailImmediately,
|  | BOOLEAN | ExclusiveLock,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 152 of file lockctrl.c.

References ASSERT_FILE_OBJECT, FALSE, FastIoIsPossible, FsRtlEnterFileSystem, FsRtlExitFileSystem, FsRtlFastLock, FsRtlOplockIsFastIoPossible(), Key, NULL, PAGED_CODE, TRUE, try_leave, TYPE_OF_OPEN, UdfCreateFileLock(), UdfFastDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

    00166                    :
    00167
    00168     This is a call back routine for doing the fast lock call.
    00169
    00170 Arguments:
    00171
    00172     FileObject - Supplies the file object used in this operation
    00173
    00174     FileOffset - Supplies the file offset used in this operation
    00175
    00176     Length - Supplies the length used in this operation
    00177
    00178     ProcessId - Supplies the process ID used in this operation
    00179
    00180     Key - Supplies the key used in this operation
    00181
    00182     FailImmediately - Indicates if the request should fail immediately
    00183         if the lock cannot be granted.
    00184
    00185     ExclusiveLock - Indicates if this is a request for an exclusive or
    00186         shared lock
    00187
    00188     IoStatus - Receives the Status if this operation is successful
    00189
    00190 Return Value:
    00191
    00192     BOOLEAN - TRUE if this operation completed and FALSE if caller
    00193         needs to take the long route.
    00194
    00195 --*/
    00196
    00197 {
    00198     BOOLEAN Results = FALSE;
    00199
    00200     PFCB Fcb;
    00201     TYPE_OF_OPEN TypeOfOpen;
    00202
    00203     PAGED_CODE();
    00204
    00205     ASSERT_FILE_OBJECT( FileObject );
    00206
    00207     IoStatus->Information = 0;
    00208
    00209     //
    00210     //  Decode the type of file object we're being asked to process and
    00211     //  make sure that is is only a user file open.
    00212     //
    00213
    00214     TypeOfOpen = UdfFastDecodeFileObject( FileObject, &Fcb );
    00215
    00216     if (TypeOfOpen != UserFileOpen) {
    00217
    00218         IoStatus->Status = STATUS_INVALID_PARAMETER;
    00219         return TRUE;
    00220     }
    00221
    00222     //
    00223     //  Only deal with 'good' Fcb's.
    00224     //
    00225
    00226     if (!UdfVerifyFcbOperation( NULL, Fcb )) {
    00227
    00228         return FALSE;
    00229     }
    00230
    00231     FsRtlEnterFileSystem();
    00232
    00233     //
    00234     //  Use a try-finally to facilitate cleanup.
    00235     //
    00236
    00237     try {
    00238
    00239         //
    00240         //  We check whether we can proceed based on the state of the file oplocks.
    00241         //
    00242
    00243         if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
    00244
    00245             try_leave( NOTHING );
    00246         }
    00247
    00248         //
    00249         //  If we don't have a file lock, then get one now.
    00250         //
    00251
    00252         if ((Fcb->FileLock == NULL) && !UdfCreateFileLock( NULL, Fcb, FALSE )) {
    00253
    00254             try_leave( NOTHING );
    00255         }
    00256
    00257         //
    00258         //  Now call the FsRtl routine to perform the lock request.
    00259         //
    00260
    00261         if (Results = FsRtlFastLock( Fcb->FileLock,
    00262                                      FileObject,
    00263                                      FileOffset,
    00264                                      Length,
    00265                                      ProcessId,
    00266                                      Key,
    00267                                      FailImmediately,
    00268                                      ExclusiveLock,
    00269                                      IoStatus,
    00270                                      NULL,
    00271                                      FALSE )) {
    00272
    00273             //
    00274             //  Set the flag indicating if Fast I/O is questionable.  We
    00275             //  only change this flag if the current state is possible.
    00276             //  Retest again after synchronizing on the header.
    00277             //
    00278
    00279             if (Fcb->IsFastIoPossible == FastIoIsPossible) {
    00280
    00281                 UdfLockFcb( NULL, Fcb );
    00282                 Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00283                 UdfUnlockFcb( NULL, Fcb );
    00284             }
    00285         }
    00286
    00287     } finally {
    00288
    00289         FsRtlExitFileSystem();
    00290     }
    00291
    00292     return Results;
    00293 }

BOOLEAN UdfFastQueryBasicInfo | ( | IN PFILE_OBJECT | FileObject,
|  | IN BOOLEAN | Wait,
|  | IN OUT PFILE_BASIC_INFORMATION | Buffer,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 496 of file fileinfo.c.

References _TIMESTAMP_BUNDLE::AccessTime, ASSERT, ASSERT_FILE_OBJECT, Buffer, _TIMESTAMP_BUNDLE::CreationTime, ExAcquireResourceShared, ExReleaseResource, FALSE, FCB_STATE_INITIALIZED, _FCB::FcbState, _FCB::FileAttributes, FlagOn, FsRtlEnterFileSystem, FsRtlExitFileSystem, _TIMESTAMP_BUNDLE::ModificationTime, NULL, PAGED_CODE, _FCB::Timestamps, TRUE, TYPE_OF_OPEN, UdfDecodeFileObject(), UdfGetExtraFileAttributes(), UdfVerifyFcbOperation(), UserDirectoryOpen, and UserFileOpen.

    00506                    :
    00507
    00508     This routine is for the fast query call for basic file information.
    00509
    00510 Arguments:
    00511
    00512     FileObject - Supplies the file object used in this operation
    00513
    00514     Wait - Indicates if we are allowed to wait for the information
    00515
    00516     Buffer - Supplies the output buffer to receive the basic information
    00517
    00518     IoStatus - Receives the final status of the operation
    00519
    00520 Return Value:
    00521
    00522     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
    00523         needs to take the long route.
    00524
    00525 --*/
    00526
    00527 {
    00528     BOOLEAN Result = FALSE;
    00529     TYPE_OF_OPEN TypeOfOpen;
    00530
    00531     PFCB Fcb;
    00532     PCCB Ccb;
    00533
    00534     PAGED_CODE();
    00535
    00536     ASSERT_FILE_OBJECT( FileObject );
    00537
    00538     FsRtlEnterFileSystem();
    00539
    00540     //
    00541     //  Decode the file object to find the type of open and the data
    00542     //  structures.
    00543     //
    00544
    00545     TypeOfOpen = UdfDecodeFileObject( FileObject, &Fcb, &Ccb );
    00546
    00547     //
    00548     //  We only support this request on user file or directory objects.
    00549     //
    00550
    00551     ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ));
    00552
    00553     if (TypeOfOpen != UserFileOpen && TypeOfOpen != UserDirectoryOpen) {
    00554
    00555         FsRtlExitFileSystem();
    00556         return FALSE;
    00557     }
    00558
    00559     //
    00560     //  Acquire the file shared to access the Fcb.
    00561     //
    00562
    00563     if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
    00564
    00565         FsRtlExitFileSystem();
    00566         return FALSE;
    00567     }
    00568
    00569     //
    00570     //  Use a try-finally to facilitate cleanup.
    00571     //
    00572
    00573     try {
    00574
    00575         //
    00576         //  Only deal with 'good' Fcb's.
    00577         //
    00578
    00579         if (UdfVerifyFcbOperation( NULL, Fcb )) {
    00580
    00581             //
    00582             //  Fill in the input buffer from the Fcb fields.
    00583             //
    00584
    00585             Buffer->CreationTime = Fcb->Timestamps.CreationTime;
    00586             Buffer->LastWriteTime =
    00587             Buffer->ChangeTime =  Fcb->Timestamps.ModificationTime;
    00588             Buffer->LastAccessTime = Fcb->Timestamps.AccessTime;
    00589
    00590             Buffer->FileAttributes = Fcb->FileAttributes | UdfGetExtraFileAttributes( Ccb );
    00591
    00592             //
    00593             //  Update the IoStatus block with the size of this data.
    00594             //
    00595
    00596             IoStatus->Status = STATUS_SUCCESS;
    00597             IoStatus->Information = sizeof( FILE_BASIC_INFORMATION );
    00598
    00599             Result = TRUE;
    00600         }
    00601
    00602     } finally {
    00603
    00604         ExReleaseResource( Fcb->Resource );
    00605
    00606         FsRtlExitFileSystem();
    00607     }
    00608
    00609     return Result;
    00610 }

BOOLEAN UdfFastQueryNetworkInfo | ( | IN PFILE_OBJECT | FileObject,
|  | IN BOOLEAN | Wait,
|  | OUT PFILE_NETWORK_OPEN_INFORMATION | Buffer,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 740 of file fileinfo.c.

References _TIMESTAMP_BUNDLE::AccessTime, ASSERT_FILE_OBJECT, Buffer, _TIMESTAMP_BUNDLE::CreationTime, ExAcquireResourceShared, ExReleaseResource, FALSE, _FCB::FileAttributes, FlagOn, FsRtlEnterFileSystem, FsRtlExitFileSystem, _TIMESTAMP_BUNDLE::ModificationTime, NULL, PAGED_CODE, _FCB::Timestamps, TRUE, TYPE_OF_OPEN, UdfDecodeFileObject(), UdfGetExtraFileAttributes(), UdfVerifyFcbOperation(), UserDirectoryOpen, and UserFileOpen.

    00750                    :
    00751
    00752     This routine is for the fast query call for network file information.
    00753
    00754 Arguments:
    00755
    00756     FileObject - Supplies the file object used in this operation
    00757
    00758     Wait - Indicates if we are allowed to wait for the information
    00759
    00760     Buffer - Supplies the output buffer to receive the basic information
    00761
    00762     IoStatus - Receives the final status of the operation
    00763
    00764 Return Value:
    00765
    00766     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
    00767         needs to take the long route.
    00768
    00769 --*/
    00770
    00771 {
    00772     BOOLEAN Result = FALSE;
    00773     TYPE_OF_OPEN TypeOfOpen;
    00774
    00775     PFCB Fcb;
    00776     PCCB Ccb;
    00777
    00778     PAGED_CODE();
    00779
    00780     ASSERT_FILE_OBJECT( FileObject );
    00781
    00782     FsRtlEnterFileSystem();
    00783
    00784     //
    00785     //  Decode the file object to find the type of open and the data
    00786     //  structures.
    00787     //
    00788
    00789     TypeOfOpen = UdfDecodeFileObject( FileObject, &Fcb, &Ccb );
    00790
    00791     //
    00792     //  We only support this request on user file or directory objects.
    00793     //
    00794
    00795     if (TypeOfOpen != UserFileOpen && TypeOfOpen != UserDirectoryOpen) {
    00796
    00797         FsRtlExitFileSystem();
    00798         return FALSE;
    00799     }
    00800
    00801     //
    00802     //  Acquire the file shared to access the Fcb.
    00803     //
    00804
    00805     if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
    00806
    00807         FsRtlExitFileSystem();
    00808         return FALSE;
    00809     }
    00810
    00811     //
    00812     //  Use a try-finally to facilitate cleanup.
    00813     //
    00814
    00815     try {
    00816
    00817         //
    00818         //  Only deal with 'good' Fcb's.
    00819         //
    00820
    00821         if (UdfVerifyFcbOperation( NULL, Fcb )) {
    00822
    00823             //
    00824             //  Fill in the input buffer from the Fcb fields.
    00825             //
    00826
    00827             Buffer->CreationTime = Fcb->Timestamps.CreationTime;
    00828             Buffer->LastWriteTime =
    00829             Buffer->ChangeTime =  Fcb->Timestamps.ModificationTime;
    00830             Buffer->LastAccessTime = Fcb->Timestamps.AccessTime;
    00831
    00832             Buffer->FileAttributes = Fcb->FileAttributes | UdfGetExtraFileAttributes( Ccb );
    00833
    00834             //
    00835             //  Check whether this is a directory.
    00836             //
    00837
    00838             if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
    00839
    00840                 Buffer->AllocationSize.QuadPart =
    00841                 Buffer->EndOfFile.QuadPart = 0;
    00842
    00843             } else {
    00844
    00845                 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
    00846                 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
    00847             }
    00848
    00849             //
    00850             //  Update the IoStatus block with the size of this data.
    00851             //
    00852
    00853             IoStatus->Status = STATUS_SUCCESS;
    00854             IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );
    00855
    00856             Result = TRUE;
    00857         }
    00858
    00859     } finally {
    00860
    00861         ExReleaseResource( Fcb->Resource );
    00862
    00863         FsRtlExitFileSystem();
    00864     }
    00865
    00866     return Result;
    00867 }

BOOLEAN UdfFastQueryStdInfo | ( | IN PFILE_OBJECT | FileObject,
|  | IN BOOLEAN | Wait,
|  | IN OUT PFILE_STANDARD_INFORMATION | Buffer,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 614 of file fileinfo.c.

References ASSERT_FILE_OBJECT, Buffer, ExAcquireResourceShared, ExReleaseResource, FALSE, _FCB::FileAttributes, FlagOn, FsRtlEnterFileSystem, FsRtlExitFileSystem, _FCB::LinkCount, NULL, PAGED_CODE, TRUE, TYPE_OF_OPEN, UdfFastDecodeFileObject(), UdfVerifyFcbOperation(), UserDirectoryOpen, and UserFileOpen.

    00624                    :
    00625
    00626     This routine is for the fast query call for standard file information.
    00627
    00628 Arguments:
    00629
    00630     FileObject - Supplies the file object used in this operation
    00631
    00632     Wait - Indicates if we are allowed to wait for the information
    00633
    00634     Buffer - Supplies the output buffer to receive the basic information
    00635
    00636     IoStatus - Receives the final status of the operation
    00637
    00638 Return Value:
    00639
    00640     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
    00641         needs to take the long route.
    00642
    00643 --*/
    00644
    00645 {
    00646     BOOLEAN Result = FALSE;
    00647     TYPE_OF_OPEN TypeOfOpen;
    00648
    00649     PFCB Fcb;
    00650
    00651     PAGED_CODE();
    00652
    00653     ASSERT_FILE_OBJECT( FileObject );
    00654
    00655     FsRtlEnterFileSystem();
    00656
    00657     //
    00658     //  Decode the file object to find the type of open and the data
    00659     //  structures.
    00660     //
    00661
    00662     TypeOfOpen = UdfFastDecodeFileObject( FileObject, &Fcb );
    00663
    00664     //
    00665     //  We only support this request on initialized user file or directory objects.
    00666     //
    00667
    00668     if (TypeOfOpen != UserFileOpen && TypeOfOpen != UserDirectoryOpen) {
    00669
    00670         FsRtlExitFileSystem();
    00671         return FALSE;
    00672     }
    00673
    00674     //
    00675     //  Acquire the file shared to access the Fcb.
    00676     //
    00677
    00678     if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
    00679
    00680         FsRtlExitFileSystem();
    00681         return FALSE;
    00682     }
    00683
    00684     //
    00685     //  Use a try-finally to facilitate cleanup.
    00686     //
    00687
    00688     try {
    00689
    00690         //
    00691         //  Only deal with 'good' Fcb's.
    00692         //
    00693
    00694         if (UdfVerifyFcbOperation( NULL, Fcb )) {
    00695
    00696             //
    00697             //  Check whether this is a directory.
    00698             //
    00699
    00700             if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
    00701
    00702                 Buffer->AllocationSize.QuadPart =
    00703                 Buffer->EndOfFile.QuadPart = 0;
    00704
    00705                 Buffer->Directory = TRUE;
    00706
    00707             } else {
    00708
    00709                 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
    00710                 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
    00711
    00712                 Buffer->Directory = FALSE;
    00713             }
    00714
    00715             Buffer->NumberOfLinks = Fcb->LinkCount;
    00716             Buffer->DeletePending = FALSE;
    00717
    00718             //
    00719             //  Update the IoStatus block with the size of this data.
    00720             //
    00721
    00722             IoStatus->Status = STATUS_SUCCESS;
    00723             IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION );
    00724
    00725             Result = TRUE;
    00726         }
    00727
    00728     } finally {
    00729
    00730         ExReleaseResource( Fcb->Resource );
    00731
    00732         FsRtlExitFileSystem();
    00733     }
    00734
    00735     return Result;
    00736 }

BOOLEAN UdfFastUnlockAll | ( | IN PFILE_OBJECT | FileObject,
|  | PEPROCESS | ProcessId,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 436 of file lockctrl.c.

References FALSE, FsRtlEnterFileSystem, FsRtlExitFileSystem, FsRtlFastUnlockAll(), FsRtlOplockIsFastIoPossible(), NULL, PAGED_CODE, TRUE, try_leave, TYPE_OF_OPEN, UdfCreateFileLock(), UdfFastDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

    00445                    :
    00446
    00447     This is a call back routine for doing the fast unlock all call.
    00448
    00449 Arguments:
    00450
    00451     FileObject - Supplies the file object used in this operation
    00452
    00453     ProcessId - Supplies the process ID used in this operation
    00454
    00455     Status - Receives the Status if this operation is successful
    00456
    00457 Return Value:
    00458
    00459     BOOLEAN - TRUE if this operation completed and FALSE if caller
    00460         needs to take the long route.
    00461
    00462 --*/
    00463
    00464 {
    00465     BOOLEAN Results = FALSE;
    00466     TYPE_OF_OPEN TypeOfOpen;
    00467     PFCB Fcb;
    00468
    00469     PAGED_CODE();
    00470
    00471     IoStatus->Information = 0;
    00472
    00473     //
    00474     //  Decode the type of file object we're being asked to process and
    00475     //  make sure that is is only a user file open.
    00476     //
    00477
    00478     TypeOfOpen = UdfFastDecodeFileObject( FileObject, &Fcb );
    00479
    00480     if (TypeOfOpen != UserFileOpen) {
    00481
    00482         IoStatus->Status = STATUS_INVALID_PARAMETER;
    00483         return TRUE;
    00484     }
    00485
    00486     //
    00487     //  Only deal with 'good' Fcb's.
    00488     //
    00489
    00490     if (!UdfVerifyFcbOperation( NULL, Fcb )) {
    00491
    00492         return FALSE;
    00493     }
    00494
    00495     //
    00496     //  If there is no lock then return immediately.
    00497     //
    00498
    00499     if (Fcb->FileLock == NULL) {
    00500
    00501         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
    00502         return TRUE;
    00503     }
    00504
    00505     FsRtlEnterFileSystem();
    00506
    00507     try {
    00508
    00509         //
    00510         //  We check whether we can proceed based on the state of the file oplocks.
    00511         //
    00512
    00513         if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
    00514
    00515             try_leave( NOTHING );
    00516         }
    00517
    00518         //
    00519         //  If we don't have a file lock, then get one now.
    00520         //
    00521
    00522         if ((Fcb->FileLock == NULL) && !UdfCreateFileLock( NULL, Fcb, FALSE )) {
    00523
    00524             try_leave( NOTHING );
    00525         }
    00526
    00527         //
    00528         //  Now call the FsRtl routine to do the actual processing of the
    00529         //  Lock request.  The call will always succeed.
    00530         //
    00531
    00532         Results = TRUE;
    00533         IoStatus->Status = FsRtlFastUnlockAll( Fcb->FileLock,
    00534                                                FileObject,
    00535                                                ProcessId,
    00536                                                NULL );
    00537
    00538
    00539         //
    00540         //  Set the flag indicating if Fast I/O is possible
    00541         //
    00542
    00543         UdfLockFcb( IrpContext, Fcb );
    00544         Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00545         UdfUnlockFcb( IrpContext, Fcb );
    00546
    00547     } finally {
    00548
    00549         FsRtlExitFileSystem();
    00550     }
    00551
    00552     return Results;
    00553 }

BOOLEAN UdfFastUnlockAllByKey | ( | IN PFILE_OBJECT | FileObject,
|  | PVOID | ProcessId,
|  | ULONG | Key,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 557 of file lockctrl.c.

References FALSE, FsRtlEnterFileSystem, FsRtlExitFileSystem, FsRtlFastUnlockAllByKey(), FsRtlOplockIsFastIoPossible(), Key, NULL, PAGED_CODE, TRUE, try_leave, TYPE_OF_OPEN, UdfCreateFileLock(), UdfFastDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

    00567                    :
    00568
    00569     This is a call back routine for doing the fast unlock all by key call.
    00570
    00571 Arguments:
    00572
    00573     FileObject - Supplies the file object used in this operation
    00574
    00575     ProcessId - Supplies the process ID used in this operation
    00576
    00577     Key - Supplies the key used in this operation
    00578
    00579     Status - Receives the Status if this operation is successful
    00580
    00581 Return Value:
    00582
    00583     BOOLEAN - TRUE if this operation completed and FALSE if caller
    00584         needs to take the long route.
    00585
    00586 --*/
    00587
    00588 {
    00589     BOOLEAN Results = FALSE;
    00590     TYPE_OF_OPEN TypeOfOpen;
    00591     PFCB Fcb;
    00592
    00593     PAGED_CODE();
    00594
    00595     IoStatus->Information = 0;
    00596
    00597     //
    00598     //  Decode the type of file object we're being asked to process and
    00599     //  make sure that is is only a user file open.
    00600     //
    00601
    00602     TypeOfOpen = UdfFastDecodeFileObject( FileObject, &Fcb );
    00603
    00604     if (TypeOfOpen != UserFileOpen) {
    00605
    00606         IoStatus->Status = STATUS_INVALID_PARAMETER;
    00607         return TRUE;
    00608     }
    00609
    00610     //
    00611     //  Only deal with 'good' Fcb's.
    00612     //
    00613
    00614     if (!UdfVerifyFcbOperation( NULL, Fcb )) {
    00615
    00616         return FALSE;
    00617     }
    00618
    00619     //
    00620     //  If there is no lock then return immediately.
    00621     //
    00622
    00623     if (Fcb->FileLock == NULL) {
    00624
    00625         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
    00626         return TRUE;
    00627     }
    00628
    00629     FsRtlEnterFileSystem();
    00630
    00631     try {
    00632
    00633         //
    00634         //  We check whether we can proceed based on the state of the file oplocks.
    00635         //
    00636
    00637         if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
    00638
    00639             try_leave( NOTHING );
    00640         }
    00641
    00642         //
    00643         //  If we don't have a file lock, then get one now.
    00644         //
    00645
    00646         if ((Fcb->FileLock == NULL) && !UdfCreateFileLock( NULL, Fcb, FALSE )) {
    00647
    00648             try_leave( NOTHING );
    00649         }
    00650
    00651         //
    00652         //  Now call the FsRtl routine to do the actual processing of the
    00653         //  Lock request.  The call will always succeed.
    00654         //
    00655
    00656         Results = TRUE;
    00657         IoStatus->Status = FsRtlFastUnlockAllByKey( Fcb->FileLock,
    00658                                                     FileObject,
    00659                                                     ProcessId,
    00660                                                     Key,
    00661                                                     NULL );
    00662
    00663
    00664         //
    00665         //  Set the flag indicating if Fast I/O is possible
    00666         //
    00667
    00668         UdfLockFcb( IrpContext, Fcb );
    00669         Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00670         UdfUnlockFcb( IrpContext, Fcb );
    00671
    00672     } finally {
    00673
    00674         FsRtlExitFileSystem();
    00675     }
    00676
    00677     return Results;
    00678 }

BOOLEAN UdfFastUnlockSingle | ( | IN PFILE_OBJECT | FileObject,
|  | IN PLARGE_INTEGER | FileOffset,
|  | IN PLARGE_INTEGER | Length,
|  | PEPROCESS | ProcessId,
|  | ULONG | Key,
|  | OUT PIO_STATUS_BLOCK | IoStatus,
|  | IN PDEVICE_OBJECT | DeviceObject
| ) |

Definition at line 297 of file lockctrl.c.

References FALSE, FastIoIsPossible, FsRtlAreThereCurrentFileLocks, FsRtlEnterFileSystem, FsRtlExitFileSystem, FsRtlFastUnlockSingle(), FsRtlOplockIsFastIoPossible(), Key, NULL, PAGED_CODE, TRUE, try_leave, TYPE_OF_OPEN, UdfCreateFileLock(), UdfFastDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

    00309                    :
    00310
    00311     This is a call back routine for doing the fast unlock single call.
    00312
    00313 Arguments:
    00314
    00315     FileObject - Supplies the file object used in this operation
    00316
    00317     FileOffset - Supplies the file offset used in this operation
    00318
    00319     Length - Supplies the length used in this operation
    00320
    00321     ProcessId - Supplies the process ID used in this operation
    00322
    00323     Key - Supplies the key used in this operation
    00324
    00325     Status - Receives the Status if this operation is successful
    00326
    00327 Return Value:
    00328
    00329     BOOLEAN - TRUE if this operation completed and FALSE if caller
    00330         needs to take the long route.
    00331
    00332 --*/
    00333
    00334 {
    00335     BOOLEAN Results = FALSE;
    00336     TYPE_OF_OPEN TypeOfOpen;
    00337     PFCB Fcb;
    00338
    00339     PAGED_CODE();
    00340
    00341     IoStatus->Information = 0;
    00342
    00343     //
    00344     //  Decode the type of file object we're being asked to process and
    00345     //  make sure that is is only a user file open.
    00346     //
    00347
    00348     TypeOfOpen = UdfFastDecodeFileObject( FileObject, &Fcb );
    00349
    00350     if (TypeOfOpen != UserFileOpen) {
    00351
    00352         IoStatus->Status = STATUS_INVALID_PARAMETER;
    00353         return TRUE;
    00354     }
    00355
    00356     //
    00357     //  Only deal with 'good' Fcb's.
    00358     //
    00359
    00360     if (!UdfVerifyFcbOperation( NULL, Fcb )) {
    00361
    00362         return FALSE;
    00363     }
    00364
    00365     //
    00366     //  If there is no lock then return immediately.
    00367     //
    00368
    00369     if (Fcb->FileLock == NULL) {
    00370
    00371         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
    00372         return TRUE;
    00373     }
    00374
    00375     FsRtlEnterFileSystem();
    00376
    00377     try {
    00378
    00379         //
    00380         //  We check whether we can proceed based on the state of the file oplocks.
    00381         //
    00382
    00383         if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
    00384
    00385             try_leave( NOTHING );
    00386         }
    00387
    00388         //
    00389         //  If we don't have a file lock, then get one now.
    00390         //
    00391
    00392         if ((Fcb->FileLock == NULL) && !UdfCreateFileLock( NULL, Fcb, FALSE )) {
    00393
    00394             try_leave( NOTHING );
    00395         }
    00396
    00397         //
    00398         //  Now call the FsRtl routine to do the actual processing of the
    00399         //  Lock request.  The call will always succeed.
    00400         //
    00401
    00402         Results = TRUE;
    00403         IoStatus->Status = FsRtlFastUnlockSingle( Fcb->FileLock,
    00404                                                   FileObject,
    00405                                                   FileOffset,
    00406                                                   Length,
    00407                                                   ProcessId,
    00408                                                   Key,
    00409                                                   NULL,
    00410                                                   FALSE );
    00411
    00412         //
    00413         //  Set the flag indicating if Fast I/O is possible.  We are
    00414         //  only concerned if there are no longer any filelocks on this
    00415         //  file.
    00416         //
    00417
    00418         if (!FsRtlAreThereCurrentFileLocks( Fcb->FileLock ) &&
    00419             (Fcb->IsFastIoPossible != FastIoIsPossible)) {
    00420
    00421             UdfLockFcb( IrpContext, Fcb );
    00422             Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00423             UdfUnlockFcb( IrpContext, Fcb );
    00424         }
    00425
    00426     } finally {
    00427
    00428         FsRtlExitFileSystem();
    00429     }
    00430
    00431     return Results;
    00432 }

BOOLEAN UdfFindDirEntry | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PUNICODE_STRING | Name,
|  | IN BOOLEAN | IgnoreCase,
|  | IN BOOLEAN | ShortName,
|  | IN PDIR_ENUM_CONTEXT | DirContext
| ) |

Definition at line 726 of file dirsup.c.

References ASSERT_FCB_INDEX, ASSERT_IRP_CONTEXT, BYTE_COUNT_8_DOT_3, Dbg, DebugTrace, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT, EqualTo, FALSE, FlagOn, FsRtlAllocatePoolWithTag, Name, NSR_FID_F_DELETED, NULL, PAGED_CODE, TAG_SHORT_FILE_NAME, TRUE, UdfFullCompareNames(), UdfGenerate8dot3Name(), UdfIs8dot3Name(), UdfLookupInitialDirEntry(), UdfLookupNextDirEntry(), UdfPagedPool, and UdfUpdateDirNames().

Referenced by UdfCommonCreate(), and UdfQueryAlternateNameInfo().

    00737                    :
    00738
    00739     This routine walks the directory specified for an entry which matches the input
    00740     criteria.
    00741
    00742 Arguments:
    00743
    00744     Fcb - the directory to search
    00745
    00746     Name - name to search for
    00747
    00748     IgnoreCase - whether this search should be case-insensitive (Name will already
    00749         be upcased)
    00750
    00751     ShortName - whether the name should be searched for according to short name rules
    00752
    00753     DirContext - context structure to use and return results in
    00754
    00755 Return Value:
    00756
    00757     BOOLEAN True if a matching directory entry is being returned, False otherwise.
    00758
    00759 --*/
    00760
    00761 {
    00762     PUNICODE_STRING MatchName;
    00763
    00764     PAGED_CODE();
    00765
    00766     //
    00767     //  Check inputs.
    00768     //
    00769
    00770     ASSERT_IRP_CONTEXT( IrpContext );
    00771     ASSERT_FCB_INDEX( Fcb );
    00772
    00773     DebugTrace(( +1, Dbg,
    00774                  "UdfFindDirEntry, Fcb=%08x Name=\"%wZ\" Ignore=%u Short=%u, DC=%08x\n",
    00775                  Fcb,
    00776                  Name,
    00777                  IgnoreCase,
    00778                  ShortName,
    00779                  DirContext ));
    00780
    00781     //
    00782     //  Depending on the kind of search we are performing a different flavor of the found name
    00783     //  wil be used in the comparison.
    00784     //
    00785
    00786     if (ShortName) {
    00787
    00788         MatchName = &DirContext->ShortObjectName;
    00789
    00790     } else {
    00791
    00792         MatchName = &DirContext->CaseObjectName;
    00793     }
    00794
    00795
    00796     //
    00797     //  Go get the first entry.
    00798     //
    00799
    00800     UdfLookupInitialDirEntry( IrpContext,
    00801                               Fcb,
    00802                               DirContext,
    00803                               NULL );
    00804
    00805     //
    00806     //  Now loop looking for a good match.
    00807     //
    00808
    00809     do {
    00810
    00811         //
    00812         //  If it is deleted, we obviously aren't interested in it.
    00813         //
    00814
    00815         if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_DELETED )) {
    00816
    00817             continue;
    00818         }
    00819
    00820         UdfUpdateDirNames( IrpContext,
    00821                            DirContext,
    00822                            IgnoreCase );
    00823
    00824
    00825         //
    00826         //  If this is a constant entry, just keep going.
    00827         //
    00828
    00829         if (!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT )) {
    00830
    00831             continue;
    00832         }
    00833
    00834         DebugTrace(( 0, Dbg,
    00835                      "\"%wZ\" (pure \"%wZ\") @ +%08x\n",
    00836                      &DirContext->ObjectName,
    00837                      &DirContext->PureObjectName,
    00838                      DirContext->ViewOffset ));
    00839
    00840         //
    00841         //  If we are searching for generated shortnames, a small subset of the names
    00842         //  in the directory are actually candidates for a match.  Go get the name.
    00843         //
    00844
    00845         if (ShortName) {
    00846
    00847             //
    00848             //  Now, only if this Fid's name is non 8.3 is it neccesary to work with it.
    00849             //
    00850
    00851             if (!UdfIs8dot3Name( IrpContext, DirContext->ObjectName )) {
    00852
    00853                 //
    00854                 //  Allocate the shortname if it isn't already done.
    00855                 //
    00856
    00857                 if (DirContext->ShortObjectName.Buffer == NULL) {
    00858
    00859                     DirContext->ShortObjectName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool,
    00860                                                                                    BYTE_COUNT_8_DOT_3,
    00861                                                                                    TAG_SHORT_FILE_NAME );
    00862                     DirContext->ShortObjectName.MaximumLength = BYTE_COUNT_8_DOT_3;
    00863                 }
    00864
    00865                 UdfGenerate8dot3Name( IrpContext,
    00866                                       &DirContext->PureObjectName,
    00867                                       &DirContext->ShortObjectName );
    00868
    00869                 DebugTrace(( 0, Dbg,
    00870                              "built shortname \"%wZ\"\n", &DirContext->ShortObjectName ));
    00871
    00872             } else {
    00873
    00874                 //
    00875                 //  As an 8.3 name already, this name will not have caused us to have to generate
    00876                 //  a short name, so it can't be the case that the caller is looking for it.
    00877                 //
    00878
    00879                 continue;
    00880             }
    00881         }
    00882
    00883         if (UdfFullCompareNames( IrpContext,
    00884                                  MatchName,
    00885                                  Name ) == EqualTo) {
    00886
    00887             //
    00888             //  Got a match, so give it up.
    00889             //
    00890
    00891             DebugTrace((  0, Dbg, "HIT\n" ));
    00892             DebugTrace(( -1, Dbg, "UdfFindDirEntry -> TRUE\n" ));
    00893
    00894             return TRUE;
    00895         }
    00896
    00897     } while ( UdfLookupNextDirEntry( IrpContext,
    00898                                      Fcb,
    00899                                      DirContext ));
    00900
    00901     //
    00902     //  No match was found.
    00903     //
    00904
    00905     DebugTrace(( -1, Dbg, "UdfFindDirEntry -> FALSE\n" ));
    00906
    00907     return FALSE;
    00908 }

ULONG UdfFindInParseTable | ( | IN PPARSE_KEYVALUE | ParseTable,
|  | IN PCHAR | Id,
|  | IN ULONG | MaxIdLen
| ) |

Definition at line 2552 of file udfs/strucsup.c.

References NULL, PAGED_CODE, and PPARSE_KEYVALUE.

Referenced by UdfRecognizeVolume().

    02560                    :
    02561
    02562     This routine walks a table of string key/value information for a match of the
    02563     input Id.  MaxIdLen can be set to get a prefix match.
    02564
    02565 Arguments:
    02566
    02567     Table - This is the table being searched.
    02568
    02569     Id - Key value.
    02570
    02571     MaxIdLen - Maximum possible length of Id.
    02572
    02573 Return Value:
    02574
    02575     Value of matching entry, or the terminating (NULL) entry's value.
    02576
    02577 --*/
    02578
    02579 {
    02580     PAGED_CODE();
    02581
    02582     while (ParseTable->Key != NULL) {
    02583
    02584         if (RtlEqualMemory(ParseTable->Key, Id, MaxIdLen)) {
    02585
    02586             break;
    02587         }
    02588
    02589         ParseTable++;
    02590     }
    02591
    02592     return ParseTable->Value;
    02593 }

PLCB UdfFindPrefix | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PFCB * | CurrentFcb,
|  | IN OUT PUNICODE_STRING | RemainingName,
|  | IN BOOLEAN | IgnoreCase
| ) |

Definition at line 324 of file prefxsup.c.

References ASSERT, ASSERT_EXCLUSIVE_FCB, ASSERT_FCB, ASSERT_IRP_CONTEXT, FALSE, FlagOn, IRP_CONTEXT_FLAG_WAIT, NULL, PAGED_CODE, SafeNodeType, TRUE, UdfAcquireFcbExclusive, UdfDissectName(), UdfFindNameLink(), UdfLockVcb, UdfRaiseStatus(), UdfReleaseFcb, UDFS_NTC_FCB_INDEX, and UdfUnlockVcb.

Referenced by UdfCommonCreate().

    00333                    :
    00334
    00335     This routine begins from the given CurrentFcb and walks through all of
    00336     components of the name looking for the longest match in the prefix
    00337     splay trees.  The search is relative to the starting Fcb so the
    00338     full name may not begin with a '\'.  On return this routine will
    00339     update Current Fcb with the lowest point it has travelled in the
    00340     tree.  It will also hold only that resource on return and it must
    00341     hold that resource.
    00342
    00343 Arguments:
    00344
    00345     CurrentFcb - Address to store the lowest Fcb we find on this search.
    00346         On return we will have acquired this Fcb.  On entry this is the
    00347         Fcb to examine.
    00348
    00349     RemainingName - Supplies a buffer to store the exact case of the name being
    00350         searched for.  Initially will contain the upcase name based on the
    00351         IgnoreCase flag.
    00352
    00353     IgnoreCase - Indicates if we are doing a case-insensitive compare.
    00354
    00355 Return Value:
    00356
    00357     The Lcb used to find the current Fcb, NULL if we didn't find any prefix
    00358     Fcbs.
    00359
    00360 --*/
    00361
    00362 {
    00363     UNICODE_STRING LocalRemainingName;
    00364     UNICODE_STRING FinalName;
    00365
    00366     PLCB NameLink;
    00367     PLCB CurrentLcb = NULL;
    00368
    00369     PAGED_CODE();
    00370
    00371     //
    00372     //  Check inputs.
    00373     //
    00374
    00375     ASSERT_IRP_CONTEXT( IrpContext );
    00376     ASSERT_FCB( *CurrentFcb );
    00377     ASSERT_EXCLUSIVE_FCB( *CurrentFcb );
    00378
    00379     //
    00380     //  Make a local copy of the input strings.
    00381     //
    00382
    00383     LocalRemainingName = *RemainingName;
    00384
    00385     //
    00386     //  Loop until we find the longest matching prefix.
    00387     //
    00388
    00389     while (TRUE) {
    00390
    00391         //
    00392         //  If there are no characters left or we are not at an IndexFcb then
    00393         //  return immediately.
    00394         //
    00395
    00396         if ((LocalRemainingName.Length == 0) ||
    00397             (SafeNodeType( *CurrentFcb ) != UDFS_NTC_FCB_INDEX)) {
    00398
    00399             return CurrentLcb;
    00400         }
    00401
    00402         //
    00403         //  Split off the next component from the name.
    00404         //
    00405
    00406         UdfDissectName( IrpContext,
    00407                         &LocalRemainingName,
    00408                         &FinalName );
    00409
    00410         //
    00411         //  Check if this name is in the splay tree for this Scb.
    00412         //
    00413
    00414         if (IgnoreCase) {
    00415
    00416             NameLink = UdfFindNameLink( IrpContext,
    00417                                         &(*CurrentFcb)->IgnoreCaseRoot,
    00418                                         &FinalName );
    00419
    00420         } else {
    00421
    00422             NameLink = UdfFindNameLink( IrpContext,
    00423                                         &(*CurrentFcb)->ExactCaseRoot,
    00424                                         &FinalName );
    00425         }
    00426
    00427         //
    00428         //  If we didn't find a match then exit.
    00429         //
    00430
    00431         if (NameLink == NULL) {
    00432
    00433             break;
    00434         }
    00435
    00436         CurrentLcb = NameLink;
    00437
    00438         //
    00439         //  If this is a case-insensitive match then copy the exact case of the name into
    00440         //  the input buffer.
    00441         //
    00442
    00443         if (IgnoreCase) {
    00444
    00445             RtlCopyMemory( FinalName.Buffer,
    00446                            NameLink->FileName.Buffer,
    00447                            NameLink->FileName.Length );
    00448         }
    00449
    00450         //
    00451         //  Update the caller's remaining name string to reflect the fact that we found
    00452         //  a match.
    00453         //
    00454
    00455         *RemainingName = LocalRemainingName;
    00456
    00457         //
    00458         //  Move down to the next component in the tree.  Acquire without waiting.
    00459         //  If this fails then lock the Fcb to reference this Fcb and then drop
    00460         //  the parent and acquire the child.
    00461         //
    00462
    00463         ASSERT( NameLink->ParentFcb == *CurrentFcb );
    00464
    00465         if (!UdfAcquireFcbExclusive( IrpContext, NameLink->ChildFcb, TRUE )) {
    00466
    00467             //
    00468             //  If we can't wait then raise CANT_WAIT.
    00469             //
    00470
    00471             if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00472
    00473                 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00474             }
    00475
    00476             UdfLockVcb( IrpContext, IrpContext->Vcb );
    00477             NameLink->ChildFcb->FcbReference += 1;
    00478             NameLink->Reference += 1;
    00479             UdfUnlockVcb( IrpContext, IrpContext->Vcb );
    00480
    00481             UdfReleaseFcb( IrpContext, *CurrentFcb );
    00482             UdfAcquireFcbExclusive( IrpContext, NameLink->ChildFcb, FALSE );
    00483
    00484             UdfLockVcb( IrpContext, IrpContext->Vcb );
    00485             NameLink->ChildFcb->FcbReference -= 1;
    00486             NameLink->Reference -= 1;
    00487             UdfUnlockVcb( IrpContext, IrpContext->Vcb );
    00488
    00489         } else {
    00490
    00491             UdfReleaseFcb( IrpContext, *CurrentFcb );
    00492         }
    00493
    00494         *CurrentFcb = NameLink->ChildFcb;
    00495     }
    00496
    00497     return CurrentLcb;
    00498 }

INLINE VOID UdfFreePool | ( | IN PVOID * | Pool | ) |

Definition at line 453 of file udfprocs.h.

References ExFreePool(), and NULL.

Referenced by UdfCleanupDirContext(), UdfCompletePcb(), UdfCreateFcb(), UdfDeleteCcb(), UdfDeletePcb(), UdfDeleteVcb(), UdfDetermineVolumeBounding(), UdfDismountVcb(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfFinishBuffers(), UdfInitializeEnumeration(), UdfInsertPrefix(), UdfLoadSparingTables(), UdfLookupDirEntryPostProcessing(), UdfLookupNextDirEntry(), UdfMountVolume(), UdfRecognizeVolume(), UdfUpdateDirNames(), and UdfVerifyVolume().

    00456 {
    00457     if (*Pool != NULL) {
    00458
    00459         ExFreePool(*Pool);
    00460         *Pool = NULL;
    00461     }
    00462 }

NTSTATUS UdfFsdDispatch | ( | IN PVOLUME_DEVICE_OBJECT | VolumeDeviceObject,
|  | IN PIRP | Irp
| ) |

Definition at line 218 of file udfdata.c.

References ASSERT, ASSERT_OPTIONAL_IRP, CanFsdWait, FALSE, FlagOn, _IRP_CONTEXT::Flags, FsRtlEnterFileSystem, FsRtlExitFileSystem, IoGetCurrentIrpStackLocation, IoGetTopLevelIrp(), Irp, IRP_CONTEXT_FLAG_MORE_PROCESSING, IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MJ_LOCK_CONTROL, IRP_MJ_PNP, IRP_MJ_QUERY_INFORMATION, IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_MJ_READ, IRP_MJ_SET_INFORMATION, IRP_MN_COMPLETE, _IRP_CONTEXT::MajorFunction, _IRP_CONTEXT::MinorFunction, NTSTATUS(), NULL, SafeNodeType, SetFlag, Status, THREAD_CONTEXT, ThreadContext, _IRP_CONTEXT::TopLevel, TRUE, UdfCleanupIrpContext(), UdfCommonCleanup(), UdfCommonClose(), UdfCommonCreate(), UdfCommonDevControl(), UdfCommonDirControl(), UdfCommonFsControl(), UdfCommonLockControl(), UdfCommonPnp(), UdfCommonQueryInfo(), UdfCommonQueryVolInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfCompleteMdl(), UdfCompleteRequest(), UdfCreateIrpContext(), UdfExceptionFilter(), UdfProcessException(), UDFS_NTC_IRP_CONTEXT, and UdfSetThreadContext().

    00225                    :
    00226
    00227     This is the driver entry to all of the Fsd dispatch points.
    00228
    00229     Conceptually the Io routine will call this routine on all requests
    00230     to the file system.  We case on the type of request and invoke the
    00231     correct handler for this type of request.  There is an exception filter
    00232     to catch any exceptions in the UDFS code as well as the UDFS process
    00233     exception routine.
    00234
    00235     This routine allocates and initializes the IrpContext for this request as
    00236     well as updating the top-level thread context as necessary.  We may loop
    00237     in this routine if we need to retry the request for any reason.  The
    00238     status code STATUS_CANT_WAIT is used to indicate this.  Suppose the disk
    00239     in the drive has changed.  An Fsd request will proceed normally until it
    00240     recognizes this condition.  STATUS_VERIFY_REQUIRED is raised at that point
    00241     and the exception code will handle the verify and either return
    00242     STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was
    00243     posted.
    00244
    00245 Arguments:
    00246
    00247     VolumeDeviceObject - Supplies the volume device object for this request
    00248
    00249     Irp - Supplies the Irp being processed
    00250
    00251 Return Value:
    00252
    00253     NTSTATUS - The FSD status for the IRP
    00254
    00255 --*/
    00256
    00257 {
    00258     THREAD_CONTEXT ThreadContext;
    00259     PIRP_CONTEXT IrpContext = NULL;
    00260     BOOLEAN Wait;
    00261
    00262 #ifdef UDF_SANITY
    00263     PVOID PreviousTopLevel;
    00264 #endif
    00265
    00266     NTSTATUS Status;
    00267
    00268     KIRQL SaveIrql = KeGetCurrentIrql();
    00269
    00270     ASSERT_OPTIONAL_IRP( Irp );
    00271
    00272     FsRtlEnterFileSystem();
    00273
    00274 #ifdef UDF_SANITY
    00275     PreviousTopLevel = IoGetTopLevelIrp();
    00276 #endif
    00277
    00278     //
    00279     //  Loop until this request has been completed or posted.
    00280     //
    00281
    00282     do {
    00283
    00284         //
    00285         //  Use a try-except to handle the exception cases.
    00286         //
    00287
    00288         try {
    00289
    00290             //
    00291             //  If the IrpContext is NULL then this is the first pass through
    00292             //  this loop.
    00293             //
    00294
    00295             if (IrpContext == NULL) {
    00296
    00297                 //
    00298                 //  Decide if this request is waitable an allocate the IrpContext.
    00299                 //  If the file object in the stack location is NULL then this
    00300                 //  is a mount which is always waitable.  Otherwise we look at
    00301                 //  the file object flags.
    00302                 //
    00303
    00304                 if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) {
    00305
    00306                     Wait = TRUE;
    00307
    00308                 } else {
    00309
    00310                     Wait = CanFsdWait( Irp );
    00311                 }
    00312
    00313                 IrpContext = UdfCreateIrpContext( Irp, Wait );
    00314
    00315                 //
    00316                 //  Update the thread context information.
    00317                 //
    00318
    00319                 UdfSetThreadContext( IrpContext, &ThreadContext );
    00320
    00321 #ifdef UDF_SANITY
    00322                 ASSERT( !UdfTestTopLevel ||
    00323                         SafeNodeType( IrpContext->TopLevel ) == UDFS_NTC_IRP_CONTEXT );
    00324 #endif
    00325
    00326             //
    00327             //  Otherwise cleanup the IrpContext for the retry.
    00328             //
    00329
    00330             } else {
    00331
    00332                 //
    00333                 //  Set the MORE_PROCESSING flag to make sure the IrpContext
    00334                 //  isn't inadvertently deleted here.  Then cleanup the
    00335                 //  IrpContext to perform the retry.
    00336                 //
    00337
    00338                 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
    00339                 UdfCleanupIrpContext( IrpContext, FALSE );
    00340             }
    00341
    00342             //
    00343             //  Case on the major irp code.
    00344             //
    00345
    00346             switch (IrpContext->MajorFunction) {
    00347
    00348                 case IRP_MJ_CLEANUP :
    00349
    00350                     Status = UdfCommonCleanup( IrpContext, Irp );
    00351                     break;
    00352
    00353                 case IRP_MJ_CLOSE :
    00354
    00355                     Status = UdfCommonClose( IrpContext, Irp );
    00356                     break;
    00357
    00358                 case IRP_MJ_CREATE :
    00359
    00360                     Status = UdfCommonCreate( IrpContext, Irp );
    00361                     break;
    00362
    00363                 case IRP_MJ_DEVICE_CONTROL :
    00364
    00365                     Status = UdfCommonDevControl( IrpContext, Irp );
    00366                     break;
    00367
    00368                 case IRP_MJ_DIRECTORY_CONTROL :
    00369
    00370                     Status = UdfCommonDirControl( IrpContext, Irp );
    00371                     break;
    00372
    00373                 case IRP_MJ_FILE_SYSTEM_CONTROL :
    00374
    00375                     Status = UdfCommonFsControl( IrpContext, Irp );
    00376                     break;
    00377
    00378                 case IRP_MJ_LOCK_CONTROL :
    00379
    00380                     Status = UdfCommonLockControl( IrpContext, Irp );
    00381                     break;
    00382
    00383                 case IRP_MJ_PNP :
    00384
    00385                     Status = UdfCommonPnp( IrpContext, Irp );
    00386                     break;
    00387
    00388                 case IRP_MJ_QUERY_INFORMATION :
    00389
    00390                     Status = UdfCommonQueryInfo( IrpContext, Irp );
    00391                     break;
    00392
    00393                 case IRP_MJ_QUERY_VOLUME_INFORMATION :
    00394
    00395                     Status = UdfCommonQueryVolInfo( IrpContext, Irp );
    00396                     break;
    00397
    00398                 case IRP_MJ_READ :
    00399
    00400                     //
    00401                     //  If this is an Mdl complete request, don't go through
    00402                     //  common read.
    00403                     //
    00404
    00405                     if (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE )) {
    00406
    00407                         Status = UdfCompleteMdl( IrpContext, Irp );
    00408
    00409                     } else {
    00410
    00411                         Status = UdfCommonRead( IrpContext, Irp );
    00412                     }
    00413
    00414                     break;
    00415
    00416                 case IRP_MJ_SET_INFORMATION :
    00417
    00418                     Status = UdfCommonSetInfo( IrpContext, Irp );
    00419                     break;
    00420
    00421                 default :
    00422
    00423                     Status = STATUS_INVALID_DEVICE_REQUEST;
    00424                     UdfCompleteRequest( IrpContext, Irp, Status );
    00425             }
    00426
    00427         } except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
    00428
    00429             Status = UdfProcessException( IrpContext, Irp, GetExceptionCode() );
    00430         }
    00431
    00432     } while (Status == STATUS_CANT_WAIT);
    00433
    00434 #ifdef UDF_SANITY
    00435     ASSERT( !UdfTestTopLevel ||
    00436             (PreviousTopLevel == IoGetTopLevelIrp()) );
    00437 #endif
    00438
    00439     FsRtlExitFileSystem();
    00440
    00441     ASSERT( SaveIrql == KeGetCurrentIrql( ));
    00442
    00443     return Status;
    00444 }

NTSTATUS UdfFsdPostRequest | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 61 of file workque.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, Irp, PAGED_CODE, UdfAddToWorkque(), and UdfPrePostIrp().

Referenced by UdfCommonRead(), UdfPerformVerify(), and UdfProcessException().

    00068                    :
    00069
    00070     This routine enqueues the request packet specified by IrpContext to the
    00071     work queue associated with the FileSystemDeviceObject.  This is a FSD
    00072     routine.
    00073
    00074 Arguments:
    00075
    00076     IrpContext - Pointer to the IrpContext to be queued to the Fsp.
    00077
    00078     Irp - I/O Request Packet.
    00079
    00080 Return Value:
    00081
    00082     STATUS_PENDING
    00083
    00084 --*/
    00085
    00086 {
    00087     PAGED_CODE();
    00088
    00089     ASSERT_IRP_CONTEXT( IrpContext );
    00090     ASSERT_IRP( Irp );
    00091
    00092     //
    00093     //  Posting is a three step operation.  First lock down any buffers
    00094     //  in the Irp.  Next cleanup the IrpContext for the post and finally
    00095     //  add this to a workque.
    00096     //
    00097
    00098     UdfPrePostIrp( IrpContext, Irp );
    00099
    00100     UdfAddToWorkque( IrpContext, Irp );
    00101
    00102     //
    00103     //  And return to our caller
    00104     //
    00105
    00106     return STATUS_PENDING;
    00107 }

VOID UdfFspClose | ( | IN PVCB Vcb | OPTIONAL | ) |

Definition at line 99 of file close.c.

References ASSERT_OPTIONAL_VCB, ClearFlag, Dbg, DebugTrace, _IRP_CONTEXT::ExceptionStatus, FALSE, _FCB::FcbReference, _FCB::FcbUserReference, _IRP_CONTEXT::Flags, FsRtlEnterFileSystem, FsRtlExitFileSystem, _IRP_CONTEXT::Irp, IRP_CONTEXT, IRP_CONTEXT_FLAG_TOP_LEVEL, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS, IRP_CONTEXT_FSP_FLAGS, _UDF_DATA::MinDelayedCloseCount, NULL, PAGED_CODE, PIRP_CONTEXT_LITE, SafeNodeType, SetFlag, THREAD_CONTEXT, ThreadContext, UdfAcquireUdfData, UdfAcquireVcbShared, UdfCheckForDismount(), UdfCommonClosePrivate(), UdfCompleteRequest(), UdfData, UdfFreeIrpContextLite, UdfInitializeStackIrpContext(), UdfReleaseUdfData, UdfReleaseVcb, UdfRemoveClose(), UDFS_NTC_IRP_CONTEXT, UdfSetThreadContext(), _FCB::Vcb, _VCB::VcbCleanup, _VCB::VcbCondition, VcbMounted, VcbMountInProgress, _VCB::VcbReference, and _VCB::VcbUserReference.

Referenced by UdfCheckForDismount(), UdfCompleteFcbOpen(), UdfDismountVcb(), UdfInitializeGlobalData(), UdfLockVolumeInternal(), and UdfPurgeVolume().

    00105                    :
    00106
    00107     This routine is called to process the close queues in the UdfData.  If the
    00108     Vcb is passed then we want to remove all of the closes for this Vcb.
    00109     Otherwise we will do as many of the delayed closes as we need to do.
    00110
    00111 Arguments:
    00112
    00113     Vcb - If specified then we are looking for all of the closes for the
    00114         given Vcb.
    00115
    00116 Return Value:
    00117
    00118     None
    00119
    00120 --*/
    00121
    00122 {
    00123     PIRP_CONTEXT IrpContext;
    00124     IRP_CONTEXT StackIrpContext;
    00125
    00126     THREAD_CONTEXT ThreadContext;
    00127
    00128     PFCB Fcb;
    00129     ULONG UserReference;
    00130
    00131     ULONG VcbHoldCount = 0;
    00132     PVCB CurrentVcb = NULL;
    00133
    00134     BOOLEAN ReleaseUdfData = FALSE;
    00135
    00136     PAGED_CODE();
    00137
    00138     //
    00139     //  Check input.
    00140     //
    00141
    00142     ASSERT_OPTIONAL_VCB( Vcb );
    00143
    00144     FsRtlEnterFileSystem();
    00145
    00146     //
    00147     //  Continue processing until there are no more closes to process.
    00148     //
    00149
    00150     while (IrpContext = UdfRemoveClose( Vcb )) {
    00151
    00152         //
    00153         //  If we don't have an IrpContext then use the one on the stack.
    00154         //  Initialize it for this request.
    00155         //
    00156
    00157         if (SafeNodeType( IrpContext ) != UDFS_NTC_IRP_CONTEXT ) {
    00158
    00159             //
    00160             //  Update the local values from the IrpContextLite.
    00161             //
    00162
    00163             Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb;
    00164             UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference;
    00165
    00166             //
    00167             //  Update the stack irp context with the values from the
    00168             //  IrpContextLite.
    00169             //
    00170
    00171             UdfInitializeStackIrpContext( &StackIrpContext,
    00172                                           (PIRP_CONTEXT_LITE) IrpContext );
    00173
    00174             //
    00175             //  Free the IrpContextLite.
    00176             //
    00177
    00178             UdfFreeIrpContextLite( (PIRP_CONTEXT_LITE) IrpContext );
    00179
    00180             //
    00181             //  Remember we have the IrpContext from the stack.
    00182             //
    00183
    00184             IrpContext = &StackIrpContext;
    00185
    00186         //
    00187         //  Otherwise cleanup the existing IrpContext.
    00188         //
    00189
    00190         } else {
    00191
    00192             //
    00193             //  Remember the Fcb and user reference count.
    00194             //
    00195
    00196             Fcb = (PFCB) IrpContext->Irp;
    00197             IrpContext->Irp = NULL;
    00198
    00199             UserReference = (ULONG) IrpContext->ExceptionStatus;
    00200             IrpContext->ExceptionStatus = STATUS_SUCCESS;
    00201         }
    00202
    00203         //
    00204         //  We have an IrpContext.  Now we need to set the top level thread
    00205         //  context.
    00206         //
    00207
    00208         SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS );
    00209
    00210         //
    00211         //  If we were given a Vcb then there is a request on top of this.
    00212         //
    00213
    00214         if (ARGUMENT_PRESENT( Vcb )) {
    00215
    00216             ClearFlag( IrpContext->Flags,
    00217                        IRP_CONTEXT_FLAG_TOP_LEVEL | IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS );
    00218         }
    00219
    00220         UdfSetThreadContext( IrpContext, &ThreadContext );
    00221
    00222         //
    00223         //  If we have hit the maximum number of requests to process without
    00224         //  releasing the Vcb then release the Vcb now.  If we are holding
    00225         //  a different Vcb to this one then release the previous Vcb.
    00226         //
    00227         //  In either case acquire the current Vcb.
    00228         //
    00229         //  We use the MinDelayedCloseCount from the UdfData since it is
    00230         //  a convenient value based on the system size.  Only thing we are trying
    00231         //  to do here is prevent this routine starving other threads which
    00232         //  may need this Vcb exclusively.
    00233         //
    00234
    00235         ReleaseUdfData = !ARGUMENT_PRESENT( Vcb ) &&
    00236                          (Fcb->Vcb->VcbCondition != VcbMounted) &&
    00237                          (Fcb->Vcb->VcbCondition != VcbMountInProgress) &&
    00238                          (Fcb->Vcb->VcbCleanup == 0);
    00239
    00240         if (ReleaseUdfData ||
    00241             (VcbHoldCount > UdfData.MinDelayedCloseCount) ||
    00242             (Fcb->Vcb != CurrentVcb)) {
    00243
    00244             if (CurrentVcb != NULL) {
    00245
    00246                 UdfReleaseVcb( IrpContext, CurrentVcb );
    00247             }
    00248
    00249             if (ReleaseUdfData) {
    00250
    00251                 UdfAcquireUdfData( IrpContext );
    00252             }
    00253
    00254             CurrentVcb = Fcb->Vcb;
    00255             UdfAcquireVcbShared( IrpContext, CurrentVcb, FALSE );
    00256
    00257             VcbHoldCount = 0;
    00258
    00259         } else {
    00260
    00261             VcbHoldCount += 1;
    00262         }
    00263
    00264         DebugTrace(( +1, Dbg,
    00265                      "UdfFspClose, Fcb %08x %4s Vcb %d/%d Fcb %d/%d\n",
    00266                      Fcb,
    00267                      ( UserReference? "USER" : "SYS" ),
    00268                      CurrentVcb->VcbReference,
    00269                      CurrentVcb->VcbUserReference,
    00270                      Fcb->FcbReference,
    00271                      Fcb->FcbUserReference ));
    00272
    00273         //
    00274         //  Call our worker routine to perform the close operation.
    00275         //
    00276
    00277         UdfCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE );
    00278
    00279         //
    00280         //  If the reference count on this Vcb is below our residual reference
    00281         //  then check if we should dismount the volume.
    00282         //
    00283
    00284         if (ReleaseUdfData) {
    00285
    00286             UdfReleaseVcb( IrpContext, CurrentVcb );
    00287             UdfCheckForDismount( IrpContext, CurrentVcb, FALSE );
    00288
    00289             CurrentVcb = NULL;
    00290
    00291             UdfReleaseUdfData( IrpContext );
    00292             ReleaseUdfData = FALSE;
    00293         }
    00294
    00295         //
    00296         //  Complete the current request to cleanup the IrpContext.
    00297         //
    00298
    00299         UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
    00300
    00301         DebugTrace(( -1, Dbg, "UdfFspClose -> VOID\n" ));
    00302     }
    00303
    00304     //
    00305     //  Release any Vcb we may still hold.
    00306     //
    00307
    00308     if (CurrentVcb != NULL) {
    00309
    00310         UdfReleaseVcb( IrpContext, CurrentVcb );
    00311     }
    00312
    00313     FsRtlExitFileSystem();
    00314     return;
    00315 }

VOID UdfFspDispatch | ( | IN PIRP_CONTEXT | IrpContext | ) |

Definition at line 38 of file fspdisp.c.

References ASSERT, _IO_STACK_LOCATION::DeviceObject, FALSE, _IO_STACK_LOCATION::FileObject, FsRtlEnterFileSystem, FsRtlExitFileSystem, IoGetCurrentIrpStackLocation, _IRP::IoStatus, Irp, IRP_CONTEXT_FLAG_MORE_PROCESSING, IRP_CONTEXT_FSP_FLAGS, IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MJ_LOCK_CONTROL, IRP_MJ_PNP, IRP_MJ_QUERY_INFORMATION, IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_MJ_READ, IRP_MJ_SET_INFORMATION, KeAcquireSpinLock, KeReleaseSpinLock(), NTSTATUS(), NULL, _VOLUME_DEVICE_OBJECT::OverflowQueue, _VOLUME_DEVICE_OBJECT::OverflowQueueCount, _VOLUME_DEVICE_OBJECT::OverflowQueueSpinLock, _VOLUME_DEVICE_OBJECT::PostedRequestCount, SetFlag, Status, ThreadContext, TRUE, UdfCleanupIrpContext(), UdfCommonCleanup(), UdfCommonCreate(), UdfCommonDevControl(), UdfCommonDirControl(), UdfCommonFsControl(), UdfCommonLockControl(), UdfCommonPnp(), UdfCommonQueryInfo(), UdfCommonQueryVolInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfCompleteRequest(), UdfExceptionFilter(), UdfProcessException(), and UdfSetThreadContext().

Referenced by UdfAddToWorkque().

    00044                    :
    00045
    00046     This is the main FSP thread routine that is executed to receive
    00047     and dispatch IRP requests.  Each FSP thread begins its execution here.
    00048     There is one thread created at system initialization time and subsequent
    00049     threads created as needed.
    00050
    00051 Arguments:
    00052
    00053     IrpContext - IrpContext for a request to process.
    00054
    00055 Return Value:
    00056
    00057     None
    00058
    00059 --*/
    00060
    00061 {
    00062     THREAD_CONTEXT ThreadContext;
    00063     NTSTATUS Status;
    00064
    00065     PIRP Irp = IrpContext->Irp;
    00066     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00067
    00068     PVOLUME_DEVICE_OBJECT VolDo = NULL;
    00069
    00070     //
    00071     //  If this request has an associated volume device object, remember it.
    00072     //
    00073
    00074     if (IrpSp->FileObject != NULL) {
    00075
    00076         VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
    00077                                    VOLUME_DEVICE_OBJECT,
    00078                                    DeviceObject );
    00079     }
    00080
    00081     //
    00082     //  Now case on the function code.  For each major function code,
    00083     //  either call the appropriate worker routine.  This routine that
    00084     //  we call is responsible for completing the IRP, and not us.
    00085     //  That way the routine can complete the IRP and then continue
    00086     //  post processing as required.  For example, a read can be
    00087     //  satisfied right away and then read can be done.
    00088     //
    00089     //  We'll do all of the work within an exception handler that
    00090     //  will be invoked if ever some underlying operation gets into
    00091     //  trouble.
    00092     //
    00093
    00094     while (TRUE) {
    00095
    00096         //
    00097         //  Set all the flags indicating we are in the Fsp.
    00098         //
    00099
    00100         SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS );
    00101
    00102         FsRtlEnterFileSystem();
    00103
    00104         UdfSetThreadContext( IrpContext, &ThreadContext );
    00105
    00106         while (TRUE) {
    00107
    00108             try {
    00109
    00110                 //
    00111                 //  Reinitialize for the next try at completing this
    00112                 //  request.
    00113                 //
    00114
    00115                 Status =
    00116                 IrpContext->ExceptionStatus = STATUS_SUCCESS;
    00117
    00118                 //
    00119                 //  Initialize the Io status field in the Irp.
    00120                 //
    00121
    00122                 Irp->IoStatus.Status = STATUS_SUCCESS;
    00123                 Irp->IoStatus.Information = 0;
    00124
    00125                 //
    00126                 //  Case on the major irp code.
    00127                 //
    00128
    00129                 switch (IrpContext->MajorFunction) {
    00130
    00131                     case IRP_MJ_CLEANUP :
    00132
    00133                         Status = UdfCommonCleanup( IrpContext, Irp );
    00134                         break;
    00135
    00136                     case IRP_MJ_CLOSE :
    00137
    00138                         //
    00139                         //  Closes should never be posted.
    00140                         //
    00141
    00142                         ASSERT( FALSE );
    00143                         break;
    00144
    00145                     case IRP_MJ_CREATE :
    00146
    00147                         Status = UdfCommonCreate( IrpContext, Irp );
    00148                         break;
    00149
    00150                     case IRP_MJ_DEVICE_CONTROL :
    00151
    00152                         Status = UdfCommonDevControl( IrpContext, Irp );
    00153                         break;
    00154
    00155                     case IRP_MJ_DIRECTORY_CONTROL :
    00156
    00157                         Status = UdfCommonDirControl( IrpContext, Irp );
    00158                         break;
    00159
    00160                     case IRP_MJ_FILE_SYSTEM_CONTROL :
    00161
    00162                         Status = UdfCommonFsControl( IrpContext, Irp );
    00163                         break;
    00164
    00165                     case IRP_MJ_LOCK_CONTROL :
    00166
    00167                         Status = UdfCommonLockControl( IrpContext, Irp );
    00168                         break;
    00169
    00170                     case IRP_MJ_PNP :
    00171
    00172                         ASSERT( FALSE );
    00173                         Status = UdfCommonPnp( IrpContext, Irp );
    00174                         break;
    00175
    00176                     case IRP_MJ_QUERY_INFORMATION :
    00177
    00178                         Status = UdfCommonQueryInfo( IrpContext, Irp );
    00179                         break;
    00180
    00181                     case IRP_MJ_QUERY_VOLUME_INFORMATION :
    00182
    00183                         Status = UdfCommonQueryVolInfo( IrpContext, Irp );
    00184                         break;
    00185
    00186                     case IRP_MJ_READ :
    00187
    00188                         Status = UdfCommonRead( IrpContext, Irp );
    00189                         break;
    00190
    00191                     case IRP_MJ_SET_INFORMATION :
    00192
    00193                         Status = UdfCommonSetInfo( IrpContext, Irp );
    00194                         break;
    00195
    00196                     default :
    00197
    00198                         Status = STATUS_INVALID_DEVICE_REQUEST;
    00199                         UdfCompleteRequest( IrpContext, Irp, Status );
    00200                 }
    00201
    00202             } except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
    00203
    00204                 Status = UdfProcessException( IrpContext, Irp, GetExceptionCode() );
    00205             }
    00206
    00207             //
    00208             //  Break out of the loop if we didn't get CANT_WAIT.
    00209             //
    00210
    00211             if (Status != STATUS_CANT_WAIT) { break; }
    00212
    00213             //
    00214             //  We are retrying this request.  Cleanup the IrpContext for the retry.
    00215             //
    00216
    00217             SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
    00218             UdfCleanupIrpContext( IrpContext, FALSE );
    00219         }
    00220
    00221         FsRtlExitFileSystem();
    00222
    00223         //
    00224         //  If there are any entries on this volume's overflow queue, service
    00225         //  them.
    00226         //
    00227
    00228         if (VolDo != NULL) {
    00229
    00230             KIRQL SavedIrql;
    00231             PVOID Entry = NULL;
    00232
    00233             //
    00234             //  We have a volume device object so see if there is any work
    00235             //  left to do in its overflow queue.
    00236             //
    00237
    00238             KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );
    00239
    00240             if (VolDo->OverflowQueueCount > 0) {
    00241
    00242                 //
    00243                 //  There is overflow work to do in this volume so we'll
    00244                 //  decrement the Overflow count, dequeue the IRP, and release
    00245                 //  the Event
    00246                 //
    00247
    00248                 VolDo->OverflowQueueCount -= 1;
    00249
    00250                 Entry = RemoveHeadList( &VolDo->OverflowQueue );
    00251             }
    00252
    00253             KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );
    00254
    00255             //
    00256             //  There wasn't an entry, break out of the loop and return to
    00257             //  the Ex Worker thread.
    00258             //
    00259
    00260             if (Entry == NULL) { break; }
    00261
    00262             //
    00263             //  Extract the IrpContext , Irp, set wait to TRUE, and loop.
    00264             //
    00265
    00266             IrpContext = CONTAINING_RECORD( Entry,
    00267                                             IRP_CONTEXT,
    00268                                             WorkQueueItem.List );
    00269
    00270             Irp = IrpContext->Irp;
    00271             IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00272
    00273             continue;
    00274         }
    00275
    00276         break;
    00277     }
    00278
    00279     //
    00280     //  Decrement the PostedRequestCount if there was a volume device object.
    00281     //
    00282
    00283     if (VolDo) {
    00284
    00285         InterlockedDecrement( &VolDo->PostedRequestCount );
    00286     }
    00287
    00288     return;
    00289 }

FSRTL_COMPARISON_RESULT UdfFullCompareNames | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | NameA,
|  | IN PUNICODE_STRING | NameB
| ) |

Definition at line 1274 of file namesup.c.

References ASSERT_IRP_CONTEXT, EqualTo, FSRTL_COMPARISON_RESULT, GreaterThan, LessThan, and PAGED_CODE.

Referenced by UdfFindDirEntry(), UdfFindNameLink(), UdfInitializeEnumeration(), and UdfInsertNameLink().

    01282                    :
    01283
    01284     This function compares two names as fast as possible.  Note that since
    01285     this comparison is case sensitive we can do a direct memory comparison.
    01286
    01287 Arguments:
    01288
    01289     NameA & NameB - The names to compare.
    01290
    01291 Return Value:
    01292
    01293     COMPARISON - returns
    01294
    01295         LessThan    if NameA < NameB lexicalgraphically,
    01296         GreaterThan if NameA > NameB lexicalgraphically,
    01297         EqualTo     if NameA is equal to NameB
    01298
    01299 --*/
    01300
    01301 {
    01302     ULONG i;
    01303     ULONG MinLength = NameA->Length;
    01304     FSRTL_COMPARISON_RESULT Result = LessThan;
    01305
    01306     PAGED_CODE();
    01307
    01308     //
    01309     //  Check inputs.
    01310     //
    01311
    01312     ASSERT_IRP_CONTEXT( IrpContext );
    01313
    01314     //
    01315     //  Figure out the minimum of the two lengths
    01316     //
    01317
    01318     if (NameA->Length > NameB->Length) {
    01319
    01320         MinLength = NameB->Length;
    01321         Result = GreaterThan;
    01322
    01323     } else if (NameA->Length == NameB->Length) {
    01324
    01325         Result = EqualTo;
    01326     }
    01327
    01328     //
    01329     //  Loop through looking at all of the characters in both strings
    01330     //  testing for equalilty, less than, and greater than
    01331     //
    01332
    01333     i = (ULONG) RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinLength );
    01334
    01335     if (i < MinLength) {
    01336
    01337         //
    01338         //  We know the offset of the first character which is different.
    01339         //
    01340
    01341         return ((NameA->Buffer[ i / 2 ] < NameB->Buffer[ i / 2 ]) ?
    01342                  LessThan :
    01343                  GreaterThan);
    01344     }
    01345
    01346     //
    01347     //  The names match up to the length of the shorter string.
    01348     //  The shorter string lexically appears first.
    01349     //
    01350
    01351     return Result;
    01352 }

VOID UdfGenerate8dot3Name | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | FileName,
|  | OUT PUNICODE_STRING | ShortFileName
| ) |

Definition at line 389 of file namesup.c.

References ASSERT, CRC_MARK, DOS_CRC_LEN, DOS_EXT_LEN, DOS_NAME_LEN, FALSE, FileName, ILLEGAL_CHAR_MARK, INT16, IsDeviceName, IsFileNameCharLegal, NativeDosCharLength(), PERIOD, SPACE, TRUE, UdfComputeCrc16Uni(), UdfCrcChar, UdfUpcaseName(), UINT16, UNICODE_CHAR, UnicodeToUpper, and USHORT.

Referenced by UdfEnumerateIndex(), UdfFindDirEntry(), UdfQueryAlternateNameInfo(), and UdfQueryDirectory().

    00397                    :
    00398
    00399     This routine is called to generate a short name from the given long name.  We will
    00400     generate a short name from the given long name.
    00401
    00402     The short form is to convert all runs of illegal characters to "_" and tack
    00403     on a base41 representation of the CRC of the original name.  The algorithm is
    00404     nearly directly lifted from the UDF (2.01 proposed!) standard, so apologies for the
    00405     style clash.
    00406
    00407 Arguments:
    00408
    00409     FileName - String of bytes containing the name.
    00410
    00411     ShortFileName - Pointer to the string to store the short name into.
    00412
    00413 Return Value:
    00414
    00415     None.
    00416
    00417 --*/
    00418
    00419 {
    00420     INT16 index;
    00421     INT16 targetIndex;
    00422     INT16 crcIndex;
    00423     INT16 extLen;
    00424     INT16 nameLen;
    00425     INT16 charLen;
    00426     INT16 overlayBytes;
    00427     INT16 bytesLeft;
    00428     UNICODE_CHAR current;
    00429     BOOLEAN needsCRC;
    00430     UNICODE_CHAR ext[DOS_EXT_LEN];
    00431
    00432     //
    00433     //  So as to lift as directly as possible from the standard, chunk things around.
    00434     //
    00435
    00436     PWCHAR dosName = ShortFileName->Buffer;
    00437     PWCHAR udfName = FileName->Buffer;
    00438     LONG udfNameLen = FileName->Length / sizeof(WCHAR);
    00439
    00440     needsCRC = FALSE;
    00441
    00442     /* Start at the end of the UDF file name and scan for a period */
    00443     /* ('.').  This will be where the DOS extension starts (if     */
    00444     /* any).                                                       */
    00445     index = udfNameLen;
    00446     while (index-- > 0) {
    00447         if (udfName[index] == PERIOD)
    00448             break;
    00449     }
    00450
    00451     if (index < 0) {
    00452         /* There name was scanned to the beginning of the buffer   */
    00453         /* and no extension was found.                             */
    00454         extLen = 0;
    00455         nameLen = udfNameLen;
    00456     }
    00457     else {
    00458         /* A DOS extension was found, process it first.            */
    00459         extLen = udfNameLen - index - 1;
    00460         nameLen = index;
    00461         targetIndex = 0;
    00462         bytesLeft = DOS_EXT_LEN;
    00463
    00464         while (++index < udfNameLen && bytesLeft > 0) {
    00465             /* Get the current character and convert it to upper   */
    00466             /* case.                                               */
    00467             current = UnicodeToUpper(udfName[index]);
    00468             if (current == SPACE) {
    00469                 /* If a space is found, a CRC must be appended to  */
    00470                 /* the mangled file name.                          */
    00471                 needsCRC = TRUE;
    00472             }
    00473             else {
    00474                 /* Determine if this is a valid file name char and */
    00475                 /* calculate its corresponding BCS character byte  */
    00476                 /* length (zero if the char is not legal or        */
    00477                 /* undisplayable on this system).                  */
    00478                 charLen = (IsFileNameCharLegal(current)) ?
    00479                     NativeDosCharLength(current) : 0;
    00480
    00481                 /* If the char is larger than the available space  */
    00482                 /* in the buffer, pretend it is undisplayable.     */
    00483                 if (charLen > bytesLeft)
    00484                     charLen = 0;
    00485
    00486                 if (charLen == 0) {
    00487                     /* Undisplayable or illegal characters are     */
    00488                     /* substituted with an underscore ("_"), and   */
    00489                     /* required a CRC code appended to the mangled */
    00490                     /* file name.                                  */
    00491                     needsCRC = TRUE;
    00492                     charLen = 1;
    00493                     current = ILLEGAL_CHAR_MARK;
    00494
    00495                     /* Skip over any following undiplayable or     */
    00496                     /* illegal chars.                              */
    00497                     while (index + 1 < udfNameLen &&
    00498                         (!IsFileNameCharLegal(udfName[index + 1]) ||
    00499                         NativeDosCharLength(udfName[index + 1]) == 0))
    00500                         index++;
    00501                 }
    00502
    00503                 /* Assign the resulting char to the next index in  */
    00504                 /* the extension buffer and determine how many BCS */
    00505                 /* bytes are left.                                 */
    00506                 ext[targetIndex++] = current;
    00507                 bytesLeft -= charLen;
    00508             }
    00509         }
    00510
    00511         /* Save the number of Unicode characters in the extension  */
    00512         extLen = targetIndex;
    00513
    00514         /* If the extension was too large, or it was zero length   */
    00515         /* (i.e. the name ended in a period), a CRC code must be   */
    00516         /* appended to the mangled name.                           */
    00517         if (index < udfNameLen || extLen == 0)
    00518             needsCRC = TRUE;
    00519     }
    00520
    00521     /* Now process the actual file name.                           */
    00522     index = 0;
    00523     targetIndex = 0;
    00524     crcIndex = 0;
    00525     overlayBytes = -1;
    00526     bytesLeft = DOS_NAME_LEN;
    00527     while (index < nameLen && bytesLeft > 0) {
    00528         /* Get the current character and convert it to upper case. */
    00529         current = UnicodeToUpper(udfName[index]);
    00530         if (current == SPACE || current == PERIOD) {
    00531             /* Spaces and periods are just skipped, a CRC code     */
    00532             /* must be added to the mangled file name.             */
    00533             needsCRC = TRUE;
    00534         }
    00535         else {
    00536             /* Determine if this is a valid file name char and     */
    00537             /* calculate its corresponding BCS character byte      */
    00538             /* length (zero if the char is not legal or            */
    00539             /* undisplayable on this system).                      */
    00540             charLen = (IsFileNameCharLegal(current)) ?
    00541                 NativeDosCharLength(current) : 0;
    00542
    00543             /* If the char is larger than the available space in   */
    00544             /* the buffer, pretend it is undisplayable.            */
    00545             if (charLen > bytesLeft)
    00546                 charLen = 0;
    00547
    00548             if (charLen == 0) {
    00549                 /* Undisplayable or illegal characters are         */
    00550                 /* substituted with an underscore ("_"), and       */
    00551                 /* required a CRC code appended to the mangled     */
    00552                 /* file name.                                      */
    00553                 needsCRC = TRUE;
    00554                 charLen = 1;
    00555                 current = ILLEGAL_CHAR_MARK;
    00556
    00557                 /* Skip over any following undiplayable or illegal */
    00558                 /* chars.                                          */
    00559                 while (index + 1 < nameLen &&
    00560                     (!IsFileNameCharLegal(udfName[index + 1]) ||
    00561                     NativeDosCharLength(udfName[index + 1]) == 0))
    00562                     index++;
    00563
    00564                 /* Terminate loop if at the end of the file name.  */
    00565                 if (index >= nameLen)
    00566                     break;
    00567             }
    00568
    00569             /* Assign the resulting char to the next index in the  */
    00570             /* file name buffer and determine how many BCS bytes   */
    00571             /* are left.                                           */
    00572             dosName[targetIndex++] = current;
    00573             bytesLeft -= charLen;
    00574
    00575             /* This figures out where the CRC code needs to start  */
    00576             /* in the file name buffer.                            */
    00577             if (bytesLeft >= DOS_CRC_LEN) {
    00578                 /* If there is enough space left, just tack it     */
    00579                 /* onto the end.                                   */
    00580                 crcIndex = targetIndex;
    00581             }
    00582             else {
    00583                 /* If there is not enough space left, the CRC      */
    00584                 /* must overlay a character already in the file    */
    00585                 /* name buffer.  Once this condition has been      */
    00586                 /* met, the value will not change.                 */
    00587                 if (overlayBytes < 0) {
    00588                     /* Determine the index and save the length of  */
    00589                     /* the BCS character that is overlayed.  It    */
    00590                     /* is possible that the CRC might overlay      */
    00591                     /* half of a two-byte BCS character depending  */
    00592                     /* upon how the character boundaries line up.  */
    00593                     overlayBytes = (bytesLeft + charLen > DOS_CRC_LEN)
    00594                         ? 1 : 0;
    00595                     crcIndex = targetIndex - 1;
    00596                 }
    00597             }
    00598         }
    00599
    00600         /* Advance to the next character.                          */
    00601         index++;
    00602     }
    00603
    00604     /* If the scan did not reach the end of the file name, or the  */
    00605     /* length of the file name is zero, a CRC code is needed.      */
    00606     if (index < nameLen || index == 0)
    00607         needsCRC = TRUE;
    00608
    00609     /* If the name has illegal characters or and extension, it     */
    00610     /* is not a DOS device name.                                   */
    00611     if (needsCRC == FALSE && extLen == 0) {
    00612         /* If this is the name of a DOS device, a CRC code should  */
    00613         /* be appended to the file name.                           */
    00614         if (IsDeviceName(udfName, udfNameLen))
    00615             needsCRC = TRUE;
    00616     }
    00617
    00618     /* Append the CRC code to the file name, if needed.            */
    00619     if (needsCRC) {
    00620         /* Get the CRC value for the original Unicode string       */
    00621         UINT16 udfCRCValue;
    00622         UINT16 modulus;
    00623
    00624         //
    00625         //  In UDF 2.00, the sample code changed to take the CRC
    00626         //  from the UNICODE expansion of the CS0 as opposed to
    00627         //  the CS0 itself.  In UDF 2.01, the wording of the spec
    00628         //  will actually match this.
    00629         //
    00630         //  Additionally, the checksum changes to be byte-order
    00631         //  independent.
    00632         //
    00633
    00634         udfCRCValue = UdfComputeCrc16Uni(udfName, udfNameLen);
    00635
    00636         /* Determine the character index where the CRC should      */
    00637         /* begin.                                                  */
    00638         targetIndex = crcIndex;
    00639
    00640         /* If the character being overlayed is a two-byte BCS      */
    00641         /* character, replace the first byte with an underscore.   */
    00642         if (overlayBytes > 0)
    00643             dosName[targetIndex++] = ILLEGAL_CHAR_MARK;
    00644
    00645         //
    00646         //  UDF 2.01 changes to a base 41 encoding.  UDF 1.50 and
    00647         //  UDF 2.00 exchanged the # delimeter with the high 4bits
    00648         //  of the CRC.
    00649         //
    00650
    00651         dosName[targetIndex++] = CRC_MARK;
    00652
    00653         dosName[targetIndex++] =
    00654             UdfCrcChar[udfCRCValue / (41 * 41)];
    00655         udfCRCValue %= (41 * 41);
    00656
    00657         dosName[targetIndex++] =
    00658             UdfCrcChar[udfCRCValue / 41];
    00659         udfCRCValue %= 41;
    00660
    00661         dosName[targetIndex++] =
    00662             UdfCrcChar[udfCRCValue];
    00663     }
    00664
    00665     /* Append the extension, if any.                               */
    00666     if (extLen > 0) {
    00667         /* Tack on a period and each successive byte in the        */
    00668         /* extension buffer.                                       */
    00669         dosName[targetIndex++] = PERIOD;
    00670         for (index = 0; index < extLen; index++)
    00671             dosName[targetIndex++] = ext[index];
    00672     }
    00673
    00674     ASSERT( (targetIndex * sizeof(WCHAR)) <= ShortFileName->MaximumLength );
    00675
    00676     ShortFileName->Length = (USHORT) (targetIndex * sizeof(WCHAR));
    00677
    00678     //
    00679     //  Now we upcase the whole name at once.
    00680     //
    00681
    00682     UdfUpcaseName( IrpContext,
    00683                    ShortFileName,
    00684                    ShortFileName );
    00685 }

PFCB UdfGetNextFcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PVOID * | RestartKey
| ) |

Definition at line 1997 of file udfs/strucsup.c.

References NULL, PAGED_CODE, PFCB_TABLE_ELEMENT, and RtlEnumerateGenericTableWithoutSplaying().

Referenced by UdfPurgeVolume().

    02005                    :
    02006
    02007     This routine will enumerate through all of the Fcb's in the Fcb table.
    02008
    02009 Arguments:
    02010
    02011     Vcb - Vcb for this volume.
    02012
    02013     RestartKey - This value is used by the table package to maintain
    02014         its position in the enumeration.  It is initialized to NULL
    02015         for the first search.
    02016
    02017 Return Value:
    02018
    02019     PFCB - A pointer to the next fcb or NULL if the enumeration is
    02020         completed
    02021
    02022 --*/
    02023
    02024 {
    02025     PFCB Fcb;
    02026
    02027     PAGED_CODE();
    02028
    02029     Fcb = (PFCB) RtlEnumerateGenericTableWithoutSplaying( &Vcb->FcbTable, RestartKey );
    02030
    02031     if (Fcb != NULL) {
    02032
    02033         Fcb = ((PFCB_TABLE_ELEMENT)(Fcb))->Fcb;
    02034     }
    02035
    02036     return Fcb;
    02037 }

ULONG UdfHighBit | ( | ULONG | Word | ) |

Definition at line 1239 of file udfdata.c.

References Offset.

Referenced by UdfInitializeVcb(), and UdfMountVolume().

    01245                    :
    01246
    01247     This routine discovers the highest set bit of the input word.  It is
    01248     equivalent to the integer logarithim base 2.
    01249
    01250 Arguments:
    01251
    01252     Word - word to check
    01253
    01254 Return Value:
    01255
    01256     Bit offset of highest set bit. If no bit is set, return is zero.
    01257
    01258 --*/
    01259
    01260 {
    01261     ULONG Offset = 31;
    01262     ULONG Mask = (ULONG)(1 << 31);
    01263
    01264     if (Word == 0) {
    01265
    01266         return 0;
    01267     }
    01268
    01269     while ((Word & Mask) == 0) {
    01270
    01271         Offset--;
    01272         Mask >>= 1;
    01273     }
    01274
    01275     return Offset;
    01276 }

INLINE BOOLEAN UdfIllegalFcbAccess | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN TYPE_OF_OPEN | TypeOfOpen,
|  | IN ACCESS_MASK | DesiredAccess
| ) |

Definition at line 675 of file udfprocs.h.

References BooleanFlagOn, and UserVolumeOpen.

Referenced by UdfOpenExistingFcb(), UdfOpenObjectByFileId(), and UdfOpenObjectFromDirContext().

    00683                    :
    00684
    00685     This routine simply asserts that the access is legal for a readonly filesystem.
    00686
    00687 Arguments:
    00688
    00689     TypeOfOpen - type of open for the Fcb in question.
    00690
    00691     DesiredAccess - mask of access the caller is trying for.
    00692
    00693 Return Value:
    00694
    00695     BOOLEAN True if illegal access, false otherwise.
    00696
    00697 --*/
    00698
    00699 {
    00700     return BooleanFlagOn( DesiredAccess,
    00701                           (TypeOfOpen != UserVolumeOpen ?
    00702                            (FILE_WRITE_ATTRIBUTES           |
    00703                             FILE_WRITE_DATA                 |
    00704                             FILE_WRITE_EA                   |
    00705                             FILE_ADD_FILE                   |
    00706                             FILE_ADD_SUBDIRECTORY           |
    00707                             FILE_APPEND_DATA) : 0)          |
    00708                           FILE_DELETE_CHILD                 |
    00709                           DELETE                            |
    00710                           WRITE_DAC );
    00711 }

VOID UdfInitializeAllocations | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PICB_SEARCH_CONTEXT | IcbContext
| ) |

Definition at line 3388 of file udfs/strucsup.c.

References _ALLOC_ENUM_CONTEXT::Alloc, ALLOC_ENUM_CONTEXT, ICBFILE::AllocLength, _ALLOC_ENUM_CONTEXT::AllocType, ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, BlockOffset, BlockSize, Dbg, DebugTrace, ICBFILE::Destag, ICBFILE::EALength, FALSE, FCB_STATE_EMBEDDED_DATA, FsRtlAddLargeMcbEntry(), ICBTAG_F_ALLOC_IMMEDIATE, DESTAG::Lbn, NSRLENGTH::Length, SHORTAD::Length, LlSectorsFromBytes, NSRLENGTH_TYPE_RECORDED, NSRLENGTH_TYPE_UNRECORDED, PAD_GENERIC, PAGED_CODE, SectorAlign, SectorsFromBytes, SetFlag, SHORTAD::Start, TRUE, NSRLENGTH::Type, UdfGetNextAllocation(), UdfGetPartitionOfCurrentAllocation(), UdfInitializeAllocationContext(), UdfInitializeFcbMcb(), UdfLookupMetaVsnOfExtent(), UdfLookupPsnOfExtent(), UdfRaiseStatus(), UdfUninitializeFcbMcb(), and USHORT.

Referenced by UdfInitializeFcbFromIcbContext(), and UdfUpdateVcbPhase0().

    03396                    :
    03397
    03398     This routine fills in the data retrieval information for an Fcb.
    03399
    03400 Arguments:
    03401
    03402     Fcb - Fcb to add retrieval information to.
    03403
    03404     IcbContext - Elaborated ICB search context corresponding to this Fcb.
    03405
    03406 Return Value:
    03407
    03408     None.
    03409
    03410 --*/
    03411
    03412 {
    03413     PICBFILE Icb = IcbContext->Active.View;
    03414     PAD_GENERIC GenericAd;
    03415
    03416     ALLOC_ENUM_CONTEXT AllocContext;
    03417
    03418     LONGLONG RunningOffset;
    03419     ULONG Psn;
    03420     USHORT Partition;
    03421
    03422     PVCB Vcb = Fcb->Vcb;
    03423
    03424     BOOLEAN Result;
    03425     BOOLEAN InFileTail = FALSE;
    03426
    03427     PAGED_CODE();
    03428
    03429     //
    03430     //  Check inputs
    03431     //
    03432
    03433     ASSERT_IRP_CONTEXT( IrpContext );
    03434     ASSERT_FCB( Fcb );
    03435
    03436     //
    03437     //  Immediately return for objects with zero information space.  Note that
    03438     //  passing this test does not indicate that the file has any recorded space.
    03439     //
    03440
    03441     if (Fcb->FileSize.QuadPart == 0) {
    03442
    03443         return;
    03444     }
    03445
    03446     UdfInitializeAllocationContext( IrpContext,
    03447                                     &AllocContext,
    03448                                     IcbContext );
    03449
    03450     //
    03451     //  Handle the case of embedded data.
    03452     //
    03453
    03454     if (AllocContext.AllocType == ICBTAG_F_ALLOC_IMMEDIATE) {
    03455
    03456         //
    03457         //  Teardown any existing mcb.
    03458         //
    03459
    03460         UdfUninitializeFcbMcb( Fcb );
    03461
    03462         //
    03463         //  Establish a single block mapping to the Icb itself and mark the Fcb as
    03464         //  having embedded data.  Mapping will occur through the Metadata stream.
    03465         //  Note that by virtue of having an Icb here we know it has already had
    03466         //  a mapping established in the Metadata stream, so just retrieve that.
    03467         //
    03468
    03469         SetFlag( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA );
    03470
    03471         Fcb->EmbeddedVsn = UdfLookupMetaVsnOfExtent( IrpContext,
    03472                                                      Vcb,
    03473                                                      IcbContext->Active.Partition,
    03474                                                      Icb->Destag.Lbn,
    03475                                                      BlockSize( Vcb ),
    03476                                                      FALSE );
    03477
    03478         //
    03479         //  Note the offset of the data in the Icb.
    03480         //
    03481
    03482         Fcb->EmbeddedOffset = FIELD_OFFSET( ICBFILE, EAs ) + Icb->EALength;
    03483
    03484         //
    03485         //  Check that the information length agrees.
    03486         //
    03487
    03488         if (Icb->AllocLength != Fcb->FileSize.LowPart) {
    03489
    03490             DebugTrace(( 0, Dbg, "UdfInitializeAllocations, embedded alloc %08x != filesize %08x\n",
    03491                          Icb->AllocLength,
    03492                          Fcb->FileSize.LowPart ));
    03493             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    03494         }
    03495
    03496         return;
    03497     }
    03498
    03499     //
    03500     //  Now initialize the mapping structure for this Fcb.
    03501     //
    03502
    03503     UdfInitializeFcbMcb( Fcb );
    03504
    03505     //
    03506     //  Now walk the chain of allocation descriptors for the object, adding them into the
    03507     //  mapping.
    03508     //
    03509
    03510     RunningOffset = 0;
    03511
    03512     do {
    03513
    03514         //
    03515         //  Do file tail consistency checking (4/12.1).  We will have a file body
    03516         //  which is exactly the size of the information length, and a run of allocated
    03517         //  but unrecorded space following.
    03518         //
    03519
    03520         if (Fcb->FileSize.QuadPart == RunningOffset) {
    03521
    03522             InFileTail = TRUE;
    03523         }
    03524
    03525         //
    03526         //  It is impermissible for an interior body extent of an object to not be
    03527         //  an integral multiple of a logical block in size (note that the last
    03528         //  will tend to be).  Also check that the body didn't overshoot the information
    03529         //  length and that the tail descriptor type is correct.
    03530         //
    03531
    03532         GenericAd = AllocContext.Alloc;
    03533
    03534         if ((!InFileTail && (BlockOffset( Vcb, RunningOffset ) ||
    03535                              Fcb->FileSize.QuadPart < RunningOffset)) ||
    03536             (InFileTail && GenericAd->Length.Type != NSRLENGTH_TYPE_UNRECORDED)) {
    03537
    03538             DebugTrace(( 0, Dbg, "UdfInitializeAllocations, InFileTail == %u, bad alloc\n",
    03539                          InFileTail ));
    03540             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    03541         }
    03542
    03543         //
    03544         //  In the file tail we'll just slum along an be a nitpick.  Technically, as a
    03545         //  readonly implementation I don't have to care at all about what is here.
    03546         //
    03547
    03548         if (InFileTail) {
    03549
    03550             continue;
    03551         }
    03552
    03553         //
    03554         //  Based on the descriptor type, pull it apart and add the mapping.
    03555         //
    03556
    03557         if (GenericAd->Length.Type == NSRLENGTH_TYPE_RECORDED) {
    03558
    03559             //
    03560             //  Grab the Psn this extent starts at and add the allocation.
    03561             //
    03562
    03563             Psn = UdfLookupPsnOfExtent( IrpContext,
    03564                                         Vcb,
    03565                                         UdfGetPartitionOfCurrentAllocation( &AllocContext ),
    03566                                         GenericAd->Start,
    03567                                         GenericAd->Length.Length );
    03568
    03569             Result = FsRtlAddLargeMcbEntry( &Fcb->Mcb,
    03570                                             LlSectorsFromBytes( Vcb, RunningOffset ),
    03571                                             Psn,
    03572                                             SectorsFromBytes( Vcb, SectorAlign( Vcb, GenericAd->Length.Length ) ));
    03573
    03574             ASSERT( Result );
    03575         }
    03576
    03577         RunningOffset += GenericAd->Length.Length;
    03578
    03579     } while ( UdfGetNextAllocation( IrpContext, &AllocContext ));
    03580
    03581     //
    03582     //  We must have had body allocation descriptors for the entire file
    03583     //  information length.
    03584     //
    03585
    03586     if (Fcb->FileSize.QuadPart != RunningOffset) {
    03587
    03588         DebugTrace(( 0, Dbg, "UdfInitializeAllocations, total descriptors != filesize\n" ));
    03589         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    03590     }
    03591 }

VOID UdfInitializeCrc16 | ( | ULONG | Polynomial | ) |

Definition at line 1083 of file udfdata.c.

References FsRtlAllocatePoolWithTag, n, PUSHORT, TAG_CRC_TABLE, UdfCrcTable, UdfPagedPool, and USHORT.

Referenced by UdfInitializeGlobalData().

    01089                    :
    01090
    01091     This routine generates the 16bit CRC Table to be used in CRC calculation.
    01092
    01093 Arguments:
    01094
    01095     Polynomial - Starting seed for the generation
    01096
    01097 Return Value:
    01098
    01099     None
    01100
    01101 --*/
    01102
    01103 {
    01104     ULONG n, i, Crc;
    01105
    01106     //
    01107     //  All CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
    01108     //  and Ned W. Rhodes of Software Systems Group.  It has been published in
    01109     //  "Design and Validation of Computer Protocols", Prentice Hall, Englewood
    01110     //  Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
    01111     //
    01112     //  Copyright is held by AT&T.
    01113     //
    01114     //  AT&T gives permission for the free use of the source code.
    01115     //
    01116
    01117     UdfCrcTable = (PUSHORT) FsRtlAllocatePoolWithTag( UdfPagedPool,
    01118                                                       256 * sizeof(USHORT),
    01119                                                       TAG_CRC_TABLE );
    01120
    01121     for (n = 0; n < 256; n++) {
    01122
    01123         Crc = n << 8;
    01124
    01125         for (i = 0; i < 8; i++) {
    01126
    01127             if(Crc & 0x8000) {
    01128
    01129                 Crc = (Crc << 1) ^ Polynomial;
    01130
    01131             } else {
    01132
    01133                 Crc <<= 1;
    01134             }
    01135
    01136             Crc &= 0xffff;
    01137         }
    01138
    01139         UdfCrcTable[n] = (USHORT) Crc;
    01140     }
    01141 }

VOID UdfInitializeDirContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PDIR_ENUM_CONTEXT | DirContext
| ) |

Definition at line 60 of file dirsup.c.

References ASSERT_IRP_CONTEXT.

Referenced by UdfCommonCreate(), UdfInitializeCompoundDirContext(), UdfInitializeEnumeration(), and UdfQueryAlternateNameInfo().

    00067                    :
    00068
    00069     This routine initializes a directory enumeartion context.
    00070
    00071     Call this exactly once in the lifetime of a context.
    00072
    00073 Arguments:
    00074
    00075     DirContext - a context to initialize
    00076
    00077 Return Value:
    00078
    00079     None.
    00080
    00081 --*/
    00082
    00083 {
    00084     //
    00085     //  Check inputs.
    00086     //
    00087
    00088     ASSERT_IRP_CONTEXT( IrpContext );
    00089
    00090     //
    00091     //  Provide defaults for fields, nothing too special.
    00092     //
    00093
    00094     RtlZeroMemory( DirContext, sizeof(DIR_ENUM_CONTEXT) );
    00095 }

VOID UdfInitializeFcbFromIcbContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PICB_SEARCH_CONTEXT | IcbContext
| ) |

Definition at line 2297 of file udfs/strucsup.c.

References ICBFILE::AllocLength, ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, BlockSize, ICBFILE::Destag, DESTAG_ID_NSR_FILE, EA_SEARCH_CONTEXT, ICBFILE::EALength, FCB_STATE_IN_FCB_TABLE, FCB_STATE_INITIALIZED, ICBTAG::FileType, ICBFILE::Icbtag, ICBTAG_FILE_T_DIRECTORY, ICBTAG_FILE_T_FILE, DESTAG::Ident, ICBFILE::InfoLength, ICBFILE::LinkCount, LlBlockAlign, LongOffset, PAGED_CODE, SetFlag, UdfInitializeAllocations(), UdfInsertFcbTable, UdfLockFcb, UdfRaiseStatus(), UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, UdfUnlockFcb, and UdfUpdateTimestampsFromIcbContext().

Referenced by UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), and UdfUpdateVcbPhase1().

    02305                    :
    02306
    02307     This routine is called to initialize an Fcb from a direct ICB.  It should
    02308     only be called once in the lifetime of an Fcb and will fill in the Mcb
    02309     from the chained allocation descriptors of the ICB.
    02310
    02311 Arguments:
    02312
    02313     Fcb - The Fcb being initialized
    02314
    02315     IcbOontext - An search context containing the active direct ICB for the object
    02316
    02317 Return Value:
    02318
    02319     None.
    02320
    02321 --*/
    02322
    02323 {
    02324     EA_SEARCH_CONTEXT EaContext;
    02325     PICBFILE Icb;
    02326
    02327     PVCB Vcb;
    02328
    02329     PAGED_CODE();
    02330
    02331     //
    02332     //  Check inputs
    02333     //
    02334
    02335     ASSERT_IRP_CONTEXT( IrpContext );
    02336     ASSERT_FCB( Fcb );
    02337
    02338     //
    02339     //  Directly reference for convenience
    02340     //
    02341
    02342     Icb = IcbContext->Active.View;
    02343     Vcb = Fcb->Vcb;
    02344
    02345     ASSERT( IcbContext->IcbType == DESTAG_ID_NSR_FILE && Icb->Destag.Ident == DESTAG_ID_NSR_FILE );
    02346
    02347     //
    02348     //  Check that the full indicated size of the direct entry is sane and
    02349     //  that the length of the EA segment is correctly aligned.  A direct
    02350     //  entry is less than a single logical block in size.
    02351     //
    02352
    02353     if (LongOffset( Icb->EALength ) ||
    02354         FIELD_OFFSET( ICBFILE, EAs ) + Icb->EALength + Icb->AllocLength > BlockSize( IcbContext->Vcb )) {
    02355
    02356         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    02357     }
    02358
    02359     UdfLockFcb( IrpContext, Fcb );
    02360
    02361     //
    02362     //  Try-finally for cleanup.
    02363     //
    02364
    02365     try {
    02366
    02367         //
    02368         //  Verify that the types mesh and set state flags.
    02369         //
    02370
    02371         if (Fcb->NodeTypeCode == UDFS_NTC_FCB_INDEX && Icb->Icbtag.FileType == ICBTAG_FILE_T_DIRECTORY) {
    02372
    02373             SetFlag( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY );
    02374
    02375         } else if (!(Fcb->NodeTypeCode == UDFS_NTC_FCB_DATA && Icb->Icbtag.FileType == ICBTAG_FILE_T_FILE)) {
    02376
    02377             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    02378         }
    02379
    02380         SetFlag( Fcb->FileAttributes, FILE_ATTRIBUTE_READONLY );
    02381
    02382         //
    02383         //  Initialize the common header in the Fcb.
    02384         //
    02385
    02386         Fcb->Resource = &Fcb->Vcb->FileResource;
    02387
    02388         //
    02389         //  Size and lookup all allocations for this object.
    02390         //
    02391
    02392         Fcb->AllocationSize.QuadPart = LlBlockAlign( Vcb, Icb->InfoLength );
    02393
    02394         Fcb->FileSize.QuadPart =
    02395         Fcb->ValidDataLength.QuadPart = Icb->InfoLength;
    02396
    02397         UdfInitializeAllocations( IrpContext,
    02398                                   Fcb,
    02399                                   IcbContext );
    02400
    02401         //
    02402         //  Lift all of the timestamps for this guy.
    02403         //
    02404
    02405         UdfUpdateTimestampsFromIcbContext( IrpContext,
    02406                                            IcbContext,
    02407                                            &Fcb->Timestamps );
    02408
    02409         //
    02410         //  Pick up the link count.
    02411         //
    02412
    02413         Fcb->LinkCount = Icb->LinkCount;
    02414
    02415         //
    02416         //  Link into the Fcb table.  Someone else is responsible for the name linkage, which is
    02417         //  all that remains.  We also note that the Fcb is fully initialized at this point.
    02418         //
    02419
    02420         UdfInsertFcbTable( IrpContext, Fcb );
    02421         SetFlag( Fcb->FcbState, FCB_STATE_IN_FCB_TABLE | FCB_STATE_INITIALIZED );
    02422
    02423     } finally {
    02424
    02425         UdfUnlockFcb( IrpContext, Fcb );
    02426     }
    02427
    02428     return;
    02429 }

VOID UdfInitializeIcbContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext,
|  | IN PVCB | Vcb,
|  | IN USHORT | IcbType,
|  | IN USHORT | Partition,
|  | IN ULONG | Lbn,
|  | IN ULONG | Length
| ) |

Definition at line 3060 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT, PAGED_CODE, and UdfMapMetadataView().

Referenced by UdfLookupFileEntryInEnumeration().

    03072                    :
    03073
    03074     This routine is called to initialize a context to search an Icb hierarchy.
    03075
    03076 Arguments:
    03077
    03078     Vcb - Vcb for the volume.
    03079
    03080     IcbType - Type of direct entry we expect to find (DESTAG_ID...)
    03081
    03082     Partition - partition of the hierarchy.
    03083
    03084     Lbn - lbn of the hierarchy.
    03085
    03086     Length - length of the root extent of the hierarchy.
    03087
    03088 Return Value:
    03089
    03090     None.
    03091
    03092 --*/
    03093
    03094 {
    03095     PAGED_CODE();
    03096
    03097     //
    03098     //  Check input parameters.
    03099     //
    03100
    03101     ASSERT_IRP_CONTEXT( IrpContext );
    03102
    03103     RtlZeroMemory( IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
    03104
    03105     IcbContext->Vcb = Vcb;
    03106     IcbContext->IcbType = IcbType;
    03107
    03108     //
    03109     //  Map the first extent into the current slot.
    03110     //
    03111
    03112     UdfMapMetadataView( IrpContext,
    03113                         &IcbContext->Current,
    03114                         Vcb,
    03115                         Partition,
    03116                         Lbn,
    03117                         Length );
    03118     return;
    03119
    03120 }

VOID UdfInitializeIcbContextFromFcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext,
|  | IN PFCB | Fcb
| ) |

Definition at line 2951 of file udfs/strucsup.c.

References ASSERT_FCB, ASSERT_IRP_CONTEXT, BlockSize, ICBFILE::Destag, DESTAG_ID_NSR_FILE, DESTAG_ID_NSR_ICBIND, DESTAG_ID_NSR_ICBTRM, DESTAG_ID_NSR_PINTEG, DESTAG_ID_NSR_UASE, FALSE, ICBFILE::Icbtag, DESTAG::Ident, ICBTAG::MaxEntries, PAGED_CODE, UdfGetFidLbn, UdfGetFidPartition, UdfMapMetadataView(), UdfRaiseStatus(), and UdfVerifyDescriptor().

Referenced by UdfLookupFileEntryInEnumeration(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), and UdfUpdateVcbPhase1().

    02959                    :
    02960
    02961     This routine is called to initialize a context to search the Icb hierarchy
    02962     associated with an Fcb.
    02963
    02964 Arguments:
    02965
    02966     Fcb - Fcb associated with the hierarchy to search.
    02967
    02968 Return Value:
    02969
    02970     None.
    02971
    02972 --*/
    02973
    02974 {
    02975     PAGED_CODE();
    02976
    02977     //
    02978     //  Check input parameters.
    02979     //
    02980
    02981     ASSERT_IRP_CONTEXT( IrpContext );
    02982     ASSERT_FCB( Fcb );
    02983
    02984     RtlZeroMemory( IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
    02985
    02986     IcbContext->Vcb = Fcb->Vcb;
    02987     IcbContext->IcbType = DESTAG_ID_NSR_FILE;
    02988
    02989     //
    02990     //  It is possible that we don't have an idea what the length of the root extent is.
    02991     //  This will commonly happen in the OpenById case.
    02992     //
    02993
    02994     if (Fcb->RootExtentLength == 0) {
    02995
    02996         PICBFILE Icb;
    02997
    02998         //
    02999         //  We have to lift the first entry from this (possibly bogus!) extent
    03000         //  and find out how many entries can be recorded, then unmap/remap the view
    03001         //  to try to get the extent.
    03002         //
    03003
    03004         UdfMapMetadataView( IrpContext,
    03005                             &IcbContext->Current,
    03006                             IcbContext->Vcb,
    03007                             UdfGetFidPartition( Fcb->FileId ),
    03008                             UdfGetFidLbn( Fcb->FileId ),
    03009                             BlockSize( IcbContext->Vcb ));
    03010
    03011         Icb = IcbContext->Current.View;
    03012
    03013         //
    03014         //  We can only accomplish the guess if we have a descriptor which contains an ICB
    03015         //  Tag, which contains a field that can tell us what we need to know.
    03016         //
    03017
    03018         if (Icb->Destag.Ident == DESTAG_ID_NSR_ICBIND ||
    03019             Icb->Destag.Ident == DESTAG_ID_NSR_ICBTRM ||
    03020             Icb->Destag.Ident == DESTAG_ID_NSR_FILE ||
    03021             Icb->Destag.Ident == DESTAG_ID_NSR_UASE ||
    03022             Icb->Destag.Ident == DESTAG_ID_NSR_PINTEG) {
    03023
    03024             UdfVerifyDescriptor( IrpContext,
    03025                                  &Icb->Destag,
    03026                                  Icb->Destag.Ident,
    03027                                  BlockSize( IcbContext->Vcb ),
    03028                                  UdfGetFidLbn( Fcb->FileId ),
    03029                                  FALSE );
    03030         } else {
    03031
    03032             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    03033         }
    03034
    03035         //
    03036         //  Now the MaxEntries (4/14.6.4) field of the Icb Tag should tell us how big the extent
    03037         //  should be.  The tail of this could be unrecorded.  We could even have landed in the middle
    03038         //  of an extent.  This is only a guess.  For whatever reason we are having to guess this
    03039         //  information, any results are expected to be coming with few guarantees.
    03040         //
    03041
    03042         Fcb->RootExtentLength = Icb->Icbtag.MaxEntries * BlockSize( IcbContext->Vcb );
    03043     }
    03044
    03045     //
    03046     //  Map the first extent into the current slot.
    03047     //
    03048
    03049     UdfMapMetadataView( IrpContext,
    03050                         &IcbContext->Current,
    03051                         IcbContext->Vcb,
    03052                         UdfGetFidPartition( Fcb->FileId ),
    03053                         UdfGetFidLbn( Fcb->FileId ),
    03054                         Fcb->RootExtentLength );
    03055     return;
    03056 }

VOID UdfInitializeLcbFromDirContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PLCB | Lcb,
|  | IN PDIR_ENUM_CONTEXT | DirContext
| ) |

Definition at line 503 of file prefxsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_LCB, FlagOn, NSR_FID_F_HIDDEN, NULL, PAGED_CODE, PDIR_ENUM_CONTEXT, and SetFlag.

Referenced by UdfOpenObjectFromDirContext().

    00511                    :
    00512
    00513     This routine performs common initialization of Lcbs from found directory
    00514     entries.
    00515
    00516 Arguments:
    00517
    00518     Lcb - the Lcb to initialize.
    00519
    00520     DirContext - the directory enumeration context, enumerated to the FID associated
    00521         with this Lcb.
    00522
    00523 Return Value:
    00524
    00525     None.
    00526
    00527 --*/
    00528
    00529 {
    00530     PAGED_CODE();
    00531
    00532     //
    00533     //  Check inputs.
    00534     //
    00535
    00536     ASSERT_IRP_CONTEXT( IrpContext );
    00537     ASSERT_LCB( Lcb );
    00538
    00539     ASSERT( DirContext->Fid != NULL );
    00540
    00541     //
    00542     //  This is falling down trivial now.  Simply update the hidden flag in the Lcb.
    00543     //
    00544
    00545     if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_HIDDEN )) {
    00546
    00547         SetFlag( Lcb->FileAttributes, FILE_ATTRIBUTE_HIDDEN );
    00548     }
    00549 }

NTSTATUS UdfInitializePcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN OUT PPCB * | Pcb,
|  | IN PNSR_LVOL | LVD
| ) |

Definition at line 367 of file allocsup.c.

References Add2Ptr, ASSERT_OPTIONAL_PCB, Dbg, DebugTrace, FALSE, FlagOn, FsRtlAllocatePoolWithTag, ISONsrLvolSize, _PARTMAP_UDF_GENERIC::Length, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _PARTMAP_UDF_GENERIC::PartID, _PARTMAP_SPARABLE::Partition, _PARTMAP_VIRTUAL::Partition, PARTMAP_PHYSICAL::Partition, PARTITION, _tagPARTITION::PartitionNumber, PARTMAP_SPARABLE, PARTMAP_TYPE_PHYSICAL, PARTMAP_TYPE_PROXY, PCB_FLAG_PHYSICAL_PARTITION, PCB_FLAG_SPARABLE_PARTITION, PCB_FLAG_VIRTUAL_PARTITION, Physical, PNSR_LVOL, PPARTMAP_PHYSICAL, PPARTMAP_SPARABLE, PPARTMAP_UDF_GENERIC, PPARTMAP_VIRTUAL, SetFlag, Status, TAG_NSR_FSD, TRUE, _PARTMAP_UDF_GENERIC::Type, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, UdfCreatePcb(), UdfDeletePcb(), UdfDomainIdentifierContained(), UdfSparablePartitionDomainIdentifier, UdfVirtualPartitionDomainIdentifier, USHORT, Virtual, _PARTMAP_SPARABLE::VolSetSeq, and PARTMAP_PHYSICAL::VolSetSeq.

Referenced by UdfFindVolumeDescriptors().

    00376                    :
    00377
    00378     This routine walks through the partition map of a Logical Volume Descriptor
    00379     and builds an intializing Pcb from it.  The Pcb will be ready to be used
    00380     in searching for the partition descriptors of a volume.
    00381
    00382 Arguments:
    00383
    00384     Vcb - The volume this Pcb will pertain to
    00385
    00386     Pcb - Caller's pointer to the Pcb
    00387
    00388     LVD - The Logical Volume Descriptor being used
    00389
    00390 Return Value:
    00391
    00392     STATUS_SUCCESS if the partition map is good and the Pcb is built
    00393
    00394     STATUS_DISK_CORRUPT_ERROR if corrupt maps are found
    00395
    00396     STATUS_UNRECOGNIZED_VOLUME if noncompliant maps are found
    00397
    00398 --*/
    00399
    00400 {
    00401     PPARTMAP_UDF_GENERIC Map;
    00402     PPARTITION Partition;
    00403
    00404     BOOLEAN Found;
    00405
    00406     PAGED_CODE();
    00407
    00408     //
    00409     //  Check the input parameters
    00410     //
    00411
    00412     ASSERT_OPTIONAL_PCB( *Pcb );
    00413
    00414     DebugTrace(( +1, Dbg,
    00415                  "UdfInitializePcb, Lvd %08x\n",
    00416                  LVD ));
    00417
    00418     //
    00419     //  Delete a pre-existing (partially initialized from a failed
    00420     //  crawl of a VDS) Pcb.
    00421     //
    00422
    00423     if (*Pcb != NULL) {
    00424
    00425         UdfDeletePcb( *Pcb );
    00426         *Pcb = NULL;
    00427     }
    00428
    00429     *Pcb = UdfCreatePcb( LVD->MapTableCount );
    00430
    00431     //
    00432     //  Walk the table of partition maps intializing the Pcb for the descriptor
    00433     //  initialization pass.
    00434     //
    00435
    00436     for (Map = (PPARTMAP_UDF_GENERIC) LVD->MapTable,
    00437          Partition = (*Pcb)->Partition;
    00438
    00439          Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
    00440
    00441          Map = Add2Ptr( Map, Map->Length, PPARTMAP_UDF_GENERIC ),
    00442          Partition++) {
    00443
    00444         //
    00445         //  Now check that this LVD can actually contain this map entry.  First check that
    00446         //  the descriptor can contain the first few fields, then check that it can hold
    00447         //  all of the bytes claimed by the descriptor.
    00448         //
    00449
    00450         if (Add2Ptr( Map, sizeof( PARTMAP_GENERIC ), PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR ) ||
    00451             Add2Ptr( Map, Map->Length,               PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR )) {
    00452
    00453             DebugTrace(( 0, Dbg,
    00454                          "UdfInitializePcb, map at +%04x beyond Lvd size %04x\n",
    00455                          (PCHAR) Map - (PCHAR) LVD,
    00456                          ISONsrLvolSize( LVD )));
    00457
    00458             DebugTrace(( -1, Dbg,
    00459                          "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
    00460
    00461             return STATUS_DISK_CORRUPT_ERROR;
    00462         }
    00463
    00464         //
    00465         //  Now load up this map entry.
    00466         //
    00467
    00468         switch (Map->Type) {
    00469
    00470             case PARTMAP_TYPE_PHYSICAL:
    00471
    00472                 {
    00473                     PPARTMAP_PHYSICAL MapPhysical = (PPARTMAP_PHYSICAL) Map;
    00474
    00475                     //
    00476                     //  Type 1 - Physical Partition
    00477                     //
    00478
    00479                     DebugTrace(( 0, Dbg,
    00480                                  "UdfInitializePcb, map reference %02x is Physical (Partition # %08x)\n",
    00481                                  (Partition - (*Pcb)->Partition)/sizeof(PARTITION),
    00482                                  MapPhysical->Partition ));
    00483
    00484                     //
    00485                     //  It must be the case that the volume the partition is on is the first
    00486                     //  one since we only do single disc UDF.  This will have already been
    00487                     //  checked by the caller.
    00488                     //
    00489
    00490                     if (MapPhysical->VolSetSeq > 1) {
    00491
    00492                         DebugTrace(( 0, Dbg,
    00493                                      "UdfInitializePcb, ... but physical partition resides on volume set volume # %08x (> 1)!\n",
    00494                                      MapPhysical->VolSetSeq ));
    00495
    00496                         DebugTrace(( -1, Dbg,
    00497                                      "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
    00498
    00499                         return STATUS_DISK_CORRUPT_ERROR;
    00500                     }
    00501
    00502                     SetFlag( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION );
    00503                     Partition->Type = Physical;
    00504                     Partition->Physical.PartitionNumber = MapPhysical->Partition;
    00505                 }
    00506
    00507                 break;
    00508
    00509             case PARTMAP_TYPE_PROXY:
    00510
    00511                 //
    00512                 //  Type 2 - a Proxy Partition, something not explicitly physical.
    00513                 //
    00514
    00515                 DebugTrace(( 0, Dbg,
    00516                              "UdfInitializePcb, map reference %02x is a proxy\n",
    00517                              (Partition - (*Pcb)->Partition)/sizeof(PARTITION)));
    00518
    00519                 //
    00520                 //  Handle the various types of proxy partitions we recognize
    00521                 //
    00522
    00523                 if (UdfDomainIdentifierContained( &Map->PartID,
    00524                                                   &UdfVirtualPartitionDomainIdentifier,
    00525                                                   UDF_VERSION_150,
    00526                                                   UDF_VERSION_RECOGNIZED )) {
    00527
    00528                     {
    00529                         PPARTMAP_VIRTUAL MapVirtual = (PPARTMAP_VIRTUAL) Map;
    00530
    00531                         //
    00532                         //  Only one of these guys can exist, since there can be only one VAT per media surface.
    00533                         //
    00534
    00535                         if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) {
    00536
    00537                             DebugTrace(( 0, Dbg,
    00538                                          "UdfInitializePcb, ... but this is a second virtual partition!?!!\n" ));
    00539
    00540                             DebugTrace(( -1, Dbg,
    00541                                          "UdfInitializePcb -> STATUS_UNCRECOGNIZED_VOLUME\n" ));
    00542
    00543                             return STATUS_UNRECOGNIZED_VOLUME;
    00544                         }
    00545
    00546                         DebugTrace(( 0, Dbg,
    00547                                      "UdfInitializePcb, ... Virtual (Partition # %08x)\n",
    00548                                      MapVirtual->Partition ));
    00549
    00550                         SetFlag( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION );
    00551                         Partition->Type = Virtual;
    00552
    00553                         //
    00554                         //  We will convert the partition number to a partition reference
    00555                         //  before returning.
    00556                         //
    00557
    00558                         Partition->Virtual.RelatedReference = MapVirtual->Partition;
    00559                     }
    00560
    00561                 } else if (UdfDomainIdentifierContained( &Map->PartID,
    00562                                                          &UdfSparablePartitionDomainIdentifier,
    00563                                                          UDF_VERSION_150,
    00564                                                          UDF_VERSION_RECOGNIZED )) {
    00565
    00566                     {
    00567                         NTSTATUS Status;
    00568                         PPARTMAP_SPARABLE MapSparable = (PPARTMAP_SPARABLE) Map;
    00569
    00570                         //
    00571                         //  It must be the case that the volume the partition is on is the first
    00572                         //  one since we only do single disc UDF.  This will have already been
    00573                         //  checked by the caller.
    00574                         //
    00575
    00576                         if (MapSparable->VolSetSeq > 1) {
    00577
    00578                             DebugTrace(( 0, Dbg,
    00579                                          "UdfInitializePcb, ... but sparable partition resides on volume set volume # %08x (> 1)!\n",
    00580                                          MapSparable->VolSetSeq ));
    00581
    00582                             DebugTrace(( -1, Dbg,
    00583                                          "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
    00584
    00585                             return STATUS_DISK_CORRUPT_ERROR;
    00586                         }
    00587
    00588                         DebugTrace(( 0, Dbg,
    00589                                      "UdfInitializePcb, ... Sparable (Partition # %08x)\n",
    00590                                      MapSparable->Partition ));
    00591
    00592                         //
    00593                         //  We pretend that sparable partitions are basically the same as
    00594                         //  physical partitions.  Since we are not r/w (and will never be
    00595                         //  on media that requires host-based sparing in any case), this
    00596                         //  is a good simplification.
    00597                         //
    00598
    00599                         SetFlag( (*Pcb)->Flags, PCB_FLAG_SPARABLE_PARTITION );
    00600                         Partition->Type = Physical;
    00601                         Partition->Physical.PartitionNumber = MapSparable->Partition;
    00602
    00603                         //
    00604                         //  Save this map for use when the partition descriptor is found.
    00605                         //  We can't load the sparing table at this time because we have
    00606                         //  to turn the Lbn->Psn mapping into a Psn->Psn mapping.  UDF
    00607                         //  believes that the way sparing will be used in concert with
    00608                         //  the Lbn->Psn mapping engine (like UdfLookupPsnOfExtent).
    00609                         //
    00610                         //  Unfortunately, this would be a bit painful at this time.
    00611                         //  The users of UdfLookupPsnOfExtent would need to iterate
    00612                         //  over a new interface (not so bad) but the Vmcb package
    00613                         //  would need to be turned inside out so that it didn't do
    00614                         //  the page-filling alignment of blocks in the metadata
    00615                         //  stream - instead, UdfLookupMetaVsnOfExtent would need to
    00616                         //  do this itself.  I choose to lay the sparing engine into
    00617                         //  the read path and raw sector read engine instead.
    00618                         //
    00619
    00620                         Partition->Physical.SparingMap = FsRtlAllocatePoolWithTag( PagedPool,
    00621                                                                                    sizeof(PARTMAP_SPARABLE),
    00622                                                                                    TAG_NSR_FSD);
    00623                         RtlCopyMemory( Partition->Physical.SparingMap,
    00624                                        MapSparable,
    00625                                        sizeof(PARTMAP_SPARABLE));
    00626                     }
    00627
    00628                 } else {
    00629
    00630                     DebugTrace(( 0, Dbg,
    00631                                  "UdfInitializePcb, ... but we don't recognize this proxy!\n" ));
    00632
    00633                     DebugTrace(( -1, Dbg,
    00634                                  "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
    00635
    00636                     return STATUS_UNRECOGNIZED_VOLUME;
    00637                 }
    00638
    00639                 break;
    00640
    00641             default:
    00642
    00643                 DebugTrace(( 0, Dbg,
    00644                              "UdfInitializePcb, map reference %02x is of unknown type %02x\n",
    00645                              Map->Type ));
    00646
    00647                 DebugTrace(( -1, Dbg,
    00648                              "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
    00649
    00650                 return STATUS_UNRECOGNIZED_VOLUME;
    00651                 break;
    00652         }
    00653     }
    00654
    00655     if (!FlagOn( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION | PCB_FLAG_SPARABLE_PARTITION )) {
    00656
    00657         DebugTrace(( 0, Dbg,
    00658                      "UdfInitializePcb, no physical partition seen on this logical volume!\n" ));
    00659
    00660         DebugTrace(( -1, Dbg,
    00661                      "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
    00662
    00663         return STATUS_UNRECOGNIZED_VOLUME;
    00664     }
    00665
    00666     if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) {
    00667
    00668         PPARTITION Host;
    00669
    00670         //
    00671         //  Confirm the validity of any type 2 virtual maps on this volume
    00672         //  and convert partition numbers to partition references that will
    00673         //  immediately index an element of the Pcb.
    00674         //
    00675
    00676         for (Partition = (*Pcb)->Partition;
    00677              Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
    00678              Partition++) {
    00679
    00680             if (Partition->Type == Virtual) {
    00681
    00682                 //
    00683                 //  Go find the partition this thing is talking about
    00684                 //
    00685
    00686                 Found = FALSE;
    00687
    00688                 for (Host = (*Pcb)->Partition;
    00689                      Host < &(*Pcb)->Partition[(*Pcb)->Partitions];
    00690                      Host++) {
    00691
    00692                     if (Host->Type == Physical &&
    00693                         Host->Physical.PartitionNumber ==
    00694                         Partition->Virtual.RelatedReference) {
    00695
    00696                         Partition->Virtual.RelatedReference =
    00697                             (USHORT)(Host - (*Pcb)->Partition)/sizeof(PARTITION);
    00698                         Found = TRUE;
    00699                         break;
    00700                     }
    00701                 }
    00702
    00703                 //
    00704                 //  Failure to find a physical partition for this virtual guy
    00705                 //  is not a good sign.
    00706                 //
    00707
    00708                 if (!Found) {
    00709
    00710                     return STATUS_DISK_CORRUPT_ERROR;
    00711                 }
    00712             }
    00713         }
    00714     }
    00715
    00716     DebugTrace(( -1, Dbg,
    00717              "UdfInitializePcb -> STATUS_SUCCESS\n" ));
    00718
    00719     return STATUS_SUCCESS;
    00720 }

VOID UdfInitializeStackIrpContext | ( | OUT PIRP_CONTEXT | IrpContext,
|  | IN PIRP_CONTEXT_LITE | IrpContextLite
| ) |

Definition at line 1528 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT_LITE, IRP_CONTEXT, IRP_CONTEXT_FLAG_ON_STACK, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_CLOSE, PAGED_CODE, PIRP_CONTEXT_LITE, SetFlag, and UDFS_NTC_IRP_CONTEXT.

Referenced by UdfFspClose().

    01535                    :
    01536
    01537     This routine is called to initialize an IrpContext for the current
    01538     UDFS request.  The IrpContext is on the stack and we need to initialize
    01539     it for the current request.  The request is a close operation.
    01540
    01541 Arguments:
    01542
    01543     IrpContext - IrpContext to initialize.
    01544
    01545     IrpContextLite - Structure containing the details of this request.
    01546
    01547 Return Value:
    01548
    01549     None
    01550
    01551 --*/
    01552
    01553 {
    01554     PAGED_CODE();
    01555
    01556     ASSERT_IRP_CONTEXT_LITE( IrpContextLite );
    01557
    01558     //
    01559     //  Zero and then initialize the structure.
    01560     //
    01561
    01562     RtlZeroMemory( IrpContext, sizeof( IRP_CONTEXT ));
    01563
    01564     //
    01565     //  Set the proper node type code and node byte size
    01566     //
    01567
    01568     IrpContext->NodeTypeCode = UDFS_NTC_IRP_CONTEXT;
    01569     IrpContext->NodeByteSize = sizeof( IRP_CONTEXT );
    01570
    01571     //
    01572     //  Note that this is from the stack.
    01573     //
    01574
    01575     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ON_STACK );
    01576
    01577     //
    01578     //  Copy RealDevice for workque algorithms.
    01579     //
    01580
    01581     IrpContext->RealDevice = IrpContextLite->RealDevice;
    01582
    01583     //
    01584     //  The Vcb is found in the Fcb.
    01585     //
    01586
    01587     IrpContext->Vcb = IrpContextLite->Fcb->Vcb;
    01588
    01589     //
    01590     //  Major/Minor Function codes
    01591     //
    01592
    01593     IrpContext->MajorFunction = IRP_MJ_CLOSE;
    01594
    01595     //
    01596     //  Set the wait parameter
    01597     //
    01598
    01599     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    01600
    01601     return;
    01602 }

BOOLEAN UdfInitializeVcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PVCB | Vcb,
|  | IN PDEVICE_OBJECT | TargetDeviceObject,
|  | IN PVPB | Vpb,
|  | IN PDISK_GEOMETRY | DiskGeometry,
|  | IN ULONG | MediaChangeCount
| ) |

Definition at line 331 of file udfs/strucsup.c.

References ExInitializeFastMutex, ExInitializeResource, FlagOn, FsRtlNotifyInitializeSync(), NULL, ObReferenceObject, PAGED_CODE, RtlInitializeGenericTable(), SetFlag, TRUE, UdfAllocateTable(), UdfData, UdfDeallocateTable(), UdfFcbTableCompare(), UdfHighBit(), UDFS_BASE_RESIDUAL_REFERENCE, UDFS_BASE_RESIDUAL_USER_REFERENCE, UDFS_NTC_VCB, VCB, VCB_STATE_REMOVABLE_MEDIA, VcbMountInProgress, and _UDF_DATA::VcbQueue.

Referenced by UdfMountVolume().

    00342                    :
    00343
    00344     This routine initializes and inserts a new Vcb record into the in-memory
    00345     data structure.  The Vcb record "hangs" off the end of the Volume device
    00346     object and must be allocated by our caller.
    00347
    00348 Arguments:
    00349
    00350     Vcb - Supplies the address of the Vcb record being initialized.
    00351
    00352     TargetDeviceObject - Supplies the address of the target device object to
    00353         associate with the Vcb record.
    00354
    00355     Vpb - Supplies the address of the Vpb to associate with the Vcb record.
    00356
    00357     MediaChangeCount - Initial media change count of the target device
    00358
    00359 Return Value:
    00360
    00361     Boolean TRUE if the volume looks reasonable to continue mounting, FALSE
    00362     otherwise.  This routine can raise on allocation failure.
    00363
    00364 --*/
    00365
    00366 {
    00367     PAGED_CODE();
    00368
    00369     //
    00370     //  We start by first zeroing out all of the VCB, this will guarantee
    00371     //  that any stale data is wiped clean.
    00372     //
    00373
    00374     RtlZeroMemory( Vcb, sizeof( VCB ));
    00375
    00376     //
    00377     //  Set the proper node type code and node byte size.
    00378     //
    00379
    00380     Vcb->NodeTypeCode = UDFS_NTC_VCB;
    00381     Vcb->NodeByteSize = sizeof( VCB );
    00382
    00383     //
    00384     //  Initialize the DirNotify structures.  Do this first so there is
    00385     //  no cleanup if it raises.  Nothing else below will fail with
    00386     //  a raise.
    00387     //
    00388
    00389     InitializeListHead( &Vcb->DirNotifyList );
    00390     FsRtlNotifyInitializeSync( &Vcb->NotifySync );
    00391
    00392     //
    00393     //  Initialize the resource variable for the Vcb and files.
    00394     //
    00395
    00396     ExInitializeResource( &Vcb->VcbResource );
    00397     ExInitializeResource( &Vcb->FileResource );
    00398     ExInitializeFastMutex( &Vcb->VcbMutex );
    00399
    00400     //
    00401     //  Insert this Vcb record on the UdfData.VcbQueue.
    00402     //
    00403
    00404     InsertHeadList( &UdfData.VcbQueue, &Vcb->VcbLinks );
    00405
    00406     //
    00407     //  Set the Target Device Object and Vpb fields, referencing the
    00408     //  target device.
    00409     //
    00410
    00411     ObReferenceObject( TargetDeviceObject );
    00412     Vcb->TargetDeviceObject = TargetDeviceObject;
    00413     Vcb->Vpb = Vpb;
    00414
    00415     //
    00416     //  Set the removable media flag based on the real device's
    00417     //  characteristics
    00418     //
    00419
    00420     if (FlagOn( Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA )) {
    00421
    00422         SetFlag( Vcb->VcbState, VCB_STATE_REMOVABLE_MEDIA );
    00423     }
    00424
    00425     //
    00426     //  Initialize the generic Fcb Table.
    00427     //
    00428
    00429     RtlInitializeGenericTable( &Vcb->FcbTable,
    00430                                (PRTL_GENERIC_COMPARE_ROUTINE) UdfFcbTableCompare,
    00431                                (PRTL_GENERIC_ALLOCATE_ROUTINE) UdfAllocateTable,
    00432                                (PRTL_GENERIC_FREE_ROUTINE) UdfDeallocateTable,
    00433                                NULL );
    00434
    00435     //
    00436     //  Show that we have a mount in progress.
    00437     //
    00438
    00439     Vcb->VcbCondition = VcbMountInProgress;
    00440
    00441     //
    00442     //  Refererence the Vcb for two reasons.  The first is a reference
    00443     //  that prevents the Vcb from going away on the last close unless
    00444     //  dismount has already occurred.  The second is to make sure
    00445     //  we don't go into the dismount path on any error during mount
    00446     //  until we get to the Mount cleanup.
    00447     //
    00448
    00449     Vcb->VcbResidualReference = UDFS_BASE_RESIDUAL_REFERENCE;
    00450     Vcb->VcbResidualUserReference = UDFS_BASE_RESIDUAL_USER_REFERENCE;
    00451
    00452     Vcb->VcbReference = 1 + Vcb->VcbResidualReference;
    00453
    00454     //
    00455     //  Set the sector size.
    00456     //
    00457
    00458     Vcb->SectorSize = DiskGeometry->BytesPerSector;
    00459
    00460     //
    00461     //  Set the sector shift amount.
    00462     //
    00463
    00464     Vcb->SectorShift = UdfHighBit( DiskGeometry->BytesPerSector );
    00465
    00466     //
    00467     //  Set the media change count on the device
    00468     //
    00469
    00470     Vcb->MediaChangeCount = MediaChangeCount;
    00471
    00472     return TRUE;
    00473 }

VOID UdfInitializeVmcb | ( | IN PVMCB | Vmcb,
|  | IN POOL_TYPE | PoolType,
|  | IN ULONG | MaximumLbn,
|  | IN ULONG | LbSize
| ) |

Definition at line 219 of file vmcbsup.c.

References Dbg, DebugTrace, DebugUnwind, FALSE, FsRtlInitializeMcb(), FsRtlUninitializeMcb(), KeInitializeMutex(), PAGED_CODE, RtlInitializeGenericTable(), SectorSize, and TRUE.

Referenced by UdfUpdateVcbPhase0().

    00228                    :
    00229
    00230     This routine initializes a new Vmcb Structure.  The caller must
    00231     supply the memory for the structure.  This must precede all other calls
    00232     that set/query the volume file mapping.
    00233
    00234     If pool is not available this routine will raise a status value
    00235     indicating insufficient resources.
    00236
    00237 Arguments:
    00238
    00239     Vmcb - Supplies a pointer to the volume file structure to initialize.
    00240
    00241     PoolType - Supplies the pool type to use when allocating additional
    00242         internal structures.
    00243
    00244     MaximumLbn - Supplies the maximum Lbn value that is valid for this
    00245         volume.
    00246
    00247     LbSize - Size of a sector on this volume
    00248
    00249 Return Value:
    00250
    00251     None
    00252
    00253 --*/
    00254
    00255 {
    00256     BOOLEAN VbnInitialized;
    00257     BOOLEAN LbnInitialized;
    00258
    00259     PAGED_CODE();
    00260
    00261     DebugTrace(( +1, Dbg, "UdfInitializeVmcb, Vmcb = %08x\n", Vmcb ));
    00262
    00263     VbnInitialized = FALSE;
    00264     LbnInitialized = FALSE;
    00265
    00266     try {
    00267
    00268         //
    00269         //  Initialize the fields in the vmcb structure
    00270         //
    00271
    00272         KeInitializeMutex( &Vmcb->Mutex, 0 );
    00273
    00274         FsRtlInitializeMcb( &Vmcb->VbnIndexed, PoolType );
    00275         VbnInitialized = TRUE;
    00276
    00277         FsRtlInitializeMcb( &Vmcb->LbnIndexed, PoolType );
    00278         LbnInitialized = TRUE;
    00279
    00280         Vmcb->MaximumLbn = MaximumLbn;
    00281
    00282         Vmcb->SectorSize = SectorSize;
    00283
    00284 #if VMCB_WRITE_SUPPORT
    00285
    00286         //
    00287         //  For the dirty table we store in the table context field the pool
    00288         //  type to use for allocating additional structures
    00289         //
    00290
    00291         RtlInitializeGenericTable( &Vmcb->DirtyTable,
    00292                                    PbCompareDirtyVmcb,
    00293                                    PbAllocateDirtyVmcb,
    00294                                    PbDeallocateDirtyVmcb,
    00295                                    (PVOID)PoolType );
    00296
    00297 #endif // VMCB_WRITE_SUPPORT
    00298
    00299     } finally {
    00300
    00301         //
    00302         //  If this is an abnormal termination then check if we need to
    00303         //  uninitialize the mcb structures
    00304         //
    00305
    00306         if (AbnormalTermination()) {
    00307
    00308             if (VbnInitialized) { FsRtlUninitializeMcb( &Vmcb->VbnIndexed ); }
    00309             if (LbnInitialized) { FsRtlUninitializeMcb( &Vmcb->LbnIndexed ); }
    00310         }
    00311
    00312         DebugUnwind("UdfInitializeVmcb");
    00313         DebugTrace(( -1, Dbg, "UdfInitializeVmcb -> VOID\n" ));
    00314     }
    00315
    00316     //
    00317     //  And return to our caller
    00318     //
    00319
    00320     return;
    00321 }

PLCB UdfInsertPrefix | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PUNICODE_STRING | Name,
|  | IN BOOLEAN | ShortNameMatch,
|  | IN BOOLEAN | IgnoreCase,
|  | IN PFCB | ParentFcb
| ) |

Definition at line 64 of file prefxsup.c.

References Add2Ptr, ASSERT_EXCLUSIVE_FCB, ASSERT_FCB, ASSERT_FCB_INDEX, ASSERT_IRP_CONTEXT, _LCB::ChildFcb, _LCB::ChildFcbLinks, ExAllocateFromPagedLookasideList(), _LCB::FileAttributes, _LCB::FileName, _LCB::Flags, FsRtlAllocatePoolWithTag, LCB_FLAG_IGNORE_CASE, LCB_FLAG_POOL_ALLOCATED, LCB_FLAG_SHORT_NAME, Name, _LCB::NodeByteSize, _LCB::NodeTypeCode, NULL, PAGED_CODE, _LCB::ParentFcb, _LCB::ParentFcbLinks, _LCB::Reference, SafeNodeType, SetFlag, SIZEOF_LOOKASIDE_LCB, TAG_LCB, UdfFindNameLink(), UdfFreePool(), UdfInsertNameLink(), UdfLcbLookasideList, UdfPagedPool, UdfRaiseStatus(), UDFS_NTC_FCB_INDEX, and UDFS_NTC_LCB.

Referenced by UdfOpenObjectFromDirContext().

    00075                    :
    00076
    00077     This routine inserts an Lcb linking the two Fcbs together.
    00078
    00079 Arguments:
    00080
    00081     Fcb - This is the Fcb whose name is being inserted into the tree.
    00082
    00083     Name - This is the name for the component.
    00084
    00085     ShortNameMatch - Indicates whether this name was found on an explicit 8.3 search
    00086
    00087     IgnoreCase - Indicates if we should insert into the case-insensitive tree.
    00088
    00089     ParentFcb - This is the ParentFcb.  The prefix tree is attached to this.
    00090
    00091 Return Value:
    00092
    00093     PLCB - the Lcb inserted.
    00094
    00095 --*/
    00096
    00097 {
    00098     PLCB Lcb;
    00099     PRTL_SPLAY_LINKS *TreeRoot;
    00100     PLIST_ENTRY ListLinks;
    00101     ULONG Flags;
    00102
    00103     PWCHAR NameBuffer;
    00104
    00105     PAGED_CODE();
    00106
    00107     //
    00108     //  Check inputs.
    00109     //
    00110
    00111     ASSERT_IRP_CONTEXT( IrpContext );
    00112     ASSERT_FCB( Fcb );
    00113
    00114     ASSERT_EXCLUSIVE_FCB( Fcb );
    00115     ASSERT_EXCLUSIVE_FCB( ParentFcb );
    00116     ASSERT_FCB_INDEX( ParentFcb );
    00117
    00118     //
    00119     //  It must be the case that an index Fcb is only referenced by a single index.  Now
    00120     //  we walk the child's Lcb queue to insure that if any prefixes have already been
    00121     //  inserted, they all refer to the index Fcb we are linking to.  This is the only way
    00122     //  we can detect directory cross-linkage.
    00123     //
    00124
    00125     if (SafeNodeType( Fcb ) == UDFS_NTC_FCB_INDEX) {
    00126
    00127         for (ListLinks = Fcb->ParentLcbQueue.Flink;
    00128              ListLinks != &Fcb->ParentLcbQueue;
    00129              ListLinks = ListLinks->Flink) {
    00130
    00131             Lcb = CONTAINING_RECORD( ListLinks, LCB, ChildFcbLinks );
    00132
    00133             if (Lcb->ParentFcb != ParentFcb) {
    00134
    00135                 UdfRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
    00136             }
    00137         }
    00138     }
    00139
    00140     //
    00141     //  Capture the separate cases.
    00142     //
    00143
    00144     if (IgnoreCase) {
    00145
    00146         TreeRoot = &ParentFcb->IgnoreCaseRoot;
    00147         Flags = LCB_FLAG_IGNORE_CASE;
    00148
    00149     } else {
    00150
    00151         TreeRoot = &ParentFcb->ExactCaseRoot;
    00152         Flags = 0;
    00153     }
    00154
    00155     if (ShortNameMatch) {
    00156
    00157         SetFlag( Flags, LCB_FLAG_SHORT_NAME );
    00158     }
    00159
    00160     //
    00161     //  Allocate space for the Lcb.
    00162     //
    00163
    00164     if ( sizeof( LCB ) + Name->Length > SIZEOF_LOOKASIDE_LCB ) {
    00165
    00166         Lcb = FsRtlAllocatePoolWithTag( UdfPagedPool,
    00167                                         sizeof( LCB ) + Name->Length,
    00168                                         TAG_LCB );
    00169
    00170         SetFlag( Flags, LCB_FLAG_POOL_ALLOCATED );
    00171
    00172     } else {
    00173
    00174         Lcb = ExAllocateFromPagedLookasideList( &UdfLcbLookasideList );
    00175     }
    00176
    00177     //
    00178     //  Set the type and size.
    00179     //
    00180
    00181     Lcb->NodeTypeCode = UDFS_NTC_LCB;
    00182     Lcb->NodeByteSize = sizeof( LCB ) + Name->Length;
    00183
    00184     //
    00185     //  Initialize the name-based file attributes.
    00186     //
    00187
    00188     Lcb->FileAttributes = 0;
    00189
    00190     //
    00191     //  Set up the filename in the Lcb.
    00192     //
    00193
    00194     Lcb->FileName.Length =
    00195     Lcb->FileName.MaximumLength = Name->Length;
    00196
    00197     Lcb->FileName.Buffer = Add2Ptr( Lcb, sizeof( LCB ), PWCHAR );
    00198
    00199     RtlCopyMemory( Lcb->FileName.Buffer,
    00200                    Name->Buffer,
    00201                    Name->Length );
    00202
    00203     //
    00204     //  Insert the Lcb into the prefix tree.
    00205     //
    00206
    00207     Lcb->Flags = Flags;
    00208
    00209     if (!UdfInsertNameLink( IrpContext,
    00210                             TreeRoot,
    00211                             Lcb )) {
    00212
    00213         //
    00214         //  This will very rarely occur.
    00215         //
    00216
    00217         UdfFreePool( &Lcb );
    00218
    00219         Lcb = UdfFindNameLink( IrpContext,
    00220                                TreeRoot,
    00221                                Name );
    00222
    00223         if (Lcb == NULL) {
    00224
    00225             //
    00226             //  Even worse.
    00227             //
    00228
    00229             UdfRaiseStatus( IrpContext, STATUS_DRIVER_INTERNAL_ERROR );
    00230         }
    00231
    00232         return Lcb;
    00233     }
    00234
    00235     //
    00236     //  Link the Fcbs together through the Lcb.
    00237     //
    00238
    00239     Lcb->ParentFcb = ParentFcb;
    00240     Lcb->ChildFcb = Fcb;
    00241
    00242     InsertHeadList( &ParentFcb->ChildLcbQueue, &Lcb->ParentFcbLinks );
    00243     InsertHeadList( &Fcb->ParentLcbQueue, &Lcb->ChildFcbLinks );
    00244
    00245     //
    00246     //  Initialize the reference count.
    00247     //
    00248
    00249     Lcb->Reference = 0;
    00250
    00251     return Lcb;
    00252 }

BOOLEAN UdfIs8dot3Name | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN UNICODE_STRING | FileName
| ) |

Definition at line 176 of file namesup.c.

References ASSERT, ASSERT_IRP_CONTEXT, BYTE_COUNT_8_DOT_3, CHAR, Count, FALSE, FileName, FsRtlIsFatDbcsLegal(), L, NT_SUCCESS, PAGED_CODE, RtlUnicodeStringToCountedOemString(), and TRUE.

Referenced by UdfEnumerateIndex(), UdfFindDirEntry(), UdfQueryAlternateNameInfo(), and UdfQueryDirectory().

    00183                    :
    00184
    00185     This routine checks if the name follows the 8.3 name conventions.  We check for
    00186     the name length and whether the characters are valid.
    00187
    00188 Arguments:
    00189
    00190     FileName - String of bytes containing the name.
    00191
    00192 Return Value:
    00193
    00194     BOOLEAN - TRUE if this name is a legal 8.3 name, FALSE otherwise.
    00195
    00196 --*/
    00197
    00198 {
    00199     CHAR DbcsNameBuffer[ BYTE_COUNT_8_DOT_3 ];
    00200     STRING DbcsName;
    00201
    00202     PWCHAR NextWchar;
    00203     ULONG Count;
    00204
    00205     ULONG DotCount = 0;
    00206     BOOLEAN LastCharDot = FALSE;
    00207
    00208     PAGED_CODE();
    00209
    00210     //
    00211     //  Check inputs.
    00212     //
    00213
    00214     ASSERT_IRP_CONTEXT( IrpContext );
    00215
    00216     //
    00217     //  The length must be less than 24 bytes.
    00218     //
    00219
    00220     ASSERT( FileName.Length != 0 );
    00221     if (FileName.Length > BYTE_COUNT_8_DOT_3) {
    00222
    00223         return FALSE;
    00224     }
    00225
    00226     //
    00227     //  Walk though and check for a space character.
    00228     //
    00229
    00230     NextWchar = FileName.Buffer;
    00231     Count = 0;
    00232
    00233     do {
    00234
    00235         //
    00236         //  No spaces allowed.
    00237         //
    00238
    00239         if (*NextWchar == L' ') { return FALSE; }
    00240
    00241         if (*NextWchar == L'.') {
    00242
    00243             //
    00244             //  Not an 8.3 name if more than 1 dot or more than 8 characters
    00245             //  remaining.  (It is legal for the dot to be in the ninth
    00246             //  position)
    00247             //
    00248
    00249             if ((DotCount > 0) ||
    00250                 (Count > 8 * sizeof( WCHAR ))) {
    00251
    00252                 return FALSE;
    00253             }
    00254
    00255             DotCount += 1;
    00256             LastCharDot = TRUE;
    00257
    00258         } else {
    00259
    00260             LastCharDot = FALSE;
    00261         }
    00262
    00263         Count += 2;
    00264         NextWchar += 1;
    00265
    00266     } while (Count < FileName.Length);
    00267
    00268     //
    00269     //  We can't have a period at the end of the name.
    00270     //
    00271
    00272     if (LastCharDot) {
    00273
    00274         return FALSE;
    00275     }
    00276
    00277     //
    00278     //  Create an Oem name to use to check for a valid short name.
    00279     //
    00280
    00281     DbcsName.MaximumLength = BYTE_COUNT_8_DOT_3;
    00282     DbcsName.Buffer = DbcsNameBuffer;
    00283
    00284     if (!NT_SUCCESS( RtlUnicodeStringToCountedOemString( &DbcsName,
    00285                                                          &FileName,
    00286                                                          FALSE ))) {
    00287
    00288         return FALSE;
    00289     }
    00290
    00291     //
    00292     //  We have now initialized the Oem string.  Call the FsRtl package to check for a
    00293     //  valid FAT name.
    00294     //
    00295
    00296     return FsRtlIsFatDbcsLegal( DbcsName, FALSE, FALSE, FALSE );
    00297 }

INLINE BOOLEAN UdfIsCharacterLegal | ( | IN WCHAR | Character | ) |

Definition at line 1208 of file udfprocs.h.

References FALSE, FsRtlIsAnsiCharacterLegalHpfs, and TRUE.

Referenced by UdfCS0DstringContainsLegalCharacters().

    01214                    :
    01215
    01216     This routine checks that a given UNICODE character is legal.
    01217
    01218 Arguments:
    01219
    01220     Character - a character to check
    01221
    01222 Return Value:
    01223
    01224     BOOLEAN True if a legal character, False otherwise.
    01225
    01226 --*/
    01227
    01228 {
    01229     if (Character < 0xff && !FsRtlIsAnsiCharacterLegalHpfs( Character, FALSE )) {
    01230
    01231         return FALSE;
    01232     }
    01233
    01234     return TRUE;
    01235 }

BOOLEAN UdfIsNameInExpression | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | CurrentName,
|  | IN PUNICODE_STRING | SearchExpression,
|  | IN BOOLEAN | Wild
| ) |

Definition at line 1203 of file namesup.c.

References ASSERT_IRP_CONTEXT, FALSE, FsRtlIsNameInExpression(), NULL, PAGED_CODE, and TRUE.

Referenced by UdfEnumerateIndex().

    01212                    :
    01213
    01214     This routine will compare two Unicode strings.  We assume that if this
    01215     is to be a case-insensitive search then they are already upcased.
    01216
    01217 Arguments:
    01218
    01219     CurrentName - Filename from the disk.
    01220
    01221     SearchExpression - Filename expression to use for match.
    01222
    01223     Wild - True if wildcards are present in SearchExpression.
    01224
    01225 Return Value:
    01226
    01227     BOOLEAN - TRUE if the expressions match, FALSE otherwise.
    01228
    01229 --*/
    01230
    01231 {
    01232     BOOLEAN Match = TRUE;
    01233
    01234     PAGED_CODE();
    01235
    01236     //
    01237     //  Check inputs.
    01238     //
    01239
    01240     ASSERT_IRP_CONTEXT( IrpContext );
    01241
    01242     //
    01243     //  If there are wildcards in the expression then we call the
    01244     //  appropriate FsRtlRoutine.
    01245     //
    01246
    01247     if (Wild) {
    01248
    01249         Match = FsRtlIsNameInExpression( SearchExpression,
    01250                                          CurrentName,
    01251                                          FALSE,
    01252                                          NULL );
    01253
    01254     //
    01255     //  Otherwise do a direct memory comparison for the name string.
    01256     //
    01257
    01258     } else {
    01259
    01260         if ((CurrentName->Length != SearchExpression->Length) ||
    01261             (!RtlEqualMemory( CurrentName->Buffer,
    01262                               SearchExpression->Buffer,
    01263                               CurrentName->Length ))) {
    01264
    01265             Match = FALSE;
    01266         }
    01267     }
    01268
    01269     return Match;
    01270 }

NTSTATUS UdfLockVolumeInternal | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PFILE_OBJECT FileObject | OPTIONAL
| ) |

Definition at line 621 of file udfs/fsctrl.c.

References ASSERT_EXCLUSIVE_VCB, CcWaitForCurrentLazyWriterActivity(), FALSE, FlagOn, IRP_CONTEXT_FLAG_WAIT, NT_SUCCESS, NTSTATUS(), PAGED_CODE, SetFlag, Status, UdfAcquireVcbExclusive, UdfFspClose(), UdfPurgeVolume(), UdfReleaseVcb, and VCB_STATE_LOCKED.

Referenced by UdfLockVolume(), and UdfPnpQueryRemove().

    00629                    :
    00630
    00631     This routine performs the actual lock volume operation.  It will be called
    00632     by anyone wishing to try to protect the volume for a long duration.  PNP
    00633     operations are such a user.
    00634
    00635     The volume must be held exclusive by the caller.
    00636
    00637 Arguments:
    00638
    00639     Vcb - The volume being locked.
    00640
    00641     FileObject - File corresponding to the handle locking the volume.  If this
    00642         is not specified, a system lock is assumed.
    00643
    00644 Return Value:
    00645
    00646     NTSTATUS - The return status for the operation
    00647
    00648 --*/
    00649
    00650 {
    00651     NTSTATUS Status;
    00652     NTSTATUS FinalStatus = (FileObject? STATUS_ACCESS_DENIED: STATUS_DEVICE_BUSY);
    00653     ULONG RemainingUserReferences = (FileObject? 1: 0);
    00654
    00655     PAGED_CODE();
    00656
    00657     ASSERT_EXCLUSIVE_VCB( Vcb );
    00658
    00659     //
    00660     //  If the volume is already locked then complete with success if this file
    00661     //  object has the volume locked, fail otherwise.
    00662     //
    00663
    00664     if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
    00665
    00666         if (FileObject && Vcb->VolumeLockFileObject == FileObject) {
    00667
    00668             FinalStatus = STATUS_SUCCESS;
    00669         }
    00670
    00671     } else if (Vcb->VcbCleanup == RemainingUserReferences) {
    00672
    00673         //
    00674         //  The cleanup count for the volume only reflects the fileobject that
    00675         //  will lock the volume.  Otherwise, we must fail the request.
    00676         //
    00677         //  Since the only cleanup is for the provided fileobject, we will try
    00678         //  to get rid of all of the other user references.  If there is only one
    00679         //  remaining after the purge then we can allow the volume to be locked.
    00680         //
    00681
    00682         UdfPurgeVolume( IrpContext, Vcb, FALSE );
    00683
    00684         //
    00685         //  Now back out of our synchronization and wait for the lazy writer
    00686         //  to finish off any lazy closes that could have been outstanding.
    00687         //
    00688         //  Since we purged, we know that the lazy writer will issue all
    00689         //  possible lazy closes in the next tick - if we hadn't, an otherwise
    00690         //  unopened file with a large amount of dirty data could have hung
    00691         //  around for a while as the data trickled out to the disk.
    00692         //
    00693         //  This is even more important now since we send notification to
    00694         //  alert other folks that this style of check is about to happen so
    00695         //  that they can close their handles.  We don't want to enter a fast
    00696         //  race with the lazy writer tearing down his references to the file.
    00697         //
    00698
    00699         UdfReleaseVcb( IrpContext, Vcb );
    00700
    00701         Status = CcWaitForCurrentLazyWriterActivity();
    00702
    00703         //
    00704         //  This is intentional. If we were able to get the Vcb before, just
    00705         //  wait for it and take advantage of knowing that it is OK to leave
    00706         //  the flag up.
    00707         //
    00708
    00709         SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    00710         UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00711
    00712         if (!NT_SUCCESS( Status )) {
    00713
    00714             return Status;
    00715         }
    00716
    00717         UdfFspClose( Vcb );
    00718
    00719         if (Vcb->VcbUserReference == Vcb->VcbResidualUserReference + RemainingUserReferences) {
    00720
    00721             SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
    00722             Vcb->VolumeLockFileObject = FileObject;
    00723             FinalStatus = STATUS_SUCCESS;
    00724         }
    00725     }
    00726
    00727     return FinalStatus;
    00728 }

VOID UdfLookupActiveIcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext
| ) |

Definition at line 3124 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT, NULL, PAGED_CODE, UDF_ICB_RECURSION_LIMIT, UdfLookupActiveIcbInExtent(), UdfRaiseStatus(), and UdfUnpinView.

Referenced by UdfLookupFileEntryInEnumeration(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), and UdfUpdateVcbPhase1().

    03131                    :
    03132
    03133     This routine is called to cause the active Icb for an Icb hierarchy to be mapped.
    03134     A context initialized by UdfInitializeIcbContext() is required.
    03135
    03136 Arguments:
    03137
    03138     IcbContext - Context which has been initialized to point into an Icb hierarchy.
    03139
    03140 Return Value:
    03141
    03142     None.
    03143
    03144     Raised status if the Icb hierarchy is invalid.
    03145
    03146 --*/
    03147
    03148 {
    03149     PAGED_CODE();
    03150
    03151     //
    03152     //  Check input parameters.
    03153     //
    03154
    03155     ASSERT_IRP_CONTEXT( IrpContext );
    03156
    03157     //
    03158     //  Travel the Icb hierarchy.  Due to the design of ISO 13346, it is convenient to
    03159     //  recursively descend the hierarchy.  Place a limit on this recursion which will
    03160     //  allow traversal of most reasonable hierarchies (this will tail recurse off of
    03161     //  the end of extents).
    03162     //
    03163
    03164     UdfLookupActiveIcbInExtent( IrpContext,
    03165                                 IcbContext,
    03166                                 UDF_ICB_RECURSION_LIMIT );
    03167
    03168     //
    03169     //  We must have found an active ICB.  Drop the last mapped part of the enumeration
    03170     //  at this point.
    03171     //
    03172
    03173     UdfUnpinView( IrpContext, &IcbContext->Current );
    03174
    03175     if (IcbContext->Active.View == NULL) {
    03176
    03177         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    03178     }
    03179 }

BOOLEAN UdfLookupAllocation | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN LONGLONG | FileOffset,
|  | OUT PLONGLONG | DiskOffset,
|  | OUT PULONG | ByteCount
| ) |

Definition at line 69 of file allocsup.c.

References ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, BytesFromSectors, Dbg, DebugTrace, FALSE, FCB_STATE_EMBEDDED_DATA, FCB_STATE_MCB_INITIALIZED, FCB_STATE_VMCB_MAPPING, FlagOn, FsRtlLookupLargeMcbEntry(), LlBytesFromSectors, LlSectorsFromBytes, NULL, PAGED_CODE, _VCB::Pcb, PFCB, SectorOffset, SectorsFromBytes, _PCB::SparingMcb, TRUE, UdfMethod2NextRunoutInSectors, UdfMethod2TransformByteOffset, UdfVmcbVbnToLbn(), VCB_STATE_METHOD_2_FIXUP, _VCB::VcbState, and _VCB::Vmcb.

Referenced by UdfPrepareBuffers().

    00079                    :
    00080
    00081     This routine looks through the mapping information for the file
    00082     to find the logical diskoffset and number of bytes at that offset.
    00083
    00084     This routine assumes we are looking up a valid range in the file.  If
    00085     a mapping does not exist,
    00086
    00087 Arguments:
    00088
    00089     Fcb - Fcb representing this stream.
    00090
    00091     FileOffset - Lookup the allocation beginning at this point.
    00092
    00093     DiskOffset - Address to store the logical disk offset.
    00094
    00095     ByteCount - Address to store the number of contiguous bytes beginning
    00096         at DiskOffset above.
    00097
    00098 Return Value:
    00099
    00100     BOOLEAN - whether the extent is unrecorded data
    00101
    00102 --*/
    00103
    00104 {
    00105     PVCB Vcb;
    00106
    00107     BOOLEAN Recorded = TRUE;
    00108
    00109     BOOLEAN Result;
    00110
    00111     LARGE_INTEGER LocalPsn;
    00112     LARGE_INTEGER LocalSectorCount;
    00113
    00114     PAGED_CODE();
    00115
    00116     //
    00117     //  Check inputs
    00118     //
    00119
    00120     ASSERT_IRP_CONTEXT( IrpContext );
    00121     ASSERT_FCB( Fcb );
    00122
    00123     //
    00124     //  We will never be looking up the allocations of embedded objects.
    00125     //
    00126
    00127     ASSERT( !FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA ));
    00128
    00129     Vcb = Fcb->Vcb;
    00130
    00131     LocalPsn.QuadPart = LocalSectorCount.QuadPart = 0;
    00132
    00133     //
    00134     //  Lookup the entry containing this file offset.
    00135     //
    00136
    00137     if (FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING )) {
    00138
    00139         //
    00140         //  Map this offset into the metadata stream.
    00141         //
    00142
    00143         ASSERT( SectorOffset( Vcb, FileOffset ) == 0 );
    00144
    00145         Result = UdfVmcbVbnToLbn( &Vcb->Vmcb,
    00146                                   SectorsFromBytes( Vcb, FileOffset ),
    00147                                   &LocalPsn.LowPart,
    00148                                   &LocalSectorCount.LowPart );
    00149
    00150         ASSERT( Result );
    00151
    00152     } else {
    00153
    00154         //
    00155         //  Map this offset in a regular stream.
    00156         //
    00157
    00158         ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_MCB_INITIALIZED ));
    00159
    00160         Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
    00161                                            LlSectorsFromBytes( Vcb, FileOffset ),
    00162                                            &LocalPsn.QuadPart,
    00163                                            &LocalSectorCount.QuadPart,
    00164                                            NULL,
    00165                                            NULL,
    00166                                            NULL );
    00167     }
    00168
    00169     //
    00170     //  If within the Mcb then we use the data out of this entry and are nearly done.
    00171     //
    00172
    00173     if (Result) {
    00174
    00175         if ( LocalPsn.QuadPart == -1 ) {
    00176
    00177             //
    00178             //  Regular files can have holey allocations which represent unrecorded extents.  For
    00179             //  such extents which are sandwiched in between recorded extents of the file, the Mcb
    00180             //  package tells us that it found a valid mapping but that it doesn't correspond to
    00181             //  any extents on the media yet.  In this case, simply fake the disk offset.  The
    00182             //  returned sector count is accurate.
    00183             //
    00184
    00185             *DiskOffset = 0;
    00186
    00187             Recorded = FALSE;
    00188
    00189         } else {
    00190
    00191             //
    00192             //  Now mimic the effects of physical sector sparing.  This may shrink the size of the
    00193             //  returned run if sparing interrupted the extent on disc.
    00194             //
    00195
    00196             ASSERT( LocalPsn.HighPart == 0 );
    00197
    00198             if (Vcb->Pcb->SparingMcb) {
    00199
    00200                 LONGLONG SparingPsn;
    00201                 LONGLONG SparingSectorCount;
    00202
    00203                 if (FsRtlLookupLargeMcbEntry( Vcb->Pcb->SparingMcb,
    00204                                               LocalPsn.LowPart,
    00205                                               &SparingPsn,
    00206                                               &SparingSectorCount,
    00207                                               NULL,
    00208                                               NULL,
    00209                                               NULL )) {
    00210
    00211                     //
    00212                     //  Only emit noise if we will really change anything as a result
    00213                     //  of the sparing table.
    00214                     //
    00215
    00216                     if (SparingPsn != -1 ||
    00217                         SparingSectorCount < LocalSectorCount.QuadPart) {
    00218
    00219                         DebugTrace(( 0, Dbg, "UdfLookupAllocation, spared [%x, +%x) onto [%x, +%x)\n",
    00220                                              LocalPsn.LowPart,
    00221                                              LocalSectorCount.LowPart,
    00222                                              (ULONG) SparingPsn,
    00223                                              (ULONG) SparingSectorCount ));
    00224                     }
    00225
    00226                     //
    00227                     //  If we did not land in a hole, map the sector.
    00228                     //
    00229
    00230                     if (SparingPsn != -1) {
    00231
    00232                         LocalPsn.QuadPart = SparingPsn;
    00233                     }
    00234
    00235                     //
    00236                     //  The returned sector count now reduces the previous sector count.
    00237                     //  If we landed in a hole, this indicates that the trailing edge of
    00238                     //  the extent is spared, if not this indicates that the leading
    00239                     //  edge is spared.
    00240                     //
    00241
    00242                     if (SparingSectorCount < LocalSectorCount.QuadPart) {
    00243
    00244                         LocalSectorCount.QuadPart = SparingSectorCount;
    00245                     }
    00246                 }
    00247             }
    00248
    00249             *DiskOffset = LlBytesFromSectors( Vcb, LocalPsn.QuadPart ) + SectorOffset( Vcb, FileOffset );
    00250
    00251             //
    00252             //  Now we can apply method 2 fixups, which will again interrupt the size of the extent.
    00253             //
    00254
    00255             if (FlagOn( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) {
    00256
    00257                 LARGE_INTEGER SectorsToRunout;
    00258
    00259                 SectorsToRunout.QuadPart= UdfMethod2NextRunoutInSectors( Vcb, *DiskOffset );
    00260
    00261                 if (SectorsToRunout.QuadPart < LocalSectorCount.QuadPart) {
    00262
    00263                     LocalSectorCount.QuadPart = SectorsToRunout.QuadPart;
    00264                 }
    00265
    00266                 *DiskOffset = UdfMethod2TransformByteOffset( Vcb, *DiskOffset );
    00267             }
    00268         }
    00269
    00270     } else {
    00271
    00272         //
    00273         //  We know that prior to this call the system has restricted IO to points within the
    00274         //  the file data.  Since we failed to find a mapping this is an unrecorded extent at
    00275         //  the end of the file, so just conjure up a proper representation.
    00276         //
    00277
    00278         ASSERT( FileOffset < Fcb->FileSize.QuadPart );
    00279
    00280         *DiskOffset = 0;
    00281
    00282         LocalSectorCount.QuadPart = LlSectorsFromBytes( Vcb, Fcb->FileSize.QuadPart ) -
    00283                                     LlSectorsFromBytes( Vcb, FileOffset ) +
    00284                                     1;
    00285
    00286         Recorded = FALSE;
    00287     }
    00288
    00289     //
    00290     //  Restrict to MAXULONG bytes of allocation
    00291     //
    00292
    00293     if (LocalSectorCount.QuadPart > SectorsFromBytes( Vcb, MAXULONG )) {
    00294
    00295         *ByteCount = MAXULONG;
    00296
    00297     } else {
    00298
    00299         *ByteCount = BytesFromSectors( Vcb, LocalSectorCount.LowPart );
    00300     }
    00301
    00302     *ByteCount -= SectorOffset( Vcb, FileOffset );
    00303
    00304     return Recorded;
    00305 }

PFCB UdfLookupFcbTable | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN FILE_ID | FileId
| ) |

Definition at line 1949 of file udfs/strucsup.c.

References _FCB_TABLE_ELEMENT::Fcb, FILE_ID, Key, NULL, PAGED_CODE, PFCB_TABLE_ELEMENT, and RtlLookupElementGenericTable().

Referenced by UdfCreateFcb().

    01957                    :
    01958
    01959     This routine will look through the Fcb table looking for a matching
    01960     entry.
    01961
    01962 Arguments:
    01963
    01964     Vcb - Vcb for this volume.
    01965
    01966     FileId - This is the key value to use for the search.
    01967
    01968 Return Value:
    01969
    01970     PFCB - A pointer to the matching entry or NULL otherwise.
    01971
    01972 --*/
    01973
    01974 {
    01975     FCB_TABLE_ELEMENT Key;
    01976     PFCB_TABLE_ELEMENT Hit;
    01977     PFCB ReturnFcb = NULL;
    01978
    01979     PAGED_CODE();
    01980
    01981     Key.FileId = FileId;
    01982
    01983     Hit = (PFCB_TABLE_ELEMENT) RtlLookupElementGenericTable( &Vcb->FcbTable, &Key );
    01984
    01985     if (Hit != NULL) {
    01986
    01987         ReturnFcb = Hit->Fcb;
    01988     }
    01989
    01990     return ReturnFcb;
    01991
    01992     UNREFERENCED_PARAMETER( IrpContext );
    01993 }

BOOLEAN UdfLookupInitialDirEntry | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PDIR_ENUM_CONTEXT | DirContext,
|  | IN PLONGLONG InitialOffset | OPTIONAL
| ) |

Definition at line 165 of file dirsup.c.

References Add2Ptr, ASSERT_FCB_INDEX, ASSERT_IRP_CONTEXT, CcMapData(), DIR_CONTEXT_FLAG_SEEN_NONCONSTANT, DIR_CONTEXT_FLAG_SEEN_PARENT, GenericOffset, GenericTruncate, NULL, PAGED_CODE, TRUE, UdfCreateInternalStream(), UdfLookupDirEntryPostProcessing(), UdfUnpinData, and VACB_MAPPING_GRANULARITY.

Referenced by UdfFindDirEntry(), UdfLookupInitialFileIndex(), and UdfLookupNextFileIndex().

    00174                    :
    00175
    00176     This routine begins the enumeration of a directory by setting the context
    00177     at the first avaliable directory entry.
    00178
    00179 Arguments:
    00180
    00181     Fcb - the directory being enumerated.
    00182
    00183     DirContext - a corresponding context for the enumeration.
    00184
    00185     InitialOffset - an optional starting byte offset to base the enumeration.
    00186
    00187 Return Value:
    00188
    00189     If InitialOffset is unspecified, TRUE will always be returned.  Failure will result
    00190     in a raised status indicating corruption.
    00191
    00192     If InitialOffset is specified, TRUE will be returned if a valid entry is found at this
    00193     offset, FALSE otherwise.
    00194
    00195 --*/
    00196
    00197 {
    00198     BOOLEAN Result;
    00199
    00200     PAGED_CODE();
    00201
    00202     //
    00203     //  Check inputs.
    00204     //
    00205
    00206     ASSERT_IRP_CONTEXT( IrpContext );
    00207     ASSERT_FCB_INDEX( Fcb );
    00208
    00209     //
    00210     //  Create the internal stream if it isn't already in place.
    00211     //
    00212
    00213     if (Fcb->FileObject == NULL) {
    00214
    00215         UdfCreateInternalStream( IrpContext, Fcb->Vcb, Fcb );
    00216     }
    00217
    00218     //
    00219     //  Reset the flags.
    00220     //
    00221
    00222     DirContext->Flags = 0;
    00223
    00224     if (InitialOffset) {
    00225
    00226         //
    00227         //  If we are beginning in the middle of the stream, adjust the sanity check flags.
    00228         //
    00229
    00230         if (*InitialOffset != 0) {
    00231
    00232             DirContext->Flags = DIR_CONTEXT_FLAG_SEEN_NONCONSTANT | DIR_CONTEXT_FLAG_SEEN_PARENT;
    00233         }
    00234
    00235         //
    00236         //  Now set up the range we will map.  This is constrained by the size of a cache view.
    00237         //
    00238
    00239         DirContext->BaseOffset.QuadPart = GenericTruncate( *InitialOffset, VACB_MAPPING_GRANULARITY );
    00240         DirContext->ViewOffset = (ULONG) GenericOffset( *InitialOffset, VACB_MAPPING_GRANULARITY );
    00241
    00242     } else {
    00243
    00244         //
    00245         //  Map at the beginning.
    00246         //
    00247
    00248         DirContext->BaseOffset.QuadPart = 0;
    00249         DirContext->ViewOffset = 0;
    00250     }
    00251
    00252     //
    00253     //  Contain the view length by the size of the stream and map.
    00254     //
    00255
    00256     DirContext->ViewLength = VACB_MAPPING_GRANULARITY;
    00257
    00258     if (DirContext->BaseOffset.QuadPart + DirContext->ViewLength > Fcb->FileSize.QuadPart) {
    00259
    00260         DirContext->ViewLength = (ULONG) (Fcb->FileSize.QuadPart - DirContext->BaseOffset.QuadPart);
    00261     }
    00262
    00263     UdfUnpinData( IrpContext, &DirContext->Bcb );
    00264
    00265     CcMapData( Fcb->FileObject,
    00266                &DirContext->BaseOffset,
    00267                DirContext->ViewLength,
    00268                TRUE,
    00269                &DirContext->Bcb,
    00270                &DirContext->View );
    00271
    00272     DirContext->Fid = Add2Ptr( DirContext->View, DirContext->ViewOffset, PNSR_FID );
    00273
    00274     //
    00275     //  The state of the context is now valid.  Tail off into our common post-processor
    00276     //  to finish the work.
    00277     //
    00278
    00279     return UdfLookupDirEntryPostProcessing( IrpContext,
    00280                                             Fcb,
    00281                                             DirContext,
    00282                                             (BOOLEAN) (InitialOffset != NULL));
    00283 }

ULONG UdfLookupMetaVsnOfExtent | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN USHORT | Reference,
|  | IN ULONG | Lbn,
|  | IN ULONG | Len,
|  | IN BOOLEAN | ExactEnd
| ) |

Definition at line 1177 of file allocsup.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, BlockOffset, BlocksFromBytes, BlocksFromSectors, CcSetFileSizes(), FALSE, LlBytesFromSectors, NULL, PCC_FILE_SIZES, SectorsFromBytes, TRUE, try_leave, UdfAddVmcbMapping(), UdfLockFcb, UdfLookupPsnOfExtent(), UdfRaiseStatus(), UdfRemoveVmcbMapping(), UdfUnlockFcb, and UdfVmcbLbnToVbn().

Referenced by UdfInitializeAllocations(), UdfMapMetadataView(), and UdfUpdateVcbPhase0().

    01188                    :
    01189
    01190     This routine maps the input logical block extent on a given partition to
    01191     a starting virtual block in the metadata stream.  If a mapping does not
    01192     exist, one will be created and the metadata stream extended.
    01193
    01194 Arguments:
    01195
    01196     Vcb - Vcb of logical volume
    01197
    01198     Reference - Partition reference to use in the mapping
    01199
    01200     Lbn - Logical block number
    01201
    01202     Len - Length of extent in bytes
    01203
    01204     ExactEnd - Indicates the extension policy if these blocks are not mapped.
    01205
    01206 Return Value:
    01207
    01208     ULONG virtual sector number
    01209
    01210     Raised status if the Lbn extent is split across multiple Vbn extents.
    01211
    01212 --*/
    01213
    01214 {
    01215     ULONG Vsn;
    01216     ULONG Psn;
    01217     ULONG SectorCount;
    01218
    01219     BOOLEAN Result;
    01220
    01221     BOOLEAN UnwindExtension = FALSE;
    01222     LONGLONG UnwindAllocationSize;
    01223
    01224     PFCB Fcb = NULL;
    01225
    01226     //
    01227     //  Check inputs
    01228     //
    01229
    01230     ASSERT_IRP_CONTEXT( IrpContext );
    01231     ASSERT_VCB( Vcb );
    01232
    01233     //
    01234     //  The extent must be an integral number of logical blocks in length.
    01235     //
    01236
    01237     if (Len == 0 || BlockOffset( Vcb, Len )) {
    01238
    01239         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    01240     }
    01241
    01242
    01243     //
    01244     //  Get the physical mapping of the extent.  The Mcb package operates on ULONG/ULONG
    01245     //  keys and values so we must render our 48bit address into 32.  We can do this since
    01246     //  this is a single surface implementation, and it is guaranteed that a surface cannot
    01247     //  contain more than MAXULONG physical sectors.
    01248     //
    01249
    01250     Psn = UdfLookupPsnOfExtent( IrpContext,
    01251                                 Vcb,
    01252                                 Reference,
    01253                                 Lbn,
    01254                                 Len );
    01255
    01256     //
    01257     //  Use try-finally for cleanup
    01258     //
    01259
    01260     try {
    01261
    01262         //
    01263         //  We must safely establish a mapping and extend the metadata stream so that cached
    01264         //  reads can occur on this new extent.
    01265         //
    01266
    01267         Fcb = Vcb->MetadataFcb;
    01268         UdfLockFcb( IrpContext, Fcb );
    01269
    01270         Result = UdfVmcbLbnToVbn( &Vcb->Vmcb,
    01271                                   Psn,
    01272                                   &Vsn,
    01273                                   &SectorCount );
    01274
    01275         if (Result) {
    01276
    01277             //
    01278             //  If the mapping covers the extent, we can give this back.
    01279             //
    01280
    01281             if (BlocksFromSectors( Vcb, SectorCount ) >= BlocksFromBytes( Vcb, Len )) {
    01282
    01283                 try_leave( NOTHING );
    01284
    01285             }
    01286
    01287             //
    01288             //  It is a fatal error if the extent we are mapping is not wholly contained
    01289             //  by an extent of Vsns in the Vmcb.  This will indicate that some structure
    01290             //  is trying to overlap another.
    01291             //
    01292
    01293             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    01294         }
    01295
    01296         //
    01297         //  Add the new mapping.  We know that it is being added to the end of the stream.
    01298         //
    01299
    01300         UdfAddVmcbMapping( &Vcb->Vmcb,
    01301                            Psn,
    01302                            SectorsFromBytes( Vcb, Len ),
    01303                            ExactEnd,
    01304                            &Vsn,
    01305                            &SectorCount );
    01306
    01307         UnwindAllocationSize = Fcb->AllocationSize.QuadPart;
    01308         UnwindExtension = TRUE;
    01309
    01310         Fcb->AllocationSize.QuadPart =
    01311         Fcb->FileSize.QuadPart =
    01312         Fcb->ValidDataLength.QuadPart = LlBytesFromSectors( Vcb, Vsn + SectorCount);
    01313
    01314         CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
    01315         UnwindExtension = FALSE;
    01316
    01317         //
    01318         //  We do not need to purge the cache maps since the Vmcb will always be
    01319         //  page aligned, and thus any reads will have filled it with valid data.
    01320         //
    01321
    01322     } finally {
    01323
    01324         if (UnwindExtension) {
    01325
    01326             ULONG FirstZappedVsn;
    01327
    01328             //
    01329             //  Strip off the additional mappings we made.
    01330             //
    01331
    01332             Fcb->AllocationSize.QuadPart =
    01333             Fcb->FileSize.QuadPart =
    01334             Fcb->ValidDataLength.QuadPart = UnwindAllocationSize;
    01335
    01336             FirstZappedVsn = SectorsFromBytes( Vcb, UnwindAllocationSize );
    01337
    01338             UdfRemoveVmcbMapping( &Vcb->Vmcb,
    01339                                   FirstZappedVsn,
    01340                                   Vsn + SectorCount - FirstZappedVsn );
    01341
    01342             CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
    01343         }
    01344
    01345         if (Fcb) { UdfUnlockFcb( IrpContext, Fcb ); }
    01346     }
    01347
    01348     return Vsn;
    01349 }

BOOLEAN UdfLookupNextDirEntry | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN PDIR_ENUM_CONTEXT | DirContext
| ) |

Definition at line 287 of file dirsup.c.

References Add2Ptr, ASSERT_FCB_INDEX, ASSERT_IRP_CONTEXT, ClearFlag, DIR_CONTEXT_FLAG_FID_BUFFERED, FALSE, FlagOn, PAGED_CODE, UdfFreePool(), and UdfLookupDirEntryPostProcessing().

Referenced by UdfFindDirEntry(), and UdfLookupNextFileIndex().

    00295                    :
    00296
    00297     This routine advances the enumeration of a directory by one entry.
    00298
    00299 Arguments:
    00300
    00301     Fcb - the directory being enumerated.
    00302
    00303     DirContext - a corresponding context for the enumeration.
    00304
    00305 Return Value:
    00306
    00307     BOOLEAN True if another Fid is avaliable, False if we are at the end.
    00308
    00309 --*/
    00310
    00311 {
    00312     PAGED_CODE();
    00313
    00314     //
    00315     //  Check inputs.
    00316     //
    00317
    00318     ASSERT_IRP_CONTEXT( IrpContext );
    00319     ASSERT_FCB_INDEX( Fcb );
    00320
    00321     //
    00322     //  If we have reached the end, stop.
    00323     //
    00324
    00325     if (DirContext->BaseOffset.QuadPart + DirContext->NextFidOffset == Fcb->FileSize.QuadPart) {
    00326
    00327         return FALSE;
    00328     }
    00329
    00330     //
    00331     //  If the previous Fid was buffered, dismantle it now.
    00332     //
    00333
    00334     if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED )) {
    00335
    00336         ClearFlag( DirContext->Flags, DIR_CONTEXT_FLAG_FID_BUFFERED );
    00337         UdfFreePool( &DirContext->Fid );
    00338     }
    00339
    00340     //
    00341     //  Move the pointers based on the knowledge generated in the previous iteration.
    00342     //
    00343
    00344     DirContext->ViewOffset = DirContext->NextFidOffset;
    00345     DirContext->Fid = Add2Ptr( DirContext->View, DirContext->ViewOffset, PNSR_FID );
    00346
    00347     //
    00348     //  The state of the context is now valid.  Tail off into our common post-processor
    00349     //  to finish the work.
    00350     //
    00351
    00352     return UdfLookupDirEntryPostProcessing( IrpContext,
    00353                                             Fcb,
    00354                                             DirContext,
    00355                                             FALSE );
    00356 }

ULONG UdfLookupPsnOfExtent | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN USHORT | Reference,
|  | IN ULONG | Lbn,
|  | IN ULONG | Len
| ) |

Definition at line 1017 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_PCB, ASSERT_VCB, BlocksFromBytes, BlockSize, CcMapData(), Dbg, DebugTrace, DebugUnwind, FALSE, _tagPARTITION::Length, Offset, PAGED_CODE, _PCB::Partition, _PCB::Partitions, PBCB, Physical, SectorsFromBlocks, SectorsFromBytes, TRUE, UdfLookupPsnOfExtent(), UdfRaiseStatus(), UdfUnpinData, and Virtual.

Referenced by UdfFindFileSetDescriptor(), UdfInitializeAllocations(), UdfLookupMetaVsnOfExtent(), and UdfLookupPsnOfExtent().

    01027                    :
    01028
    01029     This routine maps the input logical block extent on a given partition to
    01030     a starting physical sector.  It doubles as a bounds checker - if the routine
    01031     does not raise, the caller is guaranteed that the extent lies within the
    01032     partition.
    01033
    01034 Arguments:
    01035
    01036     Vcb - Vcb of logical volume
    01037
    01038     Reference - Partition reference to use in the mapping
    01039
    01040     Lbn - Logical block number
    01041
    01042     Len - Length of extent in bytes
    01043
    01044 Return Value:
    01045
    01046     ULONG physical sector number
    01047
    01048 --*/
    01049
    01050 {
    01051     PPCB Pcb = Vcb->Pcb;
    01052     ULONG Psn;
    01053
    01054     PBCB Bcb;
    01055     LARGE_INTEGER Offset;
    01056     PULONG MappedLbn;
    01057
    01058     PAGED_CODE();
    01059
    01060     //
    01061     //  Check inputs
    01062     //
    01063
    01064     ASSERT_IRP_CONTEXT( IrpContext );
    01065     ASSERT_VCB( Vcb );
    01066     ASSERT_PCB( Pcb );
    01067
    01068     DebugTrace(( +1, Dbg, "UdfLookupPsnOfExtent, [%04x/%08x, +%08x)\n", Reference, Lbn, Len ));
    01069
    01070     if (Reference < Pcb->Partitions) {
    01071
    01072         while (TRUE) {
    01073
    01074             switch (Pcb->Partition[Reference].Type) {
    01075
    01076                 case Physical:
    01077
    01078                     //
    01079                     //  Check that the input extent lies inside the partition.  Calculate the
    01080                     //  Lbn of the last block and see that it is interior.
    01081                     //
    01082
    01083                     if (SectorsFromBlocks( Vcb, Lbn ) + SectorsFromBytes( Vcb, Len ) >
    01084                         Pcb->Partition[Reference].Physical.Length) {
    01085
    01086                         goto NoGood;
    01087                     }
    01088
    01089                     Psn = Pcb->Partition[Reference].Physical.Start + SectorsFromBlocks( Vcb, Lbn );
    01090
    01091                     DebugTrace(( -1, Dbg, "UdfLookupPsnOfExtent -> %08x\n", Psn ));
    01092                     return Psn;
    01093
    01094                 case Virtual:
    01095
    01096                     //
    01097                     //  Bounds check.  Per UDF 2.00 2.3.10 and implied in UDF 1.50, virtual
    01098                     //  extent lengths cannot be greater than one block in size.
    01099                     //
    01100
    01101                     if (Lbn + BlocksFromBytes( Vcb, Len ) > Pcb->Partition[Reference].Virtual.Length ||
    01102                         Len > BlockSize( Vcb )) {
    01103
    01104                         goto NoGood;
    01105                     }
    01106
    01107                     try {
    01108
    01109                         //
    01110                         //  Calculate the location of the mapping element in the VAT
    01111                         //  and retrieve.
    01112                         //
    01113
    01114                         Offset.QuadPart = Lbn * sizeof(ULONG);
    01115
    01116                         CcMapData( Vcb->VatFcb->FileObject,
    01117                                    &Offset,
    01118                                    sizeof(ULONG),
    01119                                    TRUE,
    01120                                    &Bcb,
    01121                                    &MappedLbn );
    01122
    01123                         //
    01124                         //  Now rewrite the inputs in terms of the virtual mapping.  We
    01125                         //  will reloop to perform the logical -> physical mapping.
    01126                         //
    01127
    01128                         DebugTrace(( 0, Dbg,
    01129                                      "UdfLookupPsnOfExtent, Mapping V %04x/%08x -> L %04x/%08x\n",
    01130                                      Reference,
    01131                                      Lbn,
    01132                                      Pcb->Partition[Reference].Virtual.RelatedReference,
    01133                                      *MappedLbn ));
    01134
    01135                         Lbn = *MappedLbn;
    01136                         Reference = Pcb->Partition[Reference].Virtual.RelatedReference;
    01137
    01138                     } finally {
    01139
    01140                         DebugUnwind( UdfLookupPsnOfExtent );
    01141
    01142                         UdfUnpinData( IrpContext, &Bcb );
    01143                     }
    01144
    01145                     //
    01146                     //  An Lbn of ~0 in the VAT is defined to indicate that the sector is unused,
    01147                     //  so we should never see such a thing.
    01148                     //
    01149
    01150                     if (Lbn == ~0) {
    01151
    01152                         goto NoGood;
    01153                     }
    01154
    01155                     break;
    01156
    01157                 default:
    01158
    01159                     ASSERT(FALSE);
    01160                     break;
    01161             }
    01162         }
    01163     }
    01164
    01165     NoGood:
    01166
    01167     //
    01168     //  Some people have misinterpreted a partition number to equal a
    01169     //  partition reference, or perhaps this is just corrupt media.
    01170     //
    01171
    01172     UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    01173 }

VOID UdfMapMetadataView | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PMAPPED_PVIEW | View,
|  | IN PVCB | Vcb,
|  | IN USHORT | Partition,
|  | IN ULONG | Lbn,
|  | IN ULONG | Length
| ) |

Definition at line 337 of file udfs/cachesup.c.

References ASSERT_IRP_CONTEXT, CcMapData(), FALSE, LlBytesFromSectors, Offset, PMAPPED_PVIEW, TRUE, UdfLookupMetaVsnOfExtent(), and UdfUnpinView.

Referenced by UdfGetNextAllocationPostProcessing(), UdfInitializeIcbContext(), UdfInitializeIcbContextFromFcb(), and UdfLookupActiveIcbInExtent().

    00348                    :
    00349
    00350     Perform the common work of mapping an extent of metadata into a mapped view.
    00351
    00352 Arguments:
    00353
    00354     View - View structure to map the bytes into
    00355
    00356     Vcb - Vcb of the volume the extent is on
    00357
    00358     Partition - Partition of the extent
    00359
    00360     Lbn - Lbn of the extent
    00361
    00362     Length - Length of the extent
    00363
    00364 Return Value:
    00365
    00366     None.
    00367
    00368 --*/
    00369
    00370 {
    00371     LARGE_INTEGER Offset;
    00372     ULONG Vsn;
    00373
    00374     ASSERT_IRP_CONTEXT( IrpContext );
    00375
    00376     //
    00377     //  Remove any existing mapping
    00378     //
    00379
    00380     UdfUnpinView( IrpContext, View );
    00381
    00382     //
    00383     //  Update the view information.
    00384     //
    00385
    00386     View->Partition = Partition;
    00387     View->Lbn = Lbn;
    00388     View->Length = Length;
    00389
    00390     //
    00391     //  Find the mapping of this extent in the Metadata stream.
    00392     //
    00393
    00394     Vsn = UdfLookupMetaVsnOfExtent( IrpContext,
    00395                                     Vcb,
    00396                                     Partition,
    00397                                     Lbn,
    00398                                     Length,
    00399                                     FALSE );
    00400
    00401     Offset.QuadPart = LlBytesFromSectors( Vcb, Vsn );
    00402
    00403     //
    00404     //  Map the extent
    00405     //
    00406
    00407     CcMapData( Vcb->MetadataFcb->FileObject,
    00408                &Offset,
    00409                Length,
    00410                TRUE,
    00411                &View->Bcb,
    00412                &View->View );
    00413 }

NTSTATUS UdfNonCachedRead | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount
| ) |

Definition at line 201 of file deviosup.c.

References Add2Ptr, ASSERT, ClearFlag, DebugUnwind, FALSE, FCB_STATE_EMBEDDED_DATA, FCB_STATE_VMCB_MAPPING, FlagOn, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_WAIT, KeFlushIoBuffers(), MAX_PARALLEL_IOS, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, TRUE, try_leave, UdfCreateUserMdl(), UdfFinishBuffers(), UdfMapUserBuffer, UdfMultipleAsync(), UdfPrepareBuffers(), UdfRaiseStatus(), UdfSingleAsync(), and UdfWaitSync().

Referenced by UdfCommonRead().

    00210                    :
    00211
    00212     This routine performs the non-cached reads of sectors.  This is done by
    00213     performing the following in a loop.
    00214
    00215         Fill in the IoRuns array for the next block of Io.
    00216         Send the Io to the device.
    00217         Perform any cleanup on the Io runs array.
    00218
    00219     We will not do async Io to any request that generates non-aligned Io.
    00220     Also we will not perform async Io if it will exceed the size of our
    00221     IoRuns array.  These should be the unusual cases but we will raise
    00222     or return CANT_WAIT in this routine if we detect this case.
    00223
    00224 Arguments:
    00225
    00226     Fcb - Fcb representing the file to read.
    00227
    00228     StartingOffset - Logical offset in the file to read from.
    00229
    00230     ByteCount - Number of bytes to read.
    00231
    00232 Return Value:
    00233
    00234     NTSTATUS - Status indicating the result of the operation.
    00235
    00236 --*/
    00237
    00238 {
    00239     NTSTATUS Status = STATUS_SUCCESS;
    00240
    00241     IO_RUN IoRuns[MAX_PARALLEL_IOS];
    00242     ULONG RunCount = 0;
    00243     ULONG CleanupRunCount = 0;
    00244
    00245     PVOID UserBuffer;
    00246     ULONG UserBufferOffset = 0;
    00247     LONGLONG CurrentOffset = StartingOffset;
    00248     ULONG RemainingByteCount = ByteCount;
    00249     ULONG ThisByteCount;
    00250
    00251     BOOLEAN Unaligned;
    00252     BOOLEAN SparseRuns;
    00253     BOOLEAN FlushIoBuffers = FALSE;
    00254     BOOLEAN FirstPass = TRUE;
    00255
    00256     PAGED_CODE();
    00257
    00258     //
    00259     //  We want to make sure the user's buffer is locked in all cases.
    00260     //
    00261
    00262     if (IrpContext->Irp->MdlAddress == NULL) {
    00263
    00264         UdfCreateUserMdl( IrpContext, ByteCount, TRUE );
    00265     }
    00266
    00267     //
    00268     //  Use a try-finally to perform the final cleanup.
    00269     //
    00270
    00271     try {
    00272
    00273         UdfMapUserBuffer( IrpContext, &UserBuffer);
    00274
    00275         //
    00276         //  Loop while there are more bytes to transfer.
    00277         //
    00278
    00279         do {
    00280
    00281             //
    00282             //  Call prepare buffers to set up the next entries
    00283             //  in the IoRuns array.  Remember if there are any
    00284             //  unaligned entries.
    00285             //
    00286
    00287             RtlZeroMemory( IoRuns, sizeof( IoRuns ));
    00288
    00289             Unaligned = UdfPrepareBuffers( IrpContext,
    00290                                            IrpContext->Irp,
    00291                                            Fcb,
    00292                                            UserBuffer,
    00293                                            UserBufferOffset,
    00294                                            CurrentOffset,
    00295                                            RemainingByteCount,
    00296                                            IoRuns,
    00297                                            &CleanupRunCount,
    00298                                            &ThisByteCount,
    00299                                            &SparseRuns );
    00300
    00301
    00302             RunCount = CleanupRunCount;
    00303
    00304             //
    00305             //  Quickly finish if we wound up having no IO to perform.  This will
    00306             //  occur in the presence of unrecorded sectors.
    00307             //
    00308
    00309             ASSERT( !(SparseRuns && FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING|FCB_STATE_EMBEDDED_DATA )));
    00310
    00311             if (RunCount == 0) {
    00312
    00313                 try_leave( Status = IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS );
    00314             }
    00315
    00316             //
    00317             //  If this is an async request and there aren't enough entries
    00318             //  in the Io array then post the request.  This routine will
    00319             //  always raise if we are doing any unaligned Io for an
    00320             //  async request.
    00321             //
    00322
    00323             if ((ThisByteCount < RemainingByteCount) &&
    00324                 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00325
    00326                 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00327             }
    00328
    00329             //
    00330             //  If the entire Io is contained in a single run then
    00331             //  we can pass the Io down to the driver.  Send the driver down
    00332             //  and wait on the result if this is synchronous.  We cannot
    00333             //  do this simple form (just chucking the IRP down) if some
    00334             //  sparse runs were encountered.
    00335             //
    00336
    00337             if ((RunCount == 1) && !Unaligned && !SparseRuns && FirstPass) {
    00338
    00339                 UdfSingleAsync( IrpContext,
    00340                                 IoRuns[0].DiskOffset,
    00341                                 IoRuns[0].DiskByteCount );
    00342
    00343                 //
    00344                 //  No cleanup needed for the IoRuns array here.
    00345                 //
    00346
    00347                 CleanupRunCount = 0;
    00348
    00349                 //
    00350                 //  Wait if we are synchronous, otherwise return
    00351                 //
    00352
    00353                 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00354
    00355                     UdfWaitSync( IrpContext );
    00356
    00357                     Status = IrpContext->Irp->IoStatus.Status;
    00358
    00359                 //
    00360                 //  Our completion routine will free the Io context but
    00361                 //  we do want to return STATUS_PENDING.
    00362                 //
    00363
    00364                 } else {
    00365
    00366                     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00367                     Status = STATUS_PENDING;
    00368                 }
    00369
    00370                 try_leave( NOTHING );
    00371             }
    00372
    00373             //
    00374             //  Otherwise we will perform multiple Io to read in the data.
    00375             //
    00376
    00377             UdfMultipleAsync( IrpContext, RunCount, IoRuns );
    00378
    00379             //
    00380             //  No cleanup needed on the IoRuns now.
    00381             //
    00382
    00383             CleanupRunCount = 0;
    00384
    00385             //
    00386             //  If this is a synchronous request then perform any necessary
    00387             //  post-processing.
    00388             //
    00389
    00390             if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00391
    00392                 //
    00393                 //  Wait for the request to complete.
    00394                 //
    00395
    00396                 UdfWaitSync( IrpContext );
    00397
    00398                 Status = IrpContext->Irp->IoStatus.Status;
    00399
    00400                 //
    00401                 //  Exit this loop if there is an error.
    00402                 //
    00403
    00404                 if (!NT_SUCCESS( Status )) {
    00405
    00406                     try_leave( NOTHING );
    00407                 }
    00408
    00409                 //
    00410                 //  Perform post read operations on the IoRuns if
    00411                 //  necessary.
    00412                 //
    00413
    00414                 if (Unaligned &&
    00415                     UdfFinishBuffers( IrpContext, IoRuns, RunCount, FALSE )) {
    00416
    00417                     FlushIoBuffers = TRUE;
    00418                 }
    00419
    00420                 //
    00421                 //  Exit this loop if there are no more bytes to transfer
    00422                 //  or we have any error.
    00423                 //
    00424
    00425                 RemainingByteCount -= ThisByteCount;
    00426                 CurrentOffset += ThisByteCount;
    00427                 UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
    00428                 UserBufferOffset += ThisByteCount;
    00429
    00430             //
    00431             //  Otherwise this is an asynchronous request.  Always return
    00432             //  STATUS_PENDING.
    00433             //
    00434
    00435             } else {
    00436
    00437                 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00438                 CleanupRunCount = 0;
    00439                 try_leave( Status = STATUS_PENDING );
    00440                 break;
    00441             }
    00442
    00443             FirstPass = FALSE;
    00444         } while (RemainingByteCount != 0);
    00445
    00446         //
    00447         //  Flush the hardware cache if we performed any copy operations.
    00448         //
    00449
    00450         if (FlushIoBuffers) {
    00451
    00452             KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
    00453         }
    00454
    00455     } finally {
    00456
    00457         DebugUnwind( "UdfNonCachedRead" );
    00458
    00459         //
    00460         //  Perform final cleanup on the IoRuns if necessary.
    00461         //
    00462
    00463         if (CleanupRunCount != 0) {
    00464
    00465             UdfFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE );
    00466         }
    00467     }
    00468
    00469     return Status;
    00470 }

BOOLEAN UdfNoopAcquire | ( | IN PVOID | Fcb,
|  | IN BOOLEAN | Wait
| ) |

Definition at line 208 of file resrcsup.c.

References PAGED_CODE, and TRUE.

Referenced by UdfInitializeGlobalData().

    00215                    :
    00216
    00217     This routine does nothing.
    00218
    00219 Arguments:
    00220
    00221     Fcb - The Fcb/Vcb which was specified as a context parameter for this
    00222           routine.
    00223
    00224     Wait - TRUE if the caller is willing to block.
    00225
    00226 Return Value:
    00227
    00228     TRUE
    00229
    00230 --*/
    00231
    00232 {
    00233     PAGED_CODE();
    00234     return TRUE;
    00235 }

VOID UdfNoopRelease | ( | IN PVOID | Fcb | ) |

Definition at line 239 of file resrcsup.c.

References PAGED_CODE.

Referenced by UdfInitializeGlobalData().

    00245                    :
    00246
    00247     This routine does nothing.
    00248
    00249 Arguments:
    00250
    00251     Fcb - The Fcb/Vcb which was specified as a context parameter for this
    00252           routine.
    00253
    00254 Return Value:
    00255
    00256     None
    00257
    00258 --*/
    00259
    00260 {
    00261     PAGED_CODE();
    00262     return;
    00263 }

INLINE VOID UdfNormalizeAndRaiseStatus | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN NTSTATUS | Status
| ) |

Definition at line 418 of file udfprocs.h.

References ExRaiseStatus(), FsRtlNormalizeNtstatus(), and Status.

Referenced by UdfCommonRead(), UdfPerformVerify(), UdfReadSectors(), and UdfVerifyVcb().

    00422 {
    00423     IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR );
    00424     ExRaiseStatus( IrpContext->ExceptionStatus );
    00425 }

VOID UdfOplockComplete | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 222 of file workque.c.

References FALSE, _IRP::IoStatus, Irp, IRP_MJ_CREATE, NULL, PAGED_CODE, UdfAddToWorkque(), UdfCompleteRequest(), UdfReleaseFcb, and UdfTeardownStructures().

Referenced by UdfCommonLockControl(), UdfCommonRead(), and UdfCompleteFcbOpen().

    00229                    :
    00230
    00231     This routine is called by the oplock package when an oplock break has
    00232     completed, allowing an Irp to resume execution.  If the status in
    00233     the Irp is STATUS_SUCCESS, then we queue the Irp to the Fsp queue.
    00234     Otherwise we complete the Irp with the status in the Irp.
    00235
    00236     If we are completing due to an error then check if there is any
    00237     cleanup to do.
    00238
    00239 Arguments:
    00240
    00241     Irp - I/O Request Packet.
    00242
    00243 Return Value:
    00244
    00245     None.
    00246
    00247 --*/
    00248
    00249 {
    00250     BOOLEAN RemovedFcb;
    00251
    00252     PAGED_CODE();
    00253
    00254     //
    00255     //  Check on the return value in the Irp.  If success then we
    00256     //  are to post this request.
    00257     //
    00258
    00259     if (Irp->IoStatus.Status == STATUS_SUCCESS) {
    00260
    00261         //
    00262         //  Check if there is any cleanup work to do.
    00263         //
    00264
    00265         switch (IrpContext->MajorFunction) {
    00266
    00267         case IRP_MJ_CREATE :
    00268
    00269             //
    00270             //  If called from the oplock package then there is an
    00271             //  Fcb to possibly teardown.  We will call the teardown
    00272             //  routine and release the Fcb if still present.  The cleanup
    00273             //  code in create will know not to release this Fcb because
    00274             //  we will clear the pointer.
    00275             //
    00276
    00277             if (IrpContext->TeardownFcb != NULL) {
    00278
    00279                 UdfTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), FALSE, &RemovedFcb );
    00280
    00281                 if (!RemovedFcb) {
    00282
    00283                     UdfReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
    00284                 }
    00285
    00286                 *(IrpContext->TeardownFcb) = NULL;
    00287                 IrpContext->TeardownFcb = NULL;
    00288             }
    00289
    00290             break;
    00291         }
    00292         //
    00293         //  Insert the Irp context in the workqueue.
    00294         //
    00295
    00296         UdfAddToWorkque( IrpContext, Irp );
    00297
    00298     //
    00299     //  Otherwise complete the request.
    00300     //
    00301
    00302     } else {
    00303
    00304         UdfCompleteRequest( IrpContext, Irp, Irp->IoStatus.Status );
    00305     }
    00306
    00307     return;
    00308 }

NTSTATUS UdfPerformDevIoCtrl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN ULONG | IoControlCode,
|  | IN PDEVICE_OBJECT | Device,
|  | OUT PVOID OutputBuffer | OPTIONAL,
|  | IN ULONG | OutputBufferLength,
|  | IN BOOLEAN | InternalDeviceIoControl,
|  | IN BOOLEAN | OverrideVerify,
|  | OUT PIO_STATUS_BLOCK Iosb | OPTIONAL
| ) |

Definition at line 573 of file deviosup.c.

References Event(), Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NTSTATUS(), NULL, PAGED_CODE, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, and VOID().

Referenced by UdfDetermineVolumeBounding(), UdfMountVolume(), UdfVerifyVcb(), and UdfVerifyVolume().

    00586                    :
    00587
    00588     This routine is called to perform DevIoCtrl functions internally within
    00589     the filesystem.  We take the status from the driver and return it to our
    00590     caller.
    00591
    00592 Arguments:
    00593
    00594     IoControlCode - Code to send to driver.
    00595
    00596     Device - This is the device to send the request to.
    00597
    00598     OutPutBuffer - Pointer to output buffer.
    00599
    00600     OutputBufferLength - Length of output buffer above.
    00601
    00602     InternalDeviceIoControl - Indicates if this is an internal or external
    00603         Io control code.
    00604
    00605     OverrideVerify - Indicates if we should tell the driver not to return
    00606         STATUS_VERIFY_REQUIRED for mount and verify.
    00607
    00608     Iosb - If specified, we return the results of the operation here.
    00609
    00610 Return Value:
    00611
    00612     NTSTATUS - Status returned by next lower driver.
    00613
    00614 --*/
    00615
    00616 {
    00617     NTSTATUS Status;
    00618     PIRP Irp;
    00619     KEVENT Event;
    00620     IO_STATUS_BLOCK LocalIosb;
    00621     PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
    00622
    00623     PAGED_CODE();
    00624
    00625     //
    00626     //  Check if the user gave us an Iosb.
    00627     //
    00628
    00629     if (ARGUMENT_PRESENT( Iosb )) {
    00630
    00631         IosbToUse = Iosb;
    00632     }
    00633
    00634     IosbToUse->Status = 0;
    00635     IosbToUse->Information = 0;
    00636
    00637     KeInitializeEvent( &Event, NotificationEvent, FALSE );
    00638
    00639     Irp = IoBuildDeviceIoControlRequest( IoControlCode,
    00640                                          Device,
    00641                                          NULL,
    00642                                          0,
    00643                                          OutputBuffer,
    00644                                          OutputBufferLength,
    00645                                          InternalDeviceIoControl,
    00646                                          &Event,
    00647                                          IosbToUse );
    00648
    00649     if (Irp == NULL) {
    00650
    00651         return STATUS_INSUFFICIENT_RESOURCES;
    00652     }
    00653
    00654     if (OverrideVerify) {
    00655
    00656         SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
    00657     }
    00658
    00659     Status = IoCallDriver( Device, Irp );
    00660
    00661     //
    00662     //  We check for device not ready by first checking Status
    00663     //  and then if status pending was returned, the Iosb status
    00664     //  value.
    00665     //
    00666
    00667     if (Status == STATUS_PENDING) {
    00668
    00669         (VOID) KeWaitForSingleObject( &Event,
    00670                                       Executive,
    00671                                       KernelMode,
    00672                                       FALSE,
    00673                                       (PLARGE_INTEGER)NULL );
    00674
    00675         Status = IosbToUse->Status;
    00676     }
    00677
    00678     return Status;
    00679
    00680     UNREFERENCED_PARAMETER( IrpContext );
    00681 }

NTSTATUS UdfPerformVerify | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp,
|  | IN PDEVICE_OBJECT | DeviceToVerify
| ) |

Definition at line 42 of file udfs/verfysup.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, _IO_STACK_LOCATION::DeviceObject, DO_VERIFY_VOLUME, FALSE, _FILE_OBJECT::FileName, _IO_STACK_LOCATION::FileObject, FlagOn, IO_REMOUNT, IoGetCurrentIrpStackLocation, IoIsErrorUserInduced, IoSetHardErrorOrVerifyDevice(), _IRP::IoStatus, IoVerifyVolume(), Irp, IRP_MJ_CREATE, IRP_MJ_FILE_SYSTEM_CONTROL, IRP_MN_MOUNT_VOLUME, IRP_MN_VERIFY_VOLUME, NT_SUCCESS, NTSTATUS(), NULL, _FILE_OBJECT::RelatedFileObject, Status, TRUE, UdfAcquireUdfData, UdfCheckForDismount(), UdfCompleteRequest(), UdfExceptionFilter(), UdfFsdPostRequest(), UdfNormalizeAndRaiseStatus(), UdfProcessException(), UdfReleaseUdfData, _VCB::VcbCondition, VcbDismountInProgress, VcbInvalid, VcbMounted, VcbNotMounted, _VCB::VcbReference, and _VCB::VcbResidualReference.

Referenced by UdfProcessException().

    00050                    :
    00051
    00052     This routines performs an IoVerifyVolume operation and takes the
    00053     appropriate action.  If the verify is successful then we send the originating
    00054     Irp off to an Ex Worker Thread.  This routine is called from the exception handler.
    00055
    00056     No file system resources are held when this routine is called.
    00057
    00058 Arguments:
    00059
    00060     Irp - The irp to send off after all is well and done.
    00061
    00062     Device - The real device needing verification.
    00063
    00064 Return Value:
    00065
    00066     None.
    00067
    00068 --*/
    00069
    00070 {
    00071     PVCB Vcb;
    00072     NTSTATUS Status = STATUS_SUCCESS;
    00073     PIO_STACK_LOCATION IrpSp;
    00074
    00075     ASSERT_IRP_CONTEXT( IrpContext );
    00076     ASSERT_IRP( Irp );
    00077
    00078     //
    00079     //  Check if this Irp has a status of Verify required and if it does
    00080     //  then call the I/O system to do a verify.
    00081     //
    00082     //  Skip the IoVerifyVolume if this is a mount or verify request
    00083     //  itself.  Trying a recursive mount will cause a deadlock with
    00084     //  the DeviceObject->DeviceLock.
    00085     //
    00086
    00087     if ((IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
    00088         ((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) ||
    00089          (IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME))) {
    00090
    00091         return UdfFsdPostRequest( IrpContext, Irp );
    00092     }
    00093
    00094     //
    00095     //  Extract a pointer to the Vcb from the VolumeDeviceObject.
    00096     //  Note that since we have specifically excluded mount,
    00097     //  requests, we know that IrpSp->DeviceObject is indeed a
    00098     //  volume device object.
    00099     //
    00100
    00101     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00102
    00103     Vcb = &CONTAINING_RECORD( IrpSp->DeviceObject,
    00104                               VOLUME_DEVICE_OBJECT,
    00105                               DeviceObject )->Vcb;
    00106
    00107     //
    00108     //  Check if the volume still thinks it needs to be verified,
    00109     //  if it doesn't then we can skip doing a verify because someone
    00110     //  else beat us to it.
    00111     //
    00112
    00113     try {
    00114
    00115         if (FlagOn( DeviceToVerify->Flags, DO_VERIFY_VOLUME )) {
    00116
    00117             BOOLEAN AllowRawMount = FALSE;
    00118
    00119             //
    00120             //  We will allow Raw to mount this volume if we were doing a
    00121             //  an absolute DASD open.
    00122             //
    00123
    00124             if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
    00125                 (IrpSp->FileObject->FileName.Length == 0) &&
    00126                 (IrpSp->FileObject->RelatedFileObject == NULL)) {
    00127
    00128                 AllowRawMount = TRUE;
    00129             }
    00130
    00131             //
    00132             //  If the IopMount in IoVerifyVolume did something, and
    00133             //  this is an absolute open, force a reparse.
    00134             //
    00135
    00136             Status = IoVerifyVolume( DeviceToVerify, AllowRawMount );
    00137
    00138             //
    00139             //  If the verify operation completed it will return
    00140             //  either STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly.
    00141             //
    00142             //  If UdfVerifyVolume encountered an error during
    00143             //  processing, it will return that error.  If we got
    00144             //  STATUS_WRONG_VOLUME from the verify, and our volume
    00145             //  is now mounted, commute the status to STATUS_SUCCESS.
    00146             //
    00147
    00148             if ((Status == STATUS_WRONG_VOLUME) &&
    00149                 (Vcb->VcbCondition == VcbMounted)) {
    00150
    00151                 Status = STATUS_SUCCESS;
    00152             }
    00153
    00154             //
    00155             //  Do a quick unprotected check here.  The routine will do
    00156             //  a safe check.  After here we can release the resource.
    00157             //  Note that if the volume really went away, we will be taking
    00158             //  the Reparse path.
    00159             //
    00160
    00161             //
    00162             //  If the device might need to go away then call our dismount routine.
    00163             //
    00164
    00165             if (((Vcb->VcbCondition == VcbNotMounted) ||
    00166                  (Vcb->VcbCondition == VcbInvalid) ||
    00167                  (Vcb->VcbCondition == VcbDismountInProgress)) &&
    00168                 (Vcb->VcbReference <= Vcb->VcbResidualReference)) {
    00169
    00170                 UdfAcquireUdfData( IrpContext );
    00171                 UdfCheckForDismount( IrpContext, Vcb, FALSE );
    00172                 UdfReleaseUdfData( IrpContext );
    00173             }
    00174
    00175             //
    00176             //  If this is a create and the verify succeeded then complete the
    00177             //  request with a REPARSE status.
    00178             //
    00179
    00180             if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
    00181                 (IrpSp->FileObject->RelatedFileObject == NULL) &&
    00182                 ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
    00183
    00184                 Irp->IoStatus.Information = IO_REMOUNT;
    00185
    00186                 UdfCompleteRequest( IrpContext, Irp, STATUS_REPARSE );
    00187                 Status = STATUS_REPARSE;
    00188                 Irp = NULL;
    00189                 IrpContext = NULL;
    00190
    00191             //
    00192             //  If there is still an error to process then call the Io system
    00193             //  for a popup.
    00194             //
    00195
    00196             } else if ((Irp != NULL) && !NT_SUCCESS( Status )) {
    00197
    00198                 //
    00199                 //  Fill in the device object if required.
    00200                 //
    00201
    00202                 if (IoIsErrorUserInduced( Status ) ) {
    00203
    00204                     IoSetHardErrorOrVerifyDevice( Irp, DeviceToVerify );
    00205                 }
    00206
    00207                 UdfNormalizeAndRaiseStatus( IrpContext, Status );
    00208             }
    00209         }
    00210
    00211         //
    00212         //  If there is still an Irp, send it off to an Ex Worker thread.
    00213         //
    00214
    00215         if (IrpContext != NULL) {
    00216
    00217             Status = UdfFsdPostRequest( IrpContext, Irp );
    00218         }
    00219
    00220     } except(UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
    00221
    00222         //
    00223         //  We had some trouble trying to perform the verify or raised
    00224         //  an error ourselves.  So we'll abort the I/O request with
    00225         //  the error status that we get back from the execption code.
    00226         //
    00227
    00228         Status = UdfProcessException( IrpContext, Irp, GetExceptionCode() );
    00229     }
    00230
    00231     return Status;
    00232 }

VOID UdfPrePostIrp | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 111 of file workque.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, FALSE, FlagOn, IoGetCurrentIrpStackLocation, IoMarkIrpPending, Irp, IRP_CONTEXT_FLAG_MORE_PROCESSING, IRP_MJ_CREATE, IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_READ, IRP_MN_MDL, IRP_MN_QUERY_DIRECTORY, NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, SetFlag, TRUE, UdfCleanupIrpContext(), UdfLockUserBuffer, UdfReleaseFcb, and UdfTeardownStructures().

Referenced by UdfCommonRead(), UdfCompleteFcbOpen(), and UdfFsdPostRequest().

    00118                    :
    00119
    00120     This routine performs any neccessary work before STATUS_PENDING is
    00121     returned with the Fsd thread.  This routine is called within the
    00122     filesystem and by the oplock package.
    00123
    00124 Arguments:
    00125
    00126     Context - Pointer to the IrpContext to be queued to the Fsp
    00127
    00128     Irp - I/O Request Packet.
    00129
    00130 Return Value:
    00131
    00132     None.
    00133
    00134 --*/
    00135
    00136 {
    00137     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00138     BOOLEAN RemovedFcb;
    00139
    00140     PAGED_CODE();
    00141
    00142     ASSERT_IRP_CONTEXT( IrpContext );
    00143     ASSERT_IRP( Irp );
    00144
    00145     //
    00146     //  Case on the type of the operation.
    00147     //
    00148
    00149     switch (IrpContext->MajorFunction) {
    00150
    00151     case IRP_MJ_CREATE :
    00152
    00153         //
    00154         //  If called from the oplock package then there is an
    00155         //  Fcb to possibly teardown.  We will call the teardown
    00156         //  routine and release the Fcb if still present.  The cleanup
    00157         //  code in create will know not to release this Fcb because
    00158         //  we will clear the pointer.
    00159         //
    00160
    00161         if ((IrpContext->TeardownFcb != NULL) &&
    00162             *(IrpContext->TeardownFcb) != NULL) {
    00163
    00164             UdfTeardownStructures( IrpContext, *(IrpContext->TeardownFcb), FALSE, &RemovedFcb );
    00165
    00166             if (!RemovedFcb) {
    00167
    00168                 UdfReleaseFcb( IrpContext, *(IrpContext->TeardownFcb) );
    00169             }
    00170
    00171             *(IrpContext->TeardownFcb) = NULL;
    00172             IrpContext->TeardownFcb = NULL;
    00173         }
    00174
    00175         break;
    00176
    00177     //
    00178     //  We need to lock the user's buffer, unless this is an MDL-read,
    00179     //  in which case there is no user buffer.
    00180     //
    00181
    00182     case IRP_MJ_READ :
    00183
    00184         if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
    00185
    00186             UdfLockUserBuffer( IrpContext, IrpSp->Parameters.Read.Length );
    00187         }
    00188
    00189         break;
    00190
    00191     //
    00192     //  We also need to check whether this is a query file operation.
    00193     //
    00194
    00195     case IRP_MJ_DIRECTORY_CONTROL :
    00196
    00197         if (IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
    00198
    00199             UdfLockUserBuffer( IrpContext, IrpSp->Parameters.QueryDirectory.Length );
    00200         }
    00201
    00202         break;
    00203     }
    00204     //
    00205     //  Cleanup the IrpContext for the post.
    00206     //
    00207
    00208     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
    00209     UdfCleanupIrpContext( IrpContext, TRUE );
    00210
    00211     //
    00212     //  Mark the Irp to show that we've already returned pending to the user.
    00213     //
    00214
    00215     IoMarkIrpPending( Irp );
    00216
    00217     return;
    00218 }

NTSTATUS UdfProcessException | ( | IN PIRP_CONTEXT IrpContext | OPTIONAL,
|  | IN PIRP | Irp,
|  | IN NTSTATUS | ExceptionCode
| ) |

Definition at line 539 of file udfdata.c.

References APC_LEVEL, ASSERT, ASSERT_IRP, ASSERT_OPTIONAL_IRP_CONTEXT, ClearFlag, FlagOn, IoGetCurrentIrpStackLocation, IoGetDeviceToVerify(), IoIsErrorUserInduced, IoMarkIrpPending, IoRaiseHardError(), IoSetDeviceToVerify(), _IRP::IoStatus, Irp, IRP_CONTEXT_FLAG_DISABLE_POPUPS, IRP_CONTEXT_FLAG_FORCE_POST, IRP_CONTEXT_FLAG_MORE_PROCESSING, IRP_CONTEXT_FLAG_TOP_LEVEL, NULL, PsGetCurrentThread, _IRP::Tail, UdfCompleteRequest(), UdfExceptionFilter(), UdfFsdPostRequest(), and UdfPerformVerify().

Referenced by UdfFsdDispatch(), UdfFspDispatch(), and UdfPerformVerify().

    00547                    :
    00548
    00549     This routine processes an exception.  It either completes the request
    00550     with the exception status in the IrpContext, sends this off to the Fsp
    00551     workque or causes it to be retried in the current thread if a verification
    00552     is needed.
    00553
    00554     If the volume needs to be verified (STATUS_VERIFY_REQUIRED) and we can
    00555     do the work in the current thread we will translate the status code
    00556     to STATUS_CANT_WAIT to indicate that we need to retry the request.
    00557
    00558 Arguments:
    00559
    00560     Irp - Supplies the Irp being processed
    00561
    00562     ExceptionCode - Supplies the normalized exception status being handled
    00563
    00564 Return Value:
    00565
    00566     NTSTATUS - Returns the results of either posting the Irp or the
    00567         saved completion status.
    00568
    00569 --*/
    00570
    00571 {
    00572     PDEVICE_OBJECT Device;
    00573     PVPB Vpb;
    00574     PETHREAD Thread;
    00575
    00576     ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
    00577     ASSERT_IRP( Irp );
    00578
    00579     //
    00580     //  If there is not an irp context, then complete the request with the
    00581     //  current status code.
    00582     //
    00583
    00584     if (!ARGUMENT_PRESENT( IrpContext )) {
    00585
    00586         UdfCompleteRequest( NULL, Irp, ExceptionCode );
    00587         return ExceptionCode;
    00588     }
    00589
    00590     //
    00591     //  Get the real exception status from the IrpContext.
    00592     //
    00593
    00594     ExceptionCode = IrpContext->ExceptionStatus;
    00595
    00596     //
    00597     //  If we are not a top level request then we just complete the request
    00598     //  with the current status code.
    00599     //
    00600
    00601     if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL )) {
    00602
    00603         UdfCompleteRequest( IrpContext, Irp, ExceptionCode );
    00604
    00605         return ExceptionCode;
    00606     }
    00607
    00608     //
    00609     //  Check if we are posting this request.  One of the following must be true
    00610     //  if we are to post a request.
    00611     //
    00612     //      - Status code is STATUS_CANT_WAIT and the request is asynchronous
    00613     //          or we are forcing this to be posted.
    00614     //
    00615     //      - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
    00616     //          or higher.  Can't wait for IO in the verify path in this case.
    00617     //
    00618     //  Set the MORE_PROCESSING flag in the IrpContext to keep if from being
    00619     //  deleted if this is a retryable condition.
    00620     //
    00621     //  Note:  Children of UdfFsdPostRequest() can raise.
    00622     //
    00623
    00624     try {
    00625
    00626         if (ExceptionCode == STATUS_CANT_WAIT) {
    00627
    00628             if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST )) {
    00629
    00630                 ExceptionCode = UdfFsdPostRequest( IrpContext, Irp );
    00631             }
    00632
    00633         } else if (ExceptionCode == STATUS_VERIFY_REQUIRED) {
    00634
    00635             if (KeGetCurrentIrql() >= APC_LEVEL) {
    00636
    00637                 ExceptionCode = UdfFsdPostRequest( IrpContext, Irp );
    00638             }
    00639         }
    00640     }
    00641     except (UdfExceptionFilter( IrpContext, GetExceptionInformation()))  {
    00642
    00643         ExceptionCode = GetExceptionCode();
    00644     }
    00645
    00646     //
    00647     //  If we posted the request or our caller will retry then just return here.
    00648     //
    00649
    00650     if ((ExceptionCode == STATUS_PENDING) ||
    00651         (ExceptionCode == STATUS_CANT_WAIT)) {
    00652
    00653         return ExceptionCode;
    00654     }
    00655
    00656     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
    00657
    00658     //
    00659     //  Store this error into the Irp for posting back to the Io system.
    00660     //
    00661
    00662     Irp->IoStatus.Status = ExceptionCode;
    00663
    00664     if (IoIsErrorUserInduced( ExceptionCode )) {
    00665
    00666         //
    00667         //  Check for the various error conditions that can be caused by,
    00668         //  and possibly resolved my the user.
    00669         //
    00670
    00671         if (ExceptionCode == STATUS_VERIFY_REQUIRED) {
    00672
    00673             //
    00674             //  Now we are at the top level file system entry point.
    00675             //
    00676             //  If we have already posted this request then the device to
    00677             //  verify is in the original thread.  Find this via the Irp.
    00678             //
    00679
    00680             Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
    00681             IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );
    00682
    00683             //
    00684             //  If there is no device in that location then check in the
    00685             //  current thread.
    00686             //
    00687
    00688             if (Device == NULL) {
    00689
    00690                 Device = IoGetDeviceToVerify( PsGetCurrentThread() );
    00691                 IoSetDeviceToVerify( PsGetCurrentThread(), NULL );
    00692
    00693                 ASSERT( Device != NULL );
    00694
    00695                 //
    00696                 //  Let's not BugCheck just because the driver screwed up.
    00697                 //
    00698
    00699                 if (Device == NULL) {
    00700
    00701                     ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR;
    00702
    00703                     UdfCompleteRequest( IrpContext, Irp, ExceptionCode );
    00704
    00705                     return ExceptionCode;
    00706                 }
    00707             }
    00708
    00709             //
    00710             //  CdPerformVerify() will do the right thing with the Irp.
    00711             //  If we return STATUS_CANT_WAIT then the current thread
    00712             //  can retry the request.
    00713             //
    00714
    00715             return UdfPerformVerify( IrpContext, Irp, Device );
    00716         }
    00717
    00718         //
    00719         //  The other user induced conditions generate an error unless
    00720         //  they have been disabled for this request.
    00721         //
    00722
    00723         if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS )) {
    00724
    00725             UdfCompleteRequest( IrpContext, Irp, ExceptionCode );
    00726
    00727             return ExceptionCode;
    00728
    00729         } else {
    00730
    00731             //
    00732             //  Generate a pop-up
    00733             //
    00734
    00735             if (IoGetCurrentIrpStackLocation( Irp )->FileObject != NULL) {
    00736
    00737                 Vpb = IoGetCurrentIrpStackLocation( Irp )->FileObject->Vpb;
    00738
    00739             } else {
    00740
    00741                 Vpb = NULL;
    00742             }
    00743
    00744             //
    00745             //  The device to verify is either in my thread local storage
    00746             //  or that of the thread that owns the Irp.
    00747             //
    00748
    00749             Thread = Irp->Tail.Overlay.Thread;
    00750             Device = IoGetDeviceToVerify( Thread );
    00751
    00752             if (Device == NULL) {
    00753
    00754                 Thread = PsGetCurrentThread();
    00755                 Device = IoGetDeviceToVerify( Thread );
    00756
    00757                 ASSERT( Device != NULL );
    00758
    00759                 //
    00760                 //  Let's not BugCheck just because the driver screwed up.
    00761                 //
    00762
    00763                 if (Device == NULL) {
    00764
    00765                     UdfCompleteRequest( IrpContext, Irp, ExceptionCode );
    00766
    00767                     return ExceptionCode;
    00768                 }
    00769             }
    00770
    00771             //
    00772             //  This routine actually causes the pop-up.  It usually
    00773             //  does this by queuing an APC to the callers thread,
    00774             //  but in some cases it will complete the request immediately,
    00775             //  so it is very important to IoMarkIrpPending() first.
    00776             //
    00777
    00778             IoMarkIrpPending( Irp );
    00779             IoRaiseHardError( Irp, Vpb, Device );
    00780
    00781             //
    00782             //  We will be handing control back to the caller here, so
    00783             //  reset the saved device object.
    00784             //
    00785
    00786             IoSetDeviceToVerify( Thread, NULL );
    00787
    00788             //
    00789             //  The Irp will be completed by Io or resubmitted.  In either
    00790             //  case we must clean up the IrpContext here.
    00791             //
    00792
    00793             UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
    00794             return STATUS_PENDING;
    00795         }
    00796     }
    00797
    00798     //
    00799     //  This is just a run of the mill error.
    00800     //
    00801
    00802     UdfCompleteRequest( IrpContext, Irp, ExceptionCode );
    00803
    00804     return ExceptionCode;
    00805 }

NTSTATUS UdfPurgeVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN BOOLEAN | DismountUnderway
| ) |

Definition at line 417 of file udfs/cachesup.c.

References CcPurgeCacheSection(), _SECTION_OBJECT_POINTERS::DataSectionObject, FALSE, _FCB::FcbNonpaged, _FCB::FcbReference, _SECTION_OBJECT_POINTERS::ImageSectionObject, MmFlushForWrite, MmFlushImageSection(), NTSTATUS(), NULL, PAGED_CODE, SafeNodeType, _FCB_NONPAGED::SegmentObject, Status, TRUE, UdfAcquireAllFiles, UdfDeleteInternalStream(), UdfFspClose(), UdfGetNextFcb(), UdfLockVcb, UdfReleaseAllFiles, UDFS_NTC_FCB_DATA, UdfTeardownStructures(), and UdfUnlockVcb.

Referenced by UdfCommonCleanup(), UdfCompleteFcbOpen(), UdfDismountVcb(), UdfInvalidateVolumes(), UdfLockVolumeInternal(), and UdfVerifyVolume().

    00425                    :
    00426
    00427     This routine is called to purge the volume.  The purpose is to make all the stale file
    00428     objects in the system go away, minimizing the reference counts, so that the volume may
    00429     be locked or deleted.
    00430
    00431     The Vcb is already acquired exclusively.  We will lock out all file operations by
    00432     acquiring the global file resource.  Then we will walk through all of the Fcb's and
    00433     perform the purge.
    00434
    00435 Arguments:
    00436
    00437     Vcb - Vcb for the volume to purge.
    00438
    00439     DismountUnderway - Indicates that we are trying to delete all of the objects.
    00440         We will purge the Metadata and VolumeDasd and dereference all internal streams.
    00441
    00442 Return Value:
    00443
    00444     NTSTATUS - The first failure of the purge operation.
    00445
    00446 --*/
    00447
    00448 {
    00449     NTSTATUS Status = STATUS_SUCCESS;
    00450
    00451     PVOID RestartKey = NULL;
    00452     PFCB ThisFcb = NULL;
    00453     PFCB NextFcb;
    00454
    00455     BOOLEAN RemovedFcb;
    00456
    00457     PAGED_CODE();
    00458
    00459     //
    00460     //  Force any remaining Fcb's in the delayed close queue to be closed.
    00461     //
    00462
    00463     UdfFspClose( Vcb );
    00464
    00465     //
    00466     //  Acquire the global file resource.
    00467     //
    00468
    00469     UdfAcquireAllFiles( IrpContext, Vcb );
    00470
    00471     //
    00472     //  Loop through each Fcb in the Fcb Table and perform the flush.
    00473     //
    00474
    00475     while (TRUE) {
    00476
    00477         //
    00478         //  Lock the Vcb to lookup the next Fcb.
    00479         //
    00480
    00481         UdfLockVcb( IrpContext, Vcb );
    00482         NextFcb = UdfGetNextFcb( IrpContext, Vcb, &RestartKey );
    00483
    00484         //
    00485         //  Reference the NextFcb if present.
    00486         //
    00487
    00488         if (NextFcb != NULL) {
    00489
    00490             NextFcb->FcbReference += 1;
    00491         }
    00492
    00493         //
    00494         //  If the last Fcb is present then decrement reference count and call teardown
    00495         //  to see if it should be removed.
    00496         //
    00497
    00498         if (ThisFcb != NULL) {
    00499
    00500             ThisFcb->FcbReference -= 1;
    00501
    00502             UdfUnlockVcb( IrpContext, Vcb );
    00503
    00504             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00505
    00506         } else {
    00507
    00508             UdfUnlockVcb( IrpContext, Vcb );
    00509         }
    00510
    00511         //
    00512         //  Break out of the loop if no more Fcb's.
    00513         //
    00514
    00515         if (NextFcb == NULL) {
    00516
    00517             break;
    00518         }
    00519
    00520         //
    00521         //  Move to the next Fcb.
    00522         //
    00523
    00524         ThisFcb = NextFcb;
    00525
    00526         //
    00527         //  If there is a image section then see if that can be closed.
    00528         //
    00529
    00530         if (ThisFcb->FcbNonpaged->SegmentObject.ImageSectionObject != NULL) {
    00531
    00532             MmFlushImageSection( &ThisFcb->FcbNonpaged->SegmentObject, MmFlushForWrite );
    00533         }
    00534
    00535         //
    00536         //  If there is a data section then purge this.  If there is an image
    00537         //  section then we won't be able to.  Remember this if it is our first
    00538         //  error.
    00539         //
    00540
    00541         if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00542             !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00543                                    NULL,
    00544                                    0,
    00545                                    FALSE ) &&
    00546             (Status == STATUS_SUCCESS)) {
    00547
    00548             Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00549         }
    00550
    00551         //
    00552         //  Dereference the internal stream if dismounting.
    00553         //
    00554
    00555         if (DismountUnderway &&
    00556             (SafeNodeType( ThisFcb ) != UDFS_NTC_FCB_DATA) &&
    00557             (ThisFcb->FileObject != NULL)) {
    00558
    00559             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00560         }
    00561     }
    00562
    00563     //
    00564     //  Now look at the Root Index, Metadata, Volume Dasd and VAT Fcbs.
    00565     //  Note that we usually hit the Root Index in the loop above, but
    00566     //  it is possible miss it if it didn't get into the Fcb table in the
    00567     //  first place!
    00568     //
    00569
    00570     if (DismountUnderway) {
    00571
    00572         if (Vcb->RootIndexFcb != NULL) {
    00573
    00574             ThisFcb = Vcb->RootIndexFcb;
    00575             InterlockedIncrement( &ThisFcb->FcbReference );
    00576
    00577             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00578                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00579                                        NULL,
    00580                                        0,
    00581                                        FALSE ) &&
    00582                 (Status == STATUS_SUCCESS)) {
    00583
    00584                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00585             }
    00586
    00587             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00588             InterlockedDecrement( &ThisFcb->FcbReference );
    00589             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00590         }
    00591
    00592         if (Vcb->MetadataFcb != NULL) {
    00593
    00594             ThisFcb = Vcb->MetadataFcb;
    00595             InterlockedIncrement( &ThisFcb->FcbReference );
    00596
    00597             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00598                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00599                                        NULL,
    00600                                        0,
    00601                                        FALSE ) &&
    00602                 (Status == STATUS_SUCCESS)) {
    00603
    00604                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00605             }
    00606
    00607             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00608             InterlockedDecrement( &ThisFcb->FcbReference );
    00609             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00610         }
    00611
    00612         if (Vcb->VatFcb != NULL) {
    00613
    00614             ThisFcb = Vcb->VatFcb;
    00615             InterlockedIncrement( &ThisFcb->FcbReference );
    00616
    00617             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00618                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00619                                        NULL,
    00620                                        0,
    00621                                        FALSE ) &&
    00622                 (Status == STATUS_SUCCESS)) {
    00623
    00624                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00625             }
    00626
    00627             UdfDeleteInternalStream( IrpContext, ThisFcb );
    00628             InterlockedDecrement( &ThisFcb->FcbReference );
    00629             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00630         }
    00631
    00632         if (Vcb->VolumeDasdFcb != NULL) {
    00633
    00634             ThisFcb = Vcb->VolumeDasdFcb;
    00635             InterlockedIncrement( &ThisFcb->FcbReference );
    00636
    00637             if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
    00638                 !CcPurgeCacheSection( &ThisFcb->FcbNonpaged->SegmentObject,
    00639                                        NULL,
    00640                                        0,
    00641                                        FALSE ) &&
    00642                 (Status == STATUS_SUCCESS)) {
    00643
    00644                 Status = STATUS_UNABLE_TO_DELETE_SECTION;
    00645             }
    00646
    00647             InterlockedDecrement( &ThisFcb->FcbReference );
    00648             UdfTeardownStructures( IrpContext, ThisFcb, FALSE, &RemovedFcb );
    00649         }
    00650     }
    00651
    00652     //
    00653     //  Release all of the files.
    00654     //
    00655
    00656     UdfReleaseAllFiles( IrpContext, Vcb );
    00657
    00658     return Status;
    00659 }

INLINE DECLSPEC_NORETURN VOID UdfRaiseStatus | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN NTSTATUS | Status
| ) |

Definition at line 406 of file udfprocs.h.

References DebugBreakOnStatus, ExRaiseStatus(), and Status.

Referenced by UdfAcquireResource(), UdfCheckLegalCS0Dstring(), UdfCommonCreate(), UdfCommonRead(), UdfCompleteFcbOpen(), UdfCreateFileLock(), UdfCreateInternalStream(), UdfCreateUserMdl(), UdfDetermineVolumeBounding(), UdfFindPrefix(), UdfGetNextAllocationPostProcessing(), UdfInitializeAllocationContext(), UdfInitializeAllocations(), UdfInitializeEnumeration(), UdfInitializeFcbFromIcbContext(), UdfInitializeIcbContextFromFcb(), UdfInsertPrefix(), UdfLookupActiveIcb(), UdfLookupActiveIcbInExtent(), UdfLookupDirEntryPostProcessing(), UdfLookupEa(), UdfLookupFileEntryInEnumeration(), UdfLookupMetaVsnOfExtent(), UdfLookupPsnOfExtent(), UdfMultipleAsync(), UdfNonCachedRead(), UdfOpenObjectByFileId(), UdfPrepareBuffers(), UdfReadSectors(), UdfUpdateDirNames(), UdfUpdateVcbPhase0(), UdfVerifyDescriptor(), UdfVerifyFcbOperation(), and UdfVerifyVcb().

    00410 {
    00411     IrpContext->ExceptionStatus = Status;
    00412     DebugBreakOnStatus( Status );
    00413     ExRaiseStatus( Status );
    00414 }

INLINE ULONG UdfRawBufferSize | ( | IN PVCB | Vcb,
|  | IN ULONG | StructureSize
| ) |

Definition at line 931 of file udfprocs.h.

References ROUND_TO_PAGES, and SectorAlign.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), and UdfUpdateVcbPhase0().

    00935 {
    00936     return (ULONG)ROUND_TO_PAGES( SectorAlign( Vcb, StructureSize ));
    00937 }

INLINE ULONG UdfRawBufferSizeN | ( | IN ULONG | SectorSize,
|  | IN ULONG | StructureSize
| ) |

Definition at line 951 of file udfprocs.h.

References ROUND_TO_PAGES, SectorAlignN, and SectorSize.

Referenced by UdfRecognizeVolume().

    00955 {
    00956     return (ULONG)ROUND_TO_PAGES( SectorAlignN( SectorSize, StructureSize ));
    00957 }

INLINE ULONG UdfRawReadSize | ( | IN PVCB | Vcb,
|  | IN ULONG | StructureSize
| ) |

Definition at line 941 of file udfprocs.h.

References SectorAlign.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), and UdfUpdateVcbPhase0().

    00945 {
    00946     return SectorAlign( Vcb, StructureSize );
    00947 }

INLINE ULONG UdfRawReadSizeN | ( | IN ULONG | SectorSize,
|  | IN ULONG | StructureSize
| ) |

Definition at line 961 of file udfprocs.h.

References SectorAlignN, and SectorSize.

Referenced by UdfRecognizeVolume().

    00965 {
    00966     return SectorAlignN( SectorSize, StructureSize );
    00967 }

NTSTATUS UdfReadSectors | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount,
|  | IN BOOLEAN | ReturnError,
|  | IN OUT PVOID | Buffer,
|  | IN PDEVICE_OBJECT | TargetDeviceObject
| ) |

Definition at line 685 of file deviosup.c.

References ASSERT, Buffer, BytesFromSectors, Dbg, DebugTrace, Event(), Executive, FALSE, FlagOn, FsRtlLookupLargeMcbEntry(), IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, IRP_MJ_READ, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LlSectorsFromBytes, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, SectorSize, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, UdfMethod2TransformByteOffset, UdfNormalizeAndRaiseStatus(), UdfRaiseStatus(), and VCB_STATE_METHOD_2_FIXUP.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfLoadSparingTables(), UdfRecognizeVolume(), and UdfUpdateVcbPhase0().

    00696                    :
    00697
    00698     This routine is called to transfer sectors from the disk to a
    00699     specified buffer.  It is used for mount and volume verify operations.
    00700
    00701     This routine is synchronous, it will not return until the operation
    00702     is complete or until the operation fails.
    00703
    00704     The routine allocates an IRP and then passes this IRP to a lower
    00705     level driver.  Errors may occur in the allocation of this IRP or
    00706     in the operation of the lower driver.
    00707
    00708 Arguments:
    00709
    00710     StartingOffset - Logical offset on the disk to start the read.  This
    00711         must be on a sector boundary, no check is made here.
    00712
    00713     ByteCount - Number of bytes to read.  This is an integral number of
    00714         sectors, or otherwise a value we know the driver can handle,
    00715         no check is made here to confirm this.
    00716
    00717     ReturnError - Indicates whether we should return TRUE or FALSE
    00718         to indicate an error or raise an error condition.  This only applies
    00719         to the result of the IO.  Any other error may cause a raise.
    00720
    00721     Buffer - Buffer to transfer the disk data into.
    00722
    00723     TargetDeviceObject - The device object for the volume to be read.
    00724
    00725 Return Value:
    00726
    00727     The final status of the operation.
    00728
    00729 --*/
    00730
    00731 {
    00732     PLONGLONG UseStartingOffset;
    00733     LONGLONG LocalStartingOffset;
    00734     NTSTATUS Status;
    00735     KEVENT  Event;
    00736     PIRP Irp;
    00737
    00738     PAGED_CODE();
    00739
    00740     DebugTrace(( +1, Dbg,
    00741                  "UdfReadSectors, %x%08x +%x -> %08x from DO %08x\n",
    00742                  ((PLARGE_INTEGER)&StartingOffset)->HighPart,
    00743                  ((PLARGE_INTEGER)&StartingOffset)->LowPart,
    00744                  ByteCount,
    00745                  Buffer,
    00746                  TargetDeviceObject ));
    00747
    00748     //
    00749     //  For the time being, we assume that we only read sector-at-a-time.
    00750     //  This simplifies sparing, and is the only way I am aware of this
    00751     //  code would not be ready for blocksize != sectorsize.  It just is
    00752     //  not worth writing dead (but straightforward) code right now.
    00753     //
    00754
    00755     ASSERT( IrpContext->Vcb == NULL || ByteCount == SectorSize( IrpContext->Vcb ));
    00756
    00757     //
    00758     //  If the volume is spared (and at a point where sparing is possible),
    00759     //  check if a mapping needs to be performed.
    00760     //
    00761
    00762     if (IrpContext->Vcb &&
    00763         IrpContext->Vcb->Pcb &&
    00764         IrpContext->Vcb->Pcb->SparingMcb) {
    00765
    00766         LONGLONG SparingPsn;
    00767
    00768         if (FsRtlLookupLargeMcbEntry( IrpContext->Vcb->Pcb->SparingMcb,
    00769                                       LlSectorsFromBytes( IrpContext->Vcb, StartingOffset ),
    00770                                       &SparingPsn,
    00771                                       NULL,
    00772                                       NULL,
    00773                                       NULL,
    00774                                       NULL ) &&
    00775             SparingPsn != -1) {
    00776
    00777             StartingOffset = BytesFromSectors( IrpContext->Vcb, (ULONG) SparingPsn );
    00778         }
    00779     }
    00780
    00781     //
    00782     //  Initialize the event.
    00783     //
    00784
    00785     KeInitializeEvent( &Event, NotificationEvent, FALSE );
    00786
    00787     //
    00788     //  Correct the starting offset by the method 2 fixup if neccesary.  This also
    00789     //  assumes sector-at-a-time and sector == block so we don't need to fragment
    00790     //  the request or check if it spans a packet boundary.
    00791     //
    00792     //  We assume that no fixups are required until a Vcb exists.  This is true
    00793     //  since volume recognition may proceed in the first packet.
    00794     //
    00795
    00796     UseStartingOffset = &StartingOffset;
    00797
    00798     if (IrpContext->Vcb &&
    00799         FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) {
    00800
    00801         LocalStartingOffset = UdfMethod2TransformByteOffset( IrpContext->Vcb, StartingOffset );
    00802         UseStartingOffset = &LocalStartingOffset;
    00803
    00804         DebugTrace(( 0, Dbg,
    00805                      "UdfReadSectors, Method2 Fixup to %x%08x\n",
    00806                      ((PLARGE_INTEGER)UseStartingOffset)->HighPart,
    00807                      ((PLARGE_INTEGER)UseStartingOffset)->LowPart ));
    00808     }
    00809
    00810     //
    00811     //  Attempt to allocate the IRP.  If unsuccessful, raise
    00812     //  STATUS_INSUFFICIENT_RESOURCES.
    00813     //
    00814
    00815     Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
    00816                                         TargetDeviceObject,
    00817                                         Buffer,
    00818                                         ByteCount,
    00819                                         (PLARGE_INTEGER) UseStartingOffset,
    00820                                         &Event,
    00821                                         &IrpContext->Irp->IoStatus );
    00822
    00823     if (Irp == NULL) {
    00824
    00825         UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    00826     }
    00827
    00828     //
    00829     //  Ignore the change line (verify) for mount and verify requests
    00830     //
    00831
    00832     SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
    00833
    00834     //
    00835     //  Send the request down to the driver.  If an error occurs return
    00836     //  it to the caller.
    00837     //
    00838
    00839     Status = IoCallDriver( TargetDeviceObject, Irp );
    00840
    00841     //
    00842     //  If the status was STATUS_PENDING then wait on the event.
    00843     //
    00844
    00845     if (Status == STATUS_PENDING) {
    00846
    00847         Status = KeWaitForSingleObject( &Event,
    00848                                         Executive,
    00849                                         KernelMode,
    00850                                         FALSE,
    00851                                         NULL );
    00852
    00853         //
    00854         //  On a successful wait pull the status out of the IoStatus block.
    00855         //
    00856
    00857         if (NT_SUCCESS( Status )) {
    00858
    00859             Status = IrpContext->Irp->IoStatus.Status;
    00860         }
    00861     }
    00862
    00863     DebugTrace(( -1, Dbg, "UdfReadSectors -> %08x\n", Status ));
    00864
    00865     //
    00866     //  Check whether we should raise in the error case.
    00867     //
    00868
    00869     if (!NT_SUCCESS( Status ) && !ReturnError) {
    00870
    00871         UdfNormalizeAndRaiseStatus( IrpContext, Status );
    00872     }
    00873
    00874     return Status;
    00875 }

VOID UdfReleaseForCreateSection | ( | IN PFILE_OBJECT | FileObject | ) |

Definition at line 302 of file resrcsup.c.

References ExReleaseResource, and PAGED_CODE.

Referenced by UdfInitializeGlobalData().

    00308                    :
    00309
    00310     This is the callback routine for MM to use to release a file acquired with
    00311     the AcquireForCreateSection call above.
    00312
    00313 Arguments:
    00314
    00315     FileObject - File object for a Udffs stream.
    00316
    00317 Return Value:
    00318
    00319     None
    00320
    00321 --*/
    00322
    00323 {
    00324     PAGED_CODE();
    00325
    00326     //
    00327     //  Release the resource in the Fcb.
    00328     //
    00329
    00330     ExReleaseResource( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource );
    00331
    00332     return;
    00333 }
    }

VOID UdfReleaseFromCache | ( | IN PFCB | Fcb | ) |

Definition at line 172 of file resrcsup.c.

References ASSERT, ExReleaseResource, FSRTL_CACHE_TOP_LEVEL_IRP, IoGetTopLevelIrp(), IoSetTopLevelIrp(), NULL, and PAGED_CODE.

Referenced by UdfInitializeGlobalData().

    00178                    :
    00179
    00180     The address of this routine is specified when creating a CacheMap for
    00181     a virtual file.  It is subsequently called by the Lazy Writer to release
    00182     a resource acquired above.
    00183
    00184 Arguments:
    00185
    00186     Fcb -  The pointer supplied as context to the cache initialization
    00187            routine.
    00188
    00189 Return Value:
    00190
    00191     None
    00192
    00193 --*/
    00194
    00195 {
    00196     PAGED_CODE();
    00197
    00198     ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
    00199     IoSetTopLevelIrp( NULL );
    00200
    00201     ExReleaseResource( Fcb->Resource );
    00202
    00203     return;
    00204 }

VOID UdfRemovePrefix | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PLCB | Lcb
| ) |

Definition at line 256 of file prefxsup.c.

References ASSERT_EXCLUSIVE_FCB_OR_VCB, ASSERT_IRP_CONTEXT, ASSERT_LCB, ExFreePool(), ExFreeToPagedLookasideList(), FlagOn, LCB_FLAG_IGNORE_CASE, LCB_FLAG_POOL_ALLOCATED, PAGED_CODE, RtlDelete(), and UdfLcbLookasideList.

Referenced by UdfTeardownStructures().

    00263                    :
    00264
    00265     This routine is called to remove a given prefix of an Fcb.
    00266
    00267 Arguments:
    00268
    00269     Lcb - the prefix being removed.
    00270
    00271 Return Value:
    00272
    00273     None
    00274
    00275 --*/
    00276
    00277 {
    00278     PAGED_CODE();
    00279
    00280     //
    00281     //  Check inputs.
    00282     //
    00283
    00284     ASSERT_IRP_CONTEXT( IrpContext );
    00285     ASSERT_LCB( Lcb );
    00286
    00287     //
    00288     //  Check the acquisition of the two Fcbs.
    00289     //
    00290
    00291     ASSERT_EXCLUSIVE_FCB_OR_VCB( Lcb->ParentFcb );
    00292     ASSERT_EXCLUSIVE_FCB_OR_VCB( Lcb->ChildFcb );
    00293
    00294     //
    00295     //  Now remove the linkage and delete the Lcb.
    00296     //
    00297
    00298     RemoveEntryList( &Lcb->ParentFcbLinks );
    00299     RemoveEntryList( &Lcb->ChildFcbLinks );
    00300
    00301     if (FlagOn( Lcb->Flags, LCB_FLAG_IGNORE_CASE )) {
    00302
    00303         Lcb->ParentFcb->IgnoreCaseRoot = RtlDelete( &Lcb->Links );
    00304
    00305     } else {
    00306
    00307         Lcb->ParentFcb->ExactCaseRoot = RtlDelete( &Lcb->Links );
    00308     }
    00309
    00310     if (FlagOn( Lcb->Flags, LCB_FLAG_POOL_ALLOCATED )) {
    00311
    00312         ExFreePool( Lcb );
    00313
    00314     } else {
    00315
    00316         ExFreeToPagedLookasideList( &UdfLcbLookasideList, Lcb );
    00317     }
    00318
    00319     return;
    00320 }

VOID UdfRemoveVmcbMapping | ( | IN PVMCB | Vmcb,
|  | IN LBN | Lbn,
|  | IN ULONG | SectorCount
| ) |

VOID UdfRenderNameToLegalUnicode | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | Name,
|  | IN PUNICODE_STRING | RenderedName
| ) |

Definition at line 927 of file namesup.c.

References ASSERT, CRC_LEN, CRC_MARK, EXT_LEN, FALSE, ILLEGAL_CHAR_MARK, INT16, IsDeviceName, IsFileNameCharLegal, MAX_LEN, Name, NativeCharLength, PERIOD, SPACE, TRUE, UdfComputeCrc16Uni(), UdfCrcChar, UINT16, UNICODE_CHAR, and USHORT.

Referenced by UdfUpdateDirNames().

    00935                    :
    00936
    00937     This routine will take a Unicode string containing illegal characters and
    00938     run it through the UDF standard algorithim to render it into a "legal"
    00939     name.
    00940
    00941     The short form is to convert all runs of illegal characters to "_" and tack
    00942     on a hex representation of the CRC of the original name.  The algorithm is
    00943     nearly directly lifted from the UDF (2.01 proposed!) standard, so apologies
    00944     for the style clash.
    00945
    00946 Arguments:
    00947
    00948     Name - the actual name
    00949
    00950     RenderedName - the name rendered into legal characters
    00951
    00952 Return Value:
    00953
    00954     BOOLEAN - TRUE if the expressions match, FALSE otherwise.
    00955
    00956 --*/
    00957
    00958 {
    00959     INT16 index;
    00960     INT16 targetIndex;
    00961     INT16 crcIndex;
    00962     INT16 extLen;
    00963     INT16 nameLen;
    00964     INT16 charLen;
    00965     INT16 overlayBytes;
    00966     INT16 bytesLeft;
    00967     UNICODE_CHAR current;
    00968     BOOLEAN needsCRC;
    00969     BOOLEAN foundDot;
    00970     UNICODE_CHAR ext[EXT_LEN];
    00971
    00972     //
    00973     //  So as to lift as directly as possible from the standard, chunk things around.
    00974     //
    00975
    00976     PWCHAR newName = RenderedName->Buffer;
    00977     PWCHAR udfName = Name->Buffer;
    00978     LONG udfNameLen = Name->Length / sizeof(WCHAR);
    00979
    00980     /* Remove trailing periods ('.') and spaces (' '), Windows     */
    00981     /* does not like them.                                         */
    00982     foundDot = FALSE;
    00983     index = udfNameLen;
    00984     while (index-- > 0) {
    00985         if (udfName[index] == PERIOD)
    00986             foundDot = TRUE;
    00987         else if (udfName[index] != SPACE)
    00988             break;
    00989     }
    00990
    00991     /* If any trailing periods or spaces were found, a CRC code    */
    00992     /* needs to be added to the resulting file name.               */
    00993     nameLen = index + 1;
    00994     if (nameLen < udfNameLen)
    00995         needsCRC = TRUE;
    00996
    00997     needsCRC = FALSE;
    00998     bytesLeft = MAX_LEN;
    00999     extLen = 0;
    01000
    01001     if (needsCRC == FALSE || foundDot == FALSE) {
    01002         /* Look for an extension in the file name.  We do not      */
    01003         /* need to look for one if there were any trailing periods */
    01004         /* removed.                                                */
    01005         INT16 endIndex;
    01006         INT16 prevCharLen = 1;
    01007         INT16 extBytes = 0;
    01008
    01009         targetIndex = 0;
    01010         index = nameLen;
    01011
    01012         /* Determine how many bytes we need to scan to find the    */
    01013         /* extension delimiter.  The extension has a maximum of    */
    01014         /* five characters, but we do not want to scan past the    */
    01015         /* beginning of the buffer.                                */
    01016         endIndex = (udfNameLen > EXT_LEN + 1) ?
    01017             udfNameLen - EXT_LEN - 1 : 1;
    01018
    01019         /* Start at the end of the name and scan backward, looking */
    01020         /* for the extension delimiter (".").                      */
    01021         while (index-- > endIndex) {
    01022             /* Get the character to test.                          */
    01023             current = udfName[index];
    01024
    01025             if (current == '.') {
    01026                 /* The extension delimiter was found, figure out   */
    01027                 /* how many characters the extension contains and  */
    01028                 /* the length of the resulting file name without   */
    01029                 /* the extension.                                  */
    01030                 extLen = nameLen - index - 1;
    01031                 nameLen = index;
    01032                 break;
    01033             }
    01034
    01035             /* Determine the byte length of the current character  */
    01036             /* when converted to native format.                    */
    01037             charLen = (IsFileNameCharLegal(current)) ?
    01038                 NativeCharLength(current) : 0;
    01039
    01040             if (charLen == 0) {
    01041                 /* If the character byte length is zero, it is     */
    01042                 /* illegal or unprintable, place an underscore     */
    01043                 /* ("_") in the extension buffer if the previous   */
    01044                 /* character tested was legal.  Not that the       */
    01045                 /* characters placed in the extension buffer are   */
    01046                 /* in reverse order.                               */
    01047                 if (prevCharLen != 0) {
    01048                     ext[targetIndex++] = ILLEGAL_CHAR_MARK;
    01049                     extBytes++;
    01050                 }
    01051             }
    01052             else {
    01053                 /* The current character is legal and printable,   */
    01054                 /* put it in the extension buffer.  Note that the  */
    01055                 /* characters placed in the extension buffer are   */
    01056                 /* in reverse order.                               */
    01057                 ext[targetIndex++] = current;
    01058                 extBytes += charLen;
    01059             }
    01060
    01061             /* Save the byte length of the current character, so   */
    01062             /* we can determine if it was a legal character during */
    01063             /* the next test.                                      */
    01064             prevCharLen = charLen;
    01065         }
    01066
    01067         /* If an extension was found, determine how many bytes     */
    01068         /* remain in the file name buffer once we account for it.  */
    01069         if (extLen > 0)
    01070             bytesLeft -= extBytes + 1;
    01071     }
    01072
    01073     index = 0;
    01074     targetIndex = 0;
    01075     crcIndex = 0;
    01076     overlayBytes = -1;
    01077     while (index < nameLen && bytesLeft > 0) {
    01078         /* Get the current character and convert it to upper case. */
    01079         current = udfName[index];
    01080
    01081         /* Determine if this is a valid file name char and         */
    01082         /* calculate its corresponding native character byte       */
    01083         /* length (zero if the char is not legal or undiplayable   */
    01084         /* on this system).                                        */
    01085         charLen = (IsFileNameCharLegal(current)) ?
    01086             NativeCharLength(current) : 0;
    01087
    01088         /* If the char is larger than the available space in the   */
    01089         /* buffer, pretend it is undisplayable.                    */
    01090         if (charLen > bytesLeft)
    01091             charLen = 0;
    01092
    01093         if (charLen == 0) {
    01094             /* Undisplayable or illegal characters are substituted */
    01095             /* with an underscore ("_"), and requires a CRC code   */
    01096             /* appended to the mangled file name.                  */
    01097             needsCRC = TRUE;
    01098             charLen = 1;
    01099             current = '_';
    01100
    01101             /* Skip over any following undiplayable or illegal     */
    01102             /* chars.                                              */
    01103             while (index + 1 < udfNameLen &&
    01104                 (!IsFileNameCharLegal(udfName[index + 1]) ||
    01105                 NativeCharLength(udfName[index + 1]) == 0))
    01106                 index++;
    01107
    01108             /* Terminate loop if at the end of the file name.      */
    01109             if (index >= udfNameLen)
    01110                 break;
    01111         }
    01112
    01113         /* Assign the resulting char to the next index in the file */
    01114         /* name buffer and determine how many native bytes are     */
    01115         /* left.                                                   */
    01116         newName[targetIndex++] = current;
    01117         bytesLeft -= charLen;
    01118
    01119         /* This figures out where the CRC code needs to start in   */
    01120         /* the file name buffer.                                   */
    01121         if (bytesLeft >= CRC_LEN) {
    01122             /* If there is enough space left, just tack it onto    */
    01123             /* the end.                                            */
    01124             crcIndex = targetIndex;
    01125         }
    01126         else {
    01127             /* If there is not enough space left, the CRC must     */
    01128             /* overlay a character already in the file name        */
    01129             /* buffer.  Once this condition has been met, the      */
    01130             /* value will not change.                              */
    01131             if (overlayBytes < 0) {
    01132                 /* Determine the index and save the length of the  */
    01133                 /* native character that is overlayed.  It is      */
    01134                 /* possible that the CRC might overlay half of a   */
    01135                 /* two-byte native character depending upon how    */
    01136                 /* the character boundaries line up.               */
    01137                 overlayBytes = (bytesLeft + charLen > CRC_LEN)
    01138                     ? 1 : 0;
    01139                 crcIndex = targetIndex - 1;
    01140             }
    01141         }
    01142
    01143         /* Advance to the next character.                          */
    01144         index++;
    01145     }
    01146
    01147     /* If the scan did not reach the end of the file name, or the  */
    01148     /* length of the file name is zero, a CRC code is needed.      */
    01149     if (index < nameLen || index == 0)
    01150         needsCRC = TRUE;
    01151
    01152     /* If the name has illegal characters or and extension, it     */
    01153     /* is not a DOS device name.                                   */
    01154     if (needsCRC == FALSE && extLen == 0) {
    01155         /* If this is the name of a DOS device, a CRC code should  */
    01156         /* be appended to the file name.                           */
    01157         if (IsDeviceName(udfName, udfNameLen))
    01158             needsCRC = TRUE;
    01159     }
    01160
    01161     /* Append the CRC code to the file name, if needed.            */
    01162     if (needsCRC) {
    01163         /* Get the CRC value for the original Unicode string       */
    01164         UINT16 udfCRCValue = UdfComputeCrc16Uni(udfName, udfNameLen);
    01165
    01166         /* Determine the character index where the CRC should      */
    01167         /* begin.                                                  */
    01168         targetIndex = crcIndex;
    01169
    01170         /* If the character being overlayed is a two-byte native   */
    01171         /* character, replace the first byte with an underscore.   */
    01172         if (overlayBytes > 0)
    01173             newName[targetIndex++] = ILLEGAL_CHAR_MARK;
    01174
    01175         /* Append the encoded CRC value with delimiter.            */
    01176         newName[targetIndex++] = CRC_MARK;
    01177         newName[targetIndex++] = UdfCrcChar[(udfCRCValue & 0xf000) >> 12];
    01178         newName[targetIndex++] = UdfCrcChar[(udfCRCValue & 0x0f00) >> 8];
    01179         newName[targetIndex++] = UdfCrcChar[(udfCRCValue & 0x00f0) >> 4];
    01180         newName[targetIndex++] = UdfCrcChar[(udfCRCValue & 0x000f)];
    01181     }
    01182
    01183
    01184     /* If an extension was found, append it here.                  */
    01185     if (extLen > 0) {
    01186         /* Add the period ('.') for the extension delimiter.       */
    01187         newName[targetIndex++] = PERIOD;
    01188
    01189         /* Append the characters in the extension buffer.  They    */
    01190         /* were stored in reverse order, so we need to begin with  */
    01191         /* the last character and work forward.                    */
    01192         while (extLen-- > 0)
    01193             newName[targetIndex++] = ext[extLen];
    01194     }
    01195
    01196     ASSERT( (targetIndex * sizeof(WCHAR)) <= RenderedName->MaximumLength );
    01197
    01198     RenderedName->Length = (USHORT) (targetIndex * sizeof(WCHAR));
    01199 }

VOID UdfResetVmcb | ( | IN PVMCB | Vmcb | ) |

Definition at line 370 of file vmcbsup.c.

References Dbg, DebugTrace, FsRtlResetLargeMcb(), PAGED_CODE, PLARGE_MCB, and TRUE.

Referenced by UdfUpdateVcbPhase0().

    00376                    :
    00377
    00378     This routine resets the mappings in an existing VMCB structure.
    00379
    00380 Arguments:
    00381
    00382     Vmcb - Supplies a pointer to the VMCB structure to reset.
    00383
    00384 Return Value:
    00385
    00386     None.
    00387
    00388 --*/
    00389
    00390 {
    00391     PAGED_CODE();
    00392
    00393     DebugTrace(( +1, Dbg, "UdfResetVmcb, Vmcb = %08x\n", Vmcb ));
    00394
    00395     //
    00396     //  Unitialize the fields in the Vmcb structure
    00397     //
    00398
    00399     FsRtlResetLargeMcb( (PLARGE_MCB) &Vmcb->VbnIndexed, TRUE );
    00400     FsRtlResetLargeMcb( (PLARGE_MCB) &Vmcb->LbnIndexed, TRUE );
    00401
    00402     //
    00403     //  And return to our caller
    00404     //
    00405
    00406     DebugTrace(( -1, Dbg, "UdfResetVmcb -> VOID\n" ));
    00407
    00408     return;
    00409 }

INLINE VOID UdfRestoreThreadContext | ( | IN PIRP_CONTEXT | IrpContext | ) |

Definition at line 543 of file udfprocs.h.

References IoSetTopLevelIrp(), and NULL.

Referenced by UdfCleanupIrpContext().

    00546 {
    00547     IrpContext->ThreadContext->Udfs = 0;
    00548     IoSetTopLevelIrp( IrpContext->ThreadContext->SavedTopLevelIrp );
    00549     IrpContext->ThreadContext = NULL;
    00550 }

ULONG UdfSerial32 | ( | IN PCHAR | Buffer,
|  | IN ULONG | ByteCount
| ) |

Definition at line 1022 of file udfdata.c.

References Buffer, PAGED_CODE, and SerialId.

Referenced by UdfUpdateVolumeSerialNumber().

    01029                    :
    01030
    01031     This routine is called to generate a 32 bit serial number.  This is
    01032     done by doing four separate checksums into an array of bytes and
    01033     then treating the bytes as a ULONG.
    01034
    01035 Arguments:
    01036
    01037     Buffer - Pointer to the buffer to generate the ID for.
    01038
    01039     ByteCount - Number of bytes in the buffer.
    01040
    01041 Return Value:
    01042
    01043     ULONG - The 32 bit serial number.
    01044
    01045 --*/
    01046
    01047 {
    01048     union {
    01049         UCHAR   Bytes[4];
    01050         ULONG   SerialId;
    01051     } Checksum;
    01052
    01053     PAGED_CODE();
    01054
    01055     //
    01056     //  Initialize the serial number.
    01057     //
    01058
    01059     Checksum.SerialId = 0;
    01060
    01061     //
    01062     //  Continue while there are more bytes to use.
    01063     //
    01064
    01065     while (ByteCount--) {
    01066
    01067         //
    01068         //  Increment this sub-checksum.
    01069         //
    01070
    01071         Checksum.Bytes[ByteCount & 0x3] += *(Buffer++);
    01072     }
    01073
    01074     //
    01075     //  Return the checksums as a ULONG.
    01076     //
    01077
    01078     return Checksum.SerialId;
    01079 }

VOID UdfSetFileObject | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFILE_OBJECT | FileObject,
|  | IN TYPE_OF_OPEN | TypeOfOpen,
|  | IN PFCB Fcb | OPTIONAL,
|  | IN PCCB Ccb | OPTIONAL
| ) |

Definition at line 49 of file filobsup.c.

References ASSERTMSG, BeyondValidType, FlagOn, NULL, PAGED_CODE, SetFlag, TYPE_OF_OPEN_MASK, and UnopenedFileObject.

Referenced by UdfCompleteFcbOpen(), and UdfCreateInternalStream().

    00059                    :
    00060
    00061     This routine will initialize the FileObject context fields based on the
    00062     input type and data structures.
    00063
    00064 Arguments:
    00065
    00066     FileObject - Supplies the file object pointer being initialized.
    00067
    00068     TypeOfOpen - Sets the type of open.
    00069
    00070     Fcb - Fcb for this file object.  Ignored for UnopenedFileObject.
    00071
    00072     Ccb - Ccb for the handle corresponding to this file object.  Will not
    00073         be present for stream file objects.
    00074
    00075 Return Value:
    00076
    00077     None.
    00078
    00079 --*/
    00080
    00081 {
    00082     PAGED_CODE();
    00083
    00084     //
    00085     //  We only have values 0 to 7 available so make sure we didn't
    00086     //  inadvertantly add a new type.
    00087     //
    00088
    00089     ASSERTMSG( "FileObject types exceed available bits\n", BeyondValidType <= 8 );
    00090
    00091     //
    00092     //  Setting a file object to type UnopenedFileObject means just
    00093     //  clearing all of the context fields.  All the other input
    00094     //
    00095
    00096     if (TypeOfOpen == UnopenedFileObject) {
    00097
    00098         FileObject->FsContext =
    00099         FileObject->FsContext2 = NULL;
    00100
    00101         return;
    00102     }
    00103
    00104     //
    00105     //  Check that the 3 low-order bits of the Ccb are clear.
    00106     //
    00107
    00108     ASSERTMSG( "Ccb is not quad-aligned\n", !FlagOn( ((ULONG_PTR) Ccb), TYPE_OF_OPEN_MASK ));
    00109
    00110     //
    00111     //  We will or the type of open into the low order bits of FsContext2
    00112     //  along with the Ccb value.
    00113     //  The Fcb is stored into the FsContext field.
    00114     //
    00115
    00116     FileObject->FsContext = Fcb;
    00117     FileObject->FsContext2 = Ccb;
    00118
    00119     SetFlag( ((ULONG_PTR) FileObject->FsContext2), TypeOfOpen );
    00120
    00121     //
    00122     //  Set the Vpb field in the file object.
    00123     //
    00124
    00125     FileObject->Vpb = Fcb->Vcb->Vpb;
    00126
    00127     return;
    00128 }

VOID UdfSetMaximumLbnVmcb | ( | IN PVMCB | Vmcb,
|  | IN ULONG | MaximumLbn
| ) |

Definition at line 413 of file vmcbsup.c.

References Dbg, DebugTrace, and PAGED_CODE.

    00420                    :
    00421
    00422     This routine sets/resets the maximum allowed LBN for the specified
    00423     Vmcb structure.  The Vmcb structure must already have been initialized
    00424     by calling UdfInitializeVmcb.
    00425
    00426 Arguments:
    00427
    00428     Vmcb - Supplies a pointer to the volume file structure to initialize.
    00429
    00430     MaximumLbn - Supplies the maximum Lbn value that is valid for this
    00431         volume.
    00432
    00433 Return Value:
    00434
    00435     None
    00436
    00437 --*/
    00438
    00439 {
    00440     PAGED_CODE();
    00441
    00442     DebugTrace(( +1, Dbg, "UdfSetMaximumLbnVmcb, Vmcb = %08x\n", Vmcb ));
    00443
    00444     //
    00445     //  Set the field
    00446     //
    00447
    00448     Vmcb->MaximumLbn = MaximumLbn;
    00449
    00450     //
    00451     //  And return to our caller
    00452     //
    00453
    00454     DebugTrace(( -1, Dbg, "UdfSetMaximumLbnVmcb -> VOID\n" ));
    00455
    00456     return;
    00457 }

VOID UdfSetThreadContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PTHREAD_CONTEXT | ThreadContext
| ) |

Definition at line 873 of file udfdata.c.

References ASSERT_IRP_CONTEXT, FlagOn, IoGetStackLimits(), IoGetTopLevelIrp(), IoSetTopLevelIrp(), IRP_CONTEXT_FLAG_TOP_LEVEL, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS, LongOffsetPtr, NULL, PAGED_CODE, PTHREAD_CONTEXT, SetFlag, ThreadContext, _THREAD_CONTEXT::TopLevelIrpContext, _THREAD_CONTEXT::Udfs, and UDFS_SIGNATURE.

Referenced by UdfFsdDispatch(), UdfFspClose(), and UdfFspDispatch().

    00880                    :
    00881
    00882     This routine is called at each Fsd/Fsp entry point set up the IrpContext
    00883     and thread local storage to track top level requests.  If there is
    00884     not a Udfs context in the thread local storage then we use the input one.
    00885     Otherwise we use the one already there.  This routine also updates the
    00886     IrpContext based on the state of the top-level context.
    00887
    00888     If the TOP_LEVEL flag in the IrpContext is already set when we are called
    00889     then we force this request to appear top level.
    00890
    00891 Arguments:
    00892
    00893     ThreadContext - Address on stack for local storage if not already present.
    00894
    00895     ForceTopLevel - We force this request to appear top level regardless of
    00896         any previous stack value.
    00897
    00898 Return Value:
    00899
    00900     None
    00901
    00902 --*/
    00903
    00904 {
    00905     PTHREAD_CONTEXT CurrentThreadContext;
    00906     ULONG_PTR StackTop;
    00907     ULONG_PTR StackBottom;
    00908
    00909     PAGED_CODE();
    00910
    00911     ASSERT_IRP_CONTEXT( IrpContext );
    00912
    00913     //
    00914     //  Get the current top-level irp out of the thread storage.
    00915     //  If NULL then this is the top-level request.
    00916     //
    00917
    00918     CurrentThreadContext = (PTHREAD_CONTEXT) IoGetTopLevelIrp();
    00919
    00920     if (CurrentThreadContext == NULL) {
    00921
    00922         SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL );
    00923     }
    00924
    00925     //
    00926     //  Initialize the input context unless we are using the current
    00927     //  thread context block.  We use the new block if our caller
    00928     //  specified this or the existing block is invalid.
    00929     //
    00930     //  The following must be true for the current to be a valid Udfs context.
    00931     //
    00932     //      Structure must lie within current stack.
    00933     //      Address must be ULONG aligned.
    00934     //      Udfs signature must be present.
    00935     //
    00936     //  If this is not a valid Udfs context then use the input thread
    00937     //  context and store it in the top level context.
    00938     //
    00939
    00940     IoGetStackLimits( &StackTop, &StackBottom);
    00941
    00942     if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) ||
    00943         (((ULONG_PTR) CurrentThreadContext > StackBottom - sizeof( THREAD_CONTEXT )) ||
    00944          ((ULONG_PTR) CurrentThreadContext <= StackTop) ||
    00945          LongOffsetPtr( CurrentThreadContext ) ||
    00946          (CurrentThreadContext->Udfs != UDFS_SIGNATURE))) {
    00947
    00948         ThreadContext->Udfs = UDFS_SIGNATURE;
    00949         ThreadContext->SavedTopLevelIrp = (PIRP) CurrentThreadContext;
    00950         ThreadContext->TopLevelIrpContext = IrpContext;
    00951         IoSetTopLevelIrp( (PIRP) ThreadContext );
    00952
    00953         IrpContext->TopLevel = IrpContext;
    00954         IrpContext->ThreadContext = ThreadContext;
    00955
    00956         SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_UDFS );
    00957
    00958     //
    00959     //  Otherwise use the IrpContext in the thread context.
    00960     //
    00961
    00962     } else {
    00963
    00964         IrpContext->TopLevel = CurrentThreadContext->TopLevelIrpContext;
    00965     }
    00966
    00967     return;
    00968 }

VOID UdfStoreVolumeDescriptorIfPrevailing | ( | IN OUT PNSR_VD_GENERIC * | StoredVD,
|  | IN OUT PNSR_VD_GENERIC | NewVD
| ) |

Definition at line 235 of file udfs/fsctrl.c.

References FsRtlAllocatePoolWithTag, NULL, TAG_NSR_VDSD, and UdfNonPagedPool.

Referenced by UdfAddToPcb(), and UdfFindVolumeDescriptors().

    00242                    :
    00243
    00244     This routine updates Volume Descriptor if the new descriptor
    00245     is more prevailing than the one currently stored.
    00246
    00247 Arguments:
    00248
    00249     StoredVD - pointer to a currently stored descriptor
    00250
    00251     NewVD - pointer to a candidate descriptor
    00252
    00253 Return Value:
    00254
    00255     None.
    00256
    00257 --*/
    00258
    00259 {
    00260     PNSR_VD_GENERIC TempVD;
    00261
    00262     //
    00263     //  If we haven't stored a volume descriptor or the sequence number
    00264     //  of the stored descriptor is less than the new descriptor, make a copy
    00265     //  of it and store it.
    00266     //
    00267
    00268     if ((NULL == *StoredVD) || ((*StoredVD)->Sequence < NewVD->Sequence)) {
    00269
    00270         if ( NULL == *StoredVD)  {
    00271
    00272             *StoredVD = (PNSR_VD_GENERIC) FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    00273                                                                     sizeof(NSR_VD_GENERIC),
    00274                                                                     TAG_NSR_VDSD );
    00275         }
    00276
    00277         RtlCopyMemory( *StoredVD,  NewVD,  sizeof( NSR_VD_GENERIC));
    00278     }
    00279 }

VOID UdfTeardownStructures | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | StartingFcb,
|  | IN BOOLEAN | Recursive,
|  | OUT PBOOLEAN | RemovedStartingFcb
| ) |

Definition at line 1606 of file udfs/strucsup.c.

References ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, ASSERT_LCB, _LCB::ChildFcb, ClearFlag, Dbg, DebugTrace, FALSE, FCB_STATE_IN_FCB_TABLE, _FCB::FcbReference, _FCB::FcbState, _FCB::FcbUserReference, FlagOn, IRP_CONTEXT_FLAG_IN_TEARDOWN, NULL, PAGED_CODE, _LCB::ParentFcb, _FCB::ParentLcbQueue, _LCB::Reference, SafeNodeType, SetFlag, TRUE, UdfAcquireFcbExclusive, UdfDecrementReferenceCounts, UdfDeleteFcb(), UdfDeleteFcbTable, UdfDeleteInternalStream(), UdfLockVcb, UdfReleaseFcb, UdfRemovePrefix(), UDFS_NTC_FCB_DATA, UdfUnlockVcb, _VCB::VcbReference, and _VCB::VcbUserReference.

Referenced by UdfCommonClosePrivate(), UdfCommonCreate(), UdfOplockComplete(), UdfPrePostIrp(), and UdfPurgeVolume().

    01615                    :
    01616
    01617     This routine is used to walk from some starting point in the Fcb tree towards
    01618     the root.  It will remove the Fcb and continue walking up the tree until
    01619     it finds a point where we can't remove an Fcb.
    01620
    01621     We look at the following fields in the Fcb to determine whether we can
    01622     remove this.
    01623
    01624         1 - Handle count must be zero.
    01625         2 - If directory then only the only reference can be for a stream file.
    01626         3 - Reference count must either be zero or go to zero here.
    01627
    01628     We return immediately if we are recursively entering this routine.
    01629
    01630 Arguments:
    01631
    01632     StartingFcb - This is the Fcb node in the tree to begin with.  This Fcb
    01633         must currently be acquired exclusively.
    01634
    01635     Recursive - Indicates if this call is an intentional recursion.
    01636
    01637     RemovedStartingFcb - Address to store whether we removed the starting Fcb.
    01638
    01639 Return Value:
    01640
    01641     None
    01642
    01643 --*/
    01644
    01645 {
    01646     PVCB Vcb = StartingFcb->Vcb;
    01647     PFCB CurrentFcb = StartingFcb;
    01648     BOOLEAN AcquiredCurrentFcb = FALSE;
    01649     PFCB ParentFcb = NULL;
    01650     PLCB Lcb;
    01651
    01652     PLIST_ENTRY ListLinks;
    01653     BOOLEAN Abort = FALSE;
    01654     BOOLEAN Removed;
    01655
    01656     PAGED_CODE();
    01657
    01658     //
    01659     //  Check input.
    01660     //
    01661
    01662     ASSERT_IRP_CONTEXT( IrpContext );
    01663     ASSERT_FCB( StartingFcb );
    01664
    01665     *RemovedStartingFcb = FALSE;
    01666
    01667     //
    01668     //  If this is not an intentionally recursive call we need to check if this
    01669     //  is a layered close and we're already in another instance of teardown.
    01670     //
    01671
    01672     DebugTrace(( +1, Dbg,
    01673                  "UdfTeardownStructures, StartingFcb %08x %s\n",
    01674                  StartingFcb,
    01675                  ( Recursive? "Recursive" : "Flat" )));
    01676
    01677     if (!Recursive) {
    01678
    01679         //
    01680         //  If this is a recursive call to TearDownStructures we return immediately
    01681         //  doing no operation.
    01682         //
    01683
    01684         if (FlagOn( IrpContext->TopLevel->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN )) {
    01685
    01686             return;
    01687         }
    01688
    01689         SetFlag( IrpContext->TopLevel->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN );
    01690     }
    01691
    01692     //
    01693     //  Use a try-finally to safely clear the top-level field.
    01694     //
    01695
    01696     try {
    01697
    01698         //
    01699         //  Loop until we find an Fcb we can't remove.
    01700         //
    01701
    01702         do {
    01703
    01704             //
    01705             //  See if there is an internal stream we should delete.
    01706             //  Only do this if it is the last reference on the Fcb.
    01707             //
    01708
    01709             if ((SafeNodeType( CurrentFcb ) != UDFS_NTC_FCB_DATA) &&
    01710                 (CurrentFcb->FcbUserReference == 0) &&
    01711                 (CurrentFcb->FileObject != NULL)) {
    01712
    01713                 //
    01714                 //  Go ahead and delete the stream file object.
    01715                 //
    01716
    01717                 UdfDeleteInternalStream( IrpContext, CurrentFcb );
    01718             }
    01719
    01720             //
    01721             //  If the reference count is non-zero then break.
    01722             //
    01723
    01724             if (CurrentFcb->FcbReference != 0) {
    01725
    01726                 break;
    01727             }
    01728
    01729             //
    01730             //  It looks like we have a candidate for removal here.  We
    01731             //  will need to walk the list of prefixes and delete them
    01732             //  from their parents.  If it turns out that we have multiple
    01733             //  parents of this Fcb, we are going to recursively teardown
    01734             //  on each of these.
    01735             //
    01736
    01737             for ( ListLinks = CurrentFcb->ParentLcbQueue.Flink;
    01738                   ListLinks != &CurrentFcb->ParentLcbQueue; ) {
    01739
    01740                 Lcb = CONTAINING_RECORD( ListLinks, LCB, ChildFcbLinks );
    01741
    01742                 ASSERT_LCB( Lcb );
    01743
    01744                 //
    01745                 //  We advance the pointer now because we will be toasting this guy,
    01746                 //  invalidating whatever is here.
    01747                 //
    01748
    01749                 ListLinks = ListLinks->Flink;
    01750
    01751                 //
    01752                 //  We may have multiple parents through hard links.  If the previous parent we
    01753                 //  dealt with is not the parent of this new Lcb, lets do some work.
    01754                 //
    01755
    01756                 if (ParentFcb != Lcb->ParentFcb) {
    01757
    01758                     //
    01759                     //  We need to deal with the previous parent.  It may now be the case that
    01760                     //  we deleted the last child reference and it wants to go away at this point.
    01761                     //
    01762
    01763                     if (ParentFcb) {
    01764
    01765                         //
    01766                         //  It should never be the case that we have to recurse more than one level on
    01767                         //  any teardown since no cross-linkage of directories is possible.
    01768                         //
    01769
    01770                         ASSERT( !Recursive );
    01771
    01772                         UdfTeardownStructures( IrpContext, ParentFcb, TRUE, &Removed );
    01773
    01774                         if (!Removed) {
    01775
    01776                             UdfReleaseFcb( IrpContext, ParentFcb );
    01777                         }
    01778                     }
    01779
    01780                     //
    01781                     //  Get this new parent Fcb to work on.
    01782                     //
    01783
    01784                     ParentFcb = Lcb->ParentFcb;
    01785                     UdfAcquireFcbExclusive( IrpContext, ParentFcb, FALSE );
    01786                 }
    01787
    01788                 //
    01789                 //  Lock the Vcb so we can look at references.
    01790                 //
    01791
    01792                 UdfLockVcb( IrpContext, Vcb );
    01793
    01794                 //
    01795                 //  Now check that the reference counts on the Lcb are zero.
    01796                 //
    01797
    01798                 if ( Lcb->Reference != 0 ) {
    01799
    01800                     //
    01801                     //  A create is interested in getting in here, so we should
    01802                     //  stop right now.
    01803                     //
    01804
    01805                     UdfUnlockVcb( IrpContext, Vcb );
    01806                     UdfReleaseFcb( IrpContext, ParentFcb );
    01807                     Abort = TRUE;
    01808
    01809                     break;
    01810                 }
    01811
    01812                 //
    01813                 //  Now remove this prefix and drop the references to the parent.
    01814                 //
    01815
    01816                 ASSERT( Lcb->ChildFcb == CurrentFcb );
    01817                 ASSERT( Lcb->ParentFcb == ParentFcb );
    01818
    01819                 DebugTrace(( +0, Dbg,
    01820                              "UdfTeardownStructures, Lcb %08x P %08x <-> C %08x Vcb %d/%d PFcb %d/%d CFcb %d/%d\n",
    01821                              Lcb,
    01822                              ParentFcb,
    01823                              CurrentFcb,
    01824                              Vcb->VcbReference,
    01825                              Vcb->VcbUserReference,
    01826                              ParentFcb->FcbReference,
    01827                              ParentFcb->FcbUserReference,
    01828                              CurrentFcb->FcbReference,
    01829                              CurrentFcb->FcbUserReference ));
    01830
    01831                 UdfRemovePrefix( IrpContext, Lcb );
    01832                 UdfDecrementReferenceCounts( IrpContext, ParentFcb, 1, 1 );
    01833
    01834                 DebugTrace(( +0, Dbg,
    01835                              "UdfTeardownStructures, Vcb %d/%d PFcb %d/%d\n",
    01836                              Vcb->VcbReference,
    01837                              Vcb->VcbUserReference,
    01838                              ParentFcb->FcbReference,
    01839                              ParentFcb->FcbUserReference ));
    01840
    01841                 UdfUnlockVcb( IrpContext, Vcb );
    01842             }
    01843
    01844             //
    01845             //  Now really leave if we have to.
    01846             //
    01847
    01848             if (Abort) {
    01849
    01850                 break;
    01851             }
    01852
    01853             //
    01854             //  Now that we have removed all of the prefixes of this Fcb we can make the final check.
    01855             //  Lock the Vcb again so we can inspect the child's references.
    01856             //
    01857
    01858             UdfLockVcb( IrpContext, Vcb );
    01859
    01860             if (CurrentFcb->FcbReference != 0) {
    01861
    01862                 DebugTrace(( +0, Dbg,
    01863                              "UdfTeardownStructures, saving Fcb %08x %d/%d\n",
    01864                              CurrentFcb,
    01865                              CurrentFcb->FcbReference,
    01866                              CurrentFcb->FcbUserReference ));
    01867
    01868                 //
    01869                 //  Nope, nothing more to do.  Stop right now.
    01870                 //
    01871
    01872                 UdfUnlockVcb( IrpContext, Vcb );
    01873
    01874                 if (ParentFcb != NULL) {
    01875
    01876                     UdfReleaseFcb( IrpContext, ParentFcb );
    01877                 }
    01878
    01879                 break;
    01880             }
    01881
    01882             //
    01883             //  This Fcb is toast.  Remove it from the Fcb Table as appropriate and delete.
    01884             //
    01885
    01886             if (FlagOn( CurrentFcb->FcbState, FCB_STATE_IN_FCB_TABLE )) {
    01887
    01888                 UdfDeleteFcbTable( IrpContext, CurrentFcb );
    01889                 ClearFlag( CurrentFcb->FcbState, FCB_STATE_IN_FCB_TABLE );
    01890
    01891             }
    01892
    01893             //
    01894             //  Unlock the Vcb but hold the parent in order to walk up
    01895             //  the tree.
    01896             //
    01897
    01898             DebugTrace(( +0, Dbg,
    01899                          "UdfTeardownStructures, toasting Fcb %08x %d/%d\n",
    01900                          CurrentFcb,
    01901                          CurrentFcb->FcbReference,
    01902                          CurrentFcb->FcbUserReference ));
    01903
    01904             UdfUnlockVcb( IrpContext, Vcb );
    01905             UdfDeleteFcb( IrpContext, CurrentFcb );
    01906
    01907             //
    01908             //  Move to the parent Fcb.
    01909             //
    01910
    01911             CurrentFcb = ParentFcb;
    01912             ParentFcb = NULL;
    01913             AcquiredCurrentFcb = TRUE;
    01914
    01915         } while (CurrentFcb != NULL);
    01916
    01917     } finally {
    01918
    01919         //
    01920         //  Release the current Fcb if we have acquired it.
    01921         //
    01922
    01923         if (AcquiredCurrentFcb && (CurrentFcb != NULL)) {
    01924
    01925             UdfReleaseFcb( IrpContext, CurrentFcb );
    01926         }
    01927
    01928         //
    01929         //  Clear the teardown flag.
    01930         //
    01931
    01932         if (!Recursive) {
    01933
    01934             ClearFlag( IrpContext->TopLevel->Flags, IRP_CONTEXT_FLAG_IN_TEARDOWN );
    01935         }
    01936     }
    01937
    01938     *RemovedStartingFcb = (CurrentFcb != StartingFcb);
    01939
    01940     DebugTrace(( -1, Dbg,
    01941                  "UdfTeardownStructures, RemovedStartingFcb -> %c\n",
    01942                  ( *RemovedStartingFcb? 'T' : 'F' )));
    01943
    01944     return;
    01945 }

INLINE BOOLEAN UdfUdfIdentifierContained | ( | IN PREGID | RegID,
|  | IN PSTRING | Type,
|  | IN USHORT | RevisionMin,
|  | IN USHORT | RevisionMax,
|  | IN UCHAR | OSClass,
|  | IN UCHAR | OSIdentifier
| ) |

Definition at line 2060 of file udfprocs.h.

References NULL, _UDF_SUFFIX_UDF::OSClass, OSCLASS_INVALID, _UDF_SUFFIX_UDF::OSIdentifier, OSIDENTIFIER_INVALID, UdfEqualEntityId(), and _UDF_SUFFIX_UDF::UdfRevision.

Referenced by UdfLoadSparingTables(), and UdfUpdateVcbPhase0().

    02068 {
    02069     PUDF_SUFFIX_UDF UdfSuffix = (PUDF_SUFFIX_UDF) RegID->Suffix;
    02070
    02071     return ((UdfSuffix->UdfRevision <= RevisionMax && UdfSuffix->UdfRevision >= RevisionMin) &&
    02072             (OSClass == OSCLASS_INVALID || UdfSuffix->OSClass == OSClass) &&
    02073             (OSIdentifier == OSIDENTIFIER_INVALID || UdfSuffix->OSIdentifier == OSIdentifier) &&
    02074             UdfEqualEntityId( RegID, Type, NULL ));
    02075 }

VOID UdfUninitializeVmcb | ( | IN PVMCB | Vmcb | ) |

Definition at line 325 of file vmcbsup.c.

References Dbg, DebugTrace, FsRtlUninitializeMcb(), and PAGED_CODE.

Referenced by UdfDeleteFcb().

    00331                    :
    00332
    00333     This routine uninitializes an existing VMCB structure.  After calling
    00334     this routine the input VMCB structure must be re-initialized before
    00335     being used again.
    00336
    00337 Arguments:
    00338
    00339     Vmcb - Supplies a pointer to the VMCB structure to uninitialize.
    00340
    00341 Return Value:
    00342
    00343     None.
    00344
    00345 --*/
    00346
    00347 {
    00348     PAGED_CODE();
    00349
    00350     DebugTrace(( +1, Dbg, "UdfUninitializeVmcb, Vmcb = %08x\n", Vmcb ));
    00351
    00352     //
    00353     //  Unitialize the fields in the Vmcb structure
    00354     //
    00355
    00356     FsRtlUninitializeMcb( &Vmcb->VbnIndexed );
    00357     FsRtlUninitializeMcb( &Vmcb->LbnIndexed );
    00358
    00359     //
    00360     //  And return to our caller
    00361     //
    00362
    00363     DebugTrace(( -1, Dbg, "UdfUninitializeVmcb -> VOID\n" ));
    00364
    00365     return;
    00366 }

NTSTATUS UdfUnlockVolumeInternal | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PFILE_OBJECT FileObject | OPTIONAL
| ) |

Definition at line 732 of file udfs/fsctrl.c.

References ClearFlag, FlagOn, NTSTATUS(), NULL, Status, and VCB_STATE_LOCKED.

Referenced by UdfPnpCancelRemove(), UdfPnpRemove(), and UdfUnlockVolume().

    00740                    :
    00741
    00742     This routine performs the actual unlock volume operation.
    00743
    00744     The volume must be held exclusive by the caller.
    00745
    00746 Arguments:
    00747
    00748     Vcb - The volume being locked.
    00749
    00750     FileObject - File corresponding to the handle locking the volume.  If this
    00751         is not specified, a system lock is assumed.
    00752
    00753 Return Value:
    00754
    00755     NTSTATUS - The return status for the operation
    00756
    00757     Attempting to remove a system lock that did not exist is OK.
    00758
    00759 --*/
    00760
    00761 {
    00762     NTSTATUS Status = STATUS_INVALID_PARAMETER;
    00763
    00764     if (FlagOn(Vcb->VcbState, VCB_STATE_LOCKED) && FileObject == Vcb->VolumeLockFileObject) {
    00765
    00766         ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
    00767         Vcb->VolumeLockFileObject = NULL;
    00768         Status = STATUS_SUCCESS;
    00769     }
    00770
    00771     return Status;
    00772 }

INLINE VOID UdfUpcaseName | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PUNICODE_STRING | Name,
|  | IN OUT PUNICODE_STRING | UpcaseName
| ) |

Definition at line 1131 of file udfprocs.h.

References ASSERT, FALSE, Name, NTSTATUS(), RtlUpcaseUnicodeString(), and Status.

Referenced by UdfGenerate8dot3Name(), UdfNormalizeFileNames(), and UdfUpdateDirNames().

    01139                    :
    01140
    01141     This routine upcases a name with an assertion of success.
    01142
    01143 Arguments:
    01144
    01145     Name - an name to upcase
    01146
    01147     Length - a place to put the upcased name (can be the same as Name)
    01148
    01149 Return Value:
    01150
    01151     None.
    01152
    01153 --*/
    01154
    01155 {
    01156     NTSTATUS Status;
    01157
    01158     //
    01159     //  Upcase the string using the correct upcase routine.
    01160     //
    01161
    01162     Status = RtlUpcaseUnicodeString( UpcaseName,
    01163                                      Name,
    01164                                      FALSE );
    01165
    01166     //
    01167     //  This should never fail.
    01168     //
    01169
    01170     ASSERT( Status == STATUS_SUCCESS );
    01171
    01172     return;
    01173 }

VOID UdfUpdateDirNames | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PDIR_ENUM_CONTEXT | DirContext,
|  | IN BOOLEAN | IgnoreCase
| ) |

Definition at line 360 of file dirsup.c.

References Add2Ptr, ASSERT, ASSERT_IRP_CONTEXT, BYTE_COUNT_8_DOT_3, CRC_LEN, Dbg, DebugTrace, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT, DIR_CONTEXT_FLAG_SEEN_PARENT, FALSE, FlagOn, FsRtlAllocatePoolWithTag, ISONsrFidConstantSize, Max, MAX_LEN, NSR_FID_F_PARENT, NULL, PAGED_CODE, PARENT_ENTRY, SELF_ENTRY, SetFlag, TAG_FILE_NAME, UdfCheckLegalCS0Dstring(), UdfConvertCS0DstringToUnicode(), UdfCS0DstringContainsLegalCharacters(), UdfCS0DstringUnicodeSize(), UdfFreePool(), UdfPagedPool, UdfRaiseStatus(), UdfRenderNameToLegalUnicode(), UdfUnicodeDirectoryNames, UdfUpcaseName(), and USHORT.

Referenced by UdfEnumerateIndex(), UdfFindDirEntry(), and UdfInitializeEnumeration().

    00368                    :
    00369
    00370     This routine fills in the non-short names of a directory enumeration context
    00371     for the Fid currently referenced.
    00372
    00373 Arguments:
    00374
    00375     DirContext - a corresponding context to fill in.
    00376
    00377     IgnoreCase - whether the caller wants to be insensitive to case.
    00378
    00379 Return Value:
    00380
    00381     None.
    00382
    00383 --*/
    00384
    00385 {
    00386     PUCHAR NameDstring;
    00387     BOOLEAN ContainsIllegal;
    00388
    00389     USHORT NameLength;
    00390     USHORT BufferLength;
    00391     USHORT PresentLength;
    00392
    00393     PAGED_CODE();
    00394
    00395     //
    00396     //  Check input.
    00397     //
    00398
    00399     ASSERT_IRP_CONTEXT( IrpContext );
    00400
    00401     DebugTrace(( +1, Dbg, "UdfUpdateDirNames\n" ));
    00402
    00403     //
    00404     //  Handle the case of the self directory entry.
    00405     //
    00406
    00407     if (DirContext->Fid == NULL) {
    00408
    00409         //
    00410         //  Simply synthesize
    00411         //
    00412
    00413         //
    00414         //  It doesn't hurt to be pedantic about initialization, so do it all.
    00415         //
    00416
    00417         DirContext->PureObjectName.Length =
    00418         DirContext->CaseObjectName.Length =
    00419         DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[SELF_ENTRY].Length;
    00420
    00421         DirContext->PureObjectName.MaximumLength =
    00422         DirContext->CaseObjectName.MaximumLength =
    00423         DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[SELF_ENTRY].MaximumLength;
    00424
    00425         DirContext->PureObjectName.Buffer =
    00426         DirContext->CaseObjectName.Buffer =
    00427         DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[SELF_ENTRY].Buffer;
    00428
    00429         //
    00430         //  All done.
    00431         //
    00432
    00433         DebugTrace((  0, Dbg, "Self Entry case\n" ));
    00434         DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
    00435
    00436         return;
    00437     }
    00438
    00439     //
    00440     //  Handle the case of the parent directory entry.
    00441     //
    00442
    00443     if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_PARENT )) {
    00444
    00445         //
    00446         //  Parent entries must occur at the front of the directory and
    00447         //  have a fid length of zero (13346 4/14.4.4).
    00448         //
    00449
    00450         if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT ) ||
    00451             DirContext->Fid->FileIDLen != 0) {
    00452
    00453             UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    00454         }
    00455
    00456         //
    00457         //  Note that we have seen the parent entry.
    00458         //
    00459
    00460         SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT );
    00461
    00462         //
    00463         //  It doesn't hurt to be pedantic about initialization, so do it all.
    00464         //
    00465
    00466         DirContext->PureObjectName.Length =
    00467         DirContext->CaseObjectName.Length =
    00468         DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[PARENT_ENTRY].Length;
    00469
    00470         DirContext->PureObjectName.MaximumLength =
    00471         DirContext->CaseObjectName.MaximumLength =
    00472         DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[PARENT_ENTRY].MaximumLength;
    00473
    00474         DirContext->PureObjectName.Buffer =
    00475         DirContext->CaseObjectName.Buffer =
    00476         DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[PARENT_ENTRY].Buffer;
    00477
    00478         //
    00479         //  All done.
    00480         //
    00481
    00482         DebugTrace((  0, Dbg, "Parent Entry case\n" ));
    00483         DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
    00484
    00485         return;
    00486     }
    00487
    00488     //
    00489     //  We now know that we will need to convert the name in a real FID, so figure out where
    00490     //  it sits in the descriptor.
    00491     //
    00492
    00493     NameDstring = Add2Ptr( DirContext->Fid, ISONsrFidConstantSize + DirContext->Fid->ImpUseLen, PUCHAR );
    00494
    00495     //
    00496     //  Every directory must record a parent entry.
    00497     //
    00498
    00499     if (!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT)) {
    00500
    00501         UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    00502     }
    00503
    00504     //
    00505     //  Note that we are proceeding into the non-constant portion of a directory.
    00506     //
    00507
    00508     SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT );
    00509
    00510     //
    00511     //  Make sure the dstring is good CS0
    00512     //
    00513
    00514     UdfCheckLegalCS0Dstring( IrpContext,
    00515                              NameDstring,
    00516                              DirContext->Fid->FileIDLen,
    00517                              0,
    00518                              FALSE );
    00519
    00520     //
    00521     //  Don't bother allocating tiny buffers - always make sure we get enough for an 8.3 name.
    00522     //
    00523
    00524     BufferLength =
    00525     NameLength = Max( BYTE_COUNT_8_DOT_3, UdfCS0DstringUnicodeSize( IrpContext,
    00526                                                                     NameDstring,
    00527                                                                     DirContext->Fid->FileIDLen) );
    00528
    00529     //
    00530     //  Illegality is both actual illegal characters and too many characters.
    00531     //
    00532
    00533     ContainsIllegal = (!UdfCS0DstringContainsLegalCharacters( NameDstring, DirContext->Fid->FileIDLen ) ||
    00534                        (NameLength / sizeof( WCHAR )) > MAX_LEN);
    00535
    00536
    00537     //
    00538     //  If we're illegal, we will need more characters to hold the uniqifying stamp.
    00539     //
    00540
    00541     if (ContainsIllegal) {
    00542
    00543         BufferLength = (NameLength += (CRC_LEN * sizeof(WCHAR)));
    00544     }
    00545
    00546
    00547     //
    00548     //  If we need to build a case insensitive name, need more space.
    00549     //
    00550
    00551     if (IgnoreCase) {
    00552
    00553         BufferLength += NameLength;
    00554     }
    00555
    00556     //
    00557     //  If we need to render the names due to illegal characters, more space again.
    00558     //
    00559
    00560     if (ContainsIllegal) {
    00561
    00562         BufferLength += NameLength;
    00563
    00564     } else {
    00565
    00566         //
    00567         //  Make sure the names aren't seperated. If more illegal names are found we can
    00568         //  resplit the buffer but until then avoid the expense of having to copy bytes
    00569         //  ... odds are that illegal characters are going to be a rarish occurance.
    00570         //
    00571
    00572         DirContext->PureObjectName.Buffer = DirContext->ObjectName.Buffer;
    00573     }
    00574
    00575     DebugTrace(( 0, Dbg,
    00576                  "Ob %s%sneeds %d bytes (%d byte chunks), have %d\n",
    00577                  (IgnoreCase? "Ic " : ""),
    00578                  (ContainsIllegal? "Ci " : ""),
    00579                  BufferLength,
    00580                  NameLength,
    00581                  DirContext->AllocLength ));
    00582
    00583     //
    00584     //  Check if we need more space for the names.  We will need more if the name size is greater
    00585     //  than the maximum we can currently store, or if we have stumbled across illegal characters
    00586     //  and the current Pure name is not seperated from the exposed Object name.
    00587     //
    00588     //  Note that IgnoreCase remains constant across usage of a context so we don't have to wonder
    00589     //  if it has been seperated from the ObjectName - it'll always be correct.
    00590     //
    00591
    00592     if ((NameLength > DirContext->ObjectName.MaximumLength) ||
    00593         (ContainsIllegal && DirContext->ObjectName.Buffer == DirContext->PureObjectName.Buffer)) {
    00594
    00595         DebugTrace(( 0, Dbg, "Resizing buffers\n" ));
    00596
    00597         //
    00598         //  For some reason the sizing is not good for the current name we have to unroll.  Figure
    00599         //  out if we can break up the current allocation in a different way before falling back
    00600         //  to a new allocation.
    00601         //
    00602
    00603         if (DirContext->AllocLength >= BufferLength) {
    00604
    00605             //
    00606             //  So we can still use the current allocation.  Chop it up into the required number
    00607             //  of chunks.
    00608             //
    00609
    00610             DirContext->PureObjectName.MaximumLength =
    00611             DirContext->CaseObjectName.MaximumLength =
    00612             DirContext->ObjectName.MaximumLength = DirContext->AllocLength / (1 +
    00613                                                                               (IgnoreCase? 1 : 0) +
    00614                                                                               (ContainsIllegal? 1 : 0));
    00615
    00616             DebugTrace(( 0, Dbg,
    00617                          "... by resplit into %d byte chunks\n",
    00618                          DirContext->ObjectName.MaximumLength ));
    00619
    00620             //
    00621             //  Set the buffer pointers up.  Required adjustment will occur below.
    00622             //
    00623
    00624             DirContext->PureObjectName.Buffer =
    00625             DirContext->CaseObjectName.Buffer =
    00626             DirContext->ObjectName.Buffer = DirContext->NameBuffer;
    00627
    00628         } else {
    00629
    00630             DebugTrace(( 0, Dbg, "... by allocating new pool\n" ));
    00631
    00632             //
    00633             //  Oh well, no choice but to fall back into the pool.  Drop our previous hunk.
    00634             //
    00635
    00636             UdfFreePool( &DirContext->NameBuffer );
    00637             DirContext->AllocLength = 0;
    00638
    00639             //
    00640             //  The names share an allocation for efficiency.
    00641             //
    00642
    00643             DirContext->PureObjectName.MaximumLength =
    00644             DirContext->CaseObjectName.MaximumLength =
    00645             DirContext->ObjectName.MaximumLength = NameLength;
    00646
    00647             DirContext->NameBuffer =
    00648             DirContext->PureObjectName.Buffer =
    00649             DirContext->CaseObjectName.Buffer =
    00650             DirContext->ObjectName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool,
    00651                                                                       BufferLength,
    00652                                                                       TAG_FILE_NAME );
    00653
    00654             DirContext->AllocLength = BufferLength;
    00655         }
    00656
    00657         //
    00658         //  In the presence of the "as appropriate" names, adjust the buffer locations.  Note
    00659         //  that ObjectName.Buffer is always the base of the allocated space.
    00660         //
    00661
    00662         if (IgnoreCase) {
    00663
    00664             DirContext->CaseObjectName.Buffer = Add2Ptr( DirContext->ObjectName.Buffer,
    00665                                                          DirContext->ObjectName.MaximumLength,
    00666                                                          PWCHAR );
    00667         }
    00668
    00669         if (ContainsIllegal) {
    00670
    00671             DirContext->PureObjectName.Buffer = Add2Ptr( DirContext->CaseObjectName.Buffer,
    00672                                                          DirContext->CaseObjectName.MaximumLength,
    00673                                                          PWCHAR );
    00674         }
    00675     }
    00676
    00677     ASSERT( BufferLength <= DirContext->AllocLength );
    00678
    00679     //
    00680     //  Convert the dstring.
    00681     //
    00682
    00683     UdfConvertCS0DstringToUnicode( IrpContext,
    00684                                    NameDstring,
    00685                                    DirContext->Fid->FileIDLen,
    00686                                    0,
    00687                                    &DirContext->PureObjectName );
    00688
    00689     //
    00690     //  If illegal characters were present, run the name through the UDF transmogrifier.
    00691     //
    00692
    00693     if (ContainsIllegal) {
    00694
    00695         UdfRenderNameToLegalUnicode( IrpContext,
    00696                                      &DirContext->PureObjectName,
    00697                                      &DirContext->ObjectName );
    00698
    00699     //
    00700     //  The ObjectName is the same as the PureObjectName.
    00701     //
    00702
    00703     } else {
    00704
    00705         DirContext->ObjectName.Length = DirContext->PureObjectName.Length;
    00706     }
    00707
    00708     //
    00709     //  Upcase the result if required.
    00710     //
    00711
    00712     if (IgnoreCase) {
    00713
    00714         UdfUpcaseName( IrpContext,
    00715                        &DirContext->ObjectName,
    00716                        &DirContext->CaseObjectName );
    00717     }
    00718
    00719     DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
    00720
    00721     return;
    00722 }

VOID UdfUpdateTimestampsFromIcbContext | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PICB_SEARCH_CONTEXT | IcbContext,
|  | IN PTIMESTAMP_BUNDLE | Timestamps
| ) |

Definition at line 3595 of file udfs/strucsup.c.

References ICBFILE::AccessTime, ASSERT, ASSERT_IRP_CONTEXT, ICBFILE::Destag, DESTAG_ID_NSR_FILE, _EA_SEARCH_CONTEXT::Ea, EA_FILETIMES_E_CREATION, EA_INFOTIMES_E_CREATION, EA_INFOTIMES_E_MODIFICATION, EA_SUBTYPE_BASE, EA_TYPE_FILETIMES, EA_TYPE_INFOTIMES, NSR_EA_FILETIMES::Existence, FALSE, FlagOn, DESTAG::Ident, ICBFILE::ModifyTime, PAGED_CODE, PNSR_EA_FILETIMES, PTIMESTAMP_BUNDLE, NSR_EA_FILETIMES::Stamps, TRUE, UdfConvertUdfTimeToNtTime(), UdfInitializeEaContext(), and UdfLookupEa().

Referenced by UdfInitializeFcbFromIcbContext(), and UdfQueryDirectory().

    03603                    :
    03604
    03605     This routine converts the set of timestamps associated with a given ICB into
    03606     an NT native form.
    03607
    03608 Arguments:
    03609
    03610     IcbOontext - An search context containing the active direct ICB for the object
    03611
    03612     Timestamps - the bundle of timestamps to receive the converted times.
    03613
    03614 Return Value:
    03615
    03616     None.
    03617
    03618 --*/
    03619
    03620 {
    03621     EA_SEARCH_CONTEXT EaContext;
    03622     PICBFILE Icb;
    03623
    03624     PAGED_CODE();
    03625
    03626     //
    03627     //  Check inputs
    03628     //
    03629
    03630     ASSERT_IRP_CONTEXT( IrpContext );
    03631
    03632     //
    03633     //  Directly reference for convenience.
    03634     //
    03635
    03636     Icb = IcbContext->Active.View;
    03637
    03638     ASSERT( Icb->Destag.Ident == DESTAG_ID_NSR_FILE );
    03639
    03640     //
    03641     //  Initialize the timestamps for this object.  Due to basic idiocy in ISO 13346,
    03642     //  we must gather EAs and figure out which of several timestamps is most valid.
    03643     //
    03644
    03645     //
    03646     //  Begin by using the fields in the ICB itself.
    03647     //
    03648
    03649     UdfConvertUdfTimeToNtTime( IrpContext,
    03650                                &Icb->ModifyTime,
    03651                                (PLARGE_INTEGER) &Timestamps->ModificationTime );
    03652
    03653     Timestamps->CreationTime = Timestamps->ModificationTime;
    03654
    03655     UdfConvertUdfTimeToNtTime( IrpContext,
    03656                                &Icb->AccessTime,
    03657                                (PLARGE_INTEGER) &Timestamps->AccessTime );
    03658
    03659     //
    03660     //  Gather the File Times and Information Times EAs for this object, if they exist,
    03661     //  and set the timestamps.  Just override timestamps if they exist.
    03662     //
    03663
    03664     UdfInitializeEaContext( IrpContext,
    03665                             &EaContext,
    03666                             IcbContext,
    03667                             EA_TYPE_FILETIMES,
    03668                             EA_SUBTYPE_BASE );
    03669
    03670     if (UdfLookupEa( IrpContext, &EaContext )) {
    03671
    03672         PNSR_EA_FILETIMES FileTimes = EaContext.Ea;
    03673
    03674         if (FlagOn(FileTimes->Existence, EA_FILETIMES_E_CREATION)) {
    03675
    03676             UdfConvertUdfTimeToNtTime( IrpContext,
    03677                                        &FileTimes->Stamps[0],
    03678                                        (PLARGE_INTEGER) &Timestamps->CreationTime );
    03679         }
    03680     }
    03681
    03682     UdfInitializeEaContext( IrpContext,
    03683                             &EaContext,
    03684                             IcbContext,
    03685                             EA_TYPE_INFOTIMES,
    03686                             EA_SUBTYPE_BASE );
    03687
    03688     if (UdfLookupEa( IrpContext, &EaContext )) {
    03689
    03690         PNSR_EA_FILETIMES InfoTimes = EaContext.Ea;
    03691         BOOLEAN CreationPresent = FALSE;
    03692
    03693         if (FlagOn(InfoTimes->Existence, EA_INFOTIMES_E_CREATION)) {
    03694
    03695             UdfConvertUdfTimeToNtTime( IrpContext,
    03696                                        &InfoTimes->Stamps[0],
    03697                                        (PLARGE_INTEGER) &Timestamps->CreationTime );
    03698
    03699             CreationPresent = TRUE;
    03700         }
    03701
    03702         if (FlagOn(InfoTimes->Existence, EA_INFOTIMES_E_MODIFICATION)) {
    03703
    03704             UdfConvertUdfTimeToNtTime( IrpContext,
    03705                                        &InfoTimes->Stamps[CreationPresent? 1: 0],
    03706                                        (PLARGE_INTEGER) &Timestamps->CreationTime );
    03707         }
    03708     }
    03709 }

VOID UdfUpdateVcbPhase0 | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PVCB | Vcb
| ) |

Definition at line 477 of file udfs/strucsup.c.

References _ICB_SEARCH_CONTEXT::Active, ANCHOR_SECTOR, ASSERT, ASSERT_IRP_CONTEXT, ASSERT_VCB, BlocksFromSectors, BlockSize, CcMapData(), CcPurgeCacheSection(), CcSetFileSizes(), Dbg, DebugTrace, DebugUnwind, DESTAG_ID_NSR_FILE, ExFreePool(), FALSE, FCB_STATE_INITIALIZED, FCB_STATE_VMCB_MAPPING, FlagOn, FsRtlAllocatePoolWithTag, ICB_SEARCH_CONTEXT, ICBTAG_FILE_T_NOTSPEC, _MAPPED_PVIEW::Lbn, LlBytesFromSectors, LlSectorAlign, LongOffset, NT_SUCCESS, NULL, Offset, OSCLASS_INVALID, OSIDENTIFIER_INVALID, PAGED_CODE, _MAPPED_PVIEW::Partition, PCB_FLAG_VIRTUAL_PARTITION, PDESTAG, PFILE_ID, Physical, PICBFILE, PREGID, SectorSize, SetFlag, TAG_NSR_VDSD, TRUE, UDF_CDUDF_MAXIMUM_VAT_SIZE, UDF_CDUDF_MINIMUM_VAT_SIZE, UDF_CDUDF_TRAILING_DATA_SIZE, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, UdfCleanupIcbContext(), UdfCreateFcb(), UdfCreateInternalStream(), UdfIncrementReferenceCounts, UdfInitializeAllocations(), UdfInitializeVmcb(), UdfLockFcb, UdfLockVcb, UdfLookupMetaVsnOfExtent(), UdfPagedPool, UdfRaiseStatus(), UdfRawBufferSize(), UdfRawReadSize(), UdfReadSectors(), UdfResetVmcb(), UDFS_CDUDF_RESIDUAL_REFERENCE, UDFS_CDUDF_RESIDUAL_USER_REFERENCE, UDFS_NTC_FCB_INDEX, UdfUdfIdentifierContained(), UdfUnlockFcb, UdfUnlockVcb, UdfUnpinData, UdfVatTableIdentifier, UdfVerifyDescriptor(), USHORT, _MAPPED_PVIEW::View, and Virtual.

Referenced by UdfMountVolume().

    00484                    :
    00485
    00486     This routine is called to perform the initial spinup of the volume so that
    00487     we can do reads into it.  Primarily, this is required since virtual partitions
    00488     make us lift the remapping table, and the final sets of descriptors from the volume
    00489     can be off in these virtual partitions.
    00490
    00491     So, we need to get everything set up to read.
    00492
    00493 Arguments:
    00494
    00495     Vcb - Vcb for the volume being mounted.  We have already set up and completed
    00496         the Pcb.
    00497
    00498 Return Value:
    00499
    00500     None
    00501
    00502 --*/
    00503
    00504 {
    00505     ICB_SEARCH_CONTEXT IcbContext;
    00506
    00507     LONGLONG FileId = 0;
    00508
    00509     PICBFILE VatIcb = NULL;
    00510     PREGID RegId;
    00511     ULONG ThisPass;
    00512     ULONG Psn;
    00513     ULONG Vsn;
    00514     ULONG Lbn;
    00515     ULONG SectorCount;
    00516     USHORT Reference;
    00517
    00518     BOOLEAN UnlockVcb = FALSE;
    00519     BOOLEAN CleanupIcbContext = FALSE;
    00520
    00521     PBCB Bcb = NULL;
    00522     LARGE_INTEGER Offset;
    00523
    00524     PAGED_CODE();
    00525
    00526     //
    00527     //  Check input.
    00528     //
    00529
    00530     ASSERT_IRP_CONTEXT( IrpContext );
    00531     ASSERT_VCB( Vcb );
    00532
    00533     DebugTrace(( +1, Dbg, "UdfUpdateVcbPhase0, Vcb %08x\n", Vcb ));
    00534
    00535     try {
    00536
    00538         //
    00539         //  Create the Metadata Fcb and refererence it and the Vcb.
    00540         //
    00542
    00543         UdfLockVcb( IrpContext, Vcb );
    00544         UnlockVcb = TRUE;
    00545
    00546         Vcb->MetadataFcb = UdfCreateFcb( IrpContext,
    00547                                          *((PFILE_ID) &FileId),
    00548                                          UDFS_NTC_FCB_INDEX,
    00549                                          NULL );
    00550
    00551         UdfIncrementReferenceCounts( IrpContext, Vcb->MetadataFcb, 1, 1 );
    00552         UdfUnlockVcb( IrpContext, Vcb );
    00553         UnlockVcb = FALSE;
    00554
    00555         //
    00556         //  The metadata stream is grown lazily as we reference disk structures.
    00557         //
    00558
    00559         Vcb->MetadataFcb->FileSize.QuadPart =
    00560         Vcb->MetadataFcb->ValidDataLength.QuadPart =
    00561         Vcb->MetadataFcb->AllocationSize.QuadPart = 0;
    00562
    00563         //
    00564         //  Initialize the volume Vmcb
    00565         //
    00566
    00567         UdfLockFcb( IrpContext, Vcb->MetadataFcb );
    00568
    00569         UdfInitializeVmcb( &Vcb->Vmcb,
    00570                            UdfPagedPool,
    00571                            MAXULONG,
    00572                            SectorSize(Vcb) );
    00573
    00574         UdfUnlockFcb( IrpContext, Vcb->MetadataFcb );
    00575
    00576         //
    00577         //  Point to the file resource and set the flag that will cause mappings
    00578         //  to go through the Vmcb
    00579         //
    00580
    00581         Vcb->MetadataFcb->Resource = &Vcb->FileResource;
    00582
    00583         SetFlag( Vcb->MetadataFcb->FcbState, FCB_STATE_VMCB_MAPPING | FCB_STATE_INITIALIZED );
    00584
    00585         //
    00586         //  Create the stream file for this.
    00587         //
    00588
    00589         UdfCreateInternalStream( IrpContext, Vcb, Vcb->MetadataFcb );
    00590
    00592         //
    00593         //  If this is a volume containing a virtual partition, set up the
    00594         //  Virtual Allocation Table Fcb and adjust the residual reference
    00595         //  counts comensurately.
    00596         //
    00598
    00599         if (FlagOn( Vcb->Pcb->Flags, PCB_FLAG_VIRTUAL_PARTITION )) {
    00600
    00601             DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, handling VAT setup\n" ));
    00602
    00603             //
    00604             //  Now if some dummy has stuck us in the situation of not giving us
    00605             //  the tools to figure out where the end of the media is, tough luck.
    00606             //
    00607
    00608             if (!Vcb->BoundN || Vcb->BoundN < ANCHOR_SECTOR) {
    00609
    00610                 DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, no end bound was discoverable!\n" ));
    00611
    00612                 UdfRaiseStatus( IrpContext, STATUS_UNRECOGNIZED_VOLUME );
    00613             }
    00614
    00615             //
    00616             //  We take care of this first since the residuals must be in place
    00617             //  if we raise while finding the VAT, else we will get horribly
    00618             //  confused when the in-progress references are seen.  We will think
    00619             //  that the extra real referenes are indications that the volume can't
    00620             //  be dismounted.
    00621             //
    00622
    00623             Vcb->VcbResidualReference += UDFS_CDUDF_RESIDUAL_REFERENCE;
    00624             Vcb->VcbResidualUserReference += UDFS_CDUDF_RESIDUAL_USER_REFERENCE;
    00625
    00626             Vcb->VcbReference += UDFS_CDUDF_RESIDUAL_REFERENCE;
    00627
    00628             //
    00629             //  Now, we need to hunt about for the VAT ICB.  This is defined, on
    00630             //  closed media (meaning that the sessions have been finalized for use
    00631             //  in CDROM drives), to be in the very last information sector on the
    00632             //  media.  Complicating this simple picture is that CDROMs tell us the
    00633             //  "last sector" by telling us where the start of the leadout area is,
    00634             //  not where the end of the informational sectors are.  This is an
    00635             //  important distinction because any combination of the following can
    00636             //  be used in closing a CDROM session: 2 runout sectors, and/or 150
    00637             //  sectors (2 seconds) of postgap, or nothing.  Immediately after these
    00638             //  "closing" writes is where the leadout begins.
    00639             //
    00640             //  Runout is usually found on CD-E media and corresponds to the time it
    00641             //  will take to turn the writing laser off.  Postgap is what is used to
    00642             //  generate audio pauses.  It is easy to see that the kind of media and
    00643             //  kind of mastering tool/system used will affect us here.  There is no
    00644             //  way to know either ahead of time.
    00645             //
    00646             //  So, finally, these are the offsets from our previously discovered
    00647             //  bounding information where we might find the last information sector:
    00648             //
    00649             //          -152    runout + postgap
    00650             //          -150    postgap
    00651             //          -2      runout
    00652             //          0       nothing
    00653             //
    00654             //  We must search these from low to high since it is extrememly expensive
    00655             //  to guess wrong - CDROMs will sit there for tens of seconds trying to
    00656             //  read unwritten/unreadable sectors.  Hopefully we will find the VAT
    00657             //  ICB beforehand.
    00658             //
    00659             //  This should all be highly disturbing.
    00660             //
    00661
    00662             VatIcb = FsRtlAllocatePoolWithTag( UdfPagedPool,
    00663                                                UdfRawBufferSize( Vcb, BlockSize( Vcb )),
    00664                                                TAG_NSR_VDSD);
    00665
    00666             for (ThisPass = 0; ThisPass < 4; ThisPass++) {
    00667
    00668                 //
    00669                 //  Lift the appropriate sector.  The discerning reader will be confused that
    00670                 //  this is done in sector terms, not block.  So is the implementor.
    00671                 //
    00672
    00673                 Psn = Vcb->BoundN - ( ThisPass == 0? 152 :
    00674                                     ( ThisPass == 1? 150 :
    00675                                     ( ThisPass == 2? 2 : 0 )));
    00676
    00677                 DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, looking at Psn 0x%08x\n", Psn ));
    00678
    00679                 //
    00680                 //  Now, try to figure out what physical partition this sector lives in so
    00681                 //  that we can eventually establish workable metadata mappings to it and
    00682                 //  dereference short allocation descriptors it may use.
    00683                 //
    00684
    00685                 for (Reference = 0;
    00686                      Reference < Vcb->Pcb->Partitions;
    00687                      Reference++) {
    00688
    00689                     if (Vcb->Pcb->Partition[Reference].Type == Physical &&
    00690                         Vcb->Pcb->Partition[Reference].Physical.Start <= Psn &&
    00691                         Vcb->Pcb->Partition[Reference].Physical.Start +
    00692                         Vcb->Pcb->Partition[Reference].Physical.Length > Psn) {
    00693
    00694                         break;
    00695                     }
    00696                 }
    00697
    00698                 //
    00699                 //  If this sector is not contained in a partition, we do not
    00700                 //  need to look at it.
    00701                 //
    00702
    00703                 if (Reference == Vcb->Pcb->Partitions) {
    00704
    00705                     DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... but it isn't in a partition.\n" ));
    00706
    00707                     continue;
    00708                 }
    00709
    00710                 DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... in partition Ref %u.\n",  Reference ));
    00711
    00712                 //
    00713                 //  We must locate the Lbn of this Psn by figuring out the offset of it
    00714                 //  in the partition we already know that it is recorded in.
    00715                 //
    00716
    00717                 Lbn = BlocksFromSectors( Vcb, Psn - Vcb->Pcb->Partition[Reference].Physical.Start );
    00718
    00719                 if (!NT_SUCCESS( UdfReadSectors( IrpContext,
    00720                                                  LlBytesFromSectors( Vcb, Psn ),
    00721                                                  UdfRawReadSize( Vcb, BlockSize( Vcb )),
    00722                                                  TRUE,
    00723                                                  VatIcb,
    00724                                                  Vcb->TargetDeviceObject ))) {
    00725
    00726                     DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... but couldn't read it.\n" ));
    00727
    00728                     continue;
    00729                 }
    00730
    00731                 //
    00732                 //  First make sure this looks vageuly like a file entry.
    00733                 //
    00734
    00735                 if (!UdfVerifyDescriptor( IrpContext,
    00736                                           (PDESTAG) VatIcb,
    00737                                           DESTAG_ID_NSR_FILE,
    00738                                           BlockSize( Vcb ),
    00739                                           Lbn,
    00740                                           TRUE )) {
    00741
    00742                     DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... but it didn't verify.\n" ));
    00743
    00744                     continue;
    00745                 }
    00746
    00747                 //
    00748                 //  Make sure this is a NOTSPEC object.  We can also presume that a VAT isn't
    00749                 //  linked into any directory, so it would be surprising if the link count was
    00750                 //  nonzero.
    00751                 //
    00752
    00753                 if (VatIcb->Icbtag.FileType != ICBTAG_FILE_T_NOTSPEC ||
    00754                     VatIcb->LinkCount) {
    00755
    00756                     DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... but the type/linkcount is wrong.\n" ));
    00757
    00758                     continue;
    00759                 }
    00760
    00761                 //
    00762                 //  The VAT must be at least large enough to contain the required information and
    00763                 //  be a multiple of 4byte elements in length.  We also have defined a sanity upper
    00764                 //  bound beyond which we never expect to see a VAT go.
    00765                 //
    00766
    00767                 ASSERT( !LongOffset( UDF_CDUDF_MINIMUM_VAT_SIZE ));
    00768
    00769                 if (VatIcb->InfoLength < UDF_CDUDF_MINIMUM_VAT_SIZE ||
    00770                     VatIcb->InfoLength > UDF_CDUDF_MAXIMUM_VAT_SIZE ||
    00771                     LongOffset( VatIcb->InfoLength )) {
    00772
    00773                     DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... but the size looks pretty bogus.\n" ));
    00774
    00775                     continue;
    00776                 }
    00777
    00778                 //
    00779                 //  At this point we have to take a wild guess that this will be the guy.  Since the only
    00780                 //  way to be sure is to look at the very end of the file an look for the regid, we've got
    00781                 //  to go map this thing.
    00782                 //
    00783
    00784                 //
    00785                 //  This is pretty ugly, but we have to cobble this maybe-Icb into the metadata stream
    00786                 //  so that initialization/use is possible (embedded data!).  Normally regular Icb searches
    00787                 //  would have done this for us, but since we have to go through such an amusing search
    00788                 //  procedure that isn't possible.  So, add it as a single sector mapping.
    00789                 //
    00790                 //  Since this lives in a partition, we can just do the "lookup" in the metadata stream.
    00791                 //  If we did not have this guarantee, we'd need to do a bit more of this by hand.
    00792                 //
    00793                 //  As this is at mount time, we are very sure we are the only person messing with the
    00794                 //  metadata stream.
    00795                 //
    00796
    00797                 //
    00798                 //  Zap the previous mapping and invalidate the metadata and VAT stream content.
    00799                 //
    00800
    00801                 if (Vcb->VatFcb) {
    00802
    00803                     UdfResetVmcb( &Vcb->Vmcb );
    00804
    00805                     UdfUnpinData( IrpContext, &Bcb );
    00806
    00807                     CcPurgeCacheSection( Vcb->MetadataFcb->FileObject->SectionObjectPointer,
    00808                                          NULL,
    00809                                          0,
    00810                                          FALSE );
    00811
    00812                     CcPurgeCacheSection( Vcb->VatFcb->FileObject->SectionObjectPointer,
    00813                                          NULL,
    00814                                          0,
    00815                                          FALSE );
    00816                 }
    00817
    00818                 Vsn = UdfLookupMetaVsnOfExtent( IrpContext,
    00819                                                 Vcb,
    00820                                                 Reference,
    00821                                                 Lbn,
    00822                                                 BlockSize( Vcb ),
    00823                                                 TRUE );
    00824
    00825                 if (Vcb->VatFcb == NULL) {
    00826
    00827                     //
    00828                     //  Now stamp out the Fcb.
    00829                     //
    00830
    00831                     UdfLockVcb( IrpContext, Vcb );
    00832                     UnlockVcb = TRUE;
    00833
    00834                     Vcb->VatFcb = UdfCreateFcb( IrpContext,
    00835                                                 *((PFILE_ID) &FileId),
    00836                                                 UDFS_NTC_FCB_INDEX,
    00837                                                 NULL );
    00838
    00839                     UdfIncrementReferenceCounts( IrpContext, Vcb->VatFcb, 1, 1 );
    00840                     UdfUnlockVcb( IrpContext, Vcb );
    00841                     UnlockVcb = FALSE;
    00842
    00843                     //
    00844                     //  Point to the file resource and set the flag that will cause mappings
    00845                     //  to go through the Vmcb
    00846                     //
    00847
    00848                     Vcb->VatFcb->Resource = &Vcb->FileResource;
    00849                 }
    00850
    00851                 //
    00852                 //  Now size and try to pick up all of the allocation descriptors for this guy.
    00853                 //  We're going to need to conjure an IcbContext for this.
    00854                 //
    00855
    00856                 Vcb->VatFcb->AllocationSize.QuadPart = LlSectorAlign( Vcb, VatIcb->InfoLength );
    00857
    00858                 Vcb->VatFcb->FileSize.QuadPart =
    00859                 Vcb->VatFcb->ValidDataLength.QuadPart = VatIcb->InfoLength;
    00860
    00861                 //
    00862                 //  Clean out any previous failed attempts.
    00863                 //
    00864
    00865                 if (CleanupIcbContext) {
    00866
    00867                     UdfCleanupIcbContext( IrpContext, &IcbContext );
    00868
    00869                 } else {
    00870
    00871                     RtlZeroMemory( &IcbContext, sizeof( ICB_SEARCH_CONTEXT ));
    00872                 }
    00873
    00874                 //
    00875                 //  Now construct the ICB search context we would have had
    00876                 //  made in the process of normal ICB discovery.  Since we
    00877                 //  were unable to do that, gotta do it by hand.
    00878                 //
    00879
    00880                 IcbContext.Active.View = (PVOID) VatIcb;
    00881                 IcbContext.Active.Partition = Reference;
    00882                 IcbContext.Active.Lbn = Lbn;
    00883                 CleanupIcbContext = TRUE;
    00884
    00885                 UdfInitializeAllocations( IrpContext,
    00886                                           Vcb->VatFcb,
    00887                                           &IcbContext );
    00888
    00889                 //
    00890                 //  Create or resize the stream file for the VAT as appropriate.
    00891                 //
    00892
    00893                 if (!FlagOn( Vcb->VatFcb->FcbState, FCB_STATE_INITIALIZED )) {
    00894
    00895                     UdfCreateInternalStream( IrpContext, Vcb, Vcb->VatFcb );
    00896                     SetFlag( Vcb->VatFcb->FcbState, FCB_STATE_INITIALIZED );
    00897
    00898                 } else {
    00899
    00900                     CcSetFileSizes( Vcb->VatFcb->FileObject, (PCC_FILE_SIZES) &Vcb->VatFcb->AllocationSize );
    00901                 }
    00902
    00903                 //
    00904                 //  To complete VAT discovery, we now look for the regid at the end of the stream
    00905                 //  that will definitively tell us that this is really a VAT.  Bias from the back
    00906                 //  by the previous VAT pointer and the regid itself.  We already know the stream
    00907                 //  is big enough by virtue of our preliminary sanity checks.
    00908                 //
    00909
    00910                 Offset.QuadPart = Vcb->VatFcb->FileSize.QuadPart - UDF_CDUDF_TRAILING_DATA_SIZE;
    00911
    00912                 CcMapData( Vcb->VatFcb->FileObject,
    00913                            &Offset,
    00914                            sizeof(REGID),
    00915                            TRUE,
    00916                            &Bcb,
    00917                            &RegId );
    00918
    00919                 if (!UdfUdfIdentifierContained( RegId,
    00920                                                 &UdfVatTableIdentifier,
    00921                                                 UDF_VERSION_150,
    00922                                                 UDF_VERSION_RECOGNIZED,
    00923                                                 OSCLASS_INVALID,
    00924                                                 OSIDENTIFIER_INVALID )) {
    00925
    00926                     //
    00927                     //  Oh well, no go here.
    00928                     //
    00929
    00930                     continue;
    00931                 }
    00932
    00933                 //
    00934                 //  Got it!
    00935                 //
    00936
    00937                 break;
    00938             }
    00939
    00940             //
    00941             //  If we didn't find anything ...
    00942             //
    00943
    00944             if (ThisPass == 4) {
    00945
    00946                 DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... and so we didn't find a VAT!\n" ));
    00947
    00948                 UdfRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
    00949             }
    00950
    00951             //
    00952             //  Go find the virtual reference so we can further update the Pcb
    00953             //  with information from the VAT.
    00954             //
    00955
    00956             for (Reference = 0;
    00957                  Reference < Vcb->Pcb->Partitions;
    00958                  Reference++) {
    00959
    00960                 if (Vcb->Pcb->Partition[Reference].Type == Virtual) {
    00961
    00962                     break;
    00963                 }
    00964             }
    00965
    00966             ASSERT( Reference < Vcb->Pcb->Partitions );
    00967
    00968             //
    00969             //  We note the length so we can easily do bounds checking for
    00970             //  virtual mappings.
    00971             //
    00972
    00973             Offset.QuadPart = (Vcb->VatFcb->FileSize.QuadPart -
    00974                                UDF_CDUDF_TRAILING_DATA_SIZE) / sizeof(ULONG);
    00975
    00976             ASSERT( Offset.HighPart == 0 );
    00977             Vcb->Pcb->Partition[Reference].Virtual.Length = Offset.LowPart;
    00978
    00979             DebugTrace(( 0, Dbg, "UdfUpdateVcbPhase0, ... got it!\n" ));
    00980         }
    00981
    00982     } finally {
    00983
    00984         DebugUnwind( "UdfUpdateVcbPhase0" );
    00985
    00986         UdfUnpinData( IrpContext, &Bcb );
    00987         if (CleanupIcbContext) { UdfCleanupIcbContext( IrpContext, &IcbContext ); }
    00988         if (UnlockVcb) { UdfUnlockVcb( IrpContext, Vcb ); }
    00989         if (VatIcb) { ExFreePool( VatIcb ); }
    00990     }
    00991
    00992     DebugTrace(( -1, Dbg, "UdfUpdateVcbPhase0 -> VOID\n" ));
    00993 }

VOID UdfUpdateVcbPhase1 | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PVCB | Vcb,
|  | IN PNSR_FSD | Fsd
| ) |

Definition at line 997 of file udfs/strucsup.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, Dbg, DebugTrace, DebugUnwind, FALSE, FCB_STATE_INITIALIZED, _FCB::FcbState, FsRtlAddLargeMcbEntry(), LlBytesFromSectors, _FCB::Mcb, NULL, PAGED_CODE, PFILE_ID, Physical, PNSR_FSD, SetFlag, TRUE, UdfCleanupIcbContext(), UdfCreateFcb(), UdfCreateInternalStream(), UdfIncrementReferenceCounts, UdfInitializeFcbFromIcbContext(), UdfInitializeFcbMcb(), UdfInitializeIcbContextFromFcb(), UdfLockFcb, UdfLockVcb, UdfLookupActiveIcb(), UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, UdfSetFidDirectory, UdfSetFidFromLbAddr, UdfUnlockFcb, and UdfUnlockVcb.

Referenced by UdfMountVolume().

    01005                    :
    01006
    01007     This routine is called to perform the final initialization of a Vcb and Vpb
    01008     from the volume descriptors on the disk.
    01009
    01010 Arguments:
    01011
    01012     Vcb - Vcb for the volume being mounted.  We have already done phase 0.
    01013
    01014     Fsd - The fileset descriptor for this volume.
    01015
    01016 Return Value:
    01017
    01018     None
    01019
    01020 --*/
    01021
    01022 {
    01023     ICB_SEARCH_CONTEXT IcbContext;
    01024
    01025     LONGLONG FileId = 0;
    01026
    01027     PFCB Fcb;
    01028
    01029     BOOLEAN UnlockVcb = FALSE;
    01030     BOOLEAN UnlockFcb = FALSE;
    01031     BOOLEAN CleanupIcbContext = FALSE;
    01032
    01033     ULONG Reference;
    01034
    01035     ULONG BoundSector = 0;
    01036
    01037     PAGED_CODE();
    01038
    01039     //
    01040     //  Check input.
    01041     //
    01042
    01043     ASSERT_IRP_CONTEXT( IrpContext );
    01044     ASSERT_VCB( Vcb );
    01045
    01046     DebugTrace(( +1, Dbg, "UdfUpdateVcbPhase1, Vcb %08x Fsd %08x\n", Vcb, Fsd ));
    01047
    01048     //
    01049     //  Use a try-finally to facilitate cleanup.
    01050     //
    01051
    01052     try {
    01053
    01054         //
    01055         //  Do the final internal Fcb's and other Vcb fields.
    01056         //
    01057
    01059         //
    01060         //  Create the root index and reference it in the Vcb.
    01061         //
    01063
    01064         UdfLockVcb( IrpContext, Vcb );
    01065         UnlockVcb = TRUE;
    01066
    01067         Vcb->RootIndexFcb = UdfCreateFcb( IrpContext,
    01068                                           *((PFILE_ID) &FileId),
    01069                                           UDFS_NTC_FCB_INDEX,
    01070                                           NULL );
    01071
    01072         UdfIncrementReferenceCounts( IrpContext, Vcb->RootIndexFcb, 1, 1 );
    01073         UdfUnlockVcb( IrpContext, Vcb );
    01074         UnlockVcb = FALSE;
    01075
    01076         //
    01077         //  Create the File id by hand for this Fcb.
    01078         //
    01079
    01080         UdfSetFidFromLbAddr( Vcb->RootIndexFcb->FileId, Fsd->IcbRoot.Start );
    01081         UdfSetFidDirectory( Vcb->RootIndexFcb->FileId );
    01082         Vcb->RootIndexFcb->RootExtentLength = Fsd->IcbRoot.Length.Length;
    01083
    01084         //
    01085         //  Get the direct entry for the root directory and initialize
    01086         //  the Fcb from it.
    01087         //
    01088
    01089         UdfInitializeIcbContextFromFcb( IrpContext,
    01090                                         &IcbContext,
    01091                                         Vcb->RootIndexFcb );
    01092         CleanupIcbContext = TRUE;
    01093
    01094         UdfLookupActiveIcb( IrpContext, &IcbContext );
    01095
    01096         UdfInitializeFcbFromIcbContext( IrpContext,
    01097                                         Vcb->RootIndexFcb,
    01098                                         &IcbContext );
    01099
    01100         UdfCleanupIcbContext( IrpContext, &IcbContext );
    01101         CleanupIcbContext = FALSE;
    01102
    01103         //
    01104         //  Create the stream file for the root directory.
    01105         //
    01106
    01107         UdfCreateInternalStream( IrpContext, Vcb, Vcb->RootIndexFcb );
    01108
    01110         //
    01111         //  Now do the volume dasd Fcb.  Create this and reference it in the
    01112         //  Vcb.
    01113         //
    01115
    01116         UdfLockVcb( IrpContext, Vcb );
    01117         UnlockVcb = TRUE;
    01118
    01119         Vcb->VolumeDasdFcb = UdfCreateFcb( IrpContext,
    01120                                            *((PFILE_ID) &FileId),
    01121                                            UDFS_NTC_FCB_DATA,
    01122                                            NULL );
    01123
    01124         UdfIncrementReferenceCounts( IrpContext, Vcb->VolumeDasdFcb, 1, 1 );
    01125         UdfUnlockVcb( IrpContext, Vcb );
    01126         UnlockVcb = FALSE;
    01127
    01128         Fcb = Vcb->VolumeDasdFcb;
    01129         UdfLockFcb( IrpContext, Fcb );
    01130         UnlockFcb = TRUE;
    01131
    01132         //
    01133         //  If we were unable to determine a last sector on the media, walk the Pcb and guess
    01134         //  that it is probably OK to think of the last sector of the last partition as The
    01135         //  Last Sector.  Note that we couldn't do this before since the notion of a last
    01136         //  sector has significance at mount time, if it had been possible to find one.
    01137         //
    01138
    01139         for ( Reference = 0;
    01140               Reference < Vcb->Pcb->Partitions;
    01141               Reference++ ) {
    01142
    01143             if (Vcb->Pcb->Partition[Reference].Type == Physical &&
    01144                 Vcb->Pcb->Partition[Reference].Physical.Start +
    01145                 Vcb->Pcb->Partition[Reference].Physical.Length > BoundSector) {
    01146
    01147                 BoundSector = Vcb->Pcb->Partition[Reference].Physical.Start +
    01148                               Vcb->Pcb->Partition[Reference].Physical.Length;
    01149             }
    01150         }
    01151
    01152         //
    01153         //  Note that we cannot restrict the bound by the "physical" bound discovered
    01154         //  eariler.  This is because the MSF format of the TOC request we send is only
    01155         //  capable of representing about 2.3gb, and a lot of media we will be on that
    01156         //  responds to TOCs will be quite a bit larger - ex: DVD.
    01157         //
    01158         //  This, of course, barring proper means of discovering media bounding, prohibits
    01159         //  the possibility of having UDF virtual partitions on DVD-R.
    01160         //
    01161
    01162         //
    01163         //  Build the mapping from [0, Bound).  We have to initialize the Mcb by hand since
    01164         //  this is usually left to when we lift retrieval information from an Icb in
    01165         //  UdfInitializeAllocations.
    01166         //
    01167
    01168         UdfInitializeFcbMcb( Fcb );
    01169
    01170         FsRtlAddLargeMcbEntry( &Fcb->Mcb,
    01171                                (LONGLONG) 0,
    01172                                (LONGLONG) 0,
    01173                                (LONGLONG) BoundSector );
    01174
    01175         Fcb->FileSize.QuadPart += LlBytesFromSectors( Vcb, BoundSector );
    01176
    01177         Fcb->AllocationSize.QuadPart =
    01178         Fcb->ValidDataLength.QuadPart = Fcb->FileSize.QuadPart;
    01179
    01180         UdfUnlockFcb( IrpContext, Fcb );
    01181         UnlockFcb = FALSE;
    01182
    01183         SetFlag( Fcb->FcbState, FCB_STATE_INITIALIZED );
    01184
    01185         //
    01186         //  Point to the file resource.
    01187         //
    01188
    01189         Vcb->VolumeDasdFcb->Resource = &Vcb->FileResource;
    01190
    01191         Vcb->VolumeDasdFcb->FileAttributes = FILE_ATTRIBUTE_READONLY;
    01192
    01193     } finally {
    01194
    01195         DebugUnwind( "UdfUpdateVcbPhase1" );
    01196
    01197         if (CleanupIcbContext) { UdfCleanupIcbContext( IrpContext, &IcbContext ); }
    01198
    01199         if (UnlockFcb) { UdfUnlockFcb( IrpContext, Fcb ); }
    01200         if (UnlockVcb) { UdfUnlockVcb( IrpContext, Vcb ); }
    01201     }
    01202
    01203     DebugTrace(( -1, Dbg, "UdfUpdateVcbPhase1 -> VOID\n" ));
    01204
    01205     return;
    01206 }

BOOLEAN UdfVerifyDescriptor | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PDESTAG | Descriptor,
|  | IN USHORT | Tag,
|  | IN ULONG | Size,
|  | IN ULONG | Lbn,
|  | IN BOOLEAN | ReturnError
| ) |

Definition at line 2617 of file udfs/strucsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, Dbg, DebugTrace, DESTAG_VER_CURRENT, FALSE, PAGED_CODE, Size, TRUE, UdfComputeCrc16(), UdfRaiseStatus(), and USHORT.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfGetNextAllocationPostProcessing(), UdfInitializeIcbContextFromFcb(), UdfLoadSparingTables(), UdfLookupActiveIcbInExtent(), UdfLookupDirEntryPostProcessing(), UdfLookupEa(), and UdfUpdateVcbPhase0().

    02628                    :
    02629
    02630     This routine verifies that a descriptor using a Descriptor tag (3/7.2) is
    02631     consistent with itself and the descriptor data.
    02632
    02633 Arguments:
    02634
    02635     Descriptor - This is the pointer to the descriptor tag, which is always
    02636         at the front of a descriptor
    02637
    02638     Tag - The Tag Identifier this descriptor should have
    02639
    02640     Size - Size of this descriptor
    02641
    02642     Lbn - The logical block number this descriptor should claim it is recorded at
    02643
    02644     ReturnError - Whether this routine should return an error or raise
    02645
    02646 Return Value:
    02647
    02648     Boolean TRUE if the descriptor is consistent, FALSE or a raised status of
    02649     STATUS_DISK_CORRUPT_ERROR otherwise.
    02650
    02651 --*/
    02652
    02653 {
    02654     UCHAR Checksum = 0;
    02655     PCHAR CheckPtr;
    02656     USHORT Crc;
    02657
    02658 #ifdef UDF_SANITY
    02659
    02660     VERIFY_FAILURE FailReason = Nothing;
    02661
    02662 #endif
    02663
    02664     //
    02665     //  Check our inputs
    02666     //
    02667
    02668     ASSERT_IRP_CONTEXT( IrpContext );
    02669
    02670     PAGED_CODE();
    02671
    02672 #ifdef UDF_SANITY
    02673
    02674     if (UdfNoisyVerifyDescriptor) {
    02675
    02676         goto BeNoisy;
    02677     }
    02678
    02679     RegularEntry:
    02680
    02681 #endif
    02682
    02683     //
    02684     //  The version of the Descriptor Tag specified in ISO 13346 and used in
    02685     //  UDF is a particular value; presumeably, previous versions were used
    02686     //  in some older revision of the standard.
    02687     //
    02688
    02689 #ifdef UDF_SUPPORT_NONSTANDARD_ADAPTEC
    02690
    02691     //
    02692     //  Let bad descriptor version numbers through.
    02693     //
    02694     //  Reasons:
    02695     //
    02696     //      ADAPTEC - early CDUDF wrote version 1 as opposed to version 2.
    02697     //
    02698
    02699     if (TRUE)
    02700
    02701 #else
    02702
    02703     if (Descriptor->Version == DESTAG_VER_CURRENT)
    02704
    02705 #endif
    02706
    02707     {
    02708
    02709         //
    02710         //  A descriptor is stamped in four ways. First, the Lbn of the sector
    02711         //  containing the descriptor is written here. (3/7.2.8)
    02712         //
    02713
    02714
    02715 #ifdef UDF_SUPPORT_NONSTANDARD_HP
    02716
    02717         //
    02718         //  Let bad lbn through.
    02719         //
    02720         //  Reasons:
    02721         //
    02722         //      HP - Rob Sim;s CD-RW model disc doesn't record this reliably.
    02723         //
    02724
    02725         if (TRUE)
    02726
    02727 #else
    02728
    02729         if (Descriptor->Lbn == Lbn)
    02730
    02731 #endif
    02732         {
    02733             //
    02734             //  Next, the descriptor tag itself has an identifier which should match
    02735             //  the type we expect to find here (3/7.2.1)
    02736             //
    02737
    02738             if (Descriptor->Ident == Tag) {
    02739
    02740                 //
    02741                 //  Next, the descriptor tag itself is checksumed, minus the byte
    02742                 //  used to store the checksum. (3/7.2.3)
    02743                 //
    02744
    02745                 for (CheckPtr = (PCHAR) Descriptor;
    02746                      CheckPtr < (PCHAR) Descriptor + FIELD_OFFSET( DESTAG, Checksum );
    02747                      CheckPtr++) {
    02748
    02749                     Checksum += *CheckPtr;
    02750                 }
    02751
    02752                 for (CheckPtr = (PCHAR) Descriptor + FIELD_OFFSET( DESTAG, Checksum ) + sizeof(UCHAR);
    02753                      CheckPtr < (PCHAR) Descriptor + sizeof(DESTAG);
    02754                      CheckPtr++) {
    02755
    02756                     Checksum += *CheckPtr;
    02757                 }
    02758
    02759                 if (Descriptor->Checksum == Checksum) {
    02760
    02761                     //
    02762                     //  Now we check that the CRC in the Descriptor tag is sized sanely
    02763                     //  and matches the Descriptor data. (3/7.2.6)
    02764                     //
    02765
    02766 #ifdef UDF_SUPPORT_NONSTANDARD_HP
    02767
    02768                     //
    02769                     //  Let zero-length CRCs through.
    02770                     //
    02771                     //  Reasons:
    02772                     //
    02773                     //      HP - early CDUDF didn't CRC the terminationg descriptors (tag 8).
    02774                     //
    02775
    02776                     if (!Descriptor->CRCLen ||
    02777                         Descriptor->CRCLen <= Size - sizeof(DESTAG))
    02778 #else
    02779
    02780                     if (Descriptor->CRCLen &&
    02781                         Descriptor->CRCLen <= Size - sizeof(DESTAG))
    02782
    02783 #endif
    02784                     {
    02785
    02786                         Crc = UdfComputeCrc16( (PCHAR) Descriptor + sizeof(DESTAG),
    02787                                                Descriptor->CRCLen );
    02788
    02789 #ifdef UDF_SUPPORT_NONSTANDARD_HP
    02790
    02791                         //
    02792                         //  Let zero-length CRCs through.
    02793                         //
    02794                         //  Reasons: as above.
    02795                         //
    02796
    02797                         if (!Descriptor->CRCLen ||
    02798                             Descriptor->CRC == Crc)
    02799
    02800 #else
    02801
    02802                         if (Descriptor->CRC == Crc)
    02803
    02804 #endif
    02805                         {
    02806
    02807                             //
    02808                             //  This descriptor checks out.
    02809                             //
    02810
    02811 #ifdef UDF_SANITY
    02812                             if (UdfNoisyVerifyDescriptor) {
    02813
    02814                                 DebugTrace(( -1, Dbg, "UdfVerifyDescriptor -> TRUE\n" ));
    02815                             }
    02816 #endif
    02817                             return TRUE;
    02818
    02819                         } else {
    02820 #ifdef UDF_SANITY
    02821                             FailReason = BadCrc;
    02822                             goto ReportFailure;
    02823 #endif
    02824                         }
    02825
    02826                     } else {
    02827 #ifdef UDF_SANITY
    02828                         FailReason = BadCrcLength;
    02829                         goto ReportFailure;
    02830 #endif
    02831                     }
    02832
    02833                 } else {
    02834 #ifdef UDF_SANITY
    02835                     FailReason = BadChecksum;
    02836                     goto ReportFailure;
    02837 #endif
    02838                 }
    02839
    02840             } else {
    02841 #ifdef UDF_SANITY
    02842                 FailReason = BadTag;
    02843                 goto ReportFailure;
    02844 #endif
    02845             }
    02846
    02847         } else {
    02848 #ifdef UDF_SANITY
    02849             FailReason = BadLbn;
    02850             goto ReportFailure;
    02851 #endif
    02852         }
    02853
    02854     } else {
    02855 #ifdef UDF_SANITY
    02856         FailReason = BadDestagVersion;
    02857         goto ReportFailure;
    02858 #endif
    02859     }
    02860
    02861 #ifdef UDF_SANITY
    02862
    02863     BeNoisy:
    02864
    02865     DebugTrace(( +1, Dbg,
    02866                  "UdfVerifyDescriptor, Destag %08x, Tag %x, Size %x, Lbn %x\n",
    02867                  Descriptor,
    02868                  Tag,
    02869                  Size,
    02870                  Lbn ));
    02871
    02872     if (FailReason == Nothing) {
    02873
    02874         goto RegularEntry;
    02875
    02876     } else if (!UdfNoisyVerifyDescriptor) {
    02877
    02878         goto ReallyReportFailure;
    02879     }
    02880
    02881     ReportFailure:
    02882
    02883     if (!UdfNoisyVerifyDescriptor) {
    02884
    02885         goto BeNoisy;
    02886     }
    02887
    02888     ReallyReportFailure:
    02889
    02890     switch (FailReason) {
    02891         case BadLbn:
    02892             DebugTrace(( 0, Dbg,
    02893                          "Lbn mismatch - Lbn %x != expected %x\n",
    02894                          Descriptor->Lbn,
    02895                          Lbn ));
    02896             break;
    02897
    02898         case BadTag:
    02899             DebugTrace(( 0, Dbg,
    02900                          "Tag mismatch - Ident %x != expected %x\n",
    02901                          Descriptor->Ident,
    02902                          Tag ));
    02903             break;
    02904
    02905         case BadChecksum:
    02906             DebugTrace(( 0, Dbg,
    02907                          "Checksum mismatch - Checksum %x != descriptor's %x\n",
    02908                          Checksum,
    02909                          Descriptor->Checksum ));
    02910             break;
    02911
    02912         case BadCrcLength:
    02913             DebugTrace(( 0, Dbg,
    02914                          "CRC'd size bad - CrcLen %x is 0 or > max %x\n",
    02915                          Descriptor->CRCLen,
    02916                          Size - sizeof(DESTAG) ));
    02917             break;
    02918
    02919         case BadCrc:
    02920             DebugTrace(( 0, Dbg,
    02921                          "CRC mismatch - Crc %x != descriptor's %x\n",
    02922                          Crc,
    02923                          Descriptor->CRC ));
    02924             break;
    02925
    02926         case BadDestagVersion:
    02927             DebugTrace(( 0, Dbg,
    02928                          "Bad Destag Verion - %x != descriptor's %x\n",
    02929                          DESTAG_VER_CURRENT,
    02930                          Descriptor->Version ));
    02931             break;
    02932
    02933         default:
    02934             ASSERT( FALSE );
    02935     }
    02936
    02937     DebugTrace(( -1, Dbg, "UdfVerifyDescriptor -> FALSE\n" ));
    02938
    02939 #endif
    02940
    02941     if (!ReturnError) {
    02942
    02943         UdfRaiseStatus( IrpContext, STATUS_CRC_ERROR );
    02944     }
    02945
    02946     return FALSE;
    02947 }

BOOLEAN UdfVerifyFcbOperation | ( | IN PIRP_CONTEXT IrpContext | OPTIONAL,
|  | IN PFCB | Fcb
| ) |

Definition at line 760 of file udfs/verfysup.c.

References DO_VERIFY_VOLUME, FALSE, FlagOn, _DEVICE_OBJECT::Flags, IoSetHardErrorOrVerifyDevice(), NTSTATUS(), PAGED_CODE, _VPB::RealDevice, SetFlag, Status, TRUE, UdfRaiseStatus(), _VCB::VcbCondition, VcbDismountInProgress, VcbInvalid, VcbMounted, VcbMountInProgress, VcbNotMounted, and _VCB::Vpb.

Referenced by UdfCommonLockControl(), UdfCommonQueryInfo(), UdfCommonRead(), UdfCommonSetInfo(), UdfFastLock(), UdfFastQueryBasicInfo(), UdfFastQueryNetworkInfo(), UdfFastQueryStdInfo(), UdfFastUnlockAll(), UdfFastUnlockAllByKey(), UdfFastUnlockSingle(), UdfOplockRequest(), and UdfQueryDirectory().

    00767                    :
    00768
    00769     This routine is called to verify that the state of the Fcb is valid
    00770     to allow the current operation to continue.  We use the state of the
    00771     Vcb, target device and type of operation to determine this.
    00772
    00773 Arguments:
    00774
    00775     IrpContext - IrpContext for the request.  If not present then we
    00776         were called from the fast IO path.
    00777
    00778     Fcb - Fcb to perform the request on.
    00779
    00780 Return Value:
    00781
    00782     BOOLEAN - TRUE if the request can continue, FALSE otherwise.
    00783
    00784 --*/
    00785
    00786 {
    00787     NTSTATUS Status = STATUS_SUCCESS;
    00788     PVCB Vcb = Fcb->Vcb;
    00789     PDEVICE_OBJECT RealDevice = Vcb->Vpb->RealDevice;
    00790
    00791     PAGED_CODE();
    00792
    00793     //
    00794     //  Fail immediately if the volume is in the progress of being dismounted
    00795     //  or has been marked invalid.
    00796     //
    00797
    00798     if ((Vcb->VcbCondition == VcbInvalid) ||
    00799         (Vcb->VcbCondition == VcbDismountInProgress)) {
    00800
    00801         if (ARGUMENT_PRESENT( IrpContext )) {
    00802
    00803             UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID );
    00804         }
    00805
    00806         return FALSE;
    00807     }
    00808
    00809     //
    00810     //  Always fail if the volume needs to be verified.
    00811     //
    00812
    00813     if (FlagOn( RealDevice->Flags, DO_VERIFY_VOLUME )) {
    00814
    00815         if (ARGUMENT_PRESENT( IrpContext )) {
    00816
    00817             IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
    00818                                           RealDevice );
    00819
    00820             UdfRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED );
    00821         }
    00822
    00823         return FALSE;
    00824
    00825     //
    00826     //  All operations are allowed on mounted volumes.
    00827     //
    00828
    00829     } else if ((Vcb->VcbCondition == VcbMounted) ||
    00830                (Vcb->VcbCondition == VcbMountInProgress)) {
    00831
    00832         return TRUE;
    00833
    00834     //
    00835     //  Fail all requests for fast Io on other Vcb conditions.
    00836     //
    00837
    00838     } else if (!ARGUMENT_PRESENT( IrpContext )) {
    00839
    00840         return FALSE;
    00841
    00842     //
    00843     //  The remaining case is VcbNotMounted.
    00844     //  Mark the device to be verified and raise WRONG_VOLUME.
    00845     //
    00846
    00847     } else if (Vcb->VcbCondition == VcbNotMounted) {
    00848
    00849         if (ARGUMENT_PRESENT( IrpContext )) {
    00850
    00851             SetFlag(RealDevice->Flags, DO_VERIFY_VOLUME);
    00852
    00853             IoSetHardErrorOrVerifyDevice( IrpContext->Irp, RealDevice );
    00854             UdfRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
    00855         }
    00856
    00857         return FALSE;
    00858     }
    00859
    00860     return TRUE;
    00861 }

VOID UdfVerifyVcb | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb
| ) |

Definition at line 603 of file udfs/verfysup.c.

References DO_VERIFY_VOLUME, FALSE, FlagOn, IoSetHardErrorOrVerifyDevice(), NT_SUCCESS, NTSTATUS(), PAGED_CODE, SetFlag, Status, UdfIsRawDevice, UdfNormalizeAndRaiseStatus(), UdfPerformDevIoCtrl(), UdfRaiseStatus(), VCB_STATE_REMOVABLE_MEDIA, VcbDismountInProgress, VcbInvalid, VcbMounted, VcbMountInProgress, VcbNotMounted, and VOID().

Referenced by UdfCommonCreate(), UdfCommonDevControl(), UdfCommonQueryVolInfo(), UdfIsVolumeMounted(), UdfLockVolume(), and UdfNotifyChangeDirectory().

    00610                    :
    00611
    00612     This routine checks that the current Vcb is valid and currently mounted
    00613     on the device.  It will raise on an error condition.
    00614
    00615     We check whether the volume needs verification and the current state
    00616     of the Vcb.
    00617
    00618 Arguments:
    00619
    00620     Vcb - This is the volume to verify.
    00621
    00622 Return Value:
    00623
    00624     None
    00625
    00626 --*/
    00627
    00628 {
    00629     NTSTATUS Status;
    00630     IO_STATUS_BLOCK Iosb;
    00631     ULONG MediaChangeCount = 0;
    00632
    00633     PAGED_CODE();
    00634
    00635     //
    00636     //  Fail immediately if the volume is in the progress of being dismounted
    00637     //  or has been marked invalid.
    00638     //
    00639
    00640     if ((Vcb->VcbCondition == VcbInvalid) ||
    00641         (Vcb->VcbCondition == VcbDismountInProgress)) {
    00642
    00643         UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID );
    00644     }
    00645
    00646     //
    00647     //  If the media is removable and the verify volume flag in the
    00648     //  device object is not set then we want to ping the device
    00649     //  to see if it needs to be verified
    00650     //
    00651
    00652     if ((Vcb->VcbCondition != VcbMountInProgress) &&
    00653         FlagOn( Vcb->VcbState, VCB_STATE_REMOVABLE_MEDIA ) &&
    00654         !FlagOn( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) {
    00655
    00656         Status = UdfPerformDevIoCtrl( IrpContext,
    00657                                       ( Vcb->Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
    00658                                         IOCTL_CDROM_CHECK_VERIFY :
    00659                                         IOCTL_DISK_CHECK_VERIFY ),
    00660                                       Vcb->TargetDeviceObject,
    00661                                       &MediaChangeCount,
    00662                                       sizeof(ULONG),
    00663                                       FALSE,
    00664                                       FALSE,
    00665                                       &Iosb );
    00666
    00667         if (Iosb.Information != sizeof(ULONG)) {
    00668
    00669             //
    00670             //  Be safe about the count in case the driver didn't fill it in
    00671             //
    00672
    00673             MediaChangeCount = 0;
    00674         }
    00675
    00676         //
    00677         //  If the volume is now an empty device, or we have receieved a
    00678         //  bare STATUS_VERIFY_REQUIRED (various hardware conditions such
    00679         //  as bus resets, etc., will trigger this in the drivers), or the
    00680         //  media change count has moved since we last inspected the device,
    00681         //  then mark the volume to be verified.
    00682         //
    00683
    00684         if ((Vcb->VcbCondition == VcbMounted &&
    00685              UdfIsRawDevice( IrpContext, Status )) ||
    00686             (Status == STATUS_VERIFY_REQUIRED) ||
    00687             (NT_SUCCESS(Status) &&
    00688              (Vcb->MediaChangeCount != MediaChangeCount))) {
    00689
    00690             SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
    00691
    00692             //
    00693             //  If the volume is not mounted and we got a media change count,
    00694             //  update the Vcb so we do not trigger a verify again at this
    00695             //  count value.  If the verify->mount path detects that the media
    00696             //  has actually changed and this Vcb is valid again, this will have
    00697             //  done nothing.  We are already synchronized since the caller has
    00698             //  the Vcb.
    00699             //
    00700
    00701             if ((Vcb->VcbCondition == VcbNotMounted) &&
    00702                 NT_SUCCESS(Status)) {
    00703
    00704                 Vcb->MediaChangeCount = MediaChangeCount;
    00705             }
    00706
    00707         //
    00708         //  Raise the error condition otherwise.
    00709         //
    00710
    00711         } else if (!NT_SUCCESS( Status )) {
    00712
    00713             UdfNormalizeAndRaiseStatus( IrpContext, Status );
    00714         }
    00715
    00716     }
    00717
    00718     //
    00719     //  The Vcb may be mounted but the underlying real device may need to be verified.
    00720     //  If it does then we'll set the Iosb in the irp to be our real device
    00721     //  and raise Verify required
    00722     //
    00723
    00724     if (FlagOn( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) {
    00725
    00726         IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
    00727                                       Vcb->Vpb->RealDevice );
    00728
    00729         UdfRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED );
    00730     }
    00731
    00732     //
    00733     //  Based on the condition of the Vcb we'll either return to our
    00734     //  caller or raise an error condition
    00735     //
    00736
    00737     switch (Vcb->VcbCondition) {
    00738
    00739     case VcbNotMounted:
    00740
    00741         SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
    00742
    00743         IoSetHardErrorOrVerifyDevice( IrpContext->Irp, Vcb->Vpb->RealDevice );
    00744
    00745         UdfRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
    00746         break;
    00747
    00748     case VcbInvalid:
    00749     case VcbDismountInProgress :
    00750
    00751         UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID );
    00752         break;
    00753     }
    00754
    00755     return;
    00756 }

BOOLEAN UdfVmcbLbnToVbn | ( | IN PVMCB | Vmcb,
|  | IN LBN | Lbn,
|  | OUT PVBN | Vbn,
|  | OUT PULONG SectorCount | OPTIONAL
| ) |

Definition at line 553 of file vmcbsup.c.

References Dbg, DebugTrace, DebugUnwind, Executive, FALSE, KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), NULL, PAGED_CODE, UdfVmcbLookupMcbEntry(), and VOID().

Referenced by UdfLookupMetaVsnOfExtent().

    00562                    :
    00563
    00564     This routine translates an LBN to a VBN.
    00565
    00566 Arguments:
    00567
    00568     Vmcb - Supplies the VMCB structure being queried.
    00569
    00570     Lbn - Supplies the LBN to translate from.
    00571
    00572     Vbn - Recieves the VBN mapped by the input LBN.  This value is
    00573         only valid if the function result is TRUE.
    00574
    00575     SectorCount - Optionally receives the number of sectors corresponding
    00576         to the run.
    00577
    00578 Return Value:
    00579
    00580     BOOLEAN - TRUE if the mapping is valid and FALSE otherwise.
    00581
    00582 --*/
    00583
    00584 {
    00585     BOOLEAN Result;
    00586
    00587     PAGED_CODE();
    00588
    00589     DebugTrace(( +1, Dbg, "UdfVmcbLbnToVbn, Lbn = %08x\n", Lbn ));
    00590
    00591     //
    00592     //  If the requested Lbn is greater than the maximum allowed Lbn
    00593     //  then the result is FALSE
    00594     //
    00595
    00596     if (Lbn > Vmcb->MaximumLbn) {
    00597
    00598         DebugTrace(( -1, Dbg, "Lbn too large, UdfVmcbLbnToVbn -> FALSE\n" ));
    00599
    00600         return FALSE;
    00601     }
    00602
    00603     //
    00604     //  Now grab the mutex for the vmcb
    00605     //
    00606
    00607     (VOID)KeWaitForSingleObject( &Vmcb->Mutex,
    00608                                  Executive,
    00609                                  KernelMode,
    00610                                  FALSE,
    00611                                  (PLARGE_INTEGER) NULL );
    00612
    00613     try {
    00614
    00615         Result = UdfVmcbLookupMcbEntry( &Vmcb->LbnIndexed,
    00616                                         Lbn,
    00617                                         Vbn,
    00618                                         SectorCount,
    00619                                         NULL );
    00620
    00621         DebugTrace(( 0, Dbg, "*Vbn = %08x\n", *Vbn ));
    00622
    00623     } finally {
    00624
    00625         (VOID) KeReleaseMutex( &Vmcb->Mutex, FALSE );
    00626
    00627
    00628         DebugUnwind("UdfVmcbLbnToVbn");
    00629         DebugTrace(( -1, Dbg, "UdfVmcbLbnToVbn -> Result = %08x\n", Result ));
    00630     }
    00631
    00632     return Result;
    00633 }

BOOLEAN UdfVmcbVbnToLbn | ( | IN PVMCB | Vmcb,
|  | IN VBN | Vbn,
|  | OUT PLBN | Lbn,
|  | OUT PULONG SectorCount | OPTIONAL
| ) |