sys,dll: FspFileSystemSetMountPoint: mount manager support

This commit is contained in:
Bill Zissimopoulos 2019-09-05 19:58:14 -07:00
parent a47f853beb
commit 565caebe4c
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
9 changed files with 280 additions and 11 deletions

View File

@ -54,6 +54,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
#define FSP_FSCTL_DECLSPEC_ALIGN __declspec(align(FSP_FSCTL_DEFAULT_ALIGNMENT))
/* fsctl device codes */
#define FSP_FSCTL_MOUNTDEV \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_NAME \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_LIST \
@ -598,6 +600,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
PHANDLE PVolumeHandle);
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
BOOLEAN Persistent);
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,

View File

@ -93,7 +93,9 @@ FSP_API NTSTATUS FspFileSystemPreflight(PWSTR DevicePath,
Result = STATUS_SUCCESS;
else
{
if (FspPathIsDrive(MountPoint))
if (FspPathIsMountmgrMountPoint(MountPoint))
Result = STATUS_SUCCESS; /* cannot check with the mount manager, assume success */
else if (FspPathIsDrive(MountPoint))
Result = QueryDosDeviceW(MountPoint, TargetPath, MAX_PATH) ?
STATUS_OBJECT_NAME_COLLISION : STATUS_SUCCESS;
else
@ -220,6 +222,48 @@ static NTSTATUS FspFileSystemLauncherDefineDosDevice(
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
}
static NTSTATUS FspFileSystemMountmgrControl(ULONG IoControlCode,
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
{
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
DWORD Bytes = 0;
NTSTATUS Result;
if (0 == POutputBufferLength)
POutputBufferLength = &Bytes;
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
if (INVALID_HANDLE_VALUE == MgrHandle)
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
if (!DeviceIoControl(MgrHandle,
IoControlCode,
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
&Bytes, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
*POutputBufferLength = Bytes;
Result = STATUS_SUCCESS;
exit:
if (INVALID_HANDLE_VALUE != MgrHandle)
CloseHandle(MgrHandle);
return Result;
}
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
PHANDLE PMountHandle)
{
@ -395,6 +439,68 @@ exit:
return Result;
}
static NTSTATUS FspFileSystemSetMountPoint_Mountmgr(PWSTR MountPoint, PWSTR VolumeName,
HANDLE VolumeHandle)
{
/* only support drives for now! (format: \\.\X:) */
if (L'\0' != MountPoint[6])
return STATUS_INVALID_PARAMETER;
/* mountmgr.h */
typedef struct
{
USHORT SymbolicLinkNameOffset;
USHORT SymbolicLinkNameLength;
USHORT DeviceNameOffset;
USHORT DeviceNameLength;
} MOUNTMGR_CREATE_POINT_INPUT;
MOUNTMGR_CREATE_POINT_INPUT *Input = 0;
ULONG VolumeNameSize, InputSize;
NTSTATUS Result;
/* transform our volume into one that can be used by the MountManager */
Result = FspFsctlMakeMountdev(VolumeHandle, FALSE);
if (!NT_SUCCESS(Result))
goto exit;
VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeNameSize;
Input = MemAlloc(InputSize);
if (0 == Input)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
memset(Input, 0, sizeof *Input);
Input->SymbolicLinkNameOffset = sizeof *Input;
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
Input->DeviceNameOffset = Input->SymbolicLinkNameOffset + Input->SymbolicLinkNameLength;
Input->DeviceNameLength = (USHORT)VolumeNameSize;
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
/* convert to uppercase */
memcpy((PUINT8)Input + Input->DeviceNameOffset,
VolumeName, Input->DeviceNameLength);
Result = FspFileSystemMountmgrControl(
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
/* IOCTL_MOUNTMGR_CREATE_POINT */
Input, InputSize, 0, 0);
if (!NT_SUCCESS(Result))
goto exit;
Result = STATUS_SUCCESS;
exit:
MemFree(Input);
return Result;
}
FSP_API NTSTATUS FspFileSystemSetMountPoint(FSP_FILE_SYSTEM *FileSystem, PWSTR MountPoint)
{
return FspFileSystemSetMountPointEx(FileSystem, MountPoint, 0);
@ -450,7 +556,10 @@ FSP_API NTSTATUS FspFileSystemSetMountPointEx(FSP_FILE_SYSTEM *FileSystem, PWSTR
memcpy(P, MountPoint, L);
MountPoint = P;
if (FspPathIsDrive(MountPoint))
if (FspPathIsMountmgrMountPoint(MountPoint))
Result = FspFileSystemSetMountPoint_Mountmgr(MountPoint, FileSystem->VolumeName,
FileSystem->VolumeHandle);
else if (FspPathIsDrive(MountPoint))
Result = FspFileSystemSetMountPoint_Drive(MountPoint, FileSystem->VolumeName,
&MountHandle);
else
@ -495,12 +604,80 @@ static VOID FspFileSystemRemoveMountPoint_Directory(HANDLE MountHandle)
CloseHandle(MountHandle);
}
static VOID FspFileSystemRemoveMountPoint_Mountmgr(PWSTR MountPoint)
{
/* mountmgr.h */
typedef struct
{
ULONG SymbolicLinkNameOffset;
USHORT SymbolicLinkNameLength;
USHORT Reserved1;
ULONG UniqueIdOffset;
USHORT UniqueIdLength;
USHORT Reserved2;
ULONG DeviceNameOffset;
USHORT DeviceNameLength;
USHORT Reserved3;
} MOUNTMGR_MOUNT_POINT;
typedef struct
{
ULONG Size;
ULONG NumberOfMountPoints;
MOUNTMGR_MOUNT_POINT MountPoints[1];
} MOUNTMGR_MOUNT_POINTS;
MOUNTMGR_MOUNT_POINT *Input = 0;
MOUNTMGR_MOUNT_POINTS *Output = 0;
ULONG InputSize, OutputSize;
NTSTATUS Result;
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
OutputSize = 4096;
Input = MemAlloc(InputSize);
if (0 == Input)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
Output = MemAlloc(OutputSize);
if (0 == Output)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
memset(Input, 0, sizeof *Input);
Input->SymbolicLinkNameOffset = sizeof *Input;
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
/* convert to uppercase */
Result = FspFileSystemMountmgrControl(
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
/* IOCTL_MOUNTMGR_DELETE_POINTS */
Input, InputSize, Output, &OutputSize);
if (!NT_SUCCESS(Result))
goto exit;
Result = STATUS_SUCCESS;
exit:
MemFree(Output);
MemFree(Input);
}
FSP_API VOID FspFileSystemRemoveMountPoint(FSP_FILE_SYSTEM *FileSystem)
{
if (0 == FileSystem->MountPoint)
return;
if (FspPathIsDrive(FileSystem->MountPoint))
if (FspPathIsMountmgrMountPoint(FileSystem->MountPoint))
FspFileSystemRemoveMountPoint_Mountmgr(FileSystem->MountPoint);
else if (FspPathIsDrive(FileSystem->MountPoint))
FspFileSystemRemoveMountPoint_Drive(FileSystem->MountPoint, FileSystem->VolumeName,
FileSystem->MountHandle);
else

View File

@ -107,6 +107,20 @@ exit:
return Result;
}
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
BOOLEAN Persistent)
{
DWORD Bytes;
if (!DeviceIoControl(VolumeHandle,
FSP_FSCTL_MOUNTDEV,
&Persistent, sizeof Persistent, 0, 0,
&Bytes, 0))
return FspNtStatusFromWin32(GetLastError());
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,

View File

@ -91,6 +91,21 @@ static inline BOOLEAN FspPathIsDrive(PWSTR FileName)
) &&
L':' == FileName[1] && L'\0' == FileName[2];
}
static inline BOOLEAN FspPathIsMountmgrMountPoint(PWSTR FileName)
{
return
(
L'\\' == FileName[0] &&
L'\\' == FileName[1] &&
(L'?' == FileName[2] || L'.' == FileName[2]) &&
L'\\' == FileName[3]
) &&
(
(L'A' <= FileName[4] && FileName[4] <= L'Z') ||
(L'a' <= FileName[4] && FileName[4] <= L'z')
) &&
L':' == FileName[5];
}
#define FSP_NEXT_EA(Ea, EaEnd) \
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))

View File

@ -1105,6 +1105,7 @@ typedef struct
{
FSP_DEVICE_EXTENSION Base;
LONG IsMountdev;
BOOLEAN Persistent;
GUID UniqueId;
UNICODE_STRING VolumeName;
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
@ -1248,7 +1249,8 @@ BOOLEAN FspMountdevDeviceControl(
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
PNTSTATUS PResult);
NTSTATUS FspMountdevMake(
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
BOOLEAN Persistent);
VOID FspMountdevFini(
PDEVICE_OBJECT FsvrtDeviceObject);
@ -1267,6 +1269,8 @@ VOID FspVolumeDelete(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(

View File

@ -77,6 +77,10 @@ static NTSTATUS FspFsctlFileSystemControl(
case IRP_MN_USER_FS_REQUEST:
switch (IrpSp->Parameters.FileSystemControl.FsControlCode)
{
case FSP_FSCTL_MOUNTDEV:
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
break;
case FSP_FSCTL_VOLUME_NAME:
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);

View File

@ -29,7 +29,8 @@ BOOLEAN FspMountdevDeviceControl(
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
PNTSTATUS PResult);
NTSTATUS FspMountdevMake(
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
BOOLEAN Persistent);
VOID FspMountdevFini(
PDEVICE_OBJECT FsvrtDeviceObject);
@ -128,7 +129,8 @@ BOOLEAN FspMountdevDeviceControl(
}
NTSTATUS FspMountdevMake(
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject)
PDEVICE_OBJECT FsvrtDeviceObject, PDEVICE_OBJECT FsvolDeviceObject,
BOOLEAN Persistent)
{
/*
* This function converts the fsvrt device into a mountdev device that
@ -151,7 +153,10 @@ NTSTATUS FspMountdevMake(
ASSERT(FsvolDeviceExtension->FsvrtDeviceObject == FsvrtDeviceObject);
if (0 != InterlockedCompareExchange(&FsvrtDeviceExtension->IsMountdev, 0, 0))
return STATUS_SUCCESS;
return Persistent == FsvrtDeviceExtension->Persistent ?
STATUS_SUCCESS : STATUS_ACCESS_DENIED;
FsvrtDeviceExtension->Persistent = Persistent;
/* make UUID v5 from the fsvrt device GUID and a unique string derived from the VolumeParams */
RtlInitEmptyUnicodeString(&String, StringBuf, sizeof StringBuf);

View File

@ -34,6 +34,10 @@ NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspVolumeMountNoLock(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdevNoLock(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(
@ -57,6 +61,8 @@ NTSTATUS FspVolumeWork(
// ! #pragma alloc_text(PAGE, FspVolumeDeleteDelayed)
// ! #pragma alloc_text(PAGE, FspVolumeMount)
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
#pragma alloc_text(PAGE, FspVolumeMakeMountdevNoLock)
#pragma alloc_text(PAGE, FspVolumeGetName)
#pragma alloc_text(PAGE, FspVolumeGetNameList)
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
@ -543,6 +549,41 @@ static NTSTATUS FspVolumeMountNoLock(
return STATUS_SUCCESS;
}
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FspDeviceGlobalLock();
Result = FspVolumeMakeMountdevNoLock(FsctlDeviceObject, Irp, IrpSp);
FspDeviceGlobalUnlock();
return Result;
}
NTSTATUS FspVolumeMakeMountdevNoLock(
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_MOUNTDEV == IrpSp->Parameters.FileSystemControl.FsControlCode);
ASSERT(0 != IrpSp->FileObject->FsContext2);
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
PVOID InputBuffer = Irp->AssociatedIrp.SystemBuffer;
BOOLEAN Persistent = 0 < InputBufferLength ? !!*(PBOOLEAN)InputBuffer : FALSE;
if (0 == FsvrtDeviceObject)
return STATUS_INVALID_PARAMETER;
return FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
}
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{

View File

@ -96,7 +96,7 @@ static void volpath_test(void)
volpath_dotest(MemfsNet, L"\\\\memfs\\share");
}
static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix)
static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
{
void *memfs = memfs_start(Flags);
@ -106,7 +106,7 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix)
WCHAR FilePath[MAX_PATH];
WCHAR VolumePathName[MAX_PATH];
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), 0);
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), MountPoint);
ASSERT(NT_SUCCESS(Result));
Prefix = FspFileSystemMountPoint(MemfsFileSystem(memfs));
@ -168,9 +168,14 @@ static void volpath_mount_test(void)
return;
if (WinFspDiskTests)
volpath_mount_dotest(MemfsDisk, 0);
{
//volpath_mount_dotest(MemfsDisk, 0, 0);
volpath_mount_dotest(MemfsDisk, 0, L"\\\\.\\m:");
}
if (WinFspNetTests)
volpath_mount_dotest(MemfsNet, L"\\\\memfs\\share");
{
volpath_mount_dotest(MemfsNet, L"\\\\memfs\\share", 0);
}
}
void volpath_tests(void)