Техника защиты компакт-дисков от копирования

Доступ посредствомчерез мини-порта интерфейса SCSI-мини порт


Драйвер SCSI-мини- порта интерфейса SCSI и есть тот самый драйвер, за счет которого системе удается абстрагироваться от особенностей физических интерфейсов конкретного оборудования. Условимся для краткости называть его просто "мини-драйвером", хотя это будет и не совсем верно, поскольку, помимо SCSI-мини-портов интерфейса SCSI, существуют драйверадрайверыа для видео и сетевых мини- портов. Однако поскольку ни те, ни другие к рассматриваемому нами контексту ни коим боком не относятся, то никаких разночтений и не возникает.

Иерархически драйвер мини- порта располагается между физическими (виртуальными) устройствами, подключенными к тем или иным интерфейсным шинам компьютера (IDE/PCI/SCSI) и драйвером SCSI-порта. Драйвер мини- порта представляет собой системно-независимый драйвер, но в то же время зависимый от специфики конкретных HBA (Host Bus Adapter), то есть того самого физического/виртуального оборудования, которое он обслуживает. Драйвер мини- порта экспортирует ряд функций семейства ScsiPortXXX, предназначенных для использования драйверами верхних уровней, и обычно реализуется как динамическая библиотека (то есть DLL), естественно, исполняющийся в нулевом кольце "ядерного" уровня.

Именно он транслирует SCSI-запросы в команды подключенного к нему устройства, именно он создает виртуальные SCSI-порты с именами типа "\Device\ScsiPortx", именно он обеспечивает поддержку накопителей с физическими интерфейсами, отличными от SCSI-интерфейса. Драйвер ATAPI.SYS, обслуживающий приводы CD-ROM приводы с ATAPI-интерфейсом, драйвер DISK.SYS, обслуживающий жесткие диски, –— все они реализованы как драйверадрайверы мини- порта.

Управление мини- портом осуществляется посредством специального IOCTL-кода, передаваемого функции DeviceIoControl и определенного в файле NTDDSCSI.H как IOCTL_SCSI_MINIPORT. Если же у вас нет NT DKK, то вот его непосредственное значение: 0x4D008. Естественно, прежде чем вызывать функцию DeviceIoControl, соответствующий SCSI-порт должен быть заблаговременно открыт функцией CreateFile.
Это может выглядеть, например, так как это показано в листинге 1.4.17. Причем обратите внимание на то, что имя порта должно выглядеть как SCSIx:, а не как ScsiPortx; причем в его конце обязательно должен присутствовать символ двоеточия, иначе ничего не получится.

:

Листинг 2.1.4.1187. Открытие SCSI-порта для управления драйвером мини-порта. Причем обратите внимание: имя порта должно выглядеть как "SCSIx:", но не как "ScsiPortx"; причем в его конце обязательно должен присутствовать символ двоеточия, иначе ничего не получится

h = CreateFile("\\\\.\\SCSI1:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ |

            FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 0, NULL);

Здесь мы открываем первый, считая от нуля, SCSI-порт, который, как мы уже знаем, соответствует первому каналу IDE или, другими словами, Secondary IDE-контроллеру (на компьютере автора привод CD-ROM "висит" именно на нем). Для определения расположения приводов на неизвестном нам компьютере можно воспользоваться IOCTL-кодом IOCTL_SCSI_GET_INQUIRY_DATA, который заставит драйвер мини- порта перечислить все имеющеесяимеющееся в его наличии оборудование, после чего нам останется только определить его тип (подробнее см. "NTDDK\SRC\STORAGE\CLASS\SPTI[Y123] [n2k124] ").

Однако управление мини- портом осуществляется совсем не так, как SCSI-портом! На этом уровне никаких стандартных команд уже не существует, и мы вынуждены работать с учетом специфики и особенностей реализации конкретного оборудования. Вместо SRB-запросов, мини-драйверу передается структура SRB_IO_CONTROL, обеспечивающая управление драйвером мини-порта и определенная следующим образом (листинг 1.4.18).:

Листинг 2.1.4.1198. Назначение полей структуры SRB_IO_CONTROL, обеспечивающей управление драйвером мини-порта



typedef struct _SRB_IO_CONTROL

{

      ULONG HeaderLength;         // sizeof(SRB_IO_CONTROL)

      UCHAR Signature[8];         // сигнатура мини-драйвера



      ULONG Timeout;              // макс. время ожидания выполнения запроса в сек

      ULONG ControlCode;          // код команды

      ULONG ReturnCode;           // здесь нам вернут статус завершения

      ULONG Length;               // длина всего передаваемого буфера целиком

} SRB_IO_CONTROL, *PSRB_IO_CONTROL;

Ну, с полем HeaderLength все более или менее ясно, но вот что эта за сигнатура такая?! Дело в том, что коды управления драйверами мини-порта не стандартизованы и определяются непосредственно самим разработчиком данного драйвера, а потому коды команд одного драйвера навряд ли подойдут к другому. Вот во избежание междоусобных конфликтов каждый драйвер мини- порта и содержит уникальную сигнатуру, которую тщательно сверяет с сигнатурой переданной приложением в поле Signature структуры SRB_IO_CONTROL. И, если эти сигнатуры не совпадают, драйвер "отвечает": SRB_STATUS_INVALID_REQUEST, указывая на ошибку запроса. (типа, отвали, моя черешня). К сожалению, интерфейс штатных мини-драйверов ATAPI.SYS и DISK.SYS абсолютно незадокументирован, и, если вы не умеете дизассемблировать, то вам остается лишь посочувствовать. Дизассемблер же сразу показывает, что сигнатуры обоих драйверов выглядят как "SCSIDISK", а сигнатура мини-драйвера от Alcohol 120% –— "Alcoholx" (впрочем, последний, в силу своей нештатности, не представляет для нас особенного интереса).

С кодами команды разобраться сложнее. Правда, специалистыспециалисты, постоянно читающие MSDN, и потому неплохо в нем ориентирующиеся, вероятно, смогут вспомнить, что: "…this specification describes the API for an application to issue SMART commands to an IDE drive under Microsoft Windows  95 and Windows  NT. Under Windows  95, the API is implemented in a Vendor Specific Driver (VSD), Smartvsd.vxd. SMART functionality is implemented as a "pass through" mechanism whereby the application sets up the IDE registers in a structure and passes it to the driver through the DeviceIoControl API" ("…эта спецификация описывает интерфейс API [n2k125] для приложений, передающих SMART-команды жестким дискам с IDE-интерфейсомв под Microsoft Windows  95 и Windows NT.


Под Windows 95 API реализовано в драйвере, специфичном для конкретного производителя (VSD –— Vendor Specific Driver), называемом Smartvsd.vxd. SMART-функциональность реализована как "pass through"-механизм, посредством которого приложения устанавливают IDE-регистры, передавая их драйверу через специальную структуру, помещаемую во входной буфер функции DeviceIoControl ").

Примечание

SMART (Self-Monitoring Analysis and Reporting Technology) — технология самоконтроля и составления диагностических отчетов, направленная на активное конролирование за состоянием узлов диска. Поддерживается рядом производителей дисков и позволяет утилитам диагностировать их состояние. [n2k126] 

Ага! Один из драйверов позволяет нам манипулировать регистрами IDE-контроллера по своему усмотрению, то есть фактически предоставляет низкоуровневый доступ к диску! Очень хорошо! Интерфейс со SMART-драйвером достаточно хорошо документирован (см[Y127] [n2k128] . "MSDN à Specifications à Platforms à SMART IOCTL API Specification"), правда, раздражает "гробовое молчание" насчет Windows NT. То, что в NT никаких драйверов VxD нет –— это и "ежу ясно". Но в то же время заявляется, что технология SMART  API в ней как будто бы реализована… Если напрячь свои мозги и проявить чудеса интуиции, можно догадаться, что поддержка SMART в NT обеспечивается штатными средствами! Весь вопрос в томтом,: какими именно средствами и как? Ни SDK, ни DDK не содержат никакой информации на этот счет, но вот копание в заголовочных файлахов из комплекта NT DDK может кое-что дать! Посмотрите, что обнаруживается в файле scsi.h при тщательном его изучениипросмотре (листинг 1.4.19). Здесь представлены команды управления технологией SMART в Windows NT, которые мы можем передавать драйверу мини-порта через поле ControlCode структуры SRB_IO_CONTROL. :

Листинг 2.1.4.2019. Команды управления SMART в Windows NT, которые мы можем передавать драйверу мини-порта через поле ControlCode структуры SRB_IO_CONTROL



//

// SMART support in atapi

//

#define IOCTL_SCSI_MINIPORT_SMART_VERSION           ((FILE_DEVICE_SCSI<<16)+0x0500)

#define IOCTL_SCSI_MINIPORT_IDENTIFY                ((FILE_DEVICE_SCSI<<16)+0x0501)

#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS      ((FILE_DEVICE_SCSI<<16)+0x0502)

#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS   ((FILE_DEVICE_SCSI<<16)+0x0503)

#define IOCTL_SCSI_MINIPORT_ENABLE_SMART            ((FILE_DEVICE_SCSI<<16)+0x0504)

#define IOCTL_SCSI_MINIPORT_DISABLE_SMART           ((FILE_DEVICE_SCSI<<16)+0x0505)

#define IOCTL_SCSI_MINIPORT_RETURN_STATUS           ((FILE_DEVICE_SCSI<<16)+0x0506)

#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE ((FILE_DEVICE_SCSI<<16)+0x0507)

#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES   ((FILE_DEVICE_SCSI<<16)+0x0508)

#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS   ((FILE_DEVICE_SCSI<<16)+0x0509)

#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE

(FILE_DEVICE_SCSI<<16)+0x050a

Нет сомненияОторви Тиггеру хвост, чтоесли в Windows NT функциональность SMART реализуется не в драйвере мини- порта! И дизассемблирование драйвера ATAPI.SYS действительно подтверждает это! Вот вам и качество документации от Microsoft, –— уродство сплошное в стиле маразм крепчает. Какой смысл включать в заголовочный файл IOCTL-команды, но не документировать их?! Причем согласно лицензии дизассемблирование любых компонентов операционной системы запрещено. Ладно, не будемт скулить по поводу и без, а лучше еще раз перечитаем [Y129] [n2k130] "SMART IOCTL API Specification", откуда поймем, что для управления драйвером мини- порта под Windows NT в поле ControlCode структуры SRB_IO_CONTROL мы должны передать код одной из приведенных выше команд. Пусть это будет, например, IOCTL_SCSI_MINIPORT_IDENTIFY.

Сразу же за концом структуры SRB_IO_CONTROL должна быть расположена структура SENDCMDINPARAMS, дающая прямой доступ к IDE-регистрам и, определенная как это показано в листинге 1.4.20.следующим образом:



Листинг 2.1.4.2120.  Структура SENDCMDINPARAMS, дающая прямой доступ к IDE-регистрам

typedef struct _SENDCMDINPARAMS

{

     DWORD        cBufferSize;     // размер буфера в байтах или нуль

     IDEREGS      irDriveRegs;     // структура, содержащая значение IDE-регистров

     BYTE         bDriveNumber;    // физический номер диска, считая от нуля

     BYTE         bReserved[3];    // зарезервировано

     DWORD        dwReserved[4];   // зарезервировано

     BYTE         bBuffer[1];      // отсюда начинается входной буфер

} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;

То есть входной буфер функции DeviceIoControl должен выглядеть как на рисунке 1.4.6. так:

Рис. 2.1.4.76. 0x038 Структура входного буфера функции DeviceIoControl для управления драйвером мини- порта под Windows 9x/NT

Первый элемент структуры –— cBufferSize, содержащий размер буфера bBuffer'a слишком очевиден и не интересен. А вот структура IDREGS обеспечивает низкоуровневый доступ к IDE-регистрам и представляет собой настоящий клад., Вот взгляните сами (листинг 1.4.21), (только не упадите со стула, ибо потрясение будет столь же острым, сколь и глубоким).:

Листинг 2.1.4.2221. Структура IDEREGS, предоставляющая низкоуровневый доступ к IDE-регистрам

typedef struct _IDEREGS

{

      BYTE bFeaturesReg;       // IDE Features-регистр

      BYTE bSectorCountReg;    // IDE SectorCount-регистр

      BYTE bSectorNumberReg;   // IDE SectorNumber-регистр

      BYTE bCylLowReg;         // IDE CylLowReg-регистр

      BYTE bCylHighReg;        // IDE CylHighReg-регистр

      BYTE bDriveHeadReg;      // IDE DriveHead-регистр

      BYTE bCommandReg;        // командный регистр

      BYTE bReserved;          // зарезервировано

} IDEREGS, *PIDEREGS, *LPIDEREGS;

Всякий, кто читал спецификацию на ATA/ATAPI (Advenced Technology Attachment/ Advenced Technology Attachment Packet Interface)[n2k131]  и хоть однажды сталкивался с программированием устройств с интерфейсом IDE, должен немедленно узнать до боли знакомые регистры Command, Drive/Head, Cylinder High, Cylinder Low, Sector Number, Sector Count и Features, правда, в структуре IDEREGS они перечислены почему-то в обратном порядке, но это уже мелочи реализации.


Главное, что с помощью этой структуры мы можем проделыватьвытворять с приводом все мыслимые и немыслимые фокусы, на которые только способно "железо". Даже не верится, что в подсистеме безопасности существует такая "дыра" размерами со "слонопотама". И это при том, что для управления мини- портом наличие прав администратора совсем не обязательно! Дрожа и подпрыгивая от нетерпения, наскоро заполняем оставшиеся поля структуры SENDCMDINPARAMS, как-то: bDriveNumber –— физический номер привода, считая от нуля и буфер для передачи данных.

Внимание

Именно буфер, а не указатель на что-то..[n2k132] 

Но ведь мы пока не собираемся записывать никаких данных на диск, верно? Вот и оставим это поле пустым.

Увы! При попытке "скормить" приводу команду, отличную от команд семейства SMART, нас постигает глубокое разочарование, ибо драйвер мини- порта "далеко не дурак" и проверяет содержимое структуры IDEREGS перед ее передачей IDE-приводу. Исключение составляет лишь команда идентификации накопителя (drive)драйва, –— 0xEC, о чем Microsoft прямо и заявляет "There are three IDE commands supported in this driver, ID (0xEC), ATAPI ID (0xA1), and SMART (0xB0). The "subcommands" of the SMART commands (features register values) are limited to the currently defined values (0xD0 through 0xD6, 0xD8 through 0xEF). SMART subcommand 0xD7, write threshold value, is not allowed. Any other command or SMART subcommand will result in an error being returned from the driver. Any SMART command that is not currently implemented on the target drive will result in an ABORT error from the IDE interface" ("Только три IDE-команды поддерживаются этим драйвером: ID (код 0xEC), ATAPI ID (0xA1) и SMART (0xB0). "Подкоманды" базовой команды SMART (передаваемые через feature-регистр), ограничены лишь теми значениями, которые специфицированы на настоящий момент: от 0xD0 до 0xD6 и от 0xD8 до 0xEF. Использование подкоманды с кодом 0xD7, записывающей пороговое значение SMART, заблокировано.


Любые другие команды и подкоманды будут игнорироваться драйвером, и возвращать сообщение об ошибке. Любые SMART-команды, что не реализованы на текущий момент, в целевом приводе будует возвращать ABORT-ошибку").

Кажется, что это полный провал, но нет! Ведь эту проверку в принципе можно и отключить! Давайте дизассемблируем драйвер ATAPI.SYS (листинг 1.4.22), отвечающий за проверку передаваемых IDE-команд на соответствие принадлежности к "белому" списку, и посмотрим, что мы можем сделать.

Листинг 2.1.4.2322. Фрагмент дизассемблерного листинга драйвера ATAPI.SYS, отвечающий за проверку передаваемых IDE-команд на соответствие принадлежности к "белому" списку.

.text:00013714 aScsidisk      db 'SCSIDISK',0      ; DATA XREF: SCSI_MINIPORT+CCvo

; вот она наша сигнатура          ^^^^^^^^

;

.text:000137DF

.text:000137DF  loc_137DF:               ; CODE XREF: SCSI_MINIPORT+B5^j

.text:000137DF  mov    [edi], ebx

.text:000137E1  mov    eax, [ebx+18h]

.text:000137E4  push   8                 ; длина сравниваемой строки

.text:000137E6  add    eax, 4

.text:000137E9  push   offset aScsidisk  ; эталонная сигнатура

.text:000137EE  push   eax               ; сигнатура, переданная приложением

.text:000137EF  call   ds:RtlCompareMemory; сигнатуры совпадают?

.text:000137F5  cmp    eax, 8

.text:000137F8  jnz    loc_13898         ; нет, не совпадают, сваливаем отсюда

.text:000137F8

.text:000137FE  mov    esi,[ebx+18h]

.text:00013801  mov    eax,[esi+10h]     ; извлекаем ControlCode

.text:00013804  cmp    eax, 1B0500h      ; IOCTL_SCSI_MINIPORT_SMART_VERSION

.text:00013809  jz     loc_1389F         ; à обработка …SMART_VERSION

.text:0001380F  mov    ecx, 1B0501h      ; IOCTL_SCSI_MINIPORT_IDENTIFY

.text:00013814  cmp    eax, ecx          ;

.text:00013816  jz     short loc_1382D   ; à

обработка …IDENTIFY

.text:00013818  jbe    short loc_13898   ; IF ControlCode < IDENTIFY THEN на выход

.text:0001381A  cmp    eax, 1B050Ah      ; IOCTL_SCSI_MINIPORT_ENABLE_DISABLE…



.text:0001381F  ja     short loc_13898   ; IF ControlCode > ENABLE_DISAB… на выход

.text:00013821  push   ebx               ;

.text:00013822  push   edi               ;

.text:00013823  call   sub_12412         ; обрабатываем остальные SMART-команды

.text:00013828  jmp    loc_1393E

.text:0001382D  ; -----------------------------------------------------------

.text:00012412  sub_12412    proc near   ; CODE XREF: SCSI_MINIPORT+106vp



.text:00012433  cmp   [ebp+var_1E], 0B0h ; SMART-command

.text:00012437  jnz   loc_12633          ; если это не SMART, то выходим

.text:00012437  ; отсюда начинаются проверки

.text:0001243D  movzx  eax, [ebp+var_1C]

.text:00012441  mov    eax, [ebx+eax*4+0B0h] ; загружаем Drive/Head-регистр в EAX

.text:00012448  test   al, 1              ; сравниваем младший бит AL с единицей

.text:0001244A  jz     loc_1262F          ; если младший бит равен нулю, выходим

.text:00012450  test   al, 2              ; сравниваем следующий бит AL с единицей

.text:00012452  jnz    loc_1262F          ; если он не равен нулю, то выходим

.text:00012458  mov    al, [ebp+var_24]   ; загружаем Feature-регистр в AL

.text:0001245B  cmp    al, 0D0h           ; это SMART READ DATA?

.text:0001245D  mov    [ebx+0CCh], al           

.text:00012463  jz     loc_12523          ; если да, то переходим к его обработке

.text:00012469  cmp    al, 0D1h           ; это Obsolete?

.text:0001246B  jz     loc_12523          ; если да, то переходим к его обработке

.text:00012471  cmp    al, 0D8h           ; это SMART ENABLE OPERATIONS?

.text:00012473  jz     short loc_12491    ; если да, то переходим к его обработке

.text:00012475  cmp    al, 0D9h           ; это SMART DISABLE OPERATIONS?

.text:00012477  jz     short loc_12491    ; если да, то переходим к его обработке

.text:00012479  cmp    al, 0DA            ; это SMART RETURN STATUS?

.text:0001247B  jz     short loc_12491    ; если да, то переходим к его обработке

.text:0001247D  cmp    al, 0D2h           ; это SMART ENBL/DSBL ATTRIBUTE AUTOSAVE?



.text:0001247D  cmp    al, 0D2h           ; процессор, ты не ошибся в натуре?!

.text:0001247F  jz     short loc_12491    ; если да, то переходим к его обработке

.text:00012481  cmp    al, 0D4h           ; это SMART EXECUTE OFF-LINE IMMEDIATE?

.text:00012483  jz     short loc_12491    ; если да, то переходим к его обработке

.text:00012485  cmp    al, 0D3h           ; это SMART SAVE ATTRIBUTE VALUES?

.text:00012487  jz     short loc_12491    ; если да, то переходим к его обработке

.text:00012489  cmp    al, 0DBh           ; это SMART ENABLE OPERATIONS?

.text:0001248B  jnz    loc_12633          ; если нет, то сваливаем

.text:00012491

.text:00012491  loc_12491:                ; CODE XREF: sub_12412+61^j

.text:00012491  ; отсюда начинается обработка команд

.text:00012491  ;

.text:00012491  push   1

.text:00012493  pop    eax

.text:00012494  cmp    ds:0FFDF02C0h, eax

.text:0001249A  jnz    short loc_124A5

.text:0001249C  cmp    dword ptr [ebx+4], 640h

.text:000124A3  jz     short loc_124A7

.text:000124A5

.text:000124A5  loc_124A5:                ; CODE XREF: sub_12412+88^j

.text:000124A5  xor    eax, eax

.text:000124A7

.text:000124A7  loc_124A7:                ; CODE XREF: sub_12412+91^j

.text:000124A7  ; отсюда начинается запись в порт!

.text:000124A7  ;

.text:000124A7  mov    esi, ds:WRITE_PORT_UCHAR

.text:000124AD  test   al, al

.text:000124AF  jz     short loc_124C0

.text:000124B1  mov    al, [ebp+var_1C]

.text:000124B4  shr    al, 1

.text:000124B6  and    al, 1

.text:000124B8  push   eax

.text:000124B9  push   432h

.text:000124BE  call   esi ; WRITE_PORT_UCHAR

 

Таким образом, чтобы разрешить драйверу отправлять IDE-приводу любые команды, мы должны удалить условный переход, расположенный по адресу 0х12437 (в листинге он выделен жирным шрифтом и обведенвзят прямоугольникомв квадратик) на безусловный переход, передающий управление на команду записи по адресу 0x12491. Только не забудьте после модификации драйвера скорректировать его контрольную сумму, что можно сделать, например, с помощью утилиты EDITBIN.EXE, входящей в состав Microsoft Visual Studio, иначе Windows NT наотрез откажется загружать такой "взломанный"хакнутый драйвер.



Разумеется, такую операцию допустимо проделывать только на своем собственном драйвере, поскольку всем остальным навряд ли понравится "дыра", проделанная в системе безопасности! К тому же, распространение модифицированного драйвера ATAPI.SYS вопиющим образом нарушает авторское право самой Microsoft со всеми вытекающими отсюда последствиями. Тем не менее, ваше приложение может безбоязненно "падчить" (patch) драйвер ATAPI.SYS непосредственно на компьютерах пользователей, естественно, запрашивая у них подтверждение на правомерность такой операции (или, на худой конец, должно быть выполненопросто упоминиеая этогот аспекта в сопроводительной документации).

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

Пример программы, приведенной в листинге 1.4.23ниже, как раз и демонстрирует передачу ATA-команд IDE-приводу посредствомчерез драйвера мини- порта.

Листинг 2.1.4.2423. [/etc/SCSI.mini-port.c] Пример программы, демонстрирующий технику взаимодействия со SCSI мини- портом интерфейса SCSI

int ATAPI_MINIPORT_DEMO(void)

{

    int     a;

    HANDLE  h;

    char    *buf;

    int     LU = 0;

    DWORD   returned;

    int     controller;

    char    ScsiPort [16];

    char    buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];

   

    SRB_IO_CONTROL  *p   = (SRB_IO_CONTROL  *) buffer;

    SENDCMDINPARAMS *pin = (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));

   

    // перебираем оба IDE-контроллера в цикле

    for (controller = 0; controller < 2; controller++)

    {

          // формируем ScsiPort для каждого из котроллеров

          sprintf (ScsiPort, "\\\\.\\Scsi%d:", controller);



   

          // открываем соответствующий ScsiPort

          h= CreateFile (ScsiPort,GENERIC_READ | GENERIC_WRITE,

               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,0);

  

          if (h == INVALID_HANDLE_VALUE) { // ЕСЛИ ПРОИЗОШЛА ОШИБКА - СВАЛИВАЕМ

               printf("-ERR:Unable to open ScsiPort%d\n",controller);return -1;

          }

         

          // перебираем оба устройства на каждом из IDE-контроллеров

          for (LU = 0; LU < 2; LU++)

          {

                // инициализируем входной буфер

                memset (buffer, 0, sizeof (buffer));

  

                // ПОДГОТАВЛИВАЕМ СТРУКТУРУ SRB_IO_CONTROL,

                // предназначенную для драйвера мини- порта

                p -> Timeout      = 10000;                     // ждать до черта

                p -> Length       = SENDIDLENGTH;              // макс. длина

                p -> HeaderLength = sizeof (SRB_IO_CONTROL);   // размер заголовка

                p -> ControlCode  = IOCTL_SCSI_MINIPORT_IDENTIFY;

                // ^^^ код команды, посылаемой драйверу

 

                // сигнатура. для ATAPI.SYS это "SCSIDISK"

                strncpy ((char *) p -> Signature, "SCSIDISK", 8);

 

                // ПОДГОТАВЛИВАЕМ СТРУКТУРУ SENDCMDINPARAMS,

                // содержащую ATA-команды, передаваемые IDE-приводу

                pin -> bDriveNumber                 = LU;

                pin -> irDriveRegs.bCommandReg      = IDE_ATA_IDENTIFY;

 

                // ПОСЫЛАЕМ УПРАВЛЯЮЩИЙ ЗАПРОС ДРАЙВЕРУ МИНИ- ПОРТА

                if (DeviceIoControl (h, IOCTL_SCSI_MINIPORT, buffer,

                sizeof (SRB_IO_CONTROL) + sizeof (SENDCMDINPARAMS) - 1,

                buffer, sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, &returned, 0))

                      if (buffer[98]!=0)

                      {// в ответ нам возвращается строка с идентификационным

                      // именем IDE-привода, которую мы и выводим на экран

                              for (a = 98; a < 136; a+=2 )

                              printf("%c%c",buffer[a+1],buffer[a]);

                              printf("\n");

                      }

         }

         CloseHandle (h); // закрыть дескриптор данного SCSI мини- порта

    }

    return 0;

}

Доступ через SMART-драйвер. (задел на будущее)


Содержание раздела