[MOUNTMGR] Fix initial sending of device online notification (#7030)

1. MountMgrMountedDeviceArrival():
   Fix the conditions under which the device's online notifications
   are skipped (SkipNotifications == TRUE) and fix the code comments.
   Now, things make much more sense:
   online notifications are skipped when the device is already offline
   or is a legacy (NT <= 4) fault-tolerant volume (see point 2 below),
   or is NOT mounted (doesn't have a drive letter).
   Previously, we were sending an online notification if the device
   was NOT mounted (why?!...) or if it was deemed as "valid" (wrongly
   determined, see point 2 below).

2. QueryDeviceInformation():
   * The usage of the "Valid" parameter didn't make much sense. Indeed,
     when a partition/volume device is reported to the Mount Manager,
     it's already valid. (Also, setting "Valid" to TRUE only in the case
     of an MBR partition while ignoring GPT ones, and resetting it to
     FALSE if IOCTL_STORAGE_GET_DEVICE_NUMBER returned success, pointed
     to something incorrect was going on.)
     Instead, what we are checking here is whether the device is a
     legacy fault-tolerant volume: such volume can only reside on an
     MBR disk, have the expected partition type, and does not really
     reside on a specific storage device (hence the check for
     IOCTL_STORAGE_GET_DEVICE_NUMBER returning failure).

   * Take also the opportunity to SAL2-ify the function.
This commit is contained in:
Hermès Bélusca-Maïto 2024-06-14 22:40:55 +02:00
parent 5f26356079
commit 7e89227a00
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 46 additions and 73 deletions

View file

@ -225,15 +225,14 @@ MountMgrFreeDeadDeviceInfo(
NTSTATUS NTSTATUS
QueryDeviceInformation( QueryDeviceInformation(
IN PUNICODE_STRING SymbolicName, _In_ PUNICODE_STRING SymbolicName,
OUT PUNICODE_STRING DeviceName OPTIONAL, _Out_opt_ PUNICODE_STRING DeviceName,
OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL, _Out_opt_ PMOUNTDEV_UNIQUE_ID* UniqueId,
OUT PBOOLEAN Removable OPTIONAL, _Out_opt_ PBOOLEAN Removable,
OUT PBOOLEAN GptDriveLetter OPTIONAL, _Out_opt_ PBOOLEAN GptDriveLetter,
OUT PBOOLEAN HasGuid OPTIONAL, _Out_opt_ PBOOLEAN HasGuid,
IN OUT LPGUID StableGuid OPTIONAL, _Inout_opt_ LPGUID StableGuid,
OUT PBOOLEAN Valid OPTIONAL _Out_opt_ PBOOLEAN IsFT);
);
BOOLEAN BOOLEAN
HasDriveLetter( HasDriveLetter(

View file

@ -271,14 +271,15 @@ CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter,
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, QueryDeviceInformation(
OUT PUNICODE_STRING DeviceName OPTIONAL, _In_ PUNICODE_STRING SymbolicName,
OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL, _Out_opt_ PUNICODE_STRING DeviceName,
OUT PBOOLEAN Removable OPTIONAL, _Out_opt_ PMOUNTDEV_UNIQUE_ID* UniqueId,
OUT PBOOLEAN GptDriveLetter OPTIONAL, _Out_opt_ PBOOLEAN Removable,
OUT PBOOLEAN HasGuid OPTIONAL, _Out_opt_ PBOOLEAN GptDriveLetter,
IN OUT LPGUID StableGuid OPTIONAL, _Out_opt_ PBOOLEAN HasGuid,
OUT PBOOLEAN Valid OPTIONAL) _Inout_opt_ LPGUID StableGuid,
_Out_opt_ PBOOLEAN IsFT)
{ {
NTSTATUS Status; NTSTATUS Status;
USHORT Size; USHORT Size;
@ -334,15 +335,7 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
&GptAttributes, &GptAttributes,
sizeof(GptAttributes), sizeof(GptAttributes),
NULL); NULL);
#if 0 /* Failure isn't major */
if (Status == STATUS_INSUFFICIENT_RESOURCES)
{
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
return Status;
}
#endif
/* In case of failure, don't fail, that's no vital */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
@ -355,15 +348,16 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
} }
} }
/* If caller wants to know if there's valid contents */ /* If caller wants to know if this is a FT volume */
if (Valid) if (IsFT)
{ {
/* Suppose it's not OK */ /* Suppose it's not */
*Valid = FALSE; *IsFT = FALSE;
/* FT volume can't be removable */
if (!IsRemovable) if (!IsRemovable)
{ {
/* Query partitions information */ /* Query partition information */
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX,
DeviceObject, DeviceObject,
NULL, NULL,
@ -371,28 +365,22 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
&PartitionInfo, &PartitionInfo,
sizeof(PartitionInfo), sizeof(PartitionInfo),
NULL); NULL);
#if 0 /* Failure isn't major */
if (Status == STATUS_INSUFFICIENT_RESOURCES)
{
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
return Status;
}
#endif
/* Once again here, failure isn't major */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
/* Verify we know something in */ /* Check if this is a FT volume */
else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR && else if ((PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR) &&
IsRecognizedPartition(PartitionInfo.Mbr.PartitionType)) IsFTPartition(PartitionInfo.Mbr.PartitionType))
{ {
*Valid = TRUE; *IsFT = TRUE;
} }
/* It looks correct, ensure it is & query device number */ /* It looks like a FT volume. Verify it is really one by checking
if (*Valid) * that it does NOT lie on a specific storage device (i.e. it is
* not a basic volume). */
if (*IsFT)
{ {
Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER,
DeviceObject, DeviceObject,
@ -401,18 +389,10 @@ QueryDeviceInformation(IN PUNICODE_STRING SymbolicName,
&StorageDeviceNumber, &StorageDeviceNumber,
sizeof(StorageDeviceNumber), sizeof(StorageDeviceNumber),
NULL); NULL);
#if 0
if (Status == STATUS_INSUFFICIENT_RESOURCES)
{
ObDereferenceObject(DeviceObject);
ObDereferenceObject(FileObject);
return Status;
}
#endif
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
else else
*Valid = FALSE; *IsFT = FALSE; // Succeeded, so this cannot be a FT volume.
} }
} }
} }
@ -890,7 +870,8 @@ MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension,
PDEVICE_INFORMATION DeviceInformation, CurrentDevice; PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH]; WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink; UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError; BOOLEAN HasGuid, HasGptDriveLetter, IsFT, UseOnlyIfThereAreNoOtherLinks;
BOOLEAN IsDrvLetter, IsOff, IsVolumeName, SetOnline;
/* New device = new structure to represent it */ /* New device = new structure to represent it */
DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION)); DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
@ -927,7 +908,7 @@ MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension,
&HasGptDriveLetter, &HasGptDriveLetter,
&HasGuid, &HasGuid,
&StableGuid, &StableGuid,
&Valid); &IsFT);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL); KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
@ -1151,7 +1132,7 @@ MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension,
Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName); Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
LinkError = TRUE; BOOLEAN LinkError = TRUE;
if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) || if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
!SavedLinkInformation) !SavedLinkInformation)
@ -1315,30 +1296,23 @@ MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension,
RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength); RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
} }
/* If the device is offline or valid, skip its notifications */ /* Skip online notifications if the device is offline or a FT volume */
if (IsOff || Valid) if (IsOff || IsFT)
{
DeviceInformation->SkipNotifications = TRUE; DeviceInformation->SkipNotifications = TRUE;
}
/* If automount is enabled or the device already mounted, set it offline */ /* If automount is enabled or the device was already mounted, send now
* the online notification if needed; otherwise, defer its posting */
if (!DeviceExtension->NoAutoMount || IsDrvLetter) if (!DeviceExtension->NoAutoMount || IsDrvLetter)
{ SetOnline = !DeviceInformation->SkipNotifications;
IsOff = !DeviceInformation->SkipNotifications;
}
else else
{ SetOnline = FALSE;
IsOff = FALSE;
}
/* Finally, release the exclusive lock */ /* Finally, release the exclusive lock */
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
/* If the device is not offline, notify its arrival */ /* Set the device online now if necessary */
if (!IsOff) if (SetOnline)
{
SendOnlineNotification(SymbolicName); SendOnlineNotification(SymbolicName);
}
/* If we had symlinks (from storage), free them */ /* If we had symlinks (from storage), free them */
if (SymLinks) if (SymLinks)