From 19f220bf512e2a2a9bc29f4f0a8de46da218d725 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Thu, 23 Mar 2023 22:09:06 +0100 Subject: [PATCH] [0.4.9][CDFS_NEW] -> [CDFS] port back: 0.4.10-dev-615-g 45fd48bd0ffb56d224d2e3bf2d93db6007fefbc5 [CDFS_NEW] -> [CDFS] No old driver, thus no new driver 0.4.10-dev-614-g 5795254933b462a0a960c32900bde63c815bcc48 [CDFS] Delete the old CDFS driver. The new MS PL licensed one worked for several years fine for us now even in the older releases. So no need to keep our old unfinished one any longer within the release-branches. They are no mausoleum. This does *not* change, which driver is actually in use. We do continue to use 1:1 the state of current releases/0.4.10 --- boot/environ/lib/io/etfs.c | 2 +- drivers/filesystems/CMakeLists.txt | 2 +- drivers/filesystems/cdfs/CMakeLists.txt | 38 +- .../filesystems/{cdfs_new => cdfs}/LICENSE | 0 .../filesystems/{cdfs_new => cdfs}/README.md | 0 .../filesystems/{cdfs_new => cdfs}/allocsup.c | 0 .../filesystems/{cdfs_new => cdfs}/cachesup.c | 0 drivers/filesystems/{cdfs_new => cdfs}/cd.h | 0 .../filesystems/{cdfs_new => cdfs}/cddata.c | 0 .../filesystems/{cdfs_new => cdfs}/cddata.h | 0 drivers/filesystems/cdfs/cdfs.c | 141 - drivers/filesystems/cdfs/cdfs.h | 531 --- drivers/filesystems/cdfs/cdfs.rc | 19 +- .../filesystems/{cdfs_new => cdfs}/cdinit.c | 0 .../filesystems/{cdfs_new => cdfs}/cdprocs.h | 0 .../{cdfs_new => cdfs}/cdprocssrc.c | 0 .../filesystems/{cdfs_new => cdfs}/cdstruc.h | 0 drivers/filesystems/cdfs/cleanup.c | 449 ++- drivers/filesystems/cdfs/close.c | 1074 +++++- drivers/filesystems/cdfs/common.c | 242 -- drivers/filesystems/cdfs/create.c | 3207 +++++++++++++++-- drivers/filesystems/cdfs/devctrl.c | 226 +- .../filesystems/{cdfs_new => cdfs}/deviosup.c | 0 drivers/filesystems/cdfs/dirctl.c | 812 ----- .../filesystems/{cdfs_new => cdfs}/dirctrl.c | 0 .../filesystems/{cdfs_new => cdfs}/dirsup.c | 0 drivers/filesystems/cdfs/dispatch.c | 222 -- drivers/filesystems/cdfs/fastio.c | 116 - drivers/filesystems/cdfs/fcb.c | 722 ---- .../filesystems/{cdfs_new => cdfs}/fieldoff.c | 0 .../filesystems/{cdfs_new => cdfs}/fileinfo.c | 0 .../filesystems/{cdfs_new => cdfs}/filobsup.c | 0 drivers/filesystems/cdfs/finfo.c | 498 --- drivers/filesystems/cdfs/fsctl.c | 702 ---- .../filesystems/{cdfs_new => cdfs}/fsctrl.c | 0 .../filesystems/{cdfs_new => cdfs}/fspdisp.c | 0 .../filesystems/{cdfs_new => cdfs}/lockctrl.c | 0 drivers/filesystems/cdfs/misc.c | 380 -- .../filesystems/{cdfs_new => cdfs}/namesup.c | 0 .../filesystems/{cdfs_new => cdfs}/nodetype.h | 0 .../filesystems/{cdfs_new => cdfs}/pathsup.c | 0 drivers/filesystems/{cdfs_new => cdfs}/pnp.c | 0 .../filesystems/{cdfs_new => cdfs}/prefxsup.c | 0 drivers/filesystems/{cdfs_new => cdfs}/read.c | 0 .../filesystems/{cdfs_new => cdfs}/resrcsup.c | 0 drivers/filesystems/cdfs/rw.c | 251 -- .../filesystems/{cdfs_new => cdfs}/shutdown.c | 0 .../filesystems/{cdfs_new => cdfs}/strucsup.c | 0 .../filesystems/{cdfs_new => cdfs}/verfysup.c | 0 drivers/filesystems/cdfs/volinfo.c | 828 +++-- .../filesystems/{cdfs_new => cdfs}/workque.c | 0 .../filesystems/{cdfs_new => cdfs}/write.c | 0 drivers/filesystems/cdfs_new/CMakeLists.txt | 40 - drivers/filesystems/cdfs_new/cdfs.rc | 14 - drivers/filesystems/cdfs_new/cdfs_reg.inf | 7 - drivers/filesystems/cdfs_new/cleanup.c | 366 -- drivers/filesystems/cdfs_new/close.c | 1023 ------ drivers/filesystems/cdfs_new/create.c | 2972 --------------- drivers/filesystems/cdfs_new/devctrl.c | 199 - drivers/filesystems/cdfs_new/volinfo.c | 605 ---- 60 files changed, 5062 insertions(+), 10626 deletions(-) rename drivers/filesystems/{cdfs_new => cdfs}/LICENSE (100%) rename drivers/filesystems/{cdfs_new => cdfs}/README.md (100%) rename drivers/filesystems/{cdfs_new => cdfs}/allocsup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cachesup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cd.h (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cddata.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cddata.h (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/cdfs.c delete mode 100644 drivers/filesystems/cdfs/cdfs.h rename drivers/filesystems/{cdfs_new => cdfs}/cdinit.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cdprocs.h (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/cdprocssrc.c (100%) rename drivers/filesystems/{cdfs_new => cdfs}/cdstruc.h (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/common.c rename drivers/filesystems/{cdfs_new => cdfs}/deviosup.c (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/dirctl.c rename drivers/filesystems/{cdfs_new => cdfs}/dirctrl.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/dirsup.c (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/dispatch.c delete mode 100644 drivers/filesystems/cdfs/fastio.c delete mode 100644 drivers/filesystems/cdfs/fcb.c rename drivers/filesystems/{cdfs_new => cdfs}/fieldoff.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/fileinfo.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/filobsup.c (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/finfo.c delete mode 100644 drivers/filesystems/cdfs/fsctl.c rename drivers/filesystems/{cdfs_new => cdfs}/fsctrl.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/fspdisp.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/lockctrl.c (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/misc.c rename drivers/filesystems/{cdfs_new => cdfs}/namesup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/nodetype.h (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/pathsup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/pnp.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/prefxsup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/read.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/resrcsup.c (100%) mode change 100755 => 100644 delete mode 100644 drivers/filesystems/cdfs/rw.c rename drivers/filesystems/{cdfs_new => cdfs}/shutdown.c (100%) rename drivers/filesystems/{cdfs_new => cdfs}/strucsup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/verfysup.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/workque.c (100%) mode change 100755 => 100644 rename drivers/filesystems/{cdfs_new => cdfs}/write.c (100%) delete mode 100644 drivers/filesystems/cdfs_new/CMakeLists.txt delete mode 100644 drivers/filesystems/cdfs_new/cdfs.rc delete mode 100644 drivers/filesystems/cdfs_new/cdfs_reg.inf delete mode 100755 drivers/filesystems/cdfs_new/cleanup.c delete mode 100755 drivers/filesystems/cdfs_new/close.c delete mode 100755 drivers/filesystems/cdfs_new/create.c delete mode 100755 drivers/filesystems/cdfs_new/devctrl.c delete mode 100755 drivers/filesystems/cdfs_new/volinfo.c 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 -