1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "disk.h"
#include "common/io.h"
#include "common/time.h"
#include "common/windows/unicode.h"
#include "common/windows/nt.h"
#include <windows.h>
#include <winioctl.h>
#include <ntstatus.h>
#include <stdalign.h>
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) {
PROCESS_DEVICEMAP_INFORMATION_EX info = {};
ULONG size = 0;
if (!NT_SUCCESS(NtQueryInformationProcess(NtCurrentProcess(), ProcessDeviceMap, &info, sizeof(info), &size))) {
return "NtQueryInformationProcess(ProcessDeviceMap) failed";
}
// For cross-platform portability; used by `presets/examples/13.jsonc`
if (options->folders.length == 1 && options->folders.chars[0] == '/') {
options->folders.chars[0] = (char) SharedUserData->NtSystemRoot[0];
ffStrbufAppendS(&options->folders, ":\\");
}
wchar_t mountpointW[] = L"X:\\";
char mountpointA[] = "X:\\";
for (wchar_t i = L'A'; i <= L'Z'; i++) {
if (!(info.Query.DriveMap & (1 << (i - L'A')))) {
continue;
}
mountpointW[0] = i;
mountpointA[0] = (char) i;
UINT driveType = info.Query.DriveType[i - L'A'];
if (__builtin_expect((long) options->folders.length, 0)) {
if (!ffStrbufSeparatedContainNS(&options->folders, 3, mountpointA, FF_DISK_FOLDER_SEPARATOR)) {
continue;
}
} else if (driveType == DRIVE_NO_ROOT_DIR) {
continue;
}
if (options->hideFolders.length && ffStrbufSeparatedContainNS(&options->hideFolders, 3, mountpointA, FF_DISK_FOLDER_SEPARATOR)) {
continue;
}
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;
}
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 (fsAttr) {
ffStrbufSetNWS(&diskFileSystemBuf, fsAttr->FileSystemNameLength / sizeof(WCHAR), fsAttr->FileSystemName);
if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &diskFileSystemBuf, ':')) {
continue;
}
}
FFDisk* disk = FF_LIST_ADD(FFDisk, *disks);
disk->filesUsed = 0;
disk->filesTotal = 0;
disk->bytesTotal = 0;
disk->bytesFree = 0;
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->bytesAvailable = 0;
disk->createTime = 0;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
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
: driveType == DRIVE_FIXED
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
: FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
{
wchar_t volumeName[MAX_PATH + 1];
mountpointW[2] = L'\0';
if (QueryDosDeviceW(mountpointW, volumeName, ARRAY_SIZE(volumeName))) {
ffStrbufSetWS(&disk->mountFrom, volumeName);
}
mountpointW[2] = L'\\';
}
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) {
if (fsVolume->VolumeLabelLength > 0) {
ffStrbufSetNWS(&disk->name, fsVolume->VolumeLabelLength / sizeof(WCHAR), fsVolume->VolumeLabel);
}
if (fsVolume->VolumeCreationTime.QuadPart) {
disk->createTime = ffFileTimeToUnixMs((uint64_t) fsVolume->VolumeCreationTime.QuadPart);
}
}
if (fsAttr) {
ffStrbufInitMove(&disk->filesystem, &diskFileSystemBuf);
if (fsAttr->FileSystemAttributes & FILE_READ_ONLY_VOLUME) {
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
}
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;
}
|