home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / PMF300.ZIP / DSKIM.C < prev    next >
C/C++ Source or Header  |  1993-02-16  |  25KB  |  693 lines

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