[CDFS] Delete the old CDFS driver.

You served us well!
This commit is contained in:
Pierre Schweitzer 2018-08-21 12:27:35 +02:00
parent a4554c07b0
commit 5795254933
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
19 changed files with 0 additions and 5564 deletions

View file

@ -1,28 +0,0 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
list(APPEND SOURCE
cdfs.c
cleanup.c
close.c
common.c
create.c
devctrl.c
dirctl.c
dispatch.c
fastio.c
fcb.c
finfo.c
fsctl.c
misc.c
rw.c
volinfo.c
cdfs.h)
add_library(cdfs SHARED ${SOURCE} cdfs.rc)
set_module_type(cdfs kernelmodedriver)
target_link_libraries(cdfs ${PSEH_LIB})
add_importlibs(cdfs ntoskrnl hal)
add_pch(cdfs cdfs.h SOURCE)
add_cd_file(TARGET cdfs DESTINATION reactos/system32/drivers NO_CAB FOR all)
add_registry_inf(cdfs_reg.inf)

View file

@ -1,141 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/cdfs.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(INIT, DriverEntry)
#endif
/* GLOBALS ******************************************************************/
PCDFS_GLOBAL_DATA CdfsGlobalData;
/* FUNCTIONS ****************************************************************/
INIT_SECTION
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initialize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS: Success or failure
*/
{
NTSTATUS Status;
PDEVICE_OBJECT CdFsDeviceObject;
PDEVICE_OBJECT HddFsDeviceObject;
UNICODE_STRING CdFsDeviceName = RTL_CONSTANT_STRING(L"\\Cdfs");
UNICODE_STRING HddFsDeviceName = RTL_CONSTANT_STRING(L"\\CdfsHdd");
UNREFERENCED_PARAMETER(RegistryPath);
DPRINT("CDFS 0.0.3\n");
Status = IoCreateDevice(DriverObject,
sizeof(CDFS_GLOBAL_DATA),
&CdFsDeviceName,
FILE_DEVICE_CD_ROM_FILE_SYSTEM,
0,
FALSE,
&CdFsDeviceObject);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = IoCreateDevice(DriverObject,
0,
&HddFsDeviceName,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&HddFsDeviceObject);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Initialize global data */
CdfsGlobalData = CdFsDeviceObject->DeviceExtension;
RtlZeroMemory(CdfsGlobalData,
sizeof(CDFS_GLOBAL_DATA));
CdfsGlobalData->DriverObject = DriverObject;
CdfsGlobalData->CdFsDeviceObject = CdFsDeviceObject;
CdfsGlobalData->HddFsDeviceObject = HddFsDeviceObject;
HddFsDeviceObject->DeviceExtension = CdfsGlobalData;
/* Initialize driver data */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CdfsFsdDispatch;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = CdfsFsdDispatch;
CdfsGlobalData->FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
CdfsGlobalData->FastIoDispatch.FastIoCheckIfPossible = CdfsFastIoCheckIfPossible;
CdfsGlobalData->FastIoDispatch.FastIoRead = CdfsFastIoRead;
CdfsGlobalData->FastIoDispatch.FastIoWrite = CdfsFastIoWrite;
DriverObject->FastIoDispatch = &CdfsGlobalData->FastIoDispatch;
/* Initialize lookaside list for IRP contexts */
ExInitializeNPagedLookasideList(&CdfsGlobalData->IrpContextLookasideList,
NULL, NULL, 0, sizeof(CDFS_IRP_CONTEXT), 'PRIC', 0);
DriverObject->DriverUnload = NULL;
/* Cache manager */
CdfsGlobalData->CacheMgrCallbacks.AcquireForLazyWrite = CdfsAcquireForLazyWrite;
CdfsGlobalData->CacheMgrCallbacks.ReleaseFromLazyWrite = CdfsReleaseFromLazyWrite;
CdfsGlobalData->CacheMgrCallbacks.AcquireForReadAhead = CdfsAcquireForLazyWrite;
CdfsGlobalData->CacheMgrCallbacks.ReleaseFromReadAhead = CdfsReleaseFromLazyWrite;
CdFsDeviceObject->Flags |= DO_DIRECT_IO | DO_LOW_PRIORITY_FILESYSTEM;
HddFsDeviceObject->Flags |= DO_DIRECT_IO | DO_LOW_PRIORITY_FILESYSTEM;
IoRegisterFileSystem(CdFsDeviceObject);
IoRegisterFileSystem(HddFsDeviceObject);
return(STATUS_SUCCESS);
}

View file

@ -1,531 +0,0 @@
#ifndef CDFS_H
#define CDFS_H
#include <ntifs.h>
#include <ntddcdrm.h>
#include <pseh/pseh2.h>
#ifdef __GNUC__
#define INIT_SECTION __attribute__((section ("INIT")))
#else
#define INIT_SECTION /* Done via alloc_text for MSC */
#endif
#define CDFS_BASIC_SECTOR 2048
#define CDFS_PRIMARY_DESCRIPTOR_LOCATION 16
#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
#include <pshpack1.h>
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
};
#include <poppack.h>
typedef struct _DIR_RECORD DIR_RECORD, *PDIR_RECORD;
/* DIR_RECORD.FileFlags */
#define FILE_FLAG_HIDDEN 0x01
#define FILE_FLAG_DIRECTORY 0x02
#define FILE_FLAG_SYSTEM 0x04
#define FILE_FLAG_READONLY 0x10
/* Volume Descriptor header*/
#include <pshpack1.h>
struct _VD_HEADER
{
UCHAR VdType; // 1
UCHAR StandardId[5]; // 2-6
UCHAR VdVersion; // 7
};
typedef struct _VD_HEADER VD_HEADER, *PVD_HEADER;
/* Primary Volume Descriptor */
struct _PVD
{
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 ... */
};
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 ...
};
#include <poppack.h>
typedef struct _SVD SVD, *PSVD;
typedef struct _CDINFO
{
ULONG VolumeOffset;
ULONG VolumeSpaceSize;
ULONG JolietLevel;
ULONG RootStart;
ULONG RootSize;
WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)];
USHORT VolumeLabelLength;
ULONG SerialNumber;
} CDINFO, *PCDINFO;
#define VCB_VOLUME_LOCKED 0x0001
typedef struct
{
ERESOURCE VcbResource;
ERESOURCE DirResource;
KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead;
PDEVICE_OBJECT VolumeDevice;
PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT StreamFileObject;
ULONG Flags;
CDINFO CdInfo;
/* Notifications */
LIST_ENTRY NotifyList;
PNOTIFY_SYNC NotifySync;
/* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
ULONG OpenHandleCount;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
#define FCB_CACHE_INITIALIZED 0x0001
#define FCB_IS_VOLUME_STREAM 0x0002
#define FCB_IS_VOLUME 0x0004
#define MAX_PATH 260
typedef struct _CDFS_SHORT_NAME
{
LIST_ENTRY Entry;
LARGE_INTEGER StreamOffset;
UNICODE_STRING Name;
WCHAR NameBuffer[13];
} CDFS_SHORT_NAME, *PCDFS_SHORT_NAME;
typedef struct _FCB
{
FSRTL_COMMON_FCB_HEADER RFCB;
SECTION_OBJECT_POINTERS SectionObjectPointers;
ERESOURCE MainResource;
ERESOURCE PagingIoResource;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DevExt;
UNICODE_STRING ShortNameU;
WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */
UNICODE_STRING PathName; /* path+filename 260 max */
WCHAR PathNameBuffer[MAX_PATH]; /* Buffer for PathName */
WCHAR ShortNameBuffer[13];
LIST_ENTRY FcbListEntry;
struct _FCB* ParentFcb;
ULONG DirIndex;
LARGE_INTEGER IndexNumber; /* HighPart: Parent directory start sector */
/* LowPart: Directory record offset in the parent directory file */
LONG RefCount;
ULONG Flags;
DIR_RECORD Entry;
ERESOURCE NameListResource;
LIST_ENTRY ShortNameList;
FILE_LOCK FileLock;
} FCB, *PFCB;
typedef struct _CCB
{
LIST_ENTRY NextCCB;
PFILE_OBJECT PtrFileObject;
LARGE_INTEGER CurrentByteOffset;
/* for DirectoryControl */
ULONG Entry;
ULONG Offset;
/* for DirectoryControl */
UNICODE_STRING DirectorySearchPattern;
ULONG LastCluster;
ULONG LastOffset;
} CCB, *PCCB;
#define CDFS_TAG 'sfdC'
#define CDFS_CCB_TAG 'ccdC'
#define CDFS_NONPAGED_FCB_TAG 'nfdC'
#define CDFS_SHORT_NAME_TAG 'sgdC'
#define CDFS_SEARCH_PATTERN_TAG 'eedC'
#define CDFS_FILENAME_TAG 'nFdC'
typedef struct _CDFS_GLOBAL_DATA
{
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT CdFsDeviceObject;
PDEVICE_OBJECT HddFsDeviceObject;
ULONG Flags;
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
FAST_IO_DISPATCH FastIoDispatch;
NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
} CDFS_GLOBAL_DATA, *PCDFS_GLOBAL_DATA;
#define IRPCONTEXT_CANWAIT 0x1
#define IRPCONTEXT_COMPLETE 0x2
#define IRPCONTEXT_QUEUE 0x4
typedef struct _CDFS_IRP_CONTEXT
{
// NTFSIDENTIFIER Identifier;
ULONG Flags;
PIO_STACK_LOCATION Stack;
UCHAR MajorFunction;
UCHAR MinorFunction;
WORK_QUEUE_ITEM WorkQueueItem;
PIRP Irp;
BOOLEAN IsTopLevel;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
NTSTATUS SavedExceptionCode;
CCHAR PriorityBoost;
} CDFS_IRP_CONTEXT, *PCDFS_IRP_CONTEXT;
extern PCDFS_GLOBAL_DATA CdfsGlobalData;
/* cdfs.c */
NTSTATUS
NTAPI
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
/* cleanup.c */
NTSTATUS
NTAPI
CdfsCleanup(
PCDFS_IRP_CONTEXT IrpContext);
/* close.c */
NTSTATUS
NTAPI
CdfsClose(
PCDFS_IRP_CONTEXT IrpContext);
NTSTATUS
CdfsCloseFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject);
/* common.c */
NTSTATUS
CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN OUT PUCHAR Buffer,
IN BOOLEAN Override);
NTSTATUS
CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG pOutputBufferSize,
IN BOOLEAN Override);
/* create.c */
NTSTATUS
NTAPI
CdfsCreate(
PCDFS_IRP_CONTEXT IrpContext);
/* devctrl.c */
NTSTATUS NTAPI
CdfsDeviceControl(
PCDFS_IRP_CONTEXT IrpContext);
/* dirctl.c */
NTSTATUS
NTAPI
CdfsDirectoryControl(
PCDFS_IRP_CONTEXT IrpContext);
/* dispatch.c */
DRIVER_DISPATCH CdfsFsdDispatch;
NTSTATUS
NTAPI
CdfsFsdDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* fastio.c */
BOOLEAN
NTAPI
CdfsAcquireForLazyWrite(IN PVOID Context,
IN BOOLEAN Wait);
VOID
NTAPI
CdfsReleaseFromLazyWrite(IN PVOID Context);
FAST_IO_CHECK_IF_POSSIBLE CdfsFastIoCheckIfPossible;
FAST_IO_READ CdfsFastIoRead;
FAST_IO_WRITE CdfsFastIoWrite;
/* fcb.c */
PFCB
CdfsCreateFCB(PCWSTR FileName);
VOID
CdfsDestroyFCB(PFCB Fcb);
BOOLEAN
CdfsFCBIsDirectory(PFCB Fcb);
BOOLEAN
CdfsFCBIsRoot(PFCB Fcb);
VOID
CdfsGrabFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb);
VOID
CdfsReleaseFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb);
VOID
CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
PFCB Fcb);
PFCB
CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING FileName);
NTSTATUS
CdfsFCBInitializeCache(PVCB Vcb,
PFCB Fcb);
PFCB
CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb);
PFCB
CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb);
NTSTATUS
CdfsMakeFCBFromDirEntry(PVCB Vcb,
PFCB DirectoryFCB,
PWSTR LongName,
PWSTR ShortName,
PDIR_RECORD Record,
ULONG DirectorySector,
ULONG DirectoryOffset,
PFCB * fileFCB);
NTSTATUS
CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
PFCB Fcb,
PFILE_OBJECT FileObject);
NTSTATUS
CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
PFCB DirectoryFcb,
PUNICODE_STRING FileToFind,
PFCB *FoundFCB);
NTSTATUS
CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
PFCB *pParentFCB,
PFCB *pFCB,
PUNICODE_STRING FileName);
/* finfo.c */
NTSTATUS
NTAPI
CdfsQueryInformation(
PCDFS_IRP_CONTEXT IrpContext);
NTSTATUS
NTAPI
CdfsSetInformation(
PCDFS_IRP_CONTEXT IrpContext);
/* fsctl.c */
NTSTATUS NTAPI
CdfsFileSystemControl(
PCDFS_IRP_CONTEXT IrpContext);
/* misc.c */
BOOLEAN
CdfsIsIrpTopLevel(
PIRP Irp);
PCDFS_IRP_CONTEXT
CdfsAllocateIrpContext(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
VOID
CdfsSwapString(PWCHAR Out,
PUCHAR In,
ULONG Count);
VOID
CdfsDateTimeToSystemTime(PFCB Fcb,
PLARGE_INTEGER SystemTime);
VOID
CdfsFileFlagsToAttributes(PFCB Fcb,
PULONG FileAttributes);
VOID
CdfsShortNameCacheGet
(PFCB DirectoryFcb,
PLARGE_INTEGER StreamOffset,
PUNICODE_STRING LongName,
PUNICODE_STRING ShortName);
BOOLEAN
CdfsIsRecordValid(IN PDEVICE_EXTENSION DeviceExt,
IN PDIR_RECORD Record);
VOID
CdfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
PDIR_RECORD Record,
PWSTR Name);
/* rw.c */
NTSTATUS
NTAPI
CdfsRead(
PCDFS_IRP_CONTEXT IrpContext);
NTSTATUS
NTAPI
CdfsWrite(
PCDFS_IRP_CONTEXT IrpContext);
/* volinfo.c */
NTSTATUS
NTAPI
CdfsQueryVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext);
NTSTATUS
NTAPI
CdfsSetVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext);
#endif /* CDFS_H */

View file

@ -1,5 +0,0 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ISO9660 Driver"
#define REACTOS_STR_INTERNAL_NAME "cdfs"
#define REACTOS_STR_ORIGINAL_FILENAME "cdfs.sys"
#include <reactos/version.rc>

View file

@ -1,7 +0,0 @@
; Cdfs (ISO96660) filesystem driver
[AddReg]
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Group",0x00000000,"File System"
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","ImagePath",0x00020000,"system32\drivers\cdfs.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Start",0x00010001,0x00000003
HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Type",0x00010001,0x00000002

View file

@ -1,129 +0,0 @@
/*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/cleanup.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static NTSTATUS
CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Cleans up after a file has been closed.
*/
{
PDEVICE_EXTENSION DeviceExt;
PFCB Fcb;
DPRINT("CdfsCleanupFile(IrpContext %p, FileObject %p)\n",
IrpContext,
FileObject);
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Fcb = FileObject->FsContext;
if (!Fcb)
{
return STATUS_SUCCESS;
}
DeviceExt->OpenHandleCount--;
/* Notify about the cleanup */
FsRtlNotifyCleanup(DeviceExt->NotifySync,
&(DeviceExt->NotifyList),
FileObject->FsContext2);
if (!CdfsFCBIsDirectory(Fcb) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
FsRtlFastUnlockAll(&Fcb->FileLock,
FileObject,
IoGetRequestorProcess(IrpContext->Irp),
NULL);
}
/* Uninitialize file cache if initialized for this file object. */
if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap)
{
CcUninitializeCacheMap (FileObject, NULL, NULL);
}
/* Inform cleanup is complete */
FileObject->Flags |= FO_CLEANUP_COMPLETE;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
CdfsCleanup(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
NTSTATUS Status;
DPRINT("CdfsCleanup() called\n");
ASSERT(IrpContext);
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Stack = IrpContext->Stack;
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
{
DPRINT("Closing file system\n");
Status = STATUS_SUCCESS;
goto ByeBye;
}
FileObject = Stack->FileObject;
DeviceExtension = DeviceObject->DeviceExtension;
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE);
Status = CdfsCleanupFile(IrpContext, FileObject);
ExReleaseResourceLite(&DeviceExtension->DirResource);
KeLeaveCriticalRegion();
ByeBye:
Irp->IoStatus.Information = 0;
return(Status);
}
/* EOF */

View file

@ -1,115 +0,0 @@
/*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/close.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
NTSTATUS
CdfsCloseFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Closes a file
*/
{
PCCB Ccb;
DPRINT("CdfsCloseFile(DeviceExt %p, FileObject %p)\n",
DeviceExt,
FileObject);
Ccb = (PCCB)(FileObject->FsContext2);
DPRINT("Ccb %p\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, FileObject->FsContext);
}
if (Ccb->DirectorySearchPattern.Buffer)
{
ExFreePoolWithTag(Ccb->DirectorySearchPattern.Buffer, CDFS_SEARCH_PATTERN_TAG);
}
ExFreePoolWithTag(Ccb, CDFS_CCB_TAG);
return(STATUS_SUCCESS);
}
NTSTATUS NTAPI
CdfsClose(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
NTSTATUS Status;
DPRINT("CdfsClose() called\n");
ASSERT(IrpContext);
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Stack = IrpContext->Stack;
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
{
DPRINT("Closing file system\n");
Status = STATUS_SUCCESS;
goto ByeBye;
}
FileObject = Stack->FileObject;
DeviceExtension = DeviceObject->DeviceExtension;
Status = CdfsCloseFile(DeviceExtension,FileObject);
ByeBye:
Irp->IoStatus.Information = 0;
return(Status);
}
/* EOF */

View file

@ -1,242 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/common.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
NTSTATUS
CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN OUT PUCHAR Buffer,
IN BOOLEAN Override)
{
PIO_STACK_LOCATION Stack;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER Offset;
ULONG BlockSize;
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
BOOLEAN LastChance = FALSE;
again:
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Offset.u.LowPart = DiskSector << 11;
Offset.u.HighPart = DiskSector >> 21;
BlockSize = BLOCKSIZE * SectorCount;
DPRINT("CdfsReadSectors(DeviceObject %p, DiskSector %u, Buffer %p)\n",
DeviceObject, DiskSector, Buffer);
DPRINT("Offset %I64x BlockSize %u\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);
}
if (Override)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
}
DPRINT("Calling IO Driver... with irp %p\n", Irp);
Status = IoCallDriver(DeviceObject, Irp);
DPRINT("Waiting for IO Operation for %p\n", Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
DPRINT("Getting IO Status... for %p\n", Irp);
Status = IoStatus.Status;
}
if (!NT_SUCCESS(Status))
{
if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
Status = IoVerifyVolume(DeviceToVerify, FALSE);
if (NT_SUCCESS(Status) && !LastChance)
{
DPRINT("Volume verify succeeded; trying request again\n");
LastChance = TRUE;
goto again;
}
else if (NT_SUCCESS(Status))
{
DPRINT1("Failed to read after successful verify, aborting\n");
Status = STATUS_DEVICE_NOT_READY;
}
else
{
DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status);
}
}
DPRINT("CdfsReadSectors() failed (Status %x)\n", Status);
DPRINT("(DeviceObject %p, DiskSector %u, Buffer %p, Offset 0x%I64x)\n",
DeviceObject, DiskSector, Buffer,
Offset.QuadPart);
return(Status);
}
DPRINT("Block request succeeded for %p\n", Irp);
return(STATUS_SUCCESS);
}
NTSTATUS
CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize,
IN BOOLEAN Override)
{
PIO_STACK_LOCATION Stack;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
BOOLEAN LastChance = FALSE;
DPRINT("CdfsDeviceIoControl(DeviceObject %p, CtlCode %u, "
"InputBuffer %p, InputBufferSize %u, OutputBuffer %p, "
"POutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
OutputBufferSize ? *OutputBufferSize : 0);
again:
KeInitializeEvent (&Event, NotificationEvent, FALSE);
DPRINT("Building device I/O control request ...\n");
Irp = IoBuildDeviceIoControlRequest(CtlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
(OutputBufferSize != NULL) ? *OutputBufferSize : 0,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
if (Override)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
}
DPRINT ("Calling IO Driver... with irp %p\n", Irp);
Status = IoCallDriver(DeviceObject, Irp);
DPRINT ("Waiting for IO Operation for %p\n", Irp);
if (Status == STATUS_PENDING)
{
DPRINT ("Operation pending\n");
KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
DPRINT ("Getting IO Status... for %p\n", Irp);
Status = IoStatus.Status;
}
if (OutputBufferSize != NULL)
{
*OutputBufferSize = IoStatus.Information;
}
if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
if (DeviceToVerify)
{
Status = IoVerifyVolume(DeviceToVerify, FALSE);
DPRINT("IoVerifyVolume() returned (Status %lx)\n", Status);
}
if (NT_SUCCESS(Status) && !LastChance)
{
DPRINT1("Volume verify succeeded; trying request again\n");
LastChance = TRUE;
goto again;
}
else if (NT_SUCCESS(Status))
{
DPRINT1("Failed to read after successful verify, aborting\n");
Status = STATUS_DEVICE_NOT_READY;
}
else
{
DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status);
}
}
DPRINT("Returning Status %x\n", Status);
return Status;
}
/* EOF */

View file

@ -1,297 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/cdfs.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static NTSTATUS
CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject,
PUNICODE_STRING RelativeFileName,
PUNICODE_STRING AbsoluteFileName)
{
USHORT Length;
PFCB Fcb;
NTSTATUS Status;
DPRINT("try related for %wZ\n", RelativeFileName);
Fcb = FileObject->FsContext;
ASSERT(Fcb);
/* verify related object is a directory and target name
don't start with \. */
if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
(RelativeFileName->Length >= sizeof(WCHAR) &&
RelativeFileName->Buffer[0] == L'\\'))
{
return STATUS_INVALID_PARAMETER;
}
/* construct absolute path name */
Length = Fcb->PathName.Length +
sizeof(WCHAR) +
RelativeFileName->Length +
sizeof(WCHAR);
AbsoluteFileName->Length = 0;
AbsoluteFileName->MaximumLength = Length;
AbsoluteFileName->Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, CDFS_FILENAME_TAG);
if (AbsoluteFileName->Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
&Fcb->PathName);
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(AbsoluteFileName);
return Status;
}
if (!CdfsFCBIsRoot(Fcb))
{
Status = RtlAppendUnicodeToString(AbsoluteFileName,
L"\\");
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(AbsoluteFileName);
return Status;
}
}
Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
RelativeFileName);
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(AbsoluteFileName);
return Status;
}
return STATUS_SUCCESS;
}
/*
* FUNCTION: Opens a file
*/
static NTSTATUS
CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PUNICODE_STRING FileName)
{
PFCB ParentFcb;
PFCB Fcb;
NTSTATUS Status;
UNICODE_STRING AbsFileName;
DPRINT("CdfsOpenFile(%p, %p, %wZ)\n", DeviceExt, FileObject, FileName);
if (FileObject->RelatedFileObject)
{
DPRINT("Converting relative filename to absolute filename\n");
Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
FileName,
&AbsFileName);
if (!NT_SUCCESS(Status))
{
return Status;
}
FileName = &AbsFileName;
}
Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
IOCTL_CDROM_CHECK_VERIFY,
NULL,
0,
NULL,
0,
FALSE);
DPRINT ("Status %lx\n", Status);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("Status %lx\n", Status);
return Status;
}
DPRINT("PathName to open: %wZ\n", FileName);
/* try first to find an existing FCB in memory */
DPRINT("Checking for existing FCB in memory\n");
Fcb = CdfsGrabFCBFromTable(DeviceExt,
FileName);
if (Fcb == NULL)
{
DPRINT("No existing FCB found, making a new one if file exists.\n");
Status = CdfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
FileName);
if (ParentFcb != NULL)
{
CdfsReleaseFCB(DeviceExt,
ParentFcb);
}
if (!NT_SUCCESS (Status))
{
DPRINT("Could not make a new FCB, status: %x\n", Status);
if (FileName == &AbsFileName)
RtlFreeUnicodeString(&AbsFileName);
return Status;
}
}
DPRINT("Attaching FCB to fileObject\n");
Status = CdfsAttachFCBToFileObject(DeviceExt,
Fcb,
FileObject);
if ((FileName == &AbsFileName) && AbsFileName.Buffer)
ExFreePoolWithTag(AbsFileName.Buffer, CDFS_FILENAME_TAG);
return Status;
}
/*
* FUNCTION: Opens a file
*/
static NTSTATUS
CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
ULONG RequestedDisposition;
ULONG RequestedOptions;
PFCB Fcb;
NTSTATUS Status;
DPRINT("CdfsCreateFile() called\n");
DeviceExt = DeviceObject->DeviceExtension;
ASSERT(DeviceExt);
Stack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(Stack);
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
RequestedDisposition, RequestedOptions);
FileObject = Stack->FileObject;
if (RequestedDisposition == FILE_CREATE ||
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
return STATUS_ACCESS_DENIED;
}
Status = CdfsOpenFile(DeviceExt,
FileObject,
&FileObject->FileName);
if (NT_SUCCESS(Status))
{
Fcb = FileObject->FsContext;
/* Check whether the file has the requested attributes */
if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
{
CdfsCloseFile (DeviceExt, FileObject);
return STATUS_FILE_IS_A_DIRECTORY;
}
if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
{
CdfsCloseFile (DeviceExt, FileObject);
return STATUS_NOT_A_DIRECTORY;
}
DeviceExt->OpenHandleCount++;
}
/*
* If the directory containing the file to open doesn't exist then
* fail immediately
*/
Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
return Status;
}
NTSTATUS NTAPI
CdfsCreate(
PCDFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExt;
NTSTATUS Status;
DPRINT("CdfsCreate()\n");
ASSERT(IrpContext);
DeviceObject = IrpContext->DeviceObject;
DeviceExt = DeviceObject->DeviceExtension;
if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
{
return STATUS_ACCESS_DENIED;
}
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
{
/* DeviceObject represents FileSystem instead of logical volume */
DPRINT("Opening file system\n");
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
DeviceExt->OpenHandleCount++;
return STATUS_SUCCESS;
}
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
TRUE);
Status = CdfsCreateFile(DeviceObject,
IrpContext->Irp);
ExReleaseResourceLite(&DeviceExt->DirResource);
KeLeaveCriticalRegion();
return Status;
}
/* EOF */

View file

@ -1,69 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/devctrl.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Pierre Schweitzer
*
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
NTSTATUS NTAPI
CdfsDeviceControl(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
NTSTATUS Status;
PVCB Vcb = NULL;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
DPRINT("CdfsDeviceControl()\n");
ASSERT(IrpContext);
Irp = IrpContext->Irp;
Stack = IrpContext->Stack;
FileObject = Stack->FileObject;
Irp->IoStatus.Information = 0;
/* FIXME: HACK, it means that CD has changed */
if (!FileObject)
{
DPRINT1("FIXME: CdfsDeviceControl called without FileObject!\n");
return STATUS_INVALID_DEVICE_REQUEST;
}
/* Only support such operations on volume */
if (!(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
{
return STATUS_INVALID_PARAMETER;
}
if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE)
{
/* We should handle this one, but we don't! */
Status = STATUS_NOT_IMPLEMENTED;
}
else
{
/* Pass it to storage driver */
IoSkipCurrentIrpStackLocation(Irp);
Vcb = (PVCB)Stack->DeviceObject->DeviceExtension;
/* Lower driver will complete - we don't have to */
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
Status = IoCallDriver(Vcb->StorageDevice, Irp);
}
return Status;
}

View file

@ -1,812 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/dirctl.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
#define ROUND_DOWN(N, S) (((N) / (S)) * (S))
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
/* FUNCTIONS ****************************************************************/
/*
* FUNCTION: Retrieves the file name, be it in short or long file name format
*/
static NTSTATUS
CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
PVOID *Context,
PVOID *Block,
PLARGE_INTEGER StreamOffset,
ULONG DirLength,
PVOID *Ptr,
PWSTR Name,
PULONG pIndex,
PULONG CurrentOffset)
{
PDIR_RECORD Record = *Ptr;
ULONG Index;
if (*CurrentOffset >= DirLength)
return(STATUS_NO_MORE_ENTRIES);
if (*CurrentOffset == 0)
{
Index = 0;
Record = (PDIR_RECORD)*Block;
while (Index < *pIndex)
{
(*Ptr) = (PVOID)((ULONG_PTR)(*Ptr) + Record->RecordLength);
(*CurrentOffset) += Record->RecordLength;
Record = *Ptr;
if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
{
DPRINT("Map next sector\n");
CcUnpinData(*Context);
StreamOffset->QuadPart += BLOCKSIZE;
*CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
_SEH2_TRY
{
CcMapData(DeviceExt->StreamFileObject, StreamOffset, BLOCKSIZE, MAP_WAIT, Context, Block);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("CcMapData() failed\n");
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
*Ptr = *Block;
Record = (PDIR_RECORD)*Ptr;
}
if (*CurrentOffset >= DirLength)
return(STATUS_NO_MORE_ENTRIES);
Index++;
}
}
if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
{
DPRINT("Map next sector\n");
CcUnpinData(*Context);
StreamOffset->QuadPart += BLOCKSIZE;
*CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
_SEH2_TRY
{
CcMapData(DeviceExt->StreamFileObject, StreamOffset, BLOCKSIZE, MAP_WAIT, Context, Block);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("CcMapData() failed\n");
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
*Ptr = *Block;
Record = (PDIR_RECORD)*Ptr;
}
if (*CurrentOffset >= DirLength)
return STATUS_NO_MORE_ENTRIES;
DPRINT("Index %lu RecordLength %lu Offset %lu\n",
*pIndex, Record->RecordLength, *CurrentOffset);
if (!CdfsIsRecordValid(DeviceExt, Record))
{
CcUnpinData(*Context);
return STATUS_DISK_CORRUPT_ERROR;
}
CdfsGetDirEntryName(DeviceExt, Record, Name);
*Ptr = Record;
return(STATUS_SUCCESS);
}
/*
* FUNCTION: Find a file
*/
static NTSTATUS
CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
PFCB Fcb,
PFCB Parent,
PUNICODE_STRING FileToFind,
PULONG pDirIndex,
PULONG pOffset)
{
WCHAR name[256];
WCHAR ShortNameBuffer[13];
UNICODE_STRING TempString;
UNICODE_STRING ShortName;
UNICODE_STRING LongName;
UNICODE_STRING FileToFindUpcase;
PVOID Block;
NTSTATUS Status;
ULONG len;
ULONG DirIndex;
ULONG Offset = 0;
BOOLEAN IsRoot;
PVOID Context = NULL;
ULONG DirSize;
PDIR_RECORD Record;
LARGE_INTEGER StreamOffset, OffsetOfEntry;
DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
DPRINT("FindFile: old Pathname %p, old Objectname %p)\n",
Fcb->PathName, Fcb->ObjectName);
IsRoot = FALSE;
DirIndex = 0;
if (FileToFind == NULL || FileToFind->Length == 0)
{
RtlInitUnicodeString(&TempString, L".");
FileToFind = &TempString;
}
if (Parent)
{
if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart)
{
IsRoot = TRUE;
}
}
else
{
IsRoot = TRUE;
}
if (IsRoot != FALSE)
{
StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE;
DirSize = DeviceExt->CdInfo.RootSize;
if (FileToFind->Buffer[0] == 0 ||
(FileToFind->Buffer[0] == '\\' && FileToFind->Buffer[1] == 0) ||
(FileToFind->Buffer[0] == '.' && FileToFind->Buffer[1] == 0))
{
/* it's root : complete essentials fields then return ok */
RtlZeroMemory(Fcb, sizeof(FCB));
RtlInitEmptyUnicodeString(&Fcb->PathName, Fcb->PathNameBuffer, sizeof(Fcb->PathNameBuffer));
Fcb->PathNameBuffer[0] = '\\';
Fcb->PathName.Length = sizeof(WCHAR);
Fcb->ObjectName = &Fcb->PathNameBuffer[1];
Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart;
Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize;
Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY;
if (pDirIndex)
*pDirIndex = 0;
if (pOffset)
*pOffset = 0;
DPRINT("CdfsFindFile: new Pathname %wZ, new Objectname %S)\n",&Fcb->PathName, Fcb->ObjectName);
return STATUS_SUCCESS;
}
}
else
{
StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
DirSize = Parent->Entry.DataLengthL;
}
DPRINT("StreamOffset %I64d DirSize %u\n", StreamOffset.QuadPart, DirSize);
if (pDirIndex && (*pDirIndex))
DirIndex = *pDirIndex;
if (pOffset && (*pOffset))
{
Offset = *pOffset;
StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE);
}
_SEH2_TRY
{
CcMapData(DeviceExt->StreamFileObject, &StreamOffset, BLOCKSIZE, MAP_WAIT, &Context, &Block);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("CcMapData() failed\n");
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
Record = (PDIR_RECORD) ((ULONG_PTR)Block + Offset % BLOCKSIZE);
if (Offset)
{
Offset += Record->RecordLength;
Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
}
/* Upper case the expression for FsRtlIsNameInExpression */
Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
if (!NT_SUCCESS(Status))
{
return Status;
}
while(TRUE)
{
DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
Status = CdfsGetEntryName
(DeviceExt, &Context, &Block, &StreamOffset,
DirSize, (PVOID*)&Record, name, &DirIndex, &Offset);
if (Status == STATUS_NO_MORE_ENTRIES)
{
break;
}
else if (Status == STATUS_UNSUCCESSFUL || Status == STATUS_DISK_CORRUPT_ERROR)
{
/* Note: the directory cache has already been unpinned */
RtlFreeUnicodeString(&FileToFindUpcase);
return Status;
}
DPRINT("Name '%S'\n", name);
RtlInitUnicodeString(&LongName, name);
ShortName.Length = 0;
ShortName.MaximumLength = 26;
ShortName.Buffer = ShortNameBuffer;
OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
CdfsShortNameCacheGet(Parent, &OffsetOfEntry, &LongName, &ShortName);
DPRINT("ShortName '%wZ'\n", &ShortName);
if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
{
if (Parent->PathName.Buffer[0])
{
RtlCopyUnicodeString(&Fcb->PathName, &Parent->PathName);
len = Parent->PathName.Length / sizeof(WCHAR);
Fcb->ObjectName=&Fcb->PathName.Buffer[len];
if (len != 1 || Fcb->PathName.Buffer[0] != '\\')
{
Fcb->ObjectName[0] = '\\';
Fcb->ObjectName = &Fcb->ObjectName[1];
}
}
else
{
Fcb->ObjectName=Fcb->PathName.Buffer;
Fcb->ObjectName[0]='\\';
Fcb->ObjectName=&Fcb->ObjectName[1];
}
DPRINT("PathName '%wZ' ObjectName '%S'\n", &Fcb->PathName, Fcb->ObjectName);
memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD));
wcsncpy(Fcb->ObjectName, name, min(wcslen(name) + 1,
MAX_PATH - (Fcb->PathName.Length / sizeof(WCHAR)) + wcslen(Fcb->ObjectName)));
/* Copy short name */
Fcb->ShortNameU.Length = ShortName.Length;
Fcb->ShortNameU.MaximumLength = ShortName.Length;
Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
memcpy(Fcb->ShortNameBuffer, ShortName.Buffer, ShortName.Length);
if (pDirIndex)
*pDirIndex = DirIndex;
if (pOffset)
*pOffset = Offset;
DPRINT("FindFile: new Pathname %wZ, new Objectname %S, DirIndex %u\n",
&Fcb->PathName, Fcb->ObjectName, DirIndex);
RtlFreeUnicodeString(&FileToFindUpcase);
CcUnpinData(Context);
return STATUS_SUCCESS;
}
Offset += Record->RecordLength;
Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
DirIndex++;
}
RtlFreeUnicodeString(&FileToFindUpcase);
CcUnpinData(Context);
if (pDirIndex)
*pDirIndex = DirIndex;
if (pOffset)
*pOffset = Offset;
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
CdfsGetNameInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_NAMES_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetNameInformation() called\n");
UNREFERENCED_PARAMETER(DeviceExt);
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof(FILE_NAMES_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG));
RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
// Info->FileIndex=;
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsGetDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetDirectoryInformation() called\n");
UNREFERENCED_PARAMETER(DeviceExt);
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
Info->LastWriteTime = Info->CreationTime;
Info->ChangeTime = Info->CreationTime;
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0;
Info->AllocationSize.QuadPart = 0;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsGetFullDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIR_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetFullDirectoryInformation() called\n");
UNREFERENCED_PARAMETER(DeviceExt);
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_FULL_DIR_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) + Length, sizeof(ULONG));
RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
Info->LastWriteTime = Info->CreationTime;
Info->ChangeTime = Info->CreationTime;
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0;
Info->AllocationSize.QuadPart = 0;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
Info->EaSize = 0;
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsGetBothDirectoryInformation(PFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIR_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
DPRINT("CdfsGetBothDirectoryInformation() called\n");
UNREFERENCED_PARAMETER(DeviceExt);
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
return(STATUS_BUFFER_OVERFLOW);
Info->FileNameLength = Length;
Info->NextEntryOffset =
ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
/* Convert file times */
CdfsDateTimeToSystemTime(Fcb,
&Info->CreationTime);
Info->LastWriteTime = Info->CreationTime;
Info->ChangeTime = Info->CreationTime;
/* Convert file flags */
CdfsFileFlagsToAttributes(Fcb,
&Info->FileAttributes);
if (CdfsFCBIsDirectory(Fcb))
{
Info->EndOfFile.QuadPart = 0;
Info->AllocationSize.QuadPart = 0;
}
else
{
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
/* Make AllocSize a rounded up multiple of the sector size */
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
}
// Info->FileIndex=;
Info->EaSize = 0;
/* Copy short name */
ASSERT(Fcb->ShortNameU.Length / sizeof(WCHAR) <= 12);
Info->ShortNameLength = (CCHAR)Fcb->ShortNameU.Length;
RtlCopyMemory(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length);
return(STATUS_SUCCESS);
}
static NTSTATUS
CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
LONG BufferLength = 0;
PUNICODE_STRING SearchPattern = NULL;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG FileIndex = 0;
PUCHAR Buffer = NULL;
PFILE_NAMES_INFORMATION Buffer0 = NULL;
PFCB Fcb;
PCCB Ccb;
FCB TempFcb;
BOOLEAN First = FALSE;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CdfsQueryDirectory() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
FileObject = Stack->FileObject;
RtlInitEmptyUnicodeString(&TempFcb.PathName, TempFcb.PathNameBuffer, sizeof(TempFcb.PathNameBuffer));
Ccb = (PCCB)FileObject->FsContext2;
Fcb = (PFCB)FileObject->FsContext;
/* Obtain the callers parameters */
BufferLength = Stack->Parameters.QueryDirectory.Length;
SearchPattern = Stack->Parameters.QueryDirectory.FileName;
FileInformationClass =
Stack->Parameters.QueryDirectory.FileInformationClass;
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
/* Determine Buffer for result */
if (Irp->MdlAddress)
{
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
}
else
{
Buffer = Irp->UserBuffer;
}
/* Allocate search pattern in case:
* -> We don't have one already in context
* -> We have been given an input pattern
* -> The pattern length is not null
* -> The pattern buffer is not null
* Otherwise, we'll fall later and allocate a match all (*) pattern
*/
if (SearchPattern != NULL &&
SearchPattern->Length != 0 && SearchPattern->Buffer != NULL)
{
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
First = TRUE;
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG);
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern);
Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
}
}
else if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
First = TRUE;
Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG);
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR);
Ccb->DirectorySearchPattern.Buffer[0] = L'*';
Ccb->DirectorySearchPattern.Buffer[1] = 0;
}
DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern);
/* Determine directory index */
if (Stack->Flags & SL_INDEX_SPECIFIED)
{
Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex;
Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart;
}
else if (First || (Stack->Flags & SL_RESTART_SCAN))
{
Ccb->Entry = 0;
Ccb->Offset = 0;
}
DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern);
TempFcb.ObjectName = TempFcb.PathName.Buffer;
while (Status == STATUS_SUCCESS && BufferLength > 0)
{
Status = CdfsFindFile(DeviceExtension,
&TempFcb,
Fcb,
&Ccb->DirectorySearchPattern,
&Ccb->Entry,
&Ccb->Offset);
DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
if (NT_SUCCESS(Status))
{
switch (FileInformationClass)
{
case FileNameInformation:
Status = CdfsGetNameInformation(&TempFcb,
DeviceExtension,
(PFILE_NAMES_INFORMATION)Buffer,
BufferLength);
break;
case FileDirectoryInformation:
Status = CdfsGetDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_DIRECTORY_INFORMATION)Buffer,
BufferLength);
break;
case FileFullDirectoryInformation:
Status = CdfsGetFullDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_FULL_DIR_INFORMATION)Buffer,
BufferLength);
break;
case FileBothDirectoryInformation:
Status = CdfsGetBothDirectoryInformation(&TempFcb,
DeviceExtension,
(PFILE_BOTH_DIR_INFORMATION)Buffer,
BufferLength);
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
if (Status == STATUS_BUFFER_OVERFLOW)
{
break;
}
}
else
{
if (First)
{
Status = STATUS_NO_SUCH_FILE;
}
else
{
Status = STATUS_NO_MORE_FILES;
}
break;
}
Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
Buffer0->FileIndex = FileIndex++;
Ccb->Entry++;
BufferLength -= Buffer0->NextEntryOffset;
if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{
break;
}
Buffer += Buffer0->NextEntryOffset;
}
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
if (FileIndex > 0)
{
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Stack->Parameters.QueryDirectory.Length - BufferLength;
}
return(Status);
}
static NTSTATUS
CdfsNotifyChangeDirectory(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PCDFS_IRP_CONTEXT IrpContext)
{
PDEVICE_EXTENSION DeviceExtension;
PFCB Fcb;
PCCB Ccb;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
DPRINT("CdfsNotifyChangeDirectory() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
FileObject = Stack->FileObject;
Ccb = (PCCB)FileObject->FsContext2;
Fcb = (PFCB)FileObject->FsContext;
FsRtlNotifyFullChangeDirectory(DeviceExtension->NotifySync,
&(DeviceExtension->NotifyList),
Ccb,
(PSTRING)&(Fcb->PathName),
BooleanFlagOn(Stack->Flags, SL_WATCH_TREE),
FALSE,
Stack->Parameters.NotifyDirectory.CompletionFilter,
Irp,
NULL,
NULL);
/* We won't handle IRP completion */
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
return STATUS_PENDING;
}
NTSTATUS NTAPI
CdfsDirectoryControl(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
DPRINT("CdfsDirectoryControl() called\n");
ASSERT(IrpContext);
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Irp->IoStatus.Information = 0;
switch (IrpContext->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
Status = CdfsQueryDirectory(DeviceObject,
Irp);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
Status = CdfsNotifyChangeDirectory(DeviceObject,
Irp, IrpContext);
break;
default:
DPRINT1("CDFS: MinorFunction %u\n", IrpContext->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return(Status);
}
/* EOF */

View file

@ -1,222 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2008 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/dispatch.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Pierre Schweitzer
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
static LONG QueueCount = 0;
/* FUNCTIONS ****************************************************************/
static WORKER_THREAD_ROUTINE CdfsDoRequest;
static
NTSTATUS
CdfsQueueRequest(PCDFS_IRP_CONTEXT IrpContext)
{
InterlockedIncrement(&QueueCount);
DPRINT("CdfsQueueRequest(IrpContext %p), %d\n", IrpContext, QueueCount);
ASSERT(!(IrpContext->Flags & IRPCONTEXT_QUEUE) &&
(IrpContext->Flags & IRPCONTEXT_COMPLETE));
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
IoMarkIrpPending(IrpContext->Irp);
ExInitializeWorkItem(&IrpContext->WorkQueueItem, CdfsDoRequest, IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING;
}
static
NTSTATUS
CdfsLockControl(
IN PCDFS_IRP_CONTEXT IrpContext)
{
PFCB Fcb;
NTSTATUS Status;
DPRINT("CdfsLockControl(IrpContext %p)\n", IrpContext);
if (IrpContext->DeviceObject == CdfsGlobalData->CdFsDeviceObject || IrpContext->DeviceObject == CdfsGlobalData->HddFsDeviceObject)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
Fcb = IrpContext->FileObject->FsContext;
if (CdfsFCBIsDirectory(Fcb))
{
return STATUS_INVALID_PARAMETER;
}
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
Status = FsRtlProcessFileLock(&Fcb->FileLock,
IrpContext->Irp,
NULL);
return Status;
}
static
NTSTATUS
CdfsDispatch(PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp = IrpContext->Irp;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
DPRINT("CdfsDispatch()\n");
FsRtlEnterFileSystem();
CdfsIsIrpTopLevel(Irp);
switch (IrpContext->MajorFunction)
{
case IRP_MJ_QUERY_VOLUME_INFORMATION:
Status = CdfsQueryVolumeInformation(IrpContext);
break;
case IRP_MJ_SET_VOLUME_INFORMATION:
Status = CdfsSetVolumeInformation(IrpContext);
break;
case IRP_MJ_QUERY_INFORMATION:
Status = CdfsQueryInformation(IrpContext);
break;
case IRP_MJ_SET_INFORMATION:
Status = CdfsSetInformation(IrpContext);
break;
case IRP_MJ_DIRECTORY_CONTROL:
Status = CdfsDirectoryControl(IrpContext);
break;
case IRP_MJ_READ:
Status = CdfsRead(IrpContext);
break;
case IRP_MJ_DEVICE_CONTROL:
Status = CdfsDeviceControl(IrpContext);
break;
case IRP_MJ_WRITE:
Status = CdfsWrite(IrpContext);
break;
case IRP_MJ_CLOSE:
Status = CdfsClose(IrpContext);
break;
case IRP_MJ_CREATE:
Status = CdfsCreate(IrpContext);
break;
case IRP_MJ_CLEANUP:
Status = CdfsCleanup(IrpContext);
break;
case IRP_MJ_FILE_SYSTEM_CONTROL:
Status = CdfsFileSystemControl(IrpContext);
break;
case IRP_MJ_LOCK_CONTROL:
Status = CdfsLockControl(IrpContext);
break;
}
ASSERT((!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||
((IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||
(!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && (IrpContext->Flags & IRPCONTEXT_QUEUE)));
if (IrpContext->Flags & IRPCONTEXT_COMPLETE)
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IrpContext->PriorityBoost);
}
if (IrpContext->Flags & IRPCONTEXT_QUEUE)
{
/* Reset our status flags before queueing the IRP */
IrpContext->Flags |= IRPCONTEXT_COMPLETE;
IrpContext->Flags &= ~IRPCONTEXT_QUEUE;
Status = CdfsQueueRequest(IrpContext);
}
else
{
ExFreeToNPagedLookasideList(&CdfsGlobalData->IrpContextLookasideList, IrpContext);
}
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
return Status;
}
static
VOID
NTAPI
CdfsDoRequest(PVOID IrpContext)
{
InterlockedDecrement(&QueueCount);
DPRINT("CdfsDoRequest(IrpContext %p), MajorFunction %x, %d\n",
IrpContext, ((PCDFS_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
CdfsDispatch((PCDFS_IRP_CONTEXT)IrpContext);
}
/*
* FUNCTION: This function manages IRP for various major functions
* ARGUMENTS:
* DriverObject = object describing this driver
* Irp = IRP to be passed to internal functions
* RETURNS: Status of I/O Request
*/
NTSTATUS
NTAPI
CdfsFsdDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PCDFS_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status;
DPRINT("CdfsFsdDispatch()\n");
IrpContext = CdfsAllocateIrpContext(DeviceObject, Irp);
if (IrpContext == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else
{
Status = CdfsDispatch(IrpContext);
}
return Status;
}

View file

@ -1,116 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/fastio.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Pierre Schweitzer
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
BOOLEAN
NTAPI
CdfsAcquireForLazyWrite(
_In_ PVOID Context,
_In_ BOOLEAN Wait)
{
PFCB Fcb = (PFCB)Context;
ASSERT(Fcb);
DPRINT("CdfsAcquireForLazyWrite(): Fcb %p\n", Fcb);
if (!ExAcquireResourceExclusiveLite(&(Fcb->MainResource), Wait))
{
DPRINT("CdfsAcquireForLazyWrite(): ExReleaseResourceLite failed.\n");
return FALSE;
}
return TRUE;
}
VOID
NTAPI
CdfsReleaseFromLazyWrite(
_In_ PVOID Context)
{
PFCB Fcb = (PFCB)Context;
ASSERT(Fcb);
DPRINT("CdfsReleaseFromLazyWrite(): Fcb %p\n", Fcb);
ExReleaseResourceLite(&(Fcb->MainResource));
}
BOOLEAN
NTAPI
CdfsFastIoCheckIfPossible(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_In_ ULONG LockKey,
_In_ BOOLEAN CheckForReadOperation,
_Out_ PIO_STATUS_BLOCK IoStatus,
_In_ PDEVICE_OBJECT DeviceObject)
{
/* Deny FastIo */
UNREFERENCED_PARAMETER(FileObject);
UNREFERENCED_PARAMETER(FileOffset);
UNREFERENCED_PARAMETER(Length);
UNREFERENCED_PARAMETER(Wait);
UNREFERENCED_PARAMETER(LockKey);
UNREFERENCED_PARAMETER(CheckForReadOperation);
UNREFERENCED_PARAMETER(IoStatus);
UNREFERENCED_PARAMETER(DeviceObject);
return FALSE;
}
BOOLEAN
NTAPI
CdfsFastIoRead(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_In_ ULONG LockKey,
_Out_ PVOID Buffer,
_Out_ PIO_STATUS_BLOCK IoStatus,
_In_ PDEVICE_OBJECT DeviceObject)
{
DBG_UNREFERENCED_PARAMETER(FileObject);
DBG_UNREFERENCED_PARAMETER(FileOffset);
DBG_UNREFERENCED_PARAMETER(Length);
DBG_UNREFERENCED_PARAMETER(Wait);
DBG_UNREFERENCED_PARAMETER(LockKey);
DBG_UNREFERENCED_PARAMETER(Buffer);
DBG_UNREFERENCED_PARAMETER(IoStatus);
DBG_UNREFERENCED_PARAMETER(DeviceObject);
return FALSE;
}
BOOLEAN
NTAPI
CdfsFastIoWrite(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_In_ ULONG LockKey,
_In_ PVOID Buffer,
_Out_ PIO_STATUS_BLOCK IoStatus,
_In_ PDEVICE_OBJECT DeviceObject)
{
DBG_UNREFERENCED_PARAMETER(FileObject);
DBG_UNREFERENCED_PARAMETER(FileOffset);
DBG_UNREFERENCED_PARAMETER(Length);
DBG_UNREFERENCED_PARAMETER(Wait);
DBG_UNREFERENCED_PARAMETER(LockKey);
DBG_UNREFERENCED_PARAMETER(Buffer);
DBG_UNREFERENCED_PARAMETER(IoStatus);
DBG_UNREFERENCED_PARAMETER(DeviceObject);
return FALSE;
}

View file

@ -1,722 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/fcb.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
/* FUNCTIONS ****************************************************************/
static BOOLEAN
CdfsGetNextPathElement(PCUNICODE_STRING CurrentElement, PUNICODE_STRING NextElement)
{
*NextElement = *CurrentElement;
if (NextElement->Length == 0)
return FALSE;
while ((NextElement->Length) && (NextElement->Buffer[0] != L'\\'))
{
NextElement->Buffer++;
NextElement->Length -= sizeof(WCHAR);
NextElement->MaximumLength -= sizeof(WCHAR);
}
return TRUE;
}
PFCB
CdfsCreateFCB(PCWSTR FileName)
{
PFCB Fcb;
Fcb = ExAllocatePoolWithTag(NonPagedPool,
sizeof(FCB),
CDFS_NONPAGED_FCB_TAG);
if(!Fcb) return NULL;
RtlZeroMemory(Fcb, sizeof(FCB));
RtlInitEmptyUnicodeString(&Fcb->PathName, Fcb->PathNameBuffer, sizeof(Fcb->PathNameBuffer));
if (FileName)
{
RtlAppendUnicodeToString(&Fcb->PathName, FileName);
if (wcsrchr(Fcb->PathName.Buffer, '\\') != 0)
{
Fcb->ObjectName = wcsrchr(Fcb->PathName.Buffer, '\\');
}
else
{
Fcb->ObjectName = Fcb->PathName.Buffer;
}
}
ExInitializeResourceLite(&Fcb->PagingIoResource);
ExInitializeResourceLite(&Fcb->MainResource);
ExInitializeResourceLite(&Fcb->NameListResource);
Fcb->RFCB.PagingIoResource = &Fcb->PagingIoResource;
Fcb->RFCB.Resource = &Fcb->MainResource;
Fcb->RFCB.IsFastIoPossible = FastIoIsNotPossible;
InitializeListHead(&Fcb->ShortNameList);
FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
return(Fcb);
}
VOID
CdfsDestroyFCB(PFCB Fcb)
{
PLIST_ENTRY Entry;
FsRtlUninitializeFileLock(&Fcb->FileLock);
ExDeleteResourceLite(&Fcb->PagingIoResource);
ExDeleteResourceLite(&Fcb->MainResource);
while (!IsListEmpty(&Fcb->ShortNameList))
{
Entry = Fcb->ShortNameList.Flink;
RemoveEntryList(Entry);
ExFreePoolWithTag(Entry, CDFS_SHORT_NAME_TAG);
}
ExDeleteResourceLite(&Fcb->NameListResource);
ExFreePoolWithTag(Fcb, CDFS_NONPAGED_FCB_TAG);
}
BOOLEAN
CdfsFCBIsDirectory(PFCB Fcb)
{
return(Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY);
}
BOOLEAN
CdfsFCBIsRoot(PFCB Fcb)
{
return (Fcb->PathName.Length == sizeof(WCHAR) && Fcb->PathName.Buffer[0] == L'\\');
}
VOID
CdfsGrabFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb)
{
KIRQL oldIrql;
DPRINT("grabbing FCB at %p: %wZ, 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 %p: %wZ, refCount:%d\n",
Fcb,
&Fcb->PathName,
Fcb->RefCount);
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
Fcb->RefCount--;
if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb))
{
RemoveEntryList(&Fcb->FcbListEntry);
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,
PUNICODE_STRING FileName)
{
KIRQL oldIrql;
PFCB Fcb;
PLIST_ENTRY current_entry;
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
if (FileName == NULL || FileName->Length == 0 || FileName->Buffer[0] == 0)
{
DPRINT("Return FCB for stream file object\n");
Fcb = Vcb->StreamFileObject->FsContext;
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);
// Disabled the DPRINT! Can't be called at DISPATCH_LEVEL!
//DPRINT("Comparing '%wZ' and '%wZ'\n", FileName, &Fcb->PathName);
if (RtlCompareUnicodeString(FileName, &Fcb->PathName, TRUE) == 0)
{
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;
PCCB newCCB;
FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), CDFS_CCB_TAG);
if (newCCB == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(newCCB,
sizeof(CCB));
FileObject->ReadAccess = TRUE;
FileObject->WriteAccess = FALSE;
FileObject->DeleteAccess = FALSE;
FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
FileObject->FsContext = Fcb;
FileObject->FsContext2 = newCCB;
newCCB->PtrFileObject = FileObject;
Fcb->FileObject = FileObject;
Fcb->DevExt = Vcb;
_SEH2_TRY
{
CcInitializeCacheMap(FileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
FALSE,
&(CdfsGlobalData->CacheMgrCallbacks),
Fcb);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
FileObject->FsContext2 = NULL;
ExFreePoolWithTag(newCCB, CDFS_CCB_TAG);
ObDereferenceObject(FileObject);
Fcb->FileObject = NULL;
return _SEH2_GetExceptionCode();
}
_SEH2_END;
ObDereferenceObject(FileObject);
Fcb->Flags |= FCB_CACHE_INITIALIZED;
return STATUS_SUCCESS;
}
PFCB
CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb)
{
PFCB Fcb;
Fcb = CdfsCreateFCB(L"\\");
Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
Fcb->Entry.FileFlags = FILE_FLAG_DIRECTORY;
Fcb->IndexNumber.QuadPart = 0LL;
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)
{
UNICODE_STRING FileName;
PFCB Fcb;
RtlInitUnicodeString(&FileName, L"\\");
Fcb = CdfsGrabFCBFromTable(Vcb,
&FileName);
if (Fcb == NULL)
{
Fcb = CdfsMakeRootFCB(Vcb);
}
return(Fcb);
}
NTSTATUS
CdfsMakeFCBFromDirEntry(PVCB Vcb,
PFCB DirectoryFCB,
PWSTR LongName,
PWSTR ShortName,
PDIR_RECORD Record,
ULONG DirectorySector,
ULONG DirectoryOffset,
PFCB * fileFCB)
{
WCHAR pathName[MAX_PATH];
PFCB rcFCB;
ULONG Size;
/* Check if the full string would overflow the pathName buffer (the additional characters are for '\\' and '\0') */
if ((LongName[0] != 0) &&
((DirectoryFCB->PathName.Length / sizeof(WCHAR)) + 1 + wcslen(LongName) + 1 > MAX_PATH))
{
return(STATUS_OBJECT_NAME_INVALID);
}
wcscpy(pathName, DirectoryFCB->PathName.Buffer);
if (!CdfsFCBIsRoot(DirectoryFCB))
{
wcscat(pathName, L"\\");
}
if (LongName[0] != 0)
{
wcscat(pathName, LongName);
}
else
{
WCHAR entryName[MAX_PATH];
CdfsGetDirEntryName(Vcb, Record, entryName);
wcscat(pathName, entryName);
}
rcFCB = CdfsCreateFCB(pathName);
memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD));
/* Copy short name into FCB */
rcFCB->ShortNameU.Length = wcslen(ShortName) * sizeof(WCHAR);
rcFCB->ShortNameU.MaximumLength = rcFCB->ShortNameU.Length;
rcFCB->ShortNameU.Buffer = rcFCB->ShortNameBuffer;
wcscpy(rcFCB->ShortNameBuffer, ShortName);
Size = rcFCB->Entry.DataLengthL;
rcFCB->RFCB.FileSize.QuadPart = Size;
rcFCB->RFCB.ValidDataLength.QuadPart = Size;
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE);
if (CdfsFCBIsDirectory(rcFCB))
{
CdfsFCBInitializeCache(Vcb, rcFCB);
}
rcFCB->IndexNumber.u.HighPart = DirectorySector;
rcFCB->IndexNumber.u.LowPart = DirectoryOffset;
rcFCB->RefCount++;
CdfsAddFCBToTable(Vcb, rcFCB);
*fileFCB = rcFCB;
DPRINT("%S %u %I64d\n", LongName, Size, rcFCB->RFCB.AllocationSize.QuadPart);
return(STATUS_SUCCESS);
}
NTSTATUS
CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
PFCB Fcb,
PFILE_OBJECT FileObject)
{
PCCB newCCB;
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), CDFS_CCB_TAG);
if (newCCB == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
memset(newCCB, 0, sizeof(CCB));
FileObject->ReadAccess = TRUE;
FileObject->WriteAccess = FALSE;
FileObject->DeleteAccess = FALSE;
FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
FileObject->FsContext = Fcb;
FileObject->FsContext2 = newCCB;
newCCB->PtrFileObject = FileObject;
Fcb->DevExt = Vcb;
if (CdfsFCBIsDirectory(Fcb))
{
_SEH2_TRY
{
CcInitializeCacheMap(FileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
FALSE,
&(CdfsGlobalData->CacheMgrCallbacks),
Fcb);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
FileObject->FsContext2 = NULL;
ExFreePoolWithTag(newCCB, CDFS_CCB_TAG);
return _SEH2_GetExceptionCode();
}
_SEH2_END;
Fcb->Flags |= FCB_CACHE_INITIALIZED;
}
DPRINT("file open: fcb:%p file size: %u\n", Fcb, Fcb->Entry.DataLengthL);
return(STATUS_SUCCESS);
}
NTSTATUS
CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
PFCB DirectoryFcb,
PUNICODE_STRING FileToFind,
PFCB *FoundFCB)
{
UNICODE_STRING TempName;
WCHAR Name[256];
PVOID Block;
ULONG DirSize;
PDIR_RECORD Record;
ULONG Offset;
ULONG BlockOffset;
NTSTATUS Status;
LARGE_INTEGER StreamOffset, OffsetOfEntry;
PVOID Context;
WCHAR ShortNameBuffer[13];
UNICODE_STRING ShortName;
UNICODE_STRING LongName;
UNICODE_STRING FileToFindUpcase;
ASSERT(DeviceExt);
ASSERT(DirectoryFcb);
ASSERT(FileToFind);
DPRINT("CdfsDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
DeviceExt,
DirectoryFcb,
FileToFind);
DPRINT("Dir Path:%wZ\n", &DirectoryFcb->PathName);
/* default to '.' if no filename specified */
if (FileToFind->Length == 0)
{
RtlInitUnicodeString(&TempName, L".");
FileToFind = &TempName;
}
DirSize = DirectoryFcb->Entry.DataLengthL;
StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
_SEH2_TRY
{
CcMapData(DeviceExt->StreamFileObject, &StreamOffset, BLOCKSIZE, MAP_WAIT, &Context, &Block);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("CcMapData() failed\n");
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
Offset = 0;
BlockOffset = 0;
Record = (PDIR_RECORD)Block;
/* Upper case the expression for FsRtlIsNameInExpression */
Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
if (!NT_SUCCESS(Status))
{
return Status;
}
while(TRUE)
{
if (Record->RecordLength == 0)
{
DPRINT("RecordLength == 0 Stopped!\n");
break;
}
DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
if (!CdfsIsRecordValid(DeviceExt, Record))
{
RtlFreeUnicodeString(&FileToFindUpcase);
CcUnpinData(Context);
return STATUS_DISK_CORRUPT_ERROR;
}
CdfsGetDirEntryName(DeviceExt, Record, Name);
DPRINT ("Name '%S'\n", Name);
DPRINT ("Sector %lu\n", DirectoryFcb->Entry.ExtentLocationL);
DPRINT ("Offset %lu\n", Offset);
RtlInitUnicodeString(&LongName, Name);
RtlInitEmptyUnicodeString(&ShortName, ShortNameBuffer, sizeof(ShortNameBuffer));
RtlZeroMemory(ShortNameBuffer, sizeof(ShortNameBuffer));
OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
CdfsShortNameCacheGet(DirectoryFcb, &OffsetOfEntry, &LongName, &ShortName);
DPRINT("ShortName '%wZ'\n", &ShortName);
ASSERT(LongName.Length >= sizeof(WCHAR));
ASSERT(ShortName.Length >= sizeof(WCHAR));
if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
{
DPRINT("Match found, %S\n", Name);
Status = CdfsMakeFCBFromDirEntry(DeviceExt,
DirectoryFcb,
Name,
ShortNameBuffer,
Record,
DirectoryFcb->Entry.ExtentLocationL,
Offset,
FoundFCB);
RtlFreeUnicodeString(&FileToFindUpcase);
CcUnpinData(Context);
return(Status);
}
Offset += Record->RecordLength;
BlockOffset += Record->RecordLength;
Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
{
DPRINT("Map next sector\n");
CcUnpinData(Context);
StreamOffset.QuadPart += BLOCKSIZE;
Offset = ROUND_UP(Offset, BLOCKSIZE);
BlockOffset = 0;
_SEH2_TRY
{
CcMapData(DeviceExt->StreamFileObject, &StreamOffset, BLOCKSIZE, MAP_WAIT, &Context, &Block);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("CcMapData() failed\n");
RtlFreeUnicodeString(&FileToFindUpcase);
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
}
if (Offset >= DirSize)
break;
}
RtlFreeUnicodeString(&FileToFindUpcase);
CcUnpinData(Context);
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
NTSTATUS
CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
PFCB *pParentFCB,
PFCB *pFCB,
PUNICODE_STRING FileName)
{
UNICODE_STRING PathName;
UNICODE_STRING NextElement;
UNICODE_STRING CurrentElement;
NTSTATUS Status;
PFCB FCB;
PFCB parentFCB;
DPRINT("CdfsGetFCBForFile(%p, %p, %p, '%wZ')\n",
Vcb,
pParentFCB,
pFCB,
FileName);
/* Trivial case, open of the root directory on volume */
if (FileName->Length == 0 ||
((FileName->Buffer[0] == '\\') && (FileName->Length == sizeof(WCHAR))))
{
DPRINT("returning root FCB\n");
FCB = CdfsOpenRootFCB(Vcb);
*pFCB = FCB;
*pParentFCB = NULL;
return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
}
else
{
/* Start with empty path */
PathName = *FileName;
PathName.Length = 0;
CurrentElement = *FileName;
FCB = CdfsOpenRootFCB (Vcb);
}
parentFCB = NULL;
/* Parse filename and check each path element for existence and access */
while (CdfsGetNextPathElement(&CurrentElement, &NextElement))
{
/* Skip blank directory levels */
if (CurrentElement.Buffer[0] == L'\\')
{
CurrentElement.Buffer++;
CurrentElement.Length -= sizeof(WCHAR);
CurrentElement.MaximumLength -= sizeof(WCHAR);
continue;
}
DPRINT("Parsing, currentElement:%wZ\n", &CurrentElement);
DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB);
/* Descend to next directory level */
if (parentFCB)
{
CdfsReleaseFCB(Vcb, parentFCB);
parentFCB = NULL;
}
/* fail if element in FCB is not a directory */
if (!CdfsFCBIsDirectory(FCB))
{
DPRINT("Element in requested path is not a directory\n");
CdfsReleaseFCB(Vcb, FCB);
FCB = 0;
*pParentFCB = NULL;
*pFCB = NULL;
return(STATUS_OBJECT_PATH_NOT_FOUND);
}
parentFCB = FCB;
/* Extract next directory level */
PathName.Length = (NextElement.Buffer - FileName->Buffer) * sizeof(WCHAR);
DPRINT(" PathName:%wZ\n", &PathName);
FCB = CdfsGrabFCBFromTable(Vcb, &PathName);
if (FCB == NULL)
{
UNICODE_STRING ChildElement = CurrentElement;
ChildElement.Length = (NextElement.Buffer - CurrentElement.Buffer) * sizeof(WCHAR);
Status = CdfsDirFindFile(Vcb,
parentFCB,
&ChildElement,
&FCB);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pParentFCB = parentFCB;
*pFCB = NULL;
if (NextElement.Length == 0)
{
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
else
{
return(STATUS_OBJECT_PATH_NOT_FOUND);
}
}
else if (!NT_SUCCESS(Status))
{
CdfsReleaseFCB(Vcb, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return(Status);
}
}
CurrentElement = NextElement;
}
*pParentFCB = parentFCB;
*pFCB = FCB;
return STATUS_SUCCESS;
}
/* EOF */

View file

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

View file

@ -1,702 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/fsctl.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
* Pierre Schweitzer
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static __inline
int msf_to_lba (UCHAR m, UCHAR s, UCHAR f)
{
return (((m * 60) + s) * 75 + f) - 150;
}
static
VOID
CdfsGetPVDData(
PUCHAR Buffer,
PCDINFO CdInfo)
{
PPVD Pvd;
USHORT i;
PUCHAR 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[3] += Buffer[i+0];
Serial.Part[2] += Buffer[i+1];
Serial.Part[1] += Buffer[i+2];
Serial.Part[0] += Buffer[i+3];
}
CdInfo->SerialNumber = Serial.Value;
/* Extract the volume label */
pc = Pvd->VolumeId;
pw = CdInfo->VolumeLabel;
for (i = 0; i < (MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)) - 1; i++)
{
*pw++ = (WCHAR)*pc++;
}
*pw = 0;
/* Trim trailing spaces */
while (pw > CdInfo->VolumeLabel)
{
if (*--pw != ' ') break;
/* Remove the space */
*pw = '\0';
/* Decrease size */
i--;
}
CdInfo->VolumeLabelLength = i * sizeof(WCHAR);
CdInfo->VolumeSpaceSize = Pvd->VolumeSpaceSizeL;
CdInfo->RootStart = Pvd->RootDirRecord.ExtentLocationL;
CdInfo->RootSize = Pvd->RootDirRecord.DataLengthL;
DPRINT("VolumeSerial: %08lx\n", CdInfo->SerialNumber);
DPRINT("VolumeLabel: '%S'\n", CdInfo->VolumeLabel);
DPRINT("VolumeLabelLength: %lu\n", CdInfo->VolumeLabelLength);
DPRINT("VolumeSize: %lu\n", Pvd->VolumeSpaceSizeL);
DPRINT("RootStart: %lu\n", Pvd->RootDirRecord.ExtentLocationL);
DPRINT("RootSize: %lu\n", Pvd->RootDirRecord.DataLengthL);
DPRINT("PathTableSize: %lu\n", Pvd->PathTableSizeL);
DPRINT("PathTablePos: %lu\n", Pvd->LPathTablePos);
DPRINT("OptPathTablePos: %lu\n", Pvd->LOptPathTablePos);
#if 0
DbgPrint("******** PVD **********\n");
DbgPrint("VdType: %d\n", Pvd->VdType);
DbgPrint("StandardId: '%.*s'\n", 5, Pvd->StandardId);
DbgPrint("VdVersion: %d\n", Pvd->VdVersion);
DbgPrint("SystemId: '%.*s'\n", 32, Pvd->SystemId);
DbgPrint("VolumeId: '%.*s'\n", 32, Pvd->VolumeId);
DbgPrint("VolumeSpaceSizeL: %d (%x)\n", Pvd->VolumeSpaceSizeL, Pvd->VolumeSpaceSizeL);
DbgPrint("VolumeSpaceSizeM: %d (%x)\n", Pvd->VolumeSpaceSizeM, Pvd->VolumeSpaceSizeM);
DbgPrint("VolumeSetSize: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber);
DbgPrint("VolumeSequenceNumber: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber);
DbgPrint("LogicalBlockSize: %d (%x)\n", Pvd->LogicalBlockSize, Pvd->LogicalBlockSize);
DbgPrint("PathTableSizeL: %d (%x)\n", Pvd->PathTableSizeL, Pvd->PathTableSizeL);
DbgPrint("PathTableSizeM: %d (%x)\n", Pvd->PathTableSizeM, Pvd->PathTableSizeM);
DbgPrint("LPathTablePos: %d (%x)\n", Pvd->LPathTablePos, Pvd->LPathTablePos);
DbgPrint("LOptPathTablePos: %d (%x)\n", Pvd->LOptPathTablePos, Pvd->LOptPathTablePos);
DbgPrint("MPathTablePos: %d (%x)\n", Pvd->MPathTablePos, Pvd->MPathTablePos);
DbgPrint("MOptPathTablePos: %d (%x)\n", Pvd->MOptPathTablePos, Pvd->MOptPathTablePos);
DbgPrint("VolumeSetIdentifier: '%.*s'\n", 128, Pvd->VolumeSetIdentifier);
DbgPrint("PublisherIdentifier: '%.*s'\n", 128, Pvd->PublisherIdentifier);
DbgPrint("******** Root *********\n");
DbgPrint("RecordLength: %d\n", Pvd->RootDirRecord.RecordLength);
DbgPrint("ExtAttrRecordLength: %d\n", Pvd->RootDirRecord.ExtAttrRecordLength);
DbgPrint("ExtentLocationL: %d\n", Pvd->RootDirRecord.ExtentLocationL);
DbgPrint("DataLengthL: %d\n", Pvd->RootDirRecord.DataLengthL);
DbgPrint("Year: %d\n", Pvd->RootDirRecord.Year);
DbgPrint("Month: %d\n", Pvd->RootDirRecord.Month);
DbgPrint("Day: %d\n", Pvd->RootDirRecord.Day);
DbgPrint("Hour: %d\n", Pvd->RootDirRecord.Hour);
DbgPrint("Minute: %d\n", Pvd->RootDirRecord.Minute);
DbgPrint("Second: %d\n", Pvd->RootDirRecord.Second);
DbgPrint("TimeZone: %d\n", Pvd->RootDirRecord.TimeZone);
DbgPrint("FileFlags: %d\n", Pvd->RootDirRecord.FileFlags);
DbgPrint("FileUnitSize: %d\n", Pvd->RootDirRecord.FileUnitSize);
DbgPrint("InterleaveGapSize: %d\n", Pvd->RootDirRecord.InterleaveGapSize);
DbgPrint("VolumeSequenceNumber: %d\n", Pvd->RootDirRecord.VolumeSequenceNumber);
DbgPrint("FileIdLength: %d\n", Pvd->RootDirRecord.FileIdLength);
DbgPrint("FileId: '%.*s'\n", Pvd->RootDirRecord.FileId);
DbgPrint("***********************\n");
#endif
}
static
VOID
CdfsGetSVDData(
PUCHAR Buffer,
PCDINFO CdInfo)
{
PSVD Svd;
ULONG JolietLevel = 0;
Svd = (PSVD)Buffer;
DPRINT("EscapeSequences: '%.32s'\n", Svd->EscapeSequences);
if (strncmp((PCHAR)Svd->EscapeSequences, "%/@", 3) == 0)
{
DPRINT("Joliet extension found (UCS-2 Level 1)\n");
JolietLevel = 1;
}
else if (strncmp((PCHAR)Svd->EscapeSequences, "%/C", 3) == 0)
{
DPRINT("Joliet extension found (UCS-2 Level 2)\n");
JolietLevel = 2;
}
else if (strncmp((PCHAR)Svd->EscapeSequences, "%/E", 3) == 0)
{
DPRINT("Joliet extension found (UCS-2 Level 3)\n");
JolietLevel = 3;
}
CdInfo->JolietLevel = JolietLevel;
if (JolietLevel != 0)
{
CdInfo->RootStart = Svd->RootDirRecord.ExtentLocationL;
CdInfo->RootSize = Svd->RootDirRecord.DataLengthL;
DPRINT("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL);
DPRINT("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL);
}
}
static
NTSTATUS
CdfsGetVolumeData(
PDEVICE_OBJECT DeviceObject,
PCDINFO CdInfo)
{
PUCHAR Buffer;
NTSTATUS Status;
ULONG Sector;
PVD_HEADER VdHeader;
ULONG Size;
ULONG Offset;
CDROM_TOC Toc;
DPRINT("CdfsGetVolumeData\n");
Buffer = ExAllocatePoolWithTag(NonPagedPool, CDFS_BASIC_SECTOR, CDFS_TAG);
if (Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
Size = sizeof(Toc);
Status = CdfsDeviceIoControl(DeviceObject,
IOCTL_CDROM_READ_TOC,
NULL,
0,
&Toc,
&Size,
TRUE);
if (NT_SUCCESS(Status))
{
DPRINT("FirstTrack %u, LastTrack %u, TrackNumber %u\n",
Toc.FirstTrack, Toc.LastTrack, Toc.TrackData[0].TrackNumber);
Offset = Toc.TrackData[0].Address[1] * 60 * 75;
Offset += Toc.TrackData[0].Address[2] * 75;
Offset += Toc.TrackData[0].Address[3];
if (Offset >= 150)
{
/* Remove MSF numbering offset of first frame */
/* FIXME: should be done only for real cdroms? */
Offset -= 150;
}
}
else
{
DPRINT1("Allowing mount of CDFS volume on non-CD device\n");
Offset = 0;
}
CdInfo->VolumeOffset = Offset;
DPRINT("Offset of first track in last session %u\n", Offset);
CdInfo->JolietLevel = 0;
VdHeader = (PVD_HEADER)Buffer;
Buffer[0] = 0;
for (Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; Sector < 100 && Buffer[0] != 255; Sector++)
{
/* Read the Primary Volume Descriptor (PVD) */
Status = CdfsReadSectors(DeviceObject,
Sector + Offset,
1,
Buffer,
TRUE);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Buffer, CDFS_TAG);
return Status;
}
if (Sector == CDFS_PRIMARY_DESCRIPTOR_LOCATION)
{
DPRINT("CD-identifier: [%.5s]\n", Buffer + 1);
if (Buffer[0] != 1 || Buffer[1] != 'C' || Buffer[2] != 'D' ||
Buffer[3] != '0' || Buffer[4] != '0' || Buffer[5] != '1')
{
ExFreePoolWithTag(Buffer, CDFS_TAG);
return STATUS_UNRECOGNIZED_VOLUME;
}
}
switch (VdHeader->VdType)
{
case 0:
DPRINT("BootVolumeDescriptor found!\n");
break;
case 1:
DPRINT("PrimaryVolumeDescriptor found!\n");
CdfsGetPVDData(Buffer, CdInfo);
break;
case 2:
DPRINT("SupplementaryVolumeDescriptor found!\n");
CdfsGetSVDData(Buffer, CdInfo);
break;
case 3:
DPRINT("VolumePartitionDescriptor found!\n");
break;
case 255:
DPRINT("VolumeDescriptorSetTerminator found!\n");
break;
default:
DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType);
break;
}
}
ExFreePoolWithTag(Buffer, CDFS_TAG);
return STATUS_SUCCESS;
}
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;
PVPB Vpb;
NTSTATUS Status;
CDINFO CdInfo;
DEVICE_TYPE FilesystemDeviceType;
DPRINT("CdfsMountVolume() called\n");
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject)
{
FilesystemDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
}
else if (DeviceObject == CdfsGlobalData->HddFsDeviceObject)
{
FilesystemDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
}
else
{
Status = STATUS_INVALID_DEVICE_REQUEST;
goto ByeBye;
}
Stack = IoGetCurrentIrpStackLocation(Irp);
DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
Vpb = Stack->Parameters.MountVolume.Vpb;
Status = CdfsGetVolumeData(DeviceToMount, &CdInfo);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
Status = IoCreateDevice(CdfsGlobalData->DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FilesystemDeviceType,
DeviceToMount->Characteristics,
FALSE,
&NewDeviceObject);
if (!NT_SUCCESS(Status))
goto ByeBye;
NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExt,
sizeof(DEVICE_EXTENSION));
Vpb->SerialNumber = CdInfo.SerialNumber;
Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength;
RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength);
RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO));
NewDeviceObject->Vpb = DeviceToMount->Vpb;
DeviceExt->VolumeDevice = NewDeviceObject;
DeviceExt->StorageDevice = DeviceToMount;
DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject;
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* Close (and cleanup) might be called from IoCreateStreamFileObject
* but we use this resource from CdfsCleanup, therefore it should be
* initialized no later than this. */
ExInitializeResourceLite(&DeviceExt->DirResource);
DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
DeviceExt->StorageDevice);
Fcb = CdfsCreateFCB(NULL);
if (Fcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), CDFS_CCB_TAG);
if (Ccb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
RtlZeroMemory(Ccb,
sizeof(CCB));
DeviceExt->StreamFileObject->ReadAccess = TRUE;
DeviceExt->StreamFileObject->WriteAccess = FALSE;
DeviceExt->StreamFileObject->DeleteAccess = FALSE;
DeviceExt->StreamFileObject->FsContext = Fcb;
DeviceExt->StreamFileObject->FsContext2 = Ccb;
DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
DeviceExt->StreamFileObject->PrivateCacheMap = NULL;
DeviceExt->StreamFileObject->Vpb = DeviceToMount->Vpb;
Ccb->PtrFileObject = DeviceExt->StreamFileObject;
Fcb->FileObject = DeviceExt->StreamFileObject;
Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
Fcb->Flags = FCB_IS_VOLUME_STREAM;
Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
Fcb->Entry.ExtentLocationL = 0;
Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
_SEH2_TRY
{
CcInitializeCacheMap(DeviceExt->StreamFileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
TRUE,
&(CdfsGlobalData->CacheMgrCallbacks),
Fcb);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
goto ByeBye;
}
_SEH2_END;
ExInitializeResourceLite(&DeviceExt->VcbResource);
KeInitializeSpinLock(&DeviceExt->FcbListLock);
InitializeListHead(&DeviceExt->FcbListHead);
FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
InitializeListHead(&DeviceExt->NotifyList);
Status = STATUS_SUCCESS;
ByeBye:
if (!NT_SUCCESS(Status))
{
/* Cleanup */
if (DeviceExt && DeviceExt->StreamFileObject)
ObDereferenceObject(DeviceExt->StreamFileObject);
if (Fcb)
ExFreePoolWithTag(Fcb, CDFS_NONPAGED_FCB_TAG);
if (NewDeviceObject)
IoDeleteDevice(NewDeviceObject);
}
DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status);
return Status;
}
static
NTSTATUS
CdfsVerifyVolume(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
CDINFO CdInfo;
PLIST_ENTRY Entry;
PFCB Fcb;
PVPB VpbToVerify;
DPRINT("CdfsVerifyVolume() called\n");
DeviceExt = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation (Irp);
VpbToVerify = Stack->Parameters.VerifyVolume.Vpb;
FsRtlEnterFileSystem();
ExAcquireResourceExclusiveLite(&DeviceExt->VcbResource,
TRUE);
if (!(VpbToVerify->RealDevice->Flags & DO_VERIFY_VOLUME))
{
DPRINT1("Volume has been verified!\n");
ExReleaseResourceLite (&DeviceExt->VcbResource);
FsRtlExitFileSystem();
return STATUS_SUCCESS;
}
DPRINT1("Device object %p Device to verify %p\n", DeviceObject, VpbToVerify->RealDevice);
Status = CdfsGetVolumeData(VpbToVerify->RealDevice,
&CdInfo);
if (NT_SUCCESS(Status) &&
CdInfo.SerialNumber == VpbToVerify->SerialNumber &&
CdInfo.VolumeLabelLength == VpbToVerify->VolumeLabelLength &&
!wcsncmp(CdInfo.VolumeLabel, VpbToVerify->VolumeLabel, CdInfo.VolumeLabelLength))
{
DPRINT1("Same volume!\n");
/* FIXME: Flush and purge metadata */
Status = STATUS_SUCCESS;
}
else
{
DPRINT1("Different volume!\n");
/* FIXME: force volume dismount */
Entry = DeviceExt->FcbListHead.Flink;
while (Entry != &DeviceExt->FcbListHead)
{
Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry);
DPRINT1("OpenFile %wZ RefCount %ld\n", &Fcb->PathName, Fcb->RefCount);
Entry = Entry->Flink;
}
Status = STATUS_WRONG_VOLUME;
}
VpbToVerify->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
ExReleaseResourceLite(&DeviceExt->VcbResource);
FsRtlExitFileSystem();
return Status;
}
static
NTSTATUS
CdfsLockOrUnlockVolume(
IN PCDFS_IRP_CONTEXT IrpContext,
IN BOOLEAN LockVolume)
{
PFCB Fcb;
PVPB Vpb;
PFILE_OBJECT FileObject;
PDEVICE_EXTENSION DeviceExt;
FileObject = IrpContext->FileObject;
Fcb = FileObject->FsContext;
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Vpb = DeviceExt->StreamFileObject->Vpb;
/* Only allow locking with the volume open */
if (!BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME_STREAM))
{
return STATUS_ACCESS_DENIED;
}
/* Bail out if it's already in the demanded state */
if ((BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && LockVolume) ||
(!BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && !LockVolume))
{
return STATUS_ACCESS_DENIED;
}
/* Bail out if it's already in the demanded state */
if ((BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && LockVolume) ||
(!BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && !LockVolume))
{
return STATUS_ACCESS_DENIED;
}
/* Deny locking if we're not alone */
if (LockVolume && DeviceExt->OpenHandleCount != 1)
{
return STATUS_ACCESS_DENIED;
}
/* Finally, proceed */
if (LockVolume)
{
DeviceExt->Flags |= VCB_VOLUME_LOCKED;
Vpb->Flags |= VPB_LOCKED;
}
else
{
DeviceExt->Flags &= ~VCB_VOLUME_LOCKED;
Vpb->Flags &= ~VPB_LOCKED;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CdfsSetCompression(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
USHORT CompressionState;
UNREFERENCED_PARAMETER(DeviceObject);
Stack = IoGetCurrentIrpStackLocation(Irp);
if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CompressionState))
return STATUS_INVALID_DEVICE_REQUEST;
CompressionState = *(USHORT *)Irp->AssociatedIrp.SystemBuffer;
if (CompressionState != COMPRESSION_FORMAT_NONE)
return STATUS_INVALID_PARAMETER;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CdfsFileSystemControl(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
DPRINT("CdfsFileSystemControl() called\n");
ASSERT(IrpContext);
DeviceObject = IrpContext->DeviceObject;
Irp = IrpContext->Irp;
Stack = IrpContext->Stack;
Irp->IoStatus.Information = 0;
switch (IrpContext->MinorFunction)
{
case IRP_MN_KERNEL_CALL:
case IRP_MN_USER_FS_REQUEST:
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
{
case FSCTL_SET_COMPRESSION:
DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_SET_COMPRESSION\n");
Status = CdfsSetCompression(DeviceObject, Irp);
break;
case FSCTL_LOCK_VOLUME:
DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_LOCK_VOLUME\n");
Status = CdfsLockOrUnlockVolume(IrpContext, TRUE);
break;
case FSCTL_UNLOCK_VOLUME:
DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_UNLOCK_VOLUME\n");
Status = CdfsLockOrUnlockVolume(IrpContext, FALSE);
break;
default:
DPRINT1("CDFS: IRP_MN_USER_FS_REQUEST / Unknown IoControlCode 0x%x\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
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:
DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
Status = CdfsVerifyVolume(DeviceObject, Irp);
break;
default:
DPRINT1("CDFS FSC: MinorFunction %u\n", Stack->MinorFunction);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
return Status;
}
/* EOF */

View file

@ -1,380 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/misc.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Eric Kohl
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
/*
* FUNCTION: Used with IRP to set them to TopLevelIrp field
* ARGUMENTS:
* Irp = The IRP to set
* RETURNS: TRUE if top level was null, else FALSE
*/
BOOLEAN
CdfsIsIrpTopLevel(
PIRP Irp)
{
BOOLEAN ReturnCode = FALSE;
DPRINT("CdfsIsIrpTopLevel()\n");
if (IoGetTopLevelIrp() == NULL)
{
IoSetTopLevelIrp(Irp);
ReturnCode = TRUE;
}
return ReturnCode;
}
/*
* FUNCTION: Allocate and fill a CDFS_IRP_CONTEXT struct in order to use it for IRP
* ARGUMENTS:
* DeviceObject = Used to fill in struct
* Irp = The IRP that need IRP_CONTEXT struct
* RETURNS: NULL or PCDFS_IRP_CONTEXT
*/
PCDFS_IRP_CONTEXT
CdfsAllocateIrpContext(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PCDFS_IRP_CONTEXT IrpContext;
DPRINT("CdfsAllocateIrpContext()\n");
IrpContext = (PCDFS_IRP_CONTEXT)ExAllocateFromNPagedLookasideList(&CdfsGlobalData->IrpContextLookasideList);
if (IrpContext == NULL)
return NULL;
RtlZeroMemory(IrpContext, sizeof(CDFS_IRP_CONTEXT));
// IrpContext->Identifier.Type = NTFS_TYPE_IRP_CONTEST;
// IrpContext->Identifier.Size = sizeof(NTFS_IRP_CONTEXT);
IrpContext->Irp = Irp;
IrpContext->DeviceObject = DeviceObject;
IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
IrpContext->FileObject = IrpContext->Stack->FileObject;
IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
IrpContext->PriorityBoost = IO_NO_INCREMENT;
IrpContext->Flags = IRPCONTEXT_COMPLETE;
if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_SHUTDOWN ||
(IrpContext->MajorFunction != IRP_MJ_CLEANUP &&
IrpContext->MajorFunction != IRP_MJ_CLOSE &&
IoIsOperationSynchronous(Irp)))
{
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
}
return IrpContext;
}
VOID
CdfsSwapString(PWCHAR Out,
PUCHAR In,
ULONG Count)
{
PUCHAR t = (PUCHAR)Out;
ULONG i;
for (i = 0; i < Count; i += 2)
{
t[i] = In[i+1];
t[i+1] = In[i];
if (t[i+1] == 0 && t[i] == ';')
break;
}
if ((i>2)&&(t[i-2] == '.'))
{
t[i-2] = 0;
t[i-1] = 0;
}
t[i] = 0;
t[i+1] = 0;
}
VOID
CdfsDateTimeToSystemTime(PFCB Fcb,
PLARGE_INTEGER SystemTime)
{
TIME_FIELDS TimeFields;
LARGE_INTEGER LocalTime;
TimeFields.Milliseconds = 0;
TimeFields.Second = Fcb->Entry.Second;
TimeFields.Minute = Fcb->Entry.Minute;
TimeFields.Hour = Fcb->Entry.Hour;
TimeFields.Day = Fcb->Entry.Day;
TimeFields.Month = Fcb->Entry.Month;
TimeFields.Year = Fcb->Entry.Year + 1900;
RtlTimeFieldsToTime(&TimeFields,
&LocalTime);
ExLocalTimeToSystemTime(&LocalTime, SystemTime);
}
VOID
CdfsFileFlagsToAttributes(PFCB Fcb,
PULONG FileAttributes)
{
/* FIXME: Fix attributes */
*FileAttributes = // FILE_ATTRIBUTE_READONLY |
((Fcb->Entry.FileFlags & FILE_FLAG_HIDDEN) ? FILE_ATTRIBUTE_HIDDEN : 0) |
((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : 0) |
((Fcb->Entry.FileFlags & FILE_FLAG_SYSTEM) ? FILE_ATTRIBUTE_SYSTEM : 0) |
((Fcb->Entry.FileFlags & FILE_FLAG_READONLY) ? FILE_ATTRIBUTE_READONLY : 0);
}
BOOLEAN
CdfsIsNameLegalDOS8Dot3(IN UNICODE_STRING FileName
)
{
ULONG i;
STRING DbcsName;
CHAR DbcsNameBuffer[12];
/* 8dot3 filename is max 12 length */
if (FileName.Length / sizeof(WCHAR) > 12)
{
return FALSE;
}
ASSERT(FileName.Length >= sizeof(WCHAR));
for (i = 0; i < FileName.Length / sizeof(WCHAR) ; i++)
{
/* Don't allow spaces in FileName */
if (FileName.Buffer[i] == L' ')
return FALSE;
}
/* If FileName is finishing with a dot, remove it */
if (FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1] == '.')
{
FileName.Length -= sizeof(WCHAR);
}
/* Finally, convert the string to call the FsRtl function */
RtlInitEmptyAnsiString(&DbcsName, DbcsNameBuffer, sizeof(DbcsNameBuffer));
if (!NT_SUCCESS(RtlUnicodeStringToCountedOemString(&DbcsName,
&FileName,
FALSE)))
{
return FALSE;
}
return FsRtlIsFatDbcsLegal(DbcsName, FALSE, FALSE, FALSE);
}
BOOLEAN
CdfsIsRecordValid(IN PDEVICE_EXTENSION DeviceExt,
IN PDIR_RECORD Record)
{
if (Record->RecordLength < Record->FileIdLength + FIELD_OFFSET(DIR_RECORD, FileId))
{
DPRINT1("Found corrupted entry! %u - %u\n", Record->RecordLength, Record->FileIdLength + FIELD_OFFSET(DIR_RECORD, FileId));
return FALSE;
}
if (Record->FileIdLength == 0)
{
DPRINT1("Found corrupted entry (null size)!\n");
return FALSE;
}
if (DeviceExt->CdInfo.JolietLevel == 0)
{
if (Record->FileId[0] == ANSI_NULL && Record->FileIdLength != 1)
{
DPRINT1("Found corrupted entry!\n");
return FALSE;
}
}
else
{
if (Record->FileIdLength & 1 && Record->FileIdLength != 1)
{
DPRINT1("Found corrupted entry! %u\n", Record->FileIdLength);
return FALSE;
}
if (Record->FileIdLength == 1 && Record->FileId[0] != 0 && Record->FileId[0] != 1)
{
DPRINT1("Found corrupted entry! %c\n", Record->FileId[0]);
DPRINT1("%wc\n", ((PWSTR)Record->FileId)[0]);
return FALSE;
}
}
return TRUE;
}
VOID
CdfsShortNameCacheGet
(PFCB DirectoryFcb,
PLARGE_INTEGER StreamOffset,
PUNICODE_STRING LongName,
PUNICODE_STRING ShortName)
{
PLIST_ENTRY Entry;
PCDFS_SHORT_NAME ShortNameEntry;
GENERATE_NAME_CONTEXT Context = { 0 };
DPRINT("CdfsShortNameCacheGet(%I64d,%wZ)\n", StreamOffset->QuadPart, LongName);
/* Get the name list resource */
ExAcquireResourceExclusiveLite(&DirectoryFcb->NameListResource, TRUE);
/* Try to find the name in our cache */
for (Entry = DirectoryFcb->ShortNameList.Flink;
Entry != &DirectoryFcb->ShortNameList;
Entry = Entry->Flink)
{
ShortNameEntry = CONTAINING_RECORD(Entry, CDFS_SHORT_NAME, Entry);
if (ShortNameEntry->StreamOffset.QuadPart == StreamOffset->QuadPart)
{
/* Cache hit */
RtlCopyUnicodeString(ShortName, &ShortNameEntry->Name);
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
DPRINT("Yield short name %wZ from cache\n", ShortName);
return;
}
}
/* Cache miss */
if (!CdfsIsNameLegalDOS8Dot3(*LongName))
{
RtlGenerate8dot3Name(LongName, FALSE, &Context, ShortName);
}
else
{
/* copy short name */
RtlUpcaseUnicodeString
(ShortName,
LongName,
FALSE);
}
DPRINT("Initial Guess %wZ\n", ShortName);
/* Make it unique by scanning the cache and bumping */
/* Note that incrementing the ambiguous name is enough, since we add new
* entries at the tail. We'll scan over all collisions. */
/* XXX could perform better. */
for (Entry = DirectoryFcb->ShortNameList.Flink;
Entry != &DirectoryFcb->ShortNameList;
Entry = Entry->Flink)
{
ShortNameEntry = CONTAINING_RECORD(Entry, CDFS_SHORT_NAME, Entry);
if (RtlCompareUnicodeString
(ShortName,
&ShortNameEntry->Name,
TRUE) == 0) /* Match */
{
RtlGenerate8dot3Name(LongName, FALSE, &Context, ShortName);
DPRINT("Collide; try %wZ\n", ShortName);
}
}
/* We've scanned over all entries and now have a unique one. Cache it. */
ShortNameEntry = ExAllocatePoolWithTag(PagedPool,
sizeof(CDFS_SHORT_NAME),
CDFS_SHORT_NAME_TAG);
if (!ShortNameEntry)
{
/* We couldn't cache it, but we can return it. We run the risk of
* generating a non-unique name later. */
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
DPRINT1("Couldn't cache potentially clashing 8.3 name %wZ\n", ShortName);
return;
}
ShortNameEntry->StreamOffset = *StreamOffset;
RtlInitEmptyUnicodeString(&ShortNameEntry->Name,
ShortNameEntry->NameBuffer,
sizeof(ShortNameEntry->NameBuffer));
RtlCopyUnicodeString(&ShortNameEntry->Name, ShortName);
InsertTailList(&DirectoryFcb->ShortNameList, &ShortNameEntry->Entry);
ExReleaseResourceLite(&DirectoryFcb->NameListResource);
DPRINT("Returning short name %wZ for long name %wZ\n", ShortName, LongName);
}
VOID
CdfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
PDIR_RECORD Record,
PWSTR Name)
/*
* FUNCTION: Retrieves the file name from a directory record.
*/
{
if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
{
wcscpy(Name, L".");
}
else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
{
wcscpy(Name, L"..");
}
else
{
if (DeviceExt->CdInfo.JolietLevel == 0)
{
ULONG i;
for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
Name[i] = (WCHAR)Record->FileId[i];
Name[i] = 0;
}
else
{
CdfsSwapString(Name,
Record->FileId,
Record->FileIdLength);
}
}
DPRINT("Name '%S'\n", Name);
}
/* EOF */

View file

@ -1,251 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/rw.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
/* FUNCTIONS ****************************************************************/
static NTSTATUS
CdfsReadFile(PCDFS_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject,
PUCHAR Buffer,
ULONG Length,
ULONG ReadOffset,
ULONG IrpFlags,
PULONG LengthRead)
/*
* FUNCTION: Reads data from a file
*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION DeviceExt;
PFCB Fcb;
ULONG ToRead = Length;
DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length);
*LengthRead = 0;
if (Length == 0)
return(STATUS_SUCCESS);
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Fcb = (PFCB)FileObject->FsContext;
if (ReadOffset >= Fcb->Entry.DataLengthL)
return(STATUS_END_OF_FILE);
if (ReadOffset + Length > Fcb->Entry.DataLengthL)
ToRead = Fcb->Entry.DataLengthL - ReadOffset;
if (!(IrpFlags & IRP_PAGING_IO) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
{
return STATUS_FILE_LOCK_CONFLICT;
}
}
DPRINT("Reading %u bytes at %u\n", Length, ReadOffset);
if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
{
LARGE_INTEGER FileOffset;
IO_STATUS_BLOCK IoStatus;
CC_FILE_SIZES FileSizes;
DPRINT("Using cache\n");
if (FileObject->PrivateCacheMap == NULL)
{
FileSizes.AllocationSize = Fcb->RFCB.AllocationSize;
FileSizes.FileSize = Fcb->RFCB.FileSize;
FileSizes.ValidDataLength = Fcb->RFCB.ValidDataLength;
DPRINT("Attach FCB to File: Size %08x%08x\n",
Fcb->RFCB.ValidDataLength.HighPart,
Fcb->RFCB.ValidDataLength.LowPart);
_SEH2_TRY
{
CcInitializeCacheMap(FileObject,
&FileSizes,
FALSE,
&(CdfsGlobalData->CacheMgrCallbacks),
Fcb);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
return _SEH2_GetExceptionCode();
}
_SEH2_END;
}
FileOffset.QuadPart = (LONGLONG)ReadOffset;
_SEH2_TRY
{
CcCopyRead(FileObject,
&FileOffset,
ToRead,
TRUE,
Buffer,
&IoStatus);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
IoStatus.Information = 0;
IoStatus.Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
*LengthRead = IoStatus.Information;
Status = IoStatus.Status;
}
else
{
ULONG ActualReadOffset = ROUND_DOWN(ReadOffset, BLOCKSIZE);
ULONG nBlocks = (ROUND_UP(ReadOffset + ToRead, BLOCKSIZE) - ActualReadOffset) / BLOCKSIZE;
PUCHAR PageBuf;
BOOLEAN bFreeBuffer = FALSE;
if ((ReadOffset % BLOCKSIZE) != 0 || (ToRead % BLOCKSIZE) != 0)
{
PageBuf = ExAllocatePoolWithTag(NonPagedPool,
nBlocks * BLOCKSIZE,
CDFS_TAG);
if (!PageBuf)
{
return STATUS_NO_MEMORY;
}
bFreeBuffer = TRUE;
}
else
{
PageBuf = Buffer;
}
Status = CdfsReadSectors(DeviceExt->StorageDevice,
Fcb->Entry.ExtentLocationL + (ActualReadOffset / BLOCKSIZE),
nBlocks,
(PVOID)PageBuf,
FALSE);
if(NT_SUCCESS(Status))
{
*LengthRead = ToRead;
if(bFreeBuffer)
{
/* Copy what we've got */
RtlCopyMemory(Buffer, PageBuf + (ReadOffset - ActualReadOffset), ToRead);
}
/* Zero out the rest */
if(ToRead != Length)
RtlZeroMemory(Buffer + ToRead, Length - ToRead);
}
if(bFreeBuffer)
ExFreePoolWithTag(PageBuf, CDFS_TAG);
}
return Status;
}
NTSTATUS NTAPI
CdfsRead(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
PVOID Buffer = NULL;
ULONG ReadLength;
LARGE_INTEGER ReadOffset;
ULONG ReturnedReadLength = 0;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CdfsRead(%p)\n", IrpContext);
ASSERT(IrpContext);
Irp = IrpContext->Irp;
Stack = IrpContext->Stack;
FileObject = Stack->FileObject;
ReadLength = Stack->Parameters.Read.Length;
ReadOffset = Stack->Parameters.Read.ByteOffset;
if (ReadLength) Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Status = CdfsReadFile(IrpContext,
FileObject,
Buffer,
ReadLength,
ReadOffset.u.LowPart,
Irp->Flags,
&ReturnedReadLength);
if (NT_SUCCESS(Status))
{
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
FileObject->CurrentByteOffset.QuadPart =
ReadOffset.QuadPart + ReturnedReadLength;
}
Irp->IoStatus.Information = ReturnedReadLength;
}
else
{
Irp->IoStatus.Information = 0;
}
return(Status);
}
NTSTATUS NTAPI
CdfsWrite(
PCDFS_IRP_CONTEXT IrpContext)
{
DPRINT("CdfsWrite(%p)\n", IrpContext);
ASSERT(IrpContext);
IrpContext->Irp->IoStatus.Information = 0;
return(STATUS_NOT_SUPPORTED);
}
/* EOF */

View file

@ -1,297 +0,0 @@
/*
* ReactOS kernel
* Copyright (C) 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/filesystems/cdfs/volume.c
* PURPOSE: CDROM (ISO 9660) filesystem driver
* PROGRAMMER: Art Yerkes
* Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "cdfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static
NTSTATUS
CdfsGetFsVolumeInformation(
PDEVICE_OBJECT DeviceObject,
PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
PULONG BufferLength)
{
DPRINT("CdfsGetFsVolumeInformation() called\n");
DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
DPRINT("BufferLength %lu\n", *BufferLength);
DPRINT("Vpb %p\n", DeviceObject->Vpb);
DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength));
DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength);
DPRINT("Label %.*S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel);
if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
return STATUS_INFO_LENGTH_MISMATCH;
if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
return STATUS_BUFFER_OVERFLOW;
/* valid entries */
FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
memcpy(FsVolumeInfo->VolumeLabel,
DeviceObject->Vpb->VolumeLabel,
DeviceObject->Vpb->VolumeLabelLength);
/* dummy entries */
FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
FsVolumeInfo->SupportsObjects = FALSE;
DPRINT("Finished FsdGetFsVolumeInformation()\n");
*BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
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));
UNREFERENCED_PARAMETER(DeviceExt);
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 | FILE_READ_ONLY_VOLUME;
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 = STATUS_SUCCESS;
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 = BLOCKSIZE;
DPRINT("Finished FsdGetFsSizeInformation()\n");
if (NT_SUCCESS(Status))
*BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
return Status;
}
static
NTSTATUS
CdfsGetFsDeviceInformation(
PDEVICE_OBJECT DeviceObject,
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;
if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM;
else
FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
DPRINT("FsdGetFsDeviceInformation() finished.\n");
*BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
DPRINT("BufferLength %lu\n", *BufferLength);
return STATUS_SUCCESS;
}
static
NTSTATUS
CdfsGetFsFullSizeInformation(
PDEVICE_OBJECT DeviceObject,
PFILE_FS_FULL_SIZE_INFORMATION FsSizeInfo,
PULONG BufferLength)
{
PDEVICE_EXTENSION DeviceExt;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("CdfsGetFsFullSizeInformation()\n");
DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
if (*BufferLength < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
return STATUS_BUFFER_OVERFLOW;
DeviceExt = DeviceObject->DeviceExtension;
FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize;
FsSizeInfo->CallerAvailableAllocationUnits.QuadPart = 0;
FsSizeInfo->ActualAvailableAllocationUnits.QuadPart = 0;
FsSizeInfo->SectorsPerAllocationUnit = 1;
FsSizeInfo->BytesPerSector = BLOCKSIZE;
DPRINT("Finished CdfsGetFsFullSizeInformation()\n");
if (NT_SUCCESS(Status))
*BufferLength -= sizeof(FILE_FS_FULL_SIZE_INFORMATION);
return Status;
}
NTSTATUS
NTAPI
CdfsQueryVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
FS_INFORMATION_CLASS FsInformationClass;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
PVOID SystemBuffer;
ULONG BufferLength;
DPRINT("CdfsQueryVolumeInformation() called\n");
ASSERT(IrpContext);
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Stack = IrpContext->Stack;
FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
BufferLength = Stack->Parameters.QueryVolume.Length;
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
DPRINT("FsInformationClass %d\n", FsInformationClass);
DPRINT("SystemBuffer %p\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(DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileFsFullSizeInformation:
Status = CdfsGetFsFullSizeInformation(DeviceObject,
SystemBuffer,
&BufferLength);
break;
default:
Status = STATUS_NOT_SUPPORTED;
}
if (NT_SUCCESS(Status))
Irp->IoStatus.Information =
Stack->Parameters.QueryVolume.Length - BufferLength;
else
Irp->IoStatus.Information = 0;
return Status;
}
NTSTATUS
NTAPI
CdfsSetVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext)
{
DPRINT("CdfsSetVolumeInformation() called\n");
ASSERT(IrpContext);
IrpContext->Irp->IoStatus.Information = 0;
return STATUS_NOT_SUPPORTED;
}
/* EOF */