home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / PMF202.ZIP / DSKIM.C < prev    next >
C/C++ Source or Header  |  1990-06-06  |  23KB  |  674 lines

  1. /*
  2.            dskim.c
  3.            
  4.            disk handling routines for pmfloppy.c
  5.  
  6.            Copyright G. Bryant, 1990
  7.  
  8.    
  9.   Change Log
  10.  
  11. */
  12.  
  13. #define INCL_DOSERRORS
  14. #define INCL_DOSPROCESS
  15. #define INCL_BASE
  16. #define INCL_DOSDEVIOCTL
  17. #define INCL_DOSSESMGR
  18. #define INCL_DOSMISC
  19. #include <os2.h>
  20. #include <malloc.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "pmfloppy.h"
  24. #include "DskIm.h"
  25.  
  26. /* Global variables ------------------------------------------------------ */
  27.  
  28. // PM vbls
  29. extern HWND   hWndFrame ;
  30.  
  31. // user response vbls
  32. extern DskImage ImageBuffers[NUM_IMAGES];
  33.  
  34. // Thread variables
  35. extern ThreadContext tcThBufs[NUM_THREADS];
  36.  
  37. // "local" global vbls
  38. BYTE         _lockCmd;            /* Used with [un]lockdrive macros     */
  39. ULONG        _fmtData;            /* Used with DSK_FORMATVERIFY         */
  40.  
  41. // Global function prototypes
  42. VOID FAR readsource(USHORT);
  43. VOID FAR writetarget(USHORT);
  44. VOID FAR LoadImage(USHORT);
  45. VOID FAR SaveImage(USHORT);
  46. VOID FAR CompImages(USHORT);
  47.  
  48. // local function prototypes
  49. SHORT    fmttbl_bytessec(USHORT, USHORT *);
  50. SHORT    bspblkcmp(BSPBLK *, BSPBLK *);
  51. VOID     ThreadErrorHandler(USHORT, USHORT, HFILE);
  52. USHORT   SetBufferSel(USHORT);
  53. PBYTE    MakeHugeP(USHORT, USHORT);
  54.  
  55.  
  56.  
  57.  
  58. /* Code ------------------------------------------------------------------ */
  59.  
  60.  
  61. //   Read source disk into memory
  62. //
  63. //  when done track data is in huge space starting with selector
  64. //  stored in the global
  65. //  sets global variables:
  66. //     tcThBufs
  67. //     ImageBuffers
  68. //
  69. VOID FAR readsource(USHORT curTh) {
  70.  
  71. BYTE         parmCmd = 1;
  72. USHORT       trk, hd, cyl;
  73. HFILE        dHandle;
  74. USHORT       result;
  75. static CHAR  szdrive[] = "A:";
  76. ULONG        sourceBytes;         /* # bytes on source disk             */
  77. USHORT       sourceTracks;        /* # tracks on source disk            */
  78. USHORT       curBuff;
  79.  
  80. PBYTE        DskBuf;              // pointer to track data
  81.  
  82.   curBuff = tcThBufs[curTh].ImageNumber;
  83.  
  84.   tcThBufs[curTh].ErrorCode = 0;
  85.   /* If this isn't the first time here, free memory from last time first */
  86.   if (ImageBuffers[curBuff].Percent == 100) {
  87.     DosFreeSeg(ImageBuffers[curBuff].DskSel);
  88.     free(ImageBuffers[curBuff].DskLayout);
  89.   }
  90.  
  91.   /* Get source disk parameters */
  92.   DosError(HARDERROR_DISABLE);
  93.   szdrive[0] = ImageBuffers[curBuff].DriveID[0];
  94.   tcThBufs[curTh].ErrorCode = DosOpen(szdrive,
  95.                                       &dHandle,
  96.                                       &result,
  97.                                       0L,
  98.                                       0,
  99.                                       FILE_OPEN,
  100.                                       OPENFLAGS,
  101.                                       0L);
  102.  
  103.   if (tcThBufs[curTh].ErrorCode)
  104.     ThreadErrorHandler(UM_ERROR, curTh, dHandle);
  105.  
  106.   lockdrive(dHandle);
  107.   if (tcThBufs[curTh].ErrorCode)
  108.     ThreadErrorHandler(UM_ERROR, curTh, dHandle);
  109.  
  110.   tcThBufs[curTh].ErrorCode = DosDevIOCtl(&ImageBuffers[curBuff].DskParms,
  111.                                           &parmCmd,
  112.                                           DSK_GETDEVICEPARAMS,
  113.                                           IOCTL_DISK,
  114.                                           dHandle);
  115.  
  116.   if (!tcThBufs[curTh].ErrorCode) {
  117.     /* Set all the informational variables and build a track layout table
  118.     **  for use with the following sector reads.
  119.     */
  120.     sourceBytes   = (ULONG)(ImageBuffers[curBuff].DskParms.usBytesPerSector) *
  121.                     (ULONG)(ImageBuffers[curBuff].DskParms.cSectors);
  122.     sourceTracks  = ImageBuffers[curBuff].DskParms.cSectors         /
  123.                     ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  124.  
  125.     ImageBuffers[curBuff].usLayoutSize = sizeof(TRACKLAYOUT)   +
  126.                           ((2 * sizeof(USHORT)) *
  127.                           (ImageBuffers[curBuff].DskParms.usSectorsPerTrack - 1));
  128.  
  129.     if (ImageBuffers[curBuff].DskLayout =
  130.         (PTRACKLAYOUT)malloc(ImageBuffers[curBuff].usLayoutSize * sizeof(BYTE))) {
  131.       ImageBuffers[curBuff].DskLayout->bCommand = 1;
  132.       ImageBuffers[curBuff].DskLayout->usFirstSector = 0;
  133.       ImageBuffers[curBuff].DskLayout->cSectors = ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  134.       for (trk = 0; trk < ImageBuffers[curBuff].DskParms.usSectorsPerTrack; trk++) {
  135.         ImageBuffers[curBuff].DskLayout->TrackTable[trk].usSectorNumber = trk+1;
  136.         ImageBuffers[curBuff].DskLayout->TrackTable[trk].usSectorSize = 
  137.                                                                       ImageBuffers[curBuff].DskParms.usBytesPerSector;
  138.       }
  139.     }
  140.     else
  141.       ThreadErrorHandler(UM_ERROR, curTh, dHandle);
  142.  
  143.  
  144.  
  145.     // Allocate huge memory to hold the track data
  146.     if (tcThBufs[curTh].ErrorCode = SetBufferSel(curBuff))
  147.       ThreadErrorHandler(UM_ERROR, curTh, dHandle);
  148.  
  149.     // For each track, set the pointer and read the sector into it
  150.     for (trk = 0, cyl = 0;
  151.          trk < sourceTracks;
  152.          trk += ImageBuffers[curBuff].DskParms.cHeads, cyl++) {
  153.       ImageBuffers[curBuff].DskLayout->usCylinder = cyl;
  154.  
  155.       for (hd = 0; hd < ImageBuffers[curBuff].DskParms.cHeads; hd++) {
  156.  
  157.         ImageBuffers[curBuff].Percent =
  158.           (USHORT)(((float)((cyl*2)+hd)/(float)sourceTracks)*100.0);
  159.         WinPostMsg(hWndFrame,UM_STATUS,MPFROMSHORT(curTh),0);
  160.  
  161.         ImageBuffers[curBuff].DskLayout->usHead = hd;
  162.  
  163.         DskBuf = MakeHugeP(curBuff,trk+hd);
  164.         if (tcThBufs[curTh].ErrorCode = DosDevIOCtl(DskBuf,
  165.                                     ImageBuffers[curBuff].DskLayout,
  166.                                     DSK_READTRACK,
  167.                                     IOCTL_DISK,
  168.                                     dHandle))
  169.           ThreadErrorHandler(UM_ERROR, curTh, dHandle);
  170.       }
  171.     }
  172.     ImageBuffers[curBuff].Percent = 100;
  173.     WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(curTh),0);
  174.   }
  175.   else {
  176.     WinPostMsg(hWndFrame,UM_ERROR,MPFROMSHORT(curTh),0);
  177.   }
  178.   if (dHandle) DosClose(dHandle);
  179.   unlockdrive(dHandle);
  180.   DosError(HARDERROR_ENABLE);
  181.   DosExit(EXIT_THREAD,0);
  182. }  // readsource
  183.  
  184.  
  185. /* --- Translate bytes per sector into 0-3 code ---
  186. **       the four sector sizes listed below are alluded to in the OS/2
  187. **        docs however only 512 byte sectors are allowed under OS/2 1.x
  188. **       returns the code or -1 and sets DiskError
  189. */
  190. SHORT fmttbl_bytessec(USHORT bytesPerSec, USHORT *DiskError)
  191. {
  192.  
  193.   *DiskError = NO_ERROR;
  194.   switch (bytesPerSec)  {
  195.     case 128:  return 0;
  196.     case 256:  return 1;
  197.     case 512:  return 2;
  198.     case 1024: return 3;
  199.   }
  200.   *DiskError = ERROR_BAD_FORMAT;
  201.   return -1;
  202. }
  203.  
  204.  
  205.  
  206. /* --- write information read by readsource() onto target disk ---
  207. **       parameter is drive handle as returned by opendrive()
  208. **       checks the target disk, if it's the same format as the source
  209. **        or not formatted at all, write the information contained in
  210. **        DskBuffer formatting if neccessary.
  211. **       returns 0 if successful else errorcode
  212. **
  213. */
  214. VOID FAR writetarget(USHORT curTh) {
  215.  
  216. BYTE         _parmCmd = 1;
  217. PTRACKFORMAT trkfmt;
  218. USHORT       sizeofTrkfmt;
  219. USHORT       i, trk, hd, cyl, needFormat = FALSE;
  220. HFILE        hf;
  221. USHORT       result;
  222. static CHAR  szdrive[] = "A:";
  223. BSPBLK       targetParms;
  224. USHORT       sourceTracks;        /* # tracks on source disk            */
  225. USHORT       curBuff;
  226.  
  227. PBYTE        DskBuf;              // huge pointer to track data
  228.  
  229.   curBuff = tcThBufs[curTh].ImageNumber;
  230.  
  231.   tcThBufs[curTh].ErrorCode = 0;
  232.   /* Get source disk parameters */
  233.   DosError(HARDERROR_DISABLE);
  234.   szdrive[0] = ImageBuffers[curBuff].DriveID[0];
  235.   tcThBufs[curTh].ErrorCode = DosOpen(szdrive,
  236.                                       &hf,
  237.                                       &result,
  238.                                       0L,
  239.                                       0,
  240.                                       FILE_OPEN,
  241.                                       OPENFLAGS,
  242.                                       0L);
  243.  
  244.   if (tcThBufs[curTh].ErrorCode)
  245.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  246.  
  247.   lockdrive(hf);
  248.   if (tcThBufs[curTh].ErrorCode)
  249.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  250.  
  251.   /* Get target disk parameters */
  252.   tcThBufs[curTh].ErrorCode = DosDevIOCtl(&targetParms,
  253.                                           &_parmCmd,
  254.                                           DSK_GETDEVICEPARAMS,
  255.                                           IOCTL_DISK,
  256.                                           hf);
  257.  
  258.   if ((tcThBufs[curTh].ErrorCode == ERROR_READ_FAULT) &&
  259.       (ImageBuffers[curBuff].FormatOptions == IDD_WRF_NEVER))
  260.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  261.  
  262.   if (((tcThBufs[curTh].ErrorCode == ERROR_READ_FAULT) &&
  263.        (ImageBuffers[curBuff].FormatOptions == IDD_WRF_MAYBE)) ||
  264.       (ImageBuffers[curBuff].FormatOptions == IDD_WRF_ALWAYS))  {
  265.     /* If the disk needs formatting we build a format table for it based
  266.     **  on the source disk.
  267.     */
  268.     needFormat = TRUE;
  269.     tcThBufs[curTh].ErrorCode = 0;
  270.     // Set all the informational variables needed for formatting
  271.  
  272.     sizeofTrkfmt = sizeof(TRACKFORMAT) +
  273.                     ((4 * sizeof(BYTE)) *
  274.                     (ImageBuffers[curBuff].DskParms.usSectorsPerTrack - 1));
  275.     if ((trkfmt = (PTRACKFORMAT)malloc(sizeofTrkfmt * sizeof(BYTE))) == NULL)
  276.       ThreadErrorHandler(UM_ERROR, curTh, hf);
  277.  
  278.     trkfmt->bCommand = 1;
  279.     trkfmt->cSectors = ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  280.     for (trk = 0; trk < trkfmt->cSectors; trk++) {
  281.       trkfmt->FormatTable[trk].idSector = (BYTE)(trk+1);
  282.       trkfmt->FormatTable[trk].bBytesSector =
  283.              fmttbl_bytessec(ImageBuffers[curBuff].DskParms.usBytesPerSector,
  284.                              &(tcThBufs[curTh].ErrorCode));
  285.     }
  286.   }
  287.   else if (!tcThBufs[curTh].ErrorCode)
  288.     /* Else if no other error, make sure that the target disk is the same
  289.     **  format as the source.
  290.     */
  291.     if (bspblkcmp(&(ImageBuffers[curBuff].DskParms), &targetParms))
  292.       tcThBufs[curTh].ErrorCode = DSKIM_ERROR_WRONG_FORMAT;
  293.  
  294.   sourceTracks  = ImageBuffers[curBuff].DskParms.cSectors         /
  295.                   ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  296.  
  297.   if (!tcThBufs[curTh].ErrorCode) {
  298.     for (trk = 0, cyl = 0; trk < sourceTracks; trk += ImageBuffers[curBuff].DskParms.cHeads, cyl++) {
  299.       ImageBuffers[curBuff].DskLayout->usCylinder = cyl;
  300.       for (hd = 0; hd < ImageBuffers[curBuff].DskParms.cHeads; hd++) {
  301.         ImageBuffers[curBuff].Percent =
  302.           (USHORT)(((float)((cyl*2)+hd)/(float)sourceTracks)*100.0);
  303.         WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(curTh),0);
  304.         ImageBuffers[curBuff].DskLayout->usHead = hd;
  305.         if (needFormat)  {
  306.           trkfmt->usHead = hd;
  307.           trkfmt->usCylinder = cyl;
  308.           for (i = 0; i < trkfmt->cSectors; i++) {
  309.             trkfmt->FormatTable[i].bHead = (BYTE)hd;
  310.             trkfmt->FormatTable[i].bCylinder = (BYTE)cyl;
  311.           }
  312.  
  313.           if (tcThBufs[curTh].ErrorCode = DosDevIOCtl(&_fmtData,
  314.                                                       trkfmt,
  315.                                                       DSK_FORMATVERIFY,
  316.                                                       IOCTL_DISK,
  317.                                                       hf))
  318.             ThreadErrorHandler(UM_ERROR, curTh, hf);
  319.         }
  320.         DskBuf = MakeHugeP(curBuff,trk+hd);
  321.         if (tcThBufs[curTh].ErrorCode = DosDevIOCtl(DskBuf,
  322.                                     ImageBuffers[curBuff].DskLayout,
  323.                                     DSK_WRITETRACK,
  324.                                     IOCTL_DISK,
  325.                                     hf))
  326.           ThreadErrorHandler(UM_ERROR, curTh, hf);
  327.       }
  328.     }
  329.     ImageBuffers[curBuff].Percent = 100;
  330.     if (needFormat) free(trkfmt);
  331.     WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(curTh),0);
  332.   }
  333.   else {
  334.     WinPostMsg(hWndFrame,UM_ERROR,MPFROMSHORT(curTh),0);
  335.   }
  336.   if (hf) DosClose(hf);
  337.   unlockdrive(hf);
  338.   DosError(HARDERROR_ENABLE);
  339.   DosExit(EXIT_THREAD,0);
  340. } //writetarget
  341.  
  342.  
  343.   /* --- compare two BSPBLK structures ---
  344.   **       returns 0 if both are the same except for possibly the
  345.   **        abReserved field, else returns non-zero.
  346.   */
  347. SHORT bspblkcmp(BSPBLK *blk1, BSPBLK *blk2)  {
  348.  
  349. BSPBLK tmp1, tmp2;
  350.  
  351.   tmp1 = *blk1;
  352.   tmp2 = *blk2;
  353.   memset(tmp1.abReserved, 0, 6);
  354.   memset(tmp2.abReserved, 0, 6);
  355.   return memcmp(&tmp1, &tmp2, sizeof(BSPBLK));
  356. }
  357.  
  358.  
  359.  
  360. VOID ThreadErrorHandler(USHORT Msg, USHORT curTh, HFILE dHandle) {
  361.  
  362.   WinPostMsg(hWndFrame,Msg,MPFROMSHORT(curTh),0);
  363.  
  364.   if (dHandle) DosClose(dHandle);
  365.   unlockdrive(dHandle);
  366.   DosError(HARDERROR_ENABLE);
  367.   DosExit(EXIT_THREAD, 0);
  368. }
  369.  
  370.  
  371. // Set the selectors for the buffers to hold to disk data
  372. //
  373. // returns errnum if an error occurred, else 0
  374. //
  375. // sets DskSel & SelOff in ImageBuffers[curBuff]
  376. //
  377. USHORT SetBufferSel(USHORT curBuff) {
  378.  
  379. USHORT TpSeg;     // Tracks per Segment
  380. USHORT RemT;      // Remaining tracks
  381. USHORT tSeg;      // total segments
  382. USHORT srcT;      // # tracks on disk
  383. USHORT bpT;       // Bytes per track
  384. USHORT sCnt;      // shift count
  385. USHORT rc;        // return code from AllocHuge
  386.  
  387.   srcT  = ImageBuffers[curBuff].DskParms.cSectors         /
  388.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  389.  
  390.   bpT   = ImageBuffers[curBuff].DskParms.usBytesPerSector *
  391.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  392.  
  393.   TpSeg = (USHORT) (MAX_SEG / bpT);
  394.   tSeg  = srcT / TpSeg;
  395.   RemT  = srcT % TpSeg;
  396.   if (rc = DosAllocHuge(tSeg,
  397.                         RemT*bpT,
  398.                         &(ImageBuffers[curBuff].DskSel),
  399.                         0,
  400.                         SEG_NONSHARED))
  401.     return(rc);
  402.   DosGetHugeShift(&sCnt);
  403.   ImageBuffers[curBuff].SelOff = 1 << sCnt;
  404.   return(FALSE);
  405. }
  406.  
  407. PBYTE MakeHugeP(USHORT curBuff, USHORT Trk) {
  408.  
  409. USHORT TpSeg;     // Tracks per Segment
  410. USHORT Offs;      // offset into segment
  411. USHORT nSel;      // number of selector
  412. USHORT TSel;      // Track selector
  413. USHORT bpT;       // Bytes per track
  414.  
  415.   bpT   = ImageBuffers[curBuff].DskParms.usBytesPerSector *
  416.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  417.  
  418.   TpSeg = (USHORT) (MAX_SEG / bpT);
  419.   nSel  = Trk / TpSeg;
  420.   Offs  = (Trk % TpSeg) * bpT;
  421.  
  422.   TSel = ImageBuffers[curBuff].DskSel+(nSel * ImageBuffers[curBuff].SelOff);
  423.   return(MAKEP(TSel, Offs));
  424.  
  425. }
  426.  
  427.  
  428. // Load the disk image.
  429. //
  430. //  Note that although it is not used here, we will create the layout
  431. //  table as it is needed by writetarget
  432. //
  433. VOID FAR LoadImage(USHORT curTh) {
  434.  
  435. USHORT curBuff;
  436. USHORT bpT;            // Bytes per track
  437. USHORT sourceTracks;   // # tracks on source disk
  438. ULONG  sourceBytes;    // # bytes on source disk
  439. USHORT trk;
  440. USHORT hd;
  441. USHORT cyl;
  442. HFILE  hf;
  443. USHORT result;
  444. CHAR   Header[] = "DskImage";
  445. CHAR   NewHead[9];     // must be size of header
  446. PBYTE  DskBuf;         // huge pointer to track data
  447.  
  448.   curBuff = tcThBufs[curTh].ImageNumber;
  449.   tcThBufs[curTh].ErrorCode = 0;
  450.  
  451. // If this isn't the first time here, free memory from last time first 
  452.   if (ImageBuffers[curBuff].Percent == 100) {
  453.     DosFreeSeg(ImageBuffers[curBuff].DskSel);
  454.     free(ImageBuffers[curBuff].DskLayout);
  455.   }
  456.  
  457.   if (tcThBufs[curTh].ErrorCode = DosOpen2(ImageBuffers[curBuff].FileName,
  458.                                        &hf,
  459.                                        &result,
  460.                                        0L,
  461.                                        FILE_NORMAL,
  462.                                        FILE_OPEN,
  463.                                        OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
  464.                                        NULL,
  465.                                        0L))
  466.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  467.  
  468. // read dskim header
  469.   if (tcThBufs[curTh].ErrorCode = DosRead(hf,&NewHead,sizeof NewHead,&result))
  470.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  471.  
  472.   if (strcmp(Header,NewHead)) {
  473.     tcThBufs[curTh].ErrorCode = DSKIM_ERROR_WRONG_FILE;
  474.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  475.   }
  476.  
  477. // read parameter block
  478.   if (tcThBufs[curTh].ErrorCode = DosRead(hf,
  479.                                           &ImageBuffers[curBuff].DskParms,
  480.                                           sizeof ImageBuffers[curBuff].DskParms,
  481.                                           &result))
  482.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  483.  
  484.  
  485.   sourceBytes   = (ULONG)(ImageBuffers[curBuff].DskParms.usBytesPerSector) *
  486.                   (ULONG)(ImageBuffers[curBuff].DskParms.cSectors);
  487.   sourceTracks  = ImageBuffers[curBuff].DskParms.cSectors /
  488.                   ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  489.   bpT   = ImageBuffers[curBuff].DskParms.usBytesPerSector *
  490.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  491.  
  492.   ImageBuffers[curBuff].usLayoutSize = sizeof(TRACKLAYOUT)   +
  493.                         ((2 * sizeof(USHORT)) *
  494.                         (ImageBuffers[curBuff].DskParms.usSectorsPerTrack - 1));
  495.  
  496.   if (ImageBuffers[curBuff].DskLayout =
  497.       (PTRACKLAYOUT)malloc(ImageBuffers[curBuff].usLayoutSize * sizeof(BYTE))) {
  498.     ImageBuffers[curBuff].DskLayout->bCommand = 1;
  499.     ImageBuffers[curBuff].DskLayout->usFirstSector = 0;
  500.     ImageBuffers[curBuff].DskLayout->cSectors = ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  501.     for (trk = 0; trk < ImageBuffers[curBuff].DskParms.usSectorsPerTrack; trk++) {
  502.       ImageBuffers[curBuff].DskLayout->TrackTable[trk].usSectorNumber = trk+1;
  503.       ImageBuffers[curBuff].DskLayout->TrackTable[trk].usSectorSize =
  504.                                                                     ImageBuffers[curBuff].DskParms.usBytesPerSector;
  505.     }
  506.   }
  507.   else
  508.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  509.  
  510.  
  511.  
  512.   // Allocate huge memory to hold the track data
  513.   if (tcThBufs[curTh].ErrorCode = SetBufferSel(curBuff))
  514.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  515.  
  516. // read disk data
  517.   for (trk = 0, cyl = 0;
  518.        trk < sourceTracks;
  519.        trk += ImageBuffers[curBuff].DskParms.cHeads, cyl++) {
  520.     for (hd = 0; hd < ImageBuffers[curBuff].DskParms.cHeads; hd++) {
  521.       ImageBuffers[curBuff].Percent =
  522.         (USHORT)(((float)((cyl*2)+hd)/(float)sourceTracks)*100.0);
  523.       WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(curTh),0);
  524.  
  525.       DskBuf = MakeHugeP(curBuff,trk+hd);
  526.  
  527.       if (tcThBufs[curTh].ErrorCode = DosRead(hf,DskBuf,bpT,&result))
  528.         ThreadErrorHandler(UM_ERROR, curTh, hf);
  529.     }
  530.   }
  531.   ImageBuffers[curBuff].Percent = 100;
  532.   WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(curTh),0);
  533.   
  534.   if (hf) DosClose(hf);
  535.  
  536.   DosExit(EXIT_THREAD,0);
  537. }
  538.  
  539. // Save the following fields
  540. //
  541. //  BSPBLK       DskParms
  542. //  PTRACKLAYOUT DskLayout
  543. //  USHORT       usLayoutSize
  544.  
  545. VOID FAR SaveImage(USHORT curTh) {
  546.  
  547. USHORT curBuff;
  548. USHORT bpT;            // Bytes per track
  549. USHORT sourceTracks;   // # tracks on source disk
  550. USHORT trk;
  551. USHORT hd;
  552. USHORT cyl;
  553. HFILE  hf;
  554. USHORT result;
  555. ULONG  FileSize;
  556. CHAR   Header[] = "DskImage";
  557. PBYTE  DskBuf;              // huge pointer to track data
  558.  
  559.   curBuff = tcThBufs[curTh].ImageNumber;
  560.   tcThBufs[curTh].ErrorCode = 0;
  561.  
  562. // calculate file size
  563.   sourceTracks  = ImageBuffers[curBuff].DskParms.cSectors         /
  564.                   ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  565.  
  566.   bpT   = ImageBuffers[curBuff].DskParms.usBytesPerSector *
  567.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  568.  
  569.   FileSize = (sourceTracks * bpT) +
  570.               sizeof Header +
  571.               sizeof ImageBuffers[curBuff].DskParms;
  572.  
  573.   if (tcThBufs[curTh].ErrorCode = DosOpen2(ImageBuffers[curBuff].FileName,
  574.                                        &hf,
  575.                                        &result,
  576.                                        FileSize,
  577.                                        FILE_NORMAL,
  578.                                        FILE_OPEN | FILE_CREATE,
  579.                                        OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
  580.                                        NULL,
  581.                                        0L))
  582.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  583.  
  584. // write dskim header
  585.   if (tcThBufs[curTh].ErrorCode = DosWrite(hf,&Header,sizeof Header,&result))
  586.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  587.  
  588. // write parameter block
  589.   if (tcThBufs[curTh].ErrorCode = DosWrite(hf,
  590.                                            &ImageBuffers[curBuff].DskParms,
  591.                                            sizeof ImageBuffers[curBuff].DskParms,
  592.                                            &result))
  593.     ThreadErrorHandler(UM_ERROR, curTh, hf);
  594.  
  595. // write disk data
  596.   for (trk = 0, cyl = 0;
  597.        trk < sourceTracks;
  598.        trk += ImageBuffers[curBuff].DskParms.cHeads, cyl++) {
  599.     for (hd = 0; hd < ImageBuffers[curBuff].DskParms.cHeads; hd++) {
  600.       ImageBuffers[curBuff].Percent =
  601.         (USHORT)(((float)((cyl*2)+hd)/(float)sourceTracks)*100.0);
  602.       WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(curTh),0);
  603.  
  604.       DskBuf = MakeHugeP(curBuff,trk+hd);
  605.  
  606.       if (tcThBufs[curTh].ErrorCode = DosWrite(hf,DskBuf,bpT,&result))
  607.         ThreadErrorHandler(UM_ERROR, curTh, hf);
  608.     }
  609.   }
  610.   ImageBuffers[curBuff].Percent = 100;
  611.   WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(curTh),0);
  612.   
  613.   if (hf) DosClose(hf);
  614.  
  615.   DosExit(EXIT_THREAD,0);
  616. }
  617.  
  618.  
  619. VOID FAR CompImages(USHORT curTh) {
  620.  
  621. USHORT curBuff;
  622. USHORT compBuff;
  623. USHORT bpT;            // Bytes per track
  624. USHORT sourceTracks;   // # tracks on source disk
  625. USHORT trk;
  626. USHORT hd;
  627. USHORT cyl;
  628. HFILE  hf;              // only needed for error handling
  629. PBYTE  DskBuf1;         // huge pointer to track data
  630. PBYTE  DskBuf2;         // huge pointer to track data
  631.  
  632.   curBuff = tcThBufs[curTh].ImageNumber;
  633.   compBuff = tcThBufs[curTh].CompNumber;
  634.   tcThBufs[curTh].ErrorCode = 0;
  635.  
  636. // compare BPB
  637.  
  638.   if (memcmp(&(ImageBuffers[curBuff].DskParms),
  639.              &(ImageBuffers[compBuff].DskParms),
  640.              sizeof(BSPBLK))) {
  641.     ThreadErrorHandler(UM_COMPERR, curTh, hf);
  642.     DosExit(EXIT_THREAD,0);
  643.   }
  644.  
  645. // compare data
  646.   sourceTracks  = ImageBuffers[curBuff].DskParms.cSectors         /
  647.                   ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  648.  
  649.   bpT   = ImageBuffers[curBuff].DskParms.usBytesPerSector *
  650.           ImageBuffers[curBuff].DskParms.usSectorsPerTrack;
  651.  
  652.   for (trk = 0, cyl = 0;
  653.        trk < sourceTracks;
  654.        trk += ImageBuffers[curBuff].DskParms.cHeads, cyl++) {
  655.     for (hd = 0; hd < ImageBuffers[curBuff].DskParms.cHeads; hd++) {
  656.       ImageBuffers[curBuff].Percent =
  657.         (USHORT)(((float)((cyl*2)+hd)/(float)sourceTracks)*100.0);
  658.       WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(curTh),0);
  659.  
  660.       DskBuf1 = MakeHugeP(curBuff,trk+hd);
  661.       DskBuf2 = MakeHugeP(compBuff,trk+hd);
  662.  
  663.       if (memcmp(DskBuf1,DskBuf2,bpT)) {
  664.         ThreadErrorHandler(UM_COMPERR, curTh, hf);
  665.         DosExit(EXIT_THREAD,0);
  666.       }
  667.     }
  668.   }
  669.   ImageBuffers[curBuff].Percent = 100;
  670.  
  671.   WinPostMsg(hWndFrame,UM_COMPOK,MPFROMSHORT(curTh),0);
  672.   DosExit(EXIT_THREAD,0);
  673. } // CompImages
  674.