Tuesday, December 23, 2008

открываем файлы

Почему-то IFS DDK не достаточно освещает один забавный момент, связанный с восприятием реальности NT в области открытия файлов. Вообще, его стоило бы добавить к разделу "ZwCreateFile" или к разделу Using Files In A Driver".

Пусть у нас в системе есть некий виртуальный девайс-диск, например "\device\my_super_disk", и на него существует символическая ссылка "\DosDevices\X:".
Допустим он даже примаунчен, что значит, что к нему "снизу" присоединилось соответствующее устройство файловой системы (не то чтобы у них там какой-то "стек", на самом деле диск может, вобщем-то, и не знать, в каком он состоянии находится, ему это без разницы).

Так вот, как мне кажется, у пользователя существует целых ТРИ принципиально разных способа открытия файлов используя "\DosDevices\X". Пользователь может:
1) просто открыть файл, используя в качестве имени что-то вроде "\DosDevices\X:\MyDir\MyFile.txt". Все просто и хорошо изучено.
Что изучено плохо:
- если устройство не примаунчено, NT попытается его примаунтить прямо в месте вызова;
- если вызывать IoDeleteDevice на my_super_disk в процессе маунта, возможны bsod'ы из-за специфики реализации некоторых микрософтовских фильтров(sr.sys);
2) открыть устройство для "прямого" доступа. Делаем тот же ZwCreateFile, но используем в качестве имени "\DosDevices\X:", и, обязательно указываем FILE_READ_DATA в DesiredOptions(или любой другой "неизбранный" флаг - см ниже).
Тоже простой и хорошо изученный способ. Интересности:
- если устройство не примаунчено, NT тоже попытается его примаунтить прямо в месте вызова;
- несмотря на то что my_super_disk открыт вроде бы как "напрямую" (c) MSDN, запросы будут ходить через устройство файловой системы, со всеми вытекающими. Сможете послать ей чего-нибудь;
3) открыть устройство для "по-настоящему-прямого" доступа. Открываем файл примерно как в пункте 2, за исключением того, что в DesiredOptions не ставим никаких других флагов, кроме избранных: ACCESS_SYSTEM_SECURITY, FILE_READ_ATTRIBUTES, SYNCHRONIZE, READ_CONTROL, WRITE_OWNER, WRITE_DAC. Например, указываем только SYNCHRONIZE.
Интересности:
- если устройство не примаунчено, NT не будет пытается его примаунтить;
- если устройство и примаунчено, запросы все равно не будут заходить в файловую систему;
- у вашего файла будет pFileObject->FsContext будет равен 0;
- идеально подходит для того, чтобы пообщаться с my_super_disk напрямую.

Интересно, МСДН как бы намекает обо всем этом в описании IoGetDeviceObjectPointer:
"To get a pointer to the highest-level driver in the file system driver stack, a driver must ensure that the file system is mounted; if it is not, this routine traverses the storage device stack. To ensure that the file system is mounted on the storage device, the driver must specify an appropriate access mask, such as FILE_READ_DATA or FILE_WRITE_ATTRIBUTES, in the DesiredAccess parameter. Specifying FILE_READ_ATTRIBUTES does not cause the file system to be mounted. "
Но - уныло и поверхностно.

1 comment:

Alexander Babko said...

Вообще MSDN только на первых порах вызывает восхищение, когда начинаешь вдруг где либо копать глубже - он как и большинства других документаций становится унылым и поверхностным. может о таких ситуациях стоит писать аффторам ?