mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 03:28:38 -05:00 
			
		
		
		
	sys: fsmup device
- This commit introduces the fsmup device, which is a major change in how network file systems are handled. Previously every network file system's fsvol device was directly registered with the MUP. Now there is a single fsmup device that is registered with the MUP; network file systems' fsvol devices register with fsmup instead. The fsmup device maintains a prefix table which it uses to demultiplex and forward requests to the appropriate fsvol device. - This device change was necessatitated to fix issue #87.
This commit is contained in:
		| @@ -164,6 +164,8 @@ static NTSTATUS FspFsvolCreateNoLock( | ||||
| #pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb") | ||||
|             FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb; | ||||
|  | ||||
|         FileObject->FsContext2 = FsvolDeviceObject; | ||||
|  | ||||
|         Irp->IoStatus.Information = FILE_OPENED; | ||||
|         return STATUS_SUCCESS; | ||||
|     } | ||||
|   | ||||
| @@ -281,6 +281,8 @@ const char *DeviceExtensionKindSym(UINT32 Kind) | ||||
|     { | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         return "Ctl"; | ||||
|     case FspFsmupDeviceExtensionKind: | ||||
|         return "Mup"; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|         return "Vrt"; | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|   | ||||
| @@ -33,15 +33,7 @@ static NTSTATUS FspFsvolDeviceControl( | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST; | ||||
|     switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) | ||||
|     { | ||||
|     case IOCTL_REDIR_QUERY_PATH_EX : | ||||
|         Result = FspVolumeRedirQueryPathEx(DeviceObject, Irp, IrpSp); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return Result; | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolDeviceControlComplete( | ||||
|   | ||||
| @@ -63,6 +63,8 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I | ||||
| BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject); | ||||
| static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject); | ||||
| NTSTATUS FspDeviceCopyList( | ||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||
| VOID FspDeviceDeleteList( | ||||
| @@ -94,6 +96,8 @@ VOID FspDeviceDeleteAll(VOID); | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsmupDeviceInit) | ||||
| #pragma alloc_text(PAGE, FspFsmupDeviceFini) | ||||
| #pragma alloc_text(PAGE, FspDeviceCopyList) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteList) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteAll) | ||||
| @@ -118,6 +122,9 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION); | ||||
|         break; | ||||
|     case FspFsmupDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION); | ||||
| @@ -173,6 +180,9 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject) | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         Result = FspFsvolDeviceInit(DeviceObject); | ||||
|         break; | ||||
|     case FspFsmupDeviceExtensionKind: | ||||
|         Result = FspFsmupDeviceInit(DeviceObject); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         Result = STATUS_SUCCESS; | ||||
| @@ -199,6 +209,9 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject) | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         FspFsvolDeviceFini(DeviceObject); | ||||
|         break; | ||||
|     case FspFsmupDeviceExtensionKind: | ||||
|         FspFsmupDeviceFini(DeviceObject); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         break; | ||||
| @@ -876,6 +889,37 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject) | ||||
|     KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject); | ||||
|  | ||||
|     /* initialize our prefix table */ | ||||
|     ExInitializeResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
|     RtlInitializeUnicodePrefix(&FsmupDeviceExtension->PrefixTable); | ||||
|     FsmupDeviceExtension->InitDonePfxTab = 1; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject); | ||||
|  | ||||
|     if (FsmupDeviceExtension->InitDonePfxTab) | ||||
|     { | ||||
|         /* | ||||
|          * Normally we would have to finalize our prefix table. This is not necessary as all | ||||
|          * prefixes will be gone if this code ever gets reached. | ||||
|          */ | ||||
|         ASSERT(0 == RtlNextUnicodePrefix(&FsmupDeviceExtension->PrefixTable, TRUE)); | ||||
|         ExDeleteResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
|     } | ||||
| } | ||||
|  | ||||
| NTSTATUS FspDeviceCopyList( | ||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount) | ||||
| { | ||||
|   | ||||
							
								
								
									
										111
									
								
								src/sys/driver.c
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								src/sys/driver.c
									
									
									
									
									
								
							| @@ -44,45 +44,6 @@ NTSTATUS DriverEntry( | ||||
| { | ||||
|     FSP_ENTER_DRV(); | ||||
|  | ||||
|     FspDriverMultiVersionInitialize(); | ||||
|  | ||||
|     Result = FspProcessBufferInitialize(); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         FSP_RETURN(); | ||||
|  | ||||
|     FspDriverObject = DriverObject; | ||||
|     ExInitializeResourceLite(&FspDeviceGlobalResource); | ||||
|  | ||||
|     /* create the file system control device objects */ | ||||
|     UNICODE_STRING DeviceSddl; | ||||
|     UNICODE_STRING DeviceName; | ||||
|     RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL); | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlDiskDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FspProcessBufferFinalize(); | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlNetDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FspDeviceDelete(FspFsctlDiskDeviceObject); | ||||
|         FspProcessBufferFinalize(); | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|     Result = FspDeviceInitialize(FspFsctlDiskDeviceObject); | ||||
|     ASSERT(STATUS_SUCCESS == Result); | ||||
|     Result = FspDeviceInitialize(FspFsctlNetDeviceObject); | ||||
|     ASSERT(STATUS_SUCCESS == Result); | ||||
|  | ||||
|     /* setup the driver object */ | ||||
| #if defined(FSP_UNLOAD) | ||||
|     DriverObject->DriverUnload = FspUnload; | ||||
| @@ -127,7 +88,6 @@ NTSTATUS DriverEntry( | ||||
|     FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspFsvolShutdownComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete; | ||||
| @@ -169,9 +129,58 @@ NTSTATUS DriverEntry( | ||||
| #pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch") | ||||
|     DriverObject->FastIoDispatch = &FspFastIoDispatch; | ||||
|  | ||||
|     BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE; | ||||
|     UNICODE_STRING DeviceSddl; | ||||
|     UNICODE_STRING DeviceName; | ||||
|  | ||||
|     FspDriverObject = DriverObject; | ||||
|     ExInitializeResourceLite(&FspDeviceGlobalResource); | ||||
|     InitDoneGRes = TRUE; | ||||
|  | ||||
|     FspDriverMultiVersionInitialize(); | ||||
|  | ||||
|     Result = FspProcessBufferInitialize(); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|     InitDonePsBuf = TRUE; | ||||
|  | ||||
|     /* create the file system control device objects */ | ||||
|     RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL); | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlDiskDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlNetDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|     Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0, | ||||
|         FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE, | ||||
|         &FspFsmupDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|     Result = FspDeviceInitialize(FspFsctlDiskDeviceObject); | ||||
|     ASSERT(STATUS_SUCCESS == Result); | ||||
|     Result = FspDeviceInitialize(FspFsctlNetDeviceObject); | ||||
|     ASSERT(STATUS_SUCCESS == Result); | ||||
|     Result = FspDeviceInitialize(FspFsmupDeviceObject); | ||||
|     ASSERT(STATUS_SUCCESS == Result); | ||||
|  | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME); | ||||
|     Result = FsRtlRegisterUncProviderEx(&FspMupHandle, | ||||
|         &DeviceName, FspFsmupDeviceObject, 0); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|  | ||||
|     /* | ||||
|      * Register our "disk" device as a file system. We do not register our "net" device | ||||
|      * as a file system, but we register with the MUP instead at a later time. | ||||
|      * as a file system; we register with the MUP instead. | ||||
|      * | ||||
|      * Please note that the call below makes our driver unloadable. In fact the driver | ||||
|      * remains unloadable even if we issue an IoUnregisterFileSystem() call immediately | ||||
| @@ -180,6 +189,23 @@ NTSTATUS DriverEntry( | ||||
|      */ | ||||
|     IoRegisterFileSystem(FspFsctlDiskDeviceObject); | ||||
|  | ||||
|     Result = STATUS_SUCCESS; | ||||
|  | ||||
| exit: | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         if (0 != FspFsmupDeviceObject) | ||||
|             FspDeviceDelete(FspFsmupDeviceObject); | ||||
|         if (0 != FspFsctlNetDeviceObject) | ||||
|             FspDeviceDelete(FspFsctlNetDeviceObject); | ||||
|         if (0 != FspFsctlDiskDeviceObject) | ||||
|             FspDeviceDelete(FspFsctlDiskDeviceObject); | ||||
|         if (InitDonePsBuf) | ||||
|             FspProcessBufferFinalize(); | ||||
|         if (InitDoneGRes) | ||||
|             ExDeleteResourceLite(&FspDeviceGlobalResource); | ||||
|     } | ||||
|  | ||||
| #pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName") | ||||
|     FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"", | ||||
|         &DriverObject->DriverName, RegistryPath); | ||||
| @@ -213,6 +239,7 @@ VOID FspUnload( | ||||
|  | ||||
|     FspFsctlDiskDeviceObject = 0; | ||||
|     FspFsctlNetDeviceObject = 0; | ||||
|     FspFsmupDeviceObject = 0; | ||||
|     //FspDeviceDeleteAll(); | ||||
|  | ||||
|     ExDeleteResourceLite(&FspDeviceGlobalResource); | ||||
| @@ -229,6 +256,8 @@ VOID FspUnload( | ||||
| PDRIVER_OBJECT FspDriverObject; | ||||
| PDEVICE_OBJECT FspFsctlDiskDeviceObject; | ||||
| PDEVICE_OBJECT FspFsctlNetDeviceObject; | ||||
| PDEVICE_OBJECT FspFsmupDeviceObject; | ||||
| HANDLE FspMupHandle; | ||||
| FAST_IO_DISPATCH FspFastIoDispatch; | ||||
| CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks; | ||||
|  | ||||
|   | ||||
| @@ -180,6 +180,8 @@ VOID FspDebugLogIrp(const char *func, PIRP Irp, NTSTATUS Result); | ||||
| #define FSP_LEAVE_DRV(fmt, ...)         \ | ||||
|     FSP_LEAVE_(FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, NtStatusSym(Result))); return Result | ||||
| #define FSP_ENTER_MJ(...)               \ | ||||
|     if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\ | ||||
|         return FspMupHandleIrp(DeviceObject, Irp);\ | ||||
|     NTSTATUS Result = STATUS_SUCCESS;   \ | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\ | ||||
|     BOOLEAN fsp_device_deref = FALSE;   \ | ||||
| @@ -328,7 +330,6 @@ FSP_IOPREP_DISPATCH FspFsvolSetInformationPrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetSecurityComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetVolumeInformationComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete; | ||||
| FSP_IOPREP_DISPATCH FspFsvolWritePrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolWriteComplete; | ||||
|  | ||||
| @@ -1007,6 +1008,7 @@ typedef struct | ||||
| enum | ||||
| { | ||||
|     FspFsctlDeviceExtensionKind = '\0ltC',  /* file system control device (e.g. \Device\WinFsp.Disk) */ | ||||
|     FspFsmupDeviceExtensionKind = '\0puM',  /* our own MUP device (linked to \Device\WinFsp.Mup) */ | ||||
|     FspFsvrtDeviceExtensionKind = '\0trV',  /* virtual volume device (e.g. \Device\Volume{GUID}) */ | ||||
|     FspFsvolDeviceExtensionKind = '\0loV',  /* file system volume device (unnamed) */ | ||||
| }; | ||||
| @@ -1023,11 +1025,12 @@ typedef struct | ||||
|         InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1; | ||||
|     PDEVICE_OBJECT FsctlDeviceObject; | ||||
|     PDEVICE_OBJECT FsvrtDeviceObject; | ||||
|     HANDLE MupHandle; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject; | ||||
|     PVPB SwapVpb; | ||||
|     FSP_DELAYED_WORK_ITEM DeleteVolumeDelayedWorkItem; | ||||
|     FSP_FSCTL_VOLUME_PARAMS VolumeParams; | ||||
|     UNICODE_STRING VolumePrefix; | ||||
|     UNICODE_PREFIX_TABLE_ENTRY VolumePrefixEntry; | ||||
|     FSP_IOQ *Ioq; | ||||
|     FSP_META_CACHE *SecurityCache; | ||||
|     FSP_META_CACHE *DirInfoCache; | ||||
| @@ -1049,6 +1052,13 @@ typedef struct | ||||
|     LIST_ENTRY NotifyList; | ||||
|     FSP_STATISTICS *Statistics; | ||||
| } FSP_FSVOL_DEVICE_EXTENSION; | ||||
| typedef struct | ||||
| { | ||||
|     FSP_DEVICE_EXTENSION Base; | ||||
|     UINT32 InitDonePfxTab:1; | ||||
|     ERESOURCE PrefixTableResource; | ||||
|     UNICODE_PREFIX_TABLE PrefixTable; | ||||
| } FSP_FSMUP_DEVICE_EXTENSION; | ||||
| static inline | ||||
| FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
| @@ -1060,6 +1070,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject) | ||||
|     ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind); | ||||
|     return DeviceObject->DeviceExtension; | ||||
| } | ||||
| static inline | ||||
| FSP_FSMUP_DEVICE_EXTENSION *FspFsmupDeviceExtension(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     ASSERT(FspFsmupDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind); | ||||
|     return DeviceObject->DeviceExtension; | ||||
| } | ||||
| NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, | ||||
|     PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, ULONG DeviceCharacteristics, | ||||
|     PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid, | ||||
| @@ -1156,6 +1172,14 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* fsmup */ | ||||
| BOOLEAN FspMupRegister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject); | ||||
| VOID FspMupUnregister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject); | ||||
| NTSTATUS FspMupHandleIrp( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp); | ||||
|  | ||||
| /* volume management */ | ||||
| #define FspVolumeTransactEarlyTimeout   (1 * 10000ULL) | ||||
| NTSTATUS FspVolumeCreate( | ||||
| @@ -1164,8 +1188,6 @@ VOID FspVolumeDelete( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeMount( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeRedirQueryPathEx( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeGetName( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeGetNameList( | ||||
| @@ -1559,6 +1581,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache( | ||||
| extern PDRIVER_OBJECT FspDriverObject; | ||||
| extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; | ||||
| extern PDEVICE_OBJECT FspFsctlNetDeviceObject; | ||||
| extern PDEVICE_OBJECT FspFsmupDeviceObject; | ||||
| extern HANDLE FspMupHandle; | ||||
| extern FAST_IO_DISPATCH FspFastIoDispatch; | ||||
| extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks; | ||||
| extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; | ||||
|   | ||||
							
								
								
									
										266
									
								
								src/sys/mup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								src/sys/mup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,266 @@ | ||||
| /** | ||||
|  * @file sys/mup.c | ||||
|  * | ||||
|  * @copyright 2015-2018 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 file in | ||||
|  * accordance with the commercial license agreement provided with the | ||||
|  * software. | ||||
|  */ | ||||
|  | ||||
| #include <sys/driver.h> | ||||
|  | ||||
| BOOLEAN FspMupRegister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject); | ||||
| VOID FspMupUnregister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject); | ||||
| NTSTATUS FspMupHandleIrp( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp); | ||||
| static NTSTATUS FspMupRedirQueryPathEx( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspMupRegister) | ||||
| #pragma alloc_text(PAGE, FspMupUnregister) | ||||
| #pragma alloc_text(PAGE, FspMupHandleIrp) | ||||
| #pragma alloc_text(PAGE, FspMupRedirQueryPathEx) | ||||
| #endif | ||||
|  | ||||
| BOOLEAN FspMupRegister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     BOOLEAN Result; | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject); | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|  | ||||
|     ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE); | ||||
|     Result = RtlInsertUnicodePrefix(&FsmupDeviceExtension->PrefixTable, | ||||
|         &FsvolDeviceExtension->VolumePrefix, &FsvolDeviceExtension->VolumePrefixEntry); | ||||
|     if (Result) | ||||
|         FspDeviceReference(FsvolDeviceObject); | ||||
|     ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| VOID FspMupUnregister( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject); | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|  | ||||
|     ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE); | ||||
|     RtlRemoveUnicodePrefix(&FsmupDeviceExtension->PrefixTable, | ||||
|         &FsvolDeviceExtension->VolumePrefixEntry); | ||||
|     FspDeviceDereference(FsvolDeviceObject); | ||||
|     ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspMupHandleIrp( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject); | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = 0; | ||||
|     PUNICODE_PREFIX_TABLE_ENTRY Entry; | ||||
|     BOOLEAN DeviceDeref = FALSE; | ||||
|     NTSTATUS Result; | ||||
|  | ||||
|     FsRtlEnterFileSystem(); | ||||
|  | ||||
|     switch (IrpSp->MajorFunction) | ||||
|     { | ||||
|     case IRP_MJ_CREATE: | ||||
|         /* | ||||
|          * A CREATE request with an empty file name indicates that the fsmup device | ||||
|          * is being opened. Check for this case and handle it. | ||||
|          */ | ||||
|         if (0 == FileObject->FileName.Length) | ||||
|         { | ||||
|             Irp->IoStatus.Status = STATUS_SUCCESS; | ||||
|             Irp->IoStatus.Information = FILE_OPENED; | ||||
|             IoCompleteRequest(Irp, FSP_IO_INCREMENT); | ||||
|             Result = Irp->IoStatus.Status; | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Every other CREATE request must be forwarded to the appropriate fsvol device. | ||||
|          */ | ||||
|  | ||||
|         if (0 != FileObject->RelatedFileObject) | ||||
|             FileObject = FileObject->RelatedFileObject; | ||||
|  | ||||
|         ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE); | ||||
|         Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable, | ||||
|             &FileObject->FileName, 0); | ||||
|         if (0 != Entry) | ||||
|         { | ||||
|             FsvolDeviceObject = CONTAINING_RECORD(Entry, | ||||
|                 FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry)->FsvolDeviceObject; | ||||
|             FspDeviceReference(FsvolDeviceObject); | ||||
|             DeviceDeref = TRUE; | ||||
|         } | ||||
|         ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
|         break; | ||||
|  | ||||
|     case IRP_MJ_DEVICE_CONTROL: | ||||
|         /* | ||||
|          * A DEVICE_CONTROL request with IOCTL_REDIR_QUERY_PATH_EX must be handled | ||||
|          * by the fsmup device. Check for this case and handle it. | ||||
|          */ | ||||
|         if (IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode) | ||||
|         { | ||||
|             Irp->IoStatus.Status = FspMupRedirQueryPathEx(FsmupDeviceObject, Irp, IrpSp); | ||||
|             IoCompleteRequest(Irp, FSP_IO_INCREMENT); | ||||
|             Result = Irp->IoStatus.Status; | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Every other DEVICE_CONTROL request must be forwarded to the appropriate fsvol device. | ||||
|          */ | ||||
|  | ||||
|         /* fall through! */ | ||||
|  | ||||
|     default: | ||||
|         /* | ||||
|          * Every other request must be forwarded to the appropriate fsvol device. If there is no | ||||
|          * fsvol device, then we must return the appropriate status code (see below). | ||||
|          * | ||||
|          * Please note that since we allow the fsmup device to be opened, we must also handle | ||||
|          * CLEANUP and CLOSE requests for it. | ||||
|          */ | ||||
|  | ||||
|         if (0 != FileObject) | ||||
|         { | ||||
|             if (FspFileNodeIsValid(FileObject->FsContext)) | ||||
|                 FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject; | ||||
|             else if (0 != FileObject->FsContext2 && | ||||
|                 3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type && | ||||
|                 0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension && | ||||
|                 FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind) | ||||
|                 FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     if (0 == FsvolDeviceObject) | ||||
|     { | ||||
|         /* | ||||
|          * We were not able to find an fsvol device to forward this IRP to. We will complete | ||||
|          * the IRP with an appropriate status code. | ||||
|          */ | ||||
|  | ||||
|         switch (IrpSp->MajorFunction) | ||||
|         { | ||||
|         case IRP_MJ_CLEANUP: | ||||
|         case IRP_MJ_CLOSE: | ||||
|             /* | ||||
|              * CLEANUP and CLOSE requests ignore their status code (except for STATUS_PENDING). | ||||
|              * So return STATUS_SUCCESS. This works regardless of whether this is a legitimate | ||||
|              * fsmup request or an erroneous CLOSE request that we should not have seen. | ||||
|              */ | ||||
|             Irp->IoStatus.Status = STATUS_SUCCESS; | ||||
|             break; | ||||
|         case IRP_MJ_QUERY_INFORMATION: | ||||
|         case IRP_MJ_SET_INFORMATION: | ||||
|             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; | ||||
|             break; | ||||
|         default: | ||||
|             Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         Irp->IoStatus.Information = 0; | ||||
|         IoCompleteRequest(Irp, FSP_IO_INCREMENT); | ||||
|         Result = Irp->IoStatus.Status; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     ASSERT(FspFsvolDeviceExtensionKind == FspDeviceExtension(FsvolDeviceObject)->Kind); | ||||
|  | ||||
|     /* | ||||
|      * Forward the IRP to the appropriate fsvol device. The fsvol device will take care | ||||
|      * to complete the IRP, etc. | ||||
|      */ | ||||
|     IoSkipCurrentIrpStackLocation(Irp); | ||||
|     Result = IoCallDriver(FsvolDeviceObject, Irp); | ||||
|  | ||||
|     if (DeviceDeref) | ||||
|         FspDeviceDereference(FsvolDeviceObject); | ||||
|  | ||||
| exit: | ||||
|     FsRtlExitFileSystem(); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspMupRedirQueryPathEx( | ||||
|     PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction); | ||||
|     ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode); | ||||
|  | ||||
|     Irp->IoStatus.Information = 0; | ||||
|  | ||||
|     if (KernelMode != Irp->RequestorMode) | ||||
|         return STATUS_INVALID_DEVICE_REQUEST; | ||||
|  | ||||
|     /* check parameters */ | ||||
|     ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; | ||||
|     ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; | ||||
|     QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; | ||||
|     QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer; | ||||
|     if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength || | ||||
|         0 == QueryPathRequest || 0 == QueryPathResponse) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength) | ||||
|         return STATUS_BUFFER_TOO_SMALL; | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(FsmupDeviceObject); | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; | ||||
|     PUNICODE_PREFIX_TABLE_ENTRY Entry; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = 0; | ||||
|  | ||||
|     Result = STATUS_BAD_NETWORK_PATH; | ||||
|     ExAcquireResourceExclusiveLite(&FsmupDeviceExtension->PrefixTableResource, TRUE); | ||||
|     Entry = RtlFindUnicodePrefix(&FsmupDeviceExtension->PrefixTable, | ||||
|         &QueryPathRequest->PathName, 0); | ||||
|     if (0 != Entry) | ||||
|     { | ||||
|         FsvolDeviceExtension = CONTAINING_RECORD(Entry, FSP_FSVOL_DEVICE_EXTENSION, VolumePrefixEntry); | ||||
|         FsvolDeviceObject = FsvolDeviceExtension->FsvolDeviceObject; | ||||
|         if (!FspIoqStopped(FsvolDeviceExtension->Ioq)) | ||||
|         { | ||||
|             if (0 < FsvolDeviceExtension->VolumePrefix.Length && | ||||
|                 FspFsvolDeviceVolumePrefixInString(FsvolDeviceObject, &QueryPathRequest->PathName) && | ||||
|                 (QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length || | ||||
|                     '\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)])) | ||||
|             { | ||||
|                 QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length; | ||||
|                 Result = STATUS_SUCCESS; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
| @@ -17,45 +17,18 @@ | ||||
|  | ||||
| #include <sys/driver.h> | ||||
|  | ||||
| static NTSTATUS FspFsvolShutdown( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_DRIVER_DISPATCH FspShutdown; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolShutdownComplete; | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspFsvolShutdown) | ||||
| #pragma alloc_text(PAGE, FspFsvolShutdownComplete) | ||||
| #pragma alloc_text(PAGE, FspShutdown) | ||||
| #endif | ||||
|  | ||||
| static NTSTATUS FspFsvolShutdown( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolShutdownComplete( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     FSP_ENTER_IOC(PAGED_CODE()); | ||||
|  | ||||
|     FSP_LEAVE_IOC("%s", ""); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspShutdown( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||||
| { | ||||
|     FSP_ENTER_MJ(PAGED_CODE()); | ||||
|  | ||||
|     switch (FspDeviceExtension(DeviceObject)->Kind) | ||||
|     { | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         FSP_RETURN(Result = FspFsvolShutdown(DeviceObject, Irp, IrpSp)); | ||||
|     default: | ||||
|         FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST); | ||||
|     } | ||||
|     FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST); | ||||
|  | ||||
|     FSP_LEAVE_MJ("%s", ""); | ||||
| } | ||||
|   | ||||
							
								
								
									
										102
									
								
								src/sys/volume.c
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								src/sys/volume.c
									
									
									
									
									
								
							| @@ -21,7 +21,6 @@ NTSTATUS FspVolumeCreate( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static NTSTATUS FspVolumeCreateNoLock( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static WORKER_THREAD_ROUTINE FspVolumeCreateRegisterMup; | ||||
| VOID FspVolumeDelete( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static VOID FspVolumeDeleteNoLock( | ||||
| @@ -31,8 +30,6 @@ NTSTATUS FspVolumeMount( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static NTSTATUS FspVolumeMountNoLock( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeRedirQueryPathEx( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeGetName( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspVolumeGetNameList( | ||||
| @@ -49,13 +46,11 @@ NTSTATUS FspVolumeWork( | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspVolumeCreate) | ||||
| #pragma alloc_text(PAGE, FspVolumeCreateNoLock) | ||||
| #pragma alloc_text(PAGE, FspVolumeCreateRegisterMup) | ||||
| // ! #pragma alloc_text(PAGE, FspVolumeDelete) | ||||
| // ! #pragma alloc_text(PAGE, FspVolumeDeleteNoLock) | ||||
| // ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed) | ||||
| // ! #pragma alloc_text(PAGE, FspVolumeMount) | ||||
| // ! #pragma alloc_text(PAGE, FspVolumeMountNoLock) | ||||
| #pragma alloc_text(PAGE, FspVolumeRedirQueryPathEx) | ||||
| #pragma alloc_text(PAGE, FspVolumeGetName) | ||||
| #pragma alloc_text(PAGE, FspVolumeGetNameList) | ||||
| #pragma alloc_text(PAGE, FspVolumeGetNameListNoLock) | ||||
| @@ -67,13 +62,6 @@ NTSTATUS FspVolumeWork( | ||||
| #define PREFIXW                         L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX | ||||
| #define PREFIXW_SIZE                    (sizeof PREFIXW - sizeof(WCHAR)) | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|     PDEVICE_OBJECT FsvolDeviceObject; | ||||
|     NTSTATUS Result; | ||||
|     FSP_SYNCHRONOUS_WORK_ITEM SynchronousWorkItem; | ||||
| } FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM; | ||||
|  | ||||
| NTSTATUS FspVolumeCreate( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
| @@ -106,11 +94,11 @@ static NTSTATUS FspVolumeCreateNoLock( | ||||
|     GUID Guid; | ||||
|     UNICODE_STRING DeviceSddl; | ||||
|     UNICODE_STRING VolumeName; | ||||
|     UNICODE_STRING FsmupDeviceName; | ||||
|     WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)]; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject; | ||||
|     PDEVICE_OBJECT FsvrtDeviceObject; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; | ||||
|     FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM RegisterMupWorkItem; | ||||
|  | ||||
|     /* check parameters */ | ||||
|     if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS) * sizeof(WCHAR) > FileObject->FileName.Length) | ||||
| @@ -225,6 +213,7 @@ static NTSTATUS FspVolumeCreateNoLock( | ||||
|     FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|     FsvolDeviceExtension->FsctlDeviceObject = FsctlDeviceObject; | ||||
|     FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject; | ||||
|     FsvolDeviceExtension->FsvolDeviceObject = FsvolDeviceObject; | ||||
|     FsvolDeviceExtension->VolumeParams = VolumeParams; | ||||
|     if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType) | ||||
|         RtlInitUnicodeString(&FsvolDeviceExtension->VolumePrefix, | ||||
| @@ -245,24 +234,20 @@ static NTSTATUS FspVolumeCreateNoLock( | ||||
|         FspDeviceDereference(FsvolDeviceObject); | ||||
|     } | ||||
|  | ||||
|     /* do we need to register with MUP? */ | ||||
|     /* do we need to register with fsmup? */ | ||||
|     if (0 == FsvrtDeviceObject) | ||||
|     { | ||||
|         /* | ||||
|          * Turns out we cannot call FsRtlRegisterUncProviderEx when the PreviousMode | ||||
|          * is UserMode! So we need to somehow switch to KernelMode prior to issuing | ||||
|          * the FsRtlRegisterUncProviderEx call. There seems to be no straightforward | ||||
|          * way to switch the PreviousMode (no ExSetPreviousMode). So we do it indirectly | ||||
|          * by executing a synchronous work item (FspExecuteSynchronousWorkItem). | ||||
|          */ | ||||
|         RtlZeroMemory(&RegisterMupWorkItem, sizeof RegisterMupWorkItem); | ||||
|         RegisterMupWorkItem.FsvolDeviceObject = FsvolDeviceObject; | ||||
|         FspInitializeSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem, | ||||
|             FspVolumeCreateRegisterMup, &RegisterMupWorkItem); | ||||
|         FspExecuteSynchronousWorkItem(&RegisterMupWorkItem.SynchronousWorkItem); | ||||
|         Result = RegisterMupWorkItem.Result; | ||||
|         if (!FspMupRegister(FspFsmupDeviceObject, FsvolDeviceObject)) | ||||
|         { | ||||
|             FspDeviceDereference(FsvolDeviceObject); | ||||
|             return STATUS_OBJECT_NAME_COLLISION; | ||||
|         } | ||||
|  | ||||
|         RtlInitUnicodeString(&FsmupDeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME); | ||||
|         Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|         { | ||||
|             FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject); | ||||
|             FspDeviceDereference(FsvolDeviceObject); | ||||
|             return Result; | ||||
|         } | ||||
| @@ -275,18 +260,6 @@ static NTSTATUS FspVolumeCreateNoLock( | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static VOID FspVolumeCreateRegisterMup(PVOID Context) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_CREATE_VOLUME_REGISTER_MUP_WORK_ITEM *RegisterMupWorkItem = Context; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = RegisterMupWorkItem->FsvolDeviceObject; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|  | ||||
|     RegisterMupWorkItem->Result = FsRtlRegisterUncProviderEx(&FsvolDeviceExtension->MupHandle, | ||||
|         &FsvolDeviceExtension->VolumeName, FsvolDeviceObject, 0); | ||||
| } | ||||
|  | ||||
| VOID FspVolumeDelete( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
| @@ -333,7 +306,7 @@ static VOID FspVolumeDeleteNoLock( | ||||
|     /* stop the I/O queue */ | ||||
|     FspIoqStop(FsvolDeviceExtension->Ioq); | ||||
|  | ||||
|     /* do we have a virtual disk device or a MUP handle? */ | ||||
|     /* do we have a virtual disk device or are we registered with fsmup? */ | ||||
|     if (0 != FsvolDeviceExtension->FsvrtDeviceObject) | ||||
|     { | ||||
|         PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; | ||||
| @@ -391,10 +364,10 @@ static VOID FspVolumeDeleteNoLock( | ||||
|             FspQueueDelayedWorkItem(&FsvolDeviceExtension->DeleteVolumeDelayedWorkItem, Delay); | ||||
|         } | ||||
|     } | ||||
|     else if (0 != FsvolDeviceExtension->MupHandle) | ||||
|     else | ||||
|     { | ||||
|         FsRtlDeregisterUncProvider(FsvolDeviceExtension->MupHandle); | ||||
|         FsvolDeviceExtension->MupHandle = 0; | ||||
|         IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName); | ||||
|         FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject); | ||||
|     } | ||||
|  | ||||
|     /* release the volume device object */ | ||||
| @@ -515,49 +488,6 @@ static NTSTATUS FspVolumeMountNoLock( | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspVolumeRedirQueryPathEx( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     ASSERT(IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction); | ||||
|     ASSERT(IOCTL_REDIR_QUERY_PATH_EX == IrpSp->Parameters.DeviceIoControl.IoControlCode); | ||||
|  | ||||
|     if (KernelMode != Irp->RequestorMode) | ||||
|         return STATUS_INVALID_DEVICE_REQUEST; | ||||
|  | ||||
|     /* check parameters */ | ||||
|     ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; | ||||
|     ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; | ||||
|     QUERY_PATH_REQUEST_EX *QueryPathRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; | ||||
|     QUERY_PATH_RESPONSE *QueryPathResponse = Irp->UserBuffer; | ||||
|     if (sizeof(QUERY_PATH_REQUEST_EX) > InputBufferLength || | ||||
|         0 == QueryPathRequest || 0 == QueryPathResponse) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (sizeof(QUERY_PATH_RESPONSE) > OutputBufferLength) | ||||
|         return STATUS_BUFFER_TOO_SMALL; | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|  | ||||
|     Result = STATUS_BAD_NETWORK_PATH; | ||||
|     if (!FspIoqStopped(FsvolDeviceExtension->Ioq)) | ||||
|     { | ||||
|         if (0 < FsvolDeviceExtension->VolumePrefix.Length && | ||||
|             FspFsvolDeviceVolumePrefixInString(FsvolDeviceObject, &QueryPathRequest->PathName) && | ||||
|             (QueryPathRequest->PathName.Length == FsvolDeviceExtension->VolumePrefix.Length || | ||||
|                 '\\' == QueryPathRequest->PathName.Buffer[FsvolDeviceExtension->VolumePrefix.Length / sizeof(WCHAR)])) | ||||
|         { | ||||
|             QueryPathResponse->LengthAccepted = FsvolDeviceExtension->VolumePrefix.Length; | ||||
|  | ||||
|             Irp->IoStatus.Information = 0; | ||||
|             Result = STATUS_SUCCESS; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspVolumeGetName( | ||||
|     PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user