Disk (Windows): replaces most Kernel32 calls to ntdll calls

* Improves accurancy of detection of drive create time
* Improves performance slightly
* Removes remove drive check, `hideFolders` should be used instead
This commit is contained in:
李通洲
2026-02-10 18:50:35 +08:00
parent 996cdd3155
commit 5825bce57d
2 changed files with 80 additions and 72 deletions
+24 -6
View File
@@ -6,12 +6,12 @@
#define D3DKMT_ALIGN64 __attribute__((aligned(8)))
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
NTSTATUS NTAPI NtPowerInformation(
@@ -248,3 +248,21 @@ NtQueryDirectoryFile(
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan);
// https://ntdoc.m417z.com/process_devicemap_information_ex
typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX
{
union
{
struct
{
HANDLE DirectoryHandle; // A handle to a directory object that can be set as the new device map for the process. This handle must have DIRECTORY_TRAVERSE access.
} Set;
struct
{
ULONG DriveMap; // A bitmask that indicates which drive letters are currently in use in the process's device map.
UCHAR DriveType[32]; // A value that indicates the type of each drive (e.g., local disk, network drive, etc.). // DRIVE_* WinBase.h
} Query;
};
ULONG Flags; // PROCESS_LUID_DOSDEVICES_ONLY
} PROCESS_DEVICEMAP_INFORMATION_EX, *PPROCESS_DEVICEMAP_INFORMATION_EX;
+56 -66
View File
@@ -1,77 +1,67 @@
#include "disk.h"
#include "common/io.h"
#include "common/thread.h"
#include "common/windows/unicode.h"
#include "common/windows/nt.h"
#include <windows.h>
#include <winioctl.h>
static unsigned __stdcall testRemoteVolumeAccessible(void* mountpoint)
{
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(
(wchar_t*) mountpoint,
READ_CONTROL,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
return 0;
}
#include <ntstatus.h>
#include <stdalign.h>
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
wchar_t buf[MAX_PATH + 1];
uint32_t length = GetLogicalDriveStringsW(ARRAY_SIZE(buf), buf);
if (length == 0 || length >= ARRAY_SIZE(buf))
return "GetLogicalDriveStringsW(ARRAY_SIZE(buf), buf) failed";
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
PROCESS_DEVICEMAP_INFORMATION_EX info = {};
ULONG size = 0;
if(!NT_SUCCESS(NtQueryInformationProcess(GetCurrentProcess(), ProcessDeviceMap, &info, sizeof(info), &size)))
return "NtQueryInformationProcess(ProcessDeviceMap) failed";
// For cross-platform portability; used by `presets/examples/13.jsonc`
if (__builtin_expect(options->folders.length == 1 && options->folders.chars[0] == '/', 0))
if (options->folders.length == 1 && options->folders.chars[0] == '/')
{
wchar_t path[MAX_PATH + 1];
GetSystemWindowsDirectoryW(path, ARRAY_SIZE(path));
ffStrbufSetF(&options->folders, "%c:\\", (char) path[0]);
options->folders.chars[0] = (char) path[0];
ffStrbufAppendS(&options->folders, ":\\");
}
for(uint32_t i = 0; i < length; i++)
wchar_t mountpointW[] = L"X:\\";
char mountpointA[] = "X:\\";
for (wchar_t i = L'A'; i <= L'Z'; i++)
{
wchar_t* mountpoint = buf + i;
if (!(info.Query.DriveMap & (1 << (i - L'A'))))
continue;
mountpointW[0] = i;
mountpointA[0] = (char) i;
ffStrbufSetWS(&buffer, mountpoint);
i += buffer.length;
UINT driveType = GetDriveTypeW(mountpoint);
UINT driveType = info.Query.DriveType[i - L'A'];
if (__builtin_expect((long) options->folders.length, 0))
{
if (!ffStrbufSeparatedContain(&options->folders, &buffer, FF_DISK_FOLDER_SEPARATOR))
if (!ffStrbufSeparatedContainNS(&options->folders, 3, mountpointA, FF_DISK_FOLDER_SEPARATOR))
continue;
}
else if(driveType == DRIVE_NO_ROOT_DIR)
continue;
if (options->hideFolders.length && ffStrbufSeparatedContain(&options->hideFolders, &buffer, FF_DISK_FOLDER_SEPARATOR))
if (options->hideFolders.length && ffStrbufSeparatedContainNS(&options->hideFolders, 3, mountpointA, FF_DISK_FOLDER_SEPARATOR))
continue;
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(mountpointW, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (handle == INVALID_HANDLE_VALUE)
continue;
DWORD diskFlags;
BOOL volumeInfoAvailable = GetVolumeInformationW(mountpoint,
diskName, ARRAY_SIZE(diskName), //Volume name
NULL, //Serial number
NULL, //Max component length
&diskFlags, //File system flags
diskFileSystem, ARRAY_SIZE(diskFileSystem)
);
IO_STATUS_BLOCK iosb;
alignas(FILE_FS_ATTRIBUTE_INFORMATION) uint8_t bufFsAttr[1024];
FILE_FS_ATTRIBUTE_INFORMATION* fsAttr = NT_SUCCESS(NtQueryVolumeInformationFile(handle, &iosb, bufFsAttr, sizeof(bufFsAttr), FileFsAttributeInformation))
? (FILE_FS_ATTRIBUTE_INFORMATION*) bufFsAttr
: NULL;
FF_STRBUF_AUTO_DESTROY diskFileSystemBuf = ffStrbufCreate();
if (volumeInfoAvailable)
if (fsAttr)
{
ffStrbufSetWS(&diskFileSystemBuf, diskFileSystem);
ffStrbufSetNWS(&diskFileSystemBuf, fsAttr->FileSystemNameLength / sizeof(WCHAR), fsAttr->FileSystemName);
if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &diskFileSystemBuf, ':'))
continue;
}
@@ -87,7 +77,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
disk->createTime = 0;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
ffStrbufInitMove(&disk->mountpoint, &buffer);
ffStrbufInitNS(&disk->mountpoint, 3, mountpointA);
ffStrbufInit(&disk->mountFrom);
disk->type = driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM
? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT
@@ -95,42 +85,42 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
: FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
{
wchar_t volumeName[MAX_PATH + 1];
mountpoint[2] = L'\0';
if(QueryDosDeviceW(mountpoint, volumeName, ARRAY_SIZE(volumeName)))
mountpointW[2] = L'\0';
if(QueryDosDeviceW(mountpointW, volumeName, ARRAY_SIZE(volumeName)))
ffStrbufSetWS(&disk->mountFrom, volumeName);
mountpoint[2] = L'\\';
mountpointW[2] = L'\\';
}
#ifdef FF_HAVE_THREADS
if (driveType == DRIVE_REMOTE)
alignas(FILE_FS_VOLUME_INFORMATION) uint8_t bufFsVolume[1024];
FILE_FS_VOLUME_INFORMATION* fsVolume = NT_SUCCESS(NtQueryVolumeInformationFile(handle, &iosb, bufFsVolume, sizeof(bufFsVolume), FileFsVolumeInformation))
? (FILE_FS_VOLUME_INFORMATION*) bufFsVolume
: NULL;
if (fsVolume)
{
FFThreadType thread = ffThreadCreate(testRemoteVolumeAccessible, mountpoint);
if (!ffThreadJoin(thread, 500))
continue;
if (fsVolume->VolumeLabelLength > 0)
ffStrbufSetNWS(&disk->name, fsVolume->VolumeLabelLength / sizeof(WCHAR), fsVolume->VolumeLabel);
if (fsVolume->VolumeCreationTime.QuadPart)
disk->createTime = ((uint64_t) fsVolume->VolumeCreationTime.QuadPart - 116444736000000000ull) / 10000ull;
}
#endif
GetDiskFreeSpaceExW(
mountpoint,
(PULARGE_INTEGER)&disk->bytesAvailable,
(PULARGE_INTEGER)&disk->bytesTotal,
(PULARGE_INTEGER)&disk->bytesFree
);
if(volumeInfoAvailable)
if (fsAttr)
{
ffStrbufInitMove(&disk->filesystem, &diskFileSystemBuf);
ffStrbufSetWS(&disk->name, diskName);
if(diskFlags & FILE_READ_ONLY_VOLUME)
if(fsAttr->FileSystemAttributes & FILE_READ_ONLY_VOLUME)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
WIN32_FILE_ATTRIBUTE_DATA data;
if(GetFileAttributesExW(mountpoint, GetFileExInfoStandard, &data) && data.ftCreationTime.dwHighDateTime > 0)
disk->createTime = (*(uint64_t*) &data.ftCreationTime - 116444736000000000ull) / 10000ull;
FILE_FS_FULL_SIZE_INFORMATION fsFullSize;
if (NT_SUCCESS(NtQueryVolumeInformationFile(handle, &iosb, &fsFullSize, sizeof(fsFullSize), FileFsFullSizeInformation)))
{
uint64_t units = fsFullSize.BytesPerSector * fsFullSize.SectorsPerAllocationUnit;
disk->bytesTotal = (uint64_t) fsFullSize.TotalAllocationUnits.QuadPart * units;
disk->bytesFree = (uint64_t) fsFullSize.ActualAvailableAllocationUnits.QuadPart * units;
disk->bytesAvailable = (uint64_t) fsFullSize.CallerAvailableAllocationUnits.QuadPart * units;
}
}
return NULL;