[0.4.9][CDFS_NEW] -> [CDFS]

port back:
0.4.10-dev-615-g 45fd48bd0f [CDFS_NEW] -> [CDFS] No old driver, thus no new driver
0.4.10-dev-614-g 5795254933 [CDFS] Delete the old CDFS driver.

The new MS PL licensed one worked for several years fine for us now
even in the older releases.
So no need to keep our old unfinished one any longer within
the release-branches. They are no mausoleum.
This does *not* change, which driver is actually in use.
We do continue to use 1:1 the state of current releases/0.4.10
This commit is contained in:
Joachim Henze 2023-03-23 22:09:06 +01:00
parent c13c6e1713
commit 19f220bf51
60 changed files with 5062 additions and 10626 deletions

View file

@ -9,7 +9,7 @@
/* INCLUDES ******************************************************************/
#include <bl.h>
#include <cdfs_new/cd.h>
#include <cdfs/cd.h>
typedef struct _RAW_ET_VD
{
UCHAR BootIndicator;

View file

@ -1,6 +1,6 @@
add_subdirectory(btrfs)
add_subdirectory(cdfs_new)
add_subdirectory(cdfs)
add_subdirectory(ext2)
add_subdirectory(fastfat)
add_subdirectory(ffs)

View file

@ -2,27 +2,39 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
list(APPEND SOURCE
cdfs.c
allocsup.c
cachesup.c
cddata.c
cdinit.c
cdprocssrc.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
deviosup.c
dirctrl.c
dirsup.c
fileinfo.c
filobsup.c
fsctrl.c
fspdisp.c
lockctrl.c
namesup.c
pathsup.c
pnp.c
prefxsup.c
read.c
resrcsup.c
shutdown.c
strucsup.c
verfysup.c
volinfo.c
cdfs.h)
workque.c
write.c)
add_library(cdfs SHARED ${SOURCE} cdfs.rc)
set_module_type(cdfs kernelmodedriver)
target_link_libraries(cdfs ${PSEH_LIB})
target_link_libraries(cdfs ${PSEH_LIB} memcmp)
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

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 +1,14 @@
#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>
//
// Copyright (C) Microsoft. All rights reserved.
//
#include <verrsrc.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
#define VER_FILEDESCRIPTION_STR "CD-ROM File System Driver"
#define VER_INTERNALNAME_STR "cdfs.sys"
#include "common.ver"

View file

@ -1,129 +1,366 @@
/*
* 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 *****************************************************************/
Copyright (c) 1989-2000 Microsoft Corporation
#include "cdfs.h"
Module Name:
#define NDEBUG
#include <debug.h>
Cleanup.c
/* FUNCTIONS ****************************************************************/
Abstract:
This module implements the File Cleanup routine for Cdfs called by the
dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_CLEANUP)
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonCleanup (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
This is the common routine for cleanup of a file/directory called by both
the fsd and fsp threads.
Cleanup is invoked whenever the last handle to a file object is closed.
This is different than the Close operation which is invoked when the last
reference to a file object is deleted.
The function of cleanup is to essentially "cleanup" the file/directory
after a user is done with it. The Fcb/Dcb remains around (because MM
still has the file object referenced) but is now available for another
user to open (i.e., as far as the user is concerned the is now closed).
See close for a more complete description of what close does.
We do no synchronization in this routine until we get to the point
where we modify the counts, share access and volume lock field.
We need to update the Fcb and Vcb to show that a user handle has been closed.
The following structures and fields are affected.
Vcb:
VolumeLockFileObject - Did the user lock the volume with this file object.
VcbState - Check if we are unlocking the volume here.
VcbCleanup - Count of outstanding handles on the volume.
DirNotifyQueue - If this file object has pending DirNotify Irps.
Fcb:
ShareAccess - If this is a user handle.
FcbCleanup - Count of outstanding handles on this Fcb.
Oplock - Any outstanding oplocks on this file object.
FileLock - Any outstanding filelocks on this file object.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation.
--*/
static NTSTATUS
CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Cleans up after a file has been closed.
*/
{
PDEVICE_EXTENSION DeviceExt;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN SendUnlockNotification = FALSE;
BOOLEAN AttemptTeardown = FALSE;
BOOLEAN VcbAcquired = FALSE;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
DPRINT("CdfsCleanupFile(IrpContext %p, FileObject %p)\n",
IrpContext,
FileObject);
KIRQL SavedIrql;
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
Fcb = FileObject->FsContext;
if (!Fcb)
{
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_IRP( Irp );
//
// If we were called with our file system device object instead of a
// volume device object, just complete this request with STATUS_SUCCESS.
//
if (IrpContext->Vcb == NULL) {
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
DeviceExt->OpenHandleCount--;
//
// Get the file object out of the Irp and decode the type of open.
//
/* Notify about the cleanup */
FsRtlNotifyCleanup(DeviceExt->NotifySync,
&(DeviceExt->NotifyList),
FileObject->FsContext2);
FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
if (!CdfsFCBIsDirectory(Fcb) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
FsRtlFastUnlockAll(&Fcb->FileLock,
FileObject,
IoGetRequestorProcess(IrpContext->Irp),
NULL);
TypeOfOpen = CdDecodeFileObject( IrpContext,
FileObject,
&Fcb,
&Ccb );
//
// No work here for either an UnopenedFile object or a StreamFileObject.
//
if (TypeOfOpen <= StreamFileOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
/* Uninitialize file cache if initialized for this file object. */
if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap)
{
CcUninitializeCacheMap (FileObject, NULL, NULL);
//
// Keep a local pointer to the Vcb.
//
Vcb = Fcb->Vcb;
//
// Synchronise with reads while we set the cleanup complete
// flag on this fileobject. Once this flag is set, any further
// reads will be rejected (CdVerifyFcbOperation)
//
CdAcquireFileExclusive( IrpContext, Fcb);
//
// Set the flag in the FileObject to indicate that cleanup is complete.
//
SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE );
CdReleaseFile( IrpContext, Fcb);
if (TypeOfOpen == UserVolumeOpen) {
//
// For a force dismount, physically disconnect this Vcb from the device so
// a new mount can occur. Vcb deletion cannot happen at this time since
// there is a reference on it associated with this very request, but we'll
// call check for dismount again later after we process this close.
//
if (FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE )) {
CdAcquireCdData( IrpContext );
CdCheckForDismount( IrpContext, Vcb, TRUE );
CdReleaseCdData( IrpContext );
//
// If this handle actually wrote something, flush the device buffers,
// and then set the verify bit now just to be safe (in case there is no
// dismount).
//
} else if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) {
CdHijackIrpAndFlushDevice( IrpContext, Irp, Vcb->TargetDeviceObject );
CdMarkDevForVerifyIfVcbMounted( Vcb );
}
}
/* Inform cleanup is complete */
FileObject->Flags |= FO_CLEANUP_COMPLETE;
//
// Acquire the current file.
//
CdAcquireFcbExclusive( IrpContext, Fcb, FALSE );
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_TRY {
//
// Case on the type of open that we are trying to cleanup.
//
switch (TypeOfOpen) {
case UserDirectoryOpen:
//
// Check if we need to complete any dir notify Irps on this file object.
//
FsRtlNotifyCleanup( Vcb->NotifySync,
&Vcb->DirNotifyList,
Ccb );
break;
case UserFileOpen:
//
// Coordinate the cleanup operation with the oplock state.
// Oplock cleanup operations can always cleanup immediately so no
// need to check for STATUS_PENDING.
//
FsRtlCheckOplock( CdGetFcbOplock(Fcb),
Irp,
IrpContext,
NULL,
NULL );
//
// Unlock all outstanding file locks.
//
if (Fcb->FileLock != NULL) {
FsRtlFastUnlockAll( Fcb->FileLock,
FileObject,
IoGetRequestorProcess( Irp ),
NULL );
}
//
// Cleanup the cache map.
//
CcUninitializeCacheMap( FileObject, NULL, NULL );
//
// Check the fast io state.
//
CdLockFcb( IrpContext, Fcb );
Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
CdUnlockFcb( IrpContext, Fcb );
break;
case UserVolumeOpen:
break;
default :
#ifdef _MSC_VER
#pragma prefast( suppress:__WARNING_USE_OTHER_FUNCTION, "argument bogus" )
#endif
CdBugCheck( TypeOfOpen, 0, 0 );
}
//
// Now lock the Vcb in order to modify the fields in the in-memory
// structures.
//
CdLockVcb( IrpContext, Vcb );
//
// Decrement the cleanup counts in the Vcb and Fcb.
//
CdDecrementCleanupCounts( IrpContext, Fcb );
//
// If the cleanup count hit zero and the volume is not mounted, we
// will want to try to spark teardown.
//
AttemptTeardown = (Vcb->VcbCleanup == 0 && Vcb->VcbCondition == VcbNotMounted);
//
// If this file object has locked the volume then perform the unlock operation.
// We do this regardless of explicit or implicit (no share DASD open) lock.
//
if (FileObject == Vcb->VolumeLockFileObject) {
NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_LOCKED));
IoAcquireVpbSpinLock( &SavedIrql );
ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED);
ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
Vcb->VolumeLockFileObject = NULL;
SendUnlockNotification = TRUE;
IoReleaseVpbSpinLock( SavedIrql );
}
CdUnlockVcb( IrpContext, Vcb );
//
// We must clean up the share access at this time, since we may not
// get a Close call for awhile if the file was mapped through this
// File Object.
//
IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
} _SEH2_FINALLY {
CdReleaseFcb( IrpContext, Fcb );
if (SendUnlockNotification) {
FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK );
}
} _SEH2_END;
//
// If appropriate, try to spark teardown by purging the volume. Should
// this very fileobject we were cleaning up be the last reason for the
// volume to remain, teardown will commence on completion of this Irp.
//
if (AttemptTeardown) {
//
// Preacquire CdData here, since the purges will generate closes which
// may acquire CdData if there is a possibility of tearing the volume
// down.
//
CdAcquireCdData( IrpContext);
_SEH2_TRY {
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
VcbAcquired = TRUE;
CdPurgeVolume( IrpContext, Vcb, FALSE );
} _SEH2_FINALLY {
if (VcbAcquired) { CdReleaseVcb( IrpContext, Vcb ); }
CdReleaseCdData( IrpContext);
} _SEH2_END;
}
//
// If this is a normal termination then complete the request
//
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
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 */

File diff suppressed because it is too large Load diff

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 */

File diff suppressed because it is too large Load diff

View file

@ -1,69 +1,199 @@
/*
* 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 *****************************************************************/
Copyright (c) 1989-2000 Microsoft Corporation
#include "cdfs.h"
Module Name:
#define NDEBUG
#include <debug.h>
DevCtrl.c
/* FUNCTIONS ****************************************************************/
Abstract:
This module implements the File System Device Control routines for Cdfs
called by the dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_DEVCTRL)
//
// Local support routines
//
// Tell prefast this is a completion routine
IO_COMPLETION_ROUTINE CdDevCtrlCompletionRoutine;
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdDevCtrlCompletionRoutine (
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonDevControl)
#endif
NTSTATUS
CdCommonDevControl (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
NTSTATUS NTAPI
CdfsDeviceControl(
PCDFS_IRP_CONTEXT IrpContext)
{
PIRP Irp;
NTSTATUS Status;
PVCB Vcb = NULL;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION Stack;
DPRINT("CdfsDeviceControl()\n");
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
ASSERT(IrpContext);
PIO_STACK_LOCATION IrpSp;
PIO_STACK_LOCATION NextIrpSp;
Irp = IrpContext->Irp;
Stack = IrpContext->Stack;
FileObject = Stack->FileObject;
Irp->IoStatus.Information = 0;
PAGED_CODE();
/* FIXME: HACK, it means that CD has changed */
if (!FileObject)
{
DPRINT1("FIXME: CdfsDeviceControl called without FileObject!\n");
return STATUS_INVALID_DEVICE_REQUEST;
}
//
// Extract and decode the file object.
//
/* Only support such operations on volume */
if (!(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
{
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TypeOfOpen = CdDecodeFileObject( IrpContext,
IrpSp->FileObject,
&Fcb,
&Ccb );
//
// The only type of opens we accept are user volume opens.
//
if (TypeOfOpen != UserVolumeOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
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;
if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) {
/* Lower driver will complete - we don't have to */
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
//
// Verify the Vcb in this case to detect if the volume has changed.
//
Status = IoCallDriver(Vcb->StorageDevice, Irp);
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Handle the case of the disk type ourselves.
//
} else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {
//
// Verify the Vcb in this case to detect if the volume has changed.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Check the size of the output buffer.
//
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {
CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
return STATUS_BUFFER_TOO_SMALL;
}
//
// Copy the data from the Vcb.
//
((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags;
Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Get the next stack location, and copy over the stack parameter
// information.
//
NextIrpSp = IoGetNextIrpStackLocation( Irp );
*NextIrpSp = *IrpSp;
//
// Set up the completion routine
//
IoSetCompletionRoutine( Irp,
CdDevCtrlCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
//
// Send the request.
//
Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
//
// Cleanup our Irp Context. The driver has completed the Irp.
//
CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
return Status;
}
//
// Local support routine
//
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdDevCtrlCompletionRoutine (
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
)
{
//
// Add the hack-o-ramma to fix formats.
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Contxt );
}

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

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 +1,605 @@
/*
* 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 *****************************************************************/
Copyright (c) 1989-2000 Microsoft Corporation
#include "cdfs.h"
Module Name:
#define NDEBUG
#include <debug.h>
VolInfo.c
/* FUNCTIONS ****************************************************************/
Abstract:
static
This module implements the volume information routines for Cdfs called by
the dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO)
//
// Local support routines
//
_Requires_lock_held_(_Global_critical_region_)
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;
}
CdQueryFsVolumeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
NTAPI
CdfsQueryVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext)
CdQueryFsSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryFsDeviceInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryFsAttributeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
_Inout_ PULONG Length
);
#ifdef __REACTOS__
#define PFILE_FS_SECTOR_SIZE_INFORMATION PVOID
#endif
NTSTATUS
CdQueryFsSectorSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonQueryVolInfo)
#pragma alloc_text(PAGE, CdQueryFsAttributeInfo)
#pragma alloc_text(PAGE, CdQueryFsDeviceInfo)
#pragma alloc_text(PAGE, CdQueryFsSizeInfo)
#pragma alloc_text(PAGE, CdQueryFsVolumeInfo)
#pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo)
#endif
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonQueryVolInfo (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
This is the common routine for querying volume information called by both
the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
FS_INFORMATION_CLASS FsInformationClass;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
PVOID SystemBuffer;
ULONG BufferLength;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
DPRINT("CdfsQueryVolumeInformation() called\n");
ULONG Length;
ASSERT(IrpContext);
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
Stack = IrpContext->Stack;
FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
BufferLength = Stack->Parameters.QueryVolume.Length;
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
PAGED_CODE();
DPRINT("FsInformationClass %d\n", FsInformationClass);
DPRINT("SystemBuffer %p\n", SystemBuffer);
//
// Reference our input parameters to make things easier
//
switch (FsInformationClass)
{
case FileFsVolumeInformation:
Status = CdfsGetFsVolumeInformation(DeviceObject,
SystemBuffer,
&BufferLength);
break;
Length = IrpSp->Parameters.QueryVolume.Length;
case FileFsAttributeInformation:
Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension,
SystemBuffer,
&BufferLength);
break;
//
// Decode the file object and fail if this an unopened file object.
//
TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
if (TypeOfOpen == UnopenedFileObject) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Acquire the Vcb for this volume.
//
CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_TRY {
//
// Verify the Vcb.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Based on the information class we'll do different actions. Each
// of the procedures that we're calling fills up the output buffer
// if possible and returns true if it successfully filled the buffer
// and false if it couldn't wait for any I/O to complete.
//
switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
case FileFsSizeInformation:
Status = CdfsGetFsSizeInformation(DeviceObject,
SystemBuffer,
&BufferLength);
Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsVolumeInformation:
Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsDeviceInformation:
Status = CdfsGetFsDeviceInformation(DeviceObject,
SystemBuffer,
&BufferLength);
Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsFullSizeInformation:
Status = CdfsGetFsFullSizeInformation(DeviceObject,
SystemBuffer,
&BufferLength);
case FileFsAttributeInformation:
Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
default:
Status = STATUS_NOT_SUPPORTED;
}
#if (NTDDI_VERSION >= NTDDI_WIN8)
case FileFsSectorSizeInformation:
if (NT_SUCCESS(Status))
Irp->IoStatus.Information =
Stack->Parameters.QueryVolume.Length - BufferLength;
else
Irp->IoStatus.Information = 0;
Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
#endif
/* ReactOS Change: GCC "enumeration value not handled in switch" */
default: break;
}
//
// Set the information field to the number of bytes actually filled in
//
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
} _SEH2_FINALLY {
//
// Release the Vcb.
//
CdReleaseVcb( IrpContext, Fcb->Vcb );
} _SEH2_END;
//
// Complete the request if we didn't raise.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
NTAPI
CdfsSetVolumeInformation(
PCDFS_IRP_CONTEXT IrpContext)
CdQueryFsVolumeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume info call
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
DPRINT("CdfsSetVolumeInformation() called\n");
ULONG BytesToCopy;
ASSERT(IrpContext);
NTSTATUS Status = STATUS_SUCCESS;
IrpContext->Irp->IoStatus.Information = 0;
PAGED_CODE();
return STATUS_NOT_SUPPORTED;
UNREFERENCED_PARAMETER( IrpContext );
//
// Fill in the data from the Vcb.
//
Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
Buffer->SupportsObjects = FALSE;
*Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
//
// Check if the buffer we're given is long enough
//
if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
BytesToCopy = Vcb->Vpb->VolumeLabelLength;
} else {
BytesToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
//
// Copy over what we can of the volume label, and adjust *Length
//
Buffer->VolumeLabelLength = BytesToCopy;
if (BytesToCopy) {
RtlCopyMemory( &Buffer->VolumeLabel[0],
&Vcb->Vpb->VolumeLabel[0],
BytesToCopy );
}
*Length -= BytesToCopy;
//
// Set our status and return to our caller
//
return Status;
}
/* EOF */
//
// Local support routine
//
NTSTATUS
CdQueryFsSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume size call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Fill in the output buffer.
//
Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
Buffer->AvailableAllocationUnits.QuadPart = 0;
Buffer->SectorsPerAllocationUnit = 1;
Buffer->BytesPerSector = SECTOR_SIZE;
//
// Adjust the length variable
//
*Length -= sizeof( FILE_FS_SIZE_INFORMATION );
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdQueryFsDeviceInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume device call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Update the output buffer.
//
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
Buffer->DeviceType = FILE_DEVICE_CD_ROM;
//
// Adjust the length variable
//
*Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdQueryFsAttributeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume attribute call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
ULONG BytesToCopy;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
UNREFERENCED_PARAMETER( Vcb );
//
// Fill out the fixed portion of the buffer.
//
Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
FILE_READ_ONLY_VOLUME |
FILE_SUPPORTS_OPEN_BY_FILE_ID;
if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
Buffer->MaximumComponentNameLength = 110;
} else {
Buffer->MaximumComponentNameLength = 221;
}
*Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
//
// Make sure we can copy full unicode characters.
//
ClearFlag( *Length, 1 );
//
// Determine how much of the file system name will fit.
//
if (*Length >= 8) {
BytesToCopy = 8;
} else {
BytesToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
*Length -= BytesToCopy;
//
// Do the file system name.
//
Buffer->FileSystemNameLength = BytesToCopy;
RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
//
// And return to our caller
//
return Status;
}
#if (NTDDI_VERSION >= NTDDI_WIN8)
NTSTATUS
CdQueryFsSectorSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query sector size information call
This operation will work on any handle and requires no privilege.
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return receives the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
NTSTATUS Status;
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Sufficient buffer size is guaranteed by the I/O manager or the
// originating kernel mode driver.
//
ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
_Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
//
// Retrieve the sector size information
//
Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
Buffer );
//
// Adjust the length variable
//
if (NT_SUCCESS( Status )) {
*Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
}
return Status;
}
#endif

View file

@ -1,40 +0,0 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
list(APPEND SOURCE
allocsup.c
cachesup.c
cddata.c
cdinit.c
cdprocssrc.c
cleanup.c
close.c
create.c
devctrl.c
deviosup.c
dirctrl.c
dirsup.c
fileinfo.c
filobsup.c
fsctrl.c
fspdisp.c
lockctrl.c
namesup.c
pathsup.c
pnp.c
prefxsup.c
read.c
resrcsup.c
shutdown.c
strucsup.c
verfysup.c
volinfo.c
workque.c
write.c)
add_library(cdfs SHARED ${SOURCE} cdfs.rc)
set_module_type(cdfs kernelmodedriver)
target_link_libraries(cdfs ${PSEH_LIB} memcmp)
add_importlibs(cdfs ntoskrnl hal)
add_cd_file(TARGET cdfs DESTINATION reactos/system32/drivers NO_CAB FOR all)
add_registry_inf(cdfs_reg.inf)

View file

@ -1,14 +0,0 @@
//
// Copyright (C) Microsoft. All rights reserved.
//
#include <verrsrc.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
#define VER_FILEDESCRIPTION_STR "CD-ROM File System Driver"
#define VER_INTERNALNAME_STR "cdfs.sys"
#include "common.ver"

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,366 +0,0 @@
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
Cleanup.c
Abstract:
This module implements the File Cleanup routine for Cdfs called by the
dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_CLEANUP)
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonCleanup (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
This is the common routine for cleanup of a file/directory called by both
the fsd and fsp threads.
Cleanup is invoked whenever the last handle to a file object is closed.
This is different than the Close operation which is invoked when the last
reference to a file object is deleted.
The function of cleanup is to essentially "cleanup" the file/directory
after a user is done with it. The Fcb/Dcb remains around (because MM
still has the file object referenced) but is now available for another
user to open (i.e., as far as the user is concerned the is now closed).
See close for a more complete description of what close does.
We do no synchronization in this routine until we get to the point
where we modify the counts, share access and volume lock field.
We need to update the Fcb and Vcb to show that a user handle has been closed.
The following structures and fields are affected.
Vcb:
VolumeLockFileObject - Did the user lock the volume with this file object.
VcbState - Check if we are unlocking the volume here.
VcbCleanup - Count of outstanding handles on the volume.
DirNotifyQueue - If this file object has pending DirNotify Irps.
Fcb:
ShareAccess - If this is a user handle.
FcbCleanup - Count of outstanding handles on this Fcb.
Oplock - Any outstanding oplocks on this file object.
FileLock - Any outstanding filelocks on this file object.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation.
--*/
{
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN SendUnlockNotification = FALSE;
BOOLEAN AttemptTeardown = FALSE;
BOOLEAN VcbAcquired = FALSE;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
KIRQL SavedIrql;
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_IRP( Irp );
//
// If we were called with our file system device object instead of a
// volume device object, just complete this request with STATUS_SUCCESS.
//
if (IrpContext->Vcb == NULL) {
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Get the file object out of the Irp and decode the type of open.
//
FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
TypeOfOpen = CdDecodeFileObject( IrpContext,
FileObject,
&Fcb,
&Ccb );
//
// No work here for either an UnopenedFile object or a StreamFileObject.
//
if (TypeOfOpen <= StreamFileOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Keep a local pointer to the Vcb.
//
Vcb = Fcb->Vcb;
//
// Synchronise with reads while we set the cleanup complete
// flag on this fileobject. Once this flag is set, any further
// reads will be rejected (CdVerifyFcbOperation)
//
CdAcquireFileExclusive( IrpContext, Fcb);
//
// Set the flag in the FileObject to indicate that cleanup is complete.
//
SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE );
CdReleaseFile( IrpContext, Fcb);
if (TypeOfOpen == UserVolumeOpen) {
//
// For a force dismount, physically disconnect this Vcb from the device so
// a new mount can occur. Vcb deletion cannot happen at this time since
// there is a reference on it associated with this very request, but we'll
// call check for dismount again later after we process this close.
//
if (FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE )) {
CdAcquireCdData( IrpContext );
CdCheckForDismount( IrpContext, Vcb, TRUE );
CdReleaseCdData( IrpContext );
//
// If this handle actually wrote something, flush the device buffers,
// and then set the verify bit now just to be safe (in case there is no
// dismount).
//
} else if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) {
CdHijackIrpAndFlushDevice( IrpContext, Irp, Vcb->TargetDeviceObject );
CdMarkDevForVerifyIfVcbMounted( Vcb );
}
}
//
// Acquire the current file.
//
CdAcquireFcbExclusive( IrpContext, Fcb, FALSE );
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_TRY {
//
// Case on the type of open that we are trying to cleanup.
//
switch (TypeOfOpen) {
case UserDirectoryOpen:
//
// Check if we need to complete any dir notify Irps on this file object.
//
FsRtlNotifyCleanup( Vcb->NotifySync,
&Vcb->DirNotifyList,
Ccb );
break;
case UserFileOpen:
//
// Coordinate the cleanup operation with the oplock state.
// Oplock cleanup operations can always cleanup immediately so no
// need to check for STATUS_PENDING.
//
FsRtlCheckOplock( CdGetFcbOplock(Fcb),
Irp,
IrpContext,
NULL,
NULL );
//
// Unlock all outstanding file locks.
//
if (Fcb->FileLock != NULL) {
FsRtlFastUnlockAll( Fcb->FileLock,
FileObject,
IoGetRequestorProcess( Irp ),
NULL );
}
//
// Cleanup the cache map.
//
CcUninitializeCacheMap( FileObject, NULL, NULL );
//
// Check the fast io state.
//
CdLockFcb( IrpContext, Fcb );
Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
CdUnlockFcb( IrpContext, Fcb );
break;
case UserVolumeOpen:
break;
default :
#ifdef _MSC_VER
#pragma prefast( suppress:__WARNING_USE_OTHER_FUNCTION, "argument bogus" )
#endif
CdBugCheck( TypeOfOpen, 0, 0 );
}
//
// Now lock the Vcb in order to modify the fields in the in-memory
// structures.
//
CdLockVcb( IrpContext, Vcb );
//
// Decrement the cleanup counts in the Vcb and Fcb.
//
CdDecrementCleanupCounts( IrpContext, Fcb );
//
// If the cleanup count hit zero and the volume is not mounted, we
// will want to try to spark teardown.
//
AttemptTeardown = (Vcb->VcbCleanup == 0 && Vcb->VcbCondition == VcbNotMounted);
//
// If this file object has locked the volume then perform the unlock operation.
// We do this regardless of explicit or implicit (no share DASD open) lock.
//
if (FileObject == Vcb->VolumeLockFileObject) {
NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_LOCKED));
IoAcquireVpbSpinLock( &SavedIrql );
ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED);
ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
Vcb->VolumeLockFileObject = NULL;
SendUnlockNotification = TRUE;
IoReleaseVpbSpinLock( SavedIrql );
}
CdUnlockVcb( IrpContext, Vcb );
//
// We must clean up the share access at this time, since we may not
// get a Close call for awhile if the file was mapped through this
// File Object.
//
IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
} _SEH2_FINALLY {
CdReleaseFcb( IrpContext, Fcb );
if (SendUnlockNotification) {
FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK );
}
} _SEH2_END;
//
// If appropriate, try to spark teardown by purging the volume. Should
// this very fileobject we were cleaning up be the last reason for the
// volume to remain, teardown will commence on completion of this Irp.
//
if (AttemptTeardown) {
//
// Preacquire CdData here, since the purges will generate closes which
// may acquire CdData if there is a possibility of tearing the volume
// down.
//
CdAcquireCdData( IrpContext);
_SEH2_TRY {
CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
VcbAcquired = TRUE;
CdPurgeVolume( IrpContext, Vcb, FALSE );
} _SEH2_FINALLY {
if (VcbAcquired) { CdReleaseVcb( IrpContext, Vcb ); }
CdReleaseCdData( IrpContext);
} _SEH2_END;
}
//
// If this is a normal termination then complete the request
//
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,199 +0,0 @@
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
DevCtrl.c
Abstract:
This module implements the File System Device Control routines for Cdfs
called by the dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_DEVCTRL)
//
// Local support routines
//
// Tell prefast this is a completion routine
IO_COMPLETION_ROUTINE CdDevCtrlCompletionRoutine;
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdDevCtrlCompletionRoutine (
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonDevControl)
#endif
NTSTATUS
CdCommonDevControl (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
PIO_STACK_LOCATION IrpSp;
PIO_STACK_LOCATION NextIrpSp;
PAGED_CODE();
//
// Extract and decode the file object.
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TypeOfOpen = CdDecodeFileObject( IrpContext,
IrpSp->FileObject,
&Fcb,
&Ccb );
//
// The only type of opens we accept are user volume opens.
//
if (TypeOfOpen != UserVolumeOpen) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) {
//
// Verify the Vcb in this case to detect if the volume has changed.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Handle the case of the disk type ourselves.
//
} else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {
//
// Verify the Vcb in this case to detect if the volume has changed.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Check the size of the output buffer.
//
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {
CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
return STATUS_BUFFER_TOO_SMALL;
}
//
// Copy the data from the Vcb.
//
((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags;
Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Get the next stack location, and copy over the stack parameter
// information.
//
NextIrpSp = IoGetNextIrpStackLocation( Irp );
*NextIrpSp = *IrpSp;
//
// Set up the completion routine
//
IoSetCompletionRoutine( Irp,
CdDevCtrlCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
//
// Send the request.
//
Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
//
// Cleanup our Irp Context. The driver has completed the Irp.
//
CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
return Status;
}
//
// Local support routine
//
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
CdDevCtrlCompletionRoutine (
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
)
{
//
// Add the hack-o-ramma to fix formats.
//
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Contxt );
}

View file

@ -1,605 +0,0 @@
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
VolInfo.c
Abstract:
This module implements the volume information routines for Cdfs called by
the dispatch driver.
--*/
#include "cdprocs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO)
//
// Local support routines
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdQueryFsVolumeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryFsSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryFsDeviceInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
_Inout_ PULONG Length
);
NTSTATUS
CdQueryFsAttributeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
_Inout_ PULONG Length
);
#ifdef __REACTOS__
#define PFILE_FS_SECTOR_SIZE_INFORMATION PVOID
#endif
NTSTATUS
CdQueryFsSectorSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonQueryVolInfo)
#pragma alloc_text(PAGE, CdQueryFsAttributeInfo)
#pragma alloc_text(PAGE, CdQueryFsDeviceInfo)
#pragma alloc_text(PAGE, CdQueryFsSizeInfo)
#pragma alloc_text(PAGE, CdQueryFsVolumeInfo)
#pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo)
#endif
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdCommonQueryVolInfo (
_Inout_ PIRP_CONTEXT IrpContext,
_Inout_ PIRP Irp
)
/*++
Routine Description:
This is the common routine for querying volume information called by both
the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
ULONG Length;
TYPE_OF_OPEN TypeOfOpen;
PFCB Fcb;
PCCB Ccb;
PAGED_CODE();
//
// Reference our input parameters to make things easier
//
Length = IrpSp->Parameters.QueryVolume.Length;
//
// Decode the file object and fail if this an unopened file object.
//
TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
if (TypeOfOpen == UnopenedFileObject) {
CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
return STATUS_INVALID_PARAMETER;
}
//
// Acquire the Vcb for this volume.
//
CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
//
// Use a try-finally to facilitate cleanup.
//
_SEH2_TRY {
//
// Verify the Vcb.
//
CdVerifyVcb( IrpContext, Fcb->Vcb );
//
// Based on the information class we'll do different actions. Each
// of the procedures that we're calling fills up the output buffer
// if possible and returns true if it successfully filled the buffer
// and false if it couldn't wait for any I/O to complete.
//
switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
case FileFsSizeInformation:
Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsVolumeInformation:
Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsDeviceInformation:
Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
case FileFsAttributeInformation:
Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
#if (NTDDI_VERSION >= NTDDI_WIN8)
case FileFsSectorSizeInformation:
Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
break;
#endif
/* ReactOS Change: GCC "enumeration value not handled in switch" */
default: break;
}
//
// Set the information field to the number of bytes actually filled in
//
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
} _SEH2_FINALLY {
//
// Release the Vcb.
//
CdReleaseVcb( IrpContext, Fcb->Vcb );
} _SEH2_END;
//
// Complete the request if we didn't raise.
//
CdCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// Local support routine
//
_Requires_lock_held_(_Global_critical_region_)
NTSTATUS
CdQueryFsVolumeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume info call
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
ULONG BytesToCopy;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Fill in the data from the Vcb.
//
Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
Buffer->SupportsObjects = FALSE;
*Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
//
// Check if the buffer we're given is long enough
//
if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
BytesToCopy = Vcb->Vpb->VolumeLabelLength;
} else {
BytesToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
//
// Copy over what we can of the volume label, and adjust *Length
//
Buffer->VolumeLabelLength = BytesToCopy;
if (BytesToCopy) {
RtlCopyMemory( &Buffer->VolumeLabel[0],
&Vcb->Vpb->VolumeLabel[0],
BytesToCopy );
}
*Length -= BytesToCopy;
//
// Set our status and return to our caller
//
return Status;
}
//
// Local support routine
//
NTSTATUS
CdQueryFsSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume size call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Fill in the output buffer.
//
Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
Buffer->AvailableAllocationUnits.QuadPart = 0;
Buffer->SectorsPerAllocationUnit = 1;
Buffer->BytesPerSector = SECTOR_SIZE;
//
// Adjust the length variable
//
*Length -= sizeof( FILE_FS_SIZE_INFORMATION );
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdQueryFsDeviceInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume device call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Update the output buffer.
//
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
Buffer->DeviceType = FILE_DEVICE_CD_ROM;
//
// Adjust the length variable
//
*Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Local support routine
//
NTSTATUS
CdQueryFsAttributeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query volume attribute call.
Arguments:
Vcb - Vcb for this volume.
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
ULONG BytesToCopy;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
UNREFERENCED_PARAMETER( Vcb );
//
// Fill out the fixed portion of the buffer.
//
Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
FILE_READ_ONLY_VOLUME |
FILE_SUPPORTS_OPEN_BY_FILE_ID;
if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
Buffer->MaximumComponentNameLength = 110;
} else {
Buffer->MaximumComponentNameLength = 221;
}
*Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
//
// Make sure we can copy full unicode characters.
//
ClearFlag( *Length, 1 );
//
// Determine how much of the file system name will fit.
//
if (*Length >= 8) {
BytesToCopy = 8;
} else {
BytesToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
*Length -= BytesToCopy;
//
// Do the file system name.
//
Buffer->FileSystemNameLength = BytesToCopy;
RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
//
// And return to our caller
//
return Status;
}
#if (NTDDI_VERSION >= NTDDI_WIN8)
NTSTATUS
CdQueryFsSectorSizeInfo (
_In_ PIRP_CONTEXT IrpContext,
_In_ PVCB Vcb,
_Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
_Inout_ PULONG Length
)
/*++
Routine Description:
This routine implements the query sector size information call
This operation will work on any handle and requires no privilege.
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return receives the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
NTSTATUS Status;
PAGED_CODE();
UNREFERENCED_PARAMETER( IrpContext );
//
// Sufficient buffer size is guaranteed by the I/O manager or the
// originating kernel mode driver.
//
ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
_Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
//
// Retrieve the sector size information
//
Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
Buffer );
//
// Adjust the length variable
//
if (NT_SUCCESS( Status )) {
*Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
}
return Status;
}
#endif