mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 00:13:01 -05:00
sys,dll: mount improvements
- sys: FspFsvolFileSystemControl: FSCTL_IS_VOLUME_MOUNTED - dll: mount: Transact0, FspMountNotifyShellDriveChange
This commit is contained in:
parent
c04e3d9534
commit
db319bc3c1
@ -21,6 +21,7 @@
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <dbt.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
static INIT_ONCE FspMountInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
||||
@ -350,6 +351,19 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static VOID FspMountNotifyShellDriveChange(VOID)
|
||||
{
|
||||
HRESULT HResult;
|
||||
LPITEMIDLIST Pidl;
|
||||
|
||||
HResult = SHGetKnownFolderIDList(&FOLDERID_ComputerFolder, KF_FLAG_DEFAULT, 0, &Pidl);
|
||||
if (SUCCEEDED(HResult))
|
||||
{
|
||||
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, Pidl, 0);
|
||||
CoTaskMemFree(Pidl);
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
@ -568,7 +582,7 @@ static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle)
|
||||
return CloseHandle(MountHandle) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||
NTSTATUS FspMountSet_Internal(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||
|
||||
@ -609,7 +623,7 @@ FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||
&Desc->MountHandle);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||
NTSTATUS FspMountRemove_Internal(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||
|
||||
@ -623,3 +637,81 @@ FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||
else
|
||||
return FspMountRemove_Directory(Desc->MountHandle);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
BOOLEAN IsDrive;
|
||||
|
||||
IsDrive =
|
||||
(L'*' == Desc->MountPoint[0] && ':' == Desc->MountPoint[1] && L'\0' == Desc->MountPoint[2]) ||
|
||||
FspPathIsMountmgrDrive(Desc->MountPoint) ||
|
||||
FspPathIsDrive(Desc->MountPoint);
|
||||
|
||||
#if defined(FSP_CFG_REJECT_EARLY_IRP)
|
||||
/*
|
||||
* In the original WinFsp design the FSD could accept incoming file system requests
|
||||
* immediately after the in-kernel file system instance was created. Such requests would
|
||||
* be queued in the internal FSD queues and only delivered to the user mode file system
|
||||
* when its dispatcher was started and actively receiving them.
|
||||
*
|
||||
* At the same time the original WinFsp API design was that a user mode file system first
|
||||
* calls FspFileSystemSetMountPoint to create the file system mount point and then calls
|
||||
* FspFileSystemStartDispatcher to start the dispatcher. This design made sense at the time:
|
||||
* creating a mount point involved the creation of a symbolic link of one kind or another,
|
||||
* which could fail for a number of reasons (e.g. drive already exists), so there was no
|
||||
* point to start the dispatcher if the mounting did not succeed. Compatibility with FUSE
|
||||
* and the Unix mounting protocol was another consideration.
|
||||
*
|
||||
* Unfortunately this API design has proved problematic. The problem is that with the
|
||||
* proliferation of ways to mount a file system in WinFsp more and more system components and
|
||||
* third party filters may attempt to access the mount point upon its creation and before the
|
||||
* file system dispatcher is ready. This can result in various consequences.
|
||||
*
|
||||
* In order to properly fix this problem we should probably mandate that a user mode file
|
||||
* system should start its dispatcher first and then create its mountpoint. This way the user
|
||||
* mode file system would be ready to handle any requests from system components or third
|
||||
* party filters during mount point creation. Unfortunately we cannot easily do so because
|
||||
* of backwards compatibility.
|
||||
*
|
||||
* This problem first appeared as an incompatibility with Avast AntiVirus (GitHub issue #221).
|
||||
* In order to avoid backwards incompatible API changes the "Transact0" work around was
|
||||
* devised: when the FSD first creates an in-kernel file system it remains inoperative and any
|
||||
* requests posted to it will fail with STATUS_CANCELLED, until it receives a Transact0
|
||||
* message (an FSP_FSCTL_TRANSACT message with 0 buffers). In order to enable this work around
|
||||
* a user mode file system would specify the RejectIrpPriorToTransact0 flag upon creation.
|
||||
*
|
||||
* Another instance of this problem appeared when support for directory mounting via the Mount
|
||||
* Manager was added: mounting would not complete unless the RejectIrpPriorToTransact0 flag
|
||||
* was set. At this point the RejectIrpPriorToTransact0 was hard coded to 1 in the FSD.
|
||||
*
|
||||
* However if we are creating a drive the Transact0 work around is unnecessary and perhaps
|
||||
* harmful. So in this case send a Transact0 message to the FSD to allow file system requests
|
||||
* to be queued rather than rejected with STATUS_CANCELLED.
|
||||
*/
|
||||
if (IsDrive)
|
||||
FspFsctlTransact(Desc->VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
#endif
|
||||
|
||||
Result = FspMountSet_Internal(Desc);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
BOOLEAN IsDrive;
|
||||
|
||||
IsDrive =
|
||||
FspPathIsMountmgrDrive(Desc->MountPoint) ||
|
||||
FspPathIsDrive(Desc->MountPoint);
|
||||
|
||||
Result = FspMountRemove_Internal(Desc);
|
||||
|
||||
if (NT_SUCCESS(Result) && IsDrive)
|
||||
/* send an extra notification to remove the "ghost" drive in the shell's navigation pane */
|
||||
FspMountNotifyShellDriveChange();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -731,6 +731,7 @@ static NTSTATUS FspFsvolFileSystemControl(
|
||||
Result = FspVolumeWork(FsvolDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_QUERY_WINFSP:
|
||||
case FSCTL_IS_VOLUME_MOUNTED:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user