#include <dos.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct _DFCB_
{
  unsigned handl_num;
  unsigned char access_mode;
  unsigned reserv1;
  unsigned dev_info;
  void far *driver;
  unsigned first_clu;
  unsigned time;
  unsigned date;
  unsigned long fl_size;
  unsigned long offset;
  unsigned reserv2;
  unsigned reserv7;
  unsigned reserv3;
  char reserv4;
  char filename[11];
  char reserv5[6];
  unsigned ownr_psp;
  unsigned reserv6;
  unsigned last_clu;
  char reserv8[4];
} DFCB;
typedef DFCB far* LPDFCB;

typedef struct _DFT_
{
  struct _DFT_ far *next;
  unsigned file_count;
  DFCB dfcb;
} SFT;
typedef SFT far* LPSFT;

typedef struct
{
  unsigned mcb_seg;
  void far *dev_cb;
  void far *file_tab;
  void far *clock_dr;
  void far *con_dr;
  unsigned max_btbl;
  void far *disk_buf;
  void far *drv_info;
  void far *fcb_tabl;
  unsigned fcb_size;
  unsigned char num_bdev;
  unsigned char lastdriv;
} CVT;
typedef CVT far* LPCVT;

void main(void);
LPSFT get_fsft(LPCVT cvt);
LPSFT get_nsft(LPSFT sft);

void main(void)
{
  union REGS   regs;
  struct SREGS sregs;
  LPCVT        lpCVT;
  LPSFT        lpSFT;
  unsigned     i,j,k;
  LPDFCB       lpDFCB;
  FILE *       list;

  printf("Информация об открытых файлах MS-DOS\n"
    "(C) Фролов А.В., 1995\n");

  // Открываем файл для вывода информации о файлах
  list = fopen("!sft.lst","w+");

  fprintf(list,"Информация об открытых файлах MS-DOS\n"
    "(C) Фролов А.В., 1995\n\n");

  // Получаем адрес векторной таблицы связи
  regs.h.ah = 0x52;
  intdosx(&regs, &regs, &sregs);

  // Передвигаем указатель на поле msb_seg
  lpCVT = (LPCVT)MK_FP(sregs.es, regs.x.bx - 2);

  lpSFT = get_fsft(lpCVT);  // Адрес начала таблицы файлов

  for(;;)
  {
    if(lpSFT == NULL) break;  // Конец таблицы

    i = lpSFT->file_count;
    fprintf(list,"Таблица файлов SFT: %Fp, в ней %d файлов\n"
      "===========================================\n",
      lpSFT, i);

    for(j=0; j<i; j++)
    {
      lpDFCB = (&(lpSFT->dfcb)) + j; // Адрес DFCB файла

      fprintf(list,"\nDFCB файла: %Fp\n\n", lpDFCB);
      fprintf(list,"Имя файла: ");
      for(k=0; k<11; k++)
	fputc(lpDFCB->filename[k], list);

      fprintf(list,
       "\nКоличество идентификаторов:    %d\n"
       "Режим доступа:                 %d\n"
       "Поле reserv1:                  %04X\n"
       "Информация об устройстве:      %04X\n"
       "Адрес драйвера:                %Fp\n"
       "Начальный кластер:             %d\n"
       "Время:                         %04X\n"
       "Дата:                          %04X\n"
       "Размер файла в байтах:         %ld\n"
       "Текущее смещение в файле:      %ld\n"
       "Поле reserv2:                  %04X\n"
       "Последний прочитанный кластер: %d\n"
       "Сегмент PSP владельца файла:   %04X\n"
       "Поле reserv7:                  %d\n"
       "-------------------------------\n\n",
       lpDFCB->handl_num, lpDFCB->access_mode,
       lpDFCB->reserv1,   lpDFCB->dev_info,
       lpDFCB->driver,    lpDFCB->first_clu,
       lpDFCB->time,      lpDFCB->date,
       lpDFCB->fl_size,   lpDFCB->offset,
       lpDFCB->reserv2,   lpDFCB->last_clu,
       lpDFCB->ownr_psp,  lpDFCB->reserv7);
    }
    lpSFT = get_nsft(lpSFT);
  }
  fclose(list);
}

LPSFT get_nsft(LPSFT sft)
{
  LPSFT sft_next;

  sft_next = sft->next;
  if(FP_OFF(sft_next) == 0xffff)
    return((LPSFT)NULL);

  return(sft_next);
}

LPSFT get_fsft(LPCVT cvt)
{
  LPSFT sft;
  sft = (LPSFT)cvt->file_tab;
  return(sft);
}

