/* * ReactOS kernel * Copyright (C) 2002, 2003, 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/cdfs.c * PURPOSE: CDROM (ISO 9660) filesystem driver * PROGRAMMER: Art Yerkes * Eric Kohl */ /* INCLUDES *****************************************************************/ #include "cdfs.h" #define NDEBUG #include /* FUNCTIONS ****************************************************************/ static NTSTATUS CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject, PUNICODE_STRING RelativeFileName, PUNICODE_STRING AbsoluteFileName) { USHORT Length; PFCB Fcb; NTSTATUS Status; DPRINT("try related for %wZ\n", RelativeFileName); Fcb = FileObject->FsContext; ASSERT(Fcb); /* verify related object is a directory and target name don't start with \. */ if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 || (RelativeFileName->Length >= sizeof(WCHAR) && RelativeFileName->Buffer[0] == L'\\')) { return STATUS_INVALID_PARAMETER; } /* construct absolute path name */ Length = Fcb->PathName.Length + sizeof(WCHAR) + RelativeFileName->Length + sizeof(WCHAR); AbsoluteFileName->Length = 0; AbsoluteFileName->MaximumLength = Length; AbsoluteFileName->Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, CDFS_FILENAME_TAG); if (AbsoluteFileName->Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Status = RtlAppendUnicodeStringToString(AbsoluteFileName, &Fcb->PathName); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(AbsoluteFileName); return Status; } if (!CdfsFCBIsRoot(Fcb)) { Status = RtlAppendUnicodeToString(AbsoluteFileName, L"\\"); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(AbsoluteFileName); return Status; } } Status = RtlAppendUnicodeStringToString(AbsoluteFileName, RelativeFileName); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(AbsoluteFileName); return Status; } return STATUS_SUCCESS; } /* * FUNCTION: Opens a file */ static NTSTATUS CdfsOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PUNICODE_STRING FileName) { PFCB ParentFcb; PFCB Fcb; NTSTATUS Status; UNICODE_STRING AbsFileName; DPRINT("CdfsOpenFile(%p, %p, %wZ)\n", DeviceExt, FileObject, FileName); if (FileObject->RelatedFileObject) { DPRINT("Converting relative filename to absolute filename\n"); Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject, FileName, &AbsFileName); if (!NT_SUCCESS(Status)) { return Status; } FileName = &AbsFileName; } Status = CdfsDeviceIoControl (DeviceExt->StorageDevice, IOCTL_CDROM_CHECK_VERIFY, NULL, 0, NULL, 0, FALSE); DPRINT ("Status %lx\n", Status); if (!NT_SUCCESS(Status)) { DPRINT1 ("Status %lx\n", Status); return Status; } DPRINT("PathName to open: %wZ\n", FileName); /* try first to find an existing FCB in memory */ DPRINT("Checking for existing FCB in memory\n"); Fcb = CdfsGrabFCBFromTable(DeviceExt, FileName); if (Fcb == NULL) { DPRINT("No existing FCB found, making a new one if file exists.\n"); Status = CdfsGetFCBForFile(DeviceExt, &ParentFcb, &Fcb, FileName); if (ParentFcb != NULL) { CdfsReleaseFCB(DeviceExt, ParentFcb); } if (!NT_SUCCESS (Status)) { DPRINT("Could not make a new FCB, status: %x\n", Status); if (FileName == &AbsFileName) RtlFreeUnicodeString(&AbsFileName); return Status; } } DPRINT("Attaching FCB to fileObject\n"); Status = CdfsAttachFCBToFileObject(DeviceExt, Fcb, FileObject); if ((FileName == &AbsFileName) && AbsFileName.Buffer) ExFreePoolWithTag(AbsFileName.Buffer, CDFS_FILENAME_TAG); return Status; } /* * FUNCTION: Opens a file */ static NTSTATUS CdfsCreateFile(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExt; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; ULONG RequestedDisposition; ULONG RequestedOptions; PFCB Fcb; NTSTATUS Status; DPRINT("CdfsCreateFile() called\n"); DeviceExt = DeviceObject->DeviceExtension; ASSERT(DeviceExt); Stack = IoGetCurrentIrpStackLocation (Irp); ASSERT(Stack); RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; DPRINT("RequestedDisposition %x, RequestedOptions %x\n", RequestedDisposition, RequestedOptions); FileObject = Stack->FileObject; if (RequestedDisposition == FILE_CREATE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) { return STATUS_ACCESS_DENIED; } Status = CdfsOpenFile(DeviceExt, FileObject, &FileObject->FileName); if (NT_SUCCESS(Status)) { Fcb = FileObject->FsContext; /* Check whether the file has the requested attributes */ if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb)) { CdfsCloseFile (DeviceExt, FileObject); return STATUS_FILE_IS_A_DIRECTORY; } if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb)) { CdfsCloseFile (DeviceExt, FileObject); return STATUS_NOT_A_DIRECTORY; } DeviceExt->OpenHandleCount++; } /* * If the directory containing the file to open doesn't exist then * fail immediately */ Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0; return Status; } NTSTATUS NTAPI CdfsCreate( PCDFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; PDEVICE_EXTENSION DeviceExt; NTSTATUS Status; DPRINT("CdfsCreate()\n"); ASSERT(IrpContext); DeviceObject = IrpContext->DeviceObject; DeviceExt = DeviceObject->DeviceExtension; if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED)) { return STATUS_ACCESS_DENIED; } if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject) { /* DeviceObject represents FileSystem instead of logical volume */ DPRINT("Opening file system\n"); IrpContext->Irp->IoStatus.Information = FILE_OPENED; DeviceExt->OpenHandleCount++; return STATUS_SUCCESS; } KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); Status = CdfsCreateFile(DeviceObject, IrpContext->Irp); ExReleaseResourceLite(&DeviceExt->DirResource); KeLeaveCriticalRegion(); return Status; } /* EOF */