xbox-kernel/private/ntos/gdfx/fileinfo.c
2020-09-30 17:17:25 +02:00

255 lines
6.8 KiB
C

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
fileinfo.c
Abstract:
This module implements routines related to handling
IRP_MJ_QUERY_INFORMATION and IRP_MJ_SET_INFORMATION.
--*/
#include "gdfx.h"
VOID
GdfxQueryNetworkOpenInformation(
IN PGDF_VOLUME_EXTENSION VolumeExtension,
IN PFILE_OBJECT FileObject,
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkOpenInformation
)
/*++
Routine Description:
This routine fills the information structure with attributes about the
supplied file object.
Arguments:
VolumeExtension - Specifies the extension that the I/O request is for.
FileObject - Specifies the file object to obtain the information from.
NetworkOpenInformation - Specifies the buffer to receive the file
information.
Return Value:
None.
--*/
{
PGDF_FCB Fcb;
LARGE_INTEGER TimeStamp;
Fcb = (PGDF_FCB)FileObject->FsContext;
TimeStamp = VolumeExtension->TimeStamp;
NetworkOpenInformation->CreationTime = TimeStamp;
NetworkOpenInformation->LastAccessTime = TimeStamp;
NetworkOpenInformation->LastWriteTime = TimeStamp;
NetworkOpenInformation->ChangeTime = TimeStamp;
if (GdfxIsFlagSet(Fcb->Flags, GDF_FCB_DIRECTORY)) {
NetworkOpenInformation->FileAttributes = FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_DIRECTORY;
NetworkOpenInformation->AllocationSize.QuadPart = 0;
NetworkOpenInformation->EndOfFile.QuadPart = 0;
} else {
NetworkOpenInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
NetworkOpenInformation->AllocationSize.QuadPart = (ULONGLONG)Fcb->FileSize;
NetworkOpenInformation->EndOfFile.QuadPart = (ULONGLONG)Fcb->FileSize;
}
}
NTSTATUS
GdfxFsdQueryInformation(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O manager to handle IRP_MJ_QUERY_INFORMATION
requests.
Arguments:
DeviceObject - Specifies the device object that the I/O request is for.
Irp - Specifies the packet that describes the I/O request.
Return Value:
Status of operation.
--*/
{
NTSTATUS status;
PGDF_VOLUME_EXTENSION VolumeExtension;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
PGDF_FCB Fcb;
ULONG BytesWritten;
PFILE_INTERNAL_INFORMATION InternalInformation;
PFILE_POSITION_INFORMATION PositionInformation;
VolumeExtension = (PGDF_VOLUME_EXTENSION)DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpSp->FileObject;
Fcb = (PGDF_FCB)FileObject->FsContext;
//
// For volume file control blocks, the only thing that can be queried is the
// current file position.
//
if (GdfxIsFlagSet(Fcb->Flags, GDF_FCB_VOLUME) &&
(IrpSp->Parameters.SetFile.FileInformationClass != FilePositionInformation)) {
status = STATUS_INVALID_PARAMETER;
goto CleanupAndExit;
}
//
// Clear the output buffer.
//
RtlZeroMemory(Irp->UserBuffer, IrpSp->Parameters.QueryFile.Length);
//
// Dispatch the information class function.
//
status = STATUS_SUCCESS;
switch (IrpSp->Parameters.QueryFile.FileInformationClass) {
case FileInternalInformation:
InternalInformation = (PFILE_INTERNAL_INFORMATION)Irp->UserBuffer;
InternalInformation->IndexNumber.HighPart = PtrToUlong(VolumeExtension);
InternalInformation->IndexNumber.LowPart = PtrToUlong(Fcb);
BytesWritten = sizeof(FILE_INTERNAL_INFORMATION);
break;
case FilePositionInformation:
PositionInformation = (PFILE_POSITION_INFORMATION)Irp->UserBuffer;
PositionInformation->CurrentByteOffset = FileObject->CurrentByteOffset;
BytesWritten = sizeof(FILE_POSITION_INFORMATION);
break;
case FileNetworkOpenInformation:
GdfxQueryNetworkOpenInformation(VolumeExtension, FileObject,
(PFILE_NETWORK_OPEN_INFORMATION)Irp->UserBuffer);
BytesWritten = sizeof(FILE_NETWORK_OPEN_INFORMATION);
break;
default:
BytesWritten = 0;
status = STATUS_INVALID_PARAMETER;
break;
}
//
// Fill in the number of bytes that we wrote to the user's buffer.
//
Irp->IoStatus.Information = BytesWritten;
//
// Check that we didn't overflow the user's buffer. The I/O manager does
// the initial check to make sure there's enough space for the static
// structure for a given information class, but we might overflow the buffer
// when copying in the variable length file name.
//
ASSERT(Irp->IoStatus.Information <= IrpSp->Parameters.QueryFile.Length);
CleanupAndExit:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
GdfxFsdSetInformation(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O manager to handle IRP_MJ_SET_INFORMATION
requests.
Arguments:
DeviceObject - Specifies the device object that the I/O request is for.
Irp - Specifies the packet that describes the I/O request.
Return Value:
Status of operation.
--*/
{
NTSTATUS status;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
PFILE_POSITION_INFORMATION PositionInformation;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpSp->FileObject;
//
// The only thing that can be set is the current file position.
//
if (IrpSp->Parameters.SetFile.FileInformationClass != FilePositionInformation) {
status = STATUS_INVALID_PARAMETER;
goto CleanupAndExit;
}
PositionInformation = (PFILE_POSITION_INFORMATION)Irp->UserBuffer;
//
// If the file was opened without intermediate buffering, then the byte
// offset must be sector aligned.
//
// Note that we don't use GDF_SECTOR_CD_MASK here so that the generated code
// ends up being identical to RawxFsdSetInformation. The linker will take
// care of collapsing the two functions.
//
if (GdfxIsFlagSet(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) &&
(PositionInformation->CurrentByteOffset.LowPart &
(DeviceObject->SectorSize - 1)) != 0) {
status = STATUS_INVALID_PARAMETER;
goto CleanupAndExit;
}
//
// Update the current file position.
//
FileObject->CurrentByteOffset = PositionInformation->CurrentByteOffset;
status = STATUS_SUCCESS;
CleanupAndExit:
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}