home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / b / bootse.zip / BOOTSECT.C next >
C/C++ Source or Header  |  1992-08-04  |  17KB  |  529 lines

  1. /**** Copyright (c) 1992 The Binary Tool Foundry. All rights reserved. ******
  2.  
  3.    Project: Miscellaneous Tools        Compuserve: 70760,2663
  4.    Author : Marcus Redivo              Address   : The Binary Tool Foundry
  5.    Date   : July 1992                              4684 Sunnymead Way
  6.    Module : bootsect.c                             Victoria, BC V8Y 2V5 Canada
  7.  
  8.                        ********  WARNING ********
  9.  
  10.                   THIS PROGRAM CAN TRASH YOUR DRIVE C:!
  11.  
  12.                        ********  WARNING ********
  13.  
  14.    This program is provided for your use on an "as is" basis, and no
  15.    representation is made that it will work as documented on any particular
  16.    system. It is UP TO YOU to verify that the program will do no harm to your
  17.    system before executing it. See the notes below for a program overview.
  18.  
  19.    Abstract:
  20.  
  21.    The purpose of this program is to save the Microsoft Windows NT boot
  22.    sector in the active partition of drive C: and subsequently reinstall
  23.    either the DOS or NT boot sectors on demand. The boot sector data is
  24.    stored in the root directory of drive C: in files C:\BOOTSECT.DOS and
  25.    C:\BOOTSECT.NT. The program does this by doing absolute sector IO to
  26.    drive C:, which this program can only do in real addressing mode.
  27.  
  28.    Note that if the wrong sector or the wrong data is written, the result
  29.    can be catastrophic to the data on drive C:.
  30.  
  31.    Syntax:
  32.  
  33.       bootsect [-save | -nt | -dos]
  34.  
  35.    Options:
  36.  
  37.       No option : Identify the current boot sector.
  38.       -save     : Save the current boot sector to the appropriate file.
  39.       -nt       : Install the Windows NT boot sector.
  40.       -dos      : Install the DOS boot sector.
  41.  
  42.  
  43.    Operational notes:
  44.  
  45.    This program must be run from DOS in real mode. It will not work
  46.    properly from a DOS box in protected mode.
  47.  
  48.    This program loads the partition table from Drive C: to determine
  49.    which partition is the current boot partition. It ensures that this
  50.    partition is a DOS FAT file system, and is NOT an extended partition
  51.    (type 0x05). (This is only because I cannot test this with the equipment
  52.    available to me. If you can make it work, go right ahead and make the
  53.    necessary changes to allow this type.)
  54.  
  55.    It then loads the boot sector from the active partition, and determines
  56.    whether it is a DOS or NT boot sector. (Again, I don't check for OS/2
  57.    because I don't have any means of researching or testing it.)
  58.  
  59.    If you have requested saving the boot sector, it opens the appropriate
  60.    file (C:\BOOTSECT.DOS or C:\BOOTSECT.NT) and writes the boot sector
  61.    into it.
  62.  
  63.    If you have requested installation of a boot sector, it opens the
  64.    appropriate file (C:\BOOTSECT.DOS or C:\BOOTSECT.NT) and validates it.
  65.    If the file checks out OK, it is installed and the program terminates.
  66.  
  67.  
  68. ****************************************************************************/
  69.  
  70. #include <stdlib.h>
  71. #include <string.h>
  72. #include <stdio.h>
  73. #include <fcntl.h>
  74. #include <io.h>
  75. #include <dos.h>
  76. #include <sys\types.h>
  77. #include <sys\stat.h>
  78.  
  79.  
  80. #define DISK_SECTOR_SIZE        0x200
  81. #define BOOT_SIGNATURE         0xAA55
  82. #define BOOT_IS_NT                  1
  83. #define BOOT_IS_DOS                 2
  84. #define DISPLAY_CURRENT_STATUS      0
  85. #define SAVE_CURRENT_BOOTSECT       1
  86. #define INSTALL_NT_BOOTSECT         2
  87. #define INSTALL_DOS_BOOTSECT        3
  88. #define TRUE                        1
  89. #define FALSE                       0
  90.  
  91.  
  92. typedef unsigned char BYTE;
  93. typedef unsigned int  UINT;
  94. typedef unsigned long ULONG;
  95.  
  96. #pragma pack(1)
  97. typedef struct PTEntryTag
  98. {
  99.    BYTE Active;
  100.    BYTE StartingHead;
  101.    BYTE StartingSector;    /* Upper two bits are high bits of Cylinder. */
  102.    BYTE StartingCylinder;
  103.    BYTE PartitionType;
  104.    BYTE EndingHead;
  105.    BYTE EndingSector;      /* Upper two bits are high bits of Cylinder. */
  106.    BYTE EndingCylinder;
  107.    ULONG PartitionStartSector;
  108.    ULONG PartitionLength;
  109. } PTEntryT;
  110.  
  111. typedef struct PTableTag
  112. {
  113.    BYTE LoaderPgm[DISK_SECTOR_SIZE - ((sizeof (PTEntryT) * 4) + sizeof (int))];
  114.    PTEntryT PTable[4];
  115.    UINT Signature;
  116. } PTableT;
  117.  
  118. typedef struct BootSectorTag
  119. {
  120.    BYTE JumpInstruction[3];
  121.    BYTE BIOSParameterBlock[59];
  122.    BYTE LoaderPgm[DISK_SECTOR_SIZE - (3 + 59 + sizeof (int))];
  123.    UINT Signature;
  124. } BootSectorT;
  125. #pragma pack()
  126.  
  127.  
  128. /****************************************************************************
  129.    Global/Static Variables.
  130. ****************************************************************************/
  131.  
  132. extern unsigned char _osmajor;
  133.  
  134. static char        szNTBootSectorFile[_MAX_PATH]  = "c:\\bootsect.nt";
  135. static char        szDOSBootSectorFile[_MAX_PATH] = "c:\\bootsect.dos";
  136. static char        szBootSectorFile[_MAX_PATH];
  137. static int         hBootSectorFile;
  138. static BootSectorT DiskBootSector;
  139. static BootSectorT FileBootSector;
  140. static PTableT     MasterBootRecord;
  141.  
  142.  
  143.  
  144. /****************************************************************************
  145.    Function Declarations.
  146. ****************************************************************************/
  147.  
  148. int ReadAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
  149.                   void _far *Buffer);
  150. int WriteAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
  151.                   void _far *Buffer);
  152. int SearchSector(BYTE *Sector, char *String);
  153.  
  154.  
  155.  
  156. /***************************************************************************
  157.   Function . . : main()
  158.   Purpose  . . : See abstract.
  159. */
  160.  
  161. main(int argc, char *argv[])
  162. {
  163.    int Operation, ActivePartition, CurrentBootSector, bFileOK = TRUE;
  164.  
  165.  
  166.    /* Ensure we are operating at DOS 3.0 or better. */
  167.  
  168.    if (_osmajor < 3)
  169.    {
  170.       printf("DOS 3.0 or higher required.\n");
  171.       exit(-1);
  172.    }
  173.  
  174.  
  175.    /* Determine what action has been requested. */
  176.  
  177.    if (argc == 1)
  178.    {
  179.       Operation = DISPLAY_CURRENT_STATUS;
  180.    }
  181.    else
  182.    {
  183.       switch (tolower(argv[1][1]))
  184.       {
  185.          case 's':   /* -save - Save current boot sector. */
  186.             Operation = SAVE_CURRENT_BOOTSECT;
  187.             break;
  188.          case 'n':   /* -nt   - Install NT boot sector. */
  189.             Operation = INSTALL_NT_BOOTSECT;
  190.             break;
  191.          case 'd':   /* -dos  - Install DOS boot sector. */
  192.             Operation = INSTALL_DOS_BOOTSECT;
  193.             break;
  194.          default:
  195.             printf("\nBOOTSECT v1.00 - Manipulate Drive C: Boot Sector\n");
  196.             printf("Copyright (c) The Binary Tool Foundry 1992.\n\n");
  197.             printf("Syntax:   bootsect [-save | -nt | -dos]\n\n");
  198.             printf("   No option : Identify the current boot sector.\n");
  199.             printf("   -save     : Save the current boot sector to file.\n");
  200.             printf("   -nt       : Install the Windows NT boot sector.\n");
  201.             printf("   -dos      : Install the DOS boot sector.\n");
  202.             exit(-1);
  203.             break;
  204.       }
  205.    }
  206.  
  207.  
  208.  
  209.    /* Determine where the boot sector is by reading partition table. */
  210.  
  211.    if (ReadAbsSector('C', 0, 0, 1, &MasterBootRecord) != 0)
  212.    {
  213.       printf("Unable to extract partition table information.\n");
  214.       exit(-1);
  215.    }
  216.  
  217.  
  218.  
  219.    /* Validate the partition table sector. */
  220.  
  221.    if (MasterBootRecord.Signature != BOOT_SIGNATURE)
  222.    {
  223.       printf("Invalid partition table!\n");
  224.       exit(-1);
  225.    }
  226.  
  227.  
  228.  
  229.    /* Find the partition we booted from and validate it. */
  230.  
  231.    for (ActivePartition=0; ActivePartition<4; ActivePartition++)
  232.    {
  233.       if (MasterBootRecord.PTable[ActivePartition].Active == 0x80)
  234.          break;
  235.    }
  236.    if (ActivePartition > 3)
  237.    {
  238.       printf("No bootable partition in table!\n");
  239.       exit(-1);
  240.    }
  241.    if ((MasterBootRecord.PTable[ActivePartition].PartitionType != 0x01) &&
  242.        (MasterBootRecord.PTable[ActivePartition].PartitionType != 0x04) &&
  243.        (MasterBootRecord.PTable[ActivePartition].PartitionType != 0x06))
  244.    {
  245.       printf("Unable to work with partition type %02x.\n",
  246.                MasterBootRecord.PTable[ActivePartition].PartitionType);
  247.       exit(-1);
  248.    }
  249.  
  250.  
  251.  
  252.    /* Get the boot sector from active partition. */
  253.  
  254.    if (ReadAbsSector('C',
  255.                      MasterBootRecord.PTable[ActivePartition].StartingHead,
  256.                      MasterBootRecord.PTable[ActivePartition].StartingCylinder,
  257.                      MasterBootRecord.PTable[ActivePartition].StartingSector,
  258.                      &DiskBootSector) != 0)
  259.    {
  260.       printf("Unable to read fixed disk boot sector.\n");
  261.       exit(-1);
  262.    }
  263.  
  264.  
  265.  
  266.    /* Validate the boot sector. */
  267.  
  268.    if (DiskBootSector.Signature != BOOT_SIGNATURE)
  269.    {
  270.       printf("Invalid boot sector!\n");
  271.       exit(-1);
  272.    }
  273.  
  274.  
  275.  
  276.    /* Determine whether NT or DOS boot sector is currently installed. */
  277.  
  278.    if (SearchSector(DiskBootSector.LoaderPgm, "NTLDR"))
  279.    {
  280.       CurrentBootSector = BOOT_IS_NT;
  281.    }
  282.    else if (SearchSector(DiskBootSector.LoaderPgm, "Non-System"))
  283.    {
  284.       CurrentBootSector = BOOT_IS_DOS;
  285.    }
  286.    else
  287.    {
  288.       printf("Unable to identify current boot sector contents.\n");
  289.       exit(-1);
  290.    }
  291.  
  292.  
  293.  
  294.    /* At last! Perform specified action. */
  295.  
  296.    switch (Operation)
  297.    {
  298.       case DISPLAY_CURRENT_STATUS:
  299.          if (CurrentBootSector == BOOT_IS_NT)
  300.             printf("Current boot sector is for Windows NT.\n");
  301.          else if (CurrentBootSector == BOOT_IS_DOS)
  302.             printf("Current boot sector is for DOS.\n");
  303.          break;
  304.  
  305.       case SAVE_CURRENT_BOOTSECT:
  306.          if (CurrentBootSector == BOOT_IS_NT)
  307.             strcpy(szBootSectorFile, szNTBootSectorFile);
  308.          else if (CurrentBootSector == BOOT_IS_DOS)
  309.             strcpy(szBootSectorFile, szDOSBootSectorFile);
  310.  
  311.          if ((hBootSectorFile = _open(szBootSectorFile,
  312.                                  _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY,
  313.                                  _S_IREAD | _S_IWRITE)) == -1)
  314.          {
  315.             printf("Unable to create/open boot sector file %s.\n",
  316.                      szBootSectorFile);
  317.             exit(-1);
  318.          }
  319.          else
  320.          {
  321.             if (_write(hBootSectorFile, &DiskBootSector, DISK_SECTOR_SIZE)
  322.                   != DISK_SECTOR_SIZE)
  323.             {
  324.                printf("Unable to write boot sector file %s.\n",
  325.                         szBootSectorFile);
  326.             }
  327.             else
  328.             {
  329.                if (CurrentBootSector == BOOT_IS_NT)
  330.                   printf("Boot sector for Windows NT saved in %s.\n",
  331.                         szBootSectorFile);
  332.                else if (CurrentBootSector == BOOT_IS_DOS)
  333.                   printf("Boot sector for DOS saved in %s.\n",
  334.                         szBootSectorFile);
  335.             }
  336.             _close(hBootSectorFile);
  337.          }
  338.          break;
  339.  
  340.       case INSTALL_NT_BOOTSECT:
  341.       case INSTALL_DOS_BOOTSECT:
  342.          if (Operation == INSTALL_NT_BOOTSECT)
  343.             strcpy(szBootSectorFile, szNTBootSectorFile);
  344.          else if (Operation == INSTALL_DOS_BOOTSECT)
  345.             strcpy(szBootSectorFile, szDOSBootSectorFile);
  346.  
  347.          if ((hBootSectorFile = _open(szBootSectorFile,
  348.                                  _O_BINARY | _O_RDONLY )) == -1)
  349.          {
  350.             printf("Unable to open boot sector file %s.\n", szBootSectorFile);
  351.             exit(-1);
  352.          }
  353.          else
  354.          {
  355.             /* Read in the boot sector and validate it. */
  356.  
  357.             if (_read(hBootSectorFile, &FileBootSector, DISK_SECTOR_SIZE)
  358.                   != DISK_SECTOR_SIZE)
  359.             {
  360.                printf("Corrupt boot sector file %s.\n", szBootSectorFile);
  361.                bFileOK = FALSE;
  362.             }
  363.             else
  364.             {
  365.                if ( FileBootSector.Signature != BOOT_SIGNATURE ||
  366.                     ( !SearchSector(FileBootSector.LoaderPgm, "NTLDR") &&
  367.                       !SearchSector(FileBootSector.LoaderPgm, "Non-System")))
  368.                {
  369.                   printf("%s is not a valid boot sector.\n", szBootSectorFile);
  370.                   bFileOK = FALSE;
  371.                }
  372.                else
  373.                {
  374.                   /* Ensure that the boot sector is for THIS drive. */
  375.  
  376.                   if (memcmp(DiskBootSector.BIOSParameterBlock,
  377.                              FileBootSector.BIOSParameterBlock,
  378.                              sizeof FileBootSector.BIOSParameterBlock))
  379.                   {
  380.                      printf("%s disk parameters do not match current boot sector.\n",
  381.                               szBootSectorFile);
  382.                      bFileOK = FALSE;
  383.                   }
  384.                }
  385.             }
  386.  
  387.  
  388.             /* If the boot sector is OK, install it. */
  389.  
  390.             if (bFileOK)
  391.             {
  392.                if (WriteAbsSector('C',
  393.                      MasterBootRecord.PTable[ActivePartition].StartingHead,
  394.                      MasterBootRecord.PTable[ActivePartition].StartingCylinder,
  395.                      MasterBootRecord.PTable[ActivePartition].StartingSector,
  396.                      &FileBootSector) != 0)
  397.                {
  398.                   printf("Unable to write boot sector.\n");
  399.                   bFileOK = FALSE;
  400.                }
  401.                else
  402.                {
  403.                   if (Operation == INSTALL_NT_BOOTSECT)
  404.                      printf("Boot sector for Windows NT installed.\n");
  405.                   else if (Operation == INSTALL_DOS_BOOTSECT)
  406.                      printf("Boot sector for DOS installed.\n");
  407.                }
  408.             }
  409.  
  410.  
  411.             _close(hBootSectorFile);
  412.             if (!bFileOK)
  413.                exit(-1);
  414.          }
  415.          break;
  416.    }
  417.  
  418.  
  419.    return(0);
  420. }
  421.  
  422.  
  423.  
  424.  
  425. /***************************************************************************
  426.   Function . . : ReadAbsSector()
  427.   Purpose  . . : Read an absolute sector from a disk into buffer.
  428. */
  429.  
  430. int ReadAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
  431.                   void _far *Buffer)
  432. {
  433.    int BufferSegmnt = _FP_SEG(Buffer);
  434.    int BufferOffset = _FP_OFF(Buffer);
  435.    BYTE DriveNumber;
  436.  
  437.    switch (Drive)
  438.    {
  439.       case 'A': DriveNumber = 0x00; break;
  440.       case 'B': DriveNumber = 0x01; break;
  441.       case 'C': DriveNumber = 0x80; break;
  442.       default:  return(1);
  443.    }
  444.    _asm
  445.    {
  446.       mov   ah, 2                ; Read sectors operation
  447.       mov   al, 1                ; 1 sector
  448.       mov   dl, DriveNumber
  449.       mov   dh, Head
  450.       mov   ch, Track
  451.       mov   cl, Sector
  452.       mov   es, BufferSegmnt
  453.       mov   bx, BufferOffset
  454.       int   13h                  ; BIOS fixed disk routines.
  455.       jc    RPTErr               ; Carry indicates error, AX nonzero.
  456.       cmp   al, 1                ; 1 sector transferred?
  457.       jne   RPTErr               ; If not, error occurred.
  458.       xor   ax, ax               ; Clear AX to indicate success.
  459. RPTErr:
  460.    }
  461.    /* Return value present in AX register. */
  462. }
  463.  
  464.  
  465.  
  466.  
  467. /***************************************************************************
  468.   Function . . : WriteAbsSector()
  469.   Purpose  . . : Write an absolute sector from buffer to a disk.
  470. */
  471.  
  472. int WriteAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
  473.                   void _far *Buffer)
  474. {
  475.    int BufferSegmnt = _FP_SEG(Buffer);
  476.    int BufferOffset = _FP_OFF(Buffer);
  477.    BYTE DriveNumber;
  478.  
  479.    switch (Drive)
  480.    {
  481.       case 'A': DriveNumber = 0x00; break;
  482.       case 'B': DriveNumber = 0x01; break;
  483.       case 'C': DriveNumber = 0x80; break;
  484.       default:  return(1);
  485.    }
  486.    _asm
  487.    {
  488.       mov   ah, 3                ; Write sectors operation
  489.       mov   al, 1                ; 1 sector
  490.       mov   dl, DriveNumber
  491.       mov   dh, Head
  492.       mov   ch, Track
  493.       mov   cl, Sector
  494.       mov   es, BufferSegmnt
  495.       mov   bx, BufferOffset
  496.       int   13h                  ; BIOS fixed disk routines.
  497.       jc    RPTErr               ; Carry indicates error, AX nonzero.
  498.       cmp   al, 1                ; 1 sector transferred?
  499.       jne   RPTErr               ; If not, error occurred.
  500.       xor   ax, ax               ; Clear AX to indicate success.
  501. RPTErr:
  502.    }
  503.    /* Return value present in AX register. */
  504. }
  505.  
  506.  
  507.  
  508.  
  509. /***************************************************************************
  510.   Function . . : SearchSector()
  511.   Purpose  . . : Verify existence of a distinguishing string in a sector.
  512. */
  513.  
  514. int SearchSector(BYTE *Sector, char *String)
  515. {
  516.    BYTE *SectorEnd = Sector + DISK_SECTOR_SIZE;
  517.  
  518.  
  519.  
  520.    for (Sector  = memchr(Sector, String[0], DISK_SECTOR_SIZE);
  521.         Sector != NULL && Sector < SectorEnd;
  522.         Sector  = memchr(Sector+1, String[0], SectorEnd - Sector))
  523.    {
  524.       if (!memicmp(Sector, String, strlen(String)))
  525.          return(1);
  526.    }
  527.    return(0);
  528. }
  529.