reactos/drivers/storage/mountmgr/mntmgr.h
Hermès Bélusca-Maïto 7e89227a00
[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.
2024-06-25 22:51:08 +02:00

521 lines
11 KiB
C

#ifndef _MNTMGR_H_
#define _MNTMGR_H_
#include <ntifs.h>
#include <mountdev.h>
#include <ntddvol.h>
#include <ntdddisk.h>
#include <wdmguid.h>
#include <ndk/psfuncs.h>
#include <ntdddisk.h>
#include <section_attribs.h>
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject;
PDRIVER_OBJECT DriverObject;
LIST_ENTRY DeviceListHead;
LIST_ENTRY OfflineDeviceListHead;
PVOID NotificationEntry;
KSEMAPHORE DeviceLock;
KSEMAPHORE RemoteDatabaseLock;
BOOLEAN AutomaticDriveLetter;
LIST_ENTRY IrpListHead;
ULONG EpicNumber;
LIST_ENTRY SavedLinksListHead;
BOOLEAN ProcessedSuggestions;
BOOLEAN NoAutoMount;
LIST_ENTRY WorkerQueueListHead;
KSEMAPHORE WorkerSemaphore;
LONG WorkerReferences;
KSPIN_LOCK WorkerLock;
LIST_ENTRY UniqueIdWorkerItemListHead;
PMOUNTDEV_UNIQUE_ID DriveLetterData;
UNICODE_STRING RegistryPath;
LONG WorkerThreadStatus;
LIST_ENTRY OnlineNotificationListHead;
ULONG OnlineNotificationWorkerActive;
ULONG OnlineNotificationCount;
KEVENT OnlineNotificationEvent;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _DEVICE_INFORMATION
{
LIST_ENTRY DeviceListEntry;
LIST_ENTRY SymbolicLinksListHead;
LIST_ENTRY ReplicatedUniqueIdsListHead;
LIST_ENTRY AssociatedDevicesHead;
UNICODE_STRING SymbolicName;
PMOUNTDEV_UNIQUE_ID UniqueId;
UNICODE_STRING DeviceName;
BOOLEAN KeepLinks;
UCHAR SuggestedDriveLetter;
BOOLEAN ManuallyRegistered;
BOOLEAN Removable;
BOOLEAN LetterAssigned;
BOOLEAN NeedsReconcile;
BOOLEAN NoDatabase;
BOOLEAN SkipNotifications;
ULONG Migrated;
LONG MountState;
PVOID TargetDeviceNotificationEntry;
PDEVICE_EXTENSION DeviceExtension;
} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
typedef struct _SYMLINK_INFORMATION
{
LIST_ENTRY SymbolicLinksListEntry;
UNICODE_STRING Name;
BOOLEAN Online;
} SYMLINK_INFORMATION, *PSYMLINK_INFORMATION;
typedef struct _SAVED_LINK_INFORMATION
{
LIST_ENTRY SavedLinksListEntry;
LIST_ENTRY SymbolicLinksListHead;
PMOUNTDEV_UNIQUE_ID UniqueId;
} SAVED_LINK_INFORMATION, *PSAVED_LINK_INFORMATION;
typedef struct _UNIQUE_ID_REPLICATE
{
LIST_ENTRY ReplicatedUniqueIdsListEntry;
PMOUNTDEV_UNIQUE_ID UniqueId;
} UNIQUE_ID_REPLICATE, *PUNIQUE_ID_REPLICATE;
typedef struct _DATABASE_ENTRY
{
ULONG EntrySize;
ULONG EntryReferences;
USHORT SymbolicNameOffset;
USHORT SymbolicNameLength;
USHORT UniqueIdOffset;
USHORT UniqueIdLength;
} DATABASE_ENTRY, *PDATABASE_ENTRY;
typedef struct _ASSOCIATED_DEVICE_ENTRY
{
LIST_ENTRY AssociatedDevicesEntry;
PDEVICE_INFORMATION DeviceInformation;
UNICODE_STRING String;
} ASSOCIATED_DEVICE_ENTRY, *PASSOCIATED_DEVICE_ENTRY;
typedef struct _DEVICE_INFORMATION_ENTRY
{
LIST_ENTRY DeviceInformationEntry;
PDEVICE_INFORMATION DeviceInformation;
} DEVICE_INFORMATION_ENTRY, *PDEVICE_INFORMATION_ENTRY;
typedef struct _ONLINE_NOTIFICATION_WORK_ITEM
{
WORK_QUEUE_ITEM WorkItem;
PDEVICE_EXTENSION DeviceExtension;
UNICODE_STRING SymbolicName;
} ONLINE_NOTIFICATION_WORK_ITEM, *PONLINE_NOTIFICATION_WORK_ITEM;
typedef struct _RECONCILE_WORK_ITEM_CONTEXT
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_INFORMATION DeviceInformation;
} RECONCILE_WORK_ITEM_CONTEXT, *PRECONCILE_WORK_ITEM_CONTEXT;
typedef struct _RECONCILE_WORK_ITEM
{
LIST_ENTRY WorkerQueueListEntry;
PIO_WORKITEM WorkItem;
PWORKER_THREAD_ROUTINE WorkerRoutine;
PVOID Context;
RECONCILE_WORK_ITEM_CONTEXT;
} RECONCILE_WORK_ITEM, *PRECONCILE_WORK_ITEM;
typedef struct _MIGRATE_WORK_ITEM
{
PIO_WORKITEM WorkItem;
PDEVICE_INFORMATION DeviceInformation;
PKEVENT Event;
NTSTATUS Status;
HANDLE Database;
} MIGRATE_WORK_ITEM, *PMIGRATE_WORK_ITEM;
typedef struct _UNIQUE_ID_WORK_ITEM
{
LIST_ENTRY UniqueIdWorkerItemListEntry;
PIO_WORKITEM WorkItem;
PDEVICE_EXTENSION DeviceExtension;
PIRP Irp;
PVOID IrpBuffer;
PKEVENT Event;
UNICODE_STRING DeviceName;
ULONG IrpBufferLength;
ULONG StackSize;
} UNIQUE_ID_WORK_ITEM, *PUNIQUE_ID_WORK_ITEM;
/* Memory allocation helpers */
#define AllocatePool(Size) ExAllocatePoolWithTag(PagedPool, Size, 'AtnM')
#define FreePool(P) ExFreePoolWithTag(P, 'AtnM')
/* Misc macros */
#define MAX(a, b) ((a > b) ? a : b)
#define LETTER_POSITION 0xC
#define COLON_POSITION 0xD
#define DRIVE_LETTER_LENGTH 0x1C
/* mountmgr.c */
extern UNICODE_STRING DosDevicesMount;
extern PDEVICE_OBJECT gdeviceObject;
extern UNICODE_STRING ReparseIndex;
extern UNICODE_STRING DeviceFloppy;
extern UNICODE_STRING DeviceMount;
extern UNICODE_STRING DeviceCdRom;
extern UNICODE_STRING SafeVolumes;
extern UNICODE_STRING DosDevices;
extern UNICODE_STRING DosGlobal;
extern UNICODE_STRING Global;
extern UNICODE_STRING Volume;
extern KEVENT UnloadEvent;
extern LONG Unloading;
CODE_SEG("INIT")
DRIVER_INITIALIZE DriverEntry;
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
MountMgrSendSyncDeviceIoCtl(
_In_ ULONG IoControlCode,
_In_ PDEVICE_OBJECT DeviceObject,
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
_In_ ULONG OutputBufferLength,
_In_opt_ PFILE_OBJECT FileObject);
VOID
NTAPI
MountMgrCancel(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
MountMgrMountedDeviceArrival(
IN PDEVICE_EXTENSION Extension,
IN PUNICODE_STRING SymbolicName,
IN BOOLEAN FromVolume
);
VOID
MountMgrMountedDeviceRemoval(
IN PDEVICE_EXTENSION Extension,
IN PUNICODE_STRING DeviceName
);
NTSTATUS
FindDeviceInfo(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING SymbolicName,
IN BOOLEAN DeviceNameGiven,
OUT PDEVICE_INFORMATION * DeviceInformation
);
VOID
MountMgrFreeDeadDeviceInfo(
IN PDEVICE_INFORMATION DeviceInformation
);
NTSTATUS
QueryDeviceInformation(
_In_ PUNICODE_STRING SymbolicName,
_Out_opt_ PUNICODE_STRING DeviceName,
_Out_opt_ PMOUNTDEV_UNIQUE_ID* UniqueId,
_Out_opt_ PBOOLEAN Removable,
_Out_opt_ PBOOLEAN GptDriveLetter,
_Out_opt_ PBOOLEAN HasGuid,
_Inout_opt_ LPGUID StableGuid,
_Out_opt_ PBOOLEAN IsFT);
BOOLEAN
HasDriveLetter(
IN PDEVICE_INFORMATION DeviceInformation
);
/* database.c */
extern PWSTR DatabasePath;
extern PWSTR OfflinePath;
VOID
ReconcileThisDatabaseWithMaster(
IN PDEVICE_EXTENSION DeviceExtension,
IN PDEVICE_INFORMATION DeviceInformation
);
NTSTATUS
WaitForRemoteDatabaseSemaphore(
IN PDEVICE_EXTENSION DeviceExtension
);
VOID
ReleaseRemoteDatabaseSemaphore(
IN PDEVICE_EXTENSION DeviceExtension
);
VOID
ChangeRemoteDatabaseUniqueId(
IN PDEVICE_INFORMATION DeviceInformation,
IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
IN PMOUNTDEV_UNIQUE_ID NewUniqueId
);
VOID
ReconcileAllDatabasesWithMaster(
IN PDEVICE_EXTENSION DeviceExtension
);
VOID
DeleteFromLocalDatabase(
IN PUNICODE_STRING SymbolicLink,
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
VOID
DeleteRegistryDriveLetter(
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
VOID
DeleteNoDriveLetterEntry(
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
NTSTATUS
QueryVolumeName(
IN HANDLE RootDirectory,
IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation,
IN PUNICODE_STRING FileName OPTIONAL,
OUT PUNICODE_STRING SymbolicName,
OUT PUNICODE_STRING VolumeName
);
HANDLE
OpenRemoteDatabase(
IN PDEVICE_INFORMATION DeviceInformation,
IN BOOLEAN MigrateDatabase
);
PDATABASE_ENTRY
GetRemoteDatabaseEntry(
IN HANDLE Database,
IN LONG StartingOffset
);
NTSTATUS
WriteRemoteDatabaseEntry(
IN HANDLE Database,
IN LONG Offset,
IN PDATABASE_ENTRY Entry
);
NTSTATUS
CloseRemoteDatabase(
IN HANDLE Database
);
NTSTATUS
AddRemoteDatabaseEntry(
IN HANDLE Database,
IN PDATABASE_ENTRY Entry
);
NTSTATUS
DeleteRemoteDatabaseEntry(
IN HANDLE Database,
IN LONG StartingOffset
);
VOID
NTAPI
ReconcileThisDatabaseWithMasterWorker(
IN PVOID Parameter
);
/* device.c */
DRIVER_DISPATCH MountMgrDeviceControl;
/* notify.c */
VOID
IssueUniqueIdChangeNotifyWorker(
IN PUNIQUE_ID_WORK_ITEM WorkItem,
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
VOID
WaitForOnlinesToComplete(
IN PDEVICE_EXTENSION DeviceExtension
);
VOID
RegisterForTargetDeviceNotification(
IN PDEVICE_EXTENSION DeviceExtension,
IN PDEVICE_INFORMATION DeviceInformation
);
VOID
SendOnlineNotification(
IN PUNICODE_STRING SymbolicName
);
VOID
IssueUniqueIdChangeNotify(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING DeviceName,
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
VOID
PostOnlineNotification(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING SymbolicName
);
VOID
MountMgrNotify(
IN PDEVICE_EXTENSION DeviceExtension
);
VOID
MountMgrNotifyNameChange(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING DeviceName,
IN BOOLEAN ValidateVolume
);
/* uniqueid.c */
VOID
MountMgrUniqueIdChangeRoutine(
IN PDEVICE_EXTENSION DeviceExtension,
IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
IN PMOUNTDEV_UNIQUE_ID NewUniqueId
);
VOID
CreateNoDriveLetterEntry(
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
BOOLEAN
HasNoDriveLetterEntry(
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
VOID
UpdateReplicatedUniqueIds(
IN PDEVICE_INFORMATION DeviceInformation,
IN PDATABASE_ENTRY DatabaseEntry
);
BOOLEAN
IsUniqueIdPresent(
IN PDEVICE_EXTENSION DeviceExtension,
IN PDATABASE_ENTRY DatabaseEntry
);
/* point.c */
NTSTATUS
MountMgrCreatePointWorker(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING SymbolicLinkName,
IN PUNICODE_STRING DeviceName
);
NTSTATUS
QueryPointsFromSymbolicLinkName(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING SymbolicName,
IN PIRP Irp
);
NTSTATUS
QueryPointsFromMemory(
IN PDEVICE_EXTENSION DeviceExtension,
IN PIRP Irp,
IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL,
IN PUNICODE_STRING SymbolicName OPTIONAL
);
/* symlink.c */
NTSTATUS
GlobalCreateSymbolicLink(
IN PUNICODE_STRING DosName,
IN PUNICODE_STRING DeviceName
);
NTSTATUS
GlobalDeleteSymbolicLink(
IN PUNICODE_STRING DosName
);
NTSTATUS
QuerySuggestedLinkName(
IN PUNICODE_STRING SymbolicName,
OUT PUNICODE_STRING SuggestedLinkName,
OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks
);
NTSTATUS
QuerySymbolicLinkNamesFromStorage(
IN PDEVICE_EXTENSION DeviceExtension,
IN PDEVICE_INFORMATION DeviceInformation,
IN PUNICODE_STRING SuggestedLinkName,
IN BOOLEAN UseOnlyIfThereAreNoOtherLinks,
OUT PUNICODE_STRING * SymLinks,
OUT PULONG SymLinkCount,
IN BOOLEAN HasGuid,
IN LPGUID Guid
);
PSAVED_LINK_INFORMATION
RemoveSavedLinks(
IN PDEVICE_EXTENSION DeviceExtension,
IN PMOUNTDEV_UNIQUE_ID UniqueId
);
BOOLEAN
RedirectSavedLink(
IN PSAVED_LINK_INFORMATION SavedLinkInformation,
IN PUNICODE_STRING DosName,
IN PUNICODE_STRING NewLink
);
VOID
SendLinkCreated(
IN PUNICODE_STRING SymbolicName
);
NTSTATUS
CreateNewVolumeName(
OUT PUNICODE_STRING VolumeName,
IN PGUID VolumeGuid OPTIONAL
);
BOOLEAN
IsDriveLetter(
PUNICODE_STRING SymbolicName
);
VOID
DeleteSymbolicLinkNameFromMemory(
IN PDEVICE_EXTENSION DeviceExtension,
IN PUNICODE_STRING SymbolicLink,
IN BOOLEAN MarkOffline
);
NTSTATUS
MountMgrQuerySymbolicLink(
IN PUNICODE_STRING SymbolicName,
IN OUT PUNICODE_STRING LinkTarget
);
#endif /* _MNTMGR_H_ */