Доступ посредствомчерез SCSI-порта
Как уже говорилось ранеевыше (см. разд. "Доступ посредствомчерез SPTI" этой главы), независимо от физического интерфейса дискового накопителя (SCSI или IDE) мы можем взаимодействовать с ним посредствомчерез унифицированногоый SCSI-интерфейса. Другими словами, драйвер конкретного устройства (и привода CD-ROM, в частности) полностью абстрагирован от особенностей реализации шинного интерфейса данного устройства. Даже если завтра появится накопители, работающие через инфракрасный порт, драйвер CDROM.SYS ничего об этом не "узнает" и будет по прежнемупо-прежнему управлять ими через SCSI-порт.
Даже если на вашем компьютере не установлено ни одного SCSI-контролера, пара-тройка вполне работоспособных SCSI-портов у вас обязательно есть. Конечно, это виртуальные, а не физические порты, но с точки зрения программного обеспечения они выглядят точь-в-точь как настоящие. Попробуйте с помощью функции CreateFile отрыть устройство "\\.\SCSI0:", и оно успешно откроется, подтверждая наличие существования виртуальных SCSI-портов (только не забудьте про двоеточие на конце). Посылая определенные IOCTL-команды SCSI-порту, мы можем управлять подключенным к этому порту физическим или виртуальным устройством. Да! Между SCSI-портом (виртуальным) и интерфейсной шиной (физической) расположен еще один уровень абстракции, занимаемый SCSI-мини- портом интерфейса SCSI, который, собственно, и "отвязывает" драйвер SCSI-порта от конкретного физического оборудования (подробнее см. разд. "Доступ посредствомчерез SCSI мини- порта SCSI" этой главы).
Естественно, прежде чем посылать IOCTL-команды в SCSI-порт, неплохо бы узнать, какое именно оборудование к этому порту подключено. Существует множество способов решения этой проблемы: от послать устройству команду идентификации IOCTL_SCSI_GET_INQUIRY_DATA (см. исходный текст демонстрационного примера в NT DDK ""NTDDK\src\storage\class\spti"), и тогда оноо (устройство) среди прочей информации сообщит нам, как его наименованиезовут (например,типа "PHILIPS CDRW2412A"), до заглянуть в таблицу объектов, чем мы сейчас и займемся.
В состав NT DDK входит утилита objdir.exe, которая, как и следует из ее названия, позволяет отображать содержимое дерева объектов в виде каталогадиректории. Устройства, доступные для открытия функцией CreateFile, хранятся в каталоге с довольно нелепым именем "\DosDevices\", глядя на которое можно подумать, что оно содержит имена устройств, видимых из-под MS-DOS, котороюкоторую Windows NT вынуждена эмулировать для сохранения обратной совместимости. На самом же деле этот каталог активно используется подсистемой win32-подсистемой операционной системы Windows NT, и всякий раз, когда функция CreateFile обращается к тому или иному логическому устройству (например, пытается открыть файл "C:\MYDIR\myfile.txt"), подсистема Win32 обращается к каталогу "\DosDevices\" чтобы выяснить, с каким именно внутренним устройством это логическое устройство связано. Внутренние устройства видны лишь из-под Native-NT, а для всех ее подсистем они лишены всякого смысла. В частности, диск "С:" под Native-NT именуетсязовется как "\Device\HarddiskVolume1", а полный путь к файлу myfile.txt выглядит так: "\Device\HarddiskVolume1\MYDIR\myfile.txt". Только не пытайтесь "скормить" эту строчку функции CreateFile –— она скорее "поперхнется", чем "поймет", что же от нее хотят.
Таким образом, каталог "\DosDevices\" служит своеобразным связующим звеном между подсистемой win32 и ядром системы Windows NT. Вот и давайте, в плане "возращения к нашим баранам", посмотрим с каким native-устройством ассоциировано логическое устройство с именем "SCSI". Запустив утилиту objdir с ключом "\Dos\Devices" и не забыв перенаправить весь вывод в файл ("objdir \DosDevices | MORE" –— как альтернативный результат), мы среди "моря" прочей информации обнаружим следующие строки (при отсутствии DDK можно воспользоваться отладчиком Soft-Ice в котором для достижения аналогичного результата следует набрать команду "objdir \??", –— именно так! Здесь имеется два знака вопроса, поскольку каталогдиректория \DosDevices на самом деле никакойая не каталогдиректория, а символическая ссылка на каталогдиректорию \?? или, если так угодно, ее ярлык).
В листинге 1.4.15 показан пример взаимосвязи SCSI-устройств с native-устройствами.:
Листинг 2.1.4.15. Взаимосвязь логических SCSI-устройств с native-NT устройствами
Scsi0: SymbolicLink - \Device\Ide\IdePort0
Scsi1: SymbolicLink - \Device\Ide\IdePort1
Scsi2: SymbolicLink - \Device\Scsi\axsaki1
Оказывается, устройства Scsi0: и Scsi1: представляют собой ни что иное, как символические ссылки на IDE-порты с номерами 0- и 1- соответственно. Впрочем, устройства с именами IdePort0 и IdePort1 не являются IDE-портами в физическом смысле этого слова. Это виртуальные SCSI-порты, создаваемые драйвером ATAPI.SYS в процессе его инициализации. Он же создает символические связи с устройствами с именами "\DosDevices\SCSI0:" и "\DosDevices\SCSI1:" к ним, а также ярлыки "\Device\ScsiPort0" и "\Device\ScsiPort1", недоступные подсистеме win32, но предназначенные для внутреннего использования исключительно на уровне драйверов. Разумеется, драйвер ATAPI.SYS не только создает все ранее вышеперечисленные устройства, но и обслуживает их, предоставляя драйверам более высоких уровней унифицированный интерфейс для взаимодействия с установленным оборудованием.
А вот устройство с именем "Scsi2:" ни с какими физическими шинами вообще не связно, и к соответствующему ему SCSI-порту подключен виртуальный привод CD-ROM, создаваемый программой Alcohol 120%, а точнее ее драйвером –— AXSAKI.SYS! ДрайвераДрайверыа высокого уровня (в частности, драйвер CDROM.SYS), не заподозрив никакого подвоха, будут работать с виртуальным диском точно так же как и с настоящим, что, собственно, и не удивительно, т. к. концепция SCSI-порта обеспечивает независимость драйверов верхнего уровня от особенностей оборудования, с которым они, с позволения сказать, "работают". Именно поэтому под Windows NT так легко реализуются эмуляторы физических устройств!
Кстати, на счет авторов программы Alcohol 120%.
Посмотрите, что удается обнаружить При ее дизассемблировании драйвера AXSAKI.SYS (программы Alcohol 120%) в листинге обнаруживаются нецензурные выражения.:
Листинг 2.16. Фрагмент дизассемблерного листинга драйвера AXSAKI.SYS
.text:000239EC aDf394b_tmp db 'df394b.tmp',0
.text:000239F7 a08lx_256 db '%08lx.256',0
.text:00023A01 a08lx_016 db '%08lx.016',0
.text:00023A0B aGandoniEbanie_ db 'ГАНДОНЫ ЕБАНЫЕ!_SetVectors_If32@16',0
.text:00023A2E a0x02x0x02x0x02 db '0x%02X, 0x%02X, 0x%02X, ',0
.text:00023A47 aLaunchingProdu db 'Launching Product',0
.text:00023A59 aSAfjklIwww2312 db '%s afjkl;iwww23120x%s%sas%s%ss%',0
Управлять SCSI-устройствами можно и с прикладного уровня посредствомчерез интерфейса STPI-интерфейс, однако вместо буквенного имени привода следует задавать имя SCSI-порта, к которому этот привод подключен. Основное достоинство такого способа управления заключается в том, что для взаимодействия с приводом совершенно необязательно обладать правами администратора! Привилегий простого смертного пользователя будет более чем достаточно. К тому же, прямая работа со SCSI-портом несколько производительнее взаимодействия с устройством через длинную цепочку драйверов верхнего уровня многочисленных фильтров, окружающих их.
Однако все попытки передачи SRB-блока посредствомчерез SCSI-порта заканчиваются неизменной ошибкой. Следующий код (листинг 1.4.16) наотрез отказывается работать. Почему?
Листинг 2.1.4.1617. Пример неправильной работы с виртуальным SCSI-портом
// получаем дескриптор SCSI-порта
hCD = CreateFile ("\\\\.\\SCSI1", GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
// ФОРМИРУЕМ SRB-блок
…
// ОТПРАВЛЯЕМ SRB-блок непосредственно на SCSI-порт
status = DeviceIoControl(hCD, IOCTL_SCSI_PASS_THROUGH_DIRECT, &srb,
sizeof(SCSI_PASS_THROUGH), &srb, 0, &returned, FALSE);
Зарубежные телеконференции буквально кишат вопросами на этот счет, –— у одних этот код исправно работает, а других –— нет (и их большинство).
А ответ, между тем, находится в DDK (если, конечно, читать его сверху вниз, а не наискосок по диагонали). Вот, пожалуйста, цитата из раздела 9.2 SCSI Port I/O Control Codes: "If a class driver for the target type of device exists, the request must be sent to that class driver. Thus, an application can send this request directly to the system port driver for a target logical unit only if there is no class driver for the type of device connected to that LU"[5]
("Если класс-драйвер для целевого устройства установлен, управляющие запросы должны посылаться класс-драйверу, но не самому порту устройства. Таким образом, приложения могут посылать непосредственные запросы драйверу системного порта для целевых логических устройств только если класс-драйвер для соответствующего типа устройств, подключенных к данному LU[Y120] [n2k121] , не установлен"). В переводе на нетехнический язык, непосредственное управление портом с прикладного уровня возможно для тех и только тех
устройств, чей класс-драйвер не установлен. Скажем, если вы подключили к компьютеру какую-то нестандартную "железяку", то управлять ей напрямую посредствомчерез SCSI-порта вполне возможно (ведь класс-драйвера для нее нет!). Но приводы CD-ROM, про которые мы собственно и говорим, –— совсем иное дело! Класс-драйвер для них всегда установлен и потому операционная система всячески препятствует прямому взаимодействую с оборудованием посредствомчерез SCSI-порта, поскольку это единственный надежный путь избежать конфликтов.
Выходит, доступ к приводам посредствомчерез SCSI-порта невозможен? И так, и не так! Прямой доступ к SCSI-порту действительно блокируется системой, но та же самая система предоставляет возможность управления устройством посредствомчерез мини-порта интерфейса SCSI-мини порт. Мини- порт? Что это такое?! А вот воб этом мы сейчас и разберемсярасскажем!
Рис. 2.1.4.65. 0х036 Архитектура подсистемы ввода/вывода в Windows NT[Y122]