From ed27d733f7ef53817801e4c4df5026b487df93df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 26 May 2024 20:05:10 +0200 Subject: [PATCH] [MOUNTMGR][DDK] Fix some IOCTLs definitions to Win2k3+ compatibility (#6959) Fix IOCTL_MOUNTDEV_LINK_CREATED, IOCTL_MOUNTDEV_LINK_DELETED, IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY, to Win2k3+ compatible definitions. The previous versions of these IOCTLs (in Win2000 and XP) were defined without any access protection. This was noticed here: https://community.osr.com/t/ioctl-mountdev-link-created-definition-changed/29428 --- drivers/storage/mountmgr/symlink.c | 35 +++++++++++++++++++++--------- sdk/include/ddk/mountdev.h | 16 ++++++++++---- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/drivers/storage/mountmgr/symlink.c b/drivers/storage/mountmgr/symlink.c index f4d23815249..3e6aa6aa90b 100644 --- a/drivers/storage/mountmgr/symlink.c +++ b/drivers/storage/mountmgr/symlink.c @@ -28,6 +28,15 @@ #define NDEBUG #include +/* Deprecated Windows 2000/XP versions of IOCTL_MOUNTDEV_LINK_[CREATED|DELETED] + * without access protection, that were updated in Windows 2003. + * They are sent to MountMgr clients if they do not recognize the new IOCTLs + * (e.g. they are for an older NT version). */ +#if (NTDDI_VERSION >= NTDDI_WS03) +#define IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + UNICODE_STRING DeviceMount = RTL_CONSTANT_STRING(MOUNTMGR_DEVICE_NAME); UNICODE_STRING DosDevicesMount = RTL_CONSTANT_STRING(L"\\DosDevices\\MountPointManager"); UNICODE_STRING DosDevices = RTL_CONSTANT_STRING(L"\\DosDevices\\"); @@ -194,11 +203,12 @@ SendLinkCreated(IN PUNICODE_STRING SymbolicName) Name->NameLength = SymbolicName->Length; RtlCopyMemory(Name->Name, SymbolicName->Buffer, SymbolicName->Length); + /* Send the notification, using the new (Windows 2003+) IOCTL definition + * (with limited access) first. If this fails, the called driver may be + * for an older NT version, and so, we send again the notification using + * the old (Windows 2000) IOCTL definition (with any access). */ KeInitializeEvent(&Event, NotificationEvent, FALSE); - /* Microsoft does it twice... Once with limited access, second with any - * So, first one here - */ - Irp = IoBuildDeviceIoControlRequest(CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_CREATED, DeviceObject, Name, NameSize, @@ -219,10 +229,10 @@ SendLinkCreated(IN PUNICODE_STRING SymbolicName) KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } } - +#if (NTDDI_VERSION >= NTDDI_WS03) /* Then, second one */ KeInitializeEvent(&Event, NotificationEvent, FALSE); - Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_CREATED, + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED, DeviceObject, Name, NameSize, @@ -245,6 +255,7 @@ SendLinkCreated(IN PUNICODE_STRING SymbolicName) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } +#endif // (NTDDI_VERSION >= NTDDI_WS03) Cleanup: if (Name) @@ -300,9 +311,12 @@ SendLinkDeleted(IN PUNICODE_STRING DeviceName, Name->NameLength = SymbolicName->Length; RtlCopyMemory(Name->Name, SymbolicName->Buffer, SymbolicName->Length); + /* Send the notification, using the new (Windows 2003+) IOCTL definition + * (with limited access) first. If this fails, the called driver may be + * for an older NT version, and so, we send again the notification using + * the old (Windows 2000) IOCTL definition (with any access). */ KeInitializeEvent(&Event, NotificationEvent, FALSE); - /* Cf: SendLinkCreated comment */ - Irp = IoBuildDeviceIoControlRequest(CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_DELETED, DeviceObject, Name, NameSize, @@ -323,10 +337,10 @@ SendLinkDeleted(IN PUNICODE_STRING DeviceName, KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } } - +#if (NTDDI_VERSION >= NTDDI_WS03) /* Then, second one */ KeInitializeEvent(&Event, NotificationEvent, FALSE); - Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_DELETED, + Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_LINK_DELETED_UNSECURE_DEPRECATED, DeviceObject, Name, NameSize, @@ -349,6 +363,7 @@ SendLinkDeleted(IN PUNICODE_STRING DeviceName, { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } +#endif // (NTDDI_VERSION >= NTDDI_WS03) Cleanup: if (Name) diff --git a/sdk/include/ddk/mountdev.h b/sdk/include/ddk/mountdev.h index b2f170540d5..4c158ce9f7f 100644 --- a/sdk/include/ddk/mountdev.h +++ b/sdk/include/ddk/mountdev.h @@ -33,12 +33,19 @@ extern "C" { #endif +/* Windows 2003 fixed the required access for some IOCTLs */ +#if (NTDDI_VERSION >= NTDDI_WS03) + #define EXPECTED_ACCESS (FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#else + #define EXPECTED_ACCESS FILE_ANY_ACCESS +#endif + #if (NTDDI_VERSION >= NTDDI_WIN2K) #define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID CTL_CODE(MOUNTDEVCONTROLTYPE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME CTL_CODE(MOUNTDEVCONTROLTYPE, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_MOUNTDEV_LINK_CREATED CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_MOUNTDEV_LINK_DELETED CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_LINK_CREATED CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, EXPECTED_ACCESS) +#define IOCTL_MOUNTDEV_LINK_DELETED CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, EXPECTED_ACCESS) typedef struct _MOUNTDEV_UNIQUE_ID { USHORT UniqueIdLength; @@ -63,8 +70,9 @@ typedef struct _MOUNTDEV_STABLE_GUID { #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ -/* FIXME : These definitions don't exist in the official header : */ -#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY CTL_CODE(MOUNTDEVCONTROLTYPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* NOTE: Support for IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY + * seems to have been removed from official WDK in Vista+ */ +#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY CTL_CODE(MOUNTDEVCONTROLTYPE, 1, METHOD_BUFFERED, EXPECTED_ACCESS) typedef struct _MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT { ULONG Size; USHORT OldUniqueIdOffset;