mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[CDFS] Delete the old CDFS driver.
You served us well!
This commit is contained in:
parent
a4554c07b0
commit
5795254933
19 changed files with 0 additions and 5564 deletions
|
@ -1,28 +0,0 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
|
||||
|
||||
list(APPEND SOURCE
|
||||
cdfs.c
|
||||
cleanup.c
|
||||
close.c
|
||||
common.c
|
||||
create.c
|
||||
devctrl.c
|
||||
dirctl.c
|
||||
dispatch.c
|
||||
fastio.c
|
||||
fcb.c
|
||||
finfo.c
|
||||
fsctl.c
|
||||
misc.c
|
||||
rw.c
|
||||
volinfo.c
|
||||
cdfs.h)
|
||||
|
||||
add_library(cdfs SHARED ${SOURCE} cdfs.rc)
|
||||
set_module_type(cdfs kernelmodedriver)
|
||||
target_link_libraries(cdfs ${PSEH_LIB})
|
||||
add_importlibs(cdfs ntoskrnl hal)
|
||||
add_pch(cdfs cdfs.h SOURCE)
|
||||
add_cd_file(TARGET cdfs DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
add_registry_inf(cdfs_reg.inf)
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -1,5 +0,0 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ISO9660 Driver"
|
||||
#define REACTOS_STR_INTERNAL_NAME "cdfs"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "cdfs.sys"
|
||||
#include <reactos/version.rc>
|
|
@ -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
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2002 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystems/cdfs/cleanup.c
|
||||
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
||||
* PROGRAMMER:
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "cdfs.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static NTSTATUS
|
||||
CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext,
|
||||
PFILE_OBJECT FileObject)
|
||||
/*
|
||||
* FUNCTION: Cleans up after a file has been closed.
|
||||
*/
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
PFCB Fcb;
|
||||
|
||||
DPRINT("CdfsCleanupFile(IrpContext %p, FileObject %p)\n",
|
||||
IrpContext,
|
||||
FileObject);
|
||||
|
||||
DeviceExt = IrpContext->DeviceObject->DeviceExtension;
|
||||
Fcb = FileObject->FsContext;
|
||||
if (!Fcb)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DeviceExt->OpenHandleCount--;
|
||||
|
||||
/* Notify about the cleanup */
|
||||
FsRtlNotifyCleanup(DeviceExt->NotifySync,
|
||||
&(DeviceExt->NotifyList),
|
||||
FileObject->FsContext2);
|
||||
|
||||
if (!CdfsFCBIsDirectory(Fcb) &&
|
||||
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
|
||||
{
|
||||
FsRtlFastUnlockAll(&Fcb->FileLock,
|
||||
FileObject,
|
||||
IoGetRequestorProcess(IrpContext->Irp),
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Uninitialize file cache if initialized for this file object. */
|
||||
if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap)
|
||||
{
|
||||
CcUninitializeCacheMap (FileObject, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Inform cleanup is complete */
|
||||
FileObject->Flags |= FO_CLEANUP_COMPLETE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
CdfsCleanup(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PFILE_OBJECT FileObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CdfsCleanup() called\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
Irp = IrpContext->Irp;
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
Stack = IrpContext->Stack;
|
||||
|
||||
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
|
||||
{
|
||||
DPRINT("Closing file system\n");
|
||||
Status = STATUS_SUCCESS;
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
FileObject = Stack->FileObject;
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE);
|
||||
|
||||
Status = CdfsCleanupFile(IrpContext, FileObject);
|
||||
|
||||
ExReleaseResourceLite(&DeviceExtension->DirResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
ByeBye:
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2002 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystems/cdfs/close.c
|
||||
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
||||
* PROGRAMMER: Art Yerkes
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "cdfs.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
CdfsCloseFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject)
|
||||
/*
|
||||
* FUNCTION: Closes a file
|
||||
*/
|
||||
{
|
||||
PCCB Ccb;
|
||||
|
||||
DPRINT("CdfsCloseFile(DeviceExt %p, FileObject %p)\n",
|
||||
DeviceExt,
|
||||
FileObject);
|
||||
|
||||
Ccb = (PCCB)(FileObject->FsContext2);
|
||||
|
||||
DPRINT("Ccb %p\n", Ccb);
|
||||
if (Ccb == NULL)
|
||||
{
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
FileObject->FsContext2 = NULL;
|
||||
|
||||
if (FileObject->FileName.Buffer)
|
||||
{
|
||||
// This a FO, that was created outside from FSD.
|
||||
// Some FO's are created with IoCreateStreamFileObject() insid from FSD.
|
||||
// This FO's don't have a FileName.
|
||||
CdfsReleaseFCB(DeviceExt, FileObject->FsContext);
|
||||
}
|
||||
|
||||
if (Ccb->DirectorySearchPattern.Buffer)
|
||||
{
|
||||
ExFreePoolWithTag(Ccb->DirectorySearchPattern.Buffer, CDFS_SEARCH_PATTERN_TAG);
|
||||
}
|
||||
ExFreePoolWithTag(Ccb, CDFS_CCB_TAG);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS NTAPI
|
||||
CdfsClose(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PFILE_OBJECT FileObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CdfsClose() called\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
Irp = IrpContext->Irp;
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
Stack = IrpContext->Stack;
|
||||
|
||||
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
|
||||
{
|
||||
DPRINT("Closing file system\n");
|
||||
Status = STATUS_SUCCESS;
|
||||
goto ByeBye;
|
||||
}
|
||||
|
||||
FileObject = Stack->FileObject;
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
Status = CdfsCloseFile(DeviceExtension,FileObject);
|
||||
|
||||
ByeBye:
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -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 */
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2002, 2003, 2004 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystems/cdfs/cdfs.c
|
||||
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
||||
* PROGRAMMER: Art Yerkes
|
||||
* Eric Kohl
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "cdfs.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static NTSTATUS
|
||||
CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject,
|
||||
PUNICODE_STRING RelativeFileName,
|
||||
PUNICODE_STRING AbsoluteFileName)
|
||||
{
|
||||
USHORT Length;
|
||||
PFCB Fcb;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("try related for %wZ\n", RelativeFileName);
|
||||
Fcb = FileObject->FsContext;
|
||||
ASSERT(Fcb);
|
||||
|
||||
/* verify related object is a directory and target name
|
||||
don't start with \. */
|
||||
if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
|
||||
(RelativeFileName->Length >= sizeof(WCHAR) &&
|
||||
RelativeFileName->Buffer[0] == L'\\'))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* construct absolute path name */
|
||||
Length = Fcb->PathName.Length +
|
||||
sizeof(WCHAR) +
|
||||
RelativeFileName->Length +
|
||||
sizeof(WCHAR);
|
||||
AbsoluteFileName->Length = 0;
|
||||
AbsoluteFileName->MaximumLength = Length;
|
||||
AbsoluteFileName->Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, CDFS_FILENAME_TAG);
|
||||
if (AbsoluteFileName->Buffer == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
|
||||
&Fcb->PathName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeUnicodeString(AbsoluteFileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!CdfsFCBIsRoot(Fcb))
|
||||
{
|
||||
Status = RtlAppendUnicodeToString(AbsoluteFileName,
|
||||
L"\\");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeUnicodeString(AbsoluteFileName);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
|
||||
RelativeFileName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeUnicodeString(AbsoluteFileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTION: Opens a file
|
||||
*/
|
||||
static NTSTATUS
|
||||
CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PUNICODE_STRING FileName)
|
||||
{
|
||||
PFCB ParentFcb;
|
||||
PFCB Fcb;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING AbsFileName;
|
||||
|
||||
DPRINT("CdfsOpenFile(%p, %p, %wZ)\n", DeviceExt, FileObject, FileName);
|
||||
|
||||
if (FileObject->RelatedFileObject)
|
||||
{
|
||||
DPRINT("Converting relative filename to absolute filename\n");
|
||||
|
||||
Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
|
||||
FileName,
|
||||
&AbsFileName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
FileName = &AbsFileName;
|
||||
}
|
||||
|
||||
Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
|
||||
IOCTL_CDROM_CHECK_VERIFY,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
FALSE);
|
||||
DPRINT ("Status %lx\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("Status %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("PathName to open: %wZ\n", FileName);
|
||||
|
||||
/* try first to find an existing FCB in memory */
|
||||
DPRINT("Checking for existing FCB in memory\n");
|
||||
Fcb = CdfsGrabFCBFromTable(DeviceExt,
|
||||
FileName);
|
||||
if (Fcb == NULL)
|
||||
{
|
||||
DPRINT("No existing FCB found, making a new one if file exists.\n");
|
||||
Status = CdfsGetFCBForFile(DeviceExt,
|
||||
&ParentFcb,
|
||||
&Fcb,
|
||||
FileName);
|
||||
if (ParentFcb != NULL)
|
||||
{
|
||||
CdfsReleaseFCB(DeviceExt,
|
||||
ParentFcb);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS (Status))
|
||||
{
|
||||
DPRINT("Could not make a new FCB, status: %x\n", Status);
|
||||
|
||||
if (FileName == &AbsFileName)
|
||||
RtlFreeUnicodeString(&AbsFileName);
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("Attaching FCB to fileObject\n");
|
||||
Status = CdfsAttachFCBToFileObject(DeviceExt,
|
||||
Fcb,
|
||||
FileObject);
|
||||
|
||||
if ((FileName == &AbsFileName) && AbsFileName.Buffer)
|
||||
ExFreePoolWithTag(AbsFileName.Buffer, CDFS_FILENAME_TAG);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTION: Opens a file
|
||||
*/
|
||||
static NTSTATUS
|
||||
CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PFILE_OBJECT FileObject;
|
||||
ULONG RequestedDisposition;
|
||||
ULONG RequestedOptions;
|
||||
PFCB Fcb;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CdfsCreateFile() called\n");
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
ASSERT(DeviceExt);
|
||||
Stack = IoGetCurrentIrpStackLocation (Irp);
|
||||
ASSERT(Stack);
|
||||
|
||||
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
|
||||
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
||||
DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
|
||||
RequestedDisposition, RequestedOptions);
|
||||
|
||||
FileObject = Stack->FileObject;
|
||||
|
||||
if (RequestedDisposition == FILE_CREATE ||
|
||||
RequestedDisposition == FILE_OVERWRITE_IF ||
|
||||
RequestedDisposition == FILE_SUPERSEDE)
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
Status = CdfsOpenFile(DeviceExt,
|
||||
FileObject,
|
||||
&FileObject->FileName);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Fcb = FileObject->FsContext;
|
||||
|
||||
/* Check whether the file has the requested attributes */
|
||||
if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
|
||||
{
|
||||
CdfsCloseFile (DeviceExt, FileObject);
|
||||
return STATUS_FILE_IS_A_DIRECTORY;
|
||||
}
|
||||
|
||||
if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
|
||||
{
|
||||
CdfsCloseFile (DeviceExt, FileObject);
|
||||
return STATUS_NOT_A_DIRECTORY;
|
||||
}
|
||||
|
||||
DeviceExt->OpenHandleCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the directory containing the file to open doesn't exist then
|
||||
* fail immediately
|
||||
*/
|
||||
Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS NTAPI
|
||||
CdfsCreate(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CdfsCreate()\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
|
||||
{
|
||||
/* DeviceObject represents FileSystem instead of logical volume */
|
||||
DPRINT("Opening file system\n");
|
||||
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
|
||||
DeviceExt->OpenHandleCount++;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
|
||||
TRUE);
|
||||
Status = CdfsCreateFile(DeviceObject,
|
||||
IrpContext->Irp);
|
||||
ExReleaseResourceLite(&DeviceExt->DirResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystems/cdfs/devctrl.c
|
||||
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
||||
* PROGRAMMER: Pierre Schweitzer
|
||||
*
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "cdfs.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
CdfsDeviceControl(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
PVCB Vcb = NULL;
|
||||
PFILE_OBJECT FileObject;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
DPRINT("CdfsDeviceControl()\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
Irp = IrpContext->Irp;
|
||||
Stack = IrpContext->Stack;
|
||||
FileObject = Stack->FileObject;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
/* FIXME: HACK, it means that CD has changed */
|
||||
if (!FileObject)
|
||||
{
|
||||
DPRINT1("FIXME: CdfsDeviceControl called without FileObject!\n");
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
/* Only support such operations on volume */
|
||||
if (!(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE)
|
||||
{
|
||||
/* We should handle this one, but we don't! */
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Pass it to storage driver */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Vcb = (PVCB)Stack->DeviceObject->DeviceExtension;
|
||||
|
||||
/* Lower driver will complete - we don't have to */
|
||||
IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
|
||||
|
||||
Status = IoCallDriver(Vcb->StorageDevice, Irp);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2002, 2003 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystems/cdfs/volume.c
|
||||
* PURPOSE: CDROM (ISO 9660) filesystem driver
|
||||
* PROGRAMMER: Art Yerkes
|
||||
* Eric Kohl
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "cdfs.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CdfsGetFsVolumeInformation(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
|
||||
PULONG BufferLength)
|
||||
{
|
||||
DPRINT("CdfsGetFsVolumeInformation() called\n");
|
||||
DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
|
||||
DPRINT("Vpb %p\n", DeviceObject->Vpb);
|
||||
|
||||
DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength));
|
||||
DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength);
|
||||
DPRINT("Label %.*S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel);
|
||||
|
||||
if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
/* valid entries */
|
||||
FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
|
||||
FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
|
||||
memcpy(FsVolumeInfo->VolumeLabel,
|
||||
DeviceObject->Vpb->VolumeLabel,
|
||||
DeviceObject->Vpb->VolumeLabelLength);
|
||||
|
||||
/* dummy entries */
|
||||
FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
|
||||
FsVolumeInfo->SupportsObjects = FALSE;
|
||||
|
||||
DPRINT("Finished FsdGetFsVolumeInformation()\n");
|
||||
|
||||
*BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
|
||||
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CdfsGetFsAttributeInformation(
|
||||
PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
|
||||
PULONG BufferLength)
|
||||
{
|
||||
DPRINT("CdfsGetFsAttributeInformation()\n");
|
||||
DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8));
|
||||
|
||||
UNREFERENCED_PARAMETER(DeviceExt);
|
||||
|
||||
if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
FsAttributeInfo->FileSystemAttributes =
|
||||
FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_READ_ONLY_VOLUME;
|
||||
FsAttributeInfo->MaximumComponentNameLength = 255;
|
||||
FsAttributeInfo->FileSystemNameLength = 8;
|
||||
|
||||
memcpy(FsAttributeInfo->FileSystemName, L"CDFS", 8);
|
||||
|
||||
DPRINT("Finished FsdGetFsAttributeInformation()\n");
|
||||
|
||||
*BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
CdfsGetFsSizeInformation(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PFILE_FS_SIZE_INFORMATION FsSizeInfo,
|
||||
PULONG BufferLength)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("CdfsGetFsSizeInformation()\n");
|
||||
DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
|
||||
|
||||
if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
|
||||
FsSizeInfo->AvailableAllocationUnits.QuadPart = 0;
|
||||
FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize;
|
||||
FsSizeInfo->SectorsPerAllocationUnit = 1;
|
||||
FsSizeInfo->BytesPerSector = BLOCKSIZE;
|
||||
|
||||
DPRINT("Finished FsdGetFsSizeInformation()\n");
|
||||
if (NT_SUCCESS(Status))
|
||||
*BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CdfsGetFsDeviceInformation(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
|
||||
PULONG BufferLength)
|
||||
{
|
||||
DPRINT("CdfsGetFsDeviceInformation()\n");
|
||||
DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
|
||||
|
||||
if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
|
||||
FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM;
|
||||
else
|
||||
FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
|
||||
|
||||
FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
|
||||
|
||||
DPRINT("FsdGetFsDeviceInformation() finished.\n");
|
||||
|
||||
*BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
|
||||
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CdfsGetFsFullSizeInformation(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PFILE_FS_FULL_SIZE_INFORMATION FsSizeInfo,
|
||||
PULONG BufferLength)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("CdfsGetFsFullSizeInformation()\n");
|
||||
DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
|
||||
|
||||
if (*BufferLength < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
|
||||
FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize;
|
||||
FsSizeInfo->CallerAvailableAllocationUnits.QuadPart = 0;
|
||||
FsSizeInfo->ActualAvailableAllocationUnits.QuadPart = 0;
|
||||
FsSizeInfo->SectorsPerAllocationUnit = 1;
|
||||
FsSizeInfo->BytesPerSector = BLOCKSIZE;
|
||||
|
||||
DPRINT("Finished CdfsGetFsFullSizeInformation()\n");
|
||||
if (NT_SUCCESS(Status))
|
||||
*BufferLength -= sizeof(FILE_FS_FULL_SIZE_INFORMATION);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdfsQueryVolumeInformation(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
FS_INFORMATION_CLASS FsInformationClass;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PVOID SystemBuffer;
|
||||
ULONG BufferLength;
|
||||
|
||||
DPRINT("CdfsQueryVolumeInformation() called\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
Irp = IrpContext->Irp;
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
Stack = IrpContext->Stack;
|
||||
FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
|
||||
BufferLength = Stack->Parameters.QueryVolume.Length;
|
||||
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
DPRINT("FsInformationClass %d\n", FsInformationClass);
|
||||
DPRINT("SystemBuffer %p\n", SystemBuffer);
|
||||
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileFsVolumeInformation:
|
||||
Status = CdfsGetFsVolumeInformation(DeviceObject,
|
||||
SystemBuffer,
|
||||
&BufferLength);
|
||||
break;
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension,
|
||||
SystemBuffer,
|
||||
&BufferLength);
|
||||
break;
|
||||
|
||||
case FileFsSizeInformation:
|
||||
Status = CdfsGetFsSizeInformation(DeviceObject,
|
||||
SystemBuffer,
|
||||
&BufferLength);
|
||||
break;
|
||||
|
||||
case FileFsDeviceInformation:
|
||||
Status = CdfsGetFsDeviceInformation(DeviceObject,
|
||||
SystemBuffer,
|
||||
&BufferLength);
|
||||
break;
|
||||
|
||||
case FileFsFullSizeInformation:
|
||||
Status = CdfsGetFsFullSizeInformation(DeviceObject,
|
||||
SystemBuffer,
|
||||
&BufferLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
Irp->IoStatus.Information =
|
||||
Stack->Parameters.QueryVolume.Length - BufferLength;
|
||||
else
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdfsSetVolumeInformation(
|
||||
PCDFS_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
DPRINT("CdfsSetVolumeInformation() called\n");
|
||||
|
||||
ASSERT(IrpContext);
|
||||
|
||||
IrpContext->Irp->IoStatus.Information = 0;
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue