Blog. Just Blog

Как узнать состояние лотка CD-ROM

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
В комментариях к моей статье про управление лотком CD-ROM был задан правильный вопрос про то, как узнать состояние лотка CD-ROM, открыт он или закрыт. Обычно все программы, управляющие лотками CD-ROM, хранили эту информацию на основании своих последних действий. То есть, если программа открыла лоток привода, то в своем внутреннем массиве данных она ставит признак "открыто" и наоборот. Причем этот статус вполне мог не соответствовать реальному положению дел, если после этого лоток был закрыт или открыт вручную. Долгое время других способов определения статуса лотка CD-ROM не было. Но программист Александр (Rouse_) Багель в одной из своих разработок предложил хитрый способ определять реальное состояние лотка CD-ROM. Он заключается в том, чтобы отправить команду SCSIOP_MECHANISM_STATUS в запросе IOCTL_SCSI_PASS_THROUGH через функцию DeviceIoControl. Исходный пример был написан на Delphi, мне осталось его только перевести на Ассемблер.

Для начала определим все необходимые структуры и константы, которых по умолчанию нет в FASM.
  1. SCSI_IOCTL_DATA_IN      = 1
  2. SCSIOP_MECHANISM_STATUS = 0BDh
  3. IOCTL_SCSI_PASS_THROUGH = 4D004h
  4.  
  5. struct SCSI_PASS_THROUGH_DIRECT
  6.         Length             dw ?
  7.         ScsiStatus         db ?
  8.         PathId             db ?
  9.         TargetId           db ?
  10.         Lun                db ?
  11.         CdbLength          db ?
  12.         SenseInfoLength    db ?
  13.         DataIn             dd ?
  14.         DataTransferLength dd ?
  15.         TimeOutValue       dd ?
  16.         DataBuffer         dd ?
  17.         SenseInfoOffset    dd ?
  18.         Cdb                rb 16
  19. ends
  20.  
  21. struct SCSI_PASS_THROUGH_DIRECT_BUFFER
  22.         Header          SCSI_PASS_THROUGH_DIRECT
  23.         SenseBuffer     rb 20h
  24.         DataBuffer      rb 0C0h
  25. ends
Основные принципы работы с дисками через DeviceIoControl вы можете посмотреть по приведенной выше ссылке, здесь же я расскажу только о том, как определить статус лотка CD-ROM.

Как вы помните из предыдущего примера работы с DeviceIoControl, путь к дисководу должен быть прописан в полном формате, например, "\\.\E:"
  1. ; Сегмент данных
  2. section '.data' data readable writeable  
  3. path    db '\\.\E:',0     ; Полное имя CD-ROM
  4. tmp     dd ?              ; Временная переменная для DeviceIoControl 
  5.  
  6. tscbuff SCSI_PASS_THROUGH_DIRECT_BUFFER
  7.  
  8. ; Сегмент кода
  9. section '.code' code readable executable
  10.         ... 
  11.         ; Получить хэндл диска
  12.         invoke  CreateFile,path,GENERIC_WRITE or GENERIC_READ,\
  13.                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
  14.                 NULL,OPEN_EXISTING,NULL,NULL
  15.         mov     ebx,eax
  16.  
  17.         ; Заполнить структуру SCSI_PASS_THROUGH_DIRECT_BUFFER
  18.         mov     [tscbuff.Header.Length],sizeof.SCSI_PASS_THROUGH_DIRECT
  19.         mov     [tscbuff.Header.CdbLength],12
  20.         mov     [tscbuff.Header.DataIn],SCSI_IOCTL_DATA_IN
  21.         mov     [tscbuff.Header.DataTransferLength],0C0h
  22.         mov     [tscbuff.Header.TimeOutValue],10
  23.         lea     eax,[tscbuff.DataBuffer]
  24.         sub     eax,tscbuff
  25.         mov     [tscbuff.Header.DataBuffer],eax
  26.         mov     byte [tscbuff.Header.Cdb+0],SCSIOP_MECHANISM_STATUS
  27.         mov     byte [tscbuff.Header.Cdb+8],8
  28.  
  29.         ; Запросить информацию о состоянии лотка CD-ROM
  30.         invoke  DeviceIoControl,ebx,IOCTL_SCSI_PASS_THROUGH,tscbuff,\
  31.                 10Ch,tscbuff,10Ch,tmp,NULL
  32.  
  33.         ; 12-й бит буфера результата содержит состояние лотка
  34.         mov     al,[tscbuff.DataBuffer+1]
  35.         and     al,10h
  36.  
  37.         ; AL = 1 - лоток открыт
  38.         ; AL = 0 - лоток закрыт
Способ определения статуса лотка проверен и гарантированно работает с SATA-дисководами, CD-приводами ноутбуков и внешними CD-ROM, подключаемыми по USB. К сожалению, у меня нет возможности проверить работоспособность этого кода на IDE-приводах. Если у вас остался такой CD-ROM, то буду очень благодарен, если вы сообщите мне о результатах тестирования.

В приложении пример программы, которая проверяет статусы всех имеющихся в системе приводов CD-ROM и выводит для каждого из них состояние его лотка.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

CD-ROM.Status.Demo.zip (2,475 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 5819 | Комментариев: 5

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (29.09.2013 в 18:33):
Смех смехом, а ведь она действительно как-то определяет, что воткнуты именно наушники, а не колонки.
brute (29.09.2013 в 18:13):
ждем продолжения: "как седьмая винда определяет воткнутость колонок и наушников"
ManHunter (25.09.2013 в 09:04):
Aleksander, действительно, программа показывала только первый дисковод. Поправил, теперь должна показывать все. Еще проверил на ноутбучном дисководе, тоже работает. addhaloka, спасибо за тест!
Aleksander (25.09.2013 в 08:27):
Установлена UltraISO, виртуальный привод определяет как открытый, а  DVD-RW не видит
addhaloka (25.09.2013 в 08:12):
С IDE-приводом тоже работает.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0049 сек.) / Память: 4.5 Mb
Наверх