diff --git a/reactos/Makefile b/reactos/Makefile index c5a642b67b0..63a38957e2d 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -47,7 +47,7 @@ DEVICE_DRIVERS = vidport vga blue ide null floppy INPUT_DRIVERS = keyboard mouclass psaux #FS_DRIVERS = vfat minix ext2 template -FS_DRIVERS = vfat ms np +FS_DRIVERS = vfat ms np cdfs #NET_DRIVERS = ndis tdi tcpip tditest wshtcpip afd NET_DRIVERS = ndis tdi tcpip tditest wshtcpip afd diff --git a/reactos/bootc.lst b/reactos/bootc.lst index 811fa1a95ff..500af15dffa 100644 --- a/reactos/bootc.lst +++ b/reactos/bootc.lst @@ -4,5 +4,6 @@ system32\drivers\class2.sys system32\drivers\disk.sys system32\drivers\cdrom.sys system32\drivers\vfatfs.sys +system32\drivers\cdfs.sys system32\config\system.hiv * diff --git a/reactos/drivers/fs/cdfs/cdfs.c b/reactos/drivers/fs/cdfs/cdfs.c new file mode 100644 index 00000000000..b36b31f8d15 --- /dev/null +++ b/reactos/drivers/fs/cdfs/cdfs.c @@ -0,0 +1,756 @@ +/* + * 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" + +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; + + 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); +} + + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT _DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + UNICODE_STRING DeviceName; + + DbgPrint("CDFS 0.0.1\n"); + + DriverObject = _DriverObject; + + RtlInitUnicodeString(&DeviceName, + L"\\Device\\cdfs"); + Status = IoCreateDevice(DriverObject, + 0, + &DeviceName, + FILE_DEVICE_CD_ROM_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + 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_FILE_SYSTEM_CONTROL] = + FsdFileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + FsdDirectoryControl; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + FsdQueryInformation; + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + diff --git a/reactos/drivers/fs/cdfs/cdfs.h b/reactos/drivers/fs/cdfs/cdfs.h new file mode 100644 index 00000000000..4279624012c --- /dev/null +++ b/reactos/drivers/fs/cdfs/cdfs.h @@ -0,0 +1,116 @@ +#ifndef CDFS_H +#define CDFS_H + +#include + +#define CDFS_BASIC_SECTOR 2048 +#define CDFS_PRIMARY_DESCRIPTOR_LOCATION 16 +#define BLOCKSIZE CDFS_BASIC_SECTOR +#define CDFS_MAX_NAME_LEN 256 + +struct _DIR_RECORD +{ + UCHAR RecordLength; // 1 + UCHAR ExtAttrRecordLength; // 2 + ULONG ExtentLocationL; // 3-6 + ULONG ExtentLocationM; // 7-10 + ULONG DataLengthL; // 11-14 + ULONG DataLengthM; // 15-18 + UCHAR Year; // 19 + UCHAR Month; // 20 + UCHAR Day; // 21 + UCHAR Hour; // 22 + UCHAR Minute; // 23 + UCHAR Second; // 24 + UCHAR TimeZone; // 25 + UCHAR FileFlags; // 26 + UCHAR FileUnitSize; // 27 + UCHAR InterleaveGapSize; // 28 + ULONG VolumeSequenceNumber; // 29-32 + UCHAR FileIdLength; // 33 + UCHAR FileId[1]; // 34 +} __attribute__((packed)); + +typedef struct _DIR_RECORD DIR_RECORD, PDIR_RECORD; + + +/* 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 + DIR_RECORD RootDirRecord; // 157-190 + + /* more data ... */ + +} __attribute__((packed)); + +typedef struct _PVD PVD, *PPVD; + + + +typedef struct _FCB +{ + REACTOS_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + + /* CDFS owned elements */ + + struct _FCB *next; + struct _FCB *parent; + + wchar_t name[CDFS_MAX_NAME_LEN]; + int hashval; + unsigned int extent_start; + unsigned int byte_count; + unsigned int file_pointer; +} FsdFcbEntry, FCB, *PFCB; + + +NTSTATUS +CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer); + +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; + + +PFCB +FsdGetFcbEntry(fcb_system *fss, + PFCB ParentFcb, + PWSTR name); + +#endif//CDFS_H diff --git a/reactos/drivers/fs/cdfs/cdfs.rc b/reactos/drivers/fs/cdfs/cdfs.rc new file mode 100644 index 00000000000..4c9fb194091 --- /dev/null +++ b/reactos/drivers/fs/cdfs/cdfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ISO9660 Driver\0" + VALUE "FileVersion", "0.0.6\0" + VALUE "InternalName", "cdfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "cdfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/fs/cdfs/common.c b/reactos/drivers/fs/cdfs/common.c new file mode 100644 index 00000000000..4fc246da1fc --- /dev/null +++ b/reactos/drivers/fs/cdfs/common.c @@ -0,0 +1,75 @@ +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +NTSTATUS +CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer) +{ + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.u.LowPart = DiskSector << 11; + Offset.u.HighPart = DiskSector >> 21; + + BlockSize = BLOCKSIZE * SectorCount; + + DPRINT("CdfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("CdfsReadSectors() failed (Status %x)\n", Status); + DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", + DeviceObject, DiskSector, Buffer, + Offset.QuadPart); + return(Status); + } + + DPRINT("Block request succeeded for %x\n", Irp); + + return(STATUS_SUCCESS); +} diff --git a/reactos/drivers/fs/cdfs/fcb.c b/reactos/drivers/fs/cdfs/fcb.c new file mode 100644 index 00000000000..9842901a043 --- /dev/null +++ b/reactos/drivers/fs/cdfs/fcb.c @@ -0,0 +1,123 @@ +#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; + + for( i = 0; name[i]; i++ ) + hashval ^= name[i] << (i & 0xf); + + hashval ^= (int)parent; + + return hashval; +} + +// Init the fcb system +fcb_system *FsdFcbInit() { + fcb_system *fss = ExAllocatePool( NonPagedPool, + sizeof( fcb_system ) ); + + if( !fss ) return NULL; + + RtlZeroMemory( fss, sizeof( *fss ) ); + + 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; + } + + RtlZeroMemory( fss->fcb_table, sizeof( FsdFcbEntry ** ) * + fss->fcb_table_size ); + + return fss; +} + +// Delete the fcb system +void FsdFcbDeinit( fcb_system *fss ) { + if( fss->fcb_table ) ExFreePool( fss->fcb_table ); +} + +// 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]; + + while( table_ent && _wcsicmp( table_ent->name, name ) && + table_ent->parent != parent ) + table_ent = table_ent->next; + + return table_ent; +} + +// 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; + + hashval = FsdNameHash( parent, filename ); + tableval = hashval & fss->fcb_table_mask; + + table_ent = ExAllocatePool( NonPagedPool, sizeof( FsdFcbEntry ) ); + + 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; + } + + return table_ent; +} + +// 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( !table_ent ) return; + + while( table_ent->next ) { + if( table_ent->next == which ) { + table_ent->next = table_ent->next->next; + ExFreePool( which ); + return; + } + table_ent = table_ent->next; + } +} diff --git a/reactos/drivers/fs/cdfs/makefile b/reactos/drivers/fs/cdfs/makefile new file mode 100644 index 00000000000..d14f7043344 --- /dev/null +++ b/reactos/drivers/fs/cdfs/makefile @@ -0,0 +1,15 @@ +# $Id: makefile,v 1.1 2002/04/12 15:41:39 ekohl Exp $ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = cdfs + +TARGET_OBJECTS = $(TARGET_NAME).o common.o fcb.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/reactos/install.bat b/reactos/install.bat index 5855c6c2f07..7b135a18452 100644 --- a/reactos/install.bat +++ b/reactos/install.bat @@ -26,6 +26,7 @@ copy ntoskrnl\ntoskrnl.exe %ROS_INSTALL%\system32 copy ntoskrnl\ntoskrnl.sym %ROS_INSTALL%\symbols copy hal\halx86\hal.dll %ROS_INSTALL%\system32 copy services\fs\vfat\vfatfs.sys %ROS_INSTALL%\system32\drivers +copy services\fs\cdfs\cdfs.sys %ROS_INSTALL%\system32\drivers copy services\fs\ms\msfs.sys %ROS_INSTALL%\system32\drivers copy services\fs\np\npfs.sys %ROS_INSTALL%\system32\drivers copy services\bus\acpi\acpi.sys %ROS_INSTALL%\system32\drivers