home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / pmflp301.zip / diskcopy / pmFloppy.c < prev    next >
C/C++ Source or Header  |  1997-01-03  |  27KB  |  891 lines

  1. /*
  2.            pmfloppy.c
  3.            
  4.            main program
  5.  
  6.            PM based disk utility.  Use separate threads for disk actions to
  7.            prevent slowing up PM too much.  Use huge memory allocation for
  8.            single pass reads.
  9.  
  10.            Copyright G. Bryant, 1990
  11.  
  12.    
  13.   Change Log
  14.    8-Jun-90   Correct array bounds violation in FreeThread
  15.    9-Jun-90   Correct the EXPORTS statement in pmfloppy.def
  16.     5/95 - ROB Extensive changes to seperate the utility functions (i.e.
  17.         reading and writing) from the tasking functions in readsource() and
  18.         writetarget().  These changes allow essentially the same code to 
  19.         be executed as a subroutine and as a task.
  20.  
  21. */
  22.  
  23. #define INCL_PM
  24. #define INCL_BASE
  25. #define INCL_DOSERRORS
  26. #define INCL_DOSPROCESS
  27. #define INCL_DOSDEVIOCTL
  28. #define INCL_DOSSESMGR
  29. #define INCL_GPILCIDS
  30. #define INCL_WINSWITCHLIST
  31. #include <os2.h>
  32. #include <stdlib.h>
  33. #include <stdarg.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <process.h>
  37. #include "pmfloppy.h"
  38. #include "DskIm.h"
  39. #include "funcdefs.h"
  40.  
  41. /* prototypes for current file*/
  42. MRESULT  EXPENTRY ClientWndProc(HWND, ULONG, MPARAM, MPARAM);
  43. MRESULT  Panic(PCH, USHORT);
  44. MRESULT  DisplayStatus(HWND, HPS, USHORT);
  45. MRESULT  DisplayDone(HWND , HPS, USHORT);
  46. VOID     FreeThread(USHORT);
  47. static void copyCheckThread (void *param);
  48. static void duplicateThread (void *param);
  49. static FNTHREAD loadImageThread ;
  50. static void readThread (void *param);
  51. static FNTHREAD saveImageThread;
  52. static void writeThread (void *param);
  53. static void startThread (void func (void * param));
  54. static void fileToFloppyThread (void *param);
  55. static void floppyToFileThread (void *param);
  56. VOID     DisplayImageStat(HWND, HPS);
  57. VOID     PutBox(PSZ, PSZ);
  58.  
  59. /* GLOBAL VARIABLES */
  60.  
  61. /* PM vbls*/
  62. HAB    hab;
  63. HMQ    hmq;
  64. HWND   hWndFrame ;
  65. static CHAR szClientClass[]="PMFloppy";
  66. ULONG  ctldata = FCF_STANDARD ;
  67. HWND   hWndClient;
  68. HWND   hwndDeskTop;
  69. QMSG   qmsg;
  70. LONG   CharHeight;
  71. LONG   CharWidth;
  72.  
  73. /* User response vbls*/
  74. DskImage ImageBuffers[NUM_IMAGES];
  75. USHORT   BufferNum;                  /* only use in foreground thread*/
  76. USHORT   CompNum;                    /* only use in foreground thread*/
  77. char    imageFileName[260];
  78.  
  79. /* Thread variables*/
  80. ThreadContext tcThBufs[NUM_THREADS];
  81.  
  82.  
  83. int main(void)
  84. {
  85. SWCNTRL swctl;
  86. PID pid;
  87.  
  88.   hab = WinInitialize(0);
  89.   hmq = WinCreateMsgQueue(hab, 0);
  90.   hwndDeskTop = WinQueryDesktopWindow(hab, (HDC)NULL);
  91.  
  92.   if (!WinRegisterClass(hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0))
  93.     return(0);
  94.  
  95.   hWndFrame = WinCreateStdWindow(HWND_DESKTOP,
  96.                                  WS_VISIBLE,
  97.                                  &ctldata,
  98.                                  szClientClass,
  99.                                  "Floppy Disk Utility",
  100.                                  0L,
  101.                                  0,
  102.                                  IDR_PMFLOPPY,
  103.                                  &hWndClient);
  104.  
  105.   if (hWndFrame != 0)
  106.   {
  107.  
  108.     WinQueryWindowProcess(hWndFrame, &pid, NULL);
  109.  
  110.     swctl.hwnd = hWndFrame;
  111.     swctl.hwndIcon = 0;
  112.     swctl.hprog = 0;
  113.     swctl.idProcess = pid;
  114.     swctl.idSession = 0;
  115.     swctl.uchVisibility = SWL_VISIBLE;
  116.     swctl.fbJump = SWL_JUMPABLE;
  117.     swctl.szSwtitle[0] = '\0';
  118.  
  119.  
  120.     while ( WinGetMsg(hab, &qmsg, (HWND)NULL, 0, 0) )
  121.         WinDispatchMsg(hab, &qmsg);
  122.  
  123.     WinDestroyWindow(hWndFrame);
  124.   }
  125.  
  126.   WinDestroyMsgQueue(hmq);
  127.   WinTerminate(hab);
  128.  
  129.   DosExit(EXIT_PROCESS, 0);
  130. } /* main */
  131.  
  132.  
  133. /* ClientWndProc - main window processing*/
  134. /**/
  135. /*  note: UM messages are User-defined (in pmfloppy.h).*/
  136. /*        all UM messages use mp2 to indicate the drive the message concerns,*/
  137. /*        and mp1 is data specific to that message.  Then UM_xxxMSG is a */
  138. /*        generic msg.  It is currently only used for DONE messages.  If I*/
  139. /*        need more, set up some magic numbers and pass them through mp1. */
  140. /**/
  141. MRESULT EXPENTRY ClientWndProc(HWND hwnd
  142.                   , ULONG id
  143.                   , MPARAM mp1
  144.                   , MPARAM mp2) {
  145.  
  146. HPS         hPS;
  147. HWND        hMenu;
  148. CHAR        szTxtBuf[MAXMSGLEN];
  149. int          result;
  150. FONTMETRICS fm;
  151. USHORT      curBuff;
  152. USHORT      gotSource;
  153. BOOL        DriveActive;
  154. USHORT      curTh;
  155. RECTL       rctPaint;
  156.  
  157.   switch (id) {
  158.     case WM_CREATE:
  159.       for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
  160.         ImageBuffers[curBuff].BufferName[0] = '\0';
  161.       for (curTh=0;curTh < NUM_THREADS;curTh++) {
  162.         tcThBufs[curTh].ThID = 0;
  163.         tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
  164.         tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
  165.       }
  166.       hPS = WinGetPS(hwnd);
  167.       GpiQueryFontMetrics(hPS, (long)sizeof(fm), &fm);
  168.       CharHeight = fm.lMaxBaselineExt;
  169.       CharWidth = fm.lMaxCharInc;
  170.       WinReleasePS(hPS);
  171.       break;
  172.  
  173.     case WM_PAINT:
  174.       hPS = WinGetPS(hwnd);
  175.       GpiErase(hPS);
  176.       WinQueryUpdateRect(hwnd,&rctPaint);
  177.       DisplayImageStat(hwnd, hPS);
  178.       WinValidateRect(hwnd, &rctPaint, FALSE);
  179.       WinReleasePS(hPS);
  180.       break;
  181.  
  182.     case WM_COMMAND:
  183.       switch (COMMANDMSG(&id)->cmd) {
  184.         case IDM_READ:
  185.           if (WinDlgBox(HWND_DESKTOP,hWndFrame,ReadDlgProc,0,READ_DLG,NULL))
  186.             startThread (readThread);
  187.           break;
  188.  
  189.         case IDM_WRITE:
  190.           if (WinDlgBox(HWND_DESKTOP,hWndFrame,WriteDlgProc,0,WRITE_DLG,NULL))
  191.             startThread (writeThread);
  192.           break;
  193.         case IDM_DUPLICATE:
  194.           if (!WinDlgBox(HWND_DESKTOP,hWndFrame,duplicateDlgProc,0,
  195.                 IDD_DUPLICATE,NULL)) 
  196.               break;
  197.           startThread (duplicateThread);
  198.           break;
  199.         case IDM_COPYCHECK:
  200.           if (!WinDlgBox(HWND_DESKTOP,hWndFrame,copyCheckDlgProc,0,
  201.             IDD_DUPLICATE, NULL)) 
  202.               break;
  203.         startThread (copyCheckThread);
  204.           break;
  205.  
  206.         case IDM_ABOUT:
  207.           WinDlgBox(HWND_DESKTOP,hWndFrame,AboutDlgProc,0,ABOUT_DLG,NULL);
  208.           break;
  209.  
  210.         case IDM_DELETE:
  211.           WinDlgBox(HWND_DESKTOP,hWndFrame,DeleteDlgProc,0,DELETE_DLG,NULL);
  212.           hPS = WinGetPS(hwnd);
  213.           GpiErase(hPS);
  214.           DisplayImageStat(hwnd, hPS);
  215.           WinReleasePS(hPS);
  216.           break;
  217.  
  218.         case IDM_LOAD:
  219.           if (WinDlgBox(HWND_DESKTOP,hWndFrame,LoadDlgProc,0,LOAD_DLG,NULL)) {
  220.             /* send off thread to load*/
  221.             for (curTh=0;
  222.                  (curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
  223.                  curTh++) ;
  224.  
  225.             if (curTh < NUM_THREADS) {
  226.               tcThBufs[curTh].ImageNumber = BufferNum;
  227.  
  228.               if (DosCreateThread( &(tcThBufs[curTh].ThID),
  229.                                 loadImageThread, curTh, 0, STACK_SIZE))
  230.                {
  231.                     freeImageBuffer(BufferNum);
  232.                 PutBox("Image Load","DosCreateThread failed.");
  233.                       return FALSE;
  234.               } /* if can't create the thread. */
  235.             }
  236.             else {
  237.                 freeImageBuffer(BufferNum);
  238.               PutBox("Image Load","Out of program thread resources.");
  239.                     return FALSE;
  240.             } /* if can't create the thread. */
  241.           }
  242.           break;
  243.  
  244.         case IDM_SAVE:
  245.           if (WinDlgBox(HWND_DESKTOP,hWndFrame,SaveDlgProc,0,SAVE_DLG,NULL)) {
  246.             /* send off thread to save*/
  247.             for (curTh=0;
  248.                  (curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
  249.                  curTh++) ;
  250.  
  251.             if (curTh < NUM_THREADS) {
  252.               tcThBufs[curTh].ImageNumber = BufferNum;
  253.  
  254.               if (DosCreateThread( &(tcThBufs[curTh].ThID),
  255.                                 saveImageThread, curTh, 0, STACK_SIZE))
  256.               {
  257.                 PutBox("Image Save","DosCreateThread failed.");
  258.                       return FALSE;
  259.               } /* if can't create the thread. */
  260.             }
  261.             else {
  262.               PutBox("Image Save","Out of program thread resources.");
  263.                     return FALSE;
  264.             } /* if can't create the thread. */
  265.           }
  266.           break;
  267.  
  268.         case IDM_COMP:
  269.           if (WinDlgBox(HWND_DESKTOP,hWndFrame,CompDlgProc,0,COMP_DLG,NULL)) {
  270.             /* send off thread to compare*/
  271.             for (curTh=0;
  272.                  (curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
  273.                  curTh++) ;
  274.  
  275.             if (curTh < NUM_THREADS) {
  276.               tcThBufs[curTh].ImageNumber = BufferNum;
  277.               tcThBufs[curTh].CompNumber  = CompNum;
  278.               if (DosCreateThread( &(tcThBufs[curTh].ThID),
  279.                                 CompImages, curTh, 0, STACK_SIZE))
  280.              {
  281.                 PutBox("Image Compare","DosCreateThread failed.");
  282.                       return FALSE;
  283.               } /* if can't create the thread. */
  284.             }
  285.             else {
  286.               PutBox("Image Compare","Out of program thread resources.");
  287.                     return FALSE;
  288.             } /* if can't create the thread. */
  289.           }
  290.           break;
  291.  
  292.         case IDM_EXIT:
  293.           WinPostMsg(hWndFrame, WM_CLOSE, NULL, NULL);
  294.           break;
  295.         case IDM_FLOPPY_TO_FILE:
  296.              if (!WinDlgBox(HWND_DESKTOP,hWndFrame,floppyToFileDlgProc,0,
  297.                 IDD_IMAGEDIALOG, NULL)) 
  298.                   break;
  299.             startThread (floppyToFileThread);
  300.             break;
  301.         case IDM_FILE_TO_FLOPPY:
  302.             if (!WinDlgBox(HWND_DESKTOP,hWndFrame,fileToFloppyDlgProc,0,
  303.                 IDD_IMAGEDIALOG, NULL)) 
  304.                   break;
  305.             startThread (fileToFloppyThread);
  306.             break;
  307.       }
  308.       break;
  309.  
  310.     case WM_INITMENU:
  311.       /*set the allowable menu choices.*/
  312.       hMenu = WinWindowFromID(hWndFrame,FID_MENU);
  313.  
  314.       /* If we don't have anything to write, disable the write, save, and */
  315.       /* delete menus*/
  316.       gotSource = 0;
  317.       for (curBuff=0;curBuff < NUM_IMAGES;curBuff++) {
  318.         if (ImageBuffers[curBuff].Percent == 100) gotSource++;
  319.       }
  320.  
  321.       WinSendMsg(hMenu,MM_SETITEMATTR,
  322.         MPFROM2SHORT(IDM_WRITE,TRUE),
  323.         MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
  324.  
  325.       WinSendMsg(hMenu,MM_SETITEMATTR,
  326.         MPFROM2SHORT(IDM_SAVE,TRUE),
  327.         MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
  328.  
  329.       WinSendMsg(hMenu,MM_SETITEMATTR,
  330.         MPFROM2SHORT(IDM_DELETE,TRUE),
  331.         MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
  332.  
  333.       WinSendMsg(hMenu,MM_SETITEMATTR,
  334.         MPFROM2SHORT(IDM_COMP,TRUE),
  335.         MPFROM2SHORT(MIA_DISABLED,(gotSource > 1) ? 0 : MIA_DISABLED));
  336.       break;
  337.  
  338.  
  339.     case UM_STATUS:
  340.       curTh = SHORT1FROMMP(mp1);
  341.       hPS = WinGetPS(hwnd);
  342.       DisplayStatus(hwnd, hPS, curTh);
  343.       WinReleasePS(hPS);
  344.       break;
  345.  
  346.     case UM_DONE:
  347.       curTh = SHORT1FROMMP(mp1);
  348.       curBuff = tcThBufs[curTh].ImageNumber;
  349.       hPS = WinGetPS(hwnd);
  350.       WinAlarm(HWND_DESKTOP,WA_NOTE);
  351.       DisplayDone(hwnd, hPS,curBuff);
  352.       FreeThread(curTh);
  353.       WinReleasePS(hPS);
  354.       break;
  355.  
  356.     case UM_ERROR:
  357.         {int        deleteImage = 0;
  358.         
  359.       curTh = SHORT1FROMMP(mp1);
  360.       curBuff = tcThBufs[curTh].ImageNumber;
  361.       switch (ImageBuffers[curBuff].Busy) {
  362.         case BUSY_READ:
  363.             deleteImage = 1;
  364.           sprintf(szTxtBuf,"Read Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
  365.           break;
  366.         case BUSY_WRITE:
  367.           sprintf(szTxtBuf,"Write Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
  368.           break;
  369.         case BUSY_LOAD:
  370.             deleteImage = 1;
  371.           sprintf(szTxtBuf,"Load Error on drive %s", ImageBuffers[curBuff].FileName);
  372.           break;
  373.         case BUSY_SAVE:
  374.           sprintf(szTxtBuf,"Save Error on file %s", ImageBuffers[curBuff].FileName);
  375.           break;
  376.         }
  377.       Panic(szTxtBuf, tcThBufs[curTh].ErrorCode);
  378.       hPS = WinGetPS(hwnd);
  379.         if(deleteImage)
  380.             {
  381.              /* free the memory used by that buffer and coalesce the list*/
  382.             DosFreeMem (ImageBuffers[curBuff].diskBuffer);
  383.             ImageBuffers[curBuff].diskBuffer = NULL;
  384.             free(ImageBuffers[curBuff].DskLayout);
  385. /* It seems very dangerous to move the buffers in this environment.
  386.    Another task could be running (eg reading an image), and having the
  387.    image buffers shuffled could trash the second thread.
  388. */
  389. #if 0
  390.             while (((curBuff+1) < NUM_IMAGES) &&
  391.               (ImageBuffers[curBuff].BufferName[0] != '\0'))
  392.                 {
  393.                 ImageBuffers[curBuff]  = ImageBuffers[curBuff+1];
  394.                 curBuff++;
  395.                 }
  396. #endif
  397.             ImageBuffers[curBuff].BufferName[0] = '\0';
  398.             GpiErase ( hPS);
  399.             DisplayImageStat (hwnd, hPS);
  400.             }
  401.         else
  402.             {ImageBuffers[curBuff].Busy = 0;
  403.             ImageBuffers[curBuff].Percent = 100;
  404.             DisplayDone(hwnd, hPS, curBuff);
  405.             }
  406.       FreeThread(curTh);
  407.       WinReleasePS(hPS);
  408.       break;
  409.         }
  410.  
  411.     case UM_COMPOK:
  412.       curTh = SHORT1FROMMP(mp1);
  413.       curBuff = tcThBufs[curTh].ImageNumber;
  414.       WinAlarm(HWND_DESKTOP,WA_NOTE);
  415.       PutBox("Image Compare","Images are identical!");
  416.     ImageBuffers[BufferNum].Busy = 0;
  417.     ImageBuffers[CompNum].Busy = 0;
  418.       hPS = WinGetPS(hwnd);
  419.       DisplayImageStat(hwnd, hPS);
  420.       FreeThread(curTh);
  421.       WinReleasePS(hPS);
  422.       break;
  423.  
  424.     case UM_COMPERR:
  425.       curTh = SHORT1FROMMP(mp1);
  426.       curBuff = tcThBufs[curTh].ImageNumber;
  427.       WinAlarm(HWND_DESKTOP,WA_WARNING);
  428.       PutBox("Image Compare","Images are different");
  429.       hPS = WinGetPS(hwnd);
  430.       DisplayImageStat(hwnd, hPS);
  431.       FreeThread(curTh);
  432.       WinReleasePS(hPS);
  433.     ImageBuffers[curBuff].Busy = 0;
  434.     ImageBuffers[curBuff].Percent = 100;
  435.       break;
  436.     case UM_DESTDISK:
  437.         PutBox ("Put destination disk", "in drive");
  438.     DosResumeThread ((TID) mp1);
  439.     break;
  440.     case WM_CLOSE:
  441.       DriveActive = FALSE;
  442.       for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
  443.         if (ImageBuffers[curBuff].Busy) DriveActive = TRUE;
  444.  
  445.       if (DriveActive) {
  446.             if (MBID_OK != WinMessageBox(HWND_DESKTOP,
  447.                                      hWndFrame,
  448.                                      "are you sure you want to quit?",
  449.                                      "A Drive is still running - ",
  450.                                      0,
  451.                                      MB_OKCANCEL | MB_QUERY))
  452.         break;
  453.       }
  454.       /* else just fall through to default to get to the default proc*/
  455.     default:
  456.       return(WinDefWindowProc(hwnd, id, mp1, mp2));
  457.  
  458.   } /* switch id */
  459.  
  460.   return 0L;
  461.  
  462. } /* clientwndproc */
  463.  
  464.  
  465. /*  Panic  --  Put up a message box with an error message.*/
  466. /**/
  467. /*  Inputs:   pszCaption  --  Caption text for message box*/
  468. /**/
  469. /*  Returns:  1L, for error signalling from window procedures.*/
  470. MRESULT Panic(PCH pszCaption,USHORT ErrorNum)
  471. {
  472. CHAR buf[1024];
  473. USHORT cbBuf;
  474.  
  475.   if (ErrorNum == DSKIM_ERROR_WRONG_FORMAT)
  476.     sprintf(buf, "Error - target disk has incorrect format");
  477.   else if (ErrorNum == DSKIM_ERROR_WRONG_FILE)
  478.     sprintf(buf, "Error - file is not in correct format");
  479.   else 
  480.   {APIRET        rc;
  481.     ULONG        returnedLength;
  482.     
  483.     rc = DosGetMessage (NULL, 0, buf, 1023, ErrorNum, "OSO001.msg", 
  484.         (ULONG *) &cbBuf);
  485.     if (rc)
  486.         {sprintf(buf, "SYS%04d: error text unavailable", ErrorNum);
  487.         cbBuf = 31;
  488.         }
  489.   }
  490.   buf[cbBuf] = (char)0;
  491.  
  492.  
  493.   WinAlarm(HWND_DESKTOP, WA_ERROR);
  494.  
  495.   PutBox(pszCaption,buf);
  496.  
  497.   return( (MRESULT) 1);
  498. } /* panic*/
  499.  
  500.  
  501. /* DisplayStatus - Display the status for the drive in the PS*/
  502. /**/
  503. /*  in:  usPct   Percent done*/
  504. /*       Drive   drive letter*/
  505. /*       hwnd    window handle to display on*/
  506. /*       op      operation (eg read, write)*/
  507. /**/
  508. MRESULT DisplayStatus(HWND hwnd, HPS hPS, USHORT curTh) {
  509.  
  510. RECTL  rctStart;
  511. CHAR   szTxtBuf[MAXMSGLEN];
  512. CHAR   op[10];
  513. CHAR   Object[6];
  514. CHAR   Device[80];
  515. USHORT curBuff;
  516. USHORT compBuff;
  517. int        doPrint = 1;
  518.  
  519.   curBuff = tcThBufs[curTh].ImageNumber;
  520.   compBuff = tcThBufs[curTh].CompNumber;
  521.  
  522.   switch (ImageBuffers[curBuff].Busy) {
  523.     case BUSY_READ:
  524.       strcpy(op,"reading");
  525.       strcpy(Object,"Drive");
  526.       Device[0] = ImageBuffers[curBuff].DriveID[0];
  527.       Device[1] = '\0';
  528.       break;
  529.     case BUSY_WRITE:
  530.       strcpy(op,"writing");
  531.       strcpy(Object,"Drive");
  532.       Device[0] = ImageBuffers[curBuff].DriveID[0];
  533.       Device[1] = '\0';
  534.       break;
  535.     case BUSY_LOAD:
  536.       strcpy(op,"loading");
  537.       strcpy(Object,"file");
  538.       strcpy(Device,ImageBuffers[curBuff].FileName);
  539.       break;
  540.     case BUSY_SAVE:
  541.       strcpy(op,"saving");
  542.       strcpy(Object,"file");
  543.       strcpy(Device,ImageBuffers[curBuff].FileName);
  544.       break;
  545.     case BUSY_COMP:
  546.       strcpy(op,"comparing");
  547.       strcpy(Object,"image");
  548.       strcpy(Device,ImageBuffers[compBuff].BufferName);
  549.       break;
  550.     default:
  551.         doPrint = 0;
  552.   }
  553.  
  554.   rctStart.xLeft = 5L;
  555.   rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
  556.   rctStart.yBottom = (curBuff * CharHeight) + 5;
  557.   rctStart.yTop = rctStart.yBottom + CharHeight;
  558. if(doPrint)
  559.   sprintf(szTxtBuf,
  560.           "Image %s %s %s %s (%d%% complete)",
  561.           ImageBuffers[curBuff].BufferName,
  562.           op,
  563.           Object,
  564.           Device,
  565.           ImageBuffers[curBuff].Percent);
  566. else
  567.     strcpy (szTxtBuf, " ");
  568.   WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
  569.               DT_LEFT | DT_ERASERECT);
  570.   WinValidateRect(hwnd, &rctStart, FALSE);
  571.   return 0;
  572. }
  573.  
  574.  
  575. /* DisplayDone - Display an operation complete*/
  576. /**/
  577. /*  in:  Drive   drive letter*/
  578. /*       hwnd    window handle to display on*/
  579. /*       op      operation (eg read, write)*/
  580. /**/
  581. MRESULT DisplayDone(HWND hwnd, HPS hPS, USHORT curBuff) {
  582.  
  583. RECTL   rctStart;
  584. CHAR    szTxtBuf[MAXMSGLEN];
  585. int        count;
  586.  
  587.   rctStart.xLeft = 5L;
  588.   rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
  589.   rctStart.yBottom = (curBuff * CharHeight) + 5;
  590.   rctStart.yTop = rctStart.yBottom + CharHeight;
  591. count =  sprintf(szTxtBuf, "Image %s is full", ImageBuffers[curBuff].BufferName);
  592. sprintf( szTxtBuf+count, " (%s)", ImageBuffers[curBuff].volumeLabel);
  593.   WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
  594.               DT_LEFT | DT_ERASERECT);
  595.   WinValidateRect(hwnd, &rctStart, FALSE);
  596.   return 0;
  597. }
  598.  
  599. /* FreeThread - clean up after a child thread*/
  600. /**/
  601. /*   in: curTh  - Thread to clean up*/
  602. /**/
  603. /* Note: there doesn't seem to be an easy way to determine when a thread is*/
  604. /*       gone.  all the wait routines just work on processes.  So we cheat and*/
  605. /*       check the priority until we get a failure.  Like all busy waits,*/
  606. /*       this is incredibly idiotic, but until we get a "twait" function, I*/
  607. /*       can't think of a better way.*/
  608. /**/
  609. VOID FreeThread(USHORT curTh) {
  610.  
  611. USHORT curBuff;
  612. USHORT compBuff;
  613. USHORT Prty;
  614.  
  615. /* sit here until the thread is gone*/
  616. /*  while (DosGetPrty(PRTYS_THREAD,
  617.                     &Prty,
  618.                     tcThBufs[curTh].ThID) != ERROR_INVALID_THREADID) ; */
  619. DosWaitThread(&(tcThBufs[curTh].ThID), 0);
  620.   curBuff  = tcThBufs[curTh].ImageNumber;
  621.   compBuff = tcThBufs[curTh].CompNumber;
  622.  
  623.   tcThBufs[curTh].ThID = 0;
  624.   tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
  625.   tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
  626.   tcThBufs[curTh].ErrorCode = 0;
  627.   ImageBuffers[curBuff].Busy = FALSE;
  628.   if (compBuff < NUM_IMAGES) ImageBuffers[compBuff].Busy = FALSE;
  629.  
  630. }
  631.  
  632.  
  633. /* modified 7/94 (ROB) so that image buffers do not have to be contiguous */
  634. VOID DisplayImageStat(HWND hwnd, HPS hPS) {
  635. RECTL  rctStart;
  636. RECTL  rctPaint;
  637. USHORT curBuff;
  638. int        imageCount = 0;
  639.  
  640.   WinQueryWindowRect(hwnd,&rctPaint);
  641.   for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
  642.     if (ImageBuffers[curBuff].BufferName[0] != '\0') {
  643.       ++imageCount;
  644.       if (ImageBuffers[curBuff].Busy) 
  645.         DisplayStatus(hwnd, hPS, curBuff);
  646.       else 
  647.         DisplayDone(hwnd,hPS, curBuff);
  648.  
  649.       }
  650.  
  651.   if (!imageCount) {
  652.     rctStart.xLeft = 5L;
  653.     rctStart.xRight = 5L + (CharWidth * 16);
  654.     rctStart.yBottom = 5L;
  655.     rctStart.yTop = rctStart.yBottom + CharHeight;
  656.     WinDrawText(hPS,
  657.                 -1,
  658.                 "No images in use",
  659.                 &rctStart,
  660.                 CLR_NEUTRAL,
  661.                 CLR_BACKGROUND,
  662.                 DT_LEFT | DT_ERASERECT);
  663.   }
  664. }
  665.  
  666.  
  667. /**/
  668. /* Put the messages in an application modal message box*/
  669. /**/
  670. VOID PutBox(PSZ msg1, PSZ msg2) {
  671.  
  672.   WinMessageBox(HWND_DESKTOP,
  673.                 hWndFrame,
  674.                 msg2,
  675.                 msg1,
  676.                 0,
  677.                 MB_OK | MB_ICONEXCLAMATION);
  678.   return;
  679. } /* PutBox*/
  680.  
  681. /* *************************** freeImageBuffer ************************** */
  682.  
  683. void    freeImageBuffer (USHORT    buffer)
  684. {
  685. ImageBuffers[buffer].BufferName[0] = '0';
  686. ImageBuffers[buffer].Busy = 0;
  687. return;
  688. }
  689.  
  690. /* *************************** copyCheckThread ***************************** */
  691. static void copyCheckThread (void *param)
  692. {int        holdSource,
  693.             imageNum,
  694.             thIndex;
  695. ThreadContext    *pcontext;
  696.  
  697. thIndex = (int) param;
  698. pcontext = &(tcThBufs[thIndex]);
  699. imageNum = pcontext->ImageNumber;
  700. ImageBuffers[imageNum].Busy = BUSY_WRITE;
  701. writetarget (thIndex);
  702. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thIndex),0);
  703. holdSource = pcontext->ImageNumber;
  704. pcontext->ImageNumber = pcontext->CompNumber;
  705. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_READ;
  706. readsource (thIndex);
  707. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thIndex),0);
  708. /* See the comment in duplicateThread () for an explaination of the following
  709.    DosSleep ()
  710. */
  711. DosSleep (50);
  712. pcontext->ImageNumber = holdSource;
  713. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_COMP;
  714. CompImages (thIndex);
  715. tcThBufs[thIndex].ThID = 0;
  716. _endthread();
  717. }
  718.  
  719. /* *************************** duplicateThread *************************** */
  720. static void duplicateThread (void *param)
  721. {int            holdSource,
  722.                 imageNum,
  723.                 thID;
  724. ThreadContext    *pcontext;
  725.  
  726. thID = (int)param;
  727. pcontext = &(tcThBufs[thID]);
  728. imageNum = pcontext->ImageNumber;
  729. ImageBuffers[imageNum].Busy = BUSY_READ;
  730. readsource (thID);
  731. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  732. WinPostMsg (hWndFrame, UM_DESTDISK, (MPARAM)(pcontext->ThID), NULL);
  733. DosSuspendThread(pcontext->ThID);
  734. ImageBuffers[imageNum].Busy = BUSY_WRITE;
  735. writetarget (thID);
  736. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  737. holdSource = pcontext->ImageNumber;
  738. pcontext->ImageNumber = pcontext->CompNumber;
  739. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_READ;
  740. readsource (thID);
  741. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  742. /* the final percent complete message is not being processed until the
  743.    results of the image comparrison are posted with the result that it looks
  744.    to the user that reading of the new disk is not complete.  The following
  745.    DosSleep () gives the message processing thread time to post the final
  746.    percentage.
  747. */
  748. DosSleep (50);
  749. pcontext->ImageNumber = holdSource;
  750. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_COMP;
  751. CompImages (thID);
  752. _endthread();
  753. }
  754.  
  755. /* ************************** loadImageThread ****************************** */
  756. static void APIENTRY loadImageThread (ULONG param)
  757. {
  758. LoadImage (param);
  759. WinPostMsg (hWndFrame, UM_DONE, (MPARAM) param, NULL);
  760. _endthread();
  761. }
  762.  
  763. /* ****************************** readThread **************************** */
  764. static void readThread (void *param)
  765. {int        thIndex;
  766.  
  767. thIndex = (int)param;
  768. readsource (thIndex);
  769. if (tcThBufs[thIndex].ErrorCode)
  770.     WinPostMsg(hWndFrame,UM_ERROR,MPFROMSHORT(thIndex),0);
  771. else
  772.     WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(thIndex),0);
  773. ImageBuffers[tcThBufs[thIndex].ImageNumber].Busy = 0;
  774. _endthread();
  775.  
  776. }
  777.  
  778. /* ************************** saveImageThread ****************************** */
  779. static void APIENTRY saveImageThread (ULONG param)
  780. {
  781. SaveImage ( param);
  782. WinPostMsg (hWndFrame, UM_DONE, (MPARAM) param, NULL);
  783. _endthread();
  784. }
  785.  
  786. /* ****************************** writeThread **************************** */
  787. static void writeThread (void *param)
  788. {int        thIndex;
  789.  
  790. thIndex = (int)param;
  791. writetarget (thIndex);
  792. if (tcThBufs[thIndex].ErrorCode)
  793.     {
  794.     WinPostMsg(hWndFrame,UM_ERROR,MPFROMSHORT(thIndex),0);
  795.     }
  796. else
  797.     WinPostMsg(hWndFrame,UM_DONE,MPFROMSHORT(thIndex),0);
  798. ImageBuffers[tcThBufs[thIndex].ImageNumber].Busy = 0;
  799. _endthread ();
  800. }
  801.  
  802. /* *************************** startThread *************************** */
  803. static void startThread (void func (void * param))
  804. {int        curTh;
  805.  
  806. /* send off thread to read*/
  807. for (curTh=0;    (curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
  808.                  curTh++)
  809.     ;            /* NOTHING */
  810.  
  811. if (curTh < NUM_THREADS)
  812.     {tcThBufs[curTh].ImageNumber = BufferNum;
  813.     tcThBufs[curTh].CompNumber = CompNum;
  814.     if ((tcThBufs[curTh].ThID = _beginthread (func, NULL, 4*4096, (void *)curTh)) == -1)
  815.         {freeImageBuffer(BufferNum);
  816.         PutBox("Drive Read","DosCreateThread failed.");
  817.         return;
  818.         } /* if can't create the thread. */
  819.     }
  820. else
  821.     {freeImageBuffer(BufferNum);
  822.     PutBox("Drive Read","Out of program thread resources.");
  823.     return;
  824.     } /* if can't create the thread. */
  825. return;
  826. }
  827.  
  828. /* ************************** floppyToFileThread *************************** */
  829. static void floppyToFileThread (void *param)
  830. {
  831. int        imageNum,
  832.         thID;
  833. ThreadContext    *pcontext;
  834.  
  835. thID = (int)param;
  836. pcontext = &(tcThBufs[thID]);
  837. imageNum = pcontext->ImageNumber;
  838. ImageBuffers[imageNum].Busy = BUSY_READ;
  839. readsource (thID);
  840. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  841. SaveImage (thID);
  842. tcThBufs[thID].ThID = 0;
  843. ImageBuffers[imageNum].Busy = 0;
  844. WinPostMsg (hWndFrame, UM_DONE, (MPARAM) param, NULL);
  845. _endthread ();
  846. }
  847.  
  848. /* *************************** fileToFloppyThread ************************** */
  849. static void fileToFloppyThread (void *param)
  850. {
  851. int                holdSource,
  852.                 imageNum,
  853.                 thID;
  854. ThreadContext    *pcontext;
  855.  
  856. thID = (int) param;
  857. pcontext = &(tcThBufs[thID]);
  858. imageNum = pcontext->ImageNumber;
  859. /* ImageBuffers[imageNum].Busy = BUSY_LOAD; */
  860.  
  861. #if 1
  862. LoadImage (thID);
  863. #endif
  864.  
  865. ImageBuffers[imageNum].Busy = BUSY_WRITE;
  866. writetarget (thID);
  867. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  868. DosSleep (50);
  869. ImageBuffers[imageNum].Busy = 0;
  870. holdSource = pcontext->ImageNumber;
  871. pcontext->ImageNumber = pcontext->CompNumber;
  872. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_READ;
  873. readsource (thID);
  874. ImageBuffers[pcontext->ImageNumber].Busy = 0;
  875. WinPostMsg(hWndFrame,UM_STATUS, MPFROMSHORT(thID),0);
  876. /* See the comment in duplicateThread () for an explaination of the following
  877.    DosSleep ()
  878. */
  879. DosSleep (50);
  880. pcontext->ImageNumber = holdSource;
  881. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_COMP;
  882. CompImages (thID);
  883. ImageBuffers[pcontext->ImageNumber].Busy = BUSY_COMP;
  884.  
  885.  
  886. tcThBufs[thID].ThID = 0;
  887. WinPostMsg (hWndFrame, UM_DONE, (MPARAM) param, NULL);
  888. _endthread ();
  889. }
  890.  
  891.