Аппаратное обеспечение персонального компьютера© Александр Фролов, Григорий ФроловТом 33, М.: Диалог-МИФИ, 1997, 304 стр. Программа CDINFOПрограмма CDINFO вызывает как функции расширения MSCDEX.EXE, так и драйвер устройства чтения CD-ROM, получая различную информацию как о расширении, так и о компакт-диске. Вот пример листинга, полученного при работе программы CDINFO на виртуальной машине DOS в среде Microsoft Windows 95: CDINFO, (c) A. Frolov, 1997 MSCDEX version: 2.95 Found 1 CD Unit, start unit: G CD-ROM letters: G Status of CD Drive G: 00000390 VolumeSize: 29460 blocks Tracks: (1 - 1) 8252 track 1: location: 512, info: 41 * digital, copy prohibited * Здесь в компьютере установлено только одно устройство чтения CD‑ROM, в котором находился один цифровой компакт-диск. Ниже мы представили листинг, полученный при аналогичных условиях на компьютере, оборудованном двумя устройствами чтения CD-ROM. В первое устройство (H:) был вставлен звуковой диск, а во второе (I:) - комбинированный диск с одной цифровой и тремя звуковыми дорожками: CDINFO, (c) A. Frolov, 1997 MSCDEX version: 2.21 Found 2 CD Unit, start unit: H CD-ROM letters: H I Status of CD Drive H: 00000390 VolumeSize: 302375 blocks Tracks: (1 - 15) 2866 track 1: location: 512, info: 01 * audio, copy prohibited * track 2: location: 79922, info: 01 * audio, copy prohibited * track 3: location: 466492, info: 01 * audio, copy prohibited * track 4: location: 788490, info: 01 * audio, copy prohibited * track 5: location: 1120281, info: 01 * audio, copy prohibited * track 6: location: 1453334, info: 01 * audio, copy prohibited * track 7: location: 1778979, info: 01 * audio, copy prohibited * track 8: location: 2042649, info: 01 * audio, copy prohibited * track 9: location: 2363412, info: 01 * audio, copy prohibited * track 10: location: 2565639, info: 01 * audio, copy prohibited * track 11: location: 2823479, info: 01 * audio, copy prohibited * track 12: location: 3094814, info: 01 * audio, copy prohibited * track 13: location: 3419404, info: 01 * audio, copy prohibited * track 14: location: 3740478, info: 01 * audio, copy prohibited * track 15: location: 4130306, info: 01 * audio, copy prohibited * Status of CD Drive I: 00000390 VolumeSize: 278505 blocks Tracks: (1 - 4) 13598 track 1: location: 512, info: 41 * digital, copy prohibited * track 2: location: 3282733, info: 01 * audio, copy prohibited * track 3: location: 3608079, info: 01 * audio, copy prohibited * track 4: location: 3801921, info: 01 * audio, copy prohibited * Заметим, что в среде виртуальной машины операционной системы Microsoft Windows NT эта программа показывает неверные результаты. Скорее всего это происходит из-за неправильной работы эмулятора расширения MSCDEX. Исходный текст программы CDINFO вы найдете в листинге 9.1. Листинг 9.1. Файл cdinfo\cdinfo.с // ===================================================== // Прсмотр различной информации об устройствах // чтения CD-ROM и компакт-дисках // с помощью интерфейса MSCDEX и обращением к драйверу // устройства чтения CD-ROM // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ===================================================== #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> #include <memory.h> typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long DWORD; // Необходимо для обеспечения выравнивания // полей структур на границу байта #pragma pack(1) // Заголовок запроса для обращения к драйверу typedef struct _ReqHdr { BYTE bSize; BYTE bSubUnit; BYTE bCmd; WORD wStatus; BYTE bReserved[8]; } ReqHdr; // Запрос IOCTL Input typedef struct _IOCTL_Input { ReqHdr rh; BYTE bMediaDescriptor; DWORD lpTransferAddress; WORD wDataSize; WORD wStartSector; DWORD lpVolID; } IOCTL_Input; // Запрос на получение информации о компакт-диске typedef struct _DiskInfo { BYTE bControl; BYTE bLowest; BYTE bHighest; DWORD dwTotal; } DiskInfo; // Запрос на получение информации // о дорожке компакт-диска typedef struct _TrackInfo { BYTE bControl; BYTE bTrack; DWORD dwLoc; BYTE bInfo; } TrackInfo; // Запрос для определения текущего состояния // устройства чтения CD-ROM typedef struct _DeviceStatus { BYTE bControl; DWORD dwParam; } DeviceStatus; // Запрос для определения общего количества // секторов на компакт-диске typedef struct _VolumeSize { BYTE bControl; DWORD dwVolumeSize; } VolumeSize; #pragma pack() // Прототипы функций void GetCDLetters(BYTE *bLetters); void CallCDDriver(void *rh, int nCDUnit); int GetDiskInfo(int nCDUnit); int GetDeviceStatus(int nCDUnit); int GetVolumeSize(int nCDUnit); int GetTrackInfo(int iTrack, int nCDUnit); void delay(int ms); // Регистры для вызова функции int86 union REGS rg; // Количество установленных устройств чтения CD-ROM int nCDUnits; // Номер первого устройства чтения CD-ROM int nCDStartUnit; // Слово состояния после вызова драйвера CD-ROM int iStatus; // Информация о компакт-диске DiskInfo di; // Состояние устройства чтения CD-ROM DeviceStatus ds; // Объем компакт-диска VolumeSize vs; // Информация о дорожке TrackInfo ti; BYTE bLetters[26]; // --------------------------------------------------- // main // Точка входа в программу // --------------------------------------------------- int main() { int iRetry; int i, j; printf("CDINFO, (c) A. Frolov, 1997\n\n"); // Проверяем, установлена ли программа MSCDEX rg.x.ax = 0x1500; rg.x.bx = 0; int86(0x2f, &rg, &rg); if(rg.x.bx == 0) { printf("MSCDEX is not installed\n"); return -1; } else { // Сохраняем общее количество устройств чтения CD-ROM nCDUnits = rg.x.bx; // Сохраняем номер первого такого устройства nCDStartUnit = rg.x.cx; // Определяем и отображаем вресию MSCDEX rg.x.ax = 0x150c; int86(0x2f, &rg, &rg); printf("MSCDEX version: %d.%d\n", rg.h.bh, rg.h.bl); // Отображаем количество найденных устройств чтения // CD-ROM и номер первого устройства printf("Found %d CD Unit, start unit: %c\n", nCDUnits, nCDStartUnit + 'A'); } // Получаем массив номеров устройств чтения CD-ROM GetCDLetters(bLetters); // Отображаем обозначения всех устройств CD-ROM printf("CD-ROM letters: "); for(i = 0; i < nCDUnits; i++) { printf("%c ", bLetters[i] + 'A'); } printf("\n"); // Цикл по всем устройствам чтения CD-ROM for(i = 0; i < nCDUnits; i++) { // Определяем и отображаем состояние устройства iStatus = GetDeviceStatus(bLetters[i]); if(iStatus != 0x0100) { printf("GetDeviceStatus status: %04.4X\n", iStatus); printf("GetDeviceStatus failed\n"); exit(1); } printf("\nStatus of CD Drive %c: %08.8X\n", bLetters[i] + 'A', ds.dwParam); // Определяем и отображаем объем устройства iStatus = GetVolumeSize(bLetters[i]); if(iStatus != 0x0100) { printf("GetVolumeSize status: %04.4X\n", iStatus); printf("GetVolumeSize failed\n"); } else printf("VolumeSize: %ld blocks\n", vs.dwVolumeSize); // Определяем и отображаем информацию о // компакт-диске iStatus = GetDiskInfo(bLetters[i]); // Делаем три попытки получения информации iRetry = 0; while(iStatus != 0x0100) { printf("GetDiskInfo status: %04.4X\n", iStatus); // Задержка длительностью 1 с delay(1000); iRetry++; if(iRetry == 3) { printf("GetDiskInfo failed\n"); break; } iStatus = GetDiskInfo(bLetters[i]); } // Если удалось получить информацию о компакт-диске, // исследуем его дорожки if(iRetry != 3) { // Выводим номера дорожек printf("Tracks: (%d - %d) %d\n", di.bLowest, di.bHighest, di.dwTotal); // Цикл по всем дорожкам диска for(j = di.bLowest; j <= di.bHighest; j++) { // Получаем информацию о дорожке и отображаем ее GetTrackInfo(j, bLetters[i]); printf("track %d: location: %ld, info: %02.2X", j, ti.dwLoc, ti.bInfo); // Определяем тип дорожки - звуковая дорожка // или дорожка с данными if(ti.bInfo & 0x40) printf(" * digital"); else printf(" * audio"); // Определяем, разрашено ли копирование дорожки if(ti.bInfo & 0x20) printf(", copy permitted *\n"); else printf(", copy prohibited *\n"); } } } return 0; } // --------------------------------------------------- // GetDiskInfo // Получение информации о компакт-диске // --------------------------------------------------- int GetDiskInfo(int nCDUnit) { // Заголовок команды IOCTL Input IOCTL_Input cmd; // Очищаем заголовок memset(&cmd, 0, sizeof(IOCTL_Input )); // Заполняем заголовок cmd.rh.bSize = 26; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 3; cmd.bMediaDescriptor = 0; cmd.lpTransferAddress = (DWORD)(void far *)&di; cmd.wDataSize = 7; cmd.wStartSector = 0; cmd.lpVolID = (DWORD)(void far *)NULL; di.bControl = 10; // Вызываем драйвер CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // GetTrackInfo // Получение информации о дорожке компакт-диска // --------------------------------------------------- int GetTrackInfo(int iTrack, int nCDUnit) { IOCTL_Input cmd; memset(&cmd, 0, sizeof(IOCTL_Input )); cmd.rh.bSize = 26; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 3; cmd.bMediaDescriptor = 0; cmd.lpTransferAddress = (DWORD)(void far *)&ti; cmd.wDataSize = 7; cmd.wStartSector = 0; cmd.lpVolID = (DWORD)(void far *)NULL; ti.bControl = 11; ti.bTrack = iTrack; CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // GetDeviceStatus // Определение состояния устройства чтения CD-ROM // --------------------------------------------------- int GetDeviceStatus(int nCDUnit) { IOCTL_Input cmd; memset(&cmd, 0, sizeof(IOCTL_Input )); cmd.rh.bSize = 26; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 3; cmd.bMediaDescriptor = 0; cmd.lpTransferAddress = (DWORD)(void far *)&ds; cmd.wDataSize = 5; cmd.wStartSector = 0; cmd.lpVolID = (DWORD)(void far *)NULL; ds.bControl = 6; CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // GetVolumeSize // Определение объема компакт-диска // --------------------------------------------------- int GetVolumeSize(int nCDUnit) { IOCTL_Input cmd; memset(&cmd, 0, sizeof(IOCTL_Input )); cmd.rh.bSize = 26; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 3; cmd.bMediaDescriptor = 0; cmd.lpTransferAddress = (DWORD)(void far *)&vs; cmd.wDataSize = 5; cmd.wStartSector = 0; cmd.lpVolID = (DWORD)(void far *)NULL; vs.bControl = 8; CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // CallCDDriver // Вызов драйвера компакт-диска // --------------------------------------------------- void CallCDDriver(void *rh, int nCDUnit) { static union REGS rg; static struct SREGS srg; segread(&srg); rg.x.ax = 0x1510; rg.x.cx = nCDUnit; rg.x.bx = FP_OFF(rh); int86x(0x2f, &rg, &rg, &srg); } // --------------------------------------------------- // GetCDLetters // Заполнение массива номерами установленных // в системе устройств чтения компакт-диска // --------------------------------------------------- void GetCDLetters(BYTE *bLetters) { static union REGS rg; static struct SREGS srg; segread(&srg); rg.x.ax = 0x150d; rg.x.bx = FP_OFF(bLetters); int86x(0x2f, &rg, &rg, &srg); } // --------------------------------------------------- // delay // Формирование задержки по таймеру // --------------------------------------------------- void delay(int ms) { int ticks; ticks = ms / 55; _asm { push si mov si, ticks mov ah, 0 int 1ah mov bx, dx add bx, si delay_loop: int 1ah cmp dx, bx jne delay_loop pop si } } |