https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4838d7bd56f3fa241d8ab9a0daa20f81c7045ca1

commit 4838d7bd56f3fa241d8ab9a0daa20f81c7045ca1
Author:     Adam Słaboń <asail...@protonmail.com>
AuthorDate: Sat Mar 2 23:48:33 2024 +0100
Commit:     Hermès BÉLUSCA - MAÏTO <hermes.belusca-ma...@reactos.org>
CommitDate: Mon Oct 7 11:16:03 2024 +0200

    [SDK][FMIFS] Partially implement QueryDeviceInformation
    
    On Windows, QueryDeviceInformation leverages the ifsutil.dll's API.
    This is a standalone implementation that mimics Vista behaviour.
---
 dll/win32/fmifs/fmifs.spec             |   2 +-
 dll/win32/fmifs/query.c                | 158 +++++++++++++++++++++++++++++++++
 sdk/include/reactos/libs/fmifs/fmifs.h |  23 ++++-
 3 files changed, 178 insertions(+), 5 deletions(-)

diff --git a/dll/win32/fmifs/fmifs.spec b/dll/win32/fmifs/fmifs.spec
index 6969e36d8c4..2e038e7b209 100644
--- a/dll/win32/fmifs/fmifs.spec
+++ b/dll/win32/fmifs/fmifs.spec
@@ -8,7 +8,7 @@
 @ stdcall FormatEx(wstr ptr wstr wstr long long ptr)
 @ stub FormatEx2
 @ stdcall QueryAvailableFileSystemFormat(long wstr str str ptr)
-@ stub QueryDeviceInformation
+@ stdcall QueryDeviceInformation(wstr ptr long)
 @ stub QueryDeviceInformationByHandle
 @ stub QueryFileSystemName
 @ stub QueryLatestFileSystemVersion
diff --git a/dll/win32/fmifs/query.c b/dll/win32/fmifs/query.c
index 9903275fcac..c05e3fc65f7 100644
--- a/dll/win32/fmifs/query.c
+++ b/dll/win32/fmifs/query.c
@@ -8,6 +8,12 @@
  */
 
 #include "precomp.h"
+#include <ntddstor.h>
+#include <ntstrsafe.h>
+
+#define NTOS_MODE_USER
+#include <ndk/iofuncs.h>
+#include <ndk/obfuncs.h>
 
 BOOLEAN
 NTAPI
@@ -43,3 +49,155 @@ QueryAvailableFileSystemFormat(
 
     return TRUE;
 }
+
+/**
+ * @brief
+ * Retrieves disk device information.
+ *
+ * @param[in] DriveRoot
+ * String which contains a DOS device name,
+ *
+ * @param[in,out] DeviceInformation
+ * Pointer to buffer with DEVICE_INFORMATION structure which will receive data.
+ *
+ * @param[in] BufferSize
+ * Size of buffer in bytes.
+ *
+ * @return
+ * TRUE if the buffer was large enough and was filled with
+ * the requested information, FALSE otherwise.
+ *
+ * @remarks
+ * The returned information is mostly related to Sony Memory Stick devices.
+ * On Vista+ the returned information is disk sector size and volume length in 
sectors,
+ * regardless of the type of disk.
+ * ReactOS implementation returns DEVICE_HOTPLUG flag if inspected device is a 
hotplug device
+ * as well as sector size and volume length of disk device.
+ */
+BOOL
+NTAPI
+QueryDeviceInformation(
+    _In_ PWCHAR DriveRoot,
+    _Out_ PVOID DeviceInformation,
+    _In_ ULONG BufferSize)
+{
+    PDEVICE_INFORMATION DeviceInfo = DeviceInformation;
+    IO_STATUS_BLOCK Iosb;
+    DISK_GEOMETRY DiskGeometry;
+    STORAGE_HOTPLUG_INFO HotplugInfo;
+    GET_LENGTH_INFORMATION LengthInformation;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING DeviceName;
+    HANDLE FileHandle;
+    NTSTATUS Status;
+    WCHAR DiskDevice[MAX_PATH];
+    WCHAR DriveName[MAX_PATH];
+
+    /* Buffer should be able to at least hold DeviceFlags */
+    if (BufferSize < sizeof(ULONG) ||
+        !NT_SUCCESS(RtlStringCchCopyW(DriveName, ARRAYSIZE(DriveName), 
DriveRoot)))
+    {
+        return FALSE;
+    }
+
+    if (DriveName[wcslen(DriveName) - 1] != L'\\')
+    {
+        /* Append the trailing backslash for GetVolumeNameForVolumeMountPointW 
*/
+        if (!NT_SUCCESS(RtlStringCchCatW(DriveName, ARRAYSIZE(DriveName), 
L"\\")))
+            return FALSE;
+    }
+
+    if (!GetVolumeNameForVolumeMountPointW(DriveName, DiskDevice, 
ARRAYSIZE(DiskDevice)) ||
+        !RtlDosPathNameToNtPathName_U(DiskDevice, &DeviceName, NULL, NULL))
+    {
+        /* Disk has no volume GUID, fallback to QueryDosDevice */
+        DriveName[wcslen(DriveName) - 1] = UNICODE_NULL;
+        if (!QueryDosDeviceW(DriveName, DiskDevice, ARRAYSIZE(DiskDevice)))
+            return FALSE;
+        RtlInitUnicodeString(&DeviceName, DiskDevice);
+    }
+    else
+    {
+        /* Trim the trailing backslash since we will work with a device object 
*/
+        DeviceName.Length -= sizeof(WCHAR);
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &DeviceName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &Iosb,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
+        return FALSE;
+
+    Status = NtDeviceIoControlFile(FileHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &Iosb,
+                                   IOCTL_STORAGE_GET_HOTPLUG_INFO,
+                                   NULL,
+                                   0,
+                                   &HotplugInfo,
+                                   sizeof(HotplugInfo));
+    if (!NT_SUCCESS(Status))
+        goto Quit;
+
+    DeviceInfo->DeviceFlags = 0;
+    if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug)
+    {
+        /* This is a hotplug device */
+        DeviceInfo->DeviceFlags |= DEVICE_HOTPLUG;
+    }
+
+    /* Other flags that would be set here are related to Sony "Memory Stick"
+     * type of devices which we do not have any special support for */
+
+    if (BufferSize >= sizeof(DEVICE_INFORMATION))
+    {
+        /* This is the Vista+ version of the structure.
+         * We need to also provide disk sector size and volume length in 
sectors. */
+        Status = NtDeviceIoControlFile(FileHandle,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &Iosb,
+                                       IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                       NULL,
+                                       0,
+                                       &DiskGeometry,
+                                       sizeof(DiskGeometry));
+        if (!NT_SUCCESS(Status))
+            goto Quit;
+
+        Status = NtDeviceIoControlFile(FileHandle,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &Iosb,
+                                       IOCTL_DISK_GET_LENGTH_INFO,
+                                       NULL,
+                                       0,
+                                       &LengthInformation,
+                                       sizeof(LengthInformation));
+        if (!NT_SUCCESS(Status))
+            goto Quit;
+
+        LengthInformation.Length.QuadPart /= DiskGeometry.BytesPerSector;
+        DeviceInfo->SectorSize = DiskGeometry.BytesPerSector;
+        DeviceInfo->SectorCount = LengthInformation.Length;
+    }
+
+    Status = STATUS_SUCCESS;
+
+Quit:
+    NtClose(FileHandle);
+    return NT_SUCCESS(Status);
+}
diff --git a/sdk/include/reactos/libs/fmifs/fmifs.h 
b/sdk/include/reactos/libs/fmifs/fmifs.h
index 482b3b02457..27e3950239e 100644
--- a/sdk/include/reactos/libs/fmifs/fmifs.h
+++ b/sdk/include/reactos/libs/fmifs/fmifs.h
@@ -33,6 +33,20 @@ typedef struct
     PCHAR Output;
 } TEXTOUTPUT, *PTEXTOUTPUT;
 
+/* Device information */
+typedef struct _DEVICE_INFORMATION
+{
+    ULONG DeviceFlags;
+    ULONG SectorSize;
+    LARGE_INTEGER SectorCount;
+} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
+
+/* Device information flags */
+#define MEMORYSTICK_FORMAT_CAPABLE 0x10
+#define MEMORYSTICK_SUPPORTS_PROGRESS_BAR 0x20
+#define DEVICE_HOTPLUG 0x40
+#define DEVICE_MEMORYSTICK 0x41
+
 /* media flags */
 typedef enum
 {
@@ -163,11 +177,12 @@ QueryAvailableFileSystemFormat(
     OUT UCHAR* Minor,
     OUT BOOLEAN* LatestVersion);
 
-BOOL NTAPI
+BOOL
+NTAPI
 QueryDeviceInformation(
-    IN PWCHAR DriveRoot,
-    OUT ULONG* Buffer, /* That is probably some 4-bytes structure */
-    IN ULONG BufferSize); /* 4 */
+    _In_ PWCHAR DriveRoot,
+    _Out_ PVOID DeviceInformation,
+    _In_ ULONG BufferSize);
 
 BOOL NTAPI
 QueryFileSystemName(

Reply via email to