/** * @file sys/driver.c * * @copyright 2015-2022 Bill Zissimopoulos */ /* * This file is part of WinFsp. * * You can redistribute it and/or modify it under the terms of the GNU * General Public License version 3 as published by the Free Software * Foundation. * * Licensees holding a valid commercial license may use this software * in accordance with the commercial license agreement provided in * conjunction with the software. The terms and conditions of any such * commercial license agreement shall govern, supersede, and render * ineffective any application of the GPLv3 license to this software, * notwithstanding of any reference thereto in the software or * associated repository. */ #include DRIVER_INITIALIZE DriverEntry; static DRIVER_UNLOAD DriverUnload; static VOID FspDriverMultiVersionInitialize(VOID); static NTSTATUS FspDriverInitializeDevices(VOID); static VOID FspDriverFinalizeDevices(VOID); static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices); NTSTATUS FspDriverUnload( PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(PAGE, DriverUnload) #pragma alloc_text(INIT, FspDriverMultiVersionInitialize) #pragma alloc_text(PAGE, FspDriverInitializeDevices) #pragma alloc_text(PAGE, FspDriverFinalizeDevices) #pragma alloc_text(PAGE, FspDriverFinalizeDevicesEx) #pragma alloc_text(PAGE, FspDriverUnload) #endif NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { FSP_ENTER_DRV(); FSP_TRACE_INIT(); FspSxsIdentInitialize(&DriverObject->DriverName); /* setup the driver object */ DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose; DriverObject->MajorFunction[IRP_MJ_READ] = FspRead; DriverObject->MajorFunction[IRP_MJ_WRITE] = FspWrite; DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FspQueryInformation; DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FspSetInformation; DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = FspQueryEa; DriverObject->MajorFunction[IRP_MJ_SET_EA] = FspSetEa; DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FspFlushBuffers; DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspQueryVolumeInformation; DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspSetVolumeInformation; DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControl; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControl; DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FspShutdown; DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FspLockControl; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FspCleanup; DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = FspQuerySecurity; DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = FspSetSecurity; /* setup the I/O prepare/complete functions */ FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; FspIopPrepareFunction[IRP_MJ_READ] = FspFsvolReadPrepare; FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare; FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; FspIopCompleteFunction[IRP_MJ_QUERY_INFORMATION] = FspFsvolQueryInformationComplete; FspIopPrepareFunction[IRP_MJ_SET_INFORMATION] = FspFsvolSetInformationPrepare; FspIopCompleteFunction[IRP_MJ_SET_INFORMATION] = FspFsvolSetInformationComplete; FspIopCompleteFunction[IRP_MJ_QUERY_EA] = FspFsvolQueryEaComplete; FspIopCompleteFunction[IRP_MJ_SET_EA] = FspFsvolSetEaComplete; FspIopCompleteFunction[IRP_MJ_FLUSH_BUFFERS] = FspFsvolFlushBuffersComplete; FspIopCompleteFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspFsvolQueryVolumeInformationComplete; FspIopCompleteFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspFsvolSetVolumeInformationComplete; FspIopPrepareFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlPrepare; FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete; FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete; FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete; FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete; FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete; FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete; FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete; /* setup fast I/O and resource acquisition */ FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch; FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible; FspFastIoDispatch.FastIoRead = FspFastIoRead; FspFastIoDispatch.FastIoWrite = FspFastIoWrite; FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo; FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo; //FspFastIoDispatch.FastIoLock = 0; //FspFastIoDispatch.FastIoUnlockSingle = 0; //FspFastIoDispatch.FastIoUnlockAll = 0; //FspFastIoDispatch.FastIoUnlockAllByKey = 0; FspFastIoDispatch.FastIoDeviceControl = FspFastIoDeviceControl; FspFastIoDispatch.AcquireFileForNtCreateSection = FspAcquireFileForNtCreateSection; FspFastIoDispatch.ReleaseFileForNtCreateSection = FspReleaseFileForNtCreateSection; //FspFastIoDispatch.FastIoDetachDevice = 0; FspFastIoDispatch.FastIoQueryNetworkOpenInfo = FspFastIoQueryNetworkOpenInfo; FspFastIoDispatch.AcquireForModWrite = FspAcquireForModWrite; //FspFastIoDispatch.MdlRead = 0; //FspFastIoDispatch.MdlReadComplete = 0; //FspFastIoDispatch.PrepareMdlWrite = 0; //FspFastIoDispatch.MdlWriteComplete = 0; //FspFastIoDispatch.FastIoReadCompressed = 0; //FspFastIoDispatch.FastIoWriteCompressed = 0; //FspFastIoDispatch.MdlReadCompleteCompressed = 0; //FspFastIoDispatch.MdlWriteCompleteCompressed = 0; FspFastIoDispatch.FastIoQueryOpen = FspFastIoQueryOpen; FspFastIoDispatch.ReleaseForModWrite = FspReleaseForModWrite; FspFastIoDispatch.AcquireForCcFlush = FspAcquireForCcFlush; FspFastIoDispatch.ReleaseForCcFlush = FspReleaseForCcFlush; FspCacheManagerCallbacks.AcquireForLazyWrite = FspAcquireForLazyWrite; FspCacheManagerCallbacks.ReleaseFromLazyWrite = FspReleaseFromLazyWrite; FspCacheManagerCallbacks.AcquireForReadAhead = FspAcquireForReadAhead; FspCacheManagerCallbacks.ReleaseFromReadAhead = FspReleaseFromReadAhead; #pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch") DriverObject->FastIoDispatch = &FspFastIoDispatch; BOOLEAN InitDoneSilo = FALSE, InitDonePsBuf = FALSE, InitDoneTimers = FALSE, InitDoneDevices = FALSE; FspDriverObject = DriverObject; FspDriverMultiVersionInitialize(); ExInitializeFastMutex(&FspDriverUnloadMutex); ExInitializeFastMutex(&FspDeviceGlobalMutex); Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices); if (!NT_SUCCESS(Result)) goto exit; InitDoneSilo = TRUE; Result = FspProcessBufferInitialize(); if (!NT_SUCCESS(Result)) goto exit; InitDonePsBuf = TRUE; Result = FspDeviceInitializeAllTimers(); if (!NT_SUCCESS(Result)) goto exit; InitDoneTimers = TRUE; Result = FspDriverInitializeDevices(); if (!NT_SUCCESS(Result)) goto exit; InitDoneDevices = TRUE; Result = STATUS_SUCCESS; exit: if (!NT_SUCCESS(Result)) { if (InitDoneDevices) FspDriverFinalizeDevices(); if (InitDoneTimers) FspDeviceFinalizeAllTimers(); if (InitDonePsBuf) FspProcessBufferFinalize(); if (InitDoneSilo) FspSiloFinalize(); FSP_TRACE_FINI(); } #pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName") FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"", &DriverObject->DriverName, RegistryPath); } VOID DriverUnload( PDRIVER_OBJECT DriverObject) { FSP_ENTER_VOID(PAGED_CODE()); FspDriverFinalizeDevices(); FspDeviceFinalizeAllTimers(); FspProcessBufferFinalize(); FspSiloFinalize(); FSP_TRACE_FINI(); #pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName") FSP_LEAVE_VOID("DriverName=\"%wZ\"", &DriverObject->DriverName); } static VOID FspDriverMultiVersionInitialize(VOID) { FspProcessorCount = KeQueryActiveProcessorCount(0); #pragma prefast(suppress:30035, "FspDriverMultiVersionInitialize is called from DriverEntry") ExInitializeDriverRuntime(DrvRtPoolNxOptIn); if (FspIsNtDdiVersionAvailable(NTDDI_WIN7)) { UNICODE_STRING Name; RtlInitUnicodeString(&Name, L"CcCoherencyFlushAndPurgeCache"); FspMvCcCoherencyFlushAndPurgeCache = (FSP_MV_CcCoherencyFlushAndPurgeCache *)(UINT_PTR)MmGetSystemRoutineAddress(&Name); } if (FspIsNtDdiVersionAvailable(NTDDI_WIN8)) FspMvMdlMappingNoWrite = MdlMappingNoWrite; if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS4)) FspHasReparsePointCaseSensitivityFix = TRUE; } static NTSTATUS FspDriverInitializeDevices(VOID) { PAGED_CODE(); FSP_SILO_GLOBALS *Globals; UNICODE_STRING DeviceSddl; UNICODE_STRING DeviceName; WCHAR DeviceNameBuf[128]; UNICODE_STRING SymlinkName; GUID Guid; NTSTATUS Result; FspSiloGetGlobals(&Globals); ASSERT(0 != Globals); /* create the file system control device objects */ RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL); RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf); Result = RtlUnicodeStringPrintf(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME "%wZ", FspSxsSuffix()); ASSERT(NT_SUCCESS(Result)); Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, &DeviceSddl, &FspFsctlDeviceClassGuid, &Globals->FsctlDiskDeviceObject); if (!NT_SUCCESS(Result)) goto exit; if (0 != FspSxsIdent()->Length) { /* \Device\WinFsp.Disk SxS symlink */ RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName); if (!NT_SUCCESS(Result)) goto exit; Globals->InitDoneSymlinkDisk = 1; } RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf); Result = RtlUnicodeStringPrintf(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME "%wZ", FspSxsSuffix()); ASSERT(NT_SUCCESS(Result)); Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, &DeviceSddl, &FspFsctlDeviceClassGuid, &Globals->FsctlNetDeviceObject); if (!NT_SUCCESS(Result)) goto exit; if (0 != FspSxsIdent()->Length) { /* \Device\WinFsp.Net SxS symlink */ RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName); if (!NT_SUCCESS(Result)) goto exit; Globals->InitDoneSymlinkNet = 1; } Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE, &Globals->FsmupDeviceObject); if (!NT_SUCCESS(Result)) goto exit; #if DBG /* * Fix GitHub issue #177. All credit for the investigation of this issue * and the suggested steps to reproduce and work around the problem goes * to GitHub user @thinkport. * * On debug builds set DO_LOW_PRIORITY_FILESYSTEM to place the file system * at the end of the file system list during IoRegisterFileSystem below. * This allows us to test the behavior of our Fsvrt devices when foreign * file systems attempt to use them for mounting. */ SetFlag(Globals->FsctlDiskDeviceObject->Flags, DO_LOW_PRIORITY_FILESYSTEM); #endif Result = FspDeviceInitialize(Globals->FsctlDiskDeviceObject); ASSERT(STATUS_SUCCESS == Result); Result = FspDeviceInitialize(Globals->FsctlNetDeviceObject); ASSERT(STATUS_SUCCESS == Result); Result = FspDeviceInitialize(Globals->FsmupDeviceObject); ASSERT(STATUS_SUCCESS == Result); FspSiloGetContainerId(&Guid); RtlInitEmptyUnicodeString(&DeviceName, Globals->FsmupDeviceNameBuf, sizeof Globals->FsmupDeviceNameBuf); Result = RtlUnicodeStringPrintf(&DeviceName, 0 == ((PULONG)&Guid)[0] && 0 == ((PULONG)&Guid)[1] && 0 == ((PULONG)&Guid)[2] && 0 == ((PULONG)&Guid)[3] ? L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ": L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", FspSxsSuffix(), Guid.Data1, Guid.Data2, Guid.Data3, Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3], Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); ASSERT(NT_SUCCESS(Result)); DeviceName.MaximumLength = DeviceName.Length; Result = FsRtlRegisterUncProviderEx(&Globals->MupHandle, &DeviceName, Globals->FsmupDeviceObject, 0); if (!NT_SUCCESS(Result)) { Globals->MupHandle = 0; goto exit; } /* * Register our "disk" device as a file system. We do not register our "net" device * as a file system; we register with the MUP instead. */ IoRegisterFileSystem(Globals->FsctlDiskDeviceObject); Globals->InitDoneRegisterDisk = 1; /* * Reference primary device objects to allow for IoDeleteDevice during FspDriverUnload. */ ObReferenceObject(Globals->FsctlDiskDeviceObject); ObReferenceObject(Globals->FsctlNetDeviceObject); ObReferenceObject(Globals->FsmupDeviceObject); Result = STATUS_SUCCESS; exit: if (!NT_SUCCESS(Result)) { if (Globals->InitDoneRegisterDisk) { IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject); Globals->InitDoneRegisterDisk = 0; } if (0 != Globals->MupHandle) { FsRtlDeregisterUncProvider(Globals->MupHandle); Globals->MupHandle = 0; } if (0 != Globals->FsmupDeviceObject) { FspDeviceDelete(Globals->FsmupDeviceObject); Globals->FsmupDeviceObject = 0; } if (Globals->InitDoneSymlinkNet) { RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); IoDeleteSymbolicLink(&SymlinkName); Globals->InitDoneSymlinkNet = 0; } if (0 != Globals->FsctlNetDeviceObject) { FspDeviceDelete(Globals->FsctlNetDeviceObject); Globals->FsctlNetDeviceObject = 0; } if (Globals->InitDoneSymlinkDisk) { RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); IoDeleteSymbolicLink(&SymlinkName); Globals->InitDoneSymlinkDisk = 0; } if (0 != Globals->FsctlDiskDeviceObject) { FspDeviceDelete(Globals->FsctlDiskDeviceObject); Globals->FsctlDiskDeviceObject = 0; } } FspSiloDereferenceGlobals(Globals); return Result; } static VOID FspDriverFinalizeDevices(VOID) { PAGED_CODE(); FspDriverFinalizeDevicesEx(TRUE); } static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices) { PAGED_CODE(); FSP_SILO_GLOBALS *Globals; UNICODE_STRING SymlinkName; FspSiloGetGlobals(&Globals); ASSERT(0 != Globals); if (Globals->InitDoneRegisterDisk) { IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject); Globals->InitDoneRegisterDisk = 0; } if (0 != Globals->MupHandle) { FsRtlDeregisterUncProvider(Globals->MupHandle); Globals->MupHandle = 0; } if (0 != Globals->FsmupDeviceObject) { if (DeleteDevices) { FspDeviceDelete(Globals->FsmupDeviceObject); ObDereferenceObject(Globals->FsmupDeviceObject); Globals->FsmupDeviceObject = 0; } else FspDeviceDoIoDeleteDevice(Globals->FsmupDeviceObject); } if (Globals->InitDoneSymlinkNet) { RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); IoDeleteSymbolicLink(&SymlinkName); Globals->InitDoneSymlinkNet = 0; } if (0 != Globals->FsctlNetDeviceObject) { if (DeleteDevices) { FspDeviceDelete(Globals->FsctlNetDeviceObject); ObDereferenceObject(Globals->FsctlNetDeviceObject); Globals->FsctlNetDeviceObject = 0; } else FspDeviceDoIoDeleteDevice(Globals->FsctlNetDeviceObject); } if (Globals->InitDoneSymlinkDisk) { RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); IoDeleteSymbolicLink(&SymlinkName); Globals->InitDoneSymlinkDisk = 0; } if (0 != Globals->FsctlDiskDeviceObject) { if (DeleteDevices) { FspDeviceDelete(Globals->FsctlDiskDeviceObject); ObDereferenceObject(Globals->FsctlDiskDeviceObject); Globals->FsctlDiskDeviceObject = 0; } else FspDeviceDoIoDeleteDevice(Globals->FsctlDiskDeviceObject); } FspSiloDereferenceGlobals(Globals); } NTSTATUS FspDriverUnload( PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction); ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction); ASSERT(FSP_FSCTL_UNLOAD == IrpSp->Parameters.FileSystemControl.FsControlCode); NTSTATUS Result; UNICODE_STRING DriverServiceName, DriverName, Remain; WCHAR DriverServiceNameBuf[64 + 256]; PDEVICE_OBJECT *DeviceObjects = 0; ULONG DeviceObjectCount = 0; if (!FspSiloIsHost()) return STATUS_INVALID_DEVICE_REQUEST; if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), UserMode)) return STATUS_PRIVILEGE_NOT_HELD; ExAcquireFastMutexUnsafe(&FspDriverUnloadMutex); if (!FspDriverUnloadDone) { FspFileNameSuffix(&FspDriverObject->DriverName, &Remain, &DriverName); RtlInitEmptyUnicodeString(&DriverServiceName, DriverServiceNameBuf, sizeof DriverServiceNameBuf); Result = RtlUnicodeStringPrintf(&DriverServiceName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%wZ", &DriverName); if (!NT_SUCCESS(Result)) goto exit; Result = ZwUnloadDriver(&DriverServiceName); if (!NT_SUCCESS(Result)) goto exit; FspDriverFinalizeDevicesEx(FALSE); Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount); if (NT_SUCCESS(Result)) { for (ULONG I = 0; DeviceObjectCount > I; I++) { FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObjects[I]); if (FspFsvolDeviceExtensionKind == DeviceExtension->Kind) FspIoqStop(((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Ioq, FALSE); } FspDeviceDeleteList(DeviceObjects, DeviceObjectCount); } FspDriverUnloadDone = TRUE; } Result = STATUS_SUCCESS; exit: ExReleaseFastMutexUnsafe(&FspDriverUnloadMutex); return Result; } PDRIVER_OBJECT FspDriverObject; FAST_IO_DISPATCH FspFastIoDispatch; CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks; FAST_MUTEX FspDriverUnloadMutex; BOOLEAN FspDriverUnloadDone; ULONG FspProcessorCount; FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache; ULONG FspMvMdlMappingNoWrite = 0; BOOLEAN FspHasReparsePointCaseSensitivityFix = FALSE;