/*++ 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; }