diff --git a/boot/environ/lib/io/etfs.c b/boot/environ/lib/io/etfs.c index 8d8797b01b0..da5ee0f8654 100644 --- a/boot/environ/lib/io/etfs.c +++ b/boot/environ/lib/io/etfs.c @@ -9,7 +9,7 @@ /* INCLUDES ******************************************************************/ #include -#include +#include typedef struct _RAW_ET_VD { UCHAR BootIndicator; diff --git a/drivers/filesystems/CMakeLists.txt b/drivers/filesystems/CMakeLists.txt index 24937d7f131..7485d433b5a 100644 --- a/drivers/filesystems/CMakeLists.txt +++ b/drivers/filesystems/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(btrfs) -add_subdirectory(cdfs_new) +add_subdirectory(cdfs) add_subdirectory(ext2) add_subdirectory(fastfat) add_subdirectory(ffs) diff --git a/drivers/filesystems/cdfs/CMakeLists.txt b/drivers/filesystems/cdfs/CMakeLists.txt index 6cd539b95e8..8bf4fa2639d 100644 --- a/drivers/filesystems/cdfs/CMakeLists.txt +++ b/drivers/filesystems/cdfs/CMakeLists.txt @@ -2,27 +2,39 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers) list(APPEND SOURCE - cdfs.c + allocsup.c + cachesup.c + cddata.c + cdinit.c + cdprocssrc.c cleanup.c close.c - common.c create.c devctrl.c - dirctl.c - dispatch.c - fastio.c - fcb.c - finfo.c - fsctl.c - misc.c - rw.c + deviosup.c + dirctrl.c + dirsup.c + fileinfo.c + filobsup.c + fsctrl.c + fspdisp.c + lockctrl.c + namesup.c + pathsup.c + pnp.c + prefxsup.c + read.c + resrcsup.c + shutdown.c + strucsup.c + verfysup.c volinfo.c - cdfs.h) + workque.c + write.c) add_library(cdfs SHARED ${SOURCE} cdfs.rc) set_module_type(cdfs kernelmodedriver) -target_link_libraries(cdfs ${PSEH_LIB}) +target_link_libraries(cdfs ${PSEH_LIB} memcmp) add_importlibs(cdfs ntoskrnl hal) -add_pch(cdfs cdfs.h SOURCE) add_cd_file(TARGET cdfs DESTINATION reactos/system32/drivers NO_CAB FOR all) add_registry_inf(cdfs_reg.inf) diff --git a/drivers/filesystems/cdfs_new/LICENSE b/drivers/filesystems/cdfs/LICENSE similarity index 100% rename from drivers/filesystems/cdfs_new/LICENSE rename to drivers/filesystems/cdfs/LICENSE diff --git a/drivers/filesystems/cdfs_new/README.md b/drivers/filesystems/cdfs/README.md similarity index 100% rename from drivers/filesystems/cdfs_new/README.md rename to drivers/filesystems/cdfs/README.md diff --git a/drivers/filesystems/cdfs_new/allocsup.c b/drivers/filesystems/cdfs/allocsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/allocsup.c rename to drivers/filesystems/cdfs/allocsup.c diff --git a/drivers/filesystems/cdfs_new/cachesup.c b/drivers/filesystems/cdfs/cachesup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cachesup.c rename to drivers/filesystems/cdfs/cachesup.c diff --git a/drivers/filesystems/cdfs_new/cd.h b/drivers/filesystems/cdfs/cd.h old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cd.h rename to drivers/filesystems/cdfs/cd.h diff --git a/drivers/filesystems/cdfs_new/cddata.c b/drivers/filesystems/cdfs/cddata.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cddata.c rename to drivers/filesystems/cdfs/cddata.c diff --git a/drivers/filesystems/cdfs_new/cddata.h b/drivers/filesystems/cdfs/cddata.h old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cddata.h rename to drivers/filesystems/cdfs/cddata.h diff --git a/drivers/filesystems/cdfs/cdfs.c b/drivers/filesystems/cdfs/cdfs.c deleted file mode 100644 index aa51948f61b..00000000000 --- a/drivers/filesystems/cdfs/cdfs.c +++ /dev/null @@ -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 - -#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); -} diff --git a/drivers/filesystems/cdfs/cdfs.h b/drivers/filesystems/cdfs/cdfs.h deleted file mode 100644 index b23846f6478..00000000000 --- a/drivers/filesystems/cdfs/cdfs.h +++ /dev/null @@ -1,531 +0,0 @@ -#ifndef CDFS_H -#define CDFS_H - -#include -#include -#include - -#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 -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 - -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 -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 - -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 */ diff --git a/drivers/filesystems/cdfs/cdfs.rc b/drivers/filesystems/cdfs/cdfs.rc index f0ac8d551ea..5d4dcafce01 100644 --- a/drivers/filesystems/cdfs/cdfs.rc +++ b/drivers/filesystems/cdfs/cdfs.rc @@ -1,5 +1,14 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "ISO9660 Driver" -#define REACTOS_STR_INTERNAL_NAME "cdfs" -#define REACTOS_STR_ORIGINAL_FILENAME "cdfs.sys" -#include +// +// Copyright (C) Microsoft. All rights reserved. +// +#include + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "CD-ROM File System Driver" +#define VER_INTERNALNAME_STR "cdfs.sys" + +#include "common.ver" + diff --git a/drivers/filesystems/cdfs_new/cdinit.c b/drivers/filesystems/cdfs/cdinit.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cdinit.c rename to drivers/filesystems/cdfs/cdinit.c diff --git a/drivers/filesystems/cdfs_new/cdprocs.h b/drivers/filesystems/cdfs/cdprocs.h old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cdprocs.h rename to drivers/filesystems/cdfs/cdprocs.h diff --git a/drivers/filesystems/cdfs_new/cdprocssrc.c b/drivers/filesystems/cdfs/cdprocssrc.c similarity index 100% rename from drivers/filesystems/cdfs_new/cdprocssrc.c rename to drivers/filesystems/cdfs/cdprocssrc.c diff --git a/drivers/filesystems/cdfs_new/cdstruc.h b/drivers/filesystems/cdfs/cdstruc.h old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/cdstruc.h rename to drivers/filesystems/cdfs/cdstruc.h diff --git a/drivers/filesystems/cdfs/cleanup.c b/drivers/filesystems/cdfs/cleanup.c index 63ae24f7d92..0cdda166f57 100644 --- a/drivers/filesystems/cdfs/cleanup.c +++ b/drivers/filesystems/cdfs/cleanup.c @@ -1,129 +1,366 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/filesystems/cdfs/cleanup.c - * PURPOSE: CDROM (ISO 9660) filesystem driver - * PROGRAMMER: - * UPDATE HISTORY: - */ +/*++ -/* INCLUDES *****************************************************************/ +Copyright (c) 1989-2000 Microsoft Corporation -#include "cdfs.h" +Module Name: -#define NDEBUG -#include + Cleanup.c -/* FUNCTIONS ****************************************************************/ +Abstract: + + This module implements the File Cleanup routine for Cdfs called by the + dispatch driver. + + +--*/ + +#include "cdprocs.h" + +// +// The Bug check file id for this module +// + +#define BugCheckFileId (CDFS_BUG_CHECK_CLEANUP) + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdCommonCleanup ( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This is the common routine for cleanup of a file/directory called by both + the fsd and fsp threads. + + Cleanup is invoked whenever the last handle to a file object is closed. + This is different than the Close operation which is invoked when the last + reference to a file object is deleted. + + The function of cleanup is to essentially "cleanup" the file/directory + after a user is done with it. The Fcb/Dcb remains around (because MM + still has the file object referenced) but is now available for another + user to open (i.e., as far as the user is concerned the is now closed). + + See close for a more complete description of what close does. + + We do no synchronization in this routine until we get to the point + where we modify the counts, share access and volume lock field. + + We need to update the Fcb and Vcb to show that a user handle has been closed. + The following structures and fields are affected. + + Vcb: + + VolumeLockFileObject - Did the user lock the volume with this file object. + VcbState - Check if we are unlocking the volume here. + VcbCleanup - Count of outstanding handles on the volume. + DirNotifyQueue - If this file object has pending DirNotify Irps. + + Fcb: + + ShareAccess - If this is a user handle. + FcbCleanup - Count of outstanding handles on this Fcb. + Oplock - Any outstanding oplocks on this file object. + FileLock - Any outstanding filelocks on this file object. + +Arguments: + + Irp - Supplies the Irp to process + +Return Value: + + NTSTATUS - The return status for the operation. + +--*/ -static NTSTATUS -CdfsCleanupFile(PCDFS_IRP_CONTEXT IrpContext, - PFILE_OBJECT FileObject) - /* - * FUNCTION: Cleans up after a file has been closed. - */ { - PDEVICE_EXTENSION DeviceExt; + PFILE_OBJECT FileObject; + TYPE_OF_OPEN TypeOfOpen; + + BOOLEAN SendUnlockNotification = FALSE; + BOOLEAN AttemptTeardown = FALSE; + BOOLEAN VcbAcquired = FALSE; + + PVCB Vcb; PFCB Fcb; + PCCB Ccb; - DPRINT("CdfsCleanupFile(IrpContext %p, FileObject %p)\n", - IrpContext, - FileObject); + KIRQL SavedIrql; - DeviceExt = IrpContext->DeviceObject->DeviceExtension; - Fcb = FileObject->FsContext; - if (!Fcb) - { + ASSERT_IRP_CONTEXT( IrpContext ); + ASSERT_IRP( Irp ); + + // + // If we were called with our file system device object instead of a + // volume device object, just complete this request with STATUS_SUCCESS. + // + + if (IrpContext->Vcb == NULL) { + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; } - DeviceExt->OpenHandleCount--; + // + // Get the file object out of the Irp and decode the type of open. + // - /* Notify about the cleanup */ - FsRtlNotifyCleanup(DeviceExt->NotifySync, - &(DeviceExt->NotifyList), - FileObject->FsContext2); + FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject; - if (!CdfsFCBIsDirectory(Fcb) && - FsRtlAreThereCurrentFileLocks(&Fcb->FileLock)) - { - FsRtlFastUnlockAll(&Fcb->FileLock, - FileObject, - IoGetRequestorProcess(IrpContext->Irp), - NULL); + TypeOfOpen = CdDecodeFileObject( IrpContext, + FileObject, + &Fcb, + &Ccb ); + + // + // No work here for either an UnopenedFile object or a StreamFileObject. + // + + if (TypeOfOpen <= StreamFileOpen) { + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); + + return STATUS_SUCCESS; } - /* Uninitialize file cache if initialized for this file object. */ - if (FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->SharedCacheMap) - { - CcUninitializeCacheMap (FileObject, NULL, NULL); + // + // Keep a local pointer to the Vcb. + // + + Vcb = Fcb->Vcb; + + // + // Synchronise with reads while we set the cleanup complete + // flag on this fileobject. Once this flag is set, any further + // reads will be rejected (CdVerifyFcbOperation) + // + + CdAcquireFileExclusive( IrpContext, Fcb); + + // + // Set the flag in the FileObject to indicate that cleanup is complete. + // + + SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE ); + + CdReleaseFile( IrpContext, Fcb); + + if (TypeOfOpen == UserVolumeOpen) { + + // + // For a force dismount, physically disconnect this Vcb from the device so + // a new mount can occur. Vcb deletion cannot happen at this time since + // there is a reference on it associated with this very request, but we'll + // call check for dismount again later after we process this close. + // + + if (FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE )) { + + CdAcquireCdData( IrpContext ); + + CdCheckForDismount( IrpContext, Vcb, TRUE ); + + CdReleaseCdData( IrpContext ); + + // + // If this handle actually wrote something, flush the device buffers, + // and then set the verify bit now just to be safe (in case there is no + // dismount). + // + + } else if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) { + + CdHijackIrpAndFlushDevice( IrpContext, Irp, Vcb->TargetDeviceObject ); + + CdMarkDevForVerifyIfVcbMounted( Vcb ); + } } - /* Inform cleanup is complete */ - FileObject->Flags |= FO_CLEANUP_COMPLETE; + // + // Acquire the current file. + // + + CdAcquireFcbExclusive( IrpContext, Fcb, FALSE ); + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Case on the type of open that we are trying to cleanup. + // + + switch (TypeOfOpen) { + + case UserDirectoryOpen: + + // + // Check if we need to complete any dir notify Irps on this file object. + // + + FsRtlNotifyCleanup( Vcb->NotifySync, + &Vcb->DirNotifyList, + Ccb ); + + break; + + case UserFileOpen: + + // + // Coordinate the cleanup operation with the oplock state. + // Oplock cleanup operations can always cleanup immediately so no + // need to check for STATUS_PENDING. + // + + FsRtlCheckOplock( CdGetFcbOplock(Fcb), + Irp, + IrpContext, + NULL, + NULL ); + + // + // Unlock all outstanding file locks. + // + + if (Fcb->FileLock != NULL) { + + FsRtlFastUnlockAll( Fcb->FileLock, + FileObject, + IoGetRequestorProcess( Irp ), + NULL ); + } + + // + // Cleanup the cache map. + // + + CcUninitializeCacheMap( FileObject, NULL, NULL ); + + // + // Check the fast io state. + // + + CdLockFcb( IrpContext, Fcb ); + Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); + CdUnlockFcb( IrpContext, Fcb ); + + break; + + case UserVolumeOpen: + + break; + + default : + +#ifdef _MSC_VER +#pragma prefast( suppress:__WARNING_USE_OTHER_FUNCTION, "argument bogus" ) +#endif + CdBugCheck( TypeOfOpen, 0, 0 ); + } + + // + // Now lock the Vcb in order to modify the fields in the in-memory + // structures. + // + + CdLockVcb( IrpContext, Vcb ); + + // + // Decrement the cleanup counts in the Vcb and Fcb. + // + + CdDecrementCleanupCounts( IrpContext, Fcb ); + + // + // If the cleanup count hit zero and the volume is not mounted, we + // will want to try to spark teardown. + // + + AttemptTeardown = (Vcb->VcbCleanup == 0 && Vcb->VcbCondition == VcbNotMounted); + + // + // If this file object has locked the volume then perform the unlock operation. + // We do this regardless of explicit or implicit (no share DASD open) lock. + // + + if (FileObject == Vcb->VolumeLockFileObject) { + + NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_LOCKED)); + + IoAcquireVpbSpinLock( &SavedIrql ); + + ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED); + ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED ); + Vcb->VolumeLockFileObject = NULL; + SendUnlockNotification = TRUE; + + IoReleaseVpbSpinLock( SavedIrql ); + } + + CdUnlockVcb( IrpContext, Vcb ); + + // + // We must clean up the share access at this time, since we may not + // get a Close call for awhile if the file was mapped through this + // File Object. + // + + IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); + + } _SEH2_FINALLY { + + CdReleaseFcb( IrpContext, Fcb ); + + if (SendUnlockNotification) { + + FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK ); + } + } _SEH2_END; + + // + // If appropriate, try to spark teardown by purging the volume. Should + // this very fileobject we were cleaning up be the last reason for the + // volume to remain, teardown will commence on completion of this Irp. + // + + if (AttemptTeardown) { + + // + // Preacquire CdData here, since the purges will generate closes which + // may acquire CdData if there is a possibility of tearing the volume + // down. + // + + CdAcquireCdData( IrpContext); + + _SEH2_TRY { + + CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); + VcbAcquired = TRUE; + + CdPurgeVolume( IrpContext, Vcb, FALSE ); + + } _SEH2_FINALLY { + + if (VcbAcquired) { CdReleaseVcb( IrpContext, Vcb ); } + + CdReleaseCdData( IrpContext); + } _SEH2_END; + } + + // + // If this is a normal termination then complete the request + // + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; } -NTSTATUS NTAPI -CdfsCleanup( - PCDFS_IRP_CONTEXT IrpContext) -{ - PIRP Irp; - PDEVICE_OBJECT DeviceObject; - PDEVICE_EXTENSION DeviceExtension; - PIO_STACK_LOCATION Stack; - PFILE_OBJECT FileObject; - NTSTATUS Status; - DPRINT("CdfsCleanup() called\n"); - - ASSERT(IrpContext); - - Irp = IrpContext->Irp; - DeviceObject = IrpContext->DeviceObject; - Stack = IrpContext->Stack; - - if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject) - { - DPRINT("Closing file system\n"); - Status = STATUS_SUCCESS; - goto ByeBye; - } - - FileObject = Stack->FileObject; - DeviceExtension = DeviceObject->DeviceExtension; - - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE); - - Status = CdfsCleanupFile(IrpContext, FileObject); - - ExReleaseResourceLite(&DeviceExtension->DirResource); - KeLeaveCriticalRegion(); - -ByeBye: - Irp->IoStatus.Information = 0; - - return(Status); -} - -/* EOF */ diff --git a/drivers/filesystems/cdfs/close.c b/drivers/filesystems/cdfs/close.c index eaf645d9c8e..fecb1e6dbfb 100644 --- a/drivers/filesystems/cdfs/close.c +++ b/drivers/filesystems/cdfs/close.c @@ -1,115 +1,1023 @@ -/* - * 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 *****************************************************************/ +Copyright (c) 1989-2000 Microsoft Corporation -#include "cdfs.h" +Module Name: -#define NDEBUG -#include + Close.c -/* FUNCTIONS ****************************************************************/ +Abstract: + This module implements the File Close routine for Cdfs called by the + Fsd/Fsp dispatch routines. + + The close operation interacts with both the async and delayed close queues + in the CdData structure. Since close may be called recursively we may + violate the locking order in acquiring the Vcb or Fcb. In this case + we may move the request to the async close queue. If this is the last + reference on the Fcb and there is a chance the user may reopen this + file again soon we would like to defer the close. In this case we + may move the request to the async close queue. + + Once we are past the decode file operation there is no need for the + file object. If we are moving the request to either of the work + queues then we remember all of the information from the file object and + complete the request with STATUS_SUCCESS. The Io system can then + reuse the file object and we can complete the request when convenient. + + The async close queue consists of requests which we would like to + complete as soon as possible. They are queued using the original + IrpContext where some of the fields have been overwritten with + information from the file object. We will extract this information, + cleanup the IrpContext and then call the close worker routine. + + The delayed close queue consists of requests which we would like to + defer the close for. We keep size of this list within a range + determined by the size of the system. We let it grow to some maximum + value and then shrink to some minimum value. We allocate a small + structure which contains the key information from the file object + and use this information along with an IrpContext on the stack + to complete the request. + + +--*/ + +#include "cdprocs.h" + +// +// The Bug check file id for this module +// + +#define BugCheckFileId (CDFS_BUG_CHECK_CLOSE) + +// +// Local support routines +// + +_Requires_lock_held_(_Global_critical_region_) +BOOLEAN +CdCommonClosePrivate ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _In_ PFCB Fcb, + _In_ ULONG UserReference, + _In_ BOOLEAN FromFsd + ); + +VOID +CdQueueClose ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PFCB Fcb, + _In_ ULONG UserReference, + _In_ BOOLEAN DelayedClose + ); + +PIRP_CONTEXT +CdRemoveClose ( + _In_opt_ PVCB Vcb + ); + +// Tell prefast this is a workitem routine +IO_WORKITEM_ROUTINE CdCloseWorker; + +VOID +NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ +CdCloseWorker ( + _In_ PDEVICE_OBJECT DeviceObject, + _In_opt_ PVOID Context + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, CdFspClose) +#pragma alloc_text(PAGE, CdCommonClose) +#pragma alloc_text(PAGE, CdCommonClosePrivate) +#pragma alloc_text(PAGE, CdQueueClose) +#pragma alloc_text(PAGE, CdRemoveClose) +#pragma alloc_text(PAGE, CdCloseWorker) +#endif + + +VOID +CdFspClose ( + _In_opt_ PVCB Vcb + ) + +/*++ + +Routine Description: + + This routine is called to process the close queues in the CdData. If the + Vcb is passed then we want to remove all of the closes for this Vcb. + Otherwise we will do as many of the delayed closes as we need to do. + +Arguments: + + Vcb - If specified then we are looking for all of the closes for the + given Vcb. + +Return Value: + + None + +--*/ + +{ + PIRP_CONTEXT IrpContext; + IRP_CONTEXT StackIrpContext; + + THREAD_CONTEXT ThreadContext = {0}; + + PFCB Fcb; + ULONG UserReference; + + ULONG VcbHoldCount = 0; + PVCB CurrentVcb = NULL; + + BOOLEAN PotentialVcbTeardown = FALSE; + + PAGED_CODE(); + + FsRtlEnterFileSystem(); + + // + // Continue processing until there are no more closes to process. + // + + while ((IrpContext = CdRemoveClose( Vcb )) != NULL) { + + // + // If we don't have an IrpContext then use the one on the stack. + // Initialize it for this request. + // + + if (SafeNodeType( IrpContext ) != CDFS_NTC_IRP_CONTEXT ) { + + // + // Update the local values from the IrpContextLite. + // + + Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb; + UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference; + + // + // Update the stack irp context with the values from the + // IrpContextLite. + // + + CdInitializeStackIrpContext( &StackIrpContext, + (PIRP_CONTEXT_LITE) IrpContext ); + + // + // Free the IrpContextLite. + // + + CdFreeIrpContextLite( *(PVOID*)&IrpContext ); /* ReactOS Change: GCC "error: invalid lvalue in unary '&'" */ + + // + // Remember we have the IrpContext from the stack. + // + + IrpContext = &StackIrpContext; + + // + // Otherwise cleanup the existing IrpContext. + // + + } else { + + // + // Remember the Fcb and user reference count. + // + + Fcb = (PFCB) IrpContext->Irp; + IrpContext->Irp = NULL; + + UserReference = (ULONG) IrpContext->ExceptionStatus; + IrpContext->ExceptionStatus = STATUS_SUCCESS; + } + + _Analysis_assume_(Fcb != NULL && Fcb->Vcb != NULL); + + // + // We have an IrpContext. Now we need to set the top level thread + // context. + // + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS ); + + // + // If we were given a Vcb then there is a request on top of this. + // + + if (ARGUMENT_PRESENT( Vcb )) { + + ClearFlag( IrpContext->Flags, + IRP_CONTEXT_FLAG_TOP_LEVEL | IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS ); + } + + CdSetThreadContext( IrpContext, &ThreadContext ); + + // + // If we have hit the maximum number of requests to process without + // releasing the Vcb then release the Vcb now. If we are holding + // a different Vcb to this one then release the previous Vcb. + // + // In either case acquire the current Vcb. + // + // We use the MinDelayedCloseCount from the CdData since it is + // a convenient value based on the system size. Only thing we are trying + // to do here is prevent this routine starving other threads which + // may need this Vcb exclusively. + // + // Note that the check for potential teardown below is unsafe. We'll + // repeat later within the cddata lock. + // + + PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) && + (Fcb->Vcb->VcbCondition != VcbMounted) && + (Fcb->Vcb->VcbCondition != VcbMountInProgress) && + (Fcb->Vcb->VcbCleanup == 0); + + if (PotentialVcbTeardown || + (VcbHoldCount > CdData.MinDelayedCloseCount) || + (Fcb->Vcb != CurrentVcb)) { + + if (CurrentVcb != NULL) { + + CdReleaseVcb( IrpContext, CurrentVcb ); + } + + if (PotentialVcbTeardown) { + + CdAcquireCdData( IrpContext ); + + // + // Repeat the checks with global lock held. The volume could have + // been remounted while we didn't hold the lock. + // + + PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) && + (Fcb->Vcb->VcbCondition != VcbMounted) && + (Fcb->Vcb->VcbCondition != VcbMountInProgress) && + (Fcb->Vcb->VcbCleanup == 0); + + if (!PotentialVcbTeardown) { + + CdReleaseCdData( IrpContext); + } + } + + CurrentVcb = Fcb->Vcb; + + _Analysis_assume_( CurrentVcb != NULL ); + + CdAcquireVcbShared( IrpContext, CurrentVcb, FALSE ); + + VcbHoldCount = 0; + + } else { + + VcbHoldCount += 1; + } + + // + // Call our worker routine to perform the close operation. + // + + CdCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE ); + + // + // If the reference count on this Vcb is below our residual reference + // then check if we should dismount the volume. + // + + if (PotentialVcbTeardown) { + + CdReleaseVcb( IrpContext, CurrentVcb ); + CdCheckForDismount( IrpContext, CurrentVcb, FALSE ); + + CurrentVcb = NULL; + + CdReleaseCdData( IrpContext ); + PotentialVcbTeardown = FALSE; + } + + // + // Complete the current request to cleanup the IrpContext. + // + + CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); + } + + // + // Release any Vcb we may still hold. + // + + if (CurrentVcb != NULL) { + + CdReleaseVcb( IrpContext, CurrentVcb ); + + } + +#ifdef _MSC_VER +#pragma prefast(suppress:26165, "Esp:1153") +#endif + FsRtlExitFileSystem(); +} + +_Requires_lock_held_(_Global_critical_region_) NTSTATUS -CdfsCloseFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject) - /* - * FUNCTION: Closes a file - */ +CdCommonClose ( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This routine is the Fsd entry for the close operation. We decode the file + object to find the CDFS structures and type of open. We call our internal + worker routine to perform the actual work. If the work wasn't completed + then we post to one of our worker queues. The Ccb isn't needed after this + point so we delete the Ccb and return STATUS_SUCCESS to our caller in all + cases. + +Arguments: + + Irp - Supplies the Irp to process + +Return Value: + + STATUS_SUCCESS + +--*/ + { + TYPE_OF_OPEN TypeOfOpen; + + PVCB Vcb; + PFCB Fcb; PCCB Ccb; + ULONG UserReference = 0; - DPRINT("CdfsCloseFile(DeviceExt %p, FileObject %p)\n", - DeviceExt, - FileObject); + BOOLEAN PotentialVcbTeardown = FALSE; - Ccb = (PCCB)(FileObject->FsContext2); + PAGED_CODE(); - DPRINT("Ccb %p\n", Ccb); - if (Ccb == NULL) - { - return(STATUS_SUCCESS); + ASSERT_IRP_CONTEXT( IrpContext ); + ASSERT_IRP( Irp ); + + // + // If we were called with our file system device object instead of a + // volume device object, just complete this request with STATUS_SUCCESS. + // + + if (IrpContext->Vcb == NULL) { + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); + return STATUS_SUCCESS; } - FileObject->FsContext2 = NULL; + // + // Decode the file object to get the type of open and Fcb/Ccb. + // - 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); + TypeOfOpen = CdDecodeFileObject( IrpContext, + IoGetCurrentIrpStackLocation( Irp )->FileObject, + &Fcb, + &Ccb ); + + // + // No work to do for unopened file objects. + // + + if (TypeOfOpen == UnopenedFileObject) { + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); + + return STATUS_SUCCESS; } - if (Ccb->DirectorySearchPattern.Buffer) - { - ExFreePoolWithTag(Ccb->DirectorySearchPattern.Buffer, CDFS_SEARCH_PATTERN_TAG); - } - ExFreePoolWithTag(Ccb, CDFS_CCB_TAG); + Vcb = Fcb->Vcb; - return(STATUS_SUCCESS); + // + // Clean up any CCB associated with this open. + // + + if (Ccb != NULL) { + + UserReference = 1; + + // + // We can always deallocate the Ccb if present. + // + + CdDeleteCcb( IrpContext, Ccb ); + } + + // + // If this is the last reference to a user file or directory on a + // currently mounted volume, then post it to the delayed close queue. Note + // that the VcbCondition check is unsafe, but it doesn't really matter - + // we just might delay the volume teardown a little by posting this close. + // + + if ((Vcb->VcbCondition == VcbMounted) && + (Fcb->FcbReference == 1) && + ((TypeOfOpen == UserFileOpen) || + (TypeOfOpen == UserDirectoryOpen))) { + + CdQueueClose( IrpContext, Fcb, UserReference, TRUE ); + IrpContext = NULL; + + // + // Otherwise try to process this close. Post to the async close queue + // if we can't acquire all of the resources. + // + + } + else { + + // + // If we may be dismounting this volume then acquire the CdData + // resource. + // + // Since we now must make volumes go away as soon as reasonable after + // the last user handles closes, key off of the cleanup count. It is + // OK to do this more than neccesary. Since this Fcb could be holding + // a number of other Fcbs (and thus their references), a simple check + // on reference count is not appropriate. + // + // Do an unsafe check first to avoid taking the (global) cddata lock in the + // common case. + // + + if ((Vcb->VcbCleanup == 0) && + (Vcb->VcbCondition != VcbMounted)) { + + // + // Possible dismount. Acquire CdData to synchronise with the remount path + // before looking at the vcb condition again. + // + + CdAcquireCdData( IrpContext ); + + if ((Vcb->VcbCleanup == 0) && + (Vcb->VcbCondition != VcbMounted) && + (Vcb->VcbCondition != VcbMountInProgress) && + FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS )) { + + PotentialVcbTeardown = TRUE; + } + else { + + // + // We can't dismount this volume now, there are other references or + // it's just been remounted. + // + } + + // + // Drop the global lock if we don't need it anymore. + // + + if (!PotentialVcbTeardown) { + + CdReleaseCdData( IrpContext ); + } + } + + // + // Call the worker routine to perform the actual work. This routine + // should never raise except for a fatal error. + // + + if (!CdCommonClosePrivate( IrpContext, Vcb, Fcb, UserReference, TRUE )) { + + // + // If we didn't complete the request then post the request as needed. + // + + CdQueueClose( IrpContext, Fcb, UserReference, FALSE ); + IrpContext = NULL; + + // + // Check whether we should be dismounting the volume and then complete + // the request. + // + + } + else if (PotentialVcbTeardown) { + + CdCheckForDismount( IrpContext, Vcb, FALSE ); + } + } + + // + // Always complete this request with STATUS_SUCCESS. + // + + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); + + if (PotentialVcbTeardown) { + + CdReleaseCdData( IrpContext ); + } + + // + // Always return STATUS_SUCCESS for closes. + // + + return STATUS_SUCCESS; } + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +BOOLEAN +CdCommonClosePrivate ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _In_ PFCB Fcb, + _In_ ULONG UserReference, + _In_ BOOLEAN FromFsd + ) + +/*++ + +Routine Description: + + This is the worker routine for the close operation. We can be called in + an Fsd thread or from a worker Fsp thread. If called from the Fsd thread + then we acquire the resources without waiting. Otherwise we know it is + safe to wait. + + We check to see whether we should post this request to the delayed close + queue. If we are to process the close here then we acquire the Vcb and + Fcb. We will adjust the counts and call our teardown routine to see + if any of the structures should go away. + +Arguments: + + Vcb - Vcb for this volume. + + Fcb - Fcb for this request. + + UserReference - Number of user references for this file object. This is + zero for an internal stream. + + FromFsd - This request was called from an Fsd thread. Indicates whether + we should wait to acquire resources. + + DelayedClose - Address to store whether we should try to put this on + the delayed close queue. Ignored if this routine can process this + close. + +Return Value: + + BOOLEAN - TRUE if this thread processed the close, FALSE otherwise. + +--*/ -NTSTATUS NTAPI -CdfsClose( - PCDFS_IRP_CONTEXT IrpContext) { - PIRP Irp; - PDEVICE_OBJECT DeviceObject; - PDEVICE_EXTENSION DeviceExtension; - PIO_STACK_LOCATION Stack; - PFILE_OBJECT FileObject; - NTSTATUS Status; + BOOLEAN RemovedFcb; - DPRINT("CdfsClose() called\n"); + PAGED_CODE(); - ASSERT(IrpContext); + ASSERT_IRP_CONTEXT( IrpContext ); + ASSERT_FCB( Fcb ); - Irp = IrpContext->Irp; - DeviceObject = IrpContext->DeviceObject; - Stack = IrpContext->Stack; + // + // Try to acquire the Vcb and Fcb. If we can't acquire them then return + // and let our caller know he should post the request to the async + // queue. + // - if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject) - { - DPRINT("Closing file system\n"); - Status = STATUS_SUCCESS; - goto ByeBye; + if (CdAcquireVcbShared( IrpContext, Vcb, FromFsd )) { + + if (!CdAcquireFcbExclusive( IrpContext, Fcb, FromFsd )) { + + // + // We couldn't get the Fcb. Release the Vcb and let our caller + // know to post this request. + // + + CdReleaseVcb( IrpContext, Vcb ); + return FALSE; + } + + // + // We didn't get the Vcb. Let our caller know to post this request. + // + + } else { + + return FALSE; } - FileObject = Stack->FileObject; - DeviceExtension = DeviceObject->DeviceExtension; + // + // Lock the Vcb and decrement the reference counts. + // - Status = CdfsCloseFile(DeviceExtension,FileObject); + CdLockVcb( IrpContext, Vcb ); + CdDecrementReferenceCounts( IrpContext, Fcb, 1, UserReference ); + CdUnlockVcb( IrpContext, Vcb ); -ByeBye: - Irp->IoStatus.Information = 0; + // + // Call our teardown routine to see if this object can go away. + // If we don't remove the Fcb then release it. + // - return(Status); + CdTeardownStructures( IrpContext, Fcb, &RemovedFcb ); + + if (!RemovedFcb) { + + CdReleaseFcb( IrpContext, Fcb ); + } + else { + _Analysis_assume_lock_not_held_(Fcb->FcbNonpaged->FcbResource); + } + + // + // Release the Vcb and return to our caller. Let him know we completed + // this request. + // + + CdReleaseVcb( IrpContext, Vcb ); + + return TRUE; } -/* EOF */ +VOID +NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ +CdCloseWorker ( + _In_ PDEVICE_OBJECT DeviceObject, + _In_opt_ PVOID Context + ) +/*++ + +Routine Description: + + Worker routine to call CsFspClose. + +Arguments: + + DeviceObject - Filesystem registration device object + + Context - Callers context + +Return Value: + + None + +--*/ + +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER( DeviceObject ); + UNREFERENCED_PARAMETER( Context ); + + CdFspClose (NULL); +} + + +VOID +CdQueueClose ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PFCB Fcb, + _In_ ULONG UserReference, + _In_ BOOLEAN DelayedClose + ) + +/*++ + +Routine Description: + + This routine is called to queue a request to either the async or delayed + close queue. For the delayed queue we need to allocate a smaller + structure to contain the information about the file object. We do + that so we don't put the larger IrpContext structures into this long + lived queue. If we can allocate this structure then we put this + on the async queue instead. + +Arguments: + + Fcb - Fcb for this file object. + + UserReference - Number of user references for this file object. This is + zero for an internal stream. + + DelayedClose - Indicates whether this should go on the async or delayed + close queue. + +Return Value: + + None + +--*/ + +{ + PIRP_CONTEXT_LITE IrpContextLite = NULL; + BOOLEAN StartWorker = FALSE; + + PAGED_CODE(); + + ASSERT_IRP_CONTEXT( IrpContext ); + ASSERT_FCB( Fcb ); + + // + // Start with the delayed queue request. We can move this to the async + // queue if there is an allocation failure. + // + + if (DelayedClose) { + + // + // Try to allocate non-paged pool for the IRP_CONTEXT_LITE. + // + + IrpContextLite = CdCreateIrpContextLite( IrpContext ); + } + + // + // We want to clear the top level context in this thread if + // necessary. Call our cleanup routine to do the work. + // + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); + CdCleanupIrpContext( IrpContext, TRUE ); + + // + // Synchronize with the CdData lock. + // + + CdLockCdData(); + + // + // If we have an IrpContext then put the request on the delayed close queue. + // + + if (IrpContextLite != NULL) { + + // + // Initialize the IrpContextLite. + // + + IrpContextLite->NodeTypeCode = CDFS_NTC_IRP_CONTEXT_LITE; + IrpContextLite->NodeByteSize = sizeof( IRP_CONTEXT_LITE ); + IrpContextLite->Fcb = Fcb; + IrpContextLite->UserReference = UserReference; + IrpContextLite->RealDevice = IrpContext->RealDevice; + + // + // Add this to the delayed close list and increment + // the count. + // + + InsertTailList( &CdData.DelayedCloseQueue, + &IrpContextLite->DelayedCloseLinks ); + + CdData.DelayedCloseCount += 1; + + // + // If we are above our threshold then start the delayed + // close operation. + // + + if (CdData.DelayedCloseCount > CdData.MaxDelayedCloseCount) { + + CdData.ReduceDelayedClose = TRUE; + + if (!CdData.FspCloseActive) { + + CdData.FspCloseActive = TRUE; + StartWorker = TRUE; + } + } + + // + // Unlock the CdData. + // + + CdUnlockCdData(); + + // + // Cleanup the IrpContext. + // + + CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); + + // + // Otherwise drop into the async case below. + // + + } else { + + // + // Store the information about the file object into the IrpContext. + // + + IrpContext->Irp = (PIRP) Fcb; + IrpContext->ExceptionStatus = (NTSTATUS) UserReference; + + // + // Add this to the async close list and increment the count. + // + + InsertTailList( &CdData.AsyncCloseQueue, + &IrpContext->WorkQueueItem.List ); + + CdData.AsyncCloseCount += 1; + + // + // Remember to start the Fsp close thread if not currently started. + // + + if (!CdData.FspCloseActive) { + + CdData.FspCloseActive = TRUE; + + StartWorker = TRUE; + } + + // + // Unlock the CdData. + // + + CdUnlockCdData(); + } + + // + // Start the FspClose thread if we need to. + // + + if (StartWorker) { + + IoQueueWorkItem( CdData.CloseItem, CdCloseWorker, CriticalWorkQueue, NULL ); + } + + // + // Return to our caller. + // + + return; +} + + +// +// Local support routine +// + +PIRP_CONTEXT +CdRemoveClose ( + _In_opt_ PVCB Vcb + ) + +/*++ + +Routine Description: + +Arguments: + + This routine is called to scan the async and delayed close queues looking + for a suitable entry. If the Vcb is specified then we scan both queues + looking for an entry with the same Vcb. Otherwise we will look in the + async queue first for any close item. If none found there then we look + in the delayed close queue provided that we have triggered the delayed + close operation. + +Return Value: + + PIRP_CONTEXT - NULL if no work item found. Otherwise it is the pointer to + either the IrpContext or IrpContextLite for this request. + +--*/ + +{ + PIRP_CONTEXT IrpContext = NULL; + PIRP_CONTEXT NextIrpContext; + PIRP_CONTEXT_LITE NextIrpContextLite; + + PLIST_ENTRY Entry; + + PAGED_CODE(); + + ASSERT_OPTIONAL_VCB( Vcb ); + + // + // Lock the CdData to perform the scan. + // + + CdLockCdData(); + + // + // First check the list of async closes. + // + + Entry = CdData.AsyncCloseQueue.Flink; + + while (Entry != &CdData.AsyncCloseQueue) { + + // + // Extract the IrpContext. + // + + NextIrpContext = CONTAINING_RECORD( Entry, + IRP_CONTEXT, + WorkQueueItem.List ); + + // + // If no Vcb was specified or this Vcb is for our volume + // then perform the close. + // + + if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContext->Vcb == Vcb)) { + + RemoveEntryList( Entry ); + CdData.AsyncCloseCount -= 1; + + IrpContext = NextIrpContext; + break; + } + + // + // Move to the next entry. + // + + Entry = Entry->Flink; + } + + // + // If we didn't find anything look through the delayed close + // queue. + // + // We will only check the delayed close queue if we were given + // a Vcb or the delayed close operation is active. + // + + if ((IrpContext == NULL) && + (ARGUMENT_PRESENT( Vcb ) || + (CdData.ReduceDelayedClose && + (CdData.DelayedCloseCount > CdData.MinDelayedCloseCount)))) { + + Entry = CdData.DelayedCloseQueue.Flink; + + while (Entry != &CdData.DelayedCloseQueue) { + + // + // Extract the IrpContext. + // + + NextIrpContextLite = CONTAINING_RECORD( Entry, + IRP_CONTEXT_LITE, + DelayedCloseLinks ); + + // + // If no Vcb was specified or this Vcb is for our volume + // then perform the close. + // + + if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContextLite->Fcb->Vcb == Vcb)) { + + RemoveEntryList( Entry ); + CdData.DelayedCloseCount -= 1; + + IrpContext = (PIRP_CONTEXT) NextIrpContextLite; + break; + } + + // + // Move to the next entry. + // + + Entry = Entry->Flink; + } + } + + // + // If the Vcb wasn't specified and we couldn't find an entry + // then turn off the Fsp thread. + // + + if (!ARGUMENT_PRESENT( Vcb ) && (IrpContext == NULL)) { + + CdData.FspCloseActive = FALSE; + CdData.ReduceDelayedClose = FALSE; + } + + // + // Unlock the CdData. + // + + CdUnlockCdData(); + + return IrpContext; +} + + + diff --git a/drivers/filesystems/cdfs/common.c b/drivers/filesystems/cdfs/common.c deleted file mode 100644 index 38e4b5fca72..00000000000 --- a/drivers/filesystems/cdfs/common.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs/create.c b/drivers/filesystems/cdfs/create.c index 704a4cfc917..1fb744139e1 100644 --- a/drivers/filesystems/cdfs/create.c +++ b/drivers/filesystems/cdfs/create.c @@ -1,297 +1,2972 @@ -/* - * 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 *****************************************************************/ +Copyright (c) 1989-2000 Microsoft Corporation -#include "cdfs.h" +Module Name: -#define NDEBUG -#include + Create.c -/* FUNCTIONS ****************************************************************/ +Abstract: + + This module implements the File Create routine for Cdfs called by the + Fsd/Fsp dispatch routines. + + +--*/ + +#include "cdprocs.h" + +// +// The Bug check file id for this module +// + +#define BugCheckFileId (CDFS_BUG_CHECK_CREATE) + +// +// Local support routines +// + +_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_)) +_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_)) +_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_)) +_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_)) +NTSTATUS +CdNormalizeFileNames ( + _Inout_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _In_ BOOLEAN OpenByFileId, + _In_ BOOLEAN IgnoreCase, + _In_ TYPE_OF_OPEN RelatedTypeOfOpen, + PCCB RelatedCcb, + PUNICODE_STRING RelatedFileName, + _Inout_ PUNICODE_STRING FileName, + _Inout_ PCD_NAME RemainingName + ); + +_Requires_lock_held_(_Global_critical_region_) +_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) +NTSTATUS +CdOpenByFileId ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb + ); + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdOpenExistingFcb ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _Inout_ PFCB *CurrentFcb, + _In_ TYPE_OF_OPEN TypeOfOpen, + _In_ BOOLEAN IgnoreCase, + _In_opt_ PCCB RelatedCcb + ); + +_Requires_lock_held_(_Global_critical_region_) +_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) +NTSTATUS +CdOpenDirectoryFromPathEntry ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ PCD_NAME DirName, + _In_ BOOLEAN IgnoreCase, + _In_ BOOLEAN ShortNameMatch, + _In_ PPATH_ENTRY PathEntry, + _In_ BOOLEAN PerformUserOpen, + _In_opt_ PCCB RelatedCcb + ); + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdOpenFileFromFileContext ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ PCD_NAME FileName, + _In_ BOOLEAN IgnoreCase, + _In_ BOOLEAN ShortNameMatch, + _In_ PFILE_ENUM_CONTEXT FileContext, + _In_opt_ PCCB RelatedCcb + ); + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdCompleteFcbOpen ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ TYPE_OF_OPEN TypeOfOpen, + _In_ ULONG UserCcbFlags, + _In_ ACCESS_MASK DesiredAccess + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, CdCommonCreate) +#pragma alloc_text(PAGE, CdCompleteFcbOpen) +#pragma alloc_text(PAGE, CdNormalizeFileNames) +#pragma alloc_text(PAGE, CdOpenByFileId) +#pragma alloc_text(PAGE, CdOpenDirectoryFromPathEntry) +#pragma alloc_text(PAGE, CdOpenExistingFcb) +#pragma alloc_text(PAGE, CdOpenFileFromFileContext) +#endif + + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +#ifdef _MSC_VER +#pragma prefast(suppress:26165, "Esp:1153") +#endif +CdCommonCreate ( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This is the common routine for opening a file called by both the + Fsp and Fsd threads. + + The file can be opened either by name or by file Id either with or without + a relative name. The file name field in the file object passed to this routine + contains either a unicode string or a 64 bit value which is the file Id. + If this is not a Joliet disk then we will convert the unicode name to + an Oem string in this routine. If there is a related file object with + a name then we will already have converted that name to Oem. + + We will store the full name for the file in the file object on a successful + open. We will allocate a larger buffer if necessary and combine the + related and file object names. The only exception is the relative open + when the related file object is for an OpenByFileId file. If we need to + allocate a buffer for a case insensitive name then we allocate it at + the tail of the buffer we will store into the file object. The upcased + portion will begin immediately after the name defined by the FileName + in the file object. + + Once we have the full name in the file object we don't want to split the + name in the event of a retry. We use a flag in the IrpContext to indicate + that the name has been split. + +Arguments: + + Irp - Supplies the Irp to process + +Return Value: + + NTSTATUS - This is the status from this open operation. + +--*/ -static NTSTATUS -CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject, - PUNICODE_STRING RelativeFileName, - PUNICODE_STRING AbsoluteFileName) { - USHORT Length; - PFCB Fcb; - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); - 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"); + COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ + BOOLEAN CleanupCompoundPathEntry = FALSE; - DeviceExt = DeviceObject->DeviceExtension; - ASSERT(DeviceExt); - Stack = IoGetCurrentIrpStackLocation (Irp); - ASSERT(Stack); + FILE_ENUM_CONTEXT FileContext = {0}; + BOOLEAN CleanupFileContext = FALSE; + BOOLEAN FoundEntry; - RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); - RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; - DPRINT("RequestedDisposition %x, RequestedOptions %x\n", - RequestedDisposition, RequestedOptions); + PVCB Vcb; - FileObject = Stack->FileObject; + BOOLEAN OpenByFileId; + BOOLEAN IgnoreCase; + ULONG CreateDisposition; - if (RequestedDisposition == FILE_CREATE || - RequestedDisposition == FILE_OVERWRITE_IF || - RequestedDisposition == FILE_SUPERSEDE) - { - return STATUS_ACCESS_DENIED; - } + BOOLEAN ShortNameMatch; + ULONG ShortNameDirentOffset; - Status = CdfsOpenFile(DeviceExt, - FileObject, - &FileObject->FileName); - if (NT_SUCCESS(Status)) - { - Fcb = FileObject->FsContext; + BOOLEAN VolumeOpen = FALSE; - /* 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; - } + // + // We will be acquiring and releasing file Fcb's as we move down the + // directory tree during opens. At any time we need to know the deepest + // point we have traversed down in the tree in case we need to cleanup + // any structures created here. + // + // CurrentFcb - represents this point. If non-null it means we have + // acquired it and need to release it in finally clause. + // + // NextFcb - represents the NextFcb to walk to but haven't acquired yet. + // - if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb)) - { - CdfsCloseFile (DeviceExt, FileObject); - return STATUS_NOT_A_DIRECTORY; - } + TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject; + PFILE_OBJECT RelatedFileObject; + PCCB RelatedCcb = NULL; - DeviceExt->OpenHandleCount++; - } + PFCB NextFcb; + PFCB CurrentFcb = NULL; - /* - * If the directory containing the file to open doesn't exist then - * fail immediately - */ - Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0; + // + // During the open we need to combine the related file object name + // with the remaining name. We also may need to upcase the file name + // in order to do a case-insensitive name comparison. We also need + // to restore the name in the file object in the event that we retry + // the request. We use the following string variables to manage the + // name. We will can put these strings into either Unicode or Ansi + // form. + // + // FileName - Pointer to name as currently stored in the file + // object. We store the full name into the file object early in + // the open operation. + // + // RelatedFileName - Pointer to the name in the related file object. + // + // RemainingName - String containing remaining name to parse. + // + // MatchingName - Address of name structure in FileContext which matched. + // We need this to know whether we matched the long or short name. + // - return Status; -} + PUNICODE_STRING FileName; + PUNICODE_STRING RelatedFileName = NULL; + CD_NAME RemainingName = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ + CD_NAME FinalName; + PCD_NAME MatchingName = NULL; -NTSTATUS NTAPI -CdfsCreate( - PCDFS_IRP_CONTEXT IrpContext) -{ - PDEVICE_OBJECT DeviceObject; - PDEVICE_EXTENSION DeviceExt; - NTSTATUS Status; + PAGED_CODE(); - DPRINT("CdfsCreate()\n"); + // + // If we were called with our file system device object instead of a + // volume device object, just complete this request with STATUS_SUCCESS. + // - ASSERT(IrpContext); + if (IrpContext->Vcb == NULL) { - 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++; + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; } - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, - TRUE); - Status = CdfsCreateFile(DeviceObject, - IrpContext->Irp); - ExReleaseResourceLite(&DeviceExt->DirResource); - KeLeaveCriticalRegion(); + // + // Get create parameters from the Irp. + // + + OpenByFileId = BooleanFlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID ); + IgnoreCase = !BooleanFlagOn( IrpSp->Flags, SL_CASE_SENSITIVE ); + CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff; + + // + // Do some preliminary checks to make sure the operation is supported. + // We fail in the following cases immediately. + // + // - Open a paging file. + // - Open a target directory. + // - Open a file with Eas. + // - Create a file. + // + + if (FlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE | SL_OPEN_TARGET_DIRECTORY) || + (IrpSp->Parameters.Create.EaLength != 0) || + (CreateDisposition == FILE_CREATE)) { + + CdCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED ); + return STATUS_ACCESS_DENIED; + } + +#if (NTDDI_VERSION >= NTDDI_WIN7) + // + // CDFS does not support FILE_OPEN_REQUIRING_OPLOCK + // + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_REQUIRING_OPLOCK )) { + + CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); + return STATUS_INVALID_PARAMETER; + } +#endif + + // + // Copy the Vcb to a local. Assume the starting directory is the root. + // + + Vcb = IrpContext->Vcb; + NextFcb = Vcb->RootIndexFcb; + + // + // Reference our input parameters to make things easier + // + + FileObject = IrpSp->FileObject; + RelatedFileObject = NULL; + + FileName = &FileObject->FileName; + + // + // Set up the file object's Vpb pointer in case anything happens. + // This will allow us to get a reasonable pop-up. + // + + if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) { + + RelatedFileObject = FileObject->RelatedFileObject; + FileObject->Vpb = RelatedFileObject->Vpb; + + RelatedTypeOfOpen = CdDecodeFileObject( IrpContext, RelatedFileObject, &NextFcb, &RelatedCcb ); + + // + // Fail the request if this is not a user file object. + // + + if (RelatedTypeOfOpen < UserVolumeOpen) { + + CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); + return STATUS_INVALID_PARAMETER; + } + + // + // Remember the name in the related file object. + // + + RelatedFileName = &RelatedFileObject->FileName; + } + + // + // If we haven't initialized the names then make sure the strings are valid. + // If this an OpenByFileId then verify the file id buffer. + // + // After this routine returns we know that the full name is in the + // FileName buffer and the buffer will hold the upcased portion + // of the name yet to parse immediately after the full name in the + // buffer. Any trailing backslash has been removed and the flag + // in the IrpContext will indicate whether we removed the + // backslash. + // + + Status = CdNormalizeFileNames( IrpContext, + Vcb, + OpenByFileId, + IgnoreCase, + RelatedTypeOfOpen, + RelatedCcb, + RelatedFileName, + FileName, + &RemainingName ); + + // + // Return the error code if not successful. + // + + if (!NT_SUCCESS( Status )) { + + CdCompleteRequest( IrpContext, Irp, Status ); + return Status; + } + + // + // We want to acquire the Vcb. Exclusively for a volume open, shared otherwise. + // The file name is empty for a volume open. + // + + if ((FileName->Length == 0) && + (RelatedTypeOfOpen <= UserVolumeOpen) && + !OpenByFileId) { + + VolumeOpen = TRUE; + CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); + + } else { + + CdAcquireVcbShared( IrpContext, Vcb, FALSE ); + } + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Verify that the Vcb is not in an unusable condition. This routine + // will raise if not usable. + // + + CdVerifyVcb( IrpContext, Vcb ); + + // + // If the Vcb is locked then we cannot open another file + // + + if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + // + // If we are opening this file by FileId then process this immediately + // and exit. + // + + if (OpenByFileId) { + + // + // We only allow Dasd opens of audio disks. Fail this request at + // this point. + // + + if (FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) { + + try_return( Status = STATUS_INVALID_DEVICE_REQUEST ); + } + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + // + // Make sure we can wait for this request. + // + + if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { + + CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); + } + + try_return( Status = CdOpenByFileId( IrpContext, + IrpSp, + Vcb, + &CurrentFcb )); + } + + // + // If we are opening this volume Dasd then process this immediately + // and exit. + // + + if (VolumeOpen) { + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + // + // If they wanted to open a directory, surprise. + // + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { + + try_return( Status = STATUS_NOT_A_DIRECTORY ); + } + + // + // Acquire the Fcb first. + // + + CurrentFcb = Vcb->VolumeDasdFcb; + CdAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE ); + + try_return( Status = CdOpenExistingFcb( IrpContext, + IrpSp, + &CurrentFcb, + UserVolumeOpen, + FALSE, + NULL )); + } + + // + // At this point CurrentFcb points to the deepest Fcb for this open + // in the tree. Let's acquire this Fcb to keep it from being deleted + // beneath us. + // + + CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); + CurrentFcb = NextFcb; + + // + // Do a prefix search if there is more of the name to parse. + // + + if (RemainingName.FileName.Length != 0) { + + // + // Do the prefix search to find the longest matching name. + // + + CdFindPrefix( IrpContext, + &CurrentFcb, + &RemainingName.FileName, + IgnoreCase ); + } + + // + // If the remaining name length is zero then we have found our + // target. + // + + if (RemainingName.FileName.Length == 0) { + + // + // If this is a file so verify the user didn't want to open + // a directory. + // + + if (SafeNodeType( CurrentFcb ) == CDFS_NTC_FCB_DATA) { + + if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || + FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { + + try_return( Status = STATUS_NOT_A_DIRECTORY ); + } + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + try_return( Status = CdOpenExistingFcb( IrpContext, + IrpSp, + &CurrentFcb, + UserFileOpen, + IgnoreCase, + RelatedCcb )); + + // + // This is a directory. Verify the user didn't want to open + // as a file. + // + + } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { + + try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); + + // + // Open the file as a directory. + // + + } else { + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + try_return( Status = CdOpenExistingFcb( IrpContext, + IrpSp, + &CurrentFcb, + UserDirectoryOpen, + IgnoreCase, + RelatedCcb )); + } + } + + // + // We have more work to do. We have a starting Fcb which we own shared. + // We also have the remaining name to parse. Walk through the name + // component by component looking for the full name. + // + + // + // Our starting Fcb better be a directory. + // + + if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { + + try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); + } + + // + // If we can't wait then post this request. + // + + if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { + + CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); + } + + // + // Make sure the final name has no version string. + // + + FinalName.VersionString.Length = 0; + + while (TRUE) { + + ShortNameMatch = FALSE; + + // + // Split off the next component from the name. + // + + CdDissectName( IrpContext, + &RemainingName.FileName, + &FinalName.FileName ); + + // + // Go ahead and look this entry up in the path table. + // + + CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); + CleanupCompoundPathEntry = TRUE; + + FoundEntry = CdFindPathEntry( IrpContext, + CurrentFcb, + &FinalName, + IgnoreCase, + &CompoundPathEntry ); + + // + // If we didn't find the entry then check if the current name + // is a possible short name. + // + + if (!FoundEntry) { + + ShortNameDirentOffset = CdShortNameDirentOffset( IrpContext, &FinalName.FileName ); + + // + // If there is an embedded short name offset then look for the + // matching long name in the directory. + // + + if (ShortNameDirentOffset != MAXULONG) { + + if (CleanupFileContext) { + + CdCleanupFileContext( IrpContext, &FileContext ); + } + + CdInitializeFileContext( IrpContext, &FileContext ); + CleanupFileContext = TRUE; + + FoundEntry = CdFindFileByShortName( IrpContext, + CurrentFcb, + &FinalName, + IgnoreCase, + ShortNameDirentOffset, + &FileContext ); + + // + // If we found an entry and it is a directory then look + // this up in the path table. + // + + if (FoundEntry) { + + ShortNameMatch = TRUE; + + if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags, + CD_ATTRIBUTE_DIRECTORY )) { + + CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); + CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); + + FoundEntry = CdFindPathEntry( IrpContext, + CurrentFcb, + &FileContext.InitialDirent->Dirent.CdCaseFileName, + IgnoreCase, + &CompoundPathEntry ); + + // + // We better find this entry. + // + + if (!FoundEntry) { + + CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); + } + + // + // Upcase the name with the short name if case + // insensitive. + // + + if (IgnoreCase) { + + CdUpcaseName( IrpContext, &FinalName, &FinalName ); + } + + // + // We found a matching file. If we are at the last + // entry then break out of the loop and open the + // file below. Otherwise we return an error. + // + + } else if (RemainingName.FileName.Length == 0) { + + // + // Break out of the loop. We will process the dirent + // below. + // + + MatchingName = &FileContext.ShortName; + break; + + } else { + + try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); + } + } + } + + // + // We didn't find the name in either the path table or as + // a short name in a directory. If the remaining name + // length is zero then break out of the loop to search + // the directory. + // + + if (!FoundEntry) { + + if (RemainingName.FileName.Length == 0) { + + break; + + // + // Otherwise this path could not be cracked. + // + + } else { + + try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); + } + } + } + + // + // If this is an ignore case open then copy the exact case + // in the file object name. If it was a short name match then + // the name must be upcase already. + // + + if (IgnoreCase && !ShortNameMatch) { + + RtlCopyMemory( FinalName.FileName.Buffer, + CompoundPathEntry.PathEntry.CdDirName.FileName.Buffer, + CompoundPathEntry.PathEntry.CdDirName.FileName.Length ); + } + + // + // If we have found the last component then open this as a directory + // and return to our caller. + // + + if (RemainingName.FileName.Length == 0) { + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { + + try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); + } + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + try_return( Status = CdOpenDirectoryFromPathEntry( IrpContext, + IrpSp, + Vcb, + &CurrentFcb, + &FinalName, + IgnoreCase, + ShortNameMatch, + &CompoundPathEntry.PathEntry, + TRUE, + RelatedCcb )); + } + + // + // Otherwise open an Fcb for this intermediate index Fcb. + // + + CdOpenDirectoryFromPathEntry( IrpContext, + IrpSp, + Vcb, + &CurrentFcb, + &FinalName, + IgnoreCase, + ShortNameMatch, + &CompoundPathEntry.PathEntry, + FALSE, + NULL ); + + CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); + CleanupCompoundPathEntry = FALSE; + } + + // + // We need to scan the current directory for a matching file name + // if we don't already have one. + // + + if (!FoundEntry) { + + if (CleanupFileContext) { + + CdCleanupFileContext( IrpContext, &FileContext ); + } + + CdInitializeFileContext( IrpContext, &FileContext ); + CleanupFileContext = TRUE; + + // + // Split our search name into separate components. + // + + CdConvertNameToCdName( IrpContext, &FinalName ); + + FoundEntry = CdFindFile( IrpContext, + CurrentFcb, + &FinalName, + IgnoreCase, + &FileContext, + &MatchingName ); + } + + // + // If we didn't find a match then check if the name is invalid to + // determine which error code to return. + // + + if (!FoundEntry) { + + if ((CreateDisposition == FILE_OPEN) || + (CreateDisposition == FILE_OVERWRITE)) { + + try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND ); + } + + // + // Any other operation return STATUS_ACCESS_DENIED. + // + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + // + // If this is a directory then the disk is corrupt because it wasn't + // in the Path Table. + // + + if (FlagOn( FileContext.InitialDirent->Dirent.Flags, CD_ATTRIBUTE_DIRECTORY )) { + + CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR ); + } + + // + // Make sure our opener didn't want a directory. + // + + if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || + FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { + + try_return( Status = STATUS_NOT_A_DIRECTORY ); + } + + // + // The only create disposition we allow is OPEN. + // + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) { + + try_return( Status = STATUS_ACCESS_DENIED ); + } + + // + // If this is an ignore case open then copy the exact case + // in the file object name. Any version portion should + // already be upcased. + // + + if (IgnoreCase) { + + RtlCopyMemory( FinalName.FileName.Buffer, + MatchingName->FileName.Buffer, + MatchingName->FileName.Length ); + } + + // + // Open the file using the file context. We already have the + // first and last dirents. + // + + try_return( Status = CdOpenFileFromFileContext( IrpContext, + IrpSp, + Vcb, + &CurrentFcb, + &FinalName, + IgnoreCase, + (BOOLEAN) (MatchingName == &FileContext.ShortName), + &FileContext, + RelatedCcb )); + + try_exit: NOTHING; + } _SEH2_FINALLY { + + // + // Cleanup the PathEntry if initialized. + // + + if (CleanupCompoundPathEntry) { + + CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); + } + + // + // Cleanup the FileContext if initialized. + // + + if (CleanupFileContext) { + + CdCleanupFileContext( IrpContext, &FileContext ); + } + + // + // The result of this open could be success, pending or some error + // condition. + // + + if (_SEH2_AbnormalTermination()) { + + + // + // In the error path we start by calling our teardown routine if we + // have a CurrentFcb and its not the volume Dasd Fcb. + // + + if ((CurrentFcb != NULL) && + (CurrentFcb != Vcb->VolumeDasdFcb)) { + + BOOLEAN RemovedFcb; + + CdTeardownStructures( IrpContext, CurrentFcb, &RemovedFcb ); + + if (RemovedFcb) { + + CurrentFcb = NULL; + } + } + + // + // No need to complete the request. + // + + IrpContext = NULL; + Irp = NULL; + + // + // If we posted this request through the oplock package we need + // to show that there is no reason to complete the request. + // + + } else if (Status == STATUS_PENDING) { + + IrpContext = NULL; + Irp = NULL; + } + + // + // Release the Current Fcb if still acquired. + // + + if (CurrentFcb != NULL) { + _Analysis_assume_lock_held_(CurrentFcb->FcbNonpaged->FcbResource); + CdReleaseFcb( IrpContext, CurrentFcb ); + } + + // + // Release the Vcb. + // + + CdReleaseVcb( IrpContext, Vcb ); + + // + // Call our completion routine. It will handle the case where either + // the Irp and/or IrpContext are gone. + // + + CdCompleteRequest( IrpContext, Irp, Status ); + } _SEH2_END; return Status; } -/* EOF */ + +// +// Local support routine +// +_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_)) +_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_)) +_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_)) +_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_)) +NTSTATUS +CdNormalizeFileNames ( + _Inout_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _In_ BOOLEAN OpenByFileId, + _In_ BOOLEAN IgnoreCase, + _In_ TYPE_OF_OPEN RelatedTypeOfOpen, + PCCB RelatedCcb, + PUNICODE_STRING RelatedFileName, + _Inout_ PUNICODE_STRING FileName, + _Inout_ PCD_NAME RemainingName + ) + +/*++ + +Routine Description: + + This routine is called to store the full name and upcased name into the + filename buffer. We only upcase the portion yet to parse. We also + check for a trailing backslash and lead-in double backslashes. This + routine also verifies the mode of the related open against the name + currently in the filename. + +Arguments: + + Vcb - Vcb for this volume. + + OpenByFileId - Indicates if the filename should be a 64 bit FileId. + + IgnoreCase - Indicates if this open is a case-insensitive operation. + + RelatedTypeOfOpen - Indicates the type of the related file object. + + RelatedCcb - Ccb for the related open. Ignored if no relative open. + + RelatedFileName - FileName buffer for related open. Ignored if no + relative open. + + FileName - FileName to update in this routine. The name should + either be a 64-bit FileId or a Unicode string. + + RemainingName - Name with the remaining portion of the name. This + will begin after the related name and any separator. For a + non-relative open we also step over the initial separator. + +Return Value: + + NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code + otherwise. + +--*/ + +{ + ULONG RemainingNameLength = 0; + ULONG RelatedNameLength = 0; + ULONG SeparatorLength = 0; + + ULONG BufferLength; + + UNICODE_STRING NewFileName; + + PAGED_CODE(); + + // + // If this is the first pass then we need to build the full name and + // check for name compatibility. + // + + if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) { + + // + // Deal with the regular file name case first. + // + + if (!OpenByFileId) { + + // + // This is here because the Win32 layer can't avoid sending me double + // beginning backslashes. + // + + if ((FileName->Length > sizeof( WCHAR )) && + (FileName->Buffer[1] == L'\\') && + (FileName->Buffer[0] == L'\\')) { + + // + // If there are still two beginning backslashes, the name is bogus. + // + + if ((FileName->Length > 2 * sizeof( WCHAR )) && + (FileName->Buffer[2] == L'\\')) { + + return STATUS_OBJECT_NAME_INVALID; + } + + // + // Slide the name down in the buffer. + // + + FileName->Length -= sizeof( WCHAR ); + + RtlMoveMemory( FileName->Buffer, + FileName->Buffer + 1, + FileName->Length ); + } + + // + // Check for a trailing backslash. Don't strip off if only character + // in the full name or for relative opens where this is illegal. + // + + if (((FileName->Length > sizeof( WCHAR)) || + ((FileName->Length == sizeof( WCHAR )) && (RelatedTypeOfOpen == UserDirectoryOpen))) && + (FileName->Buffer[ (FileName->Length/2) - 1 ] == L'\\')) { + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ); + FileName->Length -= sizeof( WCHAR ); + } + + // + // Remember the length we need for this portion of the name. + // + + RemainingNameLength = FileName->Length; + + // + // If this is a related file object then we verify the compatibility + // of the name in the file object with the relative file object. + // + + if (RelatedTypeOfOpen != UnopenedFileObject) { + + // + // If the filename length was zero then it must be legal. + // If there are characters then check with the related + // type of open. + // + + if (FileName->Length != 0) { + + // + // The name length must always be zero for a volume open. + // + + if (RelatedTypeOfOpen <= UserVolumeOpen) { + + return STATUS_INVALID_PARAMETER; + + // + // The remaining name cannot begin with a backslash. + // + + } else if (FileName->Buffer[0] == L'\\' ) { + + return STATUS_INVALID_PARAMETER; + + // + // If the related file is a user file then there + // is no file with this path. + // + + } else if (RelatedTypeOfOpen == UserFileOpen) { + + return STATUS_OBJECT_PATH_NOT_FOUND; + } + } + + // + // Remember the length of the related name when building + // the full name. We leave the RelatedNameLength and + // SeparatorLength at zero if the relative file is opened + // by Id. + // + + if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { + + // + // Add a separator if the name length is non-zero + // unless the relative Fcb is at the root. + // + + if ((FileName->Length != 0) && + (RelatedCcb->Fcb != Vcb->RootIndexFcb)) { + + SeparatorLength = sizeof( WCHAR ); + } + + RelatedNameLength = RelatedFileName->Length; + } + + // + // The full name is already in the filename. It must either + // be length 0 or begin with a backslash. + // + + } else if (FileName->Length != 0) { + + if (FileName->Buffer[0] != L'\\') { + + return STATUS_INVALID_PARAMETER; + } + + // + // We will want to trim the leading backslash from the + // remaining name we return. + // + + RemainingNameLength -= sizeof( WCHAR ); + SeparatorLength = sizeof( WCHAR ); + } + + // + // Now see if the buffer is large enough to hold the full name. + // + + BufferLength = RelatedNameLength + SeparatorLength + RemainingNameLength; + + // + // Check for an overflow of the maximum filename size. + // + + if (BufferLength > MAXUSHORT) { + + return STATUS_INVALID_PARAMETER; + } + + // + // Now see if we need to allocate a new buffer. + // + + if (FileName->MaximumLength < BufferLength) { + + NewFileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool, + BufferLength, + TAG_FILE_NAME ); + + NewFileName.MaximumLength = (USHORT) BufferLength; + + } else { + + NewFileName.Buffer = FileName->Buffer; + NewFileName.MaximumLength = FileName->MaximumLength; + } + + // + // If there is a related name then we need to slide the remaining bytes up and + // insert the related name. Otherwise the name is in the correct position + // already. + // + + if (RelatedNameLength != 0) { + + // + // Store the remaining name in its correct position. + // + + if (RemainingNameLength != 0) { + + RtlMoveMemory( Add2Ptr( NewFileName.Buffer, RelatedNameLength + SeparatorLength, PVOID ), + FileName->Buffer, + RemainingNameLength ); + } + + RtlCopyMemory( NewFileName.Buffer, + RelatedFileName->Buffer, + RelatedNameLength ); + + // + // Add the separator if needed. + // + + if (SeparatorLength != 0) { + + *(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\'; + } + + // + // Update the filename value we got from the user. + // + + if (NewFileName.Buffer != FileName->Buffer) { + + if (FileName->Buffer != NULL) { + + CdFreePool( &FileName->Buffer ); + } + + FileName->Buffer = NewFileName.Buffer; + FileName->MaximumLength = NewFileName.MaximumLength; + } + + // + // Copy the name length to the user's filename. + // + + FileName->Length = (USHORT) (RelatedNameLength + SeparatorLength + RemainingNameLength); + } + + // + // Now update the remaining name to parse. + // + + RemainingName->FileName.MaximumLength = + RemainingName->FileName.Length = (USHORT) RemainingNameLength; + RemainingName->VersionString.Length = 0; + + RemainingName->FileName.Buffer = Add2Ptr( FileName->Buffer, + RelatedNameLength + SeparatorLength, + PWCHAR ); + + // + // Upcase the name if necessary. + // + + if (IgnoreCase && (RemainingNameLength != 0)) { + + CdUpcaseName( IrpContext, + RemainingName, + RemainingName ); + } + + // + // Do a quick check to make sure there are no wildcards. + // +#ifdef _MSC_VER +#pragma prefast(push) +#pragma prefast(suppress:26000, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).") +#endif + if (FsRtlDoesNameContainWildCards( &RemainingName->FileName )) { +#ifdef _MSC_VER +#pragma prefast(pop) +#endif + + return STATUS_OBJECT_NAME_INVALID; + } + + // + // For the open by file Id case we verify the name really contains + // a 64 bit value. + // + + } else { + + // + // Check for validity of the buffer. + // + + if (FileName->Length != sizeof( FILE_ID )) { + + return STATUS_INVALID_PARAMETER; + } + } + + SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME ); + + // + // If we are in the retry path then the full name is already in the + // file object name. If this is a case-sensitive operation then + // we need to upcase the name from the end of any related file name already stored + // there. + // + + } else { + + // + // Assume there is no relative name. + // + + RemainingName->FileName = *FileName; + RemainingName->VersionString.Length = 0; + + // + // Nothing to do if the name length is zero. + // + + if (RemainingName->FileName.Length != 0) { + + // + // If there is a relative name then we need to walk past it. + // + + if (RelatedTypeOfOpen != UnopenedFileObject) { + + // + // Nothing to walk past if the RelatedCcb is opened by FileId. + // + + + if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { + + // + // Related file name is a proper prefix of the full name. + // We step over the related name and if we are then + // pointing at a separator character we step over that. + // + + RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer, + RelatedFileName->Length, + PWCHAR ); + + RemainingName->FileName.Length -= RelatedFileName->Length; + } + } + + // + // If we are pointing at a separator character then step past that. + // + + if (RemainingName->FileName.Length != 0) { + + if (*(RemainingName->FileName.Buffer) == L'\\') { + + RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer, + sizeof( WCHAR ), + PWCHAR ); + + RemainingName->FileName.Length -= sizeof( WCHAR ); + } + } + } + + // + // Upcase the name if necessary. + // + + if (IgnoreCase && (RemainingName->FileName.Length != 0)) { + + CdUpcaseName( IrpContext, + RemainingName, + RemainingName ); + } + } + +#ifdef _MSC_VER +#pragma prefast(push) +#pragma prefast(suppress:26030, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).") +#endif + return STATUS_SUCCESS; +#ifdef _MSC_VER +#pragma prefast(pop) +#endif +} + + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) +NTSTATUS +CdOpenByFileId ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb + ) + +/*++ + +Routine Description: + + This routine is called to open a file by the FileId. The file Id is in + the FileObject name buffer and has been verified to be 64 bits. + + We extract the Id number and then check to see whether we are opening a + file or directory and compare that with the create options. If this + generates no error then optimistically look up the Fcb in the Fcb Table. + + If we don't find the Fcb then we need to carefully verify there is a file + at this offset. First check whether the Parent Fcb is in the table. If + not then lookup the parent at the path table offset given by file ID. + + If found then build the Fcb from this entry and store the new Fcb in the + tree. + + We know have the parent Fcb. Do a directory scan to find the dirent at + the given offset in this stream. This must point to the first entry + of a valid file. + + Finally we call our worker routine to complete the open on this Fcb. + +Arguments: + + IrpSp - Stack location within the create Irp. + + Vcb - Vcb for this volume. + + CurrentFcb - Address to store the Fcb for this open. We only store the + CurrentFcb here when we have acquired it so our caller knows to + free or deallocate it. + +Return Value: + + NTSTATUS - Status indicating the result of the operation. + +--*/ + +{ + NTSTATUS Status = STATUS_ACCESS_DENIED; + + BOOLEAN UnlockVcb = FALSE; + BOOLEAN Found; + + ULONG StreamOffset; + + NODE_TYPE_CODE NodeTypeCode; + TYPE_OF_OPEN TypeOfOpen; + + FILE_ENUM_CONTEXT FileContext; + BOOLEAN CleanupFileContext = FALSE; + + COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ + BOOLEAN CleanupCompoundPathEntry = FALSE; + + FILE_ID FileId; + FILE_ID ParentFileId; + + PFCB NextFcb; + + PAGED_CODE(); + + // + // Extract the FileId from the FileObject. + // + + RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID )); + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Go ahead and figure out the TypeOfOpen and NodeType. We can + // get these from the input FileId. + // + + if (CdFidIsDirectory( FileId )) { + + TypeOfOpen = UserDirectoryOpen; + NodeTypeCode = CDFS_NTC_FCB_INDEX; + + // + // If the offset isn't zero then the file Id is bad. + // + + if (CdQueryFidDirentOffset( FileId ) != 0) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + + } else { + + TypeOfOpen = UserFileOpen; + NodeTypeCode = CDFS_NTC_FCB_DATA; + } + + // + // Acquire the Vcb and check if there is already an Fcb. + // If not we will need to carefully verify the Fcb. + // We will post the request if we don't find the Fcb and this + // request can't wait. + // + + CdLockVcb( IrpContext, Vcb ); + UnlockVcb = TRUE; + + NextFcb = CdLookupFcbTable( IrpContext, Vcb, FileId ); + + if (NextFcb == NULL) { + + // + // Get the path table offset from the file id. + // + + StreamOffset = CdQueryFidPathTableOffset( FileId ); + + // + // Build the parent FileId for this and try looking it + // up in the PathTable. + // + + CdSetFidDirentOffset( ParentFileId, 0 ); + CdSetFidPathTableOffset( ParentFileId, StreamOffset ); + CdFidSetDirectory( ParentFileId ); + + NextFcb = CdLookupFcbTable( IrpContext, Vcb, ParentFileId ); + + // + // If not present then walk through the PathTable to this point. + // + + if (NextFcb == NULL) { + + CdUnlockVcb( IrpContext, Vcb ); + UnlockVcb = FALSE; + + // + // Check that the path table offset lies within the path + // table. + // + + if (StreamOffset > Vcb->PathTableFcb->FileSize.LowPart) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + + CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); + CleanupCompoundPathEntry = TRUE; + + // + // Start at the first entry in the PathTable. + // + + CdLookupPathEntry( IrpContext, + Vcb->PathTableFcb->StreamOffset, + 1, + TRUE, + &CompoundPathEntry ); + + // + // Continue looking until we have passed our target offset. + // + + while (TRUE) { + + // + // Move to the next entry. + // + + Found = CdLookupNextPathEntry( IrpContext, + &CompoundPathEntry.PathContext, + &CompoundPathEntry.PathEntry ); + + // + // If we didn't find the entry or are beyond it then the + // input Id is invalid. + // + + if (!Found || + (CompoundPathEntry.PathEntry.PathTableOffset > StreamOffset)) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + } + + // + // If the FileId specified a directory then we have found + // the entry. Make sure our caller wanted to open a directory. + // + + if ((TypeOfOpen == UserDirectoryOpen) && + FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { + + try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); + } + + // + // Lock the Vcb and create the Fcb if necessary. + // + + CdLockVcb( IrpContext, Vcb ); + UnlockVcb = TRUE; + + NextFcb = CdCreateFcb( IrpContext, ParentFileId, NodeTypeCode, &Found ); + + // + // It's possible that someone got in here ahead of us. + // + + if (!Found) { + + CdInitializeFcbFromPathEntry( IrpContext, + NextFcb, + NULL, + &CompoundPathEntry.PathEntry ); + } + + // + // If the user wanted to open a directory then we have found + // it. Store this Fcb into the CurrentFcb and skip the + // directory scan. + // + + if (TypeOfOpen == UserDirectoryOpen) { + + *CurrentFcb = NextFcb; + NextFcb = NULL; + } + } + + // + // Perform the directory scan if we don't already have our target. + // + + if (NextFcb != NULL) { + + // + // Acquire the parent. We currently own the Vcb lock so + // do this without waiting first. + // + + if (!CdAcquireFcbExclusive( IrpContext, + NextFcb, + TRUE )) { + + NextFcb->FcbReference += 1; + CdUnlockVcb( IrpContext, Vcb ); + + CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); + + CdLockVcb( IrpContext, Vcb ); + NextFcb->FcbReference -= 1; + CdUnlockVcb( IrpContext, Vcb ); + + } else { + + CdUnlockVcb( IrpContext, Vcb ); + } + + UnlockVcb = FALSE; + + // + // Set up the CurrentFcb pointers. We know there was + // no previous parent in this case. + // + + *CurrentFcb = NextFcb; + + // + // Calculate the offset in the stream. + // + + StreamOffset = CdQueryFidDirentOffset( FileId ); + + // + // Create the stream file if it doesn't exist. This will update + // the Fcb with the size from the self entry. + // + + CdVerifyOrCreateDirStreamFile( IrpContext, NextFcb); + + // + // If our offset is beyond the end of the directory then the + // FileId is invalid. + // + + if (StreamOffset > NextFcb->FileSize.LowPart) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + + // + // Otherwise position ourselves at the self entry and walk + // through dirent by dirent until this location is found. + // + + CdInitializeFileContext( IrpContext, &FileContext ); + CdLookupInitialFileDirent( IrpContext, + NextFcb, + &FileContext, + NextFcb->StreamOffset ); + + CleanupFileContext = TRUE; + + while (TRUE) { + + // + // Move to the first entry of the next file. + // + + Found = CdLookupNextInitialFileDirent( IrpContext, + NextFcb, + &FileContext ); + + // + // If we didn't find the entry or are beyond it then the + // input Id is invalid. + // + + if (!Found || + (FileContext.InitialDirent->Dirent.DirentOffset > StreamOffset)) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + } + + // + // This better not be a directory. Directory FileIds must + // refer to the self entry for directories. + // + + if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags, + CD_ATTRIBUTE_DIRECTORY )) { + + try_return( Status = STATUS_INVALID_PARAMETER ); + } + + // + // Check that our caller wanted to open a file. + // + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { + + try_return( Status = STATUS_NOT_A_DIRECTORY ); + } + + // + // Otherwise we want to collect all of the dirents for this file + // and create an Fcb with this. + // + + CdLookupLastFileDirent( IrpContext, NextFcb, &FileContext ); + + CdLockVcb( IrpContext, Vcb ); + UnlockVcb = TRUE; + + NextFcb = CdCreateFcb( IrpContext, FileId, NodeTypeCode, &Found ); + + // + // It's possible that someone has since created this Fcb since we + // first checked. If so then can simply use this. Otherwise + // we need to initialize a new Fcb and attach it to our parent + // and insert it into the Fcb Table. + // + + if (!Found) { + + CdInitializeFcbFromFileContext( IrpContext, + NextFcb, + *CurrentFcb, + &FileContext ); + } + } + + // + // We have the Fcb. Check that the type of the file is compatible with + // the desired type of file to open. + // + + } else { + + if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { + + try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); + } + + } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { + + try_return( Status = STATUS_NOT_A_DIRECTORY ); + } + } + + // + // If we have a the previous Fcb and have inserted the next Fcb into + // the Fcb Table. It is safe to release the current Fcb if present + // since it is referenced through the child Fcb. + // + + if (*CurrentFcb != NULL) { + + CdReleaseFcb( IrpContext, *CurrentFcb ); + } + + // + // We now know the Fcb and currently hold the Vcb lock. + // Try to acquire this Fcb without waiting. Otherwise we + // need to reference it, drop the Vcb, acquire the Fcb and + // then dereference the Fcb. + // + + if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { + + NextFcb->FcbReference += 1; + + CdUnlockVcb( IrpContext, Vcb ); + + CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); + + CdLockVcb( IrpContext, Vcb ); + NextFcb->FcbReference -= 1; + CdUnlockVcb( IrpContext, Vcb ); + + } else { + + CdUnlockVcb( IrpContext, Vcb ); + } + + UnlockVcb = FALSE; + + // + // Move to this Fcb. + // + + *CurrentFcb = NextFcb; + + // Lock object is acquired using internal state + _Analysis_suppress_lock_checking_(NextFcb->FcbNonpaged->FcbResource); + + // + // Check the requested access on this Fcb. + // + + if (!CdIllegalFcbAccess( IrpContext, + TypeOfOpen, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { + + // + // Call our worker routine to complete the open. + // + + Status = CdCompleteFcbOpen( IrpContext, + IrpSp, + Vcb, + CurrentFcb, + TypeOfOpen, + CCB_FLAG_OPEN_BY_ID, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); + + } + + try_exit: NOTHING; + } _SEH2_FINALLY { + + if (UnlockVcb) { + + CdUnlockVcb( IrpContext, Vcb ); + } + + if (CleanupFileContext) { + + CdCleanupFileContext( IrpContext, &FileContext ); + } + + if (CleanupCompoundPathEntry) { + + CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); + } + } _SEH2_END; + + return Status; +} + + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdOpenExistingFcb ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _Inout_ PFCB *CurrentFcb, + _In_ TYPE_OF_OPEN TypeOfOpen, + _In_ BOOLEAN IgnoreCase, + _In_opt_ PCCB RelatedCcb + ) + +/*++ + +Routine Description: + + This routine is called to open an Fcb which is already in the Fcb table. + We will verify the access to the file and then call our worker routine + to perform the final operations. + +Arguments: + + IrpSp - Pointer to the stack location for this open. + + CurrentFcb - Address of Fcb to open. We will clear this if the Fcb + is released here. + + TypeOfOpen - Indicates whether we are opening a file, directory or volume. + + IgnoreCase - Indicates if this open is case-insensitive. + + RelatedCcb - Ccb for related file object if relative open. We use + this when setting the Ccb flags for this open. It will tell + us whether the name currently in the file object is relative or + absolute. + +Return Value: + + NTSTATUS - Status indicating the result of the operation. + +--*/ + +{ + ULONG CcbFlags = 0; + + NTSTATUS Status = STATUS_ACCESS_DENIED; + + PAGED_CODE(); + + // + // Check that the desired access is legal. + // + + if (!CdIllegalFcbAccess( IrpContext, + TypeOfOpen, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { + + // + // Set the Ignore case. + // + + if (IgnoreCase) { + + SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); + } + + // + // Check the related Ccb to see if this was an OpenByFileId and + // whether there was a version. + // + + if (ARGUMENT_PRESENT( RelatedCcb )) { + + SetFlag( CcbFlags, FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_WITH_VERSION )); + + + if (FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { + + SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); + } + } + + // + // Call our worker routine to complete the open. + // + + Status = CdCompleteFcbOpen( IrpContext, + IrpSp, + (*CurrentFcb)->Vcb, + CurrentFcb, + TypeOfOpen, + CcbFlags, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); + } + + return Status; +} + + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) +NTSTATUS +CdOpenDirectoryFromPathEntry ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ PCD_NAME DirName, + _In_ BOOLEAN IgnoreCase, + _In_ BOOLEAN ShortNameMatch, + _In_ PPATH_ENTRY PathEntry, + _In_ BOOLEAN PerformUserOpen, + _In_opt_ PCCB RelatedCcb + ) + +/*++ + +Routine Description: + + This routine is called to open a directory where the directory was found + in the path table. This routine is called in the case where this is the + file to open for the user and where this is an intermediate node in the + full path to open. + + We first check that the desired access is legal for a directory. Then we + construct the FileId for this and do a check to see if it is the Fcb + Table. It is always possible that either it was created since or simply + wasn't in the prefix table at the time of the prefix table search. + Initialize the Fcb and store into the FcbTable if not present. + + Next we will add this to the prefix table of our parent if needed. + + Once we know that the new Fcb has been initialized then we move our pointer + in the tree down to this position. + + This routine does not own the Vcb lock on entry. We must be sure to release + it on exit. + +Arguments: + + IrpSp - Stack location for this request. + + Vcb - Vcb for this volume. + + CurrentFcb - On input this is the parent of the Fcb to open. On output we + store the Fcb for the file being opened. + + DirName - This is always the exact name used to reach this file. + + IgnoreCase - Indicates the type of case match for the open. + + ShortNameMatch - Indicates if we are opening via the short name. + + PathEntry - Path entry for the entry found. + + PerformUserOpen - TRUE if we are to open this for a user, FALSE otherwise. + + RelatedCcb - RelatedCcb for relative file object used to make this open. + +Return Value: + + NTSTATUS - Status indicating the result of the operation. + +--*/ + +{ + ULONG CcbFlags = 0; + FILE_ID FileId; + + BOOLEAN UnlockVcb = FALSE; + BOOLEAN FcbExisted; + + PFCB NextFcb; + PFCB ParentFcb = NULL; + + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Check for illegal access to this file. + // + + if (PerformUserOpen && + CdIllegalFcbAccess( IrpContext, + UserDirectoryOpen, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { + + return STATUS_ACCESS_DENIED; + } + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Check the related Ccb to see if this was an OpenByFileId. + // + + if (ARGUMENT_PRESENT( RelatedCcb ) && + FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { + + CcbFlags = CCB_FLAG_OPEN_RELATIVE_BY_ID; + } + + if (IgnoreCase) { + + SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); + } + + // + // Build the file Id for this file. + // + + FileId.QuadPart = 0; + CdSetFidPathTableOffset( FileId, PathEntry->PathTableOffset ); + CdFidSetDirectory( FileId ); + + // + // Lock the Vcb so we can examine the Fcb Table. + // + + CdLockVcb( IrpContext, Vcb ); + UnlockVcb = TRUE; + + // + // Get the Fcb for this directory. + // + + NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_INDEX, &FcbExisted ); + + // + // If the Fcb was created here then initialize from the values in the + // path table entry. + // + + if (!FcbExisted) { + + CdInitializeFcbFromPathEntry( IrpContext, NextFcb, *CurrentFcb, PathEntry ); + } + + // + // Now try to acquire the new Fcb without waiting. We will reference + // the Fcb and retry with wait if unsuccessful. + // + + if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { + + NextFcb->FcbReference += 1; + + CdUnlockVcb( IrpContext, Vcb ); + + CdReleaseFcb( IrpContext, *CurrentFcb ); + CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); + CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE ); + + CdLockVcb( IrpContext, Vcb ); + NextFcb->FcbReference -= 1; + CdUnlockVcb( IrpContext, Vcb ); + + } else { + + // + // Unlock the Vcb and move down to this new Fcb. Remember that we still + // own the parent however. + // + + CdUnlockVcb( IrpContext, Vcb ); + } + + UnlockVcb = FALSE; + + ParentFcb = *CurrentFcb; + *CurrentFcb = NextFcb; + + // Lock object is acquired using internal state + _Analysis_suppress_lock_checking_(NextFcb->FcbNonpaged->FcbResource); + + // + // Store this name into the prefix table for the parent. + // + + if (ShortNameMatch) { + + // + // Make sure the exact case is always in the tree. + // + + CdInsertPrefix( IrpContext, + NextFcb, + DirName, + FALSE, + TRUE, + ParentFcb ); + + if (IgnoreCase) { + + CdInsertPrefix( IrpContext, + NextFcb, + DirName, + TRUE, + TRUE, + ParentFcb ); + } + + } else { + + // + // Make sure the exact case is always in the tree. + // + + CdInsertPrefix( IrpContext, + NextFcb, + &PathEntry->CdDirName, + FALSE, + FALSE, + ParentFcb ); + + if (IgnoreCase) { + + CdInsertPrefix( IrpContext, + NextFcb, + &PathEntry->CdCaseDirName, + TRUE, + FALSE, + ParentFcb ); + } + } + + // + // Release the parent Fcb at this point. + // + + CdReleaseFcb( IrpContext, ParentFcb ); + ParentFcb = NULL; + + // + // Call our worker routine to complete the open. + // + + if (PerformUserOpen) { + + Status = CdCompleteFcbOpen( IrpContext, + IrpSp, + Vcb, + CurrentFcb, + UserDirectoryOpen, + CcbFlags, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); + } + + } _SEH2_FINALLY { + + // + // Unlock the Vcb if held. + // + + if (UnlockVcb) { + + CdUnlockVcb( IrpContext, Vcb ); + } + + // + // Release the parent if held. + // + + if (ParentFcb != NULL) { + + CdReleaseFcb( IrpContext, ParentFcb ); + } + } _SEH2_END; + + return Status; +} + + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdOpenFileFromFileContext ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ PCD_NAME FileName, + _In_ BOOLEAN IgnoreCase, + _In_ BOOLEAN ShortNameMatch, + _In_ PFILE_ENUM_CONTEXT FileContext, + _In_opt_ PCCB RelatedCcb + ) + +/*++ + +Routine Description: + + This routine is called to open a file where the file was found in a directory scan. + This should only be for a file in the case since we will find the directories in the + path table. + + We first check that the desired access is legal for this file. Then we + construct the FileId for this and do a check to see if it is the Fcb + Table. It is always possible that either it was created since or simply + wasn't in the prefix table at the time of the prefix table search. + Initialize the Fcb and store into the FcbTable if not present. + + Next we will add this to the prefix table of our parent if needed. + + Once we know that the new Fcb has been initialized then we move our pointer + in the tree down to this position. + + This routine does not own the Vcb lock on entry. We must be sure to release + it on exit. + +Arguments: + + IrpSp - Stack location for this request. + + Vcb - Vcb for the current volume. + + CurrentFcb - On input this is the parent of the Fcb to open. On output we + store the Fcb for the file being opened. + + FileName - This is always the exact name used to reach this file. + + IgnoreCase - Indicates the type of case of CaseName above. + + ShortNameMatch - Indicates if we are opening via the short name. + + FileContext - This is the context used to find the file. + + RelatedCcb - RelatedCcb for relative file object used to make this open. + +Return Value: + + NTSTATUS - Status indicating the result of the operation. + +--*/ + +{ + ULONG CcbFlags = 0; + FILE_ID FileId; + + BOOLEAN UnlockVcb = FALSE; + BOOLEAN FcbExisted; + + PFCB NextFcb; + PFCB ParentFcb = NULL; + + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Check for illegal access to this file. + // + + if (CdIllegalFcbAccess( IrpContext, + UserFileOpen, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { + + return STATUS_ACCESS_DENIED; + } + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Check if a version number was used to open this file. + // + + if (FileName->VersionString.Length != 0) { + + SetFlag( CcbFlags, CCB_FLAG_OPEN_WITH_VERSION ); + } + + // + // Check the related Ccb to see if this was an OpenByFileId. + // + + if (ARGUMENT_PRESENT( RelatedCcb ) && + FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { + + SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); + } + + if (IgnoreCase) { + + SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); + } + + // + // Build the file Id for this file. We can use the path table offset from the + // parent and the directory offset from the dirent. + // + + CdSetFidPathTableOffset( FileId, CdQueryFidPathTableOffset( (*CurrentFcb)->FileId )); + CdSetFidDirentOffset( FileId, FileContext->InitialDirent->Dirent.DirentOffset ); + + // + // Lock the Vcb so we can examine the Fcb Table. + // + + CdLockVcb( IrpContext, Vcb ); + UnlockVcb = TRUE; + + // + // Get the Fcb for this file. + // + + NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_DATA, &FcbExisted ); + + // + // If the Fcb was created here then initialize from the values in the + // dirent. + // + + if (!FcbExisted) { + + CdInitializeFcbFromFileContext( IrpContext, + NextFcb, + *CurrentFcb, + FileContext ); + } + + // + // Now try to acquire the new Fcb without waiting. We will reference + // the Fcb and retry with wait if unsuccessful. + // + + if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { + + NextFcb->FcbReference += 1; + + CdUnlockVcb( IrpContext, Vcb ); + + CdReleaseFcb( IrpContext, *CurrentFcb ); + CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); + CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE ); + + CdLockVcb( IrpContext, Vcb ); + NextFcb->FcbReference -= 1; + CdUnlockVcb( IrpContext, Vcb ); + + } else { + + // + // Unlock the Vcb and move down to this new Fcb. Remember that we still + // own the parent however. + // + + CdUnlockVcb( IrpContext, Vcb ); + } + + UnlockVcb = FALSE; + + ParentFcb = *CurrentFcb; + *CurrentFcb = NextFcb; + + // + // Store this name into the prefix table for the parent. + // + + + if (ShortNameMatch) { + + // + // Make sure the exact case is always in the tree. + // + + CdInsertPrefix( IrpContext, + NextFcb, + FileName, + FALSE, + TRUE, + ParentFcb ); + + if (IgnoreCase) { + + CdInsertPrefix( IrpContext, + NextFcb, + FileName, + TRUE, + TRUE, + ParentFcb ); + } + + // + // Insert this into the prefix table if we found this without + // using a version string. + // + + } else if (FileName->VersionString.Length == 0) { + + // + // Make sure the exact case is always in the tree. + // + + CdInsertPrefix( IrpContext, + NextFcb, + &FileContext->InitialDirent->Dirent.CdFileName, + FALSE, + FALSE, + ParentFcb ); + + if (IgnoreCase) { + + CdInsertPrefix( IrpContext, + NextFcb, + &FileContext->InitialDirent->Dirent.CdCaseFileName, + TRUE, + FALSE, + ParentFcb ); + } + } + + // + // Release the parent Fcb at this point. + // + + _Analysis_assume_same_lock_(ParentFcb->FcbNonpaged->FcbResource, NextFcb->FcbNonpaged->FcbResource); + CdReleaseFcb( IrpContext, ParentFcb ); + ParentFcb = NULL; + + // + // Call our worker routine to complete the open. + // + + Status = CdCompleteFcbOpen( IrpContext, + IrpSp, + Vcb, + CurrentFcb, + UserFileOpen, + CcbFlags, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); + + } _SEH2_FINALLY { + + // + // Unlock the Vcb if held. + // + + if (UnlockVcb) { + + CdUnlockVcb( IrpContext, Vcb ); + } + + // + // Release the parent if held. + // + + if (ParentFcb != NULL) { + + CdReleaseFcb( IrpContext, ParentFcb ); + } + } _SEH2_END; + + return Status; +} + + +// +// Local support routine +// + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdCompleteFcbOpen ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PIO_STACK_LOCATION IrpSp, + _In_ PVCB Vcb, + _Inout_ PFCB *CurrentFcb, + _In_ TYPE_OF_OPEN TypeOfOpen, + _In_ ULONG UserCcbFlags, + _In_ ACCESS_MASK DesiredAccess + ) + +/*++ + +Routine Description: + + This is the worker routine which takes an existing Fcb and completes + the open. We will do any necessary oplock checks and sharing checks. + Finally we will create the Ccb and update the file object and any + file object flags. + +Arguments: + + IrpSp - Stack location for the current request. + + Vcb - Vcb for the current volume. + + CurrentFcb - Address of pointer to Fcb to open. We clear this field if + we release the resource for this file. + + TypeOfOpen - Type of open for this request. + + UserCcbFlags - Flags to OR into the Ccb flags. + + DesiredAccess - Desired access for this open. + +Return Value: + + NTSTATUS - STATUS_SUCCESS if we complete this request, STATUS_PENDING if + the oplock package takes the Irp or SHARING_VIOLATION if there is a + sharing check conflict. + +--*/ + +{ + NTSTATUS Status; + NTSTATUS OplockStatus = STATUS_SUCCESS; + ULONG Information = FILE_OPENED; + + BOOLEAN LockVolume = FALSE; + + PFCB Fcb = *CurrentFcb; + PCCB Ccb; + + PAGED_CODE(); + + // + // Expand maximum allowed to something sensible for share access checking + // + + if (MAXIMUM_ALLOWED == DesiredAccess) { + + DesiredAccess = FILE_ALL_ACCESS & ~((TypeOfOpen != UserVolumeOpen ? + (FILE_WRITE_ATTRIBUTES | + FILE_WRITE_DATA | + FILE_WRITE_EA | + FILE_ADD_FILE | + FILE_ADD_SUBDIRECTORY | + FILE_APPEND_DATA) : 0) | + FILE_DELETE_CHILD | + DELETE | + WRITE_DAC ); + } + + // + // If this a volume open and the user wants to lock the volume then + // purge and lock the volume. + // + + if ((TypeOfOpen <= UserVolumeOpen) && + !FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ )) { + + // + // If there are open handles then fail this immediately. + // + + if (Vcb->VcbCleanup != 0) { + + return STATUS_SHARING_VIOLATION; + } + + // + // If we can't wait then force this to be posted. + // + + if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { + + CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); + } + + LockVolume = TRUE; + + // + // Purge the volume and make sure all of the user references + // are gone. + // + + Status = CdPurgeVolume( IrpContext, Vcb, FALSE ); + + if (Status != STATUS_SUCCESS) { + + return Status; + } + + // + // Now force all of the delayed close operations to go away. + // + + CdFspClose( Vcb ); + + if (Vcb->VcbUserReference > CDFS_RESIDUAL_USER_REFERENCE) { + + return STATUS_SHARING_VIOLATION; + } + } + + // + // If the Fcb already existed then we need to check the oplocks and + // the share access. + // + + if (Fcb->FcbCleanup != 0) { + + // + // If this is a user file open then check whether there are any + // batch oplock. + // + + if (TypeOfOpen == UserFileOpen) { + + // + // Store the address of the Fcb for a possible teardown into + // the IrpContext. We will release this in the call to + // prepost the Irp. + // + + IrpContext->TeardownFcb = CurrentFcb; + + if (FsRtlCurrentBatchOplock( CdGetFcbOplock(Fcb) )) { + + // + // We remember if a batch oplock break is underway for the + // case where the sharing check fails. + // + + Information = FILE_OPBATCH_BREAK_UNDERWAY; + + OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb), + IrpContext->Irp, + IrpContext, + (PVOID)CdOplockComplete, /* ReactOS Change: GCC "assignment from incompatible pointer type" */ + (PVOID)CdPrePostIrp ); /* ReactOS Change: GCC "assignment from incompatible pointer type" */ + + if (OplockStatus == STATUS_PENDING) { + + return STATUS_PENDING; + } + } + + // + // Check the share access before breaking any exclusive oplocks. + // + + Status = IoCheckShareAccess( DesiredAccess, + IrpSp->Parameters.Create.ShareAccess, + IrpSp->FileObject, + &Fcb->ShareAccess, + FALSE ); + + if (!NT_SUCCESS( Status )) { + + return Status; + } + + // + // Now check that we can continue based on the oplock state of the + // file. + // + + OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb), + IrpContext->Irp, + IrpContext, + (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */ + (PVOID)CdPrePostIrp );/* ReactOS Change: GCC "assignment from incompatible pointer type" */ + + if (OplockStatus == STATUS_PENDING) { + + return STATUS_PENDING; + } + + IrpContext->TeardownFcb = NULL; + + // + // Otherwise just do the sharing check. + // + + } else { + + Status = IoCheckShareAccess( DesiredAccess, + IrpSp->Parameters.Create.ShareAccess, + IrpSp->FileObject, + &Fcb->ShareAccess, + FALSE ); + + if (!NT_SUCCESS( Status )) { + + return Status; + } + } + } + + // + // Create the Ccb now. + // + + Ccb = CdCreateCcb( IrpContext, Fcb, UserCcbFlags ); + + // + // Update the share access. + // + + if (Fcb->FcbCleanup == 0) { + + IoSetShareAccess( DesiredAccess, + IrpSp->Parameters.Create.ShareAccess, + IrpSp->FileObject, + &Fcb->ShareAccess ); + + } else { + + IoUpdateShareAccess( IrpSp->FileObject, &Fcb->ShareAccess ); + } + + // + // Set the file object type. + // + + CdSetFileObject( IrpContext, IrpSp->FileObject, TypeOfOpen, Fcb, Ccb ); + + // + // Set the appropriate cache flags for a user file object. + // + + if (TypeOfOpen == UserFileOpen) { + + if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING )) { + + SetFlag( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ); + + } else { + + SetFlag( IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED ); + } + } + else if (TypeOfOpen == UserVolumeOpen) { + + SetFlag( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ); + } + + // + // Update the open and cleanup counts. Check the fast io state here. + // + + CdLockVcb( IrpContext, Vcb ); + + CdIncrementCleanupCounts( IrpContext, Fcb ); + CdIncrementReferenceCounts( IrpContext, Fcb, 1, 1 ); + + if (LockVolume) { + + Vcb->VolumeLockFileObject = IrpSp->FileObject; + SetFlag( Vcb->VcbState, VCB_STATE_LOCKED ); + } + + CdUnlockVcb( IrpContext, Vcb ); + + CdLockFcb( IrpContext, Fcb ); + + if (TypeOfOpen == UserFileOpen) { + + Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); + + } else { + + Fcb->IsFastIoPossible = FastIoIsNotPossible; + } + + CdUnlockFcb( IrpContext, Fcb ); + + // + // Show that we opened the file. + // + + IrpContext->Irp->IoStatus.Information = Information; + + // + // Point to the section object pointer in the non-paged Fcb. + // + + IrpSp->FileObject->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject; + return OplockStatus; +} + + + + + diff --git a/drivers/filesystems/cdfs/devctrl.c b/drivers/filesystems/cdfs/devctrl.c index 7e2221a3319..4d0a70ad55e 100644 --- a/drivers/filesystems/cdfs/devctrl.c +++ b/drivers/filesystems/cdfs/devctrl.c @@ -1,69 +1,199 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/filesystems/cdfs/devctrl.c - * PURPOSE: CDROM (ISO 9660) filesystem driver - * PROGRAMMER: Pierre Schweitzer - * - */ +/*++ -/* INCLUDES *****************************************************************/ +Copyright (c) 1989-2000 Microsoft Corporation -#include "cdfs.h" +Module Name: -#define NDEBUG -#include + DevCtrl.c -/* FUNCTIONS ****************************************************************/ +Abstract: + + This module implements the File System Device Control routines for Cdfs + called by the dispatch driver. + + +--*/ + +#include "cdprocs.h" + +// +// The Bug check file id for this module +// + +#define BugCheckFileId (CDFS_BUG_CHECK_DEVCTRL) + +// +// Local support routines +// + +// Tell prefast this is a completion routine +IO_COMPLETION_ROUTINE CdDevCtrlCompletionRoutine; + +NTSTATUS +NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ +CdDevCtrlCompletionRoutine ( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp, + _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, CdCommonDevControl) +#endif + + +NTSTATUS +CdCommonDevControl ( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ -NTSTATUS NTAPI -CdfsDeviceControl( - PCDFS_IRP_CONTEXT IrpContext) { - PIRP Irp; NTSTATUS Status; - PVCB Vcb = NULL; - PFILE_OBJECT FileObject; - PIO_STACK_LOCATION Stack; - DPRINT("CdfsDeviceControl()\n"); + TYPE_OF_OPEN TypeOfOpen; + PFCB Fcb; + PCCB Ccb; - ASSERT(IrpContext); + PIO_STACK_LOCATION IrpSp; + PIO_STACK_LOCATION NextIrpSp; - Irp = IrpContext->Irp; - Stack = IrpContext->Stack; - FileObject = Stack->FileObject; - Irp->IoStatus.Information = 0; + PAGED_CODE(); - /* FIXME: HACK, it means that CD has changed */ - if (!FileObject) - { - DPRINT1("FIXME: CdfsDeviceControl called without FileObject!\n"); - return STATUS_INVALID_DEVICE_REQUEST; - } + // + // Extract and decode the file object. + // - /* Only support such operations on volume */ - if (!(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL)) - { + IrpSp = IoGetCurrentIrpStackLocation( Irp ); + + TypeOfOpen = CdDecodeFileObject( IrpContext, + IrpSp->FileObject, + &Fcb, + &Ccb ); + + // + // The only type of opens we accept are user volume opens. + // + + if (TypeOfOpen != UserVolumeOpen) { + + CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); return STATUS_INVALID_PARAMETER; } - if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) - { - /* We should handle this one, but we don't! */ - Status = STATUS_NOT_IMPLEMENTED; - } - else - { - /* Pass it to storage driver */ - IoSkipCurrentIrpStackLocation(Irp); - Vcb = (PVCB)Stack->DeviceObject->DeviceExtension; + if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) { - /* Lower driver will complete - we don't have to */ - IrpContext->Flags &= ~IRPCONTEXT_COMPLETE; + // + // Verify the Vcb in this case to detect if the volume has changed. + // - Status = IoCallDriver(Vcb->StorageDevice, Irp); + CdVerifyVcb( IrpContext, Fcb->Vcb ); + + // + // Handle the case of the disk type ourselves. + // + + } else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) { + + // + // Verify the Vcb in this case to detect if the volume has changed. + // + + CdVerifyVcb( IrpContext, Fcb->Vcb ); + + // + // Check the size of the output buffer. + // + + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) { + + CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); + return STATUS_BUFFER_TOO_SMALL; + } + + // + // Copy the data from the Vcb. + // + + ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags; + + Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA ); + CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); + return STATUS_SUCCESS; } + // + // Get the next stack location, and copy over the stack parameter + // information. + // + + NextIrpSp = IoGetNextIrpStackLocation( Irp ); + + *NextIrpSp = *IrpSp; + + // + // Set up the completion routine + // + + IoSetCompletionRoutine( Irp, + CdDevCtrlCompletionRoutine, + NULL, + TRUE, + TRUE, + TRUE ); + + // + // Send the request. + // + + Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp ); + + // + // Cleanup our Irp Context. The driver has completed the Irp. + // + + CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); + return Status; } + + +// +// Local support routine +// + +NTSTATUS +NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ +CdDevCtrlCompletionRoutine ( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp, + _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt + ) + +{ + // + // Add the hack-o-ramma to fix formats. + // + + if (Irp->PendingReturned) { + + IoMarkIrpPending( Irp ); + } + + return STATUS_SUCCESS; + + UNREFERENCED_PARAMETER( DeviceObject ); + UNREFERENCED_PARAMETER( Contxt ); +} + + diff --git a/drivers/filesystems/cdfs_new/deviosup.c b/drivers/filesystems/cdfs/deviosup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/deviosup.c rename to drivers/filesystems/cdfs/deviosup.c diff --git a/drivers/filesystems/cdfs/dirctl.c b/drivers/filesystems/cdfs/dirctl.c deleted file mode 100644 index c3d2878007b..00000000000 --- a/drivers/filesystems/cdfs/dirctl.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs_new/dirctrl.c b/drivers/filesystems/cdfs/dirctrl.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/dirctrl.c rename to drivers/filesystems/cdfs/dirctrl.c diff --git a/drivers/filesystems/cdfs_new/dirsup.c b/drivers/filesystems/cdfs/dirsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/dirsup.c rename to drivers/filesystems/cdfs/dirsup.c diff --git a/drivers/filesystems/cdfs/dispatch.c b/drivers/filesystems/cdfs/dispatch.c deleted file mode 100644 index 4b1434757b4..00000000000 --- a/drivers/filesystems/cdfs/dispatch.c +++ /dev/null @@ -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 - -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; -} diff --git a/drivers/filesystems/cdfs/fastio.c b/drivers/filesystems/cdfs/fastio.c deleted file mode 100644 index 49547b5637c..00000000000 --- a/drivers/filesystems/cdfs/fastio.c +++ /dev/null @@ -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 - -/* 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; -} diff --git a/drivers/filesystems/cdfs/fcb.c b/drivers/filesystems/cdfs/fcb.c deleted file mode 100644 index 4a361d9ede1..00000000000 --- a/drivers/filesystems/cdfs/fcb.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs_new/fieldoff.c b/drivers/filesystems/cdfs/fieldoff.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/fieldoff.c rename to drivers/filesystems/cdfs/fieldoff.c diff --git a/drivers/filesystems/cdfs_new/fileinfo.c b/drivers/filesystems/cdfs/fileinfo.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/fileinfo.c rename to drivers/filesystems/cdfs/fileinfo.c diff --git a/drivers/filesystems/cdfs_new/filobsup.c b/drivers/filesystems/cdfs/filobsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/filobsup.c rename to drivers/filesystems/cdfs/filobsup.c diff --git a/drivers/filesystems/cdfs/finfo.c b/drivers/filesystems/cdfs/finfo.c deleted file mode 100644 index e0e08e1abe8..00000000000 --- a/drivers/filesystems/cdfs/finfo.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs/fsctl.c b/drivers/filesystems/cdfs/fsctl.c deleted file mode 100644 index 925819fb8e1..00000000000 --- a/drivers/filesystems/cdfs/fsctl.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs_new/fsctrl.c b/drivers/filesystems/cdfs/fsctrl.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/fsctrl.c rename to drivers/filesystems/cdfs/fsctrl.c diff --git a/drivers/filesystems/cdfs_new/fspdisp.c b/drivers/filesystems/cdfs/fspdisp.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/fspdisp.c rename to drivers/filesystems/cdfs/fspdisp.c diff --git a/drivers/filesystems/cdfs_new/lockctrl.c b/drivers/filesystems/cdfs/lockctrl.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/lockctrl.c rename to drivers/filesystems/cdfs/lockctrl.c diff --git a/drivers/filesystems/cdfs/misc.c b/drivers/filesystems/cdfs/misc.c deleted file mode 100644 index fe5d9e5388b..00000000000 --- a/drivers/filesystems/cdfs/misc.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs_new/namesup.c b/drivers/filesystems/cdfs/namesup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/namesup.c rename to drivers/filesystems/cdfs/namesup.c diff --git a/drivers/filesystems/cdfs_new/nodetype.h b/drivers/filesystems/cdfs/nodetype.h old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/nodetype.h rename to drivers/filesystems/cdfs/nodetype.h diff --git a/drivers/filesystems/cdfs_new/pathsup.c b/drivers/filesystems/cdfs/pathsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/pathsup.c rename to drivers/filesystems/cdfs/pathsup.c diff --git a/drivers/filesystems/cdfs_new/pnp.c b/drivers/filesystems/cdfs/pnp.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/pnp.c rename to drivers/filesystems/cdfs/pnp.c diff --git a/drivers/filesystems/cdfs_new/prefxsup.c b/drivers/filesystems/cdfs/prefxsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/prefxsup.c rename to drivers/filesystems/cdfs/prefxsup.c diff --git a/drivers/filesystems/cdfs_new/read.c b/drivers/filesystems/cdfs/read.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/read.c rename to drivers/filesystems/cdfs/read.c diff --git a/drivers/filesystems/cdfs_new/resrcsup.c b/drivers/filesystems/cdfs/resrcsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/resrcsup.c rename to drivers/filesystems/cdfs/resrcsup.c diff --git a/drivers/filesystems/cdfs/rw.c b/drivers/filesystems/cdfs/rw.c deleted file mode 100644 index dc42903fe87..00000000000 --- a/drivers/filesystems/cdfs/rw.c +++ /dev/null @@ -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 - -/* 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 */ diff --git a/drivers/filesystems/cdfs_new/shutdown.c b/drivers/filesystems/cdfs/shutdown.c similarity index 100% rename from drivers/filesystems/cdfs_new/shutdown.c rename to drivers/filesystems/cdfs/shutdown.c diff --git a/drivers/filesystems/cdfs_new/strucsup.c b/drivers/filesystems/cdfs/strucsup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/strucsup.c rename to drivers/filesystems/cdfs/strucsup.c diff --git a/drivers/filesystems/cdfs_new/verfysup.c b/drivers/filesystems/cdfs/verfysup.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/verfysup.c rename to drivers/filesystems/cdfs/verfysup.c diff --git a/drivers/filesystems/cdfs/volinfo.c b/drivers/filesystems/cdfs/volinfo.c index cffaf9fb913..7448dd58507 100644 --- a/drivers/filesystems/cdfs/volinfo.c +++ b/drivers/filesystems/cdfs/volinfo.c @@ -1,297 +1,605 @@ -/* - * ReactOS kernel - * Copyright (C) 2002, 2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/filesystems/cdfs/volume.c - * PURPOSE: CDROM (ISO 9660) filesystem driver - * PROGRAMMER: Art Yerkes - * Eric Kohl - */ +/*++ -/* INCLUDES *****************************************************************/ +Copyright (c) 1989-2000 Microsoft Corporation -#include "cdfs.h" +Module Name: -#define NDEBUG -#include + VolInfo.c -/* FUNCTIONS ****************************************************************/ +Abstract: -static + This module implements the volume information routines for Cdfs called by + the dispatch driver. + + +--*/ + +#include "cdprocs.h" + +// +// The Bug check file id for this module +// + +#define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO) + +// +// Local support routines +// + +_Requires_lock_held_(_Global_critical_region_) NTSTATUS -CdfsGetFsVolumeInformation( - PDEVICE_OBJECT DeviceObject, - PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, - PULONG BufferLength) -{ - DPRINT("CdfsGetFsVolumeInformation() called\n"); - DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); - DPRINT("BufferLength %lu\n", *BufferLength); - - DPRINT("Vpb %p\n", DeviceObject->Vpb); - - DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength)); - DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength); - DPRINT("Label %.*S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel); - - if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) - return STATUS_INFO_LENGTH_MISMATCH; - - if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength)) - return STATUS_BUFFER_OVERFLOW; - - /* valid entries */ - FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; - FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength; - memcpy(FsVolumeInfo->VolumeLabel, - DeviceObject->Vpb->VolumeLabel, - DeviceObject->Vpb->VolumeLabelLength); - - /* dummy entries */ - FsVolumeInfo->VolumeCreationTime.QuadPart = 0; - FsVolumeInfo->SupportsObjects = FALSE; - - DPRINT("Finished FsdGetFsVolumeInformation()\n"); - - *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength); - - DPRINT("BufferLength %lu\n", *BufferLength); - - return STATUS_SUCCESS; -} - - -static -NTSTATUS -CdfsGetFsAttributeInformation( - PDEVICE_EXTENSION DeviceExt, - PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, - PULONG BufferLength) -{ - DPRINT("CdfsGetFsAttributeInformation()\n"); - DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); - DPRINT("BufferLength %lu\n", *BufferLength); - DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)); - - UNREFERENCED_PARAMETER(DeviceExt); - - if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) - return STATUS_INFO_LENGTH_MISMATCH; - - if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)) - return STATUS_BUFFER_OVERFLOW; - - FsAttributeInfo->FileSystemAttributes = - FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_READ_ONLY_VOLUME; - FsAttributeInfo->MaximumComponentNameLength = 255; - FsAttributeInfo->FileSystemNameLength = 8; - - memcpy(FsAttributeInfo->FileSystemName, L"CDFS", 8); - - DPRINT("Finished FsdGetFsAttributeInformation()\n"); - - *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8); - DPRINT("BufferLength %lu\n", *BufferLength); - - return STATUS_SUCCESS; -} - - -static NTSTATUS -CdfsGetFsSizeInformation( - PDEVICE_OBJECT DeviceObject, - PFILE_FS_SIZE_INFORMATION FsSizeInfo, - PULONG BufferLength) -{ - PDEVICE_EXTENSION DeviceExt; - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("CdfsGetFsSizeInformation()\n"); - DPRINT("FsSizeInfo = %p\n", FsSizeInfo); - - if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) - return STATUS_BUFFER_OVERFLOW; - - DeviceExt = DeviceObject->DeviceExtension; - - FsSizeInfo->AvailableAllocationUnits.QuadPart = 0; - FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize; - FsSizeInfo->SectorsPerAllocationUnit = 1; - FsSizeInfo->BytesPerSector = BLOCKSIZE; - - DPRINT("Finished FsdGetFsSizeInformation()\n"); - if (NT_SUCCESS(Status)) - *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); - - return Status; -} - - -static -NTSTATUS -CdfsGetFsDeviceInformation( - PDEVICE_OBJECT DeviceObject, - PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, - PULONG BufferLength) -{ - DPRINT("CdfsGetFsDeviceInformation()\n"); - DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); - DPRINT("BufferLength %lu\n", *BufferLength); - DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); - - if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) - return STATUS_BUFFER_OVERFLOW; - - if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) - FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM; - else - FsDeviceInfo->DeviceType = FILE_DEVICE_DISK; - - FsDeviceInfo->Characteristics = DeviceObject->Characteristics; - - DPRINT("FsdGetFsDeviceInformation() finished.\n"); - - *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); - DPRINT("BufferLength %lu\n", *BufferLength); - - return STATUS_SUCCESS; -} - - -static -NTSTATUS -CdfsGetFsFullSizeInformation( - PDEVICE_OBJECT DeviceObject, - PFILE_FS_FULL_SIZE_INFORMATION FsSizeInfo, - PULONG BufferLength) -{ - PDEVICE_EXTENSION DeviceExt; - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("CdfsGetFsFullSizeInformation()\n"); - DPRINT("FsSizeInfo = %p\n", FsSizeInfo); - - if (*BufferLength < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) - return STATUS_BUFFER_OVERFLOW; - - DeviceExt = DeviceObject->DeviceExtension; - - FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize; - FsSizeInfo->CallerAvailableAllocationUnits.QuadPart = 0; - FsSizeInfo->ActualAvailableAllocationUnits.QuadPart = 0; - FsSizeInfo->SectorsPerAllocationUnit = 1; - FsSizeInfo->BytesPerSector = BLOCKSIZE; - - DPRINT("Finished CdfsGetFsFullSizeInformation()\n"); - if (NT_SUCCESS(Status)) - *BufferLength -= sizeof(FILE_FS_FULL_SIZE_INFORMATION); - - return Status; -} - +CdQueryFsVolumeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_VOLUME_INFORMATION Buffer, + _Inout_ PULONG Length + ); NTSTATUS -NTAPI -CdfsQueryVolumeInformation( - PCDFS_IRP_CONTEXT IrpContext) +CdQueryFsSizeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_SIZE_INFORMATION Buffer, + _Inout_ PULONG Length + ); + +NTSTATUS +CdQueryFsDeviceInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_DEVICE_INFORMATION Buffer, + _Inout_ PULONG Length + ); + +NTSTATUS +CdQueryFsAttributeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer, + _Inout_ PULONG Length + ); + +#ifdef __REACTOS__ +#define PFILE_FS_SECTOR_SIZE_INFORMATION PVOID +#endif + +NTSTATUS +CdQueryFsSectorSizeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer, + _Inout_ PULONG Length + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, CdCommonQueryVolInfo) +#pragma alloc_text(PAGE, CdQueryFsAttributeInfo) +#pragma alloc_text(PAGE, CdQueryFsDeviceInfo) +#pragma alloc_text(PAGE, CdQueryFsSizeInfo) +#pragma alloc_text(PAGE, CdQueryFsVolumeInfo) +#pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo) +#endif + + +_Requires_lock_held_(_Global_critical_region_) +NTSTATUS +CdCommonQueryVolInfo ( + _Inout_ PIRP_CONTEXT IrpContext, + _Inout_ PIRP Irp + ) + +/*++ + +Routine Description: + + This is the common routine for querying volume information called by both + the fsd and fsp threads. + +Arguments: + + Irp - Supplies the Irp being processed + +Return Value: + + NTSTATUS - The return status for the operation + +--*/ + { - PIRP Irp; - PDEVICE_OBJECT DeviceObject; - FS_INFORMATION_CLASS FsInformationClass; - PIO_STACK_LOCATION Stack; - NTSTATUS Status = STATUS_SUCCESS; - PVOID SystemBuffer; - ULONG BufferLength; + NTSTATUS Status = STATUS_INVALID_PARAMETER; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); - DPRINT("CdfsQueryVolumeInformation() called\n"); + ULONG Length; - ASSERT(IrpContext); + TYPE_OF_OPEN TypeOfOpen; + PFCB Fcb; + PCCB Ccb; - Irp = IrpContext->Irp; - DeviceObject = IrpContext->DeviceObject; - Stack = IrpContext->Stack; - FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass; - BufferLength = Stack->Parameters.QueryVolume.Length; - SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + PAGED_CODE(); - DPRINT("FsInformationClass %d\n", FsInformationClass); - DPRINT("SystemBuffer %p\n", SystemBuffer); + // + // Reference our input parameters to make things easier + // - switch (FsInformationClass) - { - case FileFsVolumeInformation: - Status = CdfsGetFsVolumeInformation(DeviceObject, - SystemBuffer, - &BufferLength); - break; + Length = IrpSp->Parameters.QueryVolume.Length; - case FileFsAttributeInformation: - Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension, - SystemBuffer, - &BufferLength); - break; + // + // Decode the file object and fail if this an unopened file object. + // + + TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); + + if (TypeOfOpen == UnopenedFileObject) { + + CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); + return STATUS_INVALID_PARAMETER; + } + + // + // Acquire the Vcb for this volume. + // + + CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE ); + + // + // Use a try-finally to facilitate cleanup. + // + + _SEH2_TRY { + + // + // Verify the Vcb. + // + + CdVerifyVcb( IrpContext, Fcb->Vcb ); + + // + // Based on the information class we'll do different actions. Each + // of the procedures that we're calling fills up the output buffer + // if possible and returns true if it successfully filled the buffer + // and false if it couldn't wait for any I/O to complete. + // + + switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { case FileFsSizeInformation: - Status = CdfsGetFsSizeInformation(DeviceObject, - SystemBuffer, - &BufferLength); + + Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); + break; + + case FileFsVolumeInformation: + + Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; case FileFsDeviceInformation: - Status = CdfsGetFsDeviceInformation(DeviceObject, - SystemBuffer, - &BufferLength); + + Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; - case FileFsFullSizeInformation: - Status = CdfsGetFsFullSizeInformation(DeviceObject, - SystemBuffer, - &BufferLength); + case FileFsAttributeInformation: + + Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; - default: - Status = STATUS_NOT_SUPPORTED; - } +#if (NTDDI_VERSION >= NTDDI_WIN8) + case FileFsSectorSizeInformation: - if (NT_SUCCESS(Status)) - Irp->IoStatus.Information = - Stack->Parameters.QueryVolume.Length - BufferLength; - else - Irp->IoStatus.Information = 0; + Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); + break; +#endif + + /* ReactOS Change: GCC "enumeration value not handled in switch" */ + default: break; + } + + // + // Set the information field to the number of bytes actually filled in + // + + Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length; + + } _SEH2_FINALLY { + + // + // Release the Vcb. + // + + CdReleaseVcb( IrpContext, Fcb->Vcb ); + } _SEH2_END; + + // + // Complete the request if we didn't raise. + // + + CdCompleteRequest( IrpContext, Irp, Status ); return Status; } + +// +// Local support routine +// +_Requires_lock_held_(_Global_critical_region_) NTSTATUS -NTAPI -CdfsSetVolumeInformation( - PCDFS_IRP_CONTEXT IrpContext) +CdQueryFsVolumeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_VOLUME_INFORMATION Buffer, + _Inout_ PULONG Length + ) + +/*++ + +Routine Description: + + This routine implements the query volume info call + +Arguments: + + Vcb - Vcb for this volume. + + Buffer - Supplies a pointer to the output buffer where the information + is to be returned + + Length - Supplies the length of the buffer in byte. This variable + upon return recieves the remaining bytes free in the buffer + +Return Value: + + NTSTATUS - Returns the status for the query + +--*/ + { - DPRINT("CdfsSetVolumeInformation() called\n"); + ULONG BytesToCopy; - ASSERT(IrpContext); + NTSTATUS Status = STATUS_SUCCESS; - IrpContext->Irp->IoStatus.Information = 0; + PAGED_CODE(); - return STATUS_NOT_SUPPORTED; + UNREFERENCED_PARAMETER( IrpContext ); + + // + // Fill in the data from the Vcb. + // + + Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime); + Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber; + + Buffer->SupportsObjects = FALSE; + + *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] ); + + // + // Check if the buffer we're given is long enough + // + + if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) { + + BytesToCopy = Vcb->Vpb->VolumeLabelLength; + + } else { + + BytesToCopy = *Length; + + Status = STATUS_BUFFER_OVERFLOW; + } + + // + // Copy over what we can of the volume label, and adjust *Length + // + + Buffer->VolumeLabelLength = BytesToCopy; + + if (BytesToCopy) { + + RtlCopyMemory( &Buffer->VolumeLabel[0], + &Vcb->Vpb->VolumeLabel[0], + BytesToCopy ); + } + + *Length -= BytesToCopy; + + // + // Set our status and return to our caller + // + + return Status; } -/* EOF */ + +// +// Local support routine +// + +NTSTATUS +CdQueryFsSizeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_SIZE_INFORMATION Buffer, + _Inout_ PULONG Length + ) + +/*++ + +Routine Description: + + This routine implements the query volume size call. + +Arguments: + + Vcb - Vcb for this volume. + + Buffer - Supplies a pointer to the output buffer where the information + is to be returned + + Length - Supplies the length of the buffer in byte. This variable + upon return recieves the remaining bytes free in the buffer + +Return Value: + + NTSTATUS - Returns the status for the query + +--*/ + +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER( IrpContext ); + + // + // Fill in the output buffer. + // + + Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart ); + + Buffer->AvailableAllocationUnits.QuadPart = 0; + Buffer->SectorsPerAllocationUnit = 1; + Buffer->BytesPerSector = SECTOR_SIZE; + + // + // Adjust the length variable + // + + *Length -= sizeof( FILE_FS_SIZE_INFORMATION ); + + // + // And return success to our caller + // + + return STATUS_SUCCESS; +} + + +// +// Local support routine +// + +NTSTATUS +CdQueryFsDeviceInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_DEVICE_INFORMATION Buffer, + _Inout_ PULONG Length + ) + +/*++ + +Routine Description: + + This routine implements the query volume device call. + +Arguments: + + Vcb - Vcb for this volume. + + Buffer - Supplies a pointer to the output buffer where the information + is to be returned + + Length - Supplies the length of the buffer in byte. This variable + upon return recieves the remaining bytes free in the buffer + +Return Value: + + NTSTATUS - Returns the status for the query + +--*/ + +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER( IrpContext ); + + // + // Update the output buffer. + // + + Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics; + Buffer->DeviceType = FILE_DEVICE_CD_ROM; + + // + // Adjust the length variable + // + + *Length -= sizeof( FILE_FS_DEVICE_INFORMATION ); + + // + // And return success to our caller + // + + return STATUS_SUCCESS; +} + + +// +// Local support routine +// + +NTSTATUS +CdQueryFsAttributeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer, + _Inout_ PULONG Length + ) + +/*++ + +Routine Description: + + This routine implements the query volume attribute call. + +Arguments: + + Vcb - Vcb for this volume. + + Buffer - Supplies a pointer to the output buffer where the information + is to be returned + + Length - Supplies the length of the buffer in byte. This variable + upon return recieves the remaining bytes free in the buffer + +Return Value: + + NTSTATUS - Returns the status for the query + +--*/ + +{ + ULONG BytesToCopy; + + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER( Vcb ); + + // + // Fill out the fixed portion of the buffer. + // + + Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | + FILE_READ_ONLY_VOLUME | + FILE_SUPPORTS_OPEN_BY_FILE_ID; + + if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) { + + SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK ); + + Buffer->MaximumComponentNameLength = 110; + + } else { + + Buffer->MaximumComponentNameLength = 221; + } + + *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ); + + // + // Make sure we can copy full unicode characters. + // + + ClearFlag( *Length, 1 ); + + // + // Determine how much of the file system name will fit. + // + + if (*Length >= 8) { + + BytesToCopy = 8; + + } else { + + BytesToCopy = *Length; + Status = STATUS_BUFFER_OVERFLOW; + } + + *Length -= BytesToCopy; + + // + // Do the file system name. + // + + Buffer->FileSystemNameLength = BytesToCopy; + + RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy ); + + // + // And return to our caller + // + + return Status; +} + +#if (NTDDI_VERSION >= NTDDI_WIN8) + +NTSTATUS +CdQueryFsSectorSizeInfo ( + _In_ PIRP_CONTEXT IrpContext, + _In_ PVCB Vcb, + _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer, + _Inout_ PULONG Length + ) + +/*++ + +Routine Description: + + This routine implements the query sector size information call + This operation will work on any handle and requires no privilege. + +Arguments: + + Vcb - Supplies the Vcb being queried + + Buffer - Supplies a pointer to the output buffer where the information + is to be returned + + Length - Supplies the length of the buffer in byte. This variable + upon return receives the remaining bytes free in the buffer + +Return Value: + + NTSTATUS - Returns the status for the query + +--*/ + +{ + NTSTATUS Status; + + PAGED_CODE(); + UNREFERENCED_PARAMETER( IrpContext ); + + // + // Sufficient buffer size is guaranteed by the I/O manager or the + // originating kernel mode driver. + // + + ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION )); + _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION )); + + // + // Retrieve the sector size information + // + + Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice, + Buffer ); + + // + // Adjust the length variable + // + + if (NT_SUCCESS( Status )) { + + *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ); + } + + return Status; +} + +#endif + diff --git a/drivers/filesystems/cdfs_new/workque.c b/drivers/filesystems/cdfs/workque.c old mode 100755 new mode 100644 similarity index 100% rename from drivers/filesystems/cdfs_new/workque.c rename to drivers/filesystems/cdfs/workque.c diff --git a/drivers/filesystems/cdfs_new/write.c b/drivers/filesystems/cdfs/write.c similarity index 100% rename from drivers/filesystems/cdfs_new/write.c rename to drivers/filesystems/cdfs/write.c diff --git a/drivers/filesystems/cdfs_new/CMakeLists.txt b/drivers/filesystems/cdfs_new/CMakeLists.txt deleted file mode 100644 index 8bf4fa2639d..00000000000 --- a/drivers/filesystems/cdfs_new/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers) - -list(APPEND SOURCE - allocsup.c - cachesup.c - cddata.c - cdinit.c - cdprocssrc.c - cleanup.c - close.c - create.c - devctrl.c - deviosup.c - dirctrl.c - dirsup.c - fileinfo.c - filobsup.c - fsctrl.c - fspdisp.c - lockctrl.c - namesup.c - pathsup.c - pnp.c - prefxsup.c - read.c - resrcsup.c - shutdown.c - strucsup.c - verfysup.c - volinfo.c - workque.c - write.c) - -add_library(cdfs SHARED ${SOURCE} cdfs.rc) -set_module_type(cdfs kernelmodedriver) -target_link_libraries(cdfs ${PSEH_LIB} memcmp) -add_importlibs(cdfs ntoskrnl hal) -add_cd_file(TARGET cdfs DESTINATION reactos/system32/drivers NO_CAB FOR all) -add_registry_inf(cdfs_reg.inf) diff --git a/drivers/filesystems/cdfs_new/cdfs.rc b/drivers/filesystems/cdfs_new/cdfs.rc deleted file mode 100644 index 5d4dcafce01..00000000000 --- a/drivers/filesystems/cdfs_new/cdfs.rc +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright (C) Microsoft. All rights reserved. -// -#include - -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_SYSTEM -#define VER_FILEDESCRIPTION_STR "CD-ROM File System Driver" -#define VER_INTERNALNAME_STR "cdfs.sys" - -#include "common.ver" - diff --git a/drivers/filesystems/cdfs_new/cdfs_reg.inf b/drivers/filesystems/cdfs_new/cdfs_reg.inf deleted file mode 100644 index 9ae7413c613..00000000000 --- a/drivers/filesystems/cdfs_new/cdfs_reg.inf +++ /dev/null @@ -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 diff --git a/drivers/filesystems/cdfs_new/cleanup.c b/drivers/filesystems/cdfs_new/cleanup.c deleted file mode 100755 index 0cdda166f57..00000000000 --- a/drivers/filesystems/cdfs_new/cleanup.c +++ /dev/null @@ -1,366 +0,0 @@ -/*++ - -Copyright (c) 1989-2000 Microsoft Corporation - -Module Name: - - Cleanup.c - -Abstract: - - This module implements the File Cleanup routine for Cdfs called by the - dispatch driver. - - ---*/ - -#include "cdprocs.h" - -// -// The Bug check file id for this module -// - -#define BugCheckFileId (CDFS_BUG_CHECK_CLEANUP) - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdCommonCleanup ( - _Inout_ PIRP_CONTEXT IrpContext, - _Inout_ PIRP Irp - ) - -/*++ - -Routine Description: - - This is the common routine for cleanup of a file/directory called by both - the fsd and fsp threads. - - Cleanup is invoked whenever the last handle to a file object is closed. - This is different than the Close operation which is invoked when the last - reference to a file object is deleted. - - The function of cleanup is to essentially "cleanup" the file/directory - after a user is done with it. The Fcb/Dcb remains around (because MM - still has the file object referenced) but is now available for another - user to open (i.e., as far as the user is concerned the is now closed). - - See close for a more complete description of what close does. - - We do no synchronization in this routine until we get to the point - where we modify the counts, share access and volume lock field. - - We need to update the Fcb and Vcb to show that a user handle has been closed. - The following structures and fields are affected. - - Vcb: - - VolumeLockFileObject - Did the user lock the volume with this file object. - VcbState - Check if we are unlocking the volume here. - VcbCleanup - Count of outstanding handles on the volume. - DirNotifyQueue - If this file object has pending DirNotify Irps. - - Fcb: - - ShareAccess - If this is a user handle. - FcbCleanup - Count of outstanding handles on this Fcb. - Oplock - Any outstanding oplocks on this file object. - FileLock - Any outstanding filelocks on this file object. - -Arguments: - - Irp - Supplies the Irp to process - -Return Value: - - NTSTATUS - The return status for the operation. - ---*/ - -{ - PFILE_OBJECT FileObject; - TYPE_OF_OPEN TypeOfOpen; - - BOOLEAN SendUnlockNotification = FALSE; - BOOLEAN AttemptTeardown = FALSE; - BOOLEAN VcbAcquired = FALSE; - - PVCB Vcb; - PFCB Fcb; - PCCB Ccb; - - KIRQL SavedIrql; - - ASSERT_IRP_CONTEXT( IrpContext ); - ASSERT_IRP( Irp ); - - // - // If we were called with our file system device object instead of a - // volume device object, just complete this request with STATUS_SUCCESS. - // - - if (IrpContext->Vcb == NULL) { - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - return STATUS_SUCCESS; - } - - // - // Get the file object out of the Irp and decode the type of open. - // - - FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject; - - TypeOfOpen = CdDecodeFileObject( IrpContext, - FileObject, - &Fcb, - &Ccb ); - - // - // No work here for either an UnopenedFile object or a StreamFileObject. - // - - if (TypeOfOpen <= StreamFileOpen) { - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - - return STATUS_SUCCESS; - } - - // - // Keep a local pointer to the Vcb. - // - - Vcb = Fcb->Vcb; - - // - // Synchronise with reads while we set the cleanup complete - // flag on this fileobject. Once this flag is set, any further - // reads will be rejected (CdVerifyFcbOperation) - // - - CdAcquireFileExclusive( IrpContext, Fcb); - - // - // Set the flag in the FileObject to indicate that cleanup is complete. - // - - SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE ); - - CdReleaseFile( IrpContext, Fcb); - - if (TypeOfOpen == UserVolumeOpen) { - - // - // For a force dismount, physically disconnect this Vcb from the device so - // a new mount can occur. Vcb deletion cannot happen at this time since - // there is a reference on it associated with this very request, but we'll - // call check for dismount again later after we process this close. - // - - if (FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE )) { - - CdAcquireCdData( IrpContext ); - - CdCheckForDismount( IrpContext, Vcb, TRUE ); - - CdReleaseCdData( IrpContext ); - - // - // If this handle actually wrote something, flush the device buffers, - // and then set the verify bit now just to be safe (in case there is no - // dismount). - // - - } else if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) { - - CdHijackIrpAndFlushDevice( IrpContext, Irp, Vcb->TargetDeviceObject ); - - CdMarkDevForVerifyIfVcbMounted( Vcb ); - } - } - - // - // Acquire the current file. - // - - CdAcquireFcbExclusive( IrpContext, Fcb, FALSE ); - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Case on the type of open that we are trying to cleanup. - // - - switch (TypeOfOpen) { - - case UserDirectoryOpen: - - // - // Check if we need to complete any dir notify Irps on this file object. - // - - FsRtlNotifyCleanup( Vcb->NotifySync, - &Vcb->DirNotifyList, - Ccb ); - - break; - - case UserFileOpen: - - // - // Coordinate the cleanup operation with the oplock state. - // Oplock cleanup operations can always cleanup immediately so no - // need to check for STATUS_PENDING. - // - - FsRtlCheckOplock( CdGetFcbOplock(Fcb), - Irp, - IrpContext, - NULL, - NULL ); - - // - // Unlock all outstanding file locks. - // - - if (Fcb->FileLock != NULL) { - - FsRtlFastUnlockAll( Fcb->FileLock, - FileObject, - IoGetRequestorProcess( Irp ), - NULL ); - } - - // - // Cleanup the cache map. - // - - CcUninitializeCacheMap( FileObject, NULL, NULL ); - - // - // Check the fast io state. - // - - CdLockFcb( IrpContext, Fcb ); - Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); - CdUnlockFcb( IrpContext, Fcb ); - - break; - - case UserVolumeOpen: - - break; - - default : - -#ifdef _MSC_VER -#pragma prefast( suppress:__WARNING_USE_OTHER_FUNCTION, "argument bogus" ) -#endif - CdBugCheck( TypeOfOpen, 0, 0 ); - } - - // - // Now lock the Vcb in order to modify the fields in the in-memory - // structures. - // - - CdLockVcb( IrpContext, Vcb ); - - // - // Decrement the cleanup counts in the Vcb and Fcb. - // - - CdDecrementCleanupCounts( IrpContext, Fcb ); - - // - // If the cleanup count hit zero and the volume is not mounted, we - // will want to try to spark teardown. - // - - AttemptTeardown = (Vcb->VcbCleanup == 0 && Vcb->VcbCondition == VcbNotMounted); - - // - // If this file object has locked the volume then perform the unlock operation. - // We do this regardless of explicit or implicit (no share DASD open) lock. - // - - if (FileObject == Vcb->VolumeLockFileObject) { - - NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_LOCKED)); - - IoAcquireVpbSpinLock( &SavedIrql ); - - ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED); - ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED ); - Vcb->VolumeLockFileObject = NULL; - SendUnlockNotification = TRUE; - - IoReleaseVpbSpinLock( SavedIrql ); - } - - CdUnlockVcb( IrpContext, Vcb ); - - // - // We must clean up the share access at this time, since we may not - // get a Close call for awhile if the file was mapped through this - // File Object. - // - - IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); - - } _SEH2_FINALLY { - - CdReleaseFcb( IrpContext, Fcb ); - - if (SendUnlockNotification) { - - FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK ); - } - } _SEH2_END; - - // - // If appropriate, try to spark teardown by purging the volume. Should - // this very fileobject we were cleaning up be the last reason for the - // volume to remain, teardown will commence on completion of this Irp. - // - - if (AttemptTeardown) { - - // - // Preacquire CdData here, since the purges will generate closes which - // may acquire CdData if there is a possibility of tearing the volume - // down. - // - - CdAcquireCdData( IrpContext); - - _SEH2_TRY { - - CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); - VcbAcquired = TRUE; - - CdPurgeVolume( IrpContext, Vcb, FALSE ); - - } _SEH2_FINALLY { - - if (VcbAcquired) { CdReleaseVcb( IrpContext, Vcb ); } - - CdReleaseCdData( IrpContext); - } _SEH2_END; - } - - // - // If this is a normal termination then complete the request - // - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - - return STATUS_SUCCESS; -} - - diff --git a/drivers/filesystems/cdfs_new/close.c b/drivers/filesystems/cdfs_new/close.c deleted file mode 100755 index fecb1e6dbfb..00000000000 --- a/drivers/filesystems/cdfs_new/close.c +++ /dev/null @@ -1,1023 +0,0 @@ -/*++ - -Copyright (c) 1989-2000 Microsoft Corporation - -Module Name: - - Close.c - -Abstract: - - This module implements the File Close routine for Cdfs called by the - Fsd/Fsp dispatch routines. - - The close operation interacts with both the async and delayed close queues - in the CdData structure. Since close may be called recursively we may - violate the locking order in acquiring the Vcb or Fcb. In this case - we may move the request to the async close queue. If this is the last - reference on the Fcb and there is a chance the user may reopen this - file again soon we would like to defer the close. In this case we - may move the request to the async close queue. - - Once we are past the decode file operation there is no need for the - file object. If we are moving the request to either of the work - queues then we remember all of the information from the file object and - complete the request with STATUS_SUCCESS. The Io system can then - reuse the file object and we can complete the request when convenient. - - The async close queue consists of requests which we would like to - complete as soon as possible. They are queued using the original - IrpContext where some of the fields have been overwritten with - information from the file object. We will extract this information, - cleanup the IrpContext and then call the close worker routine. - - The delayed close queue consists of requests which we would like to - defer the close for. We keep size of this list within a range - determined by the size of the system. We let it grow to some maximum - value and then shrink to some minimum value. We allocate a small - structure which contains the key information from the file object - and use this information along with an IrpContext on the stack - to complete the request. - - ---*/ - -#include "cdprocs.h" - -// -// The Bug check file id for this module -// - -#define BugCheckFileId (CDFS_BUG_CHECK_CLOSE) - -// -// Local support routines -// - -_Requires_lock_held_(_Global_critical_region_) -BOOLEAN -CdCommonClosePrivate ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _In_ PFCB Fcb, - _In_ ULONG UserReference, - _In_ BOOLEAN FromFsd - ); - -VOID -CdQueueClose ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PFCB Fcb, - _In_ ULONG UserReference, - _In_ BOOLEAN DelayedClose - ); - -PIRP_CONTEXT -CdRemoveClose ( - _In_opt_ PVCB Vcb - ); - -// Tell prefast this is a workitem routine -IO_WORKITEM_ROUTINE CdCloseWorker; - -VOID -NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ -CdCloseWorker ( - _In_ PDEVICE_OBJECT DeviceObject, - _In_opt_ PVOID Context - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, CdFspClose) -#pragma alloc_text(PAGE, CdCommonClose) -#pragma alloc_text(PAGE, CdCommonClosePrivate) -#pragma alloc_text(PAGE, CdQueueClose) -#pragma alloc_text(PAGE, CdRemoveClose) -#pragma alloc_text(PAGE, CdCloseWorker) -#endif - - -VOID -CdFspClose ( - _In_opt_ PVCB Vcb - ) - -/*++ - -Routine Description: - - This routine is called to process the close queues in the CdData. If the - Vcb is passed then we want to remove all of the closes for this Vcb. - Otherwise we will do as many of the delayed closes as we need to do. - -Arguments: - - Vcb - If specified then we are looking for all of the closes for the - given Vcb. - -Return Value: - - None - ---*/ - -{ - PIRP_CONTEXT IrpContext; - IRP_CONTEXT StackIrpContext; - - THREAD_CONTEXT ThreadContext = {0}; - - PFCB Fcb; - ULONG UserReference; - - ULONG VcbHoldCount = 0; - PVCB CurrentVcb = NULL; - - BOOLEAN PotentialVcbTeardown = FALSE; - - PAGED_CODE(); - - FsRtlEnterFileSystem(); - - // - // Continue processing until there are no more closes to process. - // - - while ((IrpContext = CdRemoveClose( Vcb )) != NULL) { - - // - // If we don't have an IrpContext then use the one on the stack. - // Initialize it for this request. - // - - if (SafeNodeType( IrpContext ) != CDFS_NTC_IRP_CONTEXT ) { - - // - // Update the local values from the IrpContextLite. - // - - Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb; - UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference; - - // - // Update the stack irp context with the values from the - // IrpContextLite. - // - - CdInitializeStackIrpContext( &StackIrpContext, - (PIRP_CONTEXT_LITE) IrpContext ); - - // - // Free the IrpContextLite. - // - - CdFreeIrpContextLite( *(PVOID*)&IrpContext ); /* ReactOS Change: GCC "error: invalid lvalue in unary '&'" */ - - // - // Remember we have the IrpContext from the stack. - // - - IrpContext = &StackIrpContext; - - // - // Otherwise cleanup the existing IrpContext. - // - - } else { - - // - // Remember the Fcb and user reference count. - // - - Fcb = (PFCB) IrpContext->Irp; - IrpContext->Irp = NULL; - - UserReference = (ULONG) IrpContext->ExceptionStatus; - IrpContext->ExceptionStatus = STATUS_SUCCESS; - } - - _Analysis_assume_(Fcb != NULL && Fcb->Vcb != NULL); - - // - // We have an IrpContext. Now we need to set the top level thread - // context. - // - - SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS ); - - // - // If we were given a Vcb then there is a request on top of this. - // - - if (ARGUMENT_PRESENT( Vcb )) { - - ClearFlag( IrpContext->Flags, - IRP_CONTEXT_FLAG_TOP_LEVEL | IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS ); - } - - CdSetThreadContext( IrpContext, &ThreadContext ); - - // - // If we have hit the maximum number of requests to process without - // releasing the Vcb then release the Vcb now. If we are holding - // a different Vcb to this one then release the previous Vcb. - // - // In either case acquire the current Vcb. - // - // We use the MinDelayedCloseCount from the CdData since it is - // a convenient value based on the system size. Only thing we are trying - // to do here is prevent this routine starving other threads which - // may need this Vcb exclusively. - // - // Note that the check for potential teardown below is unsafe. We'll - // repeat later within the cddata lock. - // - - PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) && - (Fcb->Vcb->VcbCondition != VcbMounted) && - (Fcb->Vcb->VcbCondition != VcbMountInProgress) && - (Fcb->Vcb->VcbCleanup == 0); - - if (PotentialVcbTeardown || - (VcbHoldCount > CdData.MinDelayedCloseCount) || - (Fcb->Vcb != CurrentVcb)) { - - if (CurrentVcb != NULL) { - - CdReleaseVcb( IrpContext, CurrentVcb ); - } - - if (PotentialVcbTeardown) { - - CdAcquireCdData( IrpContext ); - - // - // Repeat the checks with global lock held. The volume could have - // been remounted while we didn't hold the lock. - // - - PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) && - (Fcb->Vcb->VcbCondition != VcbMounted) && - (Fcb->Vcb->VcbCondition != VcbMountInProgress) && - (Fcb->Vcb->VcbCleanup == 0); - - if (!PotentialVcbTeardown) { - - CdReleaseCdData( IrpContext); - } - } - - CurrentVcb = Fcb->Vcb; - - _Analysis_assume_( CurrentVcb != NULL ); - - CdAcquireVcbShared( IrpContext, CurrentVcb, FALSE ); - - VcbHoldCount = 0; - - } else { - - VcbHoldCount += 1; - } - - // - // Call our worker routine to perform the close operation. - // - - CdCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE ); - - // - // If the reference count on this Vcb is below our residual reference - // then check if we should dismount the volume. - // - - if (PotentialVcbTeardown) { - - CdReleaseVcb( IrpContext, CurrentVcb ); - CdCheckForDismount( IrpContext, CurrentVcb, FALSE ); - - CurrentVcb = NULL; - - CdReleaseCdData( IrpContext ); - PotentialVcbTeardown = FALSE; - } - - // - // Complete the current request to cleanup the IrpContext. - // - - CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); - } - - // - // Release any Vcb we may still hold. - // - - if (CurrentVcb != NULL) { - - CdReleaseVcb( IrpContext, CurrentVcb ); - - } - -#ifdef _MSC_VER -#pragma prefast(suppress:26165, "Esp:1153") -#endif - FsRtlExitFileSystem(); -} - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdCommonClose ( - _Inout_ PIRP_CONTEXT IrpContext, - _Inout_ PIRP Irp - ) - -/*++ - -Routine Description: - - This routine is the Fsd entry for the close operation. We decode the file - object to find the CDFS structures and type of open. We call our internal - worker routine to perform the actual work. If the work wasn't completed - then we post to one of our worker queues. The Ccb isn't needed after this - point so we delete the Ccb and return STATUS_SUCCESS to our caller in all - cases. - -Arguments: - - Irp - Supplies the Irp to process - -Return Value: - - STATUS_SUCCESS - ---*/ - -{ - TYPE_OF_OPEN TypeOfOpen; - - PVCB Vcb; - PFCB Fcb; - PCCB Ccb; - ULONG UserReference = 0; - - BOOLEAN PotentialVcbTeardown = FALSE; - - PAGED_CODE(); - - ASSERT_IRP_CONTEXT( IrpContext ); - ASSERT_IRP( Irp ); - - // - // If we were called with our file system device object instead of a - // volume device object, just complete this request with STATUS_SUCCESS. - // - - if (IrpContext->Vcb == NULL) { - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - return STATUS_SUCCESS; - } - - // - // Decode the file object to get the type of open and Fcb/Ccb. - // - - TypeOfOpen = CdDecodeFileObject( IrpContext, - IoGetCurrentIrpStackLocation( Irp )->FileObject, - &Fcb, - &Ccb ); - - // - // No work to do for unopened file objects. - // - - if (TypeOfOpen == UnopenedFileObject) { - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - - return STATUS_SUCCESS; - } - - Vcb = Fcb->Vcb; - - // - // Clean up any CCB associated with this open. - // - - if (Ccb != NULL) { - - UserReference = 1; - - // - // We can always deallocate the Ccb if present. - // - - CdDeleteCcb( IrpContext, Ccb ); - } - - // - // If this is the last reference to a user file or directory on a - // currently mounted volume, then post it to the delayed close queue. Note - // that the VcbCondition check is unsafe, but it doesn't really matter - - // we just might delay the volume teardown a little by posting this close. - // - - if ((Vcb->VcbCondition == VcbMounted) && - (Fcb->FcbReference == 1) && - ((TypeOfOpen == UserFileOpen) || - (TypeOfOpen == UserDirectoryOpen))) { - - CdQueueClose( IrpContext, Fcb, UserReference, TRUE ); - IrpContext = NULL; - - // - // Otherwise try to process this close. Post to the async close queue - // if we can't acquire all of the resources. - // - - } - else { - - // - // If we may be dismounting this volume then acquire the CdData - // resource. - // - // Since we now must make volumes go away as soon as reasonable after - // the last user handles closes, key off of the cleanup count. It is - // OK to do this more than neccesary. Since this Fcb could be holding - // a number of other Fcbs (and thus their references), a simple check - // on reference count is not appropriate. - // - // Do an unsafe check first to avoid taking the (global) cddata lock in the - // common case. - // - - if ((Vcb->VcbCleanup == 0) && - (Vcb->VcbCondition != VcbMounted)) { - - // - // Possible dismount. Acquire CdData to synchronise with the remount path - // before looking at the vcb condition again. - // - - CdAcquireCdData( IrpContext ); - - if ((Vcb->VcbCleanup == 0) && - (Vcb->VcbCondition != VcbMounted) && - (Vcb->VcbCondition != VcbMountInProgress) && - FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS )) { - - PotentialVcbTeardown = TRUE; - } - else { - - // - // We can't dismount this volume now, there are other references or - // it's just been remounted. - // - } - - // - // Drop the global lock if we don't need it anymore. - // - - if (!PotentialVcbTeardown) { - - CdReleaseCdData( IrpContext ); - } - } - - // - // Call the worker routine to perform the actual work. This routine - // should never raise except for a fatal error. - // - - if (!CdCommonClosePrivate( IrpContext, Vcb, Fcb, UserReference, TRUE )) { - - // - // If we didn't complete the request then post the request as needed. - // - - CdQueueClose( IrpContext, Fcb, UserReference, FALSE ); - IrpContext = NULL; - - // - // Check whether we should be dismounting the volume and then complete - // the request. - // - - } - else if (PotentialVcbTeardown) { - - CdCheckForDismount( IrpContext, Vcb, FALSE ); - } - } - - // - // Always complete this request with STATUS_SUCCESS. - // - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - - if (PotentialVcbTeardown) { - - CdReleaseCdData( IrpContext ); - } - - // - // Always return STATUS_SUCCESS for closes. - // - - return STATUS_SUCCESS; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -BOOLEAN -CdCommonClosePrivate ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _In_ PFCB Fcb, - _In_ ULONG UserReference, - _In_ BOOLEAN FromFsd - ) - -/*++ - -Routine Description: - - This is the worker routine for the close operation. We can be called in - an Fsd thread or from a worker Fsp thread. If called from the Fsd thread - then we acquire the resources without waiting. Otherwise we know it is - safe to wait. - - We check to see whether we should post this request to the delayed close - queue. If we are to process the close here then we acquire the Vcb and - Fcb. We will adjust the counts and call our teardown routine to see - if any of the structures should go away. - -Arguments: - - Vcb - Vcb for this volume. - - Fcb - Fcb for this request. - - UserReference - Number of user references for this file object. This is - zero for an internal stream. - - FromFsd - This request was called from an Fsd thread. Indicates whether - we should wait to acquire resources. - - DelayedClose - Address to store whether we should try to put this on - the delayed close queue. Ignored if this routine can process this - close. - -Return Value: - - BOOLEAN - TRUE if this thread processed the close, FALSE otherwise. - ---*/ - -{ - BOOLEAN RemovedFcb; - - PAGED_CODE(); - - ASSERT_IRP_CONTEXT( IrpContext ); - ASSERT_FCB( Fcb ); - - // - // Try to acquire the Vcb and Fcb. If we can't acquire them then return - // and let our caller know he should post the request to the async - // queue. - // - - if (CdAcquireVcbShared( IrpContext, Vcb, FromFsd )) { - - if (!CdAcquireFcbExclusive( IrpContext, Fcb, FromFsd )) { - - // - // We couldn't get the Fcb. Release the Vcb and let our caller - // know to post this request. - // - - CdReleaseVcb( IrpContext, Vcb ); - return FALSE; - } - - // - // We didn't get the Vcb. Let our caller know to post this request. - // - - } else { - - return FALSE; - } - - // - // Lock the Vcb and decrement the reference counts. - // - - CdLockVcb( IrpContext, Vcb ); - CdDecrementReferenceCounts( IrpContext, Fcb, 1, UserReference ); - CdUnlockVcb( IrpContext, Vcb ); - - // - // Call our teardown routine to see if this object can go away. - // If we don't remove the Fcb then release it. - // - - CdTeardownStructures( IrpContext, Fcb, &RemovedFcb ); - - if (!RemovedFcb) { - - CdReleaseFcb( IrpContext, Fcb ); - } - else { - _Analysis_assume_lock_not_held_(Fcb->FcbNonpaged->FcbResource); - } - - // - // Release the Vcb and return to our caller. Let him know we completed - // this request. - // - - CdReleaseVcb( IrpContext, Vcb ); - - return TRUE; -} - -VOID -NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ -CdCloseWorker ( - _In_ PDEVICE_OBJECT DeviceObject, - _In_opt_ PVOID Context - ) -/*++ - -Routine Description: - - Worker routine to call CsFspClose. - -Arguments: - - DeviceObject - Filesystem registration device object - - Context - Callers context - -Return Value: - - None - ---*/ - -{ - PAGED_CODE(); - - UNREFERENCED_PARAMETER( DeviceObject ); - UNREFERENCED_PARAMETER( Context ); - - CdFspClose (NULL); -} - - -VOID -CdQueueClose ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PFCB Fcb, - _In_ ULONG UserReference, - _In_ BOOLEAN DelayedClose - ) - -/*++ - -Routine Description: - - This routine is called to queue a request to either the async or delayed - close queue. For the delayed queue we need to allocate a smaller - structure to contain the information about the file object. We do - that so we don't put the larger IrpContext structures into this long - lived queue. If we can allocate this structure then we put this - on the async queue instead. - -Arguments: - - Fcb - Fcb for this file object. - - UserReference - Number of user references for this file object. This is - zero for an internal stream. - - DelayedClose - Indicates whether this should go on the async or delayed - close queue. - -Return Value: - - None - ---*/ - -{ - PIRP_CONTEXT_LITE IrpContextLite = NULL; - BOOLEAN StartWorker = FALSE; - - PAGED_CODE(); - - ASSERT_IRP_CONTEXT( IrpContext ); - ASSERT_FCB( Fcb ); - - // - // Start with the delayed queue request. We can move this to the async - // queue if there is an allocation failure. - // - - if (DelayedClose) { - - // - // Try to allocate non-paged pool for the IRP_CONTEXT_LITE. - // - - IrpContextLite = CdCreateIrpContextLite( IrpContext ); - } - - // - // We want to clear the top level context in this thread if - // necessary. Call our cleanup routine to do the work. - // - - SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING ); - CdCleanupIrpContext( IrpContext, TRUE ); - - // - // Synchronize with the CdData lock. - // - - CdLockCdData(); - - // - // If we have an IrpContext then put the request on the delayed close queue. - // - - if (IrpContextLite != NULL) { - - // - // Initialize the IrpContextLite. - // - - IrpContextLite->NodeTypeCode = CDFS_NTC_IRP_CONTEXT_LITE; - IrpContextLite->NodeByteSize = sizeof( IRP_CONTEXT_LITE ); - IrpContextLite->Fcb = Fcb; - IrpContextLite->UserReference = UserReference; - IrpContextLite->RealDevice = IrpContext->RealDevice; - - // - // Add this to the delayed close list and increment - // the count. - // - - InsertTailList( &CdData.DelayedCloseQueue, - &IrpContextLite->DelayedCloseLinks ); - - CdData.DelayedCloseCount += 1; - - // - // If we are above our threshold then start the delayed - // close operation. - // - - if (CdData.DelayedCloseCount > CdData.MaxDelayedCloseCount) { - - CdData.ReduceDelayedClose = TRUE; - - if (!CdData.FspCloseActive) { - - CdData.FspCloseActive = TRUE; - StartWorker = TRUE; - } - } - - // - // Unlock the CdData. - // - - CdUnlockCdData(); - - // - // Cleanup the IrpContext. - // - - CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); - - // - // Otherwise drop into the async case below. - // - - } else { - - // - // Store the information about the file object into the IrpContext. - // - - IrpContext->Irp = (PIRP) Fcb; - IrpContext->ExceptionStatus = (NTSTATUS) UserReference; - - // - // Add this to the async close list and increment the count. - // - - InsertTailList( &CdData.AsyncCloseQueue, - &IrpContext->WorkQueueItem.List ); - - CdData.AsyncCloseCount += 1; - - // - // Remember to start the Fsp close thread if not currently started. - // - - if (!CdData.FspCloseActive) { - - CdData.FspCloseActive = TRUE; - - StartWorker = TRUE; - } - - // - // Unlock the CdData. - // - - CdUnlockCdData(); - } - - // - // Start the FspClose thread if we need to. - // - - if (StartWorker) { - - IoQueueWorkItem( CdData.CloseItem, CdCloseWorker, CriticalWorkQueue, NULL ); - } - - // - // Return to our caller. - // - - return; -} - - -// -// Local support routine -// - -PIRP_CONTEXT -CdRemoveClose ( - _In_opt_ PVCB Vcb - ) - -/*++ - -Routine Description: - -Arguments: - - This routine is called to scan the async and delayed close queues looking - for a suitable entry. If the Vcb is specified then we scan both queues - looking for an entry with the same Vcb. Otherwise we will look in the - async queue first for any close item. If none found there then we look - in the delayed close queue provided that we have triggered the delayed - close operation. - -Return Value: - - PIRP_CONTEXT - NULL if no work item found. Otherwise it is the pointer to - either the IrpContext or IrpContextLite for this request. - ---*/ - -{ - PIRP_CONTEXT IrpContext = NULL; - PIRP_CONTEXT NextIrpContext; - PIRP_CONTEXT_LITE NextIrpContextLite; - - PLIST_ENTRY Entry; - - PAGED_CODE(); - - ASSERT_OPTIONAL_VCB( Vcb ); - - // - // Lock the CdData to perform the scan. - // - - CdLockCdData(); - - // - // First check the list of async closes. - // - - Entry = CdData.AsyncCloseQueue.Flink; - - while (Entry != &CdData.AsyncCloseQueue) { - - // - // Extract the IrpContext. - // - - NextIrpContext = CONTAINING_RECORD( Entry, - IRP_CONTEXT, - WorkQueueItem.List ); - - // - // If no Vcb was specified or this Vcb is for our volume - // then perform the close. - // - - if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContext->Vcb == Vcb)) { - - RemoveEntryList( Entry ); - CdData.AsyncCloseCount -= 1; - - IrpContext = NextIrpContext; - break; - } - - // - // Move to the next entry. - // - - Entry = Entry->Flink; - } - - // - // If we didn't find anything look through the delayed close - // queue. - // - // We will only check the delayed close queue if we were given - // a Vcb or the delayed close operation is active. - // - - if ((IrpContext == NULL) && - (ARGUMENT_PRESENT( Vcb ) || - (CdData.ReduceDelayedClose && - (CdData.DelayedCloseCount > CdData.MinDelayedCloseCount)))) { - - Entry = CdData.DelayedCloseQueue.Flink; - - while (Entry != &CdData.DelayedCloseQueue) { - - // - // Extract the IrpContext. - // - - NextIrpContextLite = CONTAINING_RECORD( Entry, - IRP_CONTEXT_LITE, - DelayedCloseLinks ); - - // - // If no Vcb was specified or this Vcb is for our volume - // then perform the close. - // - - if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContextLite->Fcb->Vcb == Vcb)) { - - RemoveEntryList( Entry ); - CdData.DelayedCloseCount -= 1; - - IrpContext = (PIRP_CONTEXT) NextIrpContextLite; - break; - } - - // - // Move to the next entry. - // - - Entry = Entry->Flink; - } - } - - // - // If the Vcb wasn't specified and we couldn't find an entry - // then turn off the Fsp thread. - // - - if (!ARGUMENT_PRESENT( Vcb ) && (IrpContext == NULL)) { - - CdData.FspCloseActive = FALSE; - CdData.ReduceDelayedClose = FALSE; - } - - // - // Unlock the CdData. - // - - CdUnlockCdData(); - - return IrpContext; -} - - - diff --git a/drivers/filesystems/cdfs_new/create.c b/drivers/filesystems/cdfs_new/create.c deleted file mode 100755 index 1fb744139e1..00000000000 --- a/drivers/filesystems/cdfs_new/create.c +++ /dev/null @@ -1,2972 +0,0 @@ -/*++ - -Copyright (c) 1989-2000 Microsoft Corporation - -Module Name: - - Create.c - -Abstract: - - This module implements the File Create routine for Cdfs called by the - Fsd/Fsp dispatch routines. - - ---*/ - -#include "cdprocs.h" - -// -// The Bug check file id for this module -// - -#define BugCheckFileId (CDFS_BUG_CHECK_CREATE) - -// -// Local support routines -// - -_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_)) -_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_)) -_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_)) -_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_)) -NTSTATUS -CdNormalizeFileNames ( - _Inout_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _In_ BOOLEAN OpenByFileId, - _In_ BOOLEAN IgnoreCase, - _In_ TYPE_OF_OPEN RelatedTypeOfOpen, - PCCB RelatedCcb, - PUNICODE_STRING RelatedFileName, - _Inout_ PUNICODE_STRING FileName, - _Inout_ PCD_NAME RemainingName - ); - -_Requires_lock_held_(_Global_critical_region_) -_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) -NTSTATUS -CdOpenByFileId ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb - ); - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdOpenExistingFcb ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _Inout_ PFCB *CurrentFcb, - _In_ TYPE_OF_OPEN TypeOfOpen, - _In_ BOOLEAN IgnoreCase, - _In_opt_ PCCB RelatedCcb - ); - -_Requires_lock_held_(_Global_critical_region_) -_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) -NTSTATUS -CdOpenDirectoryFromPathEntry ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ PCD_NAME DirName, - _In_ BOOLEAN IgnoreCase, - _In_ BOOLEAN ShortNameMatch, - _In_ PPATH_ENTRY PathEntry, - _In_ BOOLEAN PerformUserOpen, - _In_opt_ PCCB RelatedCcb - ); - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdOpenFileFromFileContext ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ PCD_NAME FileName, - _In_ BOOLEAN IgnoreCase, - _In_ BOOLEAN ShortNameMatch, - _In_ PFILE_ENUM_CONTEXT FileContext, - _In_opt_ PCCB RelatedCcb - ); - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdCompleteFcbOpen ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ TYPE_OF_OPEN TypeOfOpen, - _In_ ULONG UserCcbFlags, - _In_ ACCESS_MASK DesiredAccess - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, CdCommonCreate) -#pragma alloc_text(PAGE, CdCompleteFcbOpen) -#pragma alloc_text(PAGE, CdNormalizeFileNames) -#pragma alloc_text(PAGE, CdOpenByFileId) -#pragma alloc_text(PAGE, CdOpenDirectoryFromPathEntry) -#pragma alloc_text(PAGE, CdOpenExistingFcb) -#pragma alloc_text(PAGE, CdOpenFileFromFileContext) -#endif - - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -#ifdef _MSC_VER -#pragma prefast(suppress:26165, "Esp:1153") -#endif -CdCommonCreate ( - _Inout_ PIRP_CONTEXT IrpContext, - _Inout_ PIRP Irp - ) - -/*++ - -Routine Description: - - This is the common routine for opening a file called by both the - Fsp and Fsd threads. - - The file can be opened either by name or by file Id either with or without - a relative name. The file name field in the file object passed to this routine - contains either a unicode string or a 64 bit value which is the file Id. - If this is not a Joliet disk then we will convert the unicode name to - an Oem string in this routine. If there is a related file object with - a name then we will already have converted that name to Oem. - - We will store the full name for the file in the file object on a successful - open. We will allocate a larger buffer if necessary and combine the - related and file object names. The only exception is the relative open - when the related file object is for an OpenByFileId file. If we need to - allocate a buffer for a case insensitive name then we allocate it at - the tail of the buffer we will store into the file object. The upcased - portion will begin immediately after the name defined by the FileName - in the file object. - - Once we have the full name in the file object we don't want to split the - name in the event of a retry. We use a flag in the IrpContext to indicate - that the name has been split. - -Arguments: - - Irp - Supplies the Irp to process - -Return Value: - - NTSTATUS - This is the status from this open operation. - ---*/ - -{ - NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); - - PFILE_OBJECT FileObject; - - COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ - BOOLEAN CleanupCompoundPathEntry = FALSE; - - FILE_ENUM_CONTEXT FileContext = {0}; - BOOLEAN CleanupFileContext = FALSE; - BOOLEAN FoundEntry; - - PVCB Vcb; - - BOOLEAN OpenByFileId; - BOOLEAN IgnoreCase; - ULONG CreateDisposition; - - BOOLEAN ShortNameMatch; - ULONG ShortNameDirentOffset; - - BOOLEAN VolumeOpen = FALSE; - - // - // We will be acquiring and releasing file Fcb's as we move down the - // directory tree during opens. At any time we need to know the deepest - // point we have traversed down in the tree in case we need to cleanup - // any structures created here. - // - // CurrentFcb - represents this point. If non-null it means we have - // acquired it and need to release it in finally clause. - // - // NextFcb - represents the NextFcb to walk to but haven't acquired yet. - // - - TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject; - PFILE_OBJECT RelatedFileObject; - PCCB RelatedCcb = NULL; - - PFCB NextFcb; - PFCB CurrentFcb = NULL; - - // - // During the open we need to combine the related file object name - // with the remaining name. We also may need to upcase the file name - // in order to do a case-insensitive name comparison. We also need - // to restore the name in the file object in the event that we retry - // the request. We use the following string variables to manage the - // name. We will can put these strings into either Unicode or Ansi - // form. - // - // FileName - Pointer to name as currently stored in the file - // object. We store the full name into the file object early in - // the open operation. - // - // RelatedFileName - Pointer to the name in the related file object. - // - // RemainingName - String containing remaining name to parse. - // - // MatchingName - Address of name structure in FileContext which matched. - // We need this to know whether we matched the long or short name. - // - - PUNICODE_STRING FileName; - PUNICODE_STRING RelatedFileName = NULL; - - CD_NAME RemainingName = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ - CD_NAME FinalName; - PCD_NAME MatchingName = NULL; - - PAGED_CODE(); - - // - // If we were called with our file system device object instead of a - // volume device object, just complete this request with STATUS_SUCCESS. - // - - if (IrpContext->Vcb == NULL) { - - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - return STATUS_SUCCESS; - } - - // - // Get create parameters from the Irp. - // - - OpenByFileId = BooleanFlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID ); - IgnoreCase = !BooleanFlagOn( IrpSp->Flags, SL_CASE_SENSITIVE ); - CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff; - - // - // Do some preliminary checks to make sure the operation is supported. - // We fail in the following cases immediately. - // - // - Open a paging file. - // - Open a target directory. - // - Open a file with Eas. - // - Create a file. - // - - if (FlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE | SL_OPEN_TARGET_DIRECTORY) || - (IrpSp->Parameters.Create.EaLength != 0) || - (CreateDisposition == FILE_CREATE)) { - - CdCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED ); - return STATUS_ACCESS_DENIED; - } - -#if (NTDDI_VERSION >= NTDDI_WIN7) - // - // CDFS does not support FILE_OPEN_REQUIRING_OPLOCK - // - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_REQUIRING_OPLOCK )) { - - CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); - return STATUS_INVALID_PARAMETER; - } -#endif - - // - // Copy the Vcb to a local. Assume the starting directory is the root. - // - - Vcb = IrpContext->Vcb; - NextFcb = Vcb->RootIndexFcb; - - // - // Reference our input parameters to make things easier - // - - FileObject = IrpSp->FileObject; - RelatedFileObject = NULL; - - FileName = &FileObject->FileName; - - // - // Set up the file object's Vpb pointer in case anything happens. - // This will allow us to get a reasonable pop-up. - // - - if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) { - - RelatedFileObject = FileObject->RelatedFileObject; - FileObject->Vpb = RelatedFileObject->Vpb; - - RelatedTypeOfOpen = CdDecodeFileObject( IrpContext, RelatedFileObject, &NextFcb, &RelatedCcb ); - - // - // Fail the request if this is not a user file object. - // - - if (RelatedTypeOfOpen < UserVolumeOpen) { - - CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); - return STATUS_INVALID_PARAMETER; - } - - // - // Remember the name in the related file object. - // - - RelatedFileName = &RelatedFileObject->FileName; - } - - // - // If we haven't initialized the names then make sure the strings are valid. - // If this an OpenByFileId then verify the file id buffer. - // - // After this routine returns we know that the full name is in the - // FileName buffer and the buffer will hold the upcased portion - // of the name yet to parse immediately after the full name in the - // buffer. Any trailing backslash has been removed and the flag - // in the IrpContext will indicate whether we removed the - // backslash. - // - - Status = CdNormalizeFileNames( IrpContext, - Vcb, - OpenByFileId, - IgnoreCase, - RelatedTypeOfOpen, - RelatedCcb, - RelatedFileName, - FileName, - &RemainingName ); - - // - // Return the error code if not successful. - // - - if (!NT_SUCCESS( Status )) { - - CdCompleteRequest( IrpContext, Irp, Status ); - return Status; - } - - // - // We want to acquire the Vcb. Exclusively for a volume open, shared otherwise. - // The file name is empty for a volume open. - // - - if ((FileName->Length == 0) && - (RelatedTypeOfOpen <= UserVolumeOpen) && - !OpenByFileId) { - - VolumeOpen = TRUE; - CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); - - } else { - - CdAcquireVcbShared( IrpContext, Vcb, FALSE ); - } - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Verify that the Vcb is not in an unusable condition. This routine - // will raise if not usable. - // - - CdVerifyVcb( IrpContext, Vcb ); - - // - // If the Vcb is locked then we cannot open another file - // - - if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - // - // If we are opening this file by FileId then process this immediately - // and exit. - // - - if (OpenByFileId) { - - // - // We only allow Dasd opens of audio disks. Fail this request at - // this point. - // - - if (FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) { - - try_return( Status = STATUS_INVALID_DEVICE_REQUEST ); - } - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - // - // Make sure we can wait for this request. - // - - if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { - - CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); - } - - try_return( Status = CdOpenByFileId( IrpContext, - IrpSp, - Vcb, - &CurrentFcb )); - } - - // - // If we are opening this volume Dasd then process this immediately - // and exit. - // - - if (VolumeOpen) { - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - // - // If they wanted to open a directory, surprise. - // - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - - try_return( Status = STATUS_NOT_A_DIRECTORY ); - } - - // - // Acquire the Fcb first. - // - - CurrentFcb = Vcb->VolumeDasdFcb; - CdAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE ); - - try_return( Status = CdOpenExistingFcb( IrpContext, - IrpSp, - &CurrentFcb, - UserVolumeOpen, - FALSE, - NULL )); - } - - // - // At this point CurrentFcb points to the deepest Fcb for this open - // in the tree. Let's acquire this Fcb to keep it from being deleted - // beneath us. - // - - CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); - CurrentFcb = NextFcb; - - // - // Do a prefix search if there is more of the name to parse. - // - - if (RemainingName.FileName.Length != 0) { - - // - // Do the prefix search to find the longest matching name. - // - - CdFindPrefix( IrpContext, - &CurrentFcb, - &RemainingName.FileName, - IgnoreCase ); - } - - // - // If the remaining name length is zero then we have found our - // target. - // - - if (RemainingName.FileName.Length == 0) { - - // - // If this is a file so verify the user didn't want to open - // a directory. - // - - if (SafeNodeType( CurrentFcb ) == CDFS_NTC_FCB_DATA) { - - if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || - FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - - try_return( Status = STATUS_NOT_A_DIRECTORY ); - } - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - try_return( Status = CdOpenExistingFcb( IrpContext, - IrpSp, - &CurrentFcb, - UserFileOpen, - IgnoreCase, - RelatedCcb )); - - // - // This is a directory. Verify the user didn't want to open - // as a file. - // - - } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { - - try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); - - // - // Open the file as a directory. - // - - } else { - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - try_return( Status = CdOpenExistingFcb( IrpContext, - IrpSp, - &CurrentFcb, - UserDirectoryOpen, - IgnoreCase, - RelatedCcb )); - } - } - - // - // We have more work to do. We have a starting Fcb which we own shared. - // We also have the remaining name to parse. Walk through the name - // component by component looking for the full name. - // - - // - // Our starting Fcb better be a directory. - // - - if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { - - try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); - } - - // - // If we can't wait then post this request. - // - - if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { - - CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); - } - - // - // Make sure the final name has no version string. - // - - FinalName.VersionString.Length = 0; - - while (TRUE) { - - ShortNameMatch = FALSE; - - // - // Split off the next component from the name. - // - - CdDissectName( IrpContext, - &RemainingName.FileName, - &FinalName.FileName ); - - // - // Go ahead and look this entry up in the path table. - // - - CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); - CleanupCompoundPathEntry = TRUE; - - FoundEntry = CdFindPathEntry( IrpContext, - CurrentFcb, - &FinalName, - IgnoreCase, - &CompoundPathEntry ); - - // - // If we didn't find the entry then check if the current name - // is a possible short name. - // - - if (!FoundEntry) { - - ShortNameDirentOffset = CdShortNameDirentOffset( IrpContext, &FinalName.FileName ); - - // - // If there is an embedded short name offset then look for the - // matching long name in the directory. - // - - if (ShortNameDirentOffset != MAXULONG) { - - if (CleanupFileContext) { - - CdCleanupFileContext( IrpContext, &FileContext ); - } - - CdInitializeFileContext( IrpContext, &FileContext ); - CleanupFileContext = TRUE; - - FoundEntry = CdFindFileByShortName( IrpContext, - CurrentFcb, - &FinalName, - IgnoreCase, - ShortNameDirentOffset, - &FileContext ); - - // - // If we found an entry and it is a directory then look - // this up in the path table. - // - - if (FoundEntry) { - - ShortNameMatch = TRUE; - - if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags, - CD_ATTRIBUTE_DIRECTORY )) { - - CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); - CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); - - FoundEntry = CdFindPathEntry( IrpContext, - CurrentFcb, - &FileContext.InitialDirent->Dirent.CdCaseFileName, - IgnoreCase, - &CompoundPathEntry ); - - // - // We better find this entry. - // - - if (!FoundEntry) { - - CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); - } - - // - // Upcase the name with the short name if case - // insensitive. - // - - if (IgnoreCase) { - - CdUpcaseName( IrpContext, &FinalName, &FinalName ); - } - - // - // We found a matching file. If we are at the last - // entry then break out of the loop and open the - // file below. Otherwise we return an error. - // - - } else if (RemainingName.FileName.Length == 0) { - - // - // Break out of the loop. We will process the dirent - // below. - // - - MatchingName = &FileContext.ShortName; - break; - - } else { - - try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); - } - } - } - - // - // We didn't find the name in either the path table or as - // a short name in a directory. If the remaining name - // length is zero then break out of the loop to search - // the directory. - // - - if (!FoundEntry) { - - if (RemainingName.FileName.Length == 0) { - - break; - - // - // Otherwise this path could not be cracked. - // - - } else { - - try_return( Status = STATUS_OBJECT_PATH_NOT_FOUND ); - } - } - } - - // - // If this is an ignore case open then copy the exact case - // in the file object name. If it was a short name match then - // the name must be upcase already. - // - - if (IgnoreCase && !ShortNameMatch) { - - RtlCopyMemory( FinalName.FileName.Buffer, - CompoundPathEntry.PathEntry.CdDirName.FileName.Buffer, - CompoundPathEntry.PathEntry.CdDirName.FileName.Length ); - } - - // - // If we have found the last component then open this as a directory - // and return to our caller. - // - - if (RemainingName.FileName.Length == 0) { - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { - - try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); - } - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - try_return( Status = CdOpenDirectoryFromPathEntry( IrpContext, - IrpSp, - Vcb, - &CurrentFcb, - &FinalName, - IgnoreCase, - ShortNameMatch, - &CompoundPathEntry.PathEntry, - TRUE, - RelatedCcb )); - } - - // - // Otherwise open an Fcb for this intermediate index Fcb. - // - - CdOpenDirectoryFromPathEntry( IrpContext, - IrpSp, - Vcb, - &CurrentFcb, - &FinalName, - IgnoreCase, - ShortNameMatch, - &CompoundPathEntry.PathEntry, - FALSE, - NULL ); - - CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); - CleanupCompoundPathEntry = FALSE; - } - - // - // We need to scan the current directory for a matching file name - // if we don't already have one. - // - - if (!FoundEntry) { - - if (CleanupFileContext) { - - CdCleanupFileContext( IrpContext, &FileContext ); - } - - CdInitializeFileContext( IrpContext, &FileContext ); - CleanupFileContext = TRUE; - - // - // Split our search name into separate components. - // - - CdConvertNameToCdName( IrpContext, &FinalName ); - - FoundEntry = CdFindFile( IrpContext, - CurrentFcb, - &FinalName, - IgnoreCase, - &FileContext, - &MatchingName ); - } - - // - // If we didn't find a match then check if the name is invalid to - // determine which error code to return. - // - - if (!FoundEntry) { - - if ((CreateDisposition == FILE_OPEN) || - (CreateDisposition == FILE_OVERWRITE)) { - - try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND ); - } - - // - // Any other operation return STATUS_ACCESS_DENIED. - // - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - // - // If this is a directory then the disk is corrupt because it wasn't - // in the Path Table. - // - - if (FlagOn( FileContext.InitialDirent->Dirent.Flags, CD_ATTRIBUTE_DIRECTORY )) { - - CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR ); - } - - // - // Make sure our opener didn't want a directory. - // - - if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || - FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - - try_return( Status = STATUS_NOT_A_DIRECTORY ); - } - - // - // The only create disposition we allow is OPEN. - // - - if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { - - try_return( Status = STATUS_ACCESS_DENIED ); - } - - // - // If this is an ignore case open then copy the exact case - // in the file object name. Any version portion should - // already be upcased. - // - - if (IgnoreCase) { - - RtlCopyMemory( FinalName.FileName.Buffer, - MatchingName->FileName.Buffer, - MatchingName->FileName.Length ); - } - - // - // Open the file using the file context. We already have the - // first and last dirents. - // - - try_return( Status = CdOpenFileFromFileContext( IrpContext, - IrpSp, - Vcb, - &CurrentFcb, - &FinalName, - IgnoreCase, - (BOOLEAN) (MatchingName == &FileContext.ShortName), - &FileContext, - RelatedCcb )); - - try_exit: NOTHING; - } _SEH2_FINALLY { - - // - // Cleanup the PathEntry if initialized. - // - - if (CleanupCompoundPathEntry) { - - CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); - } - - // - // Cleanup the FileContext if initialized. - // - - if (CleanupFileContext) { - - CdCleanupFileContext( IrpContext, &FileContext ); - } - - // - // The result of this open could be success, pending or some error - // condition. - // - - if (_SEH2_AbnormalTermination()) { - - - // - // In the error path we start by calling our teardown routine if we - // have a CurrentFcb and its not the volume Dasd Fcb. - // - - if ((CurrentFcb != NULL) && - (CurrentFcb != Vcb->VolumeDasdFcb)) { - - BOOLEAN RemovedFcb; - - CdTeardownStructures( IrpContext, CurrentFcb, &RemovedFcb ); - - if (RemovedFcb) { - - CurrentFcb = NULL; - } - } - - // - // No need to complete the request. - // - - IrpContext = NULL; - Irp = NULL; - - // - // If we posted this request through the oplock package we need - // to show that there is no reason to complete the request. - // - - } else if (Status == STATUS_PENDING) { - - IrpContext = NULL; - Irp = NULL; - } - - // - // Release the Current Fcb if still acquired. - // - - if (CurrentFcb != NULL) { - _Analysis_assume_lock_held_(CurrentFcb->FcbNonpaged->FcbResource); - CdReleaseFcb( IrpContext, CurrentFcb ); - } - - // - // Release the Vcb. - // - - CdReleaseVcb( IrpContext, Vcb ); - - // - // Call our completion routine. It will handle the case where either - // the Irp and/or IrpContext are gone. - // - - CdCompleteRequest( IrpContext, Irp, Status ); - } _SEH2_END; - - return Status; -} - - -// -// Local support routine -// -_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_)) -_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_)) -_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_)) -_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_)) -NTSTATUS -CdNormalizeFileNames ( - _Inout_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _In_ BOOLEAN OpenByFileId, - _In_ BOOLEAN IgnoreCase, - _In_ TYPE_OF_OPEN RelatedTypeOfOpen, - PCCB RelatedCcb, - PUNICODE_STRING RelatedFileName, - _Inout_ PUNICODE_STRING FileName, - _Inout_ PCD_NAME RemainingName - ) - -/*++ - -Routine Description: - - This routine is called to store the full name and upcased name into the - filename buffer. We only upcase the portion yet to parse. We also - check for a trailing backslash and lead-in double backslashes. This - routine also verifies the mode of the related open against the name - currently in the filename. - -Arguments: - - Vcb - Vcb for this volume. - - OpenByFileId - Indicates if the filename should be a 64 bit FileId. - - IgnoreCase - Indicates if this open is a case-insensitive operation. - - RelatedTypeOfOpen - Indicates the type of the related file object. - - RelatedCcb - Ccb for the related open. Ignored if no relative open. - - RelatedFileName - FileName buffer for related open. Ignored if no - relative open. - - FileName - FileName to update in this routine. The name should - either be a 64-bit FileId or a Unicode string. - - RemainingName - Name with the remaining portion of the name. This - will begin after the related name and any separator. For a - non-relative open we also step over the initial separator. - -Return Value: - - NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code - otherwise. - ---*/ - -{ - ULONG RemainingNameLength = 0; - ULONG RelatedNameLength = 0; - ULONG SeparatorLength = 0; - - ULONG BufferLength; - - UNICODE_STRING NewFileName; - - PAGED_CODE(); - - // - // If this is the first pass then we need to build the full name and - // check for name compatibility. - // - - if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) { - - // - // Deal with the regular file name case first. - // - - if (!OpenByFileId) { - - // - // This is here because the Win32 layer can't avoid sending me double - // beginning backslashes. - // - - if ((FileName->Length > sizeof( WCHAR )) && - (FileName->Buffer[1] == L'\\') && - (FileName->Buffer[0] == L'\\')) { - - // - // If there are still two beginning backslashes, the name is bogus. - // - - if ((FileName->Length > 2 * sizeof( WCHAR )) && - (FileName->Buffer[2] == L'\\')) { - - return STATUS_OBJECT_NAME_INVALID; - } - - // - // Slide the name down in the buffer. - // - - FileName->Length -= sizeof( WCHAR ); - - RtlMoveMemory( FileName->Buffer, - FileName->Buffer + 1, - FileName->Length ); - } - - // - // Check for a trailing backslash. Don't strip off if only character - // in the full name or for relative opens where this is illegal. - // - - if (((FileName->Length > sizeof( WCHAR)) || - ((FileName->Length == sizeof( WCHAR )) && (RelatedTypeOfOpen == UserDirectoryOpen))) && - (FileName->Buffer[ (FileName->Length/2) - 1 ] == L'\\')) { - - SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ); - FileName->Length -= sizeof( WCHAR ); - } - - // - // Remember the length we need for this portion of the name. - // - - RemainingNameLength = FileName->Length; - - // - // If this is a related file object then we verify the compatibility - // of the name in the file object with the relative file object. - // - - if (RelatedTypeOfOpen != UnopenedFileObject) { - - // - // If the filename length was zero then it must be legal. - // If there are characters then check with the related - // type of open. - // - - if (FileName->Length != 0) { - - // - // The name length must always be zero for a volume open. - // - - if (RelatedTypeOfOpen <= UserVolumeOpen) { - - return STATUS_INVALID_PARAMETER; - - // - // The remaining name cannot begin with a backslash. - // - - } else if (FileName->Buffer[0] == L'\\' ) { - - return STATUS_INVALID_PARAMETER; - - // - // If the related file is a user file then there - // is no file with this path. - // - - } else if (RelatedTypeOfOpen == UserFileOpen) { - - return STATUS_OBJECT_PATH_NOT_FOUND; - } - } - - // - // Remember the length of the related name when building - // the full name. We leave the RelatedNameLength and - // SeparatorLength at zero if the relative file is opened - // by Id. - // - - if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { - - // - // Add a separator if the name length is non-zero - // unless the relative Fcb is at the root. - // - - if ((FileName->Length != 0) && - (RelatedCcb->Fcb != Vcb->RootIndexFcb)) { - - SeparatorLength = sizeof( WCHAR ); - } - - RelatedNameLength = RelatedFileName->Length; - } - - // - // The full name is already in the filename. It must either - // be length 0 or begin with a backslash. - // - - } else if (FileName->Length != 0) { - - if (FileName->Buffer[0] != L'\\') { - - return STATUS_INVALID_PARAMETER; - } - - // - // We will want to trim the leading backslash from the - // remaining name we return. - // - - RemainingNameLength -= sizeof( WCHAR ); - SeparatorLength = sizeof( WCHAR ); - } - - // - // Now see if the buffer is large enough to hold the full name. - // - - BufferLength = RelatedNameLength + SeparatorLength + RemainingNameLength; - - // - // Check for an overflow of the maximum filename size. - // - - if (BufferLength > MAXUSHORT) { - - return STATUS_INVALID_PARAMETER; - } - - // - // Now see if we need to allocate a new buffer. - // - - if (FileName->MaximumLength < BufferLength) { - - NewFileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool, - BufferLength, - TAG_FILE_NAME ); - - NewFileName.MaximumLength = (USHORT) BufferLength; - - } else { - - NewFileName.Buffer = FileName->Buffer; - NewFileName.MaximumLength = FileName->MaximumLength; - } - - // - // If there is a related name then we need to slide the remaining bytes up and - // insert the related name. Otherwise the name is in the correct position - // already. - // - - if (RelatedNameLength != 0) { - - // - // Store the remaining name in its correct position. - // - - if (RemainingNameLength != 0) { - - RtlMoveMemory( Add2Ptr( NewFileName.Buffer, RelatedNameLength + SeparatorLength, PVOID ), - FileName->Buffer, - RemainingNameLength ); - } - - RtlCopyMemory( NewFileName.Buffer, - RelatedFileName->Buffer, - RelatedNameLength ); - - // - // Add the separator if needed. - // - - if (SeparatorLength != 0) { - - *(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\'; - } - - // - // Update the filename value we got from the user. - // - - if (NewFileName.Buffer != FileName->Buffer) { - - if (FileName->Buffer != NULL) { - - CdFreePool( &FileName->Buffer ); - } - - FileName->Buffer = NewFileName.Buffer; - FileName->MaximumLength = NewFileName.MaximumLength; - } - - // - // Copy the name length to the user's filename. - // - - FileName->Length = (USHORT) (RelatedNameLength + SeparatorLength + RemainingNameLength); - } - - // - // Now update the remaining name to parse. - // - - RemainingName->FileName.MaximumLength = - RemainingName->FileName.Length = (USHORT) RemainingNameLength; - RemainingName->VersionString.Length = 0; - - RemainingName->FileName.Buffer = Add2Ptr( FileName->Buffer, - RelatedNameLength + SeparatorLength, - PWCHAR ); - - // - // Upcase the name if necessary. - // - - if (IgnoreCase && (RemainingNameLength != 0)) { - - CdUpcaseName( IrpContext, - RemainingName, - RemainingName ); - } - - // - // Do a quick check to make sure there are no wildcards. - // -#ifdef _MSC_VER -#pragma prefast(push) -#pragma prefast(suppress:26000, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).") -#endif - if (FsRtlDoesNameContainWildCards( &RemainingName->FileName )) { -#ifdef _MSC_VER -#pragma prefast(pop) -#endif - - return STATUS_OBJECT_NAME_INVALID; - } - - // - // For the open by file Id case we verify the name really contains - // a 64 bit value. - // - - } else { - - // - // Check for validity of the buffer. - // - - if (FileName->Length != sizeof( FILE_ID )) { - - return STATUS_INVALID_PARAMETER; - } - } - - SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME ); - - // - // If we are in the retry path then the full name is already in the - // file object name. If this is a case-sensitive operation then - // we need to upcase the name from the end of any related file name already stored - // there. - // - - } else { - - // - // Assume there is no relative name. - // - - RemainingName->FileName = *FileName; - RemainingName->VersionString.Length = 0; - - // - // Nothing to do if the name length is zero. - // - - if (RemainingName->FileName.Length != 0) { - - // - // If there is a relative name then we need to walk past it. - // - - if (RelatedTypeOfOpen != UnopenedFileObject) { - - // - // Nothing to walk past if the RelatedCcb is opened by FileId. - // - - - if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { - - // - // Related file name is a proper prefix of the full name. - // We step over the related name and if we are then - // pointing at a separator character we step over that. - // - - RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer, - RelatedFileName->Length, - PWCHAR ); - - RemainingName->FileName.Length -= RelatedFileName->Length; - } - } - - // - // If we are pointing at a separator character then step past that. - // - - if (RemainingName->FileName.Length != 0) { - - if (*(RemainingName->FileName.Buffer) == L'\\') { - - RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer, - sizeof( WCHAR ), - PWCHAR ); - - RemainingName->FileName.Length -= sizeof( WCHAR ); - } - } - } - - // - // Upcase the name if necessary. - // - - if (IgnoreCase && (RemainingName->FileName.Length != 0)) { - - CdUpcaseName( IrpContext, - RemainingName, - RemainingName ); - } - } - -#ifdef _MSC_VER -#pragma prefast(push) -#pragma prefast(suppress:26030, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).") -#endif - return STATUS_SUCCESS; -#ifdef _MSC_VER -#pragma prefast(pop) -#endif -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) -NTSTATUS -CdOpenByFileId ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb - ) - -/*++ - -Routine Description: - - This routine is called to open a file by the FileId. The file Id is in - the FileObject name buffer and has been verified to be 64 bits. - - We extract the Id number and then check to see whether we are opening a - file or directory and compare that with the create options. If this - generates no error then optimistically look up the Fcb in the Fcb Table. - - If we don't find the Fcb then we need to carefully verify there is a file - at this offset. First check whether the Parent Fcb is in the table. If - not then lookup the parent at the path table offset given by file ID. - - If found then build the Fcb from this entry and store the new Fcb in the - tree. - - We know have the parent Fcb. Do a directory scan to find the dirent at - the given offset in this stream. This must point to the first entry - of a valid file. - - Finally we call our worker routine to complete the open on this Fcb. - -Arguments: - - IrpSp - Stack location within the create Irp. - - Vcb - Vcb for this volume. - - CurrentFcb - Address to store the Fcb for this open. We only store the - CurrentFcb here when we have acquired it so our caller knows to - free or deallocate it. - -Return Value: - - NTSTATUS - Status indicating the result of the operation. - ---*/ - -{ - NTSTATUS Status = STATUS_ACCESS_DENIED; - - BOOLEAN UnlockVcb = FALSE; - BOOLEAN Found; - - ULONG StreamOffset; - - NODE_TYPE_CODE NodeTypeCode; - TYPE_OF_OPEN TypeOfOpen; - - FILE_ENUM_CONTEXT FileContext; - BOOLEAN CleanupFileContext = FALSE; - - COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ - BOOLEAN CleanupCompoundPathEntry = FALSE; - - FILE_ID FileId; - FILE_ID ParentFileId; - - PFCB NextFcb; - - PAGED_CODE(); - - // - // Extract the FileId from the FileObject. - // - - RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID )); - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Go ahead and figure out the TypeOfOpen and NodeType. We can - // get these from the input FileId. - // - - if (CdFidIsDirectory( FileId )) { - - TypeOfOpen = UserDirectoryOpen; - NodeTypeCode = CDFS_NTC_FCB_INDEX; - - // - // If the offset isn't zero then the file Id is bad. - // - - if (CdQueryFidDirentOffset( FileId ) != 0) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - - } else { - - TypeOfOpen = UserFileOpen; - NodeTypeCode = CDFS_NTC_FCB_DATA; - } - - // - // Acquire the Vcb and check if there is already an Fcb. - // If not we will need to carefully verify the Fcb. - // We will post the request if we don't find the Fcb and this - // request can't wait. - // - - CdLockVcb( IrpContext, Vcb ); - UnlockVcb = TRUE; - - NextFcb = CdLookupFcbTable( IrpContext, Vcb, FileId ); - - if (NextFcb == NULL) { - - // - // Get the path table offset from the file id. - // - - StreamOffset = CdQueryFidPathTableOffset( FileId ); - - // - // Build the parent FileId for this and try looking it - // up in the PathTable. - // - - CdSetFidDirentOffset( ParentFileId, 0 ); - CdSetFidPathTableOffset( ParentFileId, StreamOffset ); - CdFidSetDirectory( ParentFileId ); - - NextFcb = CdLookupFcbTable( IrpContext, Vcb, ParentFileId ); - - // - // If not present then walk through the PathTable to this point. - // - - if (NextFcb == NULL) { - - CdUnlockVcb( IrpContext, Vcb ); - UnlockVcb = FALSE; - - // - // Check that the path table offset lies within the path - // table. - // - - if (StreamOffset > Vcb->PathTableFcb->FileSize.LowPart) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - - CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); - CleanupCompoundPathEntry = TRUE; - - // - // Start at the first entry in the PathTable. - // - - CdLookupPathEntry( IrpContext, - Vcb->PathTableFcb->StreamOffset, - 1, - TRUE, - &CompoundPathEntry ); - - // - // Continue looking until we have passed our target offset. - // - - while (TRUE) { - - // - // Move to the next entry. - // - - Found = CdLookupNextPathEntry( IrpContext, - &CompoundPathEntry.PathContext, - &CompoundPathEntry.PathEntry ); - - // - // If we didn't find the entry or are beyond it then the - // input Id is invalid. - // - - if (!Found || - (CompoundPathEntry.PathEntry.PathTableOffset > StreamOffset)) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - } - - // - // If the FileId specified a directory then we have found - // the entry. Make sure our caller wanted to open a directory. - // - - if ((TypeOfOpen == UserDirectoryOpen) && - FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { - - try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); - } - - // - // Lock the Vcb and create the Fcb if necessary. - // - - CdLockVcb( IrpContext, Vcb ); - UnlockVcb = TRUE; - - NextFcb = CdCreateFcb( IrpContext, ParentFileId, NodeTypeCode, &Found ); - - // - // It's possible that someone got in here ahead of us. - // - - if (!Found) { - - CdInitializeFcbFromPathEntry( IrpContext, - NextFcb, - NULL, - &CompoundPathEntry.PathEntry ); - } - - // - // If the user wanted to open a directory then we have found - // it. Store this Fcb into the CurrentFcb and skip the - // directory scan. - // - - if (TypeOfOpen == UserDirectoryOpen) { - - *CurrentFcb = NextFcb; - NextFcb = NULL; - } - } - - // - // Perform the directory scan if we don't already have our target. - // - - if (NextFcb != NULL) { - - // - // Acquire the parent. We currently own the Vcb lock so - // do this without waiting first. - // - - if (!CdAcquireFcbExclusive( IrpContext, - NextFcb, - TRUE )) { - - NextFcb->FcbReference += 1; - CdUnlockVcb( IrpContext, Vcb ); - - CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); - - CdLockVcb( IrpContext, Vcb ); - NextFcb->FcbReference -= 1; - CdUnlockVcb( IrpContext, Vcb ); - - } else { - - CdUnlockVcb( IrpContext, Vcb ); - } - - UnlockVcb = FALSE; - - // - // Set up the CurrentFcb pointers. We know there was - // no previous parent in this case. - // - - *CurrentFcb = NextFcb; - - // - // Calculate the offset in the stream. - // - - StreamOffset = CdQueryFidDirentOffset( FileId ); - - // - // Create the stream file if it doesn't exist. This will update - // the Fcb with the size from the self entry. - // - - CdVerifyOrCreateDirStreamFile( IrpContext, NextFcb); - - // - // If our offset is beyond the end of the directory then the - // FileId is invalid. - // - - if (StreamOffset > NextFcb->FileSize.LowPart) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - - // - // Otherwise position ourselves at the self entry and walk - // through dirent by dirent until this location is found. - // - - CdInitializeFileContext( IrpContext, &FileContext ); - CdLookupInitialFileDirent( IrpContext, - NextFcb, - &FileContext, - NextFcb->StreamOffset ); - - CleanupFileContext = TRUE; - - while (TRUE) { - - // - // Move to the first entry of the next file. - // - - Found = CdLookupNextInitialFileDirent( IrpContext, - NextFcb, - &FileContext ); - - // - // If we didn't find the entry or are beyond it then the - // input Id is invalid. - // - - if (!Found || - (FileContext.InitialDirent->Dirent.DirentOffset > StreamOffset)) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - } - - // - // This better not be a directory. Directory FileIds must - // refer to the self entry for directories. - // - - if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags, - CD_ATTRIBUTE_DIRECTORY )) { - - try_return( Status = STATUS_INVALID_PARAMETER ); - } - - // - // Check that our caller wanted to open a file. - // - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - - try_return( Status = STATUS_NOT_A_DIRECTORY ); - } - - // - // Otherwise we want to collect all of the dirents for this file - // and create an Fcb with this. - // - - CdLookupLastFileDirent( IrpContext, NextFcb, &FileContext ); - - CdLockVcb( IrpContext, Vcb ); - UnlockVcb = TRUE; - - NextFcb = CdCreateFcb( IrpContext, FileId, NodeTypeCode, &Found ); - - // - // It's possible that someone has since created this Fcb since we - // first checked. If so then can simply use this. Otherwise - // we need to initialize a new Fcb and attach it to our parent - // and insert it into the Fcb Table. - // - - if (!Found) { - - CdInitializeFcbFromFileContext( IrpContext, - NextFcb, - *CurrentFcb, - &FileContext ); - } - } - - // - // We have the Fcb. Check that the type of the file is compatible with - // the desired type of file to open. - // - - } else { - - if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { - - try_return( Status = STATUS_FILE_IS_A_DIRECTORY ); - } - - } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { - - try_return( Status = STATUS_NOT_A_DIRECTORY ); - } - } - - // - // If we have a the previous Fcb and have inserted the next Fcb into - // the Fcb Table. It is safe to release the current Fcb if present - // since it is referenced through the child Fcb. - // - - if (*CurrentFcb != NULL) { - - CdReleaseFcb( IrpContext, *CurrentFcb ); - } - - // - // We now know the Fcb and currently hold the Vcb lock. - // Try to acquire this Fcb without waiting. Otherwise we - // need to reference it, drop the Vcb, acquire the Fcb and - // then dereference the Fcb. - // - - if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { - - NextFcb->FcbReference += 1; - - CdUnlockVcb( IrpContext, Vcb ); - - CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); - - CdLockVcb( IrpContext, Vcb ); - NextFcb->FcbReference -= 1; - CdUnlockVcb( IrpContext, Vcb ); - - } else { - - CdUnlockVcb( IrpContext, Vcb ); - } - - UnlockVcb = FALSE; - - // - // Move to this Fcb. - // - - *CurrentFcb = NextFcb; - - // Lock object is acquired using internal state - _Analysis_suppress_lock_checking_(NextFcb->FcbNonpaged->FcbResource); - - // - // Check the requested access on this Fcb. - // - - if (!CdIllegalFcbAccess( IrpContext, - TypeOfOpen, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { - - // - // Call our worker routine to complete the open. - // - - Status = CdCompleteFcbOpen( IrpContext, - IrpSp, - Vcb, - CurrentFcb, - TypeOfOpen, - CCB_FLAG_OPEN_BY_ID, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); - - } - - try_exit: NOTHING; - } _SEH2_FINALLY { - - if (UnlockVcb) { - - CdUnlockVcb( IrpContext, Vcb ); - } - - if (CleanupFileContext) { - - CdCleanupFileContext( IrpContext, &FileContext ); - } - - if (CleanupCompoundPathEntry) { - - CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); - } - } _SEH2_END; - - return Status; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdOpenExistingFcb ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _Inout_ PFCB *CurrentFcb, - _In_ TYPE_OF_OPEN TypeOfOpen, - _In_ BOOLEAN IgnoreCase, - _In_opt_ PCCB RelatedCcb - ) - -/*++ - -Routine Description: - - This routine is called to open an Fcb which is already in the Fcb table. - We will verify the access to the file and then call our worker routine - to perform the final operations. - -Arguments: - - IrpSp - Pointer to the stack location for this open. - - CurrentFcb - Address of Fcb to open. We will clear this if the Fcb - is released here. - - TypeOfOpen - Indicates whether we are opening a file, directory or volume. - - IgnoreCase - Indicates if this open is case-insensitive. - - RelatedCcb - Ccb for related file object if relative open. We use - this when setting the Ccb flags for this open. It will tell - us whether the name currently in the file object is relative or - absolute. - -Return Value: - - NTSTATUS - Status indicating the result of the operation. - ---*/ - -{ - ULONG CcbFlags = 0; - - NTSTATUS Status = STATUS_ACCESS_DENIED; - - PAGED_CODE(); - - // - // Check that the desired access is legal. - // - - if (!CdIllegalFcbAccess( IrpContext, - TypeOfOpen, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { - - // - // Set the Ignore case. - // - - if (IgnoreCase) { - - SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); - } - - // - // Check the related Ccb to see if this was an OpenByFileId and - // whether there was a version. - // - - if (ARGUMENT_PRESENT( RelatedCcb )) { - - SetFlag( CcbFlags, FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_WITH_VERSION )); - - - if (FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { - - SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); - } - } - - // - // Call our worker routine to complete the open. - // - - Status = CdCompleteFcbOpen( IrpContext, - IrpSp, - (*CurrentFcb)->Vcb, - CurrentFcb, - TypeOfOpen, - CcbFlags, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); - } - - return Status; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource) -NTSTATUS -CdOpenDirectoryFromPathEntry ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ PCD_NAME DirName, - _In_ BOOLEAN IgnoreCase, - _In_ BOOLEAN ShortNameMatch, - _In_ PPATH_ENTRY PathEntry, - _In_ BOOLEAN PerformUserOpen, - _In_opt_ PCCB RelatedCcb - ) - -/*++ - -Routine Description: - - This routine is called to open a directory where the directory was found - in the path table. This routine is called in the case where this is the - file to open for the user and where this is an intermediate node in the - full path to open. - - We first check that the desired access is legal for a directory. Then we - construct the FileId for this and do a check to see if it is the Fcb - Table. It is always possible that either it was created since or simply - wasn't in the prefix table at the time of the prefix table search. - Initialize the Fcb and store into the FcbTable if not present. - - Next we will add this to the prefix table of our parent if needed. - - Once we know that the new Fcb has been initialized then we move our pointer - in the tree down to this position. - - This routine does not own the Vcb lock on entry. We must be sure to release - it on exit. - -Arguments: - - IrpSp - Stack location for this request. - - Vcb - Vcb for this volume. - - CurrentFcb - On input this is the parent of the Fcb to open. On output we - store the Fcb for the file being opened. - - DirName - This is always the exact name used to reach this file. - - IgnoreCase - Indicates the type of case match for the open. - - ShortNameMatch - Indicates if we are opening via the short name. - - PathEntry - Path entry for the entry found. - - PerformUserOpen - TRUE if we are to open this for a user, FALSE otherwise. - - RelatedCcb - RelatedCcb for relative file object used to make this open. - -Return Value: - - NTSTATUS - Status indicating the result of the operation. - ---*/ - -{ - ULONG CcbFlags = 0; - FILE_ID FileId; - - BOOLEAN UnlockVcb = FALSE; - BOOLEAN FcbExisted; - - PFCB NextFcb; - PFCB ParentFcb = NULL; - - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - // - // Check for illegal access to this file. - // - - if (PerformUserOpen && - CdIllegalFcbAccess( IrpContext, - UserDirectoryOpen, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { - - return STATUS_ACCESS_DENIED; - } - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Check the related Ccb to see if this was an OpenByFileId. - // - - if (ARGUMENT_PRESENT( RelatedCcb ) && - FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { - - CcbFlags = CCB_FLAG_OPEN_RELATIVE_BY_ID; - } - - if (IgnoreCase) { - - SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); - } - - // - // Build the file Id for this file. - // - - FileId.QuadPart = 0; - CdSetFidPathTableOffset( FileId, PathEntry->PathTableOffset ); - CdFidSetDirectory( FileId ); - - // - // Lock the Vcb so we can examine the Fcb Table. - // - - CdLockVcb( IrpContext, Vcb ); - UnlockVcb = TRUE; - - // - // Get the Fcb for this directory. - // - - NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_INDEX, &FcbExisted ); - - // - // If the Fcb was created here then initialize from the values in the - // path table entry. - // - - if (!FcbExisted) { - - CdInitializeFcbFromPathEntry( IrpContext, NextFcb, *CurrentFcb, PathEntry ); - } - - // - // Now try to acquire the new Fcb without waiting. We will reference - // the Fcb and retry with wait if unsuccessful. - // - - if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { - - NextFcb->FcbReference += 1; - - CdUnlockVcb( IrpContext, Vcb ); - - CdReleaseFcb( IrpContext, *CurrentFcb ); - CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); - CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE ); - - CdLockVcb( IrpContext, Vcb ); - NextFcb->FcbReference -= 1; - CdUnlockVcb( IrpContext, Vcb ); - - } else { - - // - // Unlock the Vcb and move down to this new Fcb. Remember that we still - // own the parent however. - // - - CdUnlockVcb( IrpContext, Vcb ); - } - - UnlockVcb = FALSE; - - ParentFcb = *CurrentFcb; - *CurrentFcb = NextFcb; - - // Lock object is acquired using internal state - _Analysis_suppress_lock_checking_(NextFcb->FcbNonpaged->FcbResource); - - // - // Store this name into the prefix table for the parent. - // - - if (ShortNameMatch) { - - // - // Make sure the exact case is always in the tree. - // - - CdInsertPrefix( IrpContext, - NextFcb, - DirName, - FALSE, - TRUE, - ParentFcb ); - - if (IgnoreCase) { - - CdInsertPrefix( IrpContext, - NextFcb, - DirName, - TRUE, - TRUE, - ParentFcb ); - } - - } else { - - // - // Make sure the exact case is always in the tree. - // - - CdInsertPrefix( IrpContext, - NextFcb, - &PathEntry->CdDirName, - FALSE, - FALSE, - ParentFcb ); - - if (IgnoreCase) { - - CdInsertPrefix( IrpContext, - NextFcb, - &PathEntry->CdCaseDirName, - TRUE, - FALSE, - ParentFcb ); - } - } - - // - // Release the parent Fcb at this point. - // - - CdReleaseFcb( IrpContext, ParentFcb ); - ParentFcb = NULL; - - // - // Call our worker routine to complete the open. - // - - if (PerformUserOpen) { - - Status = CdCompleteFcbOpen( IrpContext, - IrpSp, - Vcb, - CurrentFcb, - UserDirectoryOpen, - CcbFlags, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); - } - - } _SEH2_FINALLY { - - // - // Unlock the Vcb if held. - // - - if (UnlockVcb) { - - CdUnlockVcb( IrpContext, Vcb ); - } - - // - // Release the parent if held. - // - - if (ParentFcb != NULL) { - - CdReleaseFcb( IrpContext, ParentFcb ); - } - } _SEH2_END; - - return Status; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdOpenFileFromFileContext ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ PCD_NAME FileName, - _In_ BOOLEAN IgnoreCase, - _In_ BOOLEAN ShortNameMatch, - _In_ PFILE_ENUM_CONTEXT FileContext, - _In_opt_ PCCB RelatedCcb - ) - -/*++ - -Routine Description: - - This routine is called to open a file where the file was found in a directory scan. - This should only be for a file in the case since we will find the directories in the - path table. - - We first check that the desired access is legal for this file. Then we - construct the FileId for this and do a check to see if it is the Fcb - Table. It is always possible that either it was created since or simply - wasn't in the prefix table at the time of the prefix table search. - Initialize the Fcb and store into the FcbTable if not present. - - Next we will add this to the prefix table of our parent if needed. - - Once we know that the new Fcb has been initialized then we move our pointer - in the tree down to this position. - - This routine does not own the Vcb lock on entry. We must be sure to release - it on exit. - -Arguments: - - IrpSp - Stack location for this request. - - Vcb - Vcb for the current volume. - - CurrentFcb - On input this is the parent of the Fcb to open. On output we - store the Fcb for the file being opened. - - FileName - This is always the exact name used to reach this file. - - IgnoreCase - Indicates the type of case of CaseName above. - - ShortNameMatch - Indicates if we are opening via the short name. - - FileContext - This is the context used to find the file. - - RelatedCcb - RelatedCcb for relative file object used to make this open. - -Return Value: - - NTSTATUS - Status indicating the result of the operation. - ---*/ - -{ - ULONG CcbFlags = 0; - FILE_ID FileId; - - BOOLEAN UnlockVcb = FALSE; - BOOLEAN FcbExisted; - - PFCB NextFcb; - PFCB ParentFcb = NULL; - - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - // - // Check for illegal access to this file. - // - - if (CdIllegalFcbAccess( IrpContext, - UserFileOpen, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { - - return STATUS_ACCESS_DENIED; - } - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Check if a version number was used to open this file. - // - - if (FileName->VersionString.Length != 0) { - - SetFlag( CcbFlags, CCB_FLAG_OPEN_WITH_VERSION ); - } - - // - // Check the related Ccb to see if this was an OpenByFileId. - // - - if (ARGUMENT_PRESENT( RelatedCcb ) && - FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { - - SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); - } - - if (IgnoreCase) { - - SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); - } - - // - // Build the file Id for this file. We can use the path table offset from the - // parent and the directory offset from the dirent. - // - - CdSetFidPathTableOffset( FileId, CdQueryFidPathTableOffset( (*CurrentFcb)->FileId )); - CdSetFidDirentOffset( FileId, FileContext->InitialDirent->Dirent.DirentOffset ); - - // - // Lock the Vcb so we can examine the Fcb Table. - // - - CdLockVcb( IrpContext, Vcb ); - UnlockVcb = TRUE; - - // - // Get the Fcb for this file. - // - - NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_DATA, &FcbExisted ); - - // - // If the Fcb was created here then initialize from the values in the - // dirent. - // - - if (!FcbExisted) { - - CdInitializeFcbFromFileContext( IrpContext, - NextFcb, - *CurrentFcb, - FileContext ); - } - - // - // Now try to acquire the new Fcb without waiting. We will reference - // the Fcb and retry with wait if unsuccessful. - // - - if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { - - NextFcb->FcbReference += 1; - - CdUnlockVcb( IrpContext, Vcb ); - - CdReleaseFcb( IrpContext, *CurrentFcb ); - CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); - CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE ); - - CdLockVcb( IrpContext, Vcb ); - NextFcb->FcbReference -= 1; - CdUnlockVcb( IrpContext, Vcb ); - - } else { - - // - // Unlock the Vcb and move down to this new Fcb. Remember that we still - // own the parent however. - // - - CdUnlockVcb( IrpContext, Vcb ); - } - - UnlockVcb = FALSE; - - ParentFcb = *CurrentFcb; - *CurrentFcb = NextFcb; - - // - // Store this name into the prefix table for the parent. - // - - - if (ShortNameMatch) { - - // - // Make sure the exact case is always in the tree. - // - - CdInsertPrefix( IrpContext, - NextFcb, - FileName, - FALSE, - TRUE, - ParentFcb ); - - if (IgnoreCase) { - - CdInsertPrefix( IrpContext, - NextFcb, - FileName, - TRUE, - TRUE, - ParentFcb ); - } - - // - // Insert this into the prefix table if we found this without - // using a version string. - // - - } else if (FileName->VersionString.Length == 0) { - - // - // Make sure the exact case is always in the tree. - // - - CdInsertPrefix( IrpContext, - NextFcb, - &FileContext->InitialDirent->Dirent.CdFileName, - FALSE, - FALSE, - ParentFcb ); - - if (IgnoreCase) { - - CdInsertPrefix( IrpContext, - NextFcb, - &FileContext->InitialDirent->Dirent.CdCaseFileName, - TRUE, - FALSE, - ParentFcb ); - } - } - - // - // Release the parent Fcb at this point. - // - - _Analysis_assume_same_lock_(ParentFcb->FcbNonpaged->FcbResource, NextFcb->FcbNonpaged->FcbResource); - CdReleaseFcb( IrpContext, ParentFcb ); - ParentFcb = NULL; - - // - // Call our worker routine to complete the open. - // - - Status = CdCompleteFcbOpen( IrpContext, - IrpSp, - Vcb, - CurrentFcb, - UserFileOpen, - CcbFlags, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); - - } _SEH2_FINALLY { - - // - // Unlock the Vcb if held. - // - - if (UnlockVcb) { - - CdUnlockVcb( IrpContext, Vcb ); - } - - // - // Release the parent if held. - // - - if (ParentFcb != NULL) { - - CdReleaseFcb( IrpContext, ParentFcb ); - } - } _SEH2_END; - - return Status; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdCompleteFcbOpen ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PIO_STACK_LOCATION IrpSp, - _In_ PVCB Vcb, - _Inout_ PFCB *CurrentFcb, - _In_ TYPE_OF_OPEN TypeOfOpen, - _In_ ULONG UserCcbFlags, - _In_ ACCESS_MASK DesiredAccess - ) - -/*++ - -Routine Description: - - This is the worker routine which takes an existing Fcb and completes - the open. We will do any necessary oplock checks and sharing checks. - Finally we will create the Ccb and update the file object and any - file object flags. - -Arguments: - - IrpSp - Stack location for the current request. - - Vcb - Vcb for the current volume. - - CurrentFcb - Address of pointer to Fcb to open. We clear this field if - we release the resource for this file. - - TypeOfOpen - Type of open for this request. - - UserCcbFlags - Flags to OR into the Ccb flags. - - DesiredAccess - Desired access for this open. - -Return Value: - - NTSTATUS - STATUS_SUCCESS if we complete this request, STATUS_PENDING if - the oplock package takes the Irp or SHARING_VIOLATION if there is a - sharing check conflict. - ---*/ - -{ - NTSTATUS Status; - NTSTATUS OplockStatus = STATUS_SUCCESS; - ULONG Information = FILE_OPENED; - - BOOLEAN LockVolume = FALSE; - - PFCB Fcb = *CurrentFcb; - PCCB Ccb; - - PAGED_CODE(); - - // - // Expand maximum allowed to something sensible for share access checking - // - - if (MAXIMUM_ALLOWED == DesiredAccess) { - - DesiredAccess = FILE_ALL_ACCESS & ~((TypeOfOpen != UserVolumeOpen ? - (FILE_WRITE_ATTRIBUTES | - FILE_WRITE_DATA | - FILE_WRITE_EA | - FILE_ADD_FILE | - FILE_ADD_SUBDIRECTORY | - FILE_APPEND_DATA) : 0) | - FILE_DELETE_CHILD | - DELETE | - WRITE_DAC ); - } - - // - // If this a volume open and the user wants to lock the volume then - // purge and lock the volume. - // - - if ((TypeOfOpen <= UserVolumeOpen) && - !FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ )) { - - // - // If there are open handles then fail this immediately. - // - - if (Vcb->VcbCleanup != 0) { - - return STATUS_SHARING_VIOLATION; - } - - // - // If we can't wait then force this to be posted. - // - - if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { - - CdRaiseStatus( IrpContext, STATUS_CANT_WAIT ); - } - - LockVolume = TRUE; - - // - // Purge the volume and make sure all of the user references - // are gone. - // - - Status = CdPurgeVolume( IrpContext, Vcb, FALSE ); - - if (Status != STATUS_SUCCESS) { - - return Status; - } - - // - // Now force all of the delayed close operations to go away. - // - - CdFspClose( Vcb ); - - if (Vcb->VcbUserReference > CDFS_RESIDUAL_USER_REFERENCE) { - - return STATUS_SHARING_VIOLATION; - } - } - - // - // If the Fcb already existed then we need to check the oplocks and - // the share access. - // - - if (Fcb->FcbCleanup != 0) { - - // - // If this is a user file open then check whether there are any - // batch oplock. - // - - if (TypeOfOpen == UserFileOpen) { - - // - // Store the address of the Fcb for a possible teardown into - // the IrpContext. We will release this in the call to - // prepost the Irp. - // - - IrpContext->TeardownFcb = CurrentFcb; - - if (FsRtlCurrentBatchOplock( CdGetFcbOplock(Fcb) )) { - - // - // We remember if a batch oplock break is underway for the - // case where the sharing check fails. - // - - Information = FILE_OPBATCH_BREAK_UNDERWAY; - - OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb), - IrpContext->Irp, - IrpContext, - (PVOID)CdOplockComplete, /* ReactOS Change: GCC "assignment from incompatible pointer type" */ - (PVOID)CdPrePostIrp ); /* ReactOS Change: GCC "assignment from incompatible pointer type" */ - - if (OplockStatus == STATUS_PENDING) { - - return STATUS_PENDING; - } - } - - // - // Check the share access before breaking any exclusive oplocks. - // - - Status = IoCheckShareAccess( DesiredAccess, - IrpSp->Parameters.Create.ShareAccess, - IrpSp->FileObject, - &Fcb->ShareAccess, - FALSE ); - - if (!NT_SUCCESS( Status )) { - - return Status; - } - - // - // Now check that we can continue based on the oplock state of the - // file. - // - - OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb), - IrpContext->Irp, - IrpContext, - (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */ - (PVOID)CdPrePostIrp );/* ReactOS Change: GCC "assignment from incompatible pointer type" */ - - if (OplockStatus == STATUS_PENDING) { - - return STATUS_PENDING; - } - - IrpContext->TeardownFcb = NULL; - - // - // Otherwise just do the sharing check. - // - - } else { - - Status = IoCheckShareAccess( DesiredAccess, - IrpSp->Parameters.Create.ShareAccess, - IrpSp->FileObject, - &Fcb->ShareAccess, - FALSE ); - - if (!NT_SUCCESS( Status )) { - - return Status; - } - } - } - - // - // Create the Ccb now. - // - - Ccb = CdCreateCcb( IrpContext, Fcb, UserCcbFlags ); - - // - // Update the share access. - // - - if (Fcb->FcbCleanup == 0) { - - IoSetShareAccess( DesiredAccess, - IrpSp->Parameters.Create.ShareAccess, - IrpSp->FileObject, - &Fcb->ShareAccess ); - - } else { - - IoUpdateShareAccess( IrpSp->FileObject, &Fcb->ShareAccess ); - } - - // - // Set the file object type. - // - - CdSetFileObject( IrpContext, IrpSp->FileObject, TypeOfOpen, Fcb, Ccb ); - - // - // Set the appropriate cache flags for a user file object. - // - - if (TypeOfOpen == UserFileOpen) { - - if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING )) { - - SetFlag( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ); - - } else { - - SetFlag( IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED ); - } - } - else if (TypeOfOpen == UserVolumeOpen) { - - SetFlag( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ); - } - - // - // Update the open and cleanup counts. Check the fast io state here. - // - - CdLockVcb( IrpContext, Vcb ); - - CdIncrementCleanupCounts( IrpContext, Fcb ); - CdIncrementReferenceCounts( IrpContext, Fcb, 1, 1 ); - - if (LockVolume) { - - Vcb->VolumeLockFileObject = IrpSp->FileObject; - SetFlag( Vcb->VcbState, VCB_STATE_LOCKED ); - } - - CdUnlockVcb( IrpContext, Vcb ); - - CdLockFcb( IrpContext, Fcb ); - - if (TypeOfOpen == UserFileOpen) { - - Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); - - } else { - - Fcb->IsFastIoPossible = FastIoIsNotPossible; - } - - CdUnlockFcb( IrpContext, Fcb ); - - // - // Show that we opened the file. - // - - IrpContext->Irp->IoStatus.Information = Information; - - // - // Point to the section object pointer in the non-paged Fcb. - // - - IrpSp->FileObject->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject; - return OplockStatus; -} - - - - - diff --git a/drivers/filesystems/cdfs_new/devctrl.c b/drivers/filesystems/cdfs_new/devctrl.c deleted file mode 100755 index 4d0a70ad55e..00000000000 --- a/drivers/filesystems/cdfs_new/devctrl.c +++ /dev/null @@ -1,199 +0,0 @@ -/*++ - -Copyright (c) 1989-2000 Microsoft Corporation - -Module Name: - - DevCtrl.c - -Abstract: - - This module implements the File System Device Control routines for Cdfs - called by the dispatch driver. - - ---*/ - -#include "cdprocs.h" - -// -// The Bug check file id for this module -// - -#define BugCheckFileId (CDFS_BUG_CHECK_DEVCTRL) - -// -// Local support routines -// - -// Tell prefast this is a completion routine -IO_COMPLETION_ROUTINE CdDevCtrlCompletionRoutine; - -NTSTATUS -NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ -CdDevCtrlCompletionRoutine ( - _In_ PDEVICE_OBJECT DeviceObject, - _In_ PIRP Irp, - _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, CdCommonDevControl) -#endif - - -NTSTATUS -CdCommonDevControl ( - _Inout_ PIRP_CONTEXT IrpContext, - _Inout_ PIRP Irp - ) - -/*++ - -Routine Description: - -Arguments: - -Return Value: - ---*/ - -{ - NTSTATUS Status; - - TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb; - PCCB Ccb; - - PIO_STACK_LOCATION IrpSp; - PIO_STACK_LOCATION NextIrpSp; - - PAGED_CODE(); - - // - // Extract and decode the file object. - // - - IrpSp = IoGetCurrentIrpStackLocation( Irp ); - - TypeOfOpen = CdDecodeFileObject( IrpContext, - IrpSp->FileObject, - &Fcb, - &Ccb ); - - // - // The only type of opens we accept are user volume opens. - // - - if (TypeOfOpen != UserVolumeOpen) { - - CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); - return STATUS_INVALID_PARAMETER; - } - - if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) { - - // - // Verify the Vcb in this case to detect if the volume has changed. - // - - CdVerifyVcb( IrpContext, Fcb->Vcb ); - - // - // Handle the case of the disk type ourselves. - // - - } else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) { - - // - // Verify the Vcb in this case to detect if the volume has changed. - // - - CdVerifyVcb( IrpContext, Fcb->Vcb ); - - // - // Check the size of the output buffer. - // - - if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) { - - CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); - return STATUS_BUFFER_TOO_SMALL; - } - - // - // Copy the data from the Vcb. - // - - ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags; - - Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA ); - CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); - return STATUS_SUCCESS; - } - - // - // Get the next stack location, and copy over the stack parameter - // information. - // - - NextIrpSp = IoGetNextIrpStackLocation( Irp ); - - *NextIrpSp = *IrpSp; - - // - // Set up the completion routine - // - - IoSetCompletionRoutine( Irp, - CdDevCtrlCompletionRoutine, - NULL, - TRUE, - TRUE, - TRUE ); - - // - // Send the request. - // - - Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp ); - - // - // Cleanup our Irp Context. The driver has completed the Irp. - // - - CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); - - return Status; -} - - -// -// Local support routine -// - -NTSTATUS -NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ -CdDevCtrlCompletionRoutine ( - _In_ PDEVICE_OBJECT DeviceObject, - _In_ PIRP Irp, - _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt - ) - -{ - // - // Add the hack-o-ramma to fix formats. - // - - if (Irp->PendingReturned) { - - IoMarkIrpPending( Irp ); - } - - return STATUS_SUCCESS; - - UNREFERENCED_PARAMETER( DeviceObject ); - UNREFERENCED_PARAMETER( Contxt ); -} - - diff --git a/drivers/filesystems/cdfs_new/volinfo.c b/drivers/filesystems/cdfs_new/volinfo.c deleted file mode 100755 index 7448dd58507..00000000000 --- a/drivers/filesystems/cdfs_new/volinfo.c +++ /dev/null @@ -1,605 +0,0 @@ -/*++ - -Copyright (c) 1989-2000 Microsoft Corporation - -Module Name: - - VolInfo.c - -Abstract: - - This module implements the volume information routines for Cdfs called by - the dispatch driver. - - ---*/ - -#include "cdprocs.h" - -// -// The Bug check file id for this module -// - -#define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO) - -// -// Local support routines -// - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdQueryFsVolumeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_VOLUME_INFORMATION Buffer, - _Inout_ PULONG Length - ); - -NTSTATUS -CdQueryFsSizeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_SIZE_INFORMATION Buffer, - _Inout_ PULONG Length - ); - -NTSTATUS -CdQueryFsDeviceInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_DEVICE_INFORMATION Buffer, - _Inout_ PULONG Length - ); - -NTSTATUS -CdQueryFsAttributeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer, - _Inout_ PULONG Length - ); - -#ifdef __REACTOS__ -#define PFILE_FS_SECTOR_SIZE_INFORMATION PVOID -#endif - -NTSTATUS -CdQueryFsSectorSizeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer, - _Inout_ PULONG Length - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, CdCommonQueryVolInfo) -#pragma alloc_text(PAGE, CdQueryFsAttributeInfo) -#pragma alloc_text(PAGE, CdQueryFsDeviceInfo) -#pragma alloc_text(PAGE, CdQueryFsSizeInfo) -#pragma alloc_text(PAGE, CdQueryFsVolumeInfo) -#pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo) -#endif - - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdCommonQueryVolInfo ( - _Inout_ PIRP_CONTEXT IrpContext, - _Inout_ PIRP Irp - ) - -/*++ - -Routine Description: - - This is the common routine for querying volume information called by both - the fsd and fsp threads. - -Arguments: - - Irp - Supplies the Irp being processed - -Return Value: - - NTSTATUS - The return status for the operation - ---*/ - -{ - NTSTATUS Status = STATUS_INVALID_PARAMETER; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); - - ULONG Length; - - TYPE_OF_OPEN TypeOfOpen; - PFCB Fcb; - PCCB Ccb; - - PAGED_CODE(); - - // - // Reference our input parameters to make things easier - // - - Length = IrpSp->Parameters.QueryVolume.Length; - - // - // Decode the file object and fail if this an unopened file object. - // - - TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); - - if (TypeOfOpen == UnopenedFileObject) { - - CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); - return STATUS_INVALID_PARAMETER; - } - - // - // Acquire the Vcb for this volume. - // - - CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE ); - - // - // Use a try-finally to facilitate cleanup. - // - - _SEH2_TRY { - - // - // Verify the Vcb. - // - - CdVerifyVcb( IrpContext, Fcb->Vcb ); - - // - // Based on the information class we'll do different actions. Each - // of the procedures that we're calling fills up the output buffer - // if possible and returns true if it successfully filled the buffer - // and false if it couldn't wait for any I/O to complete. - // - - switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { - - case FileFsSizeInformation: - - Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); - break; - - case FileFsVolumeInformation: - - Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); - break; - - case FileFsDeviceInformation: - - Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); - break; - - case FileFsAttributeInformation: - - Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); - break; - -#if (NTDDI_VERSION >= NTDDI_WIN8) - case FileFsSectorSizeInformation: - - Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); - break; -#endif - - /* ReactOS Change: GCC "enumeration value not handled in switch" */ - default: break; - } - - // - // Set the information field to the number of bytes actually filled in - // - - Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length; - - } _SEH2_FINALLY { - - // - // Release the Vcb. - // - - CdReleaseVcb( IrpContext, Fcb->Vcb ); - } _SEH2_END; - - // - // Complete the request if we didn't raise. - // - - CdCompleteRequest( IrpContext, Irp, Status ); - - return Status; -} - - -// -// Local support routine -// - -_Requires_lock_held_(_Global_critical_region_) -NTSTATUS -CdQueryFsVolumeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_VOLUME_INFORMATION Buffer, - _Inout_ PULONG Length - ) - -/*++ - -Routine Description: - - This routine implements the query volume info call - -Arguments: - - Vcb - Vcb for this volume. - - Buffer - Supplies a pointer to the output buffer where the information - is to be returned - - Length - Supplies the length of the buffer in byte. This variable - upon return recieves the remaining bytes free in the buffer - -Return Value: - - NTSTATUS - Returns the status for the query - ---*/ - -{ - ULONG BytesToCopy; - - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - UNREFERENCED_PARAMETER( IrpContext ); - - // - // Fill in the data from the Vcb. - // - - Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime); - Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber; - - Buffer->SupportsObjects = FALSE; - - *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] ); - - // - // Check if the buffer we're given is long enough - // - - if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) { - - BytesToCopy = Vcb->Vpb->VolumeLabelLength; - - } else { - - BytesToCopy = *Length; - - Status = STATUS_BUFFER_OVERFLOW; - } - - // - // Copy over what we can of the volume label, and adjust *Length - // - - Buffer->VolumeLabelLength = BytesToCopy; - - if (BytesToCopy) { - - RtlCopyMemory( &Buffer->VolumeLabel[0], - &Vcb->Vpb->VolumeLabel[0], - BytesToCopy ); - } - - *Length -= BytesToCopy; - - // - // Set our status and return to our caller - // - - return Status; -} - - -// -// Local support routine -// - -NTSTATUS -CdQueryFsSizeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_SIZE_INFORMATION Buffer, - _Inout_ PULONG Length - ) - -/*++ - -Routine Description: - - This routine implements the query volume size call. - -Arguments: - - Vcb - Vcb for this volume. - - Buffer - Supplies a pointer to the output buffer where the information - is to be returned - - Length - Supplies the length of the buffer in byte. This variable - upon return recieves the remaining bytes free in the buffer - -Return Value: - - NTSTATUS - Returns the status for the query - ---*/ - -{ - PAGED_CODE(); - - UNREFERENCED_PARAMETER( IrpContext ); - - // - // Fill in the output buffer. - // - - Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart ); - - Buffer->AvailableAllocationUnits.QuadPart = 0; - Buffer->SectorsPerAllocationUnit = 1; - Buffer->BytesPerSector = SECTOR_SIZE; - - // - // Adjust the length variable - // - - *Length -= sizeof( FILE_FS_SIZE_INFORMATION ); - - // - // And return success to our caller - // - - return STATUS_SUCCESS; -} - - -// -// Local support routine -// - -NTSTATUS -CdQueryFsDeviceInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_DEVICE_INFORMATION Buffer, - _Inout_ PULONG Length - ) - -/*++ - -Routine Description: - - This routine implements the query volume device call. - -Arguments: - - Vcb - Vcb for this volume. - - Buffer - Supplies a pointer to the output buffer where the information - is to be returned - - Length - Supplies the length of the buffer in byte. This variable - upon return recieves the remaining bytes free in the buffer - -Return Value: - - NTSTATUS - Returns the status for the query - ---*/ - -{ - PAGED_CODE(); - - UNREFERENCED_PARAMETER( IrpContext ); - - // - // Update the output buffer. - // - - Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics; - Buffer->DeviceType = FILE_DEVICE_CD_ROM; - - // - // Adjust the length variable - // - - *Length -= sizeof( FILE_FS_DEVICE_INFORMATION ); - - // - // And return success to our caller - // - - return STATUS_SUCCESS; -} - - -// -// Local support routine -// - -NTSTATUS -CdQueryFsAttributeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer, - _Inout_ PULONG Length - ) - -/*++ - -Routine Description: - - This routine implements the query volume attribute call. - -Arguments: - - Vcb - Vcb for this volume. - - Buffer - Supplies a pointer to the output buffer where the information - is to be returned - - Length - Supplies the length of the buffer in byte. This variable - upon return recieves the remaining bytes free in the buffer - -Return Value: - - NTSTATUS - Returns the status for the query - ---*/ - -{ - ULONG BytesToCopy; - - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - UNREFERENCED_PARAMETER( Vcb ); - - // - // Fill out the fixed portion of the buffer. - // - - Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | - FILE_READ_ONLY_VOLUME | - FILE_SUPPORTS_OPEN_BY_FILE_ID; - - if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) { - - SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK ); - - Buffer->MaximumComponentNameLength = 110; - - } else { - - Buffer->MaximumComponentNameLength = 221; - } - - *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ); - - // - // Make sure we can copy full unicode characters. - // - - ClearFlag( *Length, 1 ); - - // - // Determine how much of the file system name will fit. - // - - if (*Length >= 8) { - - BytesToCopy = 8; - - } else { - - BytesToCopy = *Length; - Status = STATUS_BUFFER_OVERFLOW; - } - - *Length -= BytesToCopy; - - // - // Do the file system name. - // - - Buffer->FileSystemNameLength = BytesToCopy; - - RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy ); - - // - // And return to our caller - // - - return Status; -} - -#if (NTDDI_VERSION >= NTDDI_WIN8) - -NTSTATUS -CdQueryFsSectorSizeInfo ( - _In_ PIRP_CONTEXT IrpContext, - _In_ PVCB Vcb, - _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer, - _Inout_ PULONG Length - ) - -/*++ - -Routine Description: - - This routine implements the query sector size information call - This operation will work on any handle and requires no privilege. - -Arguments: - - Vcb - Supplies the Vcb being queried - - Buffer - Supplies a pointer to the output buffer where the information - is to be returned - - Length - Supplies the length of the buffer in byte. This variable - upon return receives the remaining bytes free in the buffer - -Return Value: - - NTSTATUS - Returns the status for the query - ---*/ - -{ - NTSTATUS Status; - - PAGED_CODE(); - UNREFERENCED_PARAMETER( IrpContext ); - - // - // Sufficient buffer size is guaranteed by the I/O manager or the - // originating kernel mode driver. - // - - ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION )); - _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION )); - - // - // Retrieve the sector size information - // - - Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice, - Buffer ); - - // - // Adjust the length variable - // - - if (NT_SUCCESS( Status )) { - - *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ); - } - - return Status; -} - -#endif -