summaryrefslogtreecommitdiffstats
path: root/private/ntos/cdfs/fileinfo.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/cdfs/fileinfo.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/cdfs/fileinfo.c')
-rw-r--r--private/ntos/cdfs/fileinfo.c1492
1 files changed, 1492 insertions, 0 deletions
diff --git a/private/ntos/cdfs/fileinfo.c b/private/ntos/cdfs/fileinfo.c
new file mode 100644
index 000000000..fd0e663cb
--- /dev/null
+++ b/private/ntos/cdfs/fileinfo.c
@@ -0,0 +1,1492 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ FileInfo.c
+
+Abstract:
+
+ This module implements the File Information routines for Cdfs called by
+ the Fsd/Fsp dispatch drivers.
+
+Author:
+
+ Brian Andrew [BrianAn] 01-July-1995
+
+Revision History:
+
+--*/
+
+#include "CdProcs.h"
+
+//
+// The Bug check file id for this module
+//
+
+#define BugCheckFileId (CDFS_BUG_CHECK_FILEINFO)
+
+//
+// Local support routines
+//
+
+VOID
+CdQueryBasicInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_BASIC_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+VOID
+CdQueryStandardInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_STANDARD_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+VOID
+CdQueryInternalInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_INTERNAL_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+VOID
+CdQueryEaInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_EA_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+VOID
+CdQueryPositionInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN OUT PFILE_POSITION_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+NTSTATUS
+CdQueryNameInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN OUT PFILE_NAME_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+NTSTATUS
+CdQueryAlternateNameInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN PCCB Ccb,
+ IN OUT PFILE_NAME_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+VOID
+CdQueryNetworkInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
+ IN OUT PULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, CdCommonQueryInfo)
+#pragma alloc_text(PAGE, CdCommonSetInfo)
+#pragma alloc_text(PAGE, CdFastQueryBasicInfo)
+#pragma alloc_text(PAGE, CdFastQueryStdInfo)
+#pragma alloc_text(PAGE, CdFastQueryNetworkInfo)
+#pragma alloc_text(PAGE, CdQueryAlternateNameInfo)
+#pragma alloc_text(PAGE, CdQueryBasicInfo)
+#pragma alloc_text(PAGE, CdQueryEaInfo)
+#pragma alloc_text(PAGE, CdQueryInternalInfo)
+#pragma alloc_text(PAGE, CdQueryNameInfo)
+#pragma alloc_text(PAGE, CdQueryNetworkInfo)
+#pragma alloc_text(PAGE, CdQueryPositionInfo)
+#pragma alloc_text(PAGE, CdQueryStandardInfo)
+#endif
+
+
+NTSTATUS
+CdCommonQueryInfo (
+ 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 = CdDecodeFileObject( IrpContext, 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.
+ //
+
+ CdAcquireFileShared( IrpContext, Fcb );
+ ReleaseFcb = TRUE;
+
+ //
+ // Make sure we have the correct sizes for a directory.
+ //
+
+ if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {
+
+ ASSERT( TypeOfOpen == UserDirectoryOpen );
+ CdCreateInternalStream( IrpContext, Fcb->Vcb, Fcb );
+ }
+
+ //
+ // Make sure the Fcb is in a usable condition. This will raise
+ // an error condition if the volume is unusable
+ //
+
+ CdVerifyFcbOperation( 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;
+ }
+
+ //
+ // 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 ));
+
+ CdQueryBasicInfo( IrpContext, Fcb, &Buffer->BasicInformation, &Length );
+ CdQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length );
+ CdQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length );
+ CdQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length );
+ CdQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length );
+ Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length );
+
+ break;
+
+ case FileBasicInformation:
+
+ CdQueryBasicInfo( IrpContext, Fcb, (PFILE_BASIC_INFORMATION) Buffer, &Length );
+ break;
+
+ case FileStandardInformation:
+
+ CdQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length );
+ break;
+
+ case FileInternalInformation:
+
+ CdQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length );
+ break;
+
+ case FileEaInformation:
+
+ CdQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length );
+ break;
+
+ case FilePositionInformation:
+
+ CdQueryPositionInfo( 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 = CdQueryNameInfo( 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 = CdQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length );
+
+ } else {
+
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ break;
+
+ case FileNetworkOpenInformation:
+
+ CdQueryNetworkInfo( IrpContext, Fcb, (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) {
+
+ CdReleaseFile( IrpContext, Fcb );
+ }
+ }
+
+ //
+ // Complete the request if we didn't raise.
+ //
+
+ CdCompleteRequest( IrpContext, Irp, Status );
+
+ return Status;
+}
+
+
+NTSTATUS
+CdCommonSetInfo (
+ 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 = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
+
+ //
+ // We only support a SetPositionInformation on a user file.
+ //
+
+ if ((TypeOfOpen != UserFileOpen) ||
+ (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {
+
+ CdCompleteRequest( IrpContext, Irp, Status );
+ return Status;
+ }
+
+ //
+ // Acquire shared access to this file.
+ //
+
+ CdAcquireFileShared( IrpContext, Fcb );
+
+ try {
+
+ //
+ // Make sure the Fcb is in a usable condition. This
+ // will raise an error condition if the fcb is unusable
+ //
+
+ CdVerifyFcbOperation( 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_return( NOTHING );
+ }
+
+ //
+ // The input parameter is fine so set the current byte offset and
+ // complete the request
+ //
+
+ //
+ // Lock the Fcb to provide synchronization.
+ //
+
+ CdLockFcb( IrpContext, Fcb );
+ IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
+ CdUnlockFcb( IrpContext, Fcb );
+
+ Status = STATUS_SUCCESS;
+
+ try_exit: NOTHING;
+ } finally {
+
+ CdReleaseFile( IrpContext, Fcb );
+ }
+
+ //
+ // Complete the request if there was no raise.
+ //
+
+ CdCompleteRequest( IrpContext, Irp, Status );
+ return Status;
+}
+
+
+BOOLEAN
+CdFastQueryBasicInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ IN OUT PFILE_BASIC_INFORMATION Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is for the fast query call for basic file information.
+
+Arguments:
+
+ FileObject - Supplies the file object used in this operation
+
+ Wait - Indicates if we are allowed to wait for the information
+
+ Buffer - Supplies the output buffer to receive the basic information
+
+ IoStatus - Receives the final status of the operation
+
+Return Value:
+
+ BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
+ needs to take the long route.
+
+--*/
+
+{
+ BOOLEAN Result = FALSE;
+ TYPE_OF_OPEN TypeOfOpen;
+
+ PFCB Fcb;
+
+ PAGED_CODE();
+
+ ASSERT_FILE_OBJECT( FileObject );
+
+ FsRtlEnterFileSystem();
+
+ //
+ // Decode the file object to find the type of open and the data
+ // structures.
+ //
+
+ TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
+
+ //
+ // We only support this request on user file or directory objects.
+ //
+
+ if ((TypeOfOpen != UserFileOpen) &&
+ ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Acquire the file shared to access the Fcb.
+ //
+
+ if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Use a try-finally to facilitate cleanup.
+ //
+
+ try {
+
+ //
+ // Only deal with 'good' Fcb's.
+ //
+
+ if (CdVerifyFcbOperation( NULL, Fcb )) {
+
+ //
+ // Fill in the input buffer from the Fcb fields.
+ //
+
+ Buffer->CreationTime.QuadPart =
+ Buffer->LastWriteTime.QuadPart =
+ Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
+
+ Buffer->LastAccessTime.QuadPart = 0;
+
+ Buffer->FileAttributes = Fcb->FileAttributes;
+
+ //
+ // Update the IoStatus block with the size of this data.
+ //
+
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = sizeof( FILE_BASIC_INFORMATION );
+
+ Result = TRUE;
+ }
+
+ } finally {
+
+ ExReleaseResource( Fcb->Resource );
+
+ FsRtlExitFileSystem();
+ }
+
+ return Result;
+}
+
+
+BOOLEAN
+CdFastQueryStdInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ IN OUT PFILE_STANDARD_INFORMATION Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is for the fast query call for standard file information.
+
+Arguments:
+
+ FileObject - Supplies the file object used in this operation
+
+ Wait - Indicates if we are allowed to wait for the information
+
+ Buffer - Supplies the output buffer to receive the basic information
+
+ IoStatus - Receives the final status of the operation
+
+Return Value:
+
+ BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
+ needs to take the long route.
+
+--*/
+
+{
+ BOOLEAN Result = FALSE;
+ TYPE_OF_OPEN TypeOfOpen;
+
+ PFCB Fcb;
+
+ PAGED_CODE();
+
+ ASSERT_FILE_OBJECT( FileObject );
+
+ FsRtlEnterFileSystem();
+
+ //
+ // Decode the file object to find the type of open and the data
+ // structures.
+ //
+
+ TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
+
+ //
+ // We only support this request on initialized user file or directory objects.
+ //
+
+ if ((TypeOfOpen != UserFileOpen) &&
+ ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ))) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Acquire the file shared to access the Fcb.
+ //
+
+ if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Use a try-finally to facilitate cleanup.
+ //
+
+ try {
+
+ //
+ // Only deal with 'good' Fcb's.
+ //
+
+ if (CdVerifyFcbOperation( NULL, Fcb )) {
+
+ //
+ // Check whether this is a directory.
+ //
+
+ if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
+
+ Buffer->AllocationSize.QuadPart =
+ Buffer->EndOfFile.QuadPart = 0;
+
+ Buffer->Directory = TRUE;
+
+ } else {
+
+ Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
+ Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
+
+ Buffer->Directory = FALSE;
+ }
+
+ Buffer->NumberOfLinks = 1;
+ Buffer->DeletePending = FALSE;
+
+ //
+ // Update the IoStatus block with the size of this data.
+ //
+
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION );
+
+ Result = TRUE;
+ }
+
+ } finally {
+
+ ExReleaseResource( Fcb->Resource );
+
+ FsRtlExitFileSystem();
+ }
+
+ return Result;
+}
+
+
+BOOLEAN
+CdFastQueryNetworkInfo (
+ IN PFILE_OBJECT FileObject,
+ IN BOOLEAN Wait,
+ OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PDEVICE_OBJECT DeviceObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is for the fast query call for network file information.
+
+Arguments:
+
+ FileObject - Supplies the file object used in this operation
+
+ Wait - Indicates if we are allowed to wait for the information
+
+ Buffer - Supplies the output buffer to receive the basic information
+
+ IoStatus - Receives the final status of the operation
+
+Return Value:
+
+ BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
+ needs to take the long route.
+
+--*/
+
+{
+ BOOLEAN Result = FALSE;
+ TYPE_OF_OPEN TypeOfOpen;
+
+ PFCB Fcb;
+
+ PAGED_CODE();
+
+ ASSERT_FILE_OBJECT( FileObject );
+
+ FsRtlEnterFileSystem();
+
+ //
+ // Decode the file object to find the type of open and the data
+ // structures.
+ //
+
+ TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
+
+ //
+ // We only support this request on user file or directory objects.
+ //
+
+ if ((TypeOfOpen != UserFileOpen) &&
+ ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Acquire the file shared to access the Fcb.
+ //
+
+ if (!ExAcquireResourceShared( Fcb->Resource, Wait )) {
+
+ FsRtlExitFileSystem();
+ return FALSE;
+ }
+
+ //
+ // Use a try-finally to facilitate cleanup.
+ //
+
+ try {
+
+ //
+ // Only deal with 'good' Fcb's.
+ //
+
+ if (CdVerifyFcbOperation( NULL, Fcb )) {
+
+ //
+ // Fill in the input buffer from the Fcb fields.
+ //
+
+ Buffer->CreationTime.QuadPart =
+ Buffer->LastWriteTime.QuadPart =
+ Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
+
+ Buffer->LastAccessTime.QuadPart = 0;
+
+ Buffer->FileAttributes = Fcb->FileAttributes;
+
+ //
+ // Check whether this is a directory.
+ //
+
+ if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
+
+ Buffer->AllocationSize.QuadPart =
+ Buffer->EndOfFile.QuadPart = 0;
+
+ } else {
+
+ Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
+ Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
+ }
+
+ //
+ // Update the IoStatus block with the size of this data.
+ //
+
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );
+
+ Result = TRUE;
+ }
+
+ } finally {
+
+ ExReleaseResource( Fcb->Resource );
+
+ FsRtlExitFileSystem();
+ }
+
+ return Result;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryBasicInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_BASIC_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+ Description:
+
+ This routine performs the query basic information function for Cdfs
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // We only support creation, last modify and last write times on Cdfs.
+ //
+
+ Buffer->LastWriteTime.QuadPart =
+ Buffer->CreationTime.QuadPart =
+ Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
+
+ Buffer->LastAccessTime.QuadPart = 0;
+
+ Buffer->FileAttributes = Fcb->FileAttributes;
+
+ //
+ // Update the length and status output variables
+ //
+
+ *Length -= sizeof( FILE_BASIC_INFORMATION );
+
+ return;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryStandardInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_STANDARD_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This routine performs the query standard information function for cdfs.
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // There is only one link and delete is never pending on a Cdrom file.
+ //
+
+ Buffer->NumberOfLinks = 1;
+ Buffer->DeletePending = FALSE;
+
+ //
+ // We get the sizes from the header. Return a size of zero
+ // for all directories.
+ //
+
+ if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
+
+ Buffer->AllocationSize.QuadPart =
+ Buffer->EndOfFile.QuadPart = 0;
+
+ Buffer->Directory = TRUE;
+
+ } else {
+
+ Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
+ Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
+
+ Buffer->Directory = FALSE;
+ }
+
+ //
+ // Update the length and status output variables
+ //
+
+ *Length -= sizeof( FILE_STANDARD_INFORMATION );
+
+ return;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryInternalInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_INTERNAL_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs the query internal information function for cdfs.
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // Index number is the file Id number in the Fcb.
+ //
+
+ Buffer->IndexNumber = Fcb->FileId;
+ *Length -= sizeof( FILE_INTERNAL_INFORMATION );
+
+ return;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryEaInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_EA_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs the query Ea information function for cdfs.
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // No Ea's on Cdfs volumes.
+ //
+
+ Buffer->EaSize = 0;
+ *Length -= sizeof( FILE_EA_INFORMATION );
+
+ return;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryPositionInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN OUT PFILE_POSITION_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs the query position information function for cdfs.
+
+Arguments:
+
+ FileObject - Supplies the File object being queried
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // Get the current position found in the file object.
+ //
+
+ Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
+
+ //
+ // Update the length and status output variables
+ //
+
+ *Length -= sizeof( FILE_POSITION_INFORMATION );
+
+ return;
+}
+
+
+//
+// Local support routine
+//
+
+NTSTATUS
+CdQueryNameInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN OUT PFILE_NAME_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs the query name information function for cdfs.
+
+Arguments:
+
+ FileObject - Supplies the file object containing the name.
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied.
+
+--*/
+
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ //
+ // If this a Unicode disk then simply copy the name in the file object to the
+ // user's buffer.
+ //
+
+ Buffer->FileNameLength = FileObject->FileName.Length;
+
+ if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {
+
+ Buffer->FileNameLength = *Length - sizeof( ULONG );
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, Buffer->FileNameLength );
+
+ //
+ // Reduce the available bytes by the amount stored into this buffer.
+ //
+
+ *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
+
+ return Status;
+}
+
+
+//
+// Local support routine
+//
+
+NTSTATUS
+CdQueryAlternateNameInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN PCCB Ccb,
+ IN OUT PFILE_NAME_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs the query alternate name information function.
+ We lookup the dirent for this file and then check if there is a
+ short name.
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified.
+
+ Ccb - Ccb for this open handle.
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned.
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer,
+ STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name,
+ STATUS_BUFFER_OVERFLOW otherwise.
+
+--*/
+
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DIRENT_ENUM_CONTEXT DirContext;
+ DIRENT Dirent;
+
+ PUNICODE_STRING NameToUse;
+ ULONG DirentOffset;
+
+ COMPOUND_PATH_ENTRY CompoundPathEntry;
+ FILE_ENUM_CONTEXT FileContext;
+
+ PFCB ParentFcb;
+ BOOLEAN ReleaseParentFcb = FALSE;
+
+ BOOLEAN CleanupFileLookup = FALSE;
+ BOOLEAN CleanupDirectoryLookup = FALSE;
+
+ WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ];
+ USHORT ShortNameLength;
+
+ PAGED_CODE();
+
+ //
+ // Initialize the buffer length to zero.
+ //
+
+ Buffer->FileNameLength = 0;
+
+ //
+ // If this is the root or this file was opened using a version number then
+ // there is no short name.
+ //
+
+ if ((Fcb == Fcb->Vcb->RootIndexFcb) ||
+ FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) {
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ //
+ // Use a try-finally to cleanup the structures.
+ //
+
+ try {
+
+ ParentFcb = Fcb->ParentFcb;
+ CdAcquireFileShared( IrpContext, ParentFcb );
+ ReleaseParentFcb = TRUE;
+
+ //
+ // Do an unsafe test to see if we need to create a file object.
+ //
+
+ if (ParentFcb->FileObject == NULL) {
+
+ CdCreateInternalStream( IrpContext, ParentFcb->Vcb, ParentFcb );
+ }
+
+ if (CdFidIsDirectory( Fcb->FileId)) {
+
+ //
+ // Fcb is for a directory, so we need to dig the dirent from the parent. In
+ // order to do this we need to get the name of the directory from its pathtable
+ // entry and then search in the parent for a matching dirent.
+ //
+ // This could be optimized somewhat.
+ //
+
+ CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
+ CdInitializeFileContext( IrpContext, &FileContext );
+
+ CleanupDirectoryLookup = TRUE;
+
+ CdLookupPathEntry( IrpContext,
+ CdQueryFidPathTableOffset( Fcb->FileId ),
+ Fcb->Ordinal,
+ FALSE,
+ &CompoundPathEntry );
+
+ CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE );
+
+ if (!CdFindDirectory( IrpContext,
+ ParentFcb,
+ &CompoundPathEntry.PathEntry.CdCaseDirName,
+ TRUE,
+ &FileContext )) {
+
+ //
+ // If we failed to find the child directory by name in the parent
+ // something is quite wrong with this disc.
+ //
+
+ CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
+ }
+
+ NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName;
+ DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset;
+
+ } else {
+
+ //
+ // Initialize the search dirent structures.
+ //
+
+ CdInitializeDirContext( IrpContext, &DirContext );
+ CdInitializeDirent( IrpContext, &Dirent );
+
+ CleanupFileLookup = TRUE;
+
+ CdLookupDirent( IrpContext,
+ ParentFcb,
+ CdQueryFidDirentOffset( Fcb->FileId ),
+ &DirContext );
+
+ CdUpdateDirentFromRawDirent( IrpContext,
+ ParentFcb,
+ &DirContext,
+ &Dirent );
+
+ //
+ // Now update the dirent name.
+ //
+
+ CdUpdateDirentName( IrpContext, &Dirent, TRUE );
+
+ NameToUse = &Dirent.CdCaseFileName.FileName;
+ DirentOffset = Dirent.DirentOffset;
+ }
+
+ //
+ // If the name is 8.3 then fail this request.
+ //
+
+ if (CdIs8dot3Name( IrpContext,
+ *NameToUse )) {
+
+
+ try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
+ }
+
+ CdGenerate8dot3Name( IrpContext,
+ NameToUse,
+ DirentOffset,
+ ShortNameBuffer,
+ &ShortNameLength );
+
+ //
+ // We now have the short name. We have left it in Unicode form so copy it directly.
+ //
+
+ Buffer->FileNameLength = ShortNameLength;
+
+ if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {
+
+ Buffer->FileNameLength = *Length - sizeof( ULONG );
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength );
+
+ try_exit: NOTHING;
+ } finally {
+
+ if (CleanupFileLookup) {
+
+ CdCleanupDirContext( IrpContext, &DirContext );
+ CdCleanupDirent( IrpContext, &Dirent );
+
+ } else if (CleanupDirectoryLookup) {
+
+ CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
+ CdCleanupFileContext( IrpContext, &FileContext );
+ }
+
+ if (ReleaseParentFcb) {
+
+ CdReleaseFile( IrpContext, ParentFcb );
+ }
+ }
+
+ //
+ // Reduce the available bytes by the amount stored into this buffer.
+ //
+
+ if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
+
+ *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
+ }
+
+ return Status;
+}
+
+
+//
+// Local support routine
+//
+
+VOID
+CdQueryNetworkInfo (
+ IN PIRP_CONTEXT IrpContext,
+ IN PFCB Fcb,
+ IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
+ IN OUT PULONG Length
+ )
+
+/*++
+
+ Description:
+
+ This routine performs the query network open information function for Cdfs
+
+Arguments:
+
+ Fcb - Supplies the Fcb being queried, it has been verified
+
+ Buffer - Supplies a pointer to the buffer where the information is to
+ be returned
+
+ Length - Supplies the length of the buffer in bytes, and receives the
+ remaining bytes free in the buffer upon return.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PAGED_CODE();
+
+ //
+ // We only support creation, last modify and last write times on Cdfs.
+ //
+
+ Buffer->LastWriteTime.QuadPart =
+ Buffer->CreationTime.QuadPart =
+ Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
+
+ Buffer->LastAccessTime.QuadPart = 0;
+
+ Buffer->FileAttributes = Fcb->FileAttributes;
+
+ //
+ // We get the sizes from the header. Return a size of zero
+ // for all directories.
+ //
+
+ if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
+
+ Buffer->AllocationSize.QuadPart =
+ Buffer->EndOfFile.QuadPart = 0;
+
+ } else {
+
+ Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
+ Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
+ }
+
+ //
+ // Update the length and status output variables
+ //
+
+ *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );
+
+ return;
+}