From: Eric Kohl Date: Mon, 15 Apr 2002 20:39:49 +0000 (+0000) Subject: Split the driver into more files. X-Git-Tag: backups/mpw@12443~97 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=3730336e4de5504d10ec4bd1354c95b2905e3ddd Split the driver into more files. Replaced FCB code. Improved the mount code. svn path=/trunk/; revision=2851 --- diff --git a/reactos/drivers/fs/cdfs/cdfs.c b/reactos/drivers/fs/cdfs/cdfs.c index b36b31f8d15..dec55315dd8 100644 --- a/reactos/drivers/fs/cdfs/cdfs.c +++ b/reactos/drivers/fs/cdfs/cdfs.c @@ -1,4 +1,23 @@ /* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: cdfs.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: services/fs/cdfs/cdfs.c @@ -16,695 +35,16 @@ #include "cdfs.h" -typedef struct -{ - PDEVICE_OBJECT StorageDevice; - PFILE_OBJECT StreamFileObject; - struct _fcb_system *fss; - - PFCB RootFcb; - -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; /* GLOBALS *****************************************************************/ -static PDRIVER_OBJECT DriverObject; - -/* FUNCTIONS ****************************************************************/ - -/* DIRECTORY FUNCTIONS ******************************************************/ -/* Hacked until working directory code... */ - -NTSTATUS -FsdGetRootDirectoryData(PDEVICE_OBJECT DeviceObject, - PFCB RootFcb) -{ - PPVD Buffer; - NTSTATUS Status; - - Buffer = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR ); - if (Buffer == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - Status = CdfsReadSectors(DeviceObject, - CDFS_PRIMARY_DESCRIPTOR_LOCATION, - 1, - Buffer); - if (!NT_SUCCESS(Status)) - return Status; - - RootFcb->extent_start = Buffer->RootDirRecord.ExtentLocationL; - RootFcb->byte_count = Buffer->RootDirRecord.DataLengthL; - - ExFreePool(Buffer); - - DPRINT1("RootFcb->extent_start %lu\n", RootFcb->extent_start); - DPRINT1("RootFcb->byte_count %lu\n", RootFcb->byte_count); - - return(STATUS_SUCCESS); -} - - - -/* HACK -- NEEDS FIXING */ - -int -FsdExtractDirectoryEntry(PDEVICE_EXTENSION DeviceExt, - FsdFcbEntry *parent, - FsdFcbEntry *fill_in, - int entry_to_get) -{ - switch( entry_to_get ) - { - case 0: - wcscpy( fill_in->name, L"." ); - fill_in->extent_start = parent->extent_start; - fill_in->byte_count = parent->byte_count; - break; - - case 1: - wcscpy( fill_in->name, L".." ); - fill_in->extent_start = parent->extent_start; - fill_in->byte_count = parent->byte_count; - break; - - case 2: - wcscpy( fill_in->name, L"readme.txt" ); - fill_in->extent_start = 0x190; - fill_in->byte_count = 0x800; - break; - - default: - return 1; - } - - return 0; -} - - -FsdFcbEntry *FsdSearchDirectoryAt( PDEVICE_EXTENSION DeviceExt, - FsdFcbEntry *parent, - wchar_t *look_for ) -{ - FsdFcbEntry *ent; - int i; - - ent = FsdCreateFcb( DeviceExt->fss, parent, look_for ); - if( ent ) - return ent; - - for( i = 0; i < parent->byte_count; i++ ) { - FsdFcbEntry new_ent; - if( FsdExtractDirectoryEntry( DeviceExt, parent, &new_ent, i ) ) - return NULL; - - if( !_wcsicmp( new_ent.name, look_for ) ) { - ent->extent_start = new_ent.extent_start; - ent->byte_count = new_ent.byte_count; - return ent; - } - } - - /* Not found */ - FsdDelete( ent ); - - return NULL; -} - -NTSTATUS -FsdCloseFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject) -/* - * FUNCTION: Closes a file - */ -{ - return(STATUS_SUCCESS); -} - -/* Should go into a basic library */ -PFCB -FsdSearchDirectory(PDEVICE_EXTENSION DeviceExt, - PFCB ParentFcb, - PWSTR filename) -{ - wchar_t *string_imed = NULL; - wchar_t *string_end = NULL; - FsdFcbEntry *this_elt = NULL; - - DPRINT1("FsdSearchDirectory(%S) called\n", filename); - - if (ParentFcb == NULL && *filename == 0) - return(DeviceExt->RootFcb); - -CHECKPOINT1; - string_imed = ExAllocatePool(NonPagedPool, - (wcslen( filename ) + 1) * sizeof( wchar_t ) ); - - if (string_imed == NULL) - return NULL; - - wcscpy( string_imed, filename ); - - - /* Chop off a component and try it */ - string_end = wcschr( string_imed, L'\\' ); - if (string_end != NULL) - { - *string_end = 0; - string_end++; - } -CHECKPOINT1; - - if (ParentFcb == NULL) - this_elt = FsdGetFcbEntry(DeviceExt->fss, NULL, L"\\"); - else - this_elt = FsdGetFcbEntry(DeviceExt->fss, ParentFcb, string_imed); -DPRINT1("this_elt %p\n", this_elt); - - if (this_elt) - { - ExFreePool( string_imed ); -CHECKPOINT1; - return this_elt; - } - -CHECKPOINT1; - this_elt = FsdSearchDirectoryAt( DeviceExt, ParentFcb, string_imed ); -CHECKPOINT1; - - /* It's the end if we have nothing more to do */ - if (string_end != NULL) - this_elt = FsdSearchDirectory( DeviceExt, this_elt, string_end ); -CHECKPOINT1; - - ExFreePool( string_imed ); - - DPRINT1("FsdSearchDirectory() done"); - - return this_elt; -} - - -NTSTATUS -FsdOpenFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject, - PWSTR FileName) -/* - * FUNCTION: Opens a file - */ -{ - PFCB Fcb; - - DPRINT1("FsdOpenFile(FileName %S) called\n", FileName); - - /* Just skip leading backslashes... */ - while (*FileName == L'\\') - FileName++; -CHECKPOINT1; - - Fcb = FsdSearchDirectory(DeviceExt->fss, - NULL, - FileName); -CHECKPOINT1; - if (Fcb == NULL) - { - DPRINT1("FsdSearchDirectory() failed\n"); - return(STATUS_OBJECT_PATH_NOT_FOUND); - } -CHECKPOINT1; - - FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; - FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; - FileObject->FsContext = Fcb; - FileObject->FsContext2 = DeviceExt->fss; - - DPRINT1("FsdOpenFile() done\n"); - - return(STATUS_SUCCESS); -} - - -BOOLEAN -FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount) -/* - * FUNCTION: Tests if the device contains a filesystem that can be mounted - * by this fsd - */ -{ - PUCHAR bytebuf; // [CDFS_BASIC_SECTOR]; - NTSTATUS readstatus; - int ret; - - bytebuf = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR ); - if( !bytebuf ) return FALSE; - - DPRINT1( "CDFS: Checking on mount of device %08x\n", DeviceToMount ); - - readstatus = CdfsReadSectors(DeviceToMount, - CDFS_PRIMARY_DESCRIPTOR_LOCATION, - 1, - bytebuf); - bytebuf[6] = 0; - DPRINT1( "CD-identifier: [%.5s]\n", bytebuf + 1 ); - - ret = - readstatus == STATUS_SUCCESS && - bytebuf[0] == 1 && - bytebuf[1] == 'C' && - bytebuf[2] == 'D' && - bytebuf[3] == '0' && - bytebuf[4] == '0' && - bytebuf[5] == '1'; - - ExFreePool( bytebuf ); - - return ret; -} - -NTSTATUS -FsdMountDevice(PDEVICE_EXTENSION DeviceExt, - PDEVICE_OBJECT DeviceToMount) -/* - * FUNCTION: Mounts the device - */ -{ - return(STATUS_SUCCESS); -} - - -NTSTATUS -FsdReadFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject, - PVOID Buffer, - ULONG Length, - ULONG Offset) -/* - * FUNCTION: Reads data from a file - */ -{ - PUCHAR bytebuf; // [CDFS_BASIC_SECTOR]; - NTSTATUS Status; - int ret; - int sofar = 0; - FsdFcbEntry *ffe = FileObject->FsContext; - - if( Length ) return STATUS_SUCCESS; - - bytebuf = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR ); - if (!bytebuf) - return FALSE; - - if (Offset + Length > ffe->byte_count) - Length = ffe->byte_count - Offset; - - DPRINT1( "Reading %d bytes at %d\n", Offset, Length ); - - if( Length == 0 ) return STATUS_UNSUCCESSFUL; - - while( sofar < Length ) - { - int remains = 0; - - Status = CdfsReadSectors(DeviceExt->StorageDevice, - ffe->extent_start + (sofar >> 11), - 1, - bytebuf); - if (!NT_SUCCESS(Status)) - { - ExFreePool( bytebuf ); - return(Status); - } - - remains = Length - sofar; - if (remains > BLOCKSIZE) - remains = BLOCKSIZE; - - memcpy( ((char *)Buffer) + sofar, bytebuf, remains ); - sofar += remains; - } - - ExFreePool( bytebuf ); - - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -FsdClose(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - PFILE_OBJECT FileObject = Stack->FileObject; - PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; - NTSTATUS Status; - - DPRINT1( "Closing\n" ); - - Status = FsdCloseFile(DeviceExtension,FileObject); - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return(Status); -} - -NTSTATUS STDCALL -FsdCreate(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - PFILE_OBJECT FileObject = Stack->FileObject; - NTSTATUS Status; - PDEVICE_EXTENSION DeviceExt; - - DeviceExt = DeviceObject->DeviceExtension; - Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer); - - Irp->IoStatus.Status = Status; - if (Status == STATUS_SUCCESS) - Irp->IoStatus.Information = FILE_OPENED; - else - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return(Status); -} - - -NTSTATUS STDCALL -FsdWrite(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp); - - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - return(STATUS_UNSUCCESSFUL); -} - -NTSTATUS STDCALL -FsdRead(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - ULONG Length; - PVOID Buffer; - ULONG Offset; - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - PFILE_OBJECT FileObject = Stack->FileObject; - PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; - NTSTATUS Status; - - DPRINT1("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); - - Length = Stack->Parameters.Read.Length; - Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); - Offset = Stack->Parameters.Read.ByteOffset.u.LowPart; - - Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset); - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = Length; - IoCompleteRequest(Irp,IO_NO_INCREMENT); - return(Status); -} - -// XXX The VPB in devicetomount may be null for some reason... -NTSTATUS -FsdMountVolume(PIRP Irp) -{ - PDEVICE_OBJECT DeviceObject = NULL; - PDEVICE_OBJECT DeviceToMount; - PDEVICE_EXTENSION DeviceExt = NULL; - PIO_STACK_LOCATION Stack; - NTSTATUS Status; - - DPRINT1("FsdMountVolume() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; - - if (FsdHasFileSystem(DeviceToMount) == FALSE) - return(STATUS_UNRECOGNIZED_VOLUME); - - Status = IoCreateDevice(DriverObject, - sizeof(DEVICE_EXTENSION), - NULL, - FILE_DEVICE_CD_ROM_FILE_SYSTEM, - 0, - FALSE, - &DeviceObject); - if (!NT_SUCCESS(Status)) - return(Status); - - DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; - DeviceExt = (PVOID)DeviceObject->DeviceExtension; - RtlZeroMemory(DeviceExt,sizeof(DEVICE_EXTENSION)); - - DeviceExt->fss = FsdFcbInit(); - if (!DeviceExt->fss) - return(STATUS_UNSUCCESSFUL); - - DeviceExt->RootFcb = FsdCreateFcb(DeviceExt->fss, NULL, L"\\"); - Status = FsdGetRootDirectoryData(DeviceToMount, DeviceExt->RootFcb); - - DeviceObject->Vpb = DeviceToMount->Vpb; - if (DeviceObject->Vpb != NULL) - DeviceObject->Vpb->Flags |= VPB_MOUNTED; - -#if 0 - Status = FsdMountDevice(DeviceExt, - DeviceToMount); - if (!NT_SUCCESS(Status)) - return(Status); -#endif - - DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, - DeviceToMount); - - DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, - DeviceExt->StorageDevice); - - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - NTSTATUS Status; - - DPRINT1("CDFS FsdFileSystemControl() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) - { - case IRP_MN_USER_FS_REQUEST: - DPRINT("CDFS: IRP_MN_USER_FS_REQUEST\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - - case IRP_MN_MOUNT_VOLUME: - DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n"); - Status = FsdMountVolume(Irp); - break; +PCDFS_GLOBAL_DATA CdfsGlobalData; - case IRP_MN_VERIFY_VOLUME: - DPRINT("CDFS: IRP_MN_VERIFY_VOLUME\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - - default: - DPRINT("CDFS FSC: MinorFunction %d\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); -} - - -NTSTATUS STDCALL -FsdDirectoryControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - NTSTATUS Status; - - DPRINT1("FsdDirectoryControl() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) - { -#if 0 - case IRP_MN_USER_FS_REQUEST: - DPRINT("CDFS: IRP_MN_USER_FS_REQUEST\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - - case IRP_MN_MOUNT_VOLUME: - DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n"); - Status = FsdMountVolume(Irp); - break; - - case IRP_MN_VERIFY_VOLUME: - DPRINT("CDFS: IRP_MN_VERIFY_VOLUME\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; -#endif - - default: - DPRINT("CDFS FSC: MinorFunction %d\n", Stack->MinorFunction); - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); -} - - -static NTSTATUS -FsdQueryNameInformation(PFILE_OBJECT FileObject, - PFCB Fcb, - PDEVICE_OBJECT DeviceObject, - PFILE_NAME_INFORMATION NameInfo, - PULONG BufferLength) -/* - * FUNCTION: Retrieve the file name information - */ -{ - ULONG NameLength; - - assert (NameInfo != NULL); - assert (Fcb != NULL); - -#if 0 - NameLength = wcslen(FCB->PathName) * sizeof(WCHAR); - if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength) - return STATUS_BUFFER_OVERFLOW; - - NameInfo->FileNameLength = NameLength; - memcpy(NameInfo->FileName, - FCB->PathName, - NameLength + sizeof(WCHAR)); -#endif - - /* Fake name */ - NameLength = 2; - wcscpy(NameInfo->FileName, L"\\"); - - *BufferLength -= - (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); - - return STATUS_SUCCESS; -} - -NTSTATUS STDCALL -FsdQueryInformation(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -/* - * FUNCTION: Retrieve the specified file information - */ -{ - FILE_INFORMATION_CLASS FileInformationClass; - PIO_STACK_LOCATION Stack; - PFILE_OBJECT FileObject; - PFCB Fcb; - PVOID SystemBuffer; - ULONG BufferLength; - - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT1("FsdQueryInformation() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; - FileObject = Stack->FileObject; - Fcb = FileObject->FsContext; - - SystemBuffer = Irp->AssociatedIrp.SystemBuffer; - BufferLength = Stack->Parameters.QueryFile.Length; - - switch (FileInformationClass) - { -#if 0 - case FileStandardInformation: - Status = VfatGetStandardInformation(Fcb, - IrpContext->DeviceObject, - SystemBuffer, - &BufferLength); - break; - case FilePositionInformation: - RC = VfatGetPositionInformation(IrpContext->FileObject, - FCB, - IrpContext->DeviceObject, - SystemBuffer, - &BufferLength); - break; - case FileBasicInformation: - RC = VfatGetBasicInformation(FileObject, - FCB, - DeviceObject, - SystemBuffer, - &BufferLength); - break; -#endif - - case FileNameInformation: - Status = FsdQueryNameInformation(FileObject, - Fcb, - DeviceObject, - SystemBuffer, - &BufferLength); - break; - -#if 0 - case FileInternalInformation: - Status = FsdGetInternalInformation(Fcb, - SystemBuffer, - &BufferLength); - break; - - case FileAlternateNameInformation: - case FileAllInformation: - Status = STATUS_NOT_IMPLEMENTED; - break; -#endif - default: - DPRINT("Unimplemented information class %u\n", FileInformationClass); - Status = STATUS_NOT_SUPPORTED; - } - - Irp->IoStatus.Status = Status; - if (NT_SUCCESS(Status)) - Irp->IoStatus.Information = - Stack->Parameters.QueryFile.Length - BufferLength; - else - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); -} +/* FUNCTIONS ****************************************************************/ NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT _DriverObject, +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* * FUNCTION: Called by the system to initalize the driver @@ -720,12 +60,10 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, DbgPrint("CDFS 0.0.1\n"); - DriverObject = _DriverObject; - RtlInitUnicodeString(&DeviceName, L"\\Device\\cdfs"); Status = IoCreateDevice(DriverObject, - 0, + sizeof(CDFS_GLOBAL_DATA), &DeviceName, FILE_DEVICE_CD_ROM_FILE_SYSTEM, 0, @@ -736,17 +74,30 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, return(Status); } + /* Initialize global data */ + CdfsGlobalData = DeviceObject->DeviceExtension; + RtlZeroMemory(CdfsGlobalData, + sizeof(CDFS_GLOBAL_DATA)); + CdfsGlobalData->DriverObject = DriverObject; + CdfsGlobalData->DeviceObject = DeviceObject; + + /* Initialize driver data */ DeviceObject->Flags = DO_DIRECT_IO; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose; - DriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate; - DriverObject->MajorFunction[IRP_MJ_READ] = FsdRead; - DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = CdfsClose; + DriverObject->MajorFunction[IRP_MJ_CREATE] = CdfsCreate; + DriverObject->MajorFunction[IRP_MJ_READ] = CdfsRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = CdfsWrite; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = - FsdFileSystemControl; + CdfsFileSystemControl; DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = - FsdDirectoryControl; + CdfsDirectoryControl; DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = - FsdQueryInformation; + CdfsQueryInformation; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + CdfsQueryVolumeInformation; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = + CdfsSetVolumeInformation; + DriverObject->DriverUnload = NULL; IoRegisterFileSystem(DeviceObject); diff --git a/reactos/drivers/fs/cdfs/cdfs.h b/reactos/drivers/fs/cdfs/cdfs.h index 4279624012c..40798877a84 100644 --- a/reactos/drivers/fs/cdfs/cdfs.h +++ b/reactos/drivers/fs/cdfs/cdfs.h @@ -8,6 +8,14 @@ #define BLOCKSIZE CDFS_BASIC_SECTOR #define CDFS_MAX_NAME_LEN 256 + +/* Volume descriptor types (VdType) */ +#define BOOT_VOLUME_DESCRIPTOR_TYPE 0 +#define PRIMARY_VOLUME_DESCRIPTOR_TYPE 1 +#define SUPPLEMENTARY_VOLUME_DESCRIPTOR_TYPE 2 +#define VOLUME_PARTITION_DESCRIPTOR_TYPE 3 +#define VOLUME_DESCRIPTOR_SET_TERMINATOR 255 + struct _DIR_RECORD { UCHAR RecordLength; // 1 @@ -31,32 +39,48 @@ struct _DIR_RECORD UCHAR FileId[1]; // 34 } __attribute__((packed)); -typedef struct _DIR_RECORD DIR_RECORD, PDIR_RECORD; +typedef struct _DIR_RECORD DIR_RECORD, *PDIR_RECORD; + + + + +/* Volume Descriptor header*/ +struct _VD_HEADER +{ + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 +} __attribute__((packed)); + +typedef struct _VD_HEADER VD_HEADER, *PVD_HEADER; + /* Primary Volume Descriptor */ struct _PVD { - unsigned char VdType; // 1 - unsigned char StandardId[5]; // 2-6 - unsigned char VdVersion; // 7 - unsigned char unused0; // 8 - unsigned char SystemId[32]; // 9-40 - unsigned char VolumeId[32]; // 41-72 - unsigned char unused1[8]; // 73-80 - unsigned long VolumeSpaceSizeL; // 81-84 - unsigned long VolumeSpaceSizeM; // 85-88 - unsigned char unused2[32]; // 89-120 - unsigned long VolumeSetSize; // 121-124 - unsigned long VolumeSequenceNumber; // 125-128 - unsigned long LogicalBlockSize; // 129-132 - unsigned long PathTableSizeL; // 133-136 - unsigned long PathTableSizeM; // 137-140 - ULONG LPathTablePos; // 141-144 - ULONG LOptPathTablePos; // 145-148 - ULONG MPathTablePos; // 149-152 - ULONG MOptPathTablePos; // 153-156 + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 + UCHAR unused0; // 8 + UCHAR SystemId[32]; // 9-40 + UCHAR VolumeId[32]; // 41-72 + UCHAR unused1[8]; // 73-80 + ULONG VolumeSpaceSizeL; // 81-84 + ULONG VolumeSpaceSizeM; // 85-88 + UCHAR unused2[32]; // 89-120 + ULONG VolumeSetSize; // 121-124 + ULONG VolumeSequenceNumber; // 125-128 + ULONG LogicalBlockSize; // 129-132 + ULONG PathTableSizeL; // 133-136 + ULONG PathTableSizeM; // 137-140 + ULONG LPathTablePos; // 141-144 + ULONG LOptPathTablePos; // 145-148 + ULONG MPathTablePos; // 149-152 + ULONG MOptPathTablePos; // 153-156 DIR_RECORD RootDirRecord; // 157-190 + UCHAR VolumeSetIdentifier[128]; // 191-318 + UCHAR PublisherIdentifier[128]; // 319-446 /* more data ... */ @@ -65,23 +89,128 @@ struct _PVD typedef struct _PVD PVD, *PPVD; +/* Supplementary Volume Descriptor */ +struct _SVD +{ + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 + UCHAR VolumeFlags; // 8 + UCHAR SystemId[32]; // 9-40 + UCHAR VolumeId[32]; // 41-72 + UCHAR unused1[8]; // 73-80 + ULONG VolumeSpaceSizeL; // 81-84 + ULONG VolumeSpaceSizeM; // 85-88 + UCHAR EscapeSequences[32]; // 89-120 + ULONG VolumeSetSize; // 121-124 + ULONG VolumeSequenceNumber; // 125-128 + ULONG LogicalBlockSize; // 129-132 + ULONG PathTableSizeL; // 133-136 + ULONG PathTableSizeM; // 137-140 + ULONG LPathTablePos; // 141-144 + ULONG LOptPathTablePos; // 145-148 + ULONG MPathTablePos; // 149-152 + ULONG MOptPathTablePos; // 153-156 + DIR_RECORD RootDirRecord; // 157-190 + UCHAR VolumeSetIdentifier[128]; // 191-318 + UCHAR PublisherIdentifier[128]; // 319-446 + + // more data ... +} __attribute__((packed)); + +typedef struct _SVD SVD, *PSVD; + + + + + + + +typedef struct _CDINFO +{ + ULONG VolumeSpaceSize; + ULONG JolietLevel; + ULONG RootStart; + ULONG RootSize; + +} CDINFO, *PCDINFO; + + +typedef struct +{ + ERESOURCE DirResource; +// ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT StreamFileObject; + + CDINFO CdInfo; + + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + + +#define FCB_CACHE_INITIALIZED 0x0001 typedef struct _FCB { REACTOS_COMMON_FCB_HEADER RFCB; SECTION_OBJECT_POINTERS SectionObjectPointers; - /* CDFS owned elements */ + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DevExt; + + WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */ + WCHAR PathName[MAX_PATH]; /* path+filename 260 max */ + +// ERESOURCE PagingIoResource; + ERESOURCE MainResource; - struct _FCB *next; - struct _FCB *parent; + LIST_ENTRY FcbListEntry; + struct _FCB* ParentFcb; - wchar_t name[CDFS_MAX_NAME_LEN]; - int hashval; - unsigned int extent_start; - unsigned int byte_count; - unsigned int file_pointer; -} FsdFcbEntry, FCB, *PFCB; + ULONG DirIndex; + + LONG RefCount; + ULONG Flags; + + DIR_RECORD Entry; + + +} FCB, *PFCB; + + +typedef struct _CCB +{ + PFCB Fcb; + LIST_ENTRY NextCCB; + PFILE_OBJECT PtrFileObject; + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + /* for DirectoryControl */ + PWCHAR DirectorySearchPattern; + ULONG LastCluster; + ULONG LastOffset; +} CCB, *PCCB; + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define TAG_CCB TAG('I', 'C', 'C', 'B') + + + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; +} CDFS_GLOBAL_DATA, *PCDFS_GLOBAL_DATA; + +extern PCDFS_GLOBAL_DATA CdfsGlobalData; NTSTATUS @@ -94,23 +223,117 @@ int CdfsStrcmpi( wchar_t *str1, wchar_t *str2 ); void CdfsWstrcpy( wchar_t *str1, wchar_t *str2, int max ); -/* - CDFS: FCB system (Perhaps there should be a library to make this easier) -*/ -typedef struct _fcb_system -{ - int fcbs_in_use; - int fcb_table_size; - int fcb_table_mask; - FsdFcbEntry **fcb_table; - FsdFcbEntry *parent; -} fcb_system; +/* close.c */ + +NTSTATUS STDCALL +CdfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* create.c */ + +NTSTATUS STDCALL +CdfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* dirctl.c */ + +NTSTATUS STDCALL +CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* fcb.c */ +PFCB +CdfsCreateFCB(PWCHAR FileName); + +VOID +CdfsDestroyFCB(PFCB Fcb); + +BOOLEAN +CdfsFCBIsDirectory(PFCB Fcb); + +BOOLEAN +CdfsFCBIsRoot(PFCB Fcb); + +VOID +CdfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +CdfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +PFCB +CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName); + +NTSTATUS +CdfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb); PFCB -FsdGetFcbEntry(fcb_system *fss, - PFCB ParentFcb, - PWSTR name); +CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb); + +PFCB +CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb); + + + +NTSTATUS +CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject); + + + + +NTSTATUS +CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName); + + +/* finfo.c */ + +NTSTATUS STDCALL +CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* fsctl.c */ + +NTSTATUS STDCALL +CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* rw.c */ + +NTSTATUS STDCALL +CdfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* volinfo.c */ + +NTSTATUS STDCALL +CdfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); -#endif//CDFS_H +#endif //CDFS_H diff --git a/reactos/drivers/fs/cdfs/close.c b/reactos/drivers/fs/cdfs/close.c new file mode 100644 index 00000000000..686c9462fd5 --- /dev/null +++ b/reactos/drivers/fs/cdfs/close.c @@ -0,0 +1,103 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: close.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/close.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Closes a file + */ +{ + PCCB Ccb; + + DPRINT("CdfsCloseFile(DeviceExt %x, FileObject %x)\n", + DeviceExt, + FileObject); + + Ccb = (PCCB)(FileObject->FsContext2); + + DPRINT("Ccb %x\n", Ccb); + if (Ccb == NULL) + { + return(STATUS_SUCCESS); + } + + FileObject->FsContext2 = NULL; + + if (FileObject->FileName.Buffer) + { + // This a FO, that was created outside from FSD. + // Some FO's are created with IoCreateStreamFileObject() insid from FSD. + // This FO's don't have a FileName. + CdfsReleaseFCB(DeviceExt, + Ccb->Fcb); + } + + ExFreePool(Ccb); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +CdfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + + DPRINT1("CdfsClose() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + DeviceExtension = DeviceObject->DeviceExtension; + + Status = CdfsCloseFile(DeviceExtension,FileObject); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +/* EOF */ \ No newline at end of file diff --git a/reactos/drivers/fs/cdfs/common.c b/reactos/drivers/fs/cdfs/common.c index 4fc246da1fc..c3b5680e1ae 100644 --- a/reactos/drivers/fs/cdfs/common.c +++ b/reactos/drivers/fs/cdfs/common.c @@ -1,3 +1,32 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: common.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/volume.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + */ + +/* INCLUDES *****************************************************************/ + #include #define NDEBUG @@ -6,6 +35,8 @@ #include "cdfs.h" +/* FUNCTIONS ****************************************************************/ + NTSTATUS CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, @@ -73,3 +104,5 @@ CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, return(STATUS_SUCCESS); } + +/* EOF */ diff --git a/reactos/drivers/fs/cdfs/create.c b/reactos/drivers/fs/cdfs/create.c new file mode 100644 index 00000000000..49810da5811 --- /dev/null +++ b/reactos/drivers/fs/cdfs/create.c @@ -0,0 +1,269 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: create.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/cdfs.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +#if 0 +NTSTATUS +vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject, + PWSTR pRelativeFileName, + PWSTR *pAbsoluteFilename) +{ + PWSTR rcName; + PVFATFCB fcb; + PVFATCCB ccb; + + DPRINT ("try related for %S\n", pRelativeFileName); + ccb = pFileObject->FsContext2; + assert (ccb); + fcb = ccb->pFcb; + assert (fcb); + + /* verify related object is a directory and target name + don't start with \. */ + if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) + || (pRelativeFileName[0] == L'\\')) + { + return STATUS_INVALID_PARAMETER; + } + + /* construct absolute path name */ + assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 + <= MAX_PATH); + rcName = ExAllocatePool (NonPagedPool, MAX_PATH * sizeof(WCHAR)); + if (!rcName) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy (rcName, fcb->PathName); + if (!vfatFCBIsRoot(fcb)) + wcscat (rcName, L"\\"); + wcscat (rcName, pRelativeFileName); + *pAbsoluteFilename = rcName; + + return STATUS_SUCCESS; +} +#endif + + +static NTSTATUS +CdfsOpenFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + PFCB ParentFcb; + PFCB Fcb; + NTSTATUS Status; + PWSTR AbsFileName = NULL; + + DPRINT("CdfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName); + + if (FileObject->RelatedFileObject) + { + DPRINT("Converting relative filename to absolute filename\n"); +#if 0 + Status = vfatMakeAbsoluteFilename(FileObject->RelatedFileObject, + FileName, + &AbsFileName); + FileName = AbsFileName; + if (!NT_SUCCESS(Status)) + { + return(Status); + } +#endif + return(STATUS_UNSUCCESSFUL); + } + + //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators) + + DPRINT("PathName to open: %S\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 (AbsFileName) + ExFreePool(AbsFileName); + + return(Status); + } + } + + DPRINT("Attaching FCB to fileObject\n"); + Status = CdfsAttachFCBToFileObject(DeviceExt, + Fcb, + FileObject); + + if (AbsFileName) + ExFreePool (AbsFileName); + + return Status; +} + + + + +static NTSTATUS +CdfsCreateFile(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Opens a file + */ +{ + PDEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + ULONG RequestedDisposition; + ULONG RequestedOptions; + PFCB Fcb; +// PWSTR FileName; + NTSTATUS Status; + + DPRINT1("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; +// PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE; +// if ((RequestedOptions & FILE_DIRECTORY_FILE) +// && RequestedDisposition == FILE_SUPERSEDE) +// return STATUS_INVALID_PARAMETER; + + FileObject = Stack->FileObject; + + Status = CdfsOpenFile(DeviceExt, + FileObject, + FileObject->FileName.Buffer); + + /* + * If the directory containing the file to open doesn't exist then + * fail immediately + */ + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = Status; + return(Status); + +#if 0 + /* Just skip leading backslashes... */ + while (*FileName == L'\\') + FileName++; +CHECKPOINT1; + + Fcb = FsdSearchDirectory(DeviceExt->fss, + NULL, + FileName); +CHECKPOINT1; + if (Fcb == NULL) + { + DPRINT1("FsdSearchDirectory() failed\n"); + return(STATUS_OBJECT_PATH_NOT_FOUND); + } +CHECKPOINT1; + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = Fcb; + FileObject->FsContext2 = DeviceExt->fss; + + DPRINT1("FsdOpenFile() done\n"); + + return(STATUS_SUCCESS); +#endif +} + + +NTSTATUS STDCALL +CdfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + if (DeviceObject->Size == sizeof(DEVICE_OBJECT)) + { + /* DeviceObject represents FileSystem instead of logical volume */ + DPRINT("FsdCreate called with file system\n"); + Irp->IoStatus.Information = FILE_OPENED; + Status = STATUS_SUCCESS; + goto ByeBye; + } + + DeviceExt = DeviceObject->DeviceExtension; + + ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, + TRUE); + Status = CdfsCreateFile(DeviceObject, + Irp); + ExReleaseResourceLite(&DeviceExt->DirResource); + + +ByeBye: + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ \ No newline at end of file diff --git a/reactos/drivers/fs/cdfs/dirctl.c b/reactos/drivers/fs/cdfs/dirctl.c new file mode 100644 index 00000000000..a77729fe323 --- /dev/null +++ b/reactos/drivers/fs/cdfs/dirctl.c @@ -0,0 +1,106 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: dirctl.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/dirctl.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +/* HACK -- NEEDS FIXING */ +#if 0 +int +FsdExtractDirectoryEntry(PDEVICE_EXTENSION DeviceExt, + FsdFcbEntry *parent, + FsdFcbEntry *fill_in, + int entry_to_get) +{ + switch( entry_to_get ) + { + case 0: + wcscpy( fill_in->name, L"." ); + fill_in->extent_start = parent->extent_start; + fill_in->byte_count = parent->byte_count; + break; + + case 1: + wcscpy( fill_in->name, L".." ); + fill_in->extent_start = parent->extent_start; + fill_in->byte_count = parent->byte_count; + break; + + case 2: + wcscpy( fill_in->name, L"readme.txt" ); + fill_in->extent_start = 0x190; + fill_in->byte_count = 0x800; + break; + + default: + return 1; + } + + return 0; +} +#endif + + +NTSTATUS STDCALL +CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("CdfsDirectoryControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + + default: + DPRINT("CDFS: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/reactos/drivers/fs/cdfs/fcb.c b/reactos/drivers/fs/cdfs/fcb.c index 9842901a043..3597ba76b33 100644 --- a/reactos/drivers/fs/cdfs/fcb.c +++ b/reactos/drivers/fs/cdfs/fcb.c @@ -1,123 +1,615 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: fcb.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/fcb.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + #include + +//#define NDEBUG +#include + #include "cdfs.h" -/* - CDFS: FCB system (Perhaps there should be a library to make this easier) -*/ -#if 0 -typedef struct _fcb_system { - int fcbs_in_use; - int fcb_table_size; - int fcb_table_mask; - FsdFcbEntry **fcb_table; - FsdFcbEntry *parent; -} fcb_system; -#endif -// Create a hash over this name for table -static int FsdNameHash( FsdFcbEntry *parent, wchar_t *name ) { - int i; - int hashval = 0; +/* MACROS *******************************************************************/ + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) +#define TAG_FCB TAG('I', 'F', 'C', 'B') + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) - for( i = 0; name[i]; i++ ) - hashval ^= name[i] << (i & 0xf); - hashval ^= (int)parent; +/* FUNCTIONS ****************************************************************/ - return hashval; +PFCB +CdfsCreateFCB(PWSTR FileName) +{ + PFCB Fcb; + + Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); + RtlZeroMemory(Fcb, sizeof(FCB)); + + if (FileName) + { + wcscpy(Fcb->PathName, FileName); + if (wcsrchr(Fcb->PathName, '\\') != 0) + { + Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\'); + } + else + { + Fcb->ObjectName = Fcb->PathName; + } + } + + ExInitializeResourceLite(&Fcb->MainResource); + + return(Fcb); } -// Init the fcb system -fcb_system *FsdFcbInit() { - fcb_system *fss = ExAllocatePool( NonPagedPool, - sizeof( fcb_system ) ); - if( !fss ) return NULL; +VOID +CdfsDestroyFCB(PFCB Fcb) +{ + ExDeleteResourceLite(&Fcb->MainResource); - RtlZeroMemory( fss, sizeof( *fss ) ); + ExFreePool(Fcb); +} - fss->fcb_table_size = 128; - fss->fcb_table_mask = fss->fcb_table_size - 1; - fss->fcb_table = ExAllocatePool( NonPagedPool, - sizeof( FsdFcbEntry ** ) * - fss->fcb_table_size ); - if( !fss->fcb_table ) { - ExFreePool( fss ); - return NULL; - } +BOOLEAN +CdfsFCBIsDirectory(PFCB Fcb) +{ +// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY); + return(Fcb->Entry.FileFlags & 0x02); +} - RtlZeroMemory( fss->fcb_table, sizeof( FsdFcbEntry ** ) * - fss->fcb_table_size ); - return fss; +BOOLEAN +CdfsFCBIsRoot(PFCB Fcb) +{ + return(wcscmp(Fcb->PathName, L"\\") == 0); } -// Delete the fcb system -void FsdFcbDeinit( fcb_system *fss ) { - if( fss->fcb_table ) ExFreePool( fss->fcb_table ); + +VOID +CdfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + DPRINT("grabbing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); } -// Get one entry from the FCB system by name... -FsdFcbEntry *FsdGetFcbEntry( fcb_system *fss, FsdFcbEntry *parent, - wchar_t *name ) { - int hashval; - FsdFcbEntry *table_ent = NULL; - hashval = FsdNameHash( parent, name ) & fss->fcb_table_mask; - table_ent = fss->fcb_table[hashval]; +VOID +CdfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; - while( table_ent && _wcsicmp( table_ent->name, name ) && - table_ent->parent != parent ) - table_ent = table_ent->next; + DPRINT("releasing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); - return table_ent; + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount--; + if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb)) + { + RemoveEntryList(&Fcb->FcbListEntry); + CcRosReleaseFileCache(NULL, Fcb->RFCB.Bcb); + CdfsDestroyFCB(Fcb); + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); } -// Create an fcb with the given name... -FsdFcbEntry *FsdCreateFcb( fcb_system *fss, FsdFcbEntry *parent, - wchar_t *filename ) { - int hashval; - int tableval; - FsdFcbEntry *table_ent = FsdGetFcbEntry( fss, parent, filename ); - if( table_ent ) return table_ent; +VOID +CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->DevExt = Vcb; + InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +PFCB +CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName) +{ + KIRQL oldIrql; + PFCB Fcb; + PLIST_ENTRY current_entry; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + + if (FileName == NULL || *FileName == 0) + { + DPRINT1("Return FCB for strem file object\n"); + Fcb = ((PCCB)Vcb->StreamFileObject->FsContext2)->Fcb; + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + current_entry = Vcb->FcbListHead.Flink; + while (current_entry != &Vcb->FcbListHead) + { + Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry); + +// if (wstrcmpi(FileName, Fcb->PathName)) + if (_wcsicmp(FileName, Fcb->PathName)) + { + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + //FIXME: need to compare against short name in FCB here + + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + + return(NULL); +} + + +NTSTATUS +CdfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PCCB newCCB; + + FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice); + + newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlZeroMemory(newCCB, + sizeof(CCB)); + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID) &Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->FileObject = FileObject; + Fcb->DevExt = Vcb; + + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + PAGESIZE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + + ObDereferenceObject(FileObject); + Fcb->Flags |= FCB_CACHE_INITIALIZED; + + return(Status); +} + + +PFCB +CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = CdfsCreateFCB(L"\\"); + +// memset(Fcb->entry.Filename, ' ', 11); + + Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize; + Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart; + Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY; + Fcb->RefCount = 1; + Fcb->DirIndex = 0; + Fcb->RFCB.FileSize.QuadPart = Vcb->CdInfo.RootSize; + Fcb->RFCB.ValidDataLength.QuadPart = Vcb->CdInfo.RootSize; + Fcb->RFCB.AllocationSize.QuadPart = Vcb->CdInfo.RootSize; + + CdfsFCBInitializeCache(Vcb, Fcb); + CdfsAddFCBToTable(Vcb, Fcb); + CdfsGrabFCB(Vcb, Fcb); + + return(Fcb); +} + + +PFCB +CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = CdfsGrabFCBFromTable(Vcb, L"\\"); + if (Fcb == NULL) + { + Fcb = CdfsMakeRootFCB(Vcb); + } + + return(Fcb); +} + - hashval = FsdNameHash( parent, filename ); - tableval = hashval & fss->fcb_table_mask; +#if 0 +NTSTATUS +vfatMakeFCBFromDirEntry(PVCB vcb, + PVFATFCB directoryFCB, + PWSTR longName, + PFAT_DIR_ENTRY dirEntry, + ULONG dirIndex, + PVFATFCB * fileFCB) +{ + PVFATFCB rcFCB; + WCHAR pathName [MAX_PATH]; + ULONG Size; + if (longName [0] != 0 && wcslen (directoryFCB->PathName) + + sizeof(WCHAR) + wcslen (longName) > MAX_PATH) + { + return STATUS_OBJECT_NAME_INVALID; + } + wcscpy (pathName, directoryFCB->PathName); + if (!vfatFCBIsRoot (directoryFCB)) + { + wcscat (pathName, L"\\"); + } + if (longName [0] != 0) + { + wcscat (pathName, longName); + } + else + { + WCHAR entryName [MAX_PATH]; - table_ent = ExAllocatePool( NonPagedPool, sizeof( FsdFcbEntry ) ); + vfatGetDirEntryName (dirEntry, entryName); + wcscat (pathName, entryName); + } + rcFCB = vfatNewFCB (pathName); + memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY)); - if( table_ent ) { - table_ent->next = fss->fcb_table[tableval]; - table_ent->hashval = hashval; - table_ent->parent = parent; - wcscpy( table_ent->name, filename ); - fss->fcb_table[tableval] = table_ent; + if (vfatFCBIsDirectory(vcb, rcFCB)) + { + ULONG FirstCluster, CurrentCluster; + NTSTATUS Status; + Size = 0; + FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry); + if (FirstCluster == 1) + { + Size = vcb->FatInfo.rootDirectorySectors * BLOCKSIZE; + } + else + { + CurrentCluster = FirstCluster; + while (CurrentCluster != 0xffffffff) + { + Size += vcb->FatInfo.BytesPerCluster; + Status = NextCluster (vcb, NULL, FirstCluster, &CurrentCluster, FALSE); + } + } } + else + { + Size = rcFCB->entry.FileSize; + } + rcFCB->dirIndex = dirIndex; + rcFCB->RFCB.FileSize.QuadPart = Size; + rcFCB->RFCB.ValidDataLength.QuadPart = Size; + rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); +// DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart); + vfatFCBInitializeCache (vcb, rcFCB); + rcFCB->RefCount++; + vfatAddFCBToTable (vcb, rcFCB); + *fileFCB = rcFCB; + + return STATUS_SUCCESS; +} +#endif + +NTSTATUS +CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject) +{ + NTSTATUS Status; + PCCB newCCB; + + newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + memset(newCCB, 0, sizeof(CCB)); - return table_ent; + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID)&Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->DevExt = Vcb; + + if (!(Fcb->Flags & FCB_CACHE_INITIALIZED)) + { + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + PAGESIZE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + Fcb->Flags |= FCB_CACHE_INITIALIZED; + } + + DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); + + return(STATUS_SUCCESS); } -// Delete this fcb... -void FsdDelete( fcb_system *fss, FsdFcbEntry *which ) { - int tableval = which->hashval & fss->fcb_table_mask; - FsdFcbEntry *table_ent = fss->fcb_table[tableval]; - - if( table_ent == which ) { - fss->fcb_table[tableval] = fss->fcb_table[tableval]->next; - ExFreePool( which ); - return; +#if 0 +NTSTATUS +vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt, + PVFATFCB pDirectoryFCB, + PWSTR pFileToFind, + PVFATFCB * pFoundFCB) +{ + BOOL finishedScanningDirectory; + ULONG directoryIndex; + NTSTATUS status; + WCHAR defaultFileName [2]; + WCHAR currentLongName [256]; + FAT_DIR_ENTRY currentDirEntry; + WCHAR currentEntryName [256]; + + assert (pDeviceExt); + assert (pDirectoryFCB); + assert (pFileToFind); + + DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n", + pDeviceExt, + pDirectoryFCB, + pFileToFind); + DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName); + + // default to '.' if no filename specified + if (wcslen (pFileToFind) == 0) + { + defaultFileName [0] = L'.'; + defaultFileName [1] = 0; + pFileToFind = defaultFileName; } - if( !table_ent ) return; + directoryIndex = 0; + finishedScanningDirectory = FALSE; + while (!finishedScanningDirectory) + { + status = vfatGetNextDirEntry (pDeviceExt, + pDirectoryFCB, + &directoryIndex, + currentLongName, + ¤tDirEntry); + if (status == STATUS_NO_MORE_ENTRIES) + { + finishedScanningDirectory = TRUE; + continue; + } + else if (!NT_SUCCESS(status)) + { + return status; + } + + DPRINT (" Index:%d longName:%S\n", + directoryIndex, + currentLongName); + + if (!vfatIsDirEntryDeleted (¤tDirEntry) + && !vfatIsDirEntryVolume(¤tDirEntry)) + { + if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind)) + { + DPRINT ("Match found, %S\n", currentLongName); + status = vfatMakeFCBFromDirEntry (pDeviceExt, + pDirectoryFCB, + currentLongName, + ¤tDirEntry, + directoryIndex - 1, + pFoundFCB); + return status; + } + else + { + vfatGetDirEntryName (¤tDirEntry, currentEntryName); + DPRINT (" entryName:%S\n", currentEntryName); - while( table_ent->next ) { - if( table_ent->next == which ) { - table_ent->next = table_ent->next->next; - ExFreePool( which ); - return; + if (wstrcmpjoki (currentEntryName, pFileToFind)) + { + DPRINT ("Match found, %S\n", currentEntryName); + status = vfatMakeFCBFromDirEntry (pDeviceExt, + pDirectoryFCB, + currentLongName, + ¤tDirEntry, + directoryIndex - 1, + pFoundFCB); + return status; + } + } } - table_ent = table_ent->next; } + + return STATUS_OBJECT_NAME_NOT_FOUND; } +#endif + + +NTSTATUS +CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName) +{ + NTSTATUS status; + WCHAR pathName [MAX_PATH]; + WCHAR elementName [MAX_PATH]; + PWCHAR currentElement; + PFCB FCB; + PFCB parentFCB; + + DPRINT("CdfsGetFCBForFile(%x, %x, %x, '%S')\n", + Vcb, + pParentFCB, + pFCB, + pFileName); + + /* Trivial case, open of the root directory on volume */ + if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0) + { + DPRINT("returning root FCB\n"); + + FCB = CdfsOpenRootFCB(Vcb); + *pFCB = FCB; + *pParentFCB = NULL; + + return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND); + } + + DPRINT1("CdfsGetFCBForFile() is incomplete!\n"); + return(STATUS_UNSUCCESSFUL); + +#if 0 + else + { + currentElement = pFileName + 1; + wcscpy (pathName, L"\\"); + FCB = CdfsOpenRootFCB (Vcb); + } + parentFCB = NULL; + + // Parse filename and check each path element for existance and access + while (vfatGetNextPathElement (currentElement) != 0) + { + // Skip blank directory levels + if ((vfatGetNextPathElement (currentElement) - currentElement) == 0) + { + currentElement++; + continue; + } + + DPRINT ("Parsing, currentElement:%S\n", currentElement); + DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB); + + // descend to next directory level + if (parentFCB) + { + vfatReleaseFCB (pVCB, parentFCB); + parentFCB = 0; + } + // fail if element in FCB is not a directory + if (!vfatFCBIsDirectory (pVCB, FCB)) + { + DPRINT ("Element in requested path is not a directory\n"); + + vfatReleaseFCB (pVCB, FCB); + FCB = 0; + *pParentFCB = NULL; + *pFCB = NULL; + + return STATUS_OBJECT_PATH_NOT_FOUND; + } + parentFCB = FCB; + + // Extract next directory level into dirName + vfatWSubString (pathName, + pFileName, + vfatGetNextPathElement (currentElement) - pFileName); + DPRINT (" pathName:%S\n", pathName); + + FCB = vfatGrabFCBFromTable (pVCB, pathName); + if (FCB == NULL) + { + vfatWSubString (elementName, + currentElement, + vfatGetNextPathElement (currentElement) - currentElement); + DPRINT (" elementName:%S\n", elementName); + + status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + { + *pParentFCB = parentFCB; + *pFCB = NULL; + currentElement = vfatGetNextPathElement(currentElement); + if (*currentElement == L'\0' || vfatGetNextPathElement(currentElement + 1) == 0) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + else + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + } + else if (!NT_SUCCESS (status)) + { + vfatReleaseFCB (pVCB, parentFCB); + *pParentFCB = NULL; + *pFCB = NULL; + + return status; + } + } + currentElement = vfatGetNextPathElement (currentElement); + } + + *pParentFCB = parentFCB; + *pFCB = FCB; + + return STATUS_SUCCESS; +#endif +} + +/* EOF */ diff --git a/reactos/drivers/fs/cdfs/finfo.c b/reactos/drivers/fs/cdfs/finfo.c new file mode 100644 index 00000000000..e71f6d3b4f0 --- /dev/null +++ b/reactos/drivers/fs/cdfs/finfo.c @@ -0,0 +1,166 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: finfo.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/dirctl.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsQueryNameInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_NAME_INFORMATION NameInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file name information + */ +{ + ULONG NameLength; + + assert (NameInfo != NULL); + assert (Fcb != NULL); + +#if 0 + NameLength = wcslen(FCB->PathName) * sizeof(WCHAR); + if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength) + return STATUS_BUFFER_OVERFLOW; + + NameInfo->FileNameLength = NameLength; + memcpy(NameInfo->FileName, + FCB->PathName, + NameLength + sizeof(WCHAR)); +#endif + + /* Fake name */ + NameLength = 2; + wcscpy(NameInfo->FileName, L"\\"); + + *BufferLength -= + (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PFCB Fcb; + PVOID SystemBuffer; + ULONG BufferLength; + + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT1("CdfsQueryInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; + FileObject = Stack->FileObject; + Fcb = FileObject->FsContext; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = Stack->Parameters.QueryFile.Length; + + switch (FileInformationClass) + { +#if 0 + case FileStandardInformation: + Status = CdfsGetStandardInformation(Fcb, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FilePositionInformation: + RC = CdfsGetPositionInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FileBasicInformation: + RC = CdfsGetBasicInformation(FileObject, + FCB, + DeviceObject, + SystemBuffer, + &BufferLength); + break; +#endif + + case FileNameInformation: + Status = CdfsQueryNameInformation(FileObject, + Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + +#if 0 + case FileInternalInformation: + Status = CdfsGetInternalInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + + case FileAlternateNameInformation: + case FileAllInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; +#endif + default: + DPRINT("Unimplemented information class %u\n", FileInformationClass); + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ \ No newline at end of file diff --git a/reactos/drivers/fs/cdfs/fsctl.c b/reactos/drivers/fs/cdfs/fsctl.c new file mode 100644 index 00000000000..9d411b591f1 --- /dev/null +++ b/reactos/drivers/fs/cdfs/fsctl.c @@ -0,0 +1,407 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: fsctl.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/fsctl.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static VOID +CdfsGetPVDData(PUCHAR Buffer, + PDEVICE_EXTENSION Vcb, + PVPB Vpb) +{ + PPVD Pvd; + ULONG i; + PCHAR pc; + PWCHAR pw; + + union + { + ULONG Value; + UCHAR Part[4]; + } Serial; + + Pvd = (PPVD)Buffer; + + /* Calculate the volume serial number */ + Serial.Value = 0; + for (i = 0; i < 2048; i += 4) + { + /* DON'T optimize this to ULONG!!! (breaks overflow) */ + Serial.Part[0] += Buffer[i+3]; + Serial.Part[1] += Buffer[i+2]; + Serial.Part[2] += Buffer[i+1]; + Serial.Part[3] += Buffer[i+0]; + } + Vpb->SerialNumber = Serial.Value; + + /* Extract the volume label */ + pc = Pvd->VolumeId; + pw = Vpb->VolumeLabel; + for (i = 0; i < MAXIMUM_VOLUME_LABEL_LENGTH && *pc != ' '; i++) + { + *pw++ = (WCHAR)*pc++; + } + *pw = 0; + Vpb->VolumeLabelLength = i; + + Vcb->CdInfo.VolumeSpaceSize = Pvd->VolumeSpaceSizeL; + Vcb->CdInfo.RootStart = Pvd->RootDirRecord.ExtentLocationL; + Vcb->CdInfo.RootSize = Pvd->RootDirRecord.DataLengthL; + + DPRINT1("VolumeSerial: %08lx\n", Vpb->SerialNumber); + DPRINT1("VolumeLabel: '%S'\n", Vpb->VolumeLabel); + DPRINT1("VolumeLabelLength: %lu\n", Vpb->VolumeLabelLength); + DPRINT1("VolumeSize: %lu\n", Pvd->VolumeSpaceSizeL); + DPRINT1("RootStart: %lu\n", Pvd->RootDirRecord.ExtentLocationL); + DPRINT1("RootSize: %lu\n", Pvd->RootDirRecord.DataLengthL); +} + + +static VOID +CdfsGetSVDData(PUCHAR Buffer, + PDEVICE_EXTENSION Vcb) +{ + PSVD Svd; + ULONG JolietLevel = 0; + + Svd = (PSVD)Buffer; + + DPRINT1("EscapeSequences: '%.32s'\n", Svd->EscapeSequences); + + if (strncmp(Svd->EscapeSequences, "%/@", 3) == 0) + { + DPRINT1("Joliet extension found (UCS-2 Level 1)\n"); + JolietLevel = 1; + } + else if (strncmp(Svd->EscapeSequences, "%/C", 3) == 0) + { + DPRINT1("Joliet extension found (UCS-2 Level 2)\n"); + JolietLevel = 2; + } + else if (strncmp(Svd->EscapeSequences, "%/E", 3) == 0) + { + DPRINT1("Joliet extension found (UCS-2 Level 3)\n"); + JolietLevel = 3; + } + + Vcb->CdInfo.JolietLevel = JolietLevel; + + if (JolietLevel != 0) + { + Vcb->CdInfo.RootStart = Svd->RootDirRecord.ExtentLocationL; + Vcb->CdInfo.RootSize = Svd->RootDirRecord.DataLengthL; + + DPRINT1("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL); + DPRINT1("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL); + } +} + + +static NTSTATUS +CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb) +{ + PUCHAR Buffer; + NTSTATUS Status; + ULONG Sector; + PVD_HEADER VdHeader; + + + Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; + + Buffer = ExAllocatePool(NonPagedPool, + CDFS_BASIC_SECTOR); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + VdHeader = (PVD_HEADER)Buffer; + + do + { + /* Read the Primary Volume Descriptor (PVD) */ + Status = CdfsReadSectors(DeviceObject, + Sector, + 1, + Buffer); + if (!NT_SUCCESS(Status)) + return(Status); + + switch (VdHeader->VdType) + { + case 0: + DPRINT1("BootVolumeDescriptor found!\n"); + break; + + case 1: + DPRINT1("PrimaryVolumeDescriptor found!\n"); + CdfsGetPVDData(Buffer, Vcb, DeviceObject->Vpb); + break; + + case 2: + DPRINT1("SupplementaryVolumeDescriptor found!\n"); + CdfsGetSVDData(Buffer, Vcb); + break; + + case 3: + DPRINT1("VolumePartitionDescriptor found!\n"); + break; + + case 255: + DPRINT1("VolumeDescriptorSetTerminator found!\n"); + break; + + default: + DPRINT1("VolumeDescriptor type %u found!\n", VdHeader->VdType); + break; + } + + Sector++; + } + while (VdHeader->VdType != 255); + + ExFreePool(Buffer); + + return(STATUS_SUCCESS); +} + + +static BOOLEAN +CdfsHasFileSystem(PDEVICE_OBJECT DeviceToMount) +/* + * FUNCTION: Tests if the device contains a filesystem that can be mounted + * by this fsd + */ +{ + PUCHAR bytebuf; // [CDFS_BASIC_SECTOR]; + NTSTATUS Status; + int ret; + + bytebuf = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR ); + if( !bytebuf ) return FALSE; + + DPRINT1("CDFS: Checking on mount of device %08x\n", DeviceToMount); + + Status = CdfsReadSectors(DeviceToMount, + CDFS_PRIMARY_DESCRIPTOR_LOCATION, + 1, + bytebuf); + bytebuf[6] = 0; + DPRINT1( "CD-identifier: [%.5s]\n", bytebuf + 1 ); + + ret = + Status == STATUS_SUCCESS && + bytebuf[0] == 1 && + bytebuf[1] == 'C' && + bytebuf[2] == 'D' && + bytebuf[3] == '0' && + bytebuf[4] == '0' && + bytebuf[5] == '1'; + + ExFreePool( bytebuf ); + + return ret; +} + + +static NTSTATUS +CdfsMountVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt = NULL; + PDEVICE_OBJECT NewDeviceObject = NULL; + PDEVICE_OBJECT DeviceToMount; + PIO_STACK_LOCATION Stack; + PFCB Fcb = NULL; + PCCB Ccb = NULL; + NTSTATUS Status; + + DPRINT1("CdfsMountVolume() called\n"); + + if (DeviceObject != CdfsGlobalData->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; + + if (CdfsHasFileSystem(DeviceToMount) == FALSE) + { + Status = STATUS_UNRECOGNIZED_VOLUME; + goto ByeBye; + } + + Status = IoCreateDevice(CdfsGlobalData->DriverObject, + sizeof(DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &NewDeviceObject); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExt, + sizeof(DEVICE_EXTENSION)); + + Status = CdfsGetVolumeData(DeviceToMount, + DeviceExt); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + NewDeviceObject->Vpb = DeviceToMount->Vpb; + NewDeviceObject->Vpb->Flags |= VPB_MOUNTED; + DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(NewDeviceObject, + DeviceToMount); + DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, + DeviceExt->StorageDevice); + + Fcb = CdfsCreateFCB(NULL); + if (Fcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + + Ccb = ExAllocatePoolWithTag(NonPagedPool, + sizeof(CCB), + TAG_CCB); + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + RtlZeroMemory(Ccb, + sizeof(CCB)); + + DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; + DeviceExt->StreamFileObject->FsContext = (PVOID)&Fcb->RFCB; + DeviceExt->StreamFileObject->FsContext2 = Ccb; + DeviceExt->StreamFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + DeviceExt->StreamFileObject->PrivateCacheMap = NULL; + DeviceExt->StreamFileObject->Vpb = NewDeviceObject->Vpb; + Ccb->Fcb = Fcb; + Ccb->PtrFileObject = DeviceExt->StreamFileObject; + Fcb->FileObject = DeviceExt->StreamFileObject; + Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + + Fcb->RFCB.FileSize.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE; + Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE; + Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE, PAGESIZE); + + Fcb->Entry.ExtentLocationL = 0; + Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE; + + Status = CcRosInitializeFileCache(DeviceExt->StreamFileObject, &Fcb->RFCB.Bcb, PAGESIZE); + if (!NT_SUCCESS (Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + goto ByeBye; + } + + ExInitializeResourceLite(&DeviceExt->DirResource); +// ExInitializeResourceLite(&DeviceExt->FatResource); + + KeInitializeSpinLock(&DeviceExt->FcbListLock); + InitializeListHead(&DeviceExt->FcbListHead); + + Status = STATUS_SUCCESS; + +ByeBye: + if (!NT_SUCCESS(Status)) + { + /* Cleanup */ + if (DeviceExt && DeviceExt->StreamFileObject) + ObDereferenceObject(DeviceExt->StreamFileObject); + if (Fcb) + ExFreePool(Fcb); + if (Ccb) + ExFreePool(Ccb); + if (NewDeviceObject) + IoDeleteDevice(NewDeviceObject); + } + + return(Status); +} + + +NTSTATUS STDCALL +CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT1("CdfsFileSystemControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + DPRINT("CDFS: IRP_MN_USER_FS_REQUEST\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case IRP_MN_MOUNT_VOLUME: + DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n"); + Status = CdfsMountVolume(DeviceObject, Irp); + break; + + case IRP_MN_VERIFY_VOLUME: + DPRINT("CDFS: IRP_MN_VERIFY_VOLUME\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + default: + DPRINT("CDFS FSC: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/reactos/drivers/fs/cdfs/makefile b/reactos/drivers/fs/cdfs/makefile index d14f7043344..9a9f11c0da0 100644 --- a/reactos/drivers/fs/cdfs/makefile +++ b/reactos/drivers/fs/cdfs/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.1 2002/04/12 15:41:39 ekohl Exp $ +# $Id: makefile,v 1.2 2002/04/15 20:39:49 ekohl Exp $ PATH_TO_TOP = ../../.. @@ -6,7 +6,8 @@ TARGET_TYPE = driver TARGET_NAME = cdfs -TARGET_OBJECTS = $(TARGET_NAME).o common.o fcb.o +TARGET_OBJECTS = $(TARGET_NAME).o close.o common.o create.o dirctl.o \ + fcb.o finfo.o fsctl.o rw.o volinfo.o include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/drivers/fs/cdfs/rw.c b/reactos/drivers/fs/cdfs/rw.c new file mode 100644 index 00000000000..b0a75574bea --- /dev/null +++ b/reactos/drivers/fs/cdfs/rw.c @@ -0,0 +1,118 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: rw.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/rw.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsReadFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + ULONG Offset) +/* + * FUNCTION: Reads data from a file + */ +{ + NTSTATUS Status; + PCCB Ccb; + PFCB Fcb; + + DPRINT("CdfsReadFile(Offset %lu Length %lu)\n", Offset, Length); + + if (Length == 0) + return STATUS_SUCCESS; + + Ccb = (PCCB)FileObject->FsContext2; + Fcb = Ccb->Fcb; + + if (Offset + Length > Fcb->Entry.DataLengthL) + Length = Fcb->Entry.DataLengthL - Offset; + + DPRINT( "Reading %d bytes at %d\n", Offset, Length ); + + if (Length == 0) + return(STATUS_UNSUCCESSFUL); + + Status = CdfsReadSectors(DeviceExt->StorageDevice, + Fcb->Entry.ExtentLocationL + Offset / BLOCKSIZE, + Length / BLOCKSIZE, + Buffer); + + return(Status); +} + + +NTSTATUS STDCALL +CdfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + ULONG Length; + PVOID Buffer; + ULONG Offset; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + NTSTATUS Status; + + DPRINT("CdfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Length = Stack->Parameters.Read.Length; + Offset = Stack->Parameters.Read.ByteOffset.u.LowPart; + + Status = CdfsReadFile(DeviceExt,FileObject,Buffer,Length,Offset); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return(Status); +} + + +NTSTATUS STDCALL +CdfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("CdfsWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +/* EOF */ diff --git a/reactos/drivers/fs/cdfs/volinfo.c b/reactos/drivers/fs/cdfs/volinfo.c new file mode 100644 index 00000000000..a6ef384b694 --- /dev/null +++ b/reactos/drivers/fs/cdfs/volinfo.c @@ -0,0 +1,243 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: volinfo.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/volume.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, + PULONG BufferLength) +{ + ULONG LabelLength; + + DPRINT("CdfsGetFsVolumeInformation() called\n"); + DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + + DPRINT("Vpb %p\n", DeviceObject->Vpb); + LabelLength = DeviceObject->Vpb->VolumeLabelLength; + + DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))); + DPRINT("LabelLength %lu\n", LabelLength); + DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel); + + if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))) + return STATUS_BUFFER_OVERFLOW; + + /* valid entries */ + FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; + FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR); + wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel); + + /* dummy entries */ + FsVolumeInfo->VolumeCreationTime.QuadPart = 0; + FsVolumeInfo->SupportsObjects = FALSE; + + DPRINT("Finished FsdGetFsVolumeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR)); + + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, + PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetFsAttributeInformation()\n"); + DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)); + + if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)) + return STATUS_BUFFER_OVERFLOW; + + FsAttributeInfo->FileSystemAttributes = + FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; + FsAttributeInfo->MaximumComponentNameLength = 255; + FsAttributeInfo->FileSystemNameLength = 8; + + memcpy(FsAttributeInfo->FileSystemName, L"CDFS", 8); + + DPRINT("Finished FsdGetFsAttributeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_SIZE_INFORMATION FsSizeInfo, + PULONG BufferLength) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + DPRINT("CdfsGetFsSizeInformation()\n"); + DPRINT("FsSizeInfo = %p\n", FsSizeInfo); + + if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + DeviceExt = DeviceObject->DeviceExtension; + + FsSizeInfo->AvailableAllocationUnits.QuadPart = 0; + FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize; + FsSizeInfo->SectorsPerAllocationUnit = 1; + FsSizeInfo->BytesPerSector = 2048; /* ?? */ + + DPRINT("Finished FsdGetFsSizeInformation()\n"); + if (NT_SUCCESS(Status)) + *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); + + return(Status); +} + + +static NTSTATUS +CdfsGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetFsDeviceInformation()\n"); + DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); + + if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM; + FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */ + + DPRINT("FsdGetFsDeviceInformation() finished.\n"); + + *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + + +NTSTATUS STDCALL +CdfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + FS_INFORMATION_CLASS FsInformationClass; + PIO_STACK_LOCATION Stack; + NTSTATUS Status = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + DPRINT("CdfsQueryVolumeInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass; + BufferLength = Stack->Parameters.QueryVolume.Length; + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + + DPRINT("FsInformationClass %d\n", FsInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + switch (FsInformationClass) + { + case FileFsVolumeInformation: + Status = CdfsGetFsVolumeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsAttributeInformation: + Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension, + SystemBuffer, + &BufferLength); + break; + + case FileFsSizeInformation: + Status = CdfsGetFsSizeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsDeviceInformation: + Status = CdfsGetFsDeviceInformation(SystemBuffer, + &BufferLength); + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryVolume.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +CdfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("CdfsSetVolumeInformation() called\n"); + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NOT_SUPPORTED); +} + +/* EOF */