mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
dll: MountBroadcastDriveChange registry setting
This commit is contained in:
parent
f6e6660362
commit
41d69d7186
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
#include <dbt.h>
|
||||||
|
|
||||||
static INIT_ONCE FspMountInitOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE FspMountInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
||||||
@ -28,21 +29,30 @@ static NTSTATUS (NTAPI *FspNtMakeTemporaryObject)(
|
|||||||
HANDLE Handle);
|
HANDLE Handle);
|
||||||
static NTSTATUS (NTAPI *FspNtClose)(
|
static NTSTATUS (NTAPI *FspNtClose)(
|
||||||
HANDLE Handle);
|
HANDLE Handle);
|
||||||
static BOOLEAN FspMountDoNotUseLauncher;
|
static BOOLEAN FspMountDoNotUseLauncherValue;
|
||||||
|
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
||||||
|
|
||||||
static VOID FspMountInitializeFromRegistry(VOID)
|
static VOID FspMountInitializeFromRegistry(VOID)
|
||||||
{
|
{
|
||||||
DWORD MountDoNotUseLauncher;
|
DWORD Value;
|
||||||
DWORD Size;
|
DWORD Size;
|
||||||
LONG Result;
|
LONG Result;
|
||||||
|
|
||||||
MountDoNotUseLauncher = 0;
|
Value = 0;
|
||||||
Size = sizeof MountDoNotUseLauncher;
|
Size = sizeof Value;
|
||||||
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||||
L"MountDoNotUseLauncher",
|
L"MountDoNotUseLauncher",
|
||||||
RRF_RT_REG_DWORD, 0, &MountDoNotUseLauncher, &Size);
|
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||||
if (ERROR_SUCCESS == Result)
|
if (ERROR_SUCCESS == Result)
|
||||||
FspMountDoNotUseLauncher = !!MountDoNotUseLauncher;
|
FspMountDoNotUseLauncherValue = !!Value;
|
||||||
|
|
||||||
|
Value = 0;
|
||||||
|
Size = sizeof Value;
|
||||||
|
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||||
|
L"MountBroadcastDriveChange",
|
||||||
|
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||||
|
if (ERROR_SUCCESS == Result)
|
||||||
|
FspMountBroadcastDriveChangeValue = !!Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI FspMountInitialize(
|
static BOOL WINAPI FspMountInitialize(
|
||||||
@ -375,6 +385,46 @@ static NTSTATUS FspLauncherDefineDosDevice(
|
|||||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspMountBroadcastDriveChange(PWSTR MountPoint, WPARAM WParam)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* DefineDosDeviceW (either directly or via the CSRSS) broadcasts a WM_DEVICECHANGE message
|
||||||
|
* when a drive is added/removed. Unfortunately on some systems this broadcast fails. The
|
||||||
|
* result is that Explorer does not receive the WM_DEVICECHANGE notification and does not
|
||||||
|
* become aware of the drive change. This results in only minor UI issues for local drives,
|
||||||
|
* but more seriously it makes network drives inaccessible from some Explorer windows.
|
||||||
|
*
|
||||||
|
* The problem is that BroadcastSystemMessage can hang indefinitely when supplied the flags
|
||||||
|
* NOHANG | FORCEIFHUNG | NOTIMEOUTIFNOTHUNG. The NOTIMEOUTIFNOTHUNG flag instructs the BSM
|
||||||
|
* API to not timeout an app that is not considered hung; however an app that is not hung may
|
||||||
|
* still fail to respond to a broadcasted message indefinitely. This can result in the BSM
|
||||||
|
* API never returning ("hanging").
|
||||||
|
*
|
||||||
|
* To resolve this we simply call BroadcastSystemMessage without NOTIMEOUTIFNOTHUNG.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOLEAN IsLocalSystem;
|
||||||
|
DEV_BROADCAST_VOLUME DriveChange;
|
||||||
|
DWORD Flags, Recipients;
|
||||||
|
|
||||||
|
FspServiceContextCheck(0, &IsLocalSystem);
|
||||||
|
|
||||||
|
memset(&DriveChange, 0, sizeof DriveChange);
|
||||||
|
DriveChange.dbcv_size = sizeof DriveChange;
|
||||||
|
DriveChange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
||||||
|
DriveChange.dbcv_flags = DBTF_NET;
|
||||||
|
DriveChange.dbcv_unitmask = 1 << (MountPoint[0] - 'a');
|
||||||
|
|
||||||
|
Flags = BSF_NOHANG | BSF_FORCEIFHUNG;
|
||||||
|
Recipients = BSM_APPLICATIONS | (IsLocalSystem ? BSM_ALLDESKTOPS : 0);
|
||||||
|
BroadcastSystemMessageW(
|
||||||
|
Flags,
|
||||||
|
&Recipients,
|
||||||
|
WM_DEVICECHANGE,
|
||||||
|
WParam,
|
||||||
|
(LPARAM)&DriveChange);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)
|
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -384,7 +434,7 @@ static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PM
|
|||||||
|
|
||||||
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
||||||
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
||||||
if (IsServiceContext && !FspMountDoNotUseLauncher)
|
if (IsServiceContext && !FspMountDoNotUseLauncherValue)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If the current process is in the service context but not LocalSystem,
|
* If the current process is in the service context but not LocalSystem,
|
||||||
@ -402,6 +452,13 @@ static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PM
|
|||||||
{
|
{
|
||||||
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On some systems DefineDosDeviceW fails to properly broadcast the WM_DEVICECHANGE
|
||||||
|
* notification. So use a workaround. See comments in FspMountBroadcastDriveChange.
|
||||||
|
*/
|
||||||
|
if (FspMountBroadcastDriveChangeValue)
|
||||||
|
FspMountBroadcastDriveChange(MountPoint, DBT_DEVICEARRIVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != FspNtOpenSymbolicLinkObject)
|
if (0 != FspNtOpenSymbolicLinkObject)
|
||||||
@ -457,9 +514,18 @@ static NTSTATUS FspMountRemove_Drive(PWSTR VolumeName, PWSTR MountPoint, HANDLE
|
|||||||
*/
|
*/
|
||||||
Result = FspLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
Result = FspLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Result = DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
Result = DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||||
MountPoint, VolumeName) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
MountPoint, VolumeName) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On some systems DefineDosDeviceW fails to properly broadcast the WM_DEVICECHANGE
|
||||||
|
* notification. So use a workaround. See comments in FspMountBroadcastDriveChange.
|
||||||
|
*/
|
||||||
|
if (FspMountBroadcastDriveChangeValue)
|
||||||
|
FspMountBroadcastDriveChange(MountPoint, DBT_DEVICEREMOVECOMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != MountHandle)
|
if (0 != MountHandle)
|
||||||
FspNtClose(MountHandle);
|
FspNtClose(MountHandle);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user