Таблица 6



Таблица 6

(0) 1 drv_num номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
(+1) 1drv_numd дополнительный номер устройства внутри драйвера
(+2) 2sec_size размер сектора в байтах
(+4) 1clu_size число, на единицу меньшее количества секторов в кластере
(+5) 1clu_base если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6) 2boot_siz количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8) 1fat_num количество копий FAT
(+9) 2max_dir максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11) 2data_sec номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13) 2hi_clust максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15) 1fat_size количество секторов, занимаемых одной копией FAT
(+16) 1reserv1 зарезервироано
(+17) 2root_sec номер первого сектора корневого каталога
(+19) 4drv_addr FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+23) 1media байт описания среды носителя данных
(+24) 1acc_flag флаг доступа, 0 означает, что к устройству был доступ
(+25) 4next адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
(+29) 2reserv2 зарезервироано
(+31) 2built число FFFF в этом поле означает, что блок DDCB был построен

Файл sysp.h содержит определение типа DDCB для MS-DOS версии 4.х и 5.0: /* Блок управления устройством DOS */ #pragma pack(1) typedef struct _DDCB_ { unsigned char drv_num; unsigned char drv_numd; unsigned sec_size; unsigned char clu_size; unsigned char clu_base; unsigned boot_siz; unsigned char fat_num; unsigned max_dir; unsigned data_sec; unsigned hi_clust; unsigned char fat_size; char reserv1; unsigned root_sec; void far *drv_addr; unsigned char media; unsigned char acc_flag; struct _DDCB_ far *next; unsigned reserv2; unsigned built; } DDCB; #pragma pack()

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

Приведем тексты программ для получения адресов первого и последующих блоков DDCB: /** *.Name get_fddcb * *.Title Получить адрес первого DDCB * *.Descr Функция возвращает адрес первого блока DDCB * *.Params DDCB far *get_fddcb(CVT far *cvt) * * cvt - адрес векторной таблицы связи * *.Return Указатель на первый блок DDCB **/ #include <stdlib.h> #include <stdio.h> #include "sysp.h" DDCB far *get_fddcb(CVT far *cvt) { DDCB far * ddcb; ddcb = cvt->dev_cb; return(ddcb); } /** *.Name get_nddcb * *.Title Получить адрес следующего DDCB * *.Descr Функция возвращает адрес следующего блока DDCB * или 0, если это последний блок в цепочке * *.Params DDCB far *get_nddcb(DDCB far *ddcb) * * ddcb - адрес предыдущего DDCB * *.Return Указатель на следующий блок DDCB * или 0, если это последний блок в цепочке **/ #include <dos.h> #include "sysp.h" DDCB far *get_nddcb(DDCB far *ddcb) { DDCB far *ddcb_n; ddcb_n = ddcb->next; if(FP_OFF(ddcb_n) == 0xffff) return((DDCB far *)0); return(ddcb_n); }

С помощью приведенной ниже программы можно просмотреть содержимое всех блоков DDCB. Так как при большом количестве дисков выводится очень много информации, следует использовать средство переназначения стандартного устройства вывода DOS: show_ddc > drives.lst

Эта программа проверена для версии MS/DOS 4.01. #include <dos.h> #include <stdio.h> #include <stdlib.h> #include "sysp.h" void main(void); void main(void) { CVT far *cvt; DDCB far *ddcb; printf("\nБлоки управления дисковыми устройствами (DDCB)" "\nCopyright (C)Frolov A., 1990\n" "\n"); cvt=get_mcvt(); ddcb=get_fddcb(cvt); for(;;) { if(ddcb == (DDCB far *)0) break; printf("Адрес DDCB: %Fp\n" "Номер устройства: %d\n" "Дополнительный номер: %d\n" "Размер сектора: %d\n" "Размер кластера в секторах: %d\n" "База размера кластера: %d\n" "Зарезервировано секторов: %d\n" "Число копий FAT: %d\n" "Макс. файлов в корневом каталоге : %d\n" "Первый кластер данных: %d\n" "Всего кластеров: %d\n" "Размер FAT в секторах: %d\n" "Первый сектор корневого каталога: %d\n" "Поле reserv1: %01X\n" "Адрес драйвера: %Fp\n" "Байт описателя среды носителя: %01X\n" "Флаг доступа: %01X\n" "Адрес следующего DDCB: %Fp\n" "Поле reserv2: %04X\n" "Блок построен: %04X\n" "-------------------------------------\n\n", ddcb, ddcb->drv_num, ddcb->drv_numd, ddcb->sec_size, ddcb->clu_size, ddcb->clu_base, ddcb->boot_siz, ddcb->fat_num, ddcb->max_dir, ddcb->data_sec, ddcb->hi_clust, ddcb->fat_size, ddcb->root_sec, ddcb->reserv1, ddcb->drv_addr, ddcb->media, ddcb->acc_flag, ddcb->next, ddcb->reserv2, ddcb->built); ddcb=get_nddcb(ddcb); } exit(0); }

Приведенный выше способ получения доступа к блокам DDCB больше всего подходит для просмотра блоков управления всеми дисковыми устройствами. Если вам требуется получить DDCB для какого-нибудь конкретного устройства, можно воспользоваться недокументированной функцией 32H прерывания INT21H (со всеми ограничениями, связанными с использованием недокументированных возможностей).

Функция 32H получает в регистре DL номер устройства (0 - текущий диск, 1 - А: и т.д.) и возвращает в регистровой паре DS:BX адрес соответствующего DDCB. Если номер устройства был задан неправильно, регистр AL после выполнения функции будет содержать значение FF.

Если требуется получить адрес DDCB флоппи-диска, необходимо установить диск в приемный карман дисковода.

Приведем текст программы, возвращающей указатель на DDCB диска с заданным номером: /** *.Name get_ddcb * *.Title Получить адрес DDCB заданного диска * *.Descr Функция возвращает адрес блока управления * устройством DOS DDCB * *.Params DDCB far *get_ddcb(int device_number) * * device_number - номер диска, для которого * требуется получить DDCB * Номер задается так: * 0 - текущий диск, 1 - В и т.д. * *.Return Указатель на DDCB заданного диска **/ #include <dos.h> #include <stdio.h> #include "sysp.h" DDCB far *get_ddcb(unsigned char device_number) { union REGS inregs, outregs; struct SREGS segregs; inregs.h.ah = 0x32; inregs.h.al = 0; inregs.h.dl = device_number; intdosx( &inregs, &outregs, &segregs ); if(outregs.h.al == 0xff) return(DDCB far *)0; return((DDCB far*)FP_MAKE(segregs.ds,outregs.x.bx)); }

Программа, приведенная ниже, выводит адреса всех DDCB. Можете запустить ее (она есть на дискете, прилагающейся к книге) и посмотреть, что получится. Не забудьте вставить флоппи-диски во все дисководы. #include <dos.h> #include <stdio.h> #include <stdlib.h> #include "sysp.h" void main(void); void main(void) { DDCB far *ddcb; unsigned char dr; for(dr=1;;dr++) { ddcb=get_ddcb(dr); if(ddcb == (DDCB far *)0) break; printf("%Fp\n",ddcb); } exit(0); }



- Начало - - Назад - - Вперед -