📄 fileinfo.c
字号:
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
FileInfo.c
Abstract:
This module implements the File Information routines for Udfs called by
the Fsd/Fsp dispatch drivers.
Author:
Dan Lovinger [DanLo] 16-Jan-1997
Revision History:
--*/
#include "UdfProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (UDFS_BUG_CHECK_FILEINFO)
//
// The local debug trace level
//
#define Dbg (UDFS_DEBUG_LEVEL_FILEINFO)
//
// Local macros
//
INLINE
ULONG
UdfGetExtraFileAttributes (
IN PCCB Ccb
)
/*++
Routine Description:
Safely figure out extra name-based file attributes given a context block.
Arguments:
Ccb - a context block to examine.
Return Value:
ULONG - file attributes for a file based on how it was opened (seperate from
those based on the object that was opened).
--*/
{
return ( Ccb->Lcb != NULL? Ccb->Lcb->FileAttributes : 0 );
}
//
// Local support routines
//
VOID
UdfQueryBasicInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCCB Ccb,
IN OUT PFILE_BASIC_INFORMATION Buffer,
IN OUT PULONG Length
);
VOID
UdfQueryStandardInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PFILE_STANDARD_INFORMATION Buffer,
IN OUT PULONG Length
);
VOID
UdfQueryInternalInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PFILE_INTERNAL_INFORMATION Buffer,
IN OUT PULONG Length
);
VOID
UdfQueryEaInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PFILE_EA_INFORMATION Buffer,
IN OUT PULONG Length
);
VOID
UdfQueryPositionInfo (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_POSITION_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
UdfQueryNameInfo (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_NAME_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
UdfQueryAlternateNameInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCCB Ccb,
IN OUT PFILE_NAME_INFORMATION Buffer,
IN OUT PULONG Length
);
VOID
UdfQueryNetworkInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PCCB Ccb,
IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
IN OUT PULONG Length
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, UdfCommonQueryInfo)
#pragma alloc_text(PAGE, UdfCommonSetInfo)
#pragma alloc_text(PAGE, UdfFastQueryBasicInfo)
#pragma alloc_text(PAGE, UdfFastQueryStdInfo)
#pragma alloc_text(PAGE, UdfFastQueryNetworkInfo)
#pragma alloc_text(PAGE, UdfQueryAlternateNameInfo)
#pragma alloc_text(PAGE, UdfQueryBasicInfo)
#pragma alloc_text(PAGE, UdfQueryEaInfo)
#pragma alloc_text(PAGE, UdfQueryInternalInfo)
#pragma alloc_text(PAGE, UdfQueryNameInfo)
#pragma alloc_text(PAGE, UdfQueryNetworkInfo)
#pragma alloc_text(PAGE, UdfQueryPositionInfo)
#pragma alloc_text(PAGE, UdfQueryStandardInfo)
#endif
NTSTATUS
UdfCommonQueryInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for query file information called by both the
fsd and fsp threads.
Arguments:
Irp - Supplies the Irp to process.
Return Value:
NTSTATUS - The return status for this operation.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
ULONG Length;
FILE_INFORMATION_CLASS FileInformationClass;
PFILE_ALL_INFORMATION Buffer;
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
BOOLEAN ReleaseFcb = FALSE;
PAGED_CODE();
//
// Reference our input parameters to make things easier
//
Length = IrpSp->Parameters.QueryFile.Length;
FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Decode the file object
//
TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// We only support query on file and directory handles.
//
switch (TypeOfOpen) {
case UserDirectoryOpen :
case UserFileOpen :
//
// Acquire shared access to this file.
//
UdfAcquireFileShared( IrpContext, Fcb );
ReleaseFcb = TRUE;
ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ));
//
// Make sure the Fcb is in a usable condition. This will raise
// an error condition if the volume is unusable
//
UdfVerifyFcbOperation( IrpContext, Fcb );
//
// Based on the information class we'll do different
// actions. Each of hte procedures that we're calling fills
// up the output buffer, if possible. They will raise the
// status STATUS_BUFFER_OVERFLOW for an insufficient buffer.
// This is considered a somewhat unusual case and is handled
// more cleanly with the exception mechanism rather than
// testing a return status value for each call.
//
switch (FileInformationClass) {
case FileAllInformation:
//
// We don't allow this operation on a file opened by file Id.
//
if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// In this case go ahead and call the individual routines to
// fill in the buffer. Only the name routine will
// pointer to the output buffer and then call the
// individual routines to fill in the buffer.
//
Length -= (sizeof( FILE_ACCESS_INFORMATION ) +
sizeof( FILE_MODE_INFORMATION ) +
sizeof( FILE_ALIGNMENT_INFORMATION ));
UdfQueryBasicInfo( IrpContext, Fcb, Ccb, &Buffer->BasicInformation, &Length );
UdfQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length );
UdfQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length );
UdfQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length );
UdfQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length );
Status = UdfQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length );
break;
case FileBasicInformation:
UdfQueryBasicInfo( IrpContext, Fcb, Ccb, (PFILE_BASIC_INFORMATION) Buffer, &Length );
break;
case FileStandardInformation:
UdfQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length );
break;
case FileInternalInformation:
UdfQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length );
break;
case FileEaInformation:
UdfQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length );
break;
case FilePositionInformation:
UdfQueryPositionInfo( IrpContext, IrpSp->FileObject, (PFILE_POSITION_INFORMATION) Buffer, &Length );
break;
case FileNameInformation:
//
// We don't allow this operation on a file opened by file Id.
//
if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
Status = UdfQueryNameInfo( IrpContext, IrpSp->FileObject, (PFILE_NAME_INFORMATION) Buffer, &Length );
} else {
Status = STATUS_INVALID_PARAMETER;
}
break;
case FileAlternateNameInformation:
if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
Status = UdfQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length );
} else {
Status = STATUS_INVALID_PARAMETER;
}
break;
case FileNetworkOpenInformation:
UdfQueryNetworkInfo( IrpContext, Fcb, Ccb, (PFILE_NETWORK_OPEN_INFORMATION) Buffer, &Length );
break;
default :
Status = STATUS_INVALID_PARAMETER;
}
break;
default :
Status = STATUS_INVALID_PARAMETER;
}
//
// Set the information field to the number of bytes actually filled in
// and then complete the request
//
Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
} finally {
//
// Release the file.
//
if (ReleaseFcb) {
UdfReleaseFile( IrpContext, Fcb );
}
}
//
// Complete the request if we didn't raise.
//
UdfCompleteRequest( IrpContext, Irp, Status );
return Status;
}
NTSTATUS
UdfCommonSetInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for set file information called by both the
fsd and fsp threads. We only support operations which set the file position.
Arguments:
Irp - Supplies the Irp to process.
Return Value:
NTSTATUS - The return status for this operation.
--*/
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PFILE_POSITION_INFORMATION Buffer;
PAGED_CODE();
//
// Decode the file object
//
TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
//
// We only support a SetPositionInformation on a user file.
//
if ((TypeOfOpen != UserFileOpen) ||
(IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {
UdfCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Acquire shared access to this file.
//
UdfAcquireFileShared( IrpContext, Fcb );
try {
//
// Make sure the Fcb is in a usable condition. This
// will raise an error condition if the fcb is unusable
//
UdfVerifyFcbOperation( IrpContext, Fcb );
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Check if the file does not use intermediate buffering. If it
// does not use intermediate buffering then the new position we're
// supplied must be aligned properly for the device
//
if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
((Buffer->CurrentByteOffset.LowPart & IrpSp->DeviceObject->AlignmentRequirement) != 0)) {
try_leave( NOTHING );
}
//
// The input parameter is fine so set the current byte offset and
// complete the request
//
//
// Lock the Fcb to provide synchronization.
//
UdfLockFcb( IrpContext, Fcb );
IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
UdfUnlockFcb( IrpContext, Fcb );
Status = STATUS_SUCCESS;
} finally {
UdfReleaseFile( IrpContext, Fcb );
}
//
// Complete the request if there was no raise.
//
UdfCompleteRequest( IrpContext, Irp, Status );
return Status;
}
BOOLEAN
UdfFastQueryBasicInfo (
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN OUT PFILE_BASIC_INFORMATION Buffer,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -