home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / FORMAT.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  21KB  |  693 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **  Writen by:  Wayne Halsdorf
  5. **  Finished:   12-Jul-1994
  6. **
  7. **  This program is released to the PUBLIC DOMAIN.
  8. **
  9. **  A method for formatting floppy disks.
  10. **
  11. **  Testted with Microsoft C 7.0
  12. */
  13.  
  14. #include    <stdio.h>
  15. #include    <stdlib.h>
  16. #include    <string.h>
  17. #if defined(__TURBOC__)
  18.  #include    <alloc.h>
  19. #elif defined(__ZTC__)
  20.  #if !defined(__SC__) || (__SC__ < 0x700)
  21.   #error FORMAT.C >> _fcalloc() not supported bt ZTC or SC ver. 6.xx
  22.  #endif
  23. #else
  24.  #include    <malloc.h>
  25. #endif
  26. #include    <dos.h>
  27. #include    <direct.h>
  28. #include    <time.h>
  29. #include    <conio.h>
  30. #include    <bios.h>
  31. #include    <ctype.h>
  32. #include    "format.h"
  33.  
  34.  
  35. DPB        FAR        *dpb;
  36. FPB        FAR        *fpb;
  37. APB        FAR        *apb;
  38. IOPB       FAR        *iopb;
  39. BOOTSECTOR FAR        *BootSector;
  40.  
  41. FORMAT_TABLE    D360[] = {
  42.       {"360K", 0, 1, 2, 40,  9, 7, 0xFD, 1, 3, 706},
  43.       {"360K", 0, 1, 2, 40,  9, 7, 0xFD, 2, 2, 354},
  44.       {"360K", 0, 1, 2, 40,  9, 5, 0xFD, 4, 1, 178}
  45. };
  46.  
  47. FORMAT_TABLE    D1200[] = {
  48.       {"360K", 0, 1, 2, 40,  9,  7, 0xFD, 1, 3,  706},
  49.       {"360K", 0, 1, 2, 40,  9,  7, 0xFD, 2, 2,  354},
  50.       {"360K", 0, 1, 2, 40,  9,  5, 0xFD, 4, 1,  178},
  51.       {"1.2M", 1, 0, 2, 80, 15,  7, 0xF9, 1, 7, 2378},
  52.       {"1.2M", 1, 0, 2, 80, 15,  7, 0xF9, 2, 4, 1192},
  53.       {"1.2M", 1, 0, 2, 80, 15,  7, 0xF9, 4, 2,  597},
  54.       {"1.2M", 1, 0, 2, 80, 15,  5, 0xF9, 8, 1,  299},
  55.       {"1.2M", 1, 0, 2, 80, 15, 14, 0xF9, 1, 7, 2371},
  56.       {"1.2M", 1, 0, 2, 80, 15, 15, 0xF9, 2, 4, 1188},
  57.       {"1.2M", 1, 0, 2, 80, 15, 15, 0xF9, 4, 2,  595},
  58.       {"1.2M", 1, 0, 2, 80, 15, 13, 0xF9, 8, 1,  298}
  59. };
  60.  
  61. FORMAT_TABLE    D720[] = {
  62.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 1, 5, 1422},
  63.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 2, 3,  713},
  64.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 4, 2,  357},
  65.       { "720K", 2, 0, 2, 80,  9,  5, 0xF9, 8, 1,  179}
  66. };
  67.  
  68. FORMAT_TABLE    D1440[] = {
  69.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 1, 5, 1422},
  70.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 2, 3,  713},
  71.       { "720K", 2, 0, 2, 80,  9,  7, 0xF9, 4, 2,  357},
  72.       { "720K", 2, 0, 2, 80,  9,  5, 0xF9, 8, 1,  179},
  73.       {"1.44M", 7, 0, 2, 80, 18,  7, 0xF0, 1, 9, 2854},
  74.       {"1.44M", 7, 0, 2, 80, 18,  7, 0xF0, 2, 5, 1431},
  75.       {"1.44M", 7, 0, 2, 80, 18,  5, 0xF0, 4, 3,  717},
  76.       {"1.44M", 7, 0, 2, 80, 18,  3, 0xF0, 8, 2,  359},
  77.       {"1.44M", 7, 0, 2, 80, 18, 14, 0xF0, 1, 9, 2847},
  78.       {"1.44M", 7, 0, 2, 80, 18, 13, 0xF0, 2, 5, 1428},
  79.       {"1.44M", 7, 0, 2, 80, 18, 13, 0xF0, 4, 3,  715},
  80.       {"1.44M", 7, 0, 2, 80, 18, 11, 0xF0, 8, 2,  358}
  81. };
  82.  
  83. unsigned int    GetKey(void)
  84. {
  85.       while (!_bios_keybrd(_KEYBRD_READY))
  86.             ;
  87.       return(_bios_keybrd(_KEYBRD_READ) & 0xff);
  88. }
  89.  
  90. void    GetLine(char FAR *in, unsigned int len)
  91. {
  92.       unsigned int    k, l;
  93.       char FAR *p;
  94.  
  95.       p = in;
  96.       l = 0;
  97.       *p = '\0';
  98.       do
  99.       {
  100.             k = GetKey();
  101.             if(k == 8 && l)
  102.             {
  103.                   l--;
  104.                   p--;
  105.                   *p = '\0';
  106.                   printf("\b \b");
  107.             }
  108.             else  if(__iscsym(k) && l < len)
  109.             {
  110.                   k = (unsigned int)toupper(k);
  111.                   *p = (char)k;
  112.                   l++;
  113.                   p++;
  114.                   *p = '\0';
  115.                   printf("%c", k);
  116.             }
  117.       } while (k != 0x0d);
  118. }
  119.  
  120. void    InitVars(void)
  121. {
  122.       dpb = _fcalloc(1, sizeof(DPB));
  123.       fpb = _fcalloc(1, sizeof(FPB));
  124.       apb = _fcalloc(1, sizeof(APB));
  125.       BootSector = _fcalloc(1, sizeof(BOOTSECTOR));
  126. }
  127.  
  128. void    FreeVars(void)
  129. {
  130.       if(apb)
  131.             _ffree(apb);
  132.       if(dpb)
  133.             _ffree(dpb);
  134.       if(fpb)
  135.             _ffree(fpb);
  136.       if(iopb->dta)
  137.             _ffree(iopb->dta);
  138.       if(iopb)
  139.             _ffree(iopb);
  140.       if(BootSector)
  141.             _ffree(BootSector);
  142. }
  143.  
  144. void    Error_Message(char *message_)
  145. {
  146.       printf(message_);
  147.       FreeVars();
  148.       exit(1);
  149. }
  150.  
  151. unsigned int    AvailableDrives(void)
  152. {
  153.       _outp(0x70, 16);
  154.       return(_inp(0x71));
  155. }
  156.  
  157. void    SelectDrive(unsigned int *dr)
  158. {
  159.       unsigned int    d, a;
  160.  
  161.       a = 0;
  162.       d = AvailableDrives();
  163.       if(d & 0x0f)            /* drive b */
  164.             a = 2;
  165.       if(d & 0xf0)            /* drive a */
  166.             a |= 1;
  167.  
  168.       switch(a)
  169.       {
  170.       case 0:
  171.             Error_Message("No floppies found\n");
  172.             break;
  173.  
  174.       case 1:
  175.             *dr = 1;
  176.             break;
  177.  
  178.       case 2:
  179.             *dr = 2;
  180.             break;
  181.  
  182.       case 3:
  183.             printf("Format which drive (A or B) : ");
  184.             do
  185.             {
  186.                   d = GetKey();
  187.                   d = (unsigned int)(toupper(d) - 'A');
  188.             } while (d > 1);
  189.             printf("%c\n", d + 'A');
  190.             *dr = d + 1;
  191.             break;
  192.       }
  193. }
  194.  
  195. void    GetDrive(char *c_, unsigned int *dr)
  196. {
  197.       *dr = (unsigned int)(toupper(*c_) - 'A' + 1);
  198.       if(*dr < 1)
  199.             Error_Message("Attempted to format unknown device\n");
  200.  
  201.       if(*dr > 2)
  202.             Error_Message("Attempted to format non-floppy device\n");
  203. }
  204.  
  205. void    GetFloppyTable(unsigned int drive_number,
  206.                        unsigned int *s,
  207.                        FORMAT_TABLE **ft)
  208. {
  209.       unsigned int    d;
  210.  
  211.       d = AvailableDrives();
  212.       if(drive_number == 1)
  213.             d = d >> 4;
  214.       else  d = d & 15;
  215.  
  216.       switch(d)
  217.       {
  218.       case 1:
  219.             *ft = D360;
  220.             *s = sizeof(D360) / sizeof(FORMAT_TABLE);
  221.             break;
  222.  
  223.       case 2:
  224.             *ft = D1200;
  225.             *s = sizeof(D1200) / sizeof(FORMAT_TABLE);
  226.             break;
  227.  
  228.       case 3:
  229.             *ft = D720;
  230.             *s = sizeof(D720) / sizeof(FORMAT_TABLE);
  231.             break;
  232.  
  233.       case 4:
  234.             *ft = D1440;
  235.             *s = sizeof(D1440) / sizeof(FORMAT_TABLE);
  236.             break;
  237.  
  238.       default:
  239.             Error_Message("Don't know about formats for select drive\n");
  240.             break;
  241.       }
  242. }
  243.  
  244. void    DriveParameters(unsigned int *format,
  245.                         FORMAT_TABLE *ftable,
  246.                         unsigned int s)
  247. {
  248.       unsigned int    x;
  249.  
  250.       printf("Available formats for selected drive\n");
  251.       printf("    Format Directory Cluster  Clusters  Storage\n");
  252.       printf("     Type  Available  Size    Available Capacity\n");
  253.       for (x = 0; x < s; x++)
  254.       {
  255.             printf(" %c) %6s    %3u     %4u      %4u   %9lu\n", x + 'A',
  256.                    ftable[x].Formats_,
  257.                    ftable[x].Max_Entries * 16,
  258.                    ftable[x].Cluster_Size * 512,
  259.                    ftable[x].Available,
  260.                    512L * ftable[x].Available * ftable[x].Cluster_Size);
  261.       }
  262.       printf("Input which format: ");
  263.  
  264.       do
  265.       {
  266.             x = GetKey();
  267.             x = (unsigned int)(toupper((int)x) - 'A');
  268.       } while (x >= s);
  269.  
  270.       printf("%c\n", x + 'A');
  271.       *format = x;
  272. }
  273.  
  274. unsigned int DOS_IOCTL(unsigned drive, unsigned func, void _far *data)
  275. {
  276.       union   REGS   ir, or;
  277.       struct  SREGS  sr;
  278.  
  279.       ir.x.ax = GENERIC_IO;
  280.       ir.x.bx = drive;
  281.       ir.x.cx = func;
  282.       ir.x.dx = _FP_OFF(data);
  283.       sr.ds = _FP_SEG(data);
  284.       _int86x(0x21, &ir, &or, &sr);
  285.       return(or.x.cflag);
  286. }
  287.  
  288. unsigned int Extended_Error_Code(void)
  289. {
  290.       union   _REGS   ir, or;
  291.  
  292.       ir.h.ah = 0x59;
  293.       ir.x.bx = 0;
  294.       _int86(0x21, &ir, &or);
  295.       return(or.h.bh);
  296. }
  297.  
  298. unsigned int SerialNumber(unsigned drive, unsigned func, void _far *data)
  299. {
  300.       union   _REGS   ir, or;
  301.       struct  _SREGS  sr;
  302.  
  303.       ir.x.ax = SERIAL_NUMBER + func;
  304.       ir.x.bx = drive;
  305.       ir.x.dx = _FP_OFF(data);
  306.       sr.ds = _FP_SEG(data);
  307.       _int86x(0x21, &ir, &or, &sr);
  308.       if(or.x.cflag)
  309.             return(or.x.ax);
  310.       else  return(0);
  311. }
  312.  
  313. unsigned long GenSerialNumber(void)
  314. {
  315.       union   _REGS   ir, or;
  316.       union {
  317.             unsigned long   d;
  318.             unsigned int    i[2];
  319.       } g;
  320.  
  321.       ir.x.ax = GetDate;
  322.       _int86(0x21, &ir, &or);
  323.       g.i[0] = or.x.cx;
  324.       g.i[1] = or.x.dx;
  325.       ir.x.ax = GetTime;
  326.       _int86(0x21, &ir, &or);
  327.       g.i[0] += or.x.cx;
  328.       g.i[1] += or.x.dx;
  329.       return(g.d);
  330. }
  331.  
  332. unsigned int    FlopyStatus(unsigned int drive)
  333. {
  334.       union   _REGS   ir, or;
  335.  
  336.       ir.h.ah = 1;
  337.       ir.x.dx = drive - 1;
  338.       _int86(0x13, &ir, &or);
  339.       return(or.h.al);
  340. }
  341.  
  342. void    ResetDisk(unsigned int drive)
  343. {
  344.       union   _REGS   ir, or;
  345.  
  346.       ir.h.ah = 0;
  347.       ir.x.dx = drive - 1;
  348.       _int86(0x13, &ir, &or);
  349. }
  350.  
  351. /*
  352. ** gain acces to drive (required if disk in drive is unformated)
  353. */
  354.  
  355. void    SetAccess(unsigned int drivenumber, APB FAR *apb)
  356. {
  357.       apb->Function = 0;
  358.       DOS_IOCTL(drivenumber, GENERIC_GETACC, apb);
  359.       if(apb->Flag == 0)
  360.       {
  361.             apb->Flag = 1;
  362.             DOS_IOCTL(drivenumber, GENERIC_SETACC, apb);
  363.       }
  364. }
  365.  
  366. void    InitParameters(unsigned int drive_number,
  367.                        unsigned int format,
  368.                        FORMAT_TABLE *ftable)
  369. {
  370.       unsigned int    t;
  371.  
  372.       dpb->Function = 0;
  373.       dpb->Device_Type = ftable[format].Device_Type;
  374.       dpb->Tracks = ftable[format].Tracks;
  375.       dpb->Media_Type = ftable[format].Media_Type;
  376.       dpb->bpb.Bytes_Sector = 0x0200;
  377.       dpb->bpb.Cluster_Size = ftable[format].Cluster_Size;
  378.       dpb->bpb.Reserved_Sectors = 1;
  379.       dpb->bpb.Number_FATS = 2;
  380.       dpb->bpb.Max_Root_Entries = ftable[format].Max_Entries * 16;
  381.       dpb->bpb.Number_Sectors   = ftable[format].Tracks *
  382.                                   ftable[format].Heads *
  383.                                   ftable[format].Sectors_Per_Tracks;
  384.       dpb->bpb.Media_Descriptor = ftable[format].Media_Descriptor;
  385.       dpb->bpb.Sectors_FAT = ftable[format].FatSize;
  386.       dpb->bpb.Sectors_Track = ftable[format].Sectors_Per_Tracks;
  387.       dpb->bpb.Number_Heads = ftable[format].Heads;
  388.       dpb->bpb.Hidden_Sectors = 0;
  389.       dpb->bpb.Large_Number_Sectors = 0;
  390.       dpb->track.Number_Sectors = ftable[format].Sectors_Per_Tracks;
  391.       for (t = 0; t < dpb->track.Number_Sectors; t++)
  392.       {
  393.             dpb->track.track_layout[t].Sector_Number = t + 1;
  394.             dpb->track.track_layout[t].Sector_Size = dpb->bpb.Bytes_Sector;
  395.       }
  396.  
  397.       iopb = _fcalloc(1, sizeof(IOPB));
  398.       iopb->dta = _fcalloc(dpb->bpb.Sectors_Track * dpb->bpb.Bytes_Sector,
  399.                            sizeof(char));
  400.       DOS_IOCTL(drive_number, GENERIC_SETDEV, dpb);
  401.       dpb->Function = 5;
  402. }
  403.  
  404. #ifdef  _MSC_VER
  405. #pragma warning(disable:4001)
  406. #endif
  407.  
  408. /*
  409. ** format each track, both sides
  410. */
  411.  
  412. void    FormatDisk(unsigned int drive_number,
  413.                    unsigned int ftype,
  414.                    FORMAT_TABLE *ftable)
  415. {
  416.       unsigned int    retries, er;
  417.  
  418.       printf("Insert disk in drive %c: and press enter ",
  419.              drive_number + 'A' - 1);
  420.  
  421.       while (GetKey() != 0x0d)
  422.             ;
  423.  
  424.       printf("\nFormatting %s Data Disk, Please Wait.\n",
  425.              ftable[ftype].Formats_);
  426.       fpb->Function = 0;      /* format/Verify track */
  427.       for (fpb->Track = 0; fpb->Track < dpb->Tracks; fpb->Track += 1)
  428.       {
  429.             for (fpb->Head = 0;
  430.                  fpb->Head < ftable[ftype].Heads;
  431.                  fpb->Head += 1)
  432.             {
  433.                   SetAccess(drive_number, apb);
  434.                   DOS_IOCTL(drive_number, GENERIC_SETDEV, dpb);
  435.                   printf("Formating Track %2u Side %u\r",
  436.                          fpb->Track, fpb->Head);
  437.                   retries = 0;
  438.                   while (retries++ < 4 && DOS_IOCTL(drive_number,
  439.                         GENERIC_FORMAT, fpb))
  440.                   {
  441.                         er = FlopyStatus(drive_number);
  442.                         if((er & 0x80) == 0)
  443.                         {
  444.                               er = Extended_Error_Code();
  445.                               if(er == 0x0d)
  446.                                     Error_Message("Invlaid Media\n");
  447.  
  448.                               if(er == 0x0b)
  449.                               {
  450.                                     printf("Disk write proteced.\n"
  451.                                            "Press enter after correcting "
  452.                                            "or escape to abort\n");
  453.                                     do
  454.                                     {
  455.                                           er = GetKey();
  456.                                           if(er == 0x1b)
  457.                                                 Error_Message("Format aborted"
  458.                                                       ". Disk now invalid.\n");
  459.                                     } while (er != 0x0d);
  460.                               }
  461.                         }
  462.                         ResetDisk(drive_number);
  463.                         SetAccess(drive_number, apb);
  464.                         DOS_IOCTL(drive_number, GENERIC_SETDEV, dpb);
  465.                   }
  466.             }
  467.       }
  468. }
  469.  
  470. void    InitializeDisk(unsigned int drive_number)
  471. {
  472.       struct tm *today;
  473.       VPB     FAR   *vpb;
  474.       time_t   timer;
  475.       unsigned int    er;
  476.       char    *er_;
  477.       static char FAR iname[NLEN + 1];
  478.       static unsigned char FAR boot_start[BJLEN] = {0xeb,0x3C,0x90};
  479.       static unsigned char FAR os_[OLEN] = {"PDDF 1.0"};
  480.       static unsigned char FAR fat_start[3] = {0xfd,0xff,0xff};
  481.       static unsigned char FAR name[NLEN] = {"NO NAME    "};
  482.       static unsigned char FAR fatname[FLEN] = {"FAT12   "};
  483.       static unsigned char FAR boot_code[BLEN];
  484.       static unsigned char boot_code_default[] = {
  485.             0xfa,                   /* 7c3e cli                     */
  486.             0xbc, 0x00, 0x7c,       /* 7c3f mov sp, 7c00h           */
  487.             0xfb,                   /* 7c42 sti                     */
  488.             0xb2, 0x00,             /* 7c43 mov dl,0                */
  489.             0x33, 0xc0,             /* 7c45 xor ax,ax               */
  490.             0xcd, 0x13,             /* 7c47 int 13h                 */
  491.             0x0e,                   /* 7c49 push cs                 */
  492.             0x1f,                   /* 7c4a pop  ds                 */
  493.             0xfc,                   /* 7c4b cld                     */
  494.             0xbe, 0x63, 0x7c,       /* 7c4c mov si, OFFSET message  */
  495.             0xac,                   /* 7c4f lodsb                   */
  496.             0x0a, 0xc0,             /* 7c50 or  al,al               */
  497.             0x74, 0x09,             /* 7c52 je  7c5c                */
  498.             0xb4, 0x0e,             /* 7c54 mov ah,0eh              */
  499.             0xbb, 0x07, 0x00,       /* 7c56 mov bx,7                */
  500.             0xcd, 0x10,             /* 7c59 int 10h                 */
  501.             0xeb, 0xf2,             /* 7c5b jmp SHORT 7c50          */
  502.             0x33, 0xc0,             /* 7c5d xor ax,ax               */
  503.             0xcd, 0x16,             /* 7c5f int 16h                 */
  504.             0xcd, 0x19              /* 7c61 int 19h                 */
  505.                                     /* 7c63 db  'message'           */
  506.     };
  507.     static char boot_text_default[] = {
  508.             "\r\nNon-System disk for DATA USE ONLY!"
  509.             "\r\nProduced by a Public Domain Disk Formater 1.0 ."
  510.             "\r\nSource code freely available."
  511.             "\r\nReplace or remove disk then press any key when ready\r\n"
  512.       };
  513.  
  514.       printf("\nInitializing Disk\n");
  515.       _fmemcpy(&boot_code[0], boot_code_default, sizeof(boot_code_default));
  516.       _fmemcpy(&boot_code[sizeof(boot_code_default)], boot_text_default,
  517.                sizeof(boot_text_default));
  518.  
  519.       /*
  520.       ** test to see if BOOT FATS and DIRECTORY records can be placed
  521.       */
  522.  
  523.       iopb->Function = 0;
  524.       iopb->Side = 0;
  525.       iopb->Track = 0;
  526.       iopb->FirstSector = 0;
  527.       iopb->NumberSectors = dpb->bpb.Sectors_Track;
  528.       er = DOS_IOCTL(drive_number, GENERIC_READ, iopb);
  529.       _fmemset(iopb->dta, 0, dpb->bpb.Sectors_Track * dpb->bpb.Bytes_Sector);
  530.       er = DOS_IOCTL(drive_number, GENERIC_WRITE, iopb);
  531.       er = DOS_IOCTL(drive_number, GENERIC_VERIFY, iopb);
  532.       if(er)
  533.             Error_Message("Track 0 side 0 defective\n");
  534.  
  535.       iopb->Function = 0;
  536.       iopb->Side = 1;
  537.       iopb->Track = 0;
  538.       iopb->FirstSector = 0;
  539.       iopb->NumberSectors = dpb->bpb.Sectors_Track;
  540.       er = DOS_IOCTL(drive_number, GENERIC_WRITE, iopb);
  541.       er = DOS_IOCTL(drive_number, GENERIC_VERIFY, iopb);
  542.       if(er)
  543.             Error_Message("Track 0 side 1 defective\n");
  544.  
  545.       /*
  546.       ** place BOOT Record
  547.       */
  548.  
  549.       iopb->Function = 0;
  550.       iopb->Side = 0;
  551.       iopb->Track = 0;
  552.       iopb->FirstSector = 0;
  553.       iopb->NumberSectors = 1;
  554.       _fmemcpy(BootSector->boot_start_, boot_start, BJLEN);
  555.       _fmemcpy(BootSector->os_name_, os_, OLEN);
  556.       _fmemcpy(&(BootSector->bpb), &(dpb->bpb), sizeof(BPB) + 1);
  557.       BootSector->bpb.Reserved[2] = 0x29;       /* needed for serial number */
  558.       _fmemcpy(BootSector->volname_, name, NLEN);
  559.       _fmemcpy(BootSector->fat_, fatname, FLEN);
  560.       _fmemcpy(BootSector->boot_code_, boot_code, BLEN);
  561.       _fmemcpy(iopb->dta, BootSector, sizeof(BOOTSECTOR));
  562.       er = DOS_IOCTL(drive_number, GENERIC_WRITE, iopb);
  563.       er = DOS_IOCTL(drive_number, GENERIC_VERIFY, iopb);
  564.       if(er)
  565.             Error_Message("Bad Boot Sector\n");
  566.  
  567.       /*
  568.       ** place first FAT
  569.       */
  570.  
  571.       _fmemset(iopb->dta, 0, dpb->bpb.Sectors_FAT * dpb->bpb.Bytes_Sector);
  572.       _fmemcpy(iopb->dta, fat_start, sizeof(fat_start));
  573.       iopb->Function = 0;
  574.       iopb->Side = 0;
  575.       iopb->Track = 0;
  576.       iopb->FirstSector = 1;
  577.       iopb->NumberSectors = dpb->bpb.Sectors_FAT;
  578.       er = DOS_IOCTL(drive_number, GENERIC_WRITE, iopb);
  579.       er = DOS_IOCTL(drive_number, GENERIC_VERIFY, iopb);
  580.       if(er)
  581.             Error_Message("Bad File Allocation Table\n");
  582.  
  583.       /*
  584.       ** place second FAT
  585.       */
  586.  
  587.       iopb->Function = 0;
  588.       iopb->Side = 0;
  589.       iopb->Track = 0;
  590.       iopb->FirstSector = 1 + dpb->bpb.Sectors_FAT;
  591.       iopb->NumberSectors = dpb->bpb.Sectors_FAT;
  592.       er = DOS_IOCTL(drive_number, GENERIC_WRITE, iopb);
  593.       er = DOS_IOCTL(drive_number, GENERIC_VERIFY, iopb);
  594.       if(er)
  595.             Error_Message("Bad File Allocation Table\n");
  596.  
  597.       /*
  598.       ** place extend information on BOOT record
  599.       */
  600.  
  601.       vpb = _fcalloc(1, sizeof(VPB));
  602.       SerialNumber(drive_number, SERIAL_READ, vpb);
  603.       today = localtime( &timer );
  604.       vpb->SerialNumber = GenSerialNumber();
  605.       printf("Internal Volume Name: ");
  606.       GetLine(iname, NLEN);
  607.       if(_fstrlen(iname))
  608.       {
  609.             _fmemset(vpb->VolumeLabel, ' ', NLEN);
  610.             _fmemcpy(vpb->VolumeLabel, iname, _fstrlen(iname));
  611.       }
  612.       er = SerialNumber(drive_number, SERIAL_WRITE, vpb);
  613.       _ffree(vpb);
  614.       if(er)
  615.       {
  616.             er = Extended_Error_Code();
  617.             switch(er)
  618.             {
  619.             case 0x15:
  620.                   er_ = "Drive not Ready. Can't update Boot.\n";
  621.                   break;
  622.  
  623.             case 0x1F:
  624.                   er_ = "General Failure. Can't update Boot\n";
  625.                   break;
  626.  
  627.             default:
  628.                   er_ = "Can't update Boot\n";
  629.                   break;
  630.             }
  631.             Error_Message(er_);
  632.       }
  633. }
  634.  
  635. void    CheckDrive(unsigned int drive_number)
  636. {
  637.       union   _REGS   ir, or;
  638.       struct  _SREGS  sr;
  639.  
  640.       ir.x.ax = CHECK_REMOVABLE;
  641.       ir.x.bx = drive_number;
  642.       _int86x(0x21, &ir, &or, &sr);
  643.       if(or.x.cflag)
  644.             Error_Message("Can't determine if media is removable.\n");
  645.  
  646.       if(or.x.ax)
  647.             Error_Message("Selected media not removable, "
  648.                           "my not be a floppy.\n");
  649.  
  650.       ir.x.ax = CHECK_REMOTE;
  651.       _int86x(0x21, &ir, &or, &sr);
  652.       if(or.x.cflag)
  653.             Error_Message("Can't determine if media is remote or shared.\n");
  654.  
  655.       if((or.x.dx & 0x8000) != 0)
  656.             Error_Message("Can't format SUBSTITUTE drive.\n");
  657.  
  658.       if((or.x.dx & 0x1000) != 0)
  659.             Error_Message("Can't format REMOTE drive.\n");
  660. }
  661.  
  662. /*
  663. ** get real dos version
  664. */
  665.  
  666. void    CheckDosVersion(void)
  667. {
  668.       if(_osmajor < 4)
  669.             Error_Message("Must be DOS 4.0 or higher.\n");
  670. }
  671.  
  672. int     main(int argc, char *argv[])
  673. {
  674.       unsigned int    format, drive_number, size;
  675.       FORMAT_TABLE    *ftable;
  676.  
  677.       CheckDosVersion();
  678.       InitVars();
  679.  
  680.       if(argc == 1)
  681.             SelectDrive(&drive_number);
  682.       else  GetDrive(argv[1], &drive_number);
  683.  
  684.       CheckDrive(drive_number);
  685.       GetFloppyTable(drive_number, &size, &ftable);
  686.       DriveParameters(&format, ftable, size);
  687.       InitParameters(drive_number, format, ftable);
  688.       FormatDisk(drive_number, format, ftable);
  689.       InitializeDisk(drive_number);
  690.       FreeVars();
  691.       return(0);
  692. }
  693.