Split the driver into more files.

Replaced FCB code.
Improved the mount code.

svn path=/trunk/; revision=2851
This commit is contained in:
Eric Kohl 2002-04-15 20:39:49 +00:00
parent e00643eb28
commit 3730336e4d
12 changed files with 2364 additions and 852 deletions

View file

@ -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;
PCDFS_GLOBAL_DATA CdfsGlobalData;
/* 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,
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);

View file

@ -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;
struct _FCB *next;
struct _FCB *parent;
WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */
WCHAR PathName[MAX_PATH]; /* path+filename 260 max */
wchar_t name[CDFS_MAX_NAME_LEN];
int hashval;
unsigned int extent_start;
unsigned int byte_count;
unsigned int file_pointer;
} FsdFcbEntry, FCB, *PFCB;
// ERESOURCE PagingIoResource;
ERESOURCE MainResource;
LIST_ENTRY FcbListEntry;
struct _FCB* ParentFcb;
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
FsdGetFcbEntry(fcb_system *fss,
PFCB ParentFcb,
PWSTR name);
CdfsCreateFCB(PWCHAR FileName);
#endif//CDFS_H
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
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

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#include "cdfs.h"
/*
CDFS: FCB system (Perhaps there should be a library to make this easier)
*/
/* 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))
/* FUNCTIONS ****************************************************************/
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);
}
VOID
CdfsDestroyFCB(PFCB Fcb)
{
ExDeleteResourceLite(&Fcb->MainResource);
ExFreePool(Fcb);
}
BOOLEAN
CdfsFCBIsDirectory(PFCB Fcb)
{
// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY);
return(Fcb->Entry.FileFlags & 0x02);
}
BOOLEAN
CdfsFCBIsRoot(PFCB Fcb)
{
return(wcscmp(Fcb->PathName, L"\\") == 0);
}
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);
}
VOID
CdfsReleaseFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb)
{
KIRQL oldIrql;
DPRINT("releasing FCB at %x: %S, refCount:%d\n",
Fcb,
Fcb->PathName,
Fcb->RefCount);
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);
}
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);
}
#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;
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];
vfatGetDirEntryName (dirEntry, entryName);
wcscat (pathName, entryName);
}
rcFCB = vfatNewFCB (pathName);
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY));
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
// Create a hash over this name for table
static int FsdNameHash( FsdFcbEntry *parent, wchar_t *name ) {
int i;
int hashval = 0;
NTSTATUS
CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
PFCB Fcb,
PFILE_OBJECT FileObject)
{
NTSTATUS Status;
PCCB newCCB;
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;
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof(CCB), TAG_CCB);
if (newCCB == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
table_ent = table_ent->next;
}
memset(newCCB, 0, 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->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);
}
#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;
}
directoryIndex = 0;
finishedScanningDirectory = FALSE;
while (!finishedScanningDirectory)
{
status = vfatGetNextDirEntry (pDeviceExt,
pDirectoryFCB,
&directoryIndex,
currentLongName,
&currentDirEntry);
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 (&currentDirEntry)
&& !vfatIsDirEntryVolume(&currentDirEntry))
{
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentLongName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
directoryIndex - 1,
pFoundFCB);
return status;
}
else
{
vfatGetDirEntryName (&currentDirEntry, currentEntryName);
DPRINT (" entryName:%S\n", currentEntryName);
if (wstrcmpjoki (currentEntryName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentEntryName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
directoryIndex - 1,
pFoundFCB);
return status;
}
}
}
}
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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */

View file

@ -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 <ddk/ntddk.h>
//#define NDEBUG
#include <debug.h>
#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 */