Как узнать состояние лотка CD-ROM
В комментариях к моей статье про управление лотком CD-ROM был задан правильный вопрос про то, как узнать состояние лотка CD-ROM, открыт он или закрыт. Обычно все программы, управляющие лотками CD-ROM, хранили эту информацию на основании своих последних действий. То есть, если программа открыла лоток привода, то в своем внутреннем массиве данных она ставит признак "открыто" и наоборот. Причем этот статус вполне мог не соответствовать реальному положению дел, если после этого лоток был закрыт или открыт вручную. Долгое время других способов определения статуса лотка CD-ROM не было. Но программист Александр (Rouse_) Багель в одной из своих разработок предложил хитрый способ определять реальное состояние лотка CD-ROM. Он заключается в том, чтобы отправить команду SCSIOP_MECHANISM_STATUS в запросе IOCTL_SCSI_PASS_THROUGH через функцию DeviceIoControl. Исходный пример был написан на Delphi, мне осталось его только перевести на Ассемблер.Для начала определим все необходимые структуры и константы, которых по умолчанию нет в FASM.
Code (Assembler) : Убрать нумерацию
- SCSI_IOCTL_DATA_IN = 1
- SCSIOP_MECHANISM_STATUS = 0BDh
- IOCTL_SCSI_PASS_THROUGH = 4D004h
- struct SCSI_PASS_THROUGH_DIRECT
- Length dw ?
- ScsiStatus db ?
- PathId db ?
- TargetId db ?
- Lun db ?
- CdbLength db ?
- SenseInfoLength db ?
- DataIn dd ?
- DataTransferLength dd ?
- TimeOutValue dd ?
- DataBuffer dd ?
- SenseInfoOffset dd ?
- Cdb rb 16
- ends
- struct SCSI_PASS_THROUGH_DIRECT_BUFFER
- Header SCSI_PASS_THROUGH_DIRECT
- SenseBuffer rb 20h
- DataBuffer rb 0C0h
- ends
Как вы помните из предыдущего примера работы с DeviceIoControl, путь к дисководу должен быть прописан в полном формате, например, "\\.\E:"
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- path db '\\.\E:',0 ; Полное имя CD-ROM
- tmp dd ? ; Временная переменная для DeviceIoControl
- tscbuff SCSI_PASS_THROUGH_DIRECT_BUFFER
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Получить хэндл диска
- invoke CreateFile,path,GENERIC_WRITE or GENERIC_READ,\
- FILE_SHARE_READ or FILE_SHARE_WRITE,\
- NULL,OPEN_EXISTING,NULL,NULL
- mov ebx,eax
- ; Заполнить структуру SCSI_PASS_THROUGH_DIRECT_BUFFER
- mov [tscbuff.Header.Length],sizeof.SCSI_PASS_THROUGH_DIRECT
- mov [tscbuff.Header.CdbLength],12
- mov [tscbuff.Header.DataIn],SCSI_IOCTL_DATA_IN
- mov [tscbuff.Header.DataTransferLength],0C0h
- mov [tscbuff.Header.TimeOutValue],10
- lea eax,[tscbuff.DataBuffer]
- sub eax,tscbuff
- mov [tscbuff.Header.DataBuffer],eax
- mov byte [tscbuff.Header.Cdb+0],SCSIOP_MECHANISM_STATUS
- mov byte [tscbuff.Header.Cdb+8],8
- ; Запросить информацию о состоянии лотка CD-ROM
- invoke DeviceIoControl,ebx,IOCTL_SCSI_PASS_THROUGH,tscbuff,\
- 10Ch,tscbuff,10Ch,tmp,NULL
- ; 12-й бит буфера результата содержит состояние лотка
- mov al,[tscbuff.DataBuffer+1]
- and al,10h
- ; AL = 1 - лоток открыт
- ; AL = 0 - лоток закрыт
В приложении пример программы, которая проверяет статусы всех имеющихся в системе приводов CD-ROM и выводит для каждого из них состояние его лотка.
Просмотров: 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-приводом тоже работает.
Добавить комментарий
Заполните форму для добавления комментария