reactos/drivers/filesystems/cdfs/fileinfo.c
Joachim Henze 19f220bf51 [0.4.9][CDFS_NEW] -> [CDFS]
port back:
0.4.10-dev-615-g 45fd48bd0f [CDFS_NEW] -> [CDFS] No old driver, thus no new driver
0.4.10-dev-614-g 5795254933 [CDFS] Delete the old CDFS driver.

The new MS PL licensed one worked for several years fine for us now
even in the older releases.
So no need to keep our old unfinished one any longer within
the release-branches. They are no mausoleum.
This does *not* change, which driver is actually in use.
We do continue to use 1:1 the state of current releases/0.4.10
2023-03-23 22:09:06 +01:00

1532 lines
35 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
FileInfo.c
Abstract:
This module implements the File Information routines for Cdfs called by
the Fsd/Fsp dispatch drivers.
--*/
#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,
_Out_ PFILE_BASIC_INFORMATION Buffer,
_Inout_ PULONG Length
);
VOID
CdQueryStandardInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_Out_ PFILE_STANDARD_INFORMATION Buffer,
_Inout_ PULONG Length
);
VOID
CdQueryInternalInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_Out_ PFILE_INTERNAL_INFORMATION Buffer,
_Inout_ PULONG Length
);
VOID
CdQueryEaInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_Out_ PFILE_EA_INFORMATION Buffer,
_Inout_ PULONG Length
);
VOID
CdQueryPositionInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFILE_OBJECT FileObject,
_Out_ PFILE_POSITION_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryNameInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFILE_OBJECT FileObject,
_Out_ PFILE_NAME_INFORMATION Buffer,
_Inout_ PULONG Length
);
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdQueryAlternateNameInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_In_ PCCB Ccb,
_Out_ PFILE_NAME_INFORMATION Buffer,
_Inout_ PULONG Length
);
VOID
CdQueryNetworkInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
_Inout_ 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
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonQueryInfo (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ 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.
//
_SEH2_TRY {
//
// We only support query on file and directory handles.
//
switch (TypeOfOpen) {
case UserDirectoryOpen :
case UserFileOpen :
//
// Acquire shared access to this file. NOTE that this could be
// a recursive acquire, if we already preacquired in
// CdAcquireForCreateSection().
//
CdAcquireFileShared( IrpContext, Fcb );
ReleaseFcb = TRUE;
//
// Make sure we have the correct sizes for a directory.
//
if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {
NT_ASSERT( TypeOfOpen == UserDirectoryOpen );
CdVerifyOrCreateDirStreamFile( IrpContext, 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;
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 ));
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;
} _SEH2_FINALLY {
//
// Release the file.
//
if (ReleaseFcb) {
CdReleaseFile( IrpContext, Fcb );
}
} _SEH2_END;
//
// Complete the request if we didn't raise.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonSetInfo (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ 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 );
_SEH2_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 & Fcb->Vcb->BlockMask) != 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;
} _SEH2_FINALLY {
CdReleaseFile( IrpContext, Fcb );
} _SEH2_END;
//
// Complete the request if there was no raise.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
_Function_class_(FAST_IO_QUERY_BASIC_INFO)
_IRQL_requires_same_
_Success_(return != FALSE)
BOOLEAN
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdFastQueryBasicInfo (
_In_ PFILE_OBJECT FileObject,
_In_ BOOLEAN Wait,
_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();
UNREFERENCED_PARAMETER( DeviceObject );
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 (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
FsRtlExitFileSystem();
return FALSE;
}
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_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;
}
} _SEH2_FINALLY {
ExReleaseResourceLite( Fcb->Resource );
FsRtlExitFileSystem();
} _SEH2_END;
return Result;
}
_Function_class_(FAST_IO_QUERY_STANDARD_INFO)
_IRQL_requires_same_
_Success_(return != FALSE)
BOOLEAN
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdFastQueryStdInfo (
_In_ PFILE_OBJECT FileObject,
_In_ BOOLEAN Wait,
_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();
UNREFERENCED_PARAMETER( DeviceObject );
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 (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
FsRtlExitFileSystem();
return FALSE;
}
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_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;
}
} _SEH2_FINALLY {
ExReleaseResourceLite( Fcb->Resource );
FsRtlExitFileSystem();
} _SEH2_END;
return Result;
}
_Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
_IRQL_requires_same_
_Success_(return != FALSE)
BOOLEAN
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
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();
UNREFERENCED_PARAMETER( DeviceObject );
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 (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
FsRtlExitFileSystem();
return FALSE;
}
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_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;
}
} _SEH2_FINALLY {
ExReleaseResourceLite( Fcb->Resource );
FsRtlExitFileSystem();
} _SEH2_END;
return Result;
}
//
// Local support routine
//
VOID
CdQueryBasicInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_Out_ PFILE_BASIC_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
//
// 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,
_Out_ PFILE_STANDARD_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
//
// 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,
_Out_ PFILE_INTERNAL_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
//
// 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,
_Out_ PFILE_EA_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
UNREFERENCED_PARAMETER( Fcb );
//
// 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,
_Out_ PFILE_POSITION_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
//
// 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,
_Out_ PFILE_NAME_INFORMATION Buffer,
_Inout_ 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;
ULONG LengthToCopy;
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
NT_ASSERT(*Length >= sizeof(ULONG));
//
// Simply copy the name in the file object to the user's buffer.
//
//
// Place the size of the filename in the user's buffer and reduce the remaining
// size to match.
//
Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length;
*Length -= sizeof(ULONG);
if (LengthToCopy > *Length) {
LengthToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy );
//
// Reduce the available bytes by the amount stored into this buffer. In the overflow
// case, this simply drops to zero. The returned filenamelength will indicate to the
// caller how much space is required.
//
*Length -= LengthToCopy;
return Status;
}
//
// Local support routine
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdQueryAlternateNameInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PFCB Fcb,
_In_ PCCB Ccb,
_Out_ PFILE_NAME_INFORMATION Buffer,
_Inout_ 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 = {0};
DIRENT Dirent = {0};
PUNICODE_STRING NameToUse;
ULONG DirentOffset;
COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
FILE_ENUM_CONTEXT FileContext;
PFCB ParentFcb = NULL;
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.
//
_SEH2_TRY {
ParentFcb = Fcb->ParentFcb;
CdAcquireFileShared( IrpContext, ParentFcb );
ReleaseParentFcb = TRUE;
CdVerifyOrCreateDirStreamFile( IrpContext, 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;
} _SEH2_FINALLY {
if (CleanupFileLookup) {
CdCleanupDirContext( IrpContext, &DirContext );
CdCleanupDirent( IrpContext, &Dirent );/* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
} else if (CleanupDirectoryLookup) {
CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
CdCleanupFileContext( IrpContext, &FileContext );
}
if (ReleaseParentFcb) {
CdReleaseFile( IrpContext, ParentFcb );
}
} _SEH2_END;
//
// 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,
_Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
_Inout_ 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();
UNREFERENCED_PARAMETER( IrpContext );
//
// 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;
}