mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: mountdev: mount manager support
This commit is contained in:
parent
89ec3e6733
commit
a47f853beb
@ -176,6 +176,7 @@
|
||||
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||
<ClCompile Include="..\..\src\sys\meta.c" />
|
||||
<ClCompile Include="..\..\src\sys\mountdev.c" />
|
||||
<ClCompile Include="..\..\src\sys\mup.c" />
|
||||
<ClCompile Include="..\..\src\sys\name.c" />
|
||||
<ClCompile Include="..\..\src\sys\psbuffer.c" />
|
||||
|
@ -116,6 +116,9 @@
|
||||
<ClCompile Include="..\..\src\ku\uuid5.c">
|
||||
<Filter>Source\ku</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\mountdev.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -43,10 +43,15 @@ enum
|
||||
};
|
||||
|
||||
static NTSTATUS FspFsvrtDeviceControl(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
if (FspMountdevDeviceControl(FsvrtDeviceObject, Irp, IrpSp, &Result))
|
||||
return Result;
|
||||
|
||||
/*
|
||||
* Fix GitHub issue #177. All credit for the investigation of this issue
|
||||
* and the suggested steps to reproduce and work around the problem goes
|
||||
@ -72,6 +77,19 @@ static NTSTATUS FspFsvolDeviceControl(
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (FspMountdevDeviceControl(FsvolDeviceExtension->FsvrtDeviceObject, Irp, IrpSp, &Result))
|
||||
return Result;
|
||||
|
||||
/*
|
||||
* Possibly forward the IOCTL request to the user mode file system. The rules are:
|
||||
*
|
||||
* - File system must support DeviceControl.
|
||||
* - Only IOCTL with custom devices (see DEVICE_TYPE_FROM_CTL_CODE) and
|
||||
* METHOD_BUFFERED will be forwarded.
|
||||
*/
|
||||
|
||||
|
||||
/* do we support DeviceControl? */
|
||||
if (!FsvolDeviceExtension->VolumeParams.DeviceControl)
|
||||
@ -90,7 +108,6 @@ static NTSTATUS FspFsvolDeviceControl(
|
||||
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
@ -67,6 +67,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 FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
@ -100,6 +102,8 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||
@ -126,10 +130,12 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSVRT_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_FSMUP_DEVICE_EXTENSION);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
DeviceExtensionSize = sizeof(FSP_DEVICE_EXTENSION);
|
||||
break;
|
||||
@ -184,10 +190,12 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
Result = FspFsvolDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
Result = FspFsvrtDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
Result = FspFsmupDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
Result = STATUS_SUCCESS;
|
||||
break;
|
||||
@ -213,10 +221,12 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
case FspFsvolDeviceExtensionKind:
|
||||
FspFsvolDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
FspFsvrtDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
FspFsmupDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
break;
|
||||
default:
|
||||
@ -940,6 +950,20 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspMountdevFini(DeviceObject);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#define POOL_NX_OPTIN 1
|
||||
#include <ntifs.h>
|
||||
#include <mountdev.h>
|
||||
#include <ntstrsafe.h>
|
||||
#include <wdmsec.h>
|
||||
#include <winfsp/fsctl.h>
|
||||
@ -1101,6 +1102,14 @@ typedef struct
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 FsextData[];
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
LONG IsMountdev;
|
||||
GUID UniqueId;
|
||||
UNICODE_STRING VolumeName;
|
||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT32 InitDonePfxTab:1;
|
||||
@ -1120,6 +1129,12 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
return DeviceObject->DeviceExtension;
|
||||
}
|
||||
static inline
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FspFsvrtDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ASSERT(FspFsvrtDeviceExtensionKind == ((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);
|
||||
@ -1224,6 +1239,19 @@ BOOLEAN FspQueryDirectoryIrpShouldUseProcessBuffer(PIRP Irp, SIZE_T BufferSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mountdev */
|
||||
NTSTATUS FspMountdevQueryDeviceName(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspMountdevQueryUniqueId(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
BOOLEAN FspMountdevDeviceControl(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||
PNTSTATUS PResult);
|
||||
NTSTATUS FspMountdevMake(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMountdevFini(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
|
186
src/sys/mountdev.c
Normal file
186
src/sys/mountdev.c
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @file sys/mountdev.c
|
||||
*
|
||||
* @copyright 2015-2019 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 <sys/driver.h>
|
||||
|
||||
NTSTATUS FspMountdevQueryDeviceName(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspMountdevQueryUniqueId(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
BOOLEAN FspMountdevDeviceControl(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||
PNTSTATUS PResult);
|
||||
NTSTATUS FspMountdevMake(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
VOID FspMountdevFini(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspMountdevQueryDeviceName)
|
||||
#pragma alloc_text(PAGE, FspMountdevQueryUniqueId)
|
||||
#pragma alloc_text(PAGE, FspMountdevDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspMountdevMake)
|
||||
#pragma alloc_text(PAGE, FspMountdevFini)
|
||||
#endif
|
||||
|
||||
NTSTATUS FspMountdevQueryDeviceName(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
PMOUNTDEV_NAME OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (sizeof(MOUNTDEV_NAME) > OutputBufferLength)
|
||||
/* NOTE: Windows storage samples also set: Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME) */
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
RtlZeroMemory(OutputBuffer, sizeof(MOUNTDEV_NAME));
|
||||
OutputBuffer->NameLength = FsvrtDeviceExtension->VolumeName.Length;
|
||||
|
||||
Irp->IoStatus.Information =
|
||||
FIELD_OFFSET(MOUNTDEV_NAME, Name) + OutputBuffer->NameLength;
|
||||
if (Irp->IoStatus.Information > OutputBufferLength)
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
RtlCopyMemory(OutputBuffer->Name,
|
||||
FsvrtDeviceExtension->VolumeName.Buffer, OutputBuffer->NameLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountdevQueryUniqueId(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||
PMOUNTDEV_UNIQUE_ID OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
if (sizeof(MOUNTDEV_UNIQUE_ID) > OutputBufferLength)
|
||||
/* NOTE: Windows storage samples also set: Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID) */
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
RtlZeroMemory(OutputBuffer, sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
OutputBuffer->UniqueIdLength = sizeof FsvrtDeviceExtension->UniqueId;
|
||||
|
||||
Irp->IoStatus.Information =
|
||||
FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + OutputBuffer->UniqueIdLength;
|
||||
if (Irp->IoStatus.Information > OutputBufferLength)
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
RtlCopyMemory(OutputBuffer->UniqueId,
|
||||
&FsvrtDeviceExtension->UniqueId, OutputBuffer->UniqueIdLength);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN FspMountdevDeviceControl(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
|
||||
PNTSTATUS PResult)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (0 != FsvrtDeviceObject)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
if (0 != InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
|
||||
{
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
||||
*PResult = FspMountdevQueryDeviceName(FsvrtDeviceObject, Irp, IrpSp);
|
||||
return TRUE;
|
||||
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
||||
*PResult = FspMountdevQueryUniqueId(FsvrtDeviceObject, Irp, IrpSp);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountdevMake(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
|
||||
{
|
||||
/*
|
||||
* This function converts the fsvrt device into a mountdev device that
|
||||
* responds to MountManager IOCTL's. This allows the fsvrt device to
|
||||
* be mounted using the MountManager.
|
||||
*
|
||||
* This function requires protection against concurrency. In general this
|
||||
* is achieved by acquiring the GlobalDeviceLock.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
UNICODE_STRING String;
|
||||
WCHAR StringBuf[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR) + 18];
|
||||
GUID Guid;
|
||||
NTSTATUS Result;
|
||||
|
||||
ASSERT(FsvolDeviceExtension->FsvrtDeviceObject == FsvrtDeviceObject);
|
||||
|
||||
if (0 != InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* make UUID v5 from the fsvrt device GUID and a unique string derived from the VolumeParams */
|
||||
RtlInitEmptyUnicodeString(&String, StringBuf, sizeof StringBuf);
|
||||
Result = RtlUnicodeStringPrintf(&String,
|
||||
L"%s:%08lx:%08lx",
|
||||
FsvolDeviceExtension->VolumeParams.FileSystemName,
|
||||
FsvolDeviceExtension->VolumeParams.VolumeSerialNumber,
|
||||
FsvolDeviceExtension->VolumeParams.VolumeCreationTime);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
Result = FspUuid5Make(&FspFsvrtDeviceClassGuid, String.Buffer, String.Length, &Guid);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* initialize the fsvrt device extension */
|
||||
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||
|
||||
/* mark the fsvrt device as initialized */
|
||||
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspMountdevFini(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject)
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user