mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
sys: mountdev: mount manager support
This commit is contained in:
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)
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user