В общем, программа должна найти все логические жёсткие диски. Проблема в том, что все функции, которые пытался использовать, не могут отличить CDROM от жёсткого диска. Вот мои неудачные варианты: Вариант 1: Code (Text): unsigned int type = 0; asm { MOV AH, 0x44 MOV AL, 0x8 MOV AX, 0x4408 MOV BL, disk INT 0x21 MOV type, AX } Вариант 2: Code (Text): unsigned char type = 0; asm { MOV AH, 0x10 MOV DL, disk INT 0x13 MOV type, AH } В обоих случаях для жёсткого диска и для CDROM значение type одно и то же. Может, кто подскажет, что я делаю неправильно... Может надо использовать другую функцию, которую я не нашёл? На сайте есть примеры для Win32, а для DOS нет.
Ignat не могут отличить CDROM от жёсткого диска - получи DPB и посмотри у него размер сектора. Code (Text): --------D-2132------------------------------- INT 21 - DOS 2+ - GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE AH = 32h DL = drive number (00h = default, 01h = A:, etc) Return: AL = status 00h successful DS:BX -> Drive Parameter Block (DPB) (see #01395) for specified drive FFh invalid or network drive Notes: the OS/2 compatibility box supports the DOS 3.3 version of this call except for the DWORD at offset 12h this call updates the DPB by reading the disk; the DPB may be accessed via the DOS list of lists (see #01627 at AH=52h) if disk access is not desirable. undocumented prior to the release of DOS 5.0; only the DOS 4.0+ version of the DPB has been documented, however supported by DR DOS 3.41+; DR DOS 3.41-6.0 return the same data as MS-DOS 3.31 IBM ROM-DOS v4.0 also reports invalid/network (AL=FFh) on the ROM drive SeeAlso: AH=1Fh,AH=52h,AX=7302h Format of DOS Drive Parameter Block: Offset Size Description (Table 01395) 00h BYTE drive number (00h = A:, 01h = B:, etc) 01h BYTE unit number within device driver 02h WORD bytes per sector 04h BYTE highest sector number within a cluster 05h BYTE shift count to convert clusters into sectors 06h WORD number of reserved sectors at beginning of drive 08h BYTE number of FATs 09h WORD number of root directory entries 0Bh WORD number of first sector containing user data 0Dh WORD highest cluster number (number of data clusters + 1) 16-bit FAT if greater than 0FF6h, else 12-bit FAT 0Fh BYTE number of sectors per FAT 10h WORD sector number of first directory sector 12h DWORD address of device driver header (see #01646) 16h BYTE media ID byte (see #01356) 17h BYTE 00h if disk accessed, FFh if not 18h DWORD pointer to next DPB ---DOS 2.x--- 1Ch WORD cluster containing start of current directory, 0000h=root, FFFFh = unknown 1Eh 64 BYTEs ASCIZ pathname of current directory for drive ---DOS 3.x--- 1Ch WORD cluster at which to start search for free space when writing 1Eh WORD number of free clusters on drive, FFFFh = unknown ---DOS 4.0-6.0--- 0Fh WORD number of sectors per FAT 11h WORD sector number of first directory sector 13h DWORD address of device driver header (see #01646) 17h BYTE media ID byte (see #01356) 18h BYTE 00h if disk accessed, FFh if not 19h DWORD pointer to next DPB 1Dh WORD cluster at which to start search for free space when writing, usually the last cluster allocated 1Fh WORD number of free clusters on drive, FFFFh = unknown SeeAlso: #01357,#01663,#01787 at AX=7302h,#04039 at INT E0/CL=71h
Спасибо за совет, но вот проблема - предоставленная функция работает под DOS, а Винды при запуске программы ругаются на 16-разрядную функцию, и выполнять её не собираются. А мне надо, чтоб работало и в Виндах и в DOSе ... Жду ответа как соловей лета!
Долгие поиски завели в тупик. Наиболее подходящая функция, которую я нашёл: Code (Text): asm { MOV AH, 0x36 MOV DL, disk INT 0x21 MOV type, AX } type выдаёт размер сектора. Всё бы ничего, но если в CDROM нет диска, то цикл останавливается с сообщением на консоль "Нет готовности чтение диск X. Abort, Retry, Fail?", и требует нажатия клавиши. Если нажать 'F' то цикл продолжается. Такая интерактивность меня не устраивает, программа должна искать диски автоматически. Я начинаю постепенно приходить к выводу, что задача не решаема.
Ignat Проверил код под Хрюхой (думаю, и под Ви98СЕ пойдет) - находит все логические харды. СиДиРамы игнорирует, если диска в нем нет. Code (Text): --------D-2171A0----------------------------- INT 21 - Windows95 - LONG FILENAME - GET VOLUME INFORMATION AX = 71A0h DS:DX -> ASCIZ root name (e.g. "C:\") ES:DI -> buffer for file system name CX = size of ES:DI buffer Return: CF clear if successful AX destroyed (0000h and 0200h seen) BX = file system flags (see #01783) CX = maximum length of file name [usually 255] DX = maximum length of path [usually 260] ES:DI buffer filled (ASCIZ, e.g. "FAT","NTFS","CDFS") CF set on error AX = error code 7100h if function not supported Notes: for the file system name buffer, 32 bytes should be sufficient; that's what is used in some sample code by Walter Oney from Microsoft. this function accesses the disk the first time it is called BUG: this function returns DX=0000h for CD-ROM drives under Win95 SP1 SeeAlso: AX=714Eh,AX=7160h/CL=00h Bitfields for long filename volume information flags: Bit(s) Description (Table 01783) 0 searches are case sensitive 1 preserves case in directory entries 2 uses Unicode characters in file and directory names 3-13 reserved (0) 14 supports DOS long filename functions 15 volume is compressed Фрагмент ниже не проверял - лень. Code (Text): --------D-217302----------------------------- INT 21 - Windows95 - FAT32 - "Get_ExtDPB" - GET EXTENDED DPB AX = 7302h DL = drive number (00h=default, 01h=A:, etc.) ES:DI -> buffer for returned data (see #01786) CX = length of buffer (003Fh for Windows95) SI = signature (undocumented, must be F1A6h to get device driver address and next-DBP pointer) (see #01787) Return: CF clear if successful ES:DI buffer filled CF set on error AX = error code 0018h bad buffer length SeeAlso: AX=7303h,AX=7304h,AH=1Fh,AH=32h Format of Get_ExtDPB data buffer: Offset Size Description (Table 01786) 00h WORD (call) length of following data (003Dh) 02h 61 BYTEs (ret) drive parameter block (DPB) (see #01787) Format of Extended Drive Parameter Block: Offset Size Description (Table 01787) 00h 24 BYTEs standard DOS 4+ DPB 18h BYTE "dpb_flags" (undocumented) FFh force media check 19h DWORD pointer to next DPB (see note) 1Dh WORD cluster at which to start search for free space when writing, usually the last cluster allocated 1Fh WORD number of free clusters on drive, FFFFh = unknown 21h WORD high word of free cluster count 23h WORD active FAT/mirroring bit 7: do not mirror active FAT to inactive FATs bits 6-4: reserved (0) bits 3-0: the 0-based FAT number of the active FAT (only meaningful if mirroring disabled) 25h WORD sector number of file system information sector, or FFFFh for none (see also #01788) 27h WORD sector number of backup boot sector, or FFFFh for none 29h DWORD first sector number of the first cluster 2Dh DWORD maximum cluster number 31h DWORD number of sectors occupied by FAT 35h DWORD cluster number of start of root directory 39h DWORD cluster number at which to start searching for free space Notes: except for offset 18h, all of the first 33 bytes are identical to the standard DOS 4-6 DPB unless the proper value is given in SI on entry to "Get_ExtDBP", the next-DPB pointer and device driver address are set to 0000h:0000h SeeAlso: #01786,#01395 at AH=32h,#01664 Format of File System Information structure: Offset Size Description (Table 01788) 00h DWORD signature 61417272h 04h DWORD number of free clusters (FFFFFFFFh if unknown) 08h DWORD most recently allocated cluster 0Ch 12 BYTEs reserved SeeAlso: #01787
Первая функция работает только под виндами, а в DOS выдаёт мусор. Вторая функция судя по всему - только для FAT32, поэтому не проверял. Но всё таки уже можно построить некую работающую конструкцию, типа такой: Вначале определяется версия DOS: Code (Text): asm { MOV AH, 0x30 INT 0x21 MOV highver, AL MOV lowver, AH } Если highver равен 5, то запуск идёт из Виндов и выполняем (получая тип ФС): Code (Text): unsigned char type[100]; unsigned char sdisk[5]; sprintf(sdisk,"%c:\\",disk + 'A' - 1); asm { MOV AX, 0x71A0 LEA DX, sdisk LEA DI, type MOV CX, 100 INT 0x21 } Иначе - выполняем 16-ти разрядную функцию в DOS (получая размер сектора): Code (Text): unsigned char type = 0; asm { MOV AH, 0x32 MOV DL, disk INT 0x21 MOV type, AL } Тут слабое звено - определение версии DOS, потому что наверно не всегда Винды будут соответствовать 5 версии, а 16-разрядный DOS - остальным версиям.
Ignat Первая функция работает только под виндами, а в DOS выдаёт мусор. - Если в ДОСе выставляет флаг CF - замечательно. Так можно узнать, активна ли Виндоза. Если активна, используй 71А0, если нет - 32 для INT21h.
Memphis Как выяснилось, флаг в ДОСе выставляется. Но он также выставляется в Винде, если в cdrom нет диска. Поэтому лучше наверное через версию.