/* * ReactOS kernel * Copyright (C) 2002, 2004 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/filesystems/cdfs/finfo.c * PURPOSE: CDROM (ISO 9660) filesystem driver * PROGRAMMER: Art Yerkes * Eric Kohl * UPDATE HISTORY: */ /* INCLUDES *****************************************************************/ #include "cdfs.h" #define NDEBUG #include /* FUNCTIONS ****************************************************************/ /* * FUNCTION: Retrieve the standard file information */ static NTSTATUS CdfsGetStandardInformation(PFCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_STANDARD_INFORMATION StandardInfo, PULONG BufferLength) { DPRINT("CdfsGetStandardInformation() called\n"); UNREFERENCED_PARAMETER(DeviceObject); if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) return STATUS_BUFFER_OVERFLOW; /* PRECONDITION */ ASSERT(StandardInfo != NULL); ASSERT(Fcb != NULL); RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION)); if (CdfsFCBIsDirectory(Fcb)) { StandardInfo->AllocationSize.QuadPart = 0LL; StandardInfo->EndOfFile.QuadPart = 0LL; StandardInfo->Directory = TRUE; } else { StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize; StandardInfo->EndOfFile = Fcb->RFCB.FileSize; StandardInfo->Directory = FALSE; } StandardInfo->NumberOfLinks = 0; StandardInfo->DeletePending = FALSE; *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); return(STATUS_SUCCESS); } /* * FUNCTION: Retrieve the file position information */ static NTSTATUS CdfsGetPositionInformation(PFILE_OBJECT FileObject, PFILE_POSITION_INFORMATION PositionInfo, PULONG BufferLength) { DPRINT("CdfsGetPositionInformation() called\n"); if (*BufferLength < sizeof(FILE_POSITION_INFORMATION)) return STATUS_BUFFER_OVERFLOW; PositionInfo->CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart; DPRINT("Getting position %I64x\n", PositionInfo->CurrentByteOffset.QuadPart); *BufferLength -= sizeof(FILE_POSITION_INFORMATION); return(STATUS_SUCCESS); } /* * FUNCTION: Retrieve the basic file information */ static NTSTATUS CdfsGetBasicInformation(PFILE_OBJECT FileObject, PFCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_BASIC_INFORMATION BasicInfo, PULONG BufferLength) { DPRINT("CdfsGetBasicInformation() called\n"); UNREFERENCED_PARAMETER(FileObject); UNREFERENCED_PARAMETER(DeviceObject); if (*BufferLength < sizeof(FILE_BASIC_INFORMATION)) return STATUS_BUFFER_OVERFLOW; CdfsDateTimeToSystemTime(Fcb, &BasicInfo->CreationTime); CdfsDateTimeToSystemTime(Fcb, &BasicInfo->LastAccessTime); CdfsDateTimeToSystemTime(Fcb, &BasicInfo->LastWriteTime); CdfsDateTimeToSystemTime(Fcb, &BasicInfo->ChangeTime); CdfsFileFlagsToAttributes(Fcb, &BasicInfo->FileAttributes); *BufferLength -= sizeof(FILE_BASIC_INFORMATION); return(STATUS_SUCCESS); } /* * FUNCTION: Retrieve the file name information */ static NTSTATUS CdfsGetNameInformation(PFILE_OBJECT FileObject, PFCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_NAME_INFORMATION NameInfo, PULONG BufferLength) { ULONG NameLength; ULONG BytesToCopy; DPRINT("CdfsGetNameInformation() called\n"); ASSERT(NameInfo != NULL); ASSERT(Fcb != NULL); UNREFERENCED_PARAMETER(FileObject); UNREFERENCED_PARAMETER(DeviceObject); /* If buffer can't hold at least the file name length, bail out */ if (*BufferLength < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0])) return STATUS_BUFFER_OVERFLOW; /* Calculate file name length in bytes */ NameLength = Fcb->PathName.Length; NameInfo->FileNameLength = NameLength; /* Calculate amount of bytes to copy not to overflow the buffer */ BytesToCopy = min(NameLength, *BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0])); /* Fill in the bytes */ RtlCopyMemory(NameInfo->FileName, Fcb->PathName.Buffer, BytesToCopy); /* Check if we could write more but are not able to */ if (*BufferLength < NameLength + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0])) { /* Return number of bytes written */ *BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy; return STATUS_BUFFER_OVERFLOW; } /* We filled up as many bytes, as needed */ *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + NameLength); return STATUS_SUCCESS; } /* * FUNCTION: Retrieve the internal file information */ static NTSTATUS CdfsGetInternalInformation(PFCB Fcb, PFILE_INTERNAL_INFORMATION InternalInfo, PULONG BufferLength) { DPRINT("CdfsGetInternalInformation() called\n"); ASSERT(InternalInfo); ASSERT(Fcb); if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION)) return(STATUS_BUFFER_OVERFLOW); InternalInfo->IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart; *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION); return(STATUS_SUCCESS); } /* * FUNCTION: Retrieve the file network open information */ static NTSTATUS CdfsGetNetworkOpenInformation(PFCB Fcb, PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, PULONG BufferLength) { ASSERT(NetworkInfo); ASSERT(Fcb); if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION)) return(STATUS_BUFFER_OVERFLOW); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->CreationTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->LastAccessTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->LastWriteTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->ChangeTime); if (CdfsFCBIsDirectory(Fcb)) { NetworkInfo->AllocationSize.QuadPart = 0LL; NetworkInfo->EndOfFile.QuadPart = 0LL; } else { NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize; NetworkInfo->EndOfFile = Fcb->RFCB.FileSize; } CdfsFileFlagsToAttributes(Fcb, &NetworkInfo->FileAttributes); *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION); return(STATUS_SUCCESS); } /* * FUNCTION: Retrieve all file information */ static NTSTATUS CdfsGetAllInformation(PFILE_OBJECT FileObject, PFCB Fcb, PFILE_ALL_INFORMATION Info, PULONG BufferLength) { ULONG NameLength; ASSERT(Info); ASSERT(Fcb); NameLength = Fcb->PathName.Length; if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength) return(STATUS_BUFFER_OVERFLOW); /* Basic Information */ CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.CreationTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.LastAccessTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.LastWriteTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.ChangeTime); CdfsFileFlagsToAttributes(Fcb, &Info->BasicInformation.FileAttributes); /* Standard Information */ if (CdfsFCBIsDirectory(Fcb)) { Info->StandardInformation.AllocationSize.QuadPart = 0LL; Info->StandardInformation.EndOfFile.QuadPart = 0LL; Info->StandardInformation.Directory = TRUE; } else { Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize; Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize; Info->StandardInformation.Directory = FALSE; } Info->StandardInformation.NumberOfLinks = 0; Info->StandardInformation.DeletePending = FALSE; /* Internal Information */ Info->InternalInformation.IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart; /* EA Information */ Info->EaInformation.EaSize = 0; /* Access Information */ /* The IO-Manager adds this information */ /* Position Information */ Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart; /* Mode Information */ /* The IO-Manager adds this information */ /* Alignment Information */ /* The IO-Manager adds this information */ /* Name Information */ Info->NameInformation.FileNameLength = NameLength; RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName.Buffer, NameLength + sizeof(WCHAR)); *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR)); return STATUS_SUCCESS; } /* * FUNCTION: Retrieve the specified file information */ NTSTATUS NTAPI CdfsQueryInformation( PCDFS_IRP_CONTEXT IrpContext) { PIRP Irp; PDEVICE_OBJECT DeviceObject; FILE_INFORMATION_CLASS FileInformationClass; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; PFCB Fcb; PVOID SystemBuffer; ULONG BufferLength; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsQueryInformation() called\n"); Irp = IrpContext->Irp; DeviceObject = IrpContext->DeviceObject; Stack = IrpContext->Stack; FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; FileObject = Stack->FileObject; Fcb = FileObject->FsContext; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; BufferLength = Stack->Parameters.QueryFile.Length; switch (FileInformationClass) { case FileStandardInformation: Status = CdfsGetStandardInformation(Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FilePositionInformation: Status = CdfsGetPositionInformation(FileObject, SystemBuffer, &BufferLength); break; case FileBasicInformation: Status = CdfsGetBasicInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileNameInformation: Status = CdfsGetNameInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileInternalInformation: Status = CdfsGetInternalInformation(Fcb, SystemBuffer, &BufferLength); break; case FileNetworkOpenInformation: Status = CdfsGetNetworkOpenInformation(Fcb, SystemBuffer, &BufferLength); break; case FileAllInformation: Status = CdfsGetAllInformation(FileObject, Fcb, SystemBuffer, &BufferLength); break; case FileAlternateNameInformation: Status = STATUS_NOT_IMPLEMENTED; break; default: DPRINT("Unimplemented information class %x\n", FileInformationClass); Status = STATUS_INVALID_PARAMETER; break; } if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - BufferLength; else Irp->IoStatus.Information = 0; return(Status); } /* * FUNCTION: Set the file position information */ static NTSTATUS CdfsSetPositionInformation(PFILE_OBJECT FileObject, PFILE_POSITION_INFORMATION PositionInfo) { DPRINT ("CdfsSetPositionInformation()\n"); DPRINT ("PositionInfo %p\n", PositionInfo); DPRINT ("Setting position %I64d\n", PositionInfo->CurrentByteOffset.QuadPart); FileObject->CurrentByteOffset.QuadPart = PositionInfo->CurrentByteOffset.QuadPart; return STATUS_SUCCESS; } /* * FUNCTION: Set the specified file information */ NTSTATUS NTAPI CdfsSetInformation( PCDFS_IRP_CONTEXT IrpContext) { PIRP Irp; FILE_INFORMATION_CLASS FileInformationClass; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; PVOID SystemBuffer; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsSetInformation() called\n"); Irp = IrpContext->Irp; Stack = IrpContext->Stack; FileInformationClass = Stack->Parameters.SetFile.FileInformationClass; FileObject = Stack->FileObject; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; switch (FileInformationClass) { case FilePositionInformation: Status = CdfsSetPositionInformation(FileObject, SystemBuffer); break; case FileBasicInformation: case FileRenameInformation: Status = STATUS_NOT_IMPLEMENTED; break; default: Status = STATUS_NOT_SUPPORTED; break; } Irp->IoStatus.Information = 0; return Status; } /* EOF */