Где-нибудь есть собранная в одном документе и достаточно структурированная инфа о том, как взаимосвязаны устройства/тома/кластеры/LBA в винде, и как с ними работать? Хочу прочитать содержимое файла через прямое чтение LBA-блоков, но пока только смог заполучить списки логических номеров кластеров, в которых располагается файл, через DeviceIoControl / FSCTL_GET_RETRIEVAL_POINTERS. Теперь, скорее всего, надо как-то преобразовать логические номера кластеров в номера LBA и найти функции, позволяющие работать с конкретными LBA (хотя может быть я даже неправильно знаю, и LBA относится не к устройствам, а к томам?). На learn.microsoft.com наверное это где-то есть, но, скажем, https://learn.microsoft.com/en-us/windows/win32/api/_fs/ - просто огромный плоский список всяких штук, о назначении которых без предварительного знания догадаться очень сложно.
Да.. тема мутная, а потому приходится искать истину только опытным путём. Когда-то я тоже читал файл таким образом, причём вполне успешно. Конкретных деталей сейчас не припомню, но общая картина вроде такая. Кластер обозвали логическим только потому, что во-первых адресация к тому Volume, а не к физ.диску как к более крупной единице. Поскольку через CreateFile() мы можем открывать тома, то логический превращается в физический. Во-вторых, при вызове FSCTL_GET_RETRIEVAL_POINTERS можно указывать стартовый кластер (аля точку отсчёта) в структуре STARTING_VCN_INPUT_BUFFER - нужно всегда сбрасывать его в нуль, иначе к результату нужно будет применять поправки, т.е. фактически кластер так-же становится логическим. Таким образом если открываем том и указываем стартовый кластер(0), то на выходе получаем физ.кластер. Остальное проблемы драйвера и он сам разберётся что там к чему. В общем случае двигаться нужно так.. 1. GetDiskFreeSpace() чтобы узнать кол-во секторов в одном кластере. 2. FSCTL_GET_RETRIEVAL_POINTERS с vcn=0, чтобы запросить инфу о кластерах файла. 3. Результат пункта(2) умножить на кол-во секторов пункта(1). 4. Открыть том через CreateFile() с обязательной шарой R/W. 5. Установить позицию для чтения SetFilePointer(), передав ей результат пункта(3). 6. ReadFile() для чтения секторов. 7. Если пункт(2) вернул фрагменты, то возврат к пункту(5).
Dmitry_Milk, о прямом чтении файлов с диска с учетом его геометрии я видел в какой-то из статей Marylin, ссылки на них собраны здесь
Marylin, Все это похоже на то, как было устроено еще в MS-DOS-овском FAT, когда были функции BIOS, позволяющие читать/писать сектор по логическому номеру. Но меня смущает тот факт, что много где пишется про то, что работа с носителями сейчас осуществляется через LBA (Logical Block Addressing). Вроде по сути похоже на логическую нумерацию секторов в томе, но я не уверен, что это одно и то же. В частности, везде, где говорится про особенности работы SSD-накопителей, везде фигурирует чтение/запись (и переотображение на разные физические участки контроллером SSD) именно этих блоков LBA, а не логическая нумерация секторов.
LBA этот тот-же сектор, просто не с 3-хмерной адресацией CHS, а линейной 0..N. Транслятор адресов в контроллёре диска сам преобразует линейную адресацию как нужно в зависимости от того, какого типа накопитель HDD или SSD.
А, ну то есть все-таки логическая (не цилиндр/сектор, а подряд целочисленная) нумерация секторов и LBA это разные названия одного и того же. Тогда действительно все понятно. Спасибо.
Dmitry_Milk, для тестов возьми редактор HxD, открой в нём том где лежит файл, и перейди к сектору, который вычислишь по результату FSCTL_GET_RETRIEVAL_POINTERS. Если файла там нет, значит где-то в расчётах ошибка. --- Сообщение объединено, 3 июн 2024 --- обычно в кластере 8-секторов = 4КБ. если от FSCTL_GET_RETRIEVAL_POINTERS ты получил кластер(200), то умножаешь его 8 и получаешь таким образом LBA(1600), который будет совпадать с номером сектора в HxD.
Спасибо, все получилось, через GetDiskFreeSpace() действительно получил всю нужную инфу, и по вычисленному смещению из "файла" информация соответствует содержимому файла. Правда для установки позиции надо использовать уже SetFilePointerEx() c 64-битной позицией (т.к. размер тома сейчас редко у кого бывает меньше 4 гигабайт ). Ну и возможно в скором времени размеры дисков могут перестать "влезать" в функцию GetDiskFreeSpace(). И если я не ошибаюсь, на замену ей придется использовать GetDiskSpaceInformation(), принимающую структуру с 64-битными полями (правда не проверял, т.к пока хватает размеров GetDiskFreeSpace).