home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / PMFLOPPY.ZIP / DSKCPY.C < prev    next >
C/C++ Source or Header  |  1990-04-24  |  18KB  |  562 lines

  1. #define INCL_DOSERRORS
  2. #define INCL_DOSPROCESS
  3. #define INCL_BASE
  4. #define INCL_DOSDEVIOCTL
  5. #define INCL_DOSSESMGR
  6. #define INCL_DOSMISC
  7. #include <os2.h>
  8. #include <malloc.h>
  9. #include <stdlib.h>
  10. #include <stdarg.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "pmfloppy.h"
  14.  
  15. /* Global variables ------------------------------------------------------ */
  16.  
  17. // PM vbls
  18. extern HWND   hWndFrame ;
  19.  
  20. // Disk handling vbls
  21. extern int   gotSource;           /* Bool: Source disk has been read    */
  22.  
  23. // user response vbls
  24. extern USHORT FormatOptions;     // Bit map indicating formatting choice
  25. extern CHAR   Volume[11];        // Volume Name
  26.  
  27. // "local" global vbls
  28. BYTE         _lockCmd;            /* Used with [un]lockdrive macros     */
  29. ULONG        _fmtData;            /* Used with DSK_FORMATVERIFY         */
  30.                                          /*  (kudos to RMK!)                   */
  31. BSPBLK       sourceParms;         /* Param block for source drive       */
  32. PBYTE        *sourceBuffer;       /* Array of pointers to track buffers */
  33. ULONG        sourceBytes;         /* # bytes on source disk             */
  34. USHORT       sourceTracks;        /* # tracks on source disk            */
  35. USHORT       bytesPerTrack;       /* Bytes per track on source disk     */
  36. PTRACKLAYOUT sourceLayout;        /* Pointer to track layout table      */
  37. USHORT       sizeofLayoutElement; /* Total size of layout table         */
  38.  
  39. USHORT DiskError;
  40.  
  41.  
  42. /* Prototypes ------------------------------------------------------------ */
  43.  
  44. VOID FAR readsource(USHORT);
  45. VOID FAR writetarget(USHORT);
  46. VOID FAR fmtdisk(USHORT);
  47. BYTE  fmttbl_bytessec(USHORT bytesPerSec);
  48. int   bspblkcmp(BSPBLK *blk1, BSPBLK *blk2);
  49. void far *Alloc(unsigned num, unsigned size);
  50. void ThreadErrorHandler(USHORT, USHORT, HFILE);
  51. VOID fatset(int, CHAR *,int,int);
  52.  
  53.  
  54. /* Code ------------------------------------------------------------------ */
  55.  
  56.  
  57.   /* --- Read source disk into memory ---
  58.   **       parameter is drive handle as returned from opendrive()
  59.   **       reads the entire source disk into memory allocating as it goes,
  60.   **        when done sourceBuffer points to an array of buffer pointers,
  61.   **        one for each track on the disk and each the the size of a track
  62.   **        in bytes.
  63.   **       sets global variables:
  64.   **        gotSource
  65.   **        sourceBytes
  66.   **        sourceTracks
  67.   **        bytesPerTrack
  68.   **        sizeofLayoutElement
  69.   **        sourceBuffer
  70.   **        sourceLayout
  71.   **        DiskError
  72.   */
  73. VOID FAR readsource(USHORT Drive)
  74. {
  75. BYTE   _parmCmd = 1;
  76. USHORT trk, hd, cyl;
  77. HFILE  dHandle;
  78. USHORT result;
  79. static CHAR szdrive[] = "A:";
  80.  
  81.   DiskError = 0;
  82.   /* If this isn't the first time here, free memory from last time first */
  83.   if (gotSource)
  84.     {
  85.     for (trk = 0; trk < sourceTracks; trk++)
  86.       free(sourceBuffer[trk]);
  87.     free(sourceBuffer);
  88.     free(sourceLayout);
  89.     sourceBuffer = NULL;
  90.     sourceLayout = NULL;
  91.     gotSource = FALSE;
  92.     }
  93.  
  94.   /* Get source disk parameters */
  95.   DosError(HARDERROR_DISABLE);
  96.   szdrive[0] = (CHAR) Drive;
  97.   DiskError = DosOpen(szdrive, &dHandle, &result, 0L, 0, FILE_OPEN, OPENFLAGS, 0L);
  98.   if (DiskError)
  99.     ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  100.  
  101.   lockdrive(dHandle);
  102.   if (DiskError)
  103.     ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  104.  
  105.   DiskError = DosDevIOCtl(&sourceParms, &_parmCmd, DSK_GETDEVICEPARAMS, IOCTL_DISK, dHandle);
  106.   if (!DiskError)
  107.   {
  108.     /* Set all the informational variables and build a track layout table
  109.     **  for use with the following sector reads.
  110.     */
  111.     sourceBytes   = (ULONG)(sourceParms.usBytesPerSector) *
  112.                     (ULONG)(sourceParms.cSectors);
  113.     sourceTracks  = sourceParms.cSectors         /
  114.                     sourceParms.usSectorsPerTrack;
  115.     bytesPerTrack = sourceParms.usBytesPerSector *
  116.                     sourceParms.usSectorsPerTrack;
  117.  
  118.     sizeofLayoutElement = sizeof(TRACKLAYOUT)   +
  119.                           ((2 * sizeof(USHORT)) *
  120.                           (sourceParms.usSectorsPerTrack - 1));
  121.  
  122.     if (sourceLayout = (PTRACKLAYOUT)Alloc(sizeofLayoutElement, sizeof(BYTE)))
  123.     {
  124.       sourceLayout->bCommand = 1;
  125.       sourceLayout->usFirstSector = 0;
  126.       sourceLayout->cSectors = sourceParms.usSectorsPerTrack;
  127.       for (trk = 0; trk < sourceParms.usSectorsPerTrack; trk++)
  128.       {
  129.         sourceLayout->TrackTable[trk].usSectorNumber = trk+1;
  130.         sourceLayout->TrackTable[trk].usSectorSize = sourceParms.usBytesPerSector;
  131.       }
  132.     }
  133.     else
  134.       ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  135.  
  136.     /* Allocate the array of BYTE pointers to hold the track data */
  137.     if ((sourceBuffer = (PBYTE *)Alloc(sourceTracks, sizeof(PBYTE))) == NULL)
  138.       ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  139.  
  140.     /* For each track, allocate a buffer and read the sector into it */
  141.     for (trk = 0, cyl = 0; trk < sourceTracks; trk += sourceParms.cHeads, cyl++)
  142.     {
  143.       sourceLayout->usCylinder = cyl;
  144.       for (hd = 0; hd < sourceParms.cHeads; hd++)
  145.       {
  146.         WinPostMsg(hWndFrame,UM_READSTATUS,
  147.           MPFROM2SHORT((cyl*2)+hd,sourceTracks),MPFROMSHORT(Drive));
  148.         sourceLayout->usHead = hd;
  149.         if ((sourceBuffer[trk+hd] = (PBYTE)Alloc(bytesPerTrack, sizeof(BYTE))) == NULL)
  150.           ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  151.         if (DiskError = DosDevIOCtl(sourceBuffer[trk+hd], sourceLayout, DSK_READTRACK, IOCTL_DISK, dHandle))
  152.           ThreadErrorHandler(UM_READERROR, Drive, dHandle);
  153.       }
  154.     }
  155.  
  156.     WinPostMsg(hWndFrame,UM_READMSG,MPFROMSHORT(0),MPFROMSHORT(Drive));
  157.     gotSource = TRUE;
  158.   }
  159.   else
  160.     WinPostMsg(hWndFrame,UM_READERROR,MPFROMSHORT(DiskError),MPFROMSHORT(Drive));
  161.  
  162.   if (dHandle) DosClose(dHandle);
  163.   unlockdrive(dHandle);
  164.   DosError(HARDERROR_ENABLE);
  165.   DosExit(EXIT_THREAD, 0);
  166. }  // readsource
  167.  
  168.  
  169.  
  170. /* --- Translate bytes per sector into 0-3 code ---
  171. **       the four sector sizes listed below are alluded to in the OS/2
  172. **        docs however only 512 byte sectors are allowed under OS/2 1.x
  173. **       returns the code or -1 and sets DiskError
  174. */
  175. BYTE fmttbl_bytessec(USHORT bytesPerSec)
  176. {
  177.  
  178.   DiskError = NO_ERROR;
  179.   switch (bytesPerSec)
  180.   {
  181.     case 128:  return 0;
  182.     case 256:  return 1;
  183.     case 512:  return 2;
  184.     case 1024: return 3;
  185.   }
  186.   DiskError = ERROR_BAD_FORMAT;
  187.   return -1;
  188. }
  189.  
  190.  
  191.  
  192. /* --- write information read by readsource() onto target disk ---
  193. **       parameter is drive handle as returned by opendrive()
  194. **       checks the target disk, if it's the same format as the source
  195. **        or not formatted at all, write the information contained in
  196. **        sourceBuffer formatting if neccessary.
  197. **       returns 0 if successful else errorcode (DiskError)
  198. **
  199. */
  200. VOID FAR writetarget(USHORT Drive)
  201. {
  202. BYTE         _parmCmd = 1;
  203. PTRACKFORMAT trkfmt;
  204. USHORT       sizeofTrkfmt;
  205. int          i, trk, hd, cyl, needFormat = FALSE;
  206. HFILE        hf;
  207. USHORT       result;
  208. static CHAR  szdrive[] = "A:";
  209. BSPBLK       targetParms;
  210.  
  211.   /* Get source disk parameters */
  212.   DosError(HARDERROR_DISABLE);
  213.   szdrive[0] = (CHAR) Drive;
  214.   DiskError = DosOpen(szdrive, &hf, &result, 0L, 0, FILE_OPEN, OPENFLAGS, 0L);
  215.   if (DiskError)
  216.     ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  217.  
  218.   lockdrive(hf);
  219.   if (DiskError)
  220.     ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  221.  
  222.   /* Get target disk parameters */
  223.   DiskError = DosDevIOCtl(&targetParms, &_parmCmd, DSK_GETDEVICEPARAMS, IOCTL_DISK, hf);
  224.  
  225.   if ((DiskError == ERROR_READ_FAULT) && (FormatOptions == IDD_WRF_NEVER))
  226.     ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  227.  
  228.   if (((DiskError == ERROR_READ_FAULT) && (FormatOptions == IDD_WRF_MAYBE)) ||
  229.       (FormatOptions == IDD_WRF_ALWAYS))
  230.   {
  231.     /* If the disk needs formatting we build a format table for it based
  232.     **  on the source disk.
  233.     */
  234.     needFormat = TRUE;
  235.     DiskError = 0;
  236.     /* Set all the informational variables and build a track layout table
  237.     **  for use with the following sector reads.
  238.     */
  239.     sourceBytes   = (ULONG)(sourceParms.usBytesPerSector) *
  240.                     (ULONG)(sourceParms.cSectors);
  241.     sourceTracks  = sourceParms.cSectors         /
  242.                     sourceParms.usSectorsPerTrack;
  243.     bytesPerTrack = sourceParms.usBytesPerSector *
  244.                     sourceParms.usSectorsPerTrack;
  245.  
  246.     sizeofTrkfmt = sizeof(TRACKFORMAT) +
  247.                     ((4 * sizeof(BYTE)) *
  248.                     (sourceParms.usSectorsPerTrack - 1));
  249.     if ((trkfmt = (PTRACKFORMAT)Alloc(sizeofTrkfmt, sizeof(BYTE))) == NULL)
  250.       ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  251.  
  252.     trkfmt->bCommand = 1;
  253.     trkfmt->cSectors = sourceParms.usSectorsPerTrack;
  254.     for (trk = 0; trk < trkfmt->cSectors; trk++)
  255.     {
  256.       trkfmt->FormatTable[trk].idSector = (BYTE)(trk+1);
  257.       trkfmt->FormatTable[trk].bBytesSector = fmttbl_bytessec(sourceParms.usBytesPerSector);
  258.     }
  259.   }
  260.   else if (!DiskError)
  261.     /* Else if no other error, make sure that the target disk is the same
  262.     **  format as the source.
  263.     */
  264.     if (bspblkcmp(&sourceParms, &targetParms))
  265.       DiskError = DSKCPY_ERROR_WRONG_FORMAT;
  266.  
  267.  
  268.   if (!DiskError)
  269.   {
  270.     for (trk = 0, cyl = 0; trk < sourceTracks; trk += sourceParms.cHeads, cyl++)
  271.     {
  272.       sourceLayout->usCylinder = cyl;
  273.       for (hd = 0; hd < sourceParms.cHeads; hd++)
  274.       {
  275.         WinPostMsg(hWndFrame,UM_WRITESTATUS,
  276.           MPFROM2SHORT((cyl*2)+hd,sourceTracks),MPFROMSHORT(Drive));
  277.         sourceLayout->usHead = hd;
  278.         if (needFormat)
  279.         {
  280.           trkfmt->usHead = hd;
  281.           trkfmt->usCylinder = cyl;
  282.           for (i = 0; i < trkfmt->cSectors; i++)
  283.           {
  284.             trkfmt->FormatTable[i].bHead = (BYTE)hd;
  285.             trkfmt->FormatTable[i].bCylinder = (BYTE)cyl;
  286.           }
  287.  
  288.           if (DiskError = DosDevIOCtl(&_fmtData, trkfmt, DSK_FORMATVERIFY, IOCTL_DISK, hf))
  289.             ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  290.         }
  291.         if (DiskError = DosDevIOCtl(sourceBuffer[trk+hd], sourceLayout, DSK_WRITETRACK, IOCTL_DISK, hf))
  292.           ThreadErrorHandler(UM_WRITEERROR, Drive, hf);
  293.       }
  294.     }
  295.  
  296.     WinPostMsg(hWndFrame,UM_WRITEMSG,MPFROMSHORT(0),MPFROMSHORT(Drive));
  297.     if (needFormat) free(trkfmt);
  298.   }
  299.   else
  300.     WinPostMsg(hWndFrame,UM_WRITEERROR,MPFROMSHORT(DiskError),MPFROMSHORT(Drive));
  301.  
  302.   if (hf) DosClose(hf);
  303.   unlockdrive(hf);
  304.   DosError(HARDERROR_ENABLE);
  305.   DosExit(EXIT_THREAD, 0);
  306. } //writetarget
  307.  
  308.  
  309. // --- format a disk ---
  310. //       parameter is ascii char indicating drive
  311. //
  312. //  This will currently format a disk, but track 0 needs some addt'l work
  313. //  to set up the FAT table and the directory table.  Also, I couldn't find
  314. //  a way to detect an unformatted low density disk in a high density drive.
  315. //  The MS Format program requires the user to provide that info, but I've
  316. //  seen third party stuff that detects this.  Perhaps they write the first
  317. //  track HD, then try to read it?  Anyway, it's kind of interesting
  318. //  to actually run this and see what it does.
  319. //
  320. VOID FAR fmtdisk(USHORT Drive)
  321. {
  322. BYTE         _getparmCmd = 0;
  323. PTRACKFORMAT trkfmt;
  324. PTRACKLAYOUT trklout;
  325. USHORT       sizeofTrkfmt;
  326. int          i, j, trk, hd, cyl, sec;
  327. HFILE        hf;
  328. USHORT       result;
  329. static CHAR  szdrive[] = "A:";
  330. BSPBLK       BPB;
  331. USHORT       fmtTracks;        /* # tracks on source disk            */
  332. USHORT       ReservedSize;
  333. PBYTE        *sectordata;
  334. PCHAR        fatptr;
  335. USHORT       fatlen;
  336. PCHAR        rootptr;
  337. USHORT       rootsize;
  338. USHORT       rootentries;
  339. USHORT       writesize;
  340. USHORT       skippedsectors;
  341. USHORT       maxcluster;
  342. USHORT       size;
  343. LONG         devicesize;
  344.  
  345.   /* Get format disk parameters */
  346.   DosError(HARDERROR_DISABLE);
  347.   szdrive[0] = (CHAR) Drive;
  348.   DiskError = DosOpen(szdrive, &hf, &result, 0L, 0, FILE_OPEN, OPENFLAGS, 0L);
  349.   if (DiskError)
  350.     ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  351.  
  352.   lockdrive(hf);
  353.   if (DiskError)
  354.     ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  355.  
  356.   /* Get target drive parameters */
  357.   DiskError = DosDevIOCtl(&BPB, &_getparmCmd, DSK_GETDEVICEPARAMS, IOCTL_DISK, hf);
  358.   if (DiskError)
  359.     ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  360.  
  361.   // build a format table for the disk
  362.   fmtTracks  = BPB.cSectors / BPB.usSectorsPerTrack;
  363.   sizeofTrkfmt = sizeof(TRACKFORMAT) +
  364.                   ((4 * sizeof(BYTE)) *
  365.                   (BPB.usSectorsPerTrack - 1));
  366.   if ((trkfmt = (PTRACKFORMAT)Alloc(sizeofTrkfmt, sizeof(BYTE))) == NULL)
  367.     ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  368.  
  369.   trkfmt->bCommand = 1;
  370.   trkfmt->cSectors = BPB.usSectorsPerTrack;
  371.   for (trk = 0; trk < trkfmt->cSectors; trk++)
  372.   {
  373.     trkfmt->FormatTable[trk].idSector = (BYTE)(trk+1);
  374.     trkfmt->FormatTable[trk].bBytesSector = fmttbl_bytessec(BPB.usBytesPerSector);
  375.   }
  376.  
  377.   if (!DiskError)
  378.   {
  379.     for (trk = 0, cyl = 0; trk < fmtTracks; trk += BPB.cHeads, cyl++)
  380.     {
  381.       for (hd = 0; hd < BPB.cHeads; hd++)
  382.       {
  383.         WinPostMsg(hWndFrame,UM_FMTSTATUS,
  384.           MPFROM2SHORT((cyl*2)+hd,fmtTracks),MPFROMSHORT(Drive));
  385.         trkfmt->usHead = hd;
  386.         trkfmt->usCylinder = cyl;
  387.         for (i = 0; i < trkfmt->cSectors; i++)
  388.         {
  389.           trkfmt->FormatTable[i].bHead = (BYTE)hd;
  390.           trkfmt->FormatTable[i].bCylinder = (BYTE)cyl;
  391.         }
  392.  
  393.         if (DiskError = DosDevIOCtl(&_fmtData, trkfmt, DSK_FORMATVERIFY, IOCTL_DISK, hf))
  394.           ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  395.       }
  396.       free(trkfmt);
  397.     }
  398.  
  399. // Allocate space for track 0
  400.     bytesPerTrack = BPB.usBytesPerSector * BPB.usSectorsPerTrack;
  401.     if ((sectordata = (PBYTE *)Alloc(bytesPerTrack, sizeof(PBYTE))) == NULL)
  402.       ThreadErrorHandler(UM_READERROR, Drive, hf);
  403.  
  404.     ReservedSize = BPB.usBytesPerSector * BPB.usReservedSectors;
  405.     for (sec=0;sec<ReservedSize;sec++)
  406.       *(sectordata+sec) = 0;
  407.     for (sec=0;sec<sizeof(BSPBLK); sec++)
  408.       *(sectordata+sec+11) = ((CHAR *)(&BPB))[sec];
  409.     strncpy((sectordata+3),"OS/2    ",8);
  410.  
  411.     fatptr = sectordata + ReservedSize;
  412.     fatlen = BPB.usSectorsPerFAT * BPB.usBytesPerSector;
  413.     for (i=0;i<BPB.cFATs * fatlen;i++)
  414.       fatptr[i] = -1;
  415.  
  416.     rootptr = fatptr + BPB.cFATs * fatlen;
  417.     rootsize = BPB.usBytesPerSector *
  418.       ((BPB.usBytesPerSector - 1 + 32*BPB.cRootEntries)/BPB.usBytesPerSector);
  419.     rootentries = rootsize / 32;
  420.     writesize = ReservedSize + fatlen*BPB.cFATs + rootsize;
  421.     skippedsectors = writesize / BPB.usBytesPerSector;
  422.  
  423.     if (BPB.cSectors != 0)
  424.     {
  425.       devicesize = BPB.cSectors * BPB.usBytesPerSector;
  426.       maxcluster = (BPB.cSectors - skippedsectors) / BPB.bSectorsPerCluster + 2;
  427.       if (BPB.cSectors <= 20740)
  428.         size = 12;
  429.       else
  430.         size = 16;
  431.     }
  432.     else
  433.     {
  434.       devicesize = BPB.cLargeSectors * BPB.usBytesPerSector;
  435.       maxcluster =
  436.         (BPB.cLargeSectors - skippedsectors) / BPB.bSectorsPerCluster + 2;
  437.       if (BPB.cLargeSectors <= 20740)
  438.         size = 12;
  439.       else
  440.         size = 16;
  441.     }
  442.  
  443.     for (i=2;i<maxcluster;i++)
  444.       for (j=0;j<BPB.cFATs;j++)
  445.         fatset(size,fatptr+j*fatlen,i,0);
  446.  
  447.     for (i=0;i<BPB.cFATs;i++)
  448.     {
  449.       fatset(size,fatptr+i*fatlen,0,BPB.bMedia);
  450.       fatset(size,fatptr+i*fatlen,1,-1);
  451.     }
  452.  
  453.     for (i=0;i<rootentries;i++)
  454.       for (j=0;j<32;j++)
  455.         rootptr[i*32+j] = 0;
  456.     for (i=0;i<11;i++)
  457.       rootptr[i] = Volume[i];
  458.     rootptr[11] = 8;
  459.  
  460. // write track 0
  461.     sizeofLayoutElement = sizeof(TRACKLAYOUT) + ((2 * sizeof(USHORT)) *
  462.                         (BPB.usSectorsPerTrack - 1));
  463.  
  464.     if (trklout = (PTRACKLAYOUT)Alloc(sizeofLayoutElement, sizeof(BYTE)))
  465.     {
  466.       trklout->bCommand = 1;
  467.       trklout->cSectors = BPB.usSectorsPerTrack;
  468.       for (trk = 0; trk < BPB.usSectorsPerTrack; trk++)
  469.       {
  470.         trklout->TrackTable[trk].usSectorNumber = trk+1;
  471.         trklout->TrackTable[trk].usSectorSize = BPB.usBytesPerSector;
  472.       }
  473.     }
  474.  
  475.     for (sec=0;sec<skippedsectors;sec++)
  476.     {
  477.       cyl = sec / (BPB.usSectorsPerTrack * BPB.cHeads);
  478.       hd = (sec - cyl*BPB.usSectorsPerTrack*BPB.cHeads) / BPB.usSectorsPerTrack;
  479.       trklout->usHead = hd;
  480.       trklout->usCylinder = cyl;
  481.       trklout->usFirstSector = (sec - cyl*BPB.usSectorsPerTrack*BPB.cHeads
  482.                                 - hd*BPB.usSectorsPerTrack);
  483.       if (DiskError = DosDevIOCtl(sectordata+sec*BPB.usBytesPerSector,trklout,
  484.                             DSK_WRITETRACK,IOCTL_DISK,hf))
  485.         ThreadErrorHandler(UM_FMTERROR, Drive, hf);
  486.     }
  487.     free(trklout);
  488.     free(sectordata);
  489.     WinPostMsg(hWndFrame,UM_FMTMSG,MPFROMSHORT(0),MPFROMSHORT(Drive));
  490.   }
  491.   else
  492.     WinPostMsg(hWndFrame,UM_FMTERROR,MPFROMSHORT(DiskError),MPFROMSHORT(Drive));
  493.  
  494.   if (hf) DosClose(hf);
  495.   unlockdrive(hf);
  496.   DosError(HARDERROR_ENABLE);
  497.   DosExit(EXIT_THREAD, 0);
  498. } // fmtdisk
  499.  
  500.  
  501. VOID fatset(int size, CHAR * start,int index,int value)
  502. {
  503.   int byteindex;
  504.   int * fatword;
  505.  
  506.   if (size == 16)
  507.     ((int *)start)[index] = value;
  508.   else
  509.     {
  510.     byteindex = (3*index)/2;
  511.     fatword = (int *)(start + byteindex);
  512.     if ((index & 1) == 0)
  513.       *fatword = (*fatword & 0xf000) | (value & 0xfff);
  514.     else
  515.       *fatword = (*fatword & 0xf) | ((value & 0xfff)<<4);
  516.     }
  517. }
  518.  
  519.   /* --- compare two BSPBLK structures ---
  520.   **       returns 0 if both are the same except for possibly the
  521.   **        abReserved field, else returns non-zero.
  522.   */
  523. int bspblkcmp(BSPBLK *blk1, BSPBLK *blk2)
  524.   {
  525.   BSPBLK tmp1, tmp2;
  526.  
  527.   tmp1 = *blk1;
  528.   tmp2 = *blk2;
  529.   memset(tmp1.abReserved, 0, 6);
  530.   memset(tmp2.abReserved, 0, 6);
  531.   return memcmp(&tmp1, &tmp2, sizeof(BSPBLK));
  532.   }
  533.  
  534.  
  535.  
  536.   /* --- calloc type routine ---
  537.   **       sets DiskError to ERROR_NOT_ENOUGH_MEMORY upon failure
  538.   */
  539. void far *Alloc(unsigned num, unsigned size)
  540.   {
  541.   void far *rVal;
  542.  
  543.   DiskError = NO_ERROR;
  544.   if ((rVal = _fmalloc(num * size)) == NULL)
  545.     DiskError = ERROR_NOT_ENOUGH_MEMORY;
  546.  
  547.   return rVal;
  548.   }
  549.  
  550.  
  551.  
  552. void ThreadErrorHandler(USHORT Msg, USHORT Drive, HFILE dHandle)
  553. {
  554.   WinPostMsg(hWndFrame,Msg,MPFROMSHORT(DiskError),MPFROMSHORT(Drive));
  555.   if (dHandle) DosClose(dHandle);
  556.   unlockdrive(dHandle);
  557.   DosError(HARDERROR_ENABLE);
  558.   DosExit(EXIT_THREAD, 0);
  559. }
  560.  
  561.  
  562.