home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / INST / COPY.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  30KB  |  1,121 lines

  1. /*
  2.  *  copy.c - Copy routine for wInstall
  3.  *
  4.  *  notes:
  5.  *    we now use the LZCopy stuff so COMPRESS is NOT defined
  6.  *    we now set the crit error handler ourselves so CHECKFLOPPY is
  7.  *    NOT defined
  8.  */
  9.  
  10. #include <dos.h>
  11. #include <string.h>
  12.  
  13. #include "lobotomy.h"
  14.  
  15. // ...and lets even remove some more brain cells...
  16.  
  17. #define NOWINSTYLES       //- WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
  18. #define NOSHOWWINDOW      //- SW_*
  19. #define NOATOM            //- Atom Manager routines
  20. #define NOCOLOR           //- Screen colors
  21. #define NOGDI             //- All GDI defines and routines
  22. #define NOMINMAX          //- Macros min(a,b) and max(a,b)
  23. #define NOOPENFILE        //- OpenFile(), OemToAnsi, AnsiToOem, and OF_*
  24. #define NOTEXTMETRIC      //- typedef TEXTMETRIC and associated routines
  25. #define NOWINOFFSETS      //- GWL_*, GCL_*, associated routines
  26.  
  27. #include <windows.h>
  28.  
  29. #include "sulib.h"
  30. #include "..\install.h"
  31. #include "ws.h"
  32. #include "progdde.h"
  33. #include "gauge.h"
  34.  
  35. char szDisks[] = "disks";
  36.  
  37. BOOL NEAR GetDiskPath(char cDisk, PSTR szPath);
  38. WORD FAR PASCAL wsCopyStatus(int msg, int n, LPSTR szFile);
  39. BOOL fnMystrstr(char *szSrcStr, char *szSearchStr);
  40.  
  41. /*
  42.  *  global vars used by DosCopy
  43.  */
  44. static LPSTR    lpBuf = NULL;   // copy buffer
  45. static int      iBuf = 0;       // usage count
  46. static WORD     nBufSize;
  47. static char    cDisk;
  48. static LPSTR    szEdit;
  49. extern PSTR    pErrMsg;
  50.  
  51. #define MAXBUF  (60 * 1024)     // size of default copy buffer
  52.  
  53. void NEAR PASCAL AllocCopyBuf();
  54. void NEAR PASCAL FreeCopyBuf();
  55.  
  56. void FAR PASCAL fartonear(LPSTR dst, LPSTR src)
  57. {
  58.     while (*src)
  59.         *dst++ = *src++;
  60.  
  61.     *dst = 0;
  62. }
  63.  
  64. /*  WORD FileCopy (szSource, szDir, fpfnCopy, WORD f)
  65.  *
  66.  *  This function will copy a group of files to a single destination
  67.  *
  68.  *  ENTRY:
  69.  *
  70.  *  szSourc      : pointer to a SETUP.INF section
  71.  *  szDest       : pointer to a string containing the target DIR
  72.  *  fpfnCopy     : callback function used to notify called of copy status
  73.  *  fCopy        : flags
  74.  *
  75.  *      FC_SECTION      - szSource is a section name
  76.  *      FC_LIST         - szSource is a pointer to a list, each item \0
  77.  *                        terminated and the whole list \0\0 terminated
  78.  *      FC_FILE         - szSource is a file name.
  79.  *      FC_QUALIFIED    - szSource is a fully qualified file name.
  80.  *      FC_DEST_QUALIFIED - szDir is fully qualified. Don't expand this.
  81.  *
  82.  *  NOTES:
  83.  *      if szSource points to a string of the form '#name' the section
  84.  *      named by 'name' will be used as the source files
  85.  *
  86.  *      the first field of each line in the secion is used as the name of the
  87.  *      source file.  A file name has the following form:
  88.  *
  89.  *          #:name
  90.  *
  91.  *          #       - Disk number containing file 1-9,A-Z
  92.  *          name    - name of the file, may be a wild card expression
  93.  *
  94.  *  Format for copy status function
  95.  *
  96.  *  BOOL FAR PASCAL CopyStatus(int msg, int n, PSTR szFile)
  97.  *
  98.  *      msg:
  99.  *          COPY_ERROR          error occured while copying file(s)
  100.  *                              n      is the DOS error number
  101.  *                              szFile is the file that got the error
  102.  *                              return: TRUE ok, FALSE abort copy
  103.  *
  104.  *          COPY_STATUS         Called each time a new file is copied
  105.  *                              n      is the percent done
  106.  *                              szFile is the file being copied
  107.  *                              return: TRUE ok, FALSE abort copy
  108.  *
  109.  *          COPY_INSERTDISK     Please tell the user to insert a disk
  110.  *                              n      is the disk needed ('1' - '9')
  111.  *                              return: TRUE try again, FALSE abort copy
  112.  *
  113.  *          COPY_QUERYCOPY      Should this file be copied?
  114.  *                              n      line index in SETUP.INF section (0 based)
  115.  *                              szFile is the line from section
  116.  *                              return: TRUE copy it, FALSE dont copy
  117.  *
  118.  *          COPY_START          Sent before any files are copied
  119.  *
  120.  *          COPY_END            Sent after all files have been copied
  121.  *                              n   is dos error if copy failed
  122.  *
  123.  *
  124.  *  EXIT: returns TRUE if successful, FALSE if failure.
  125.  *
  126.  */
  127.  
  128. WORD FAR PASCAL FileCopy (LPSTR szSource, PSTR szDir, FPFNCOPY fpfnCopy, WORD fCopy)
  129. {
  130.     int       err = ERROR_OK;
  131.     char      szFile[MAXPATHLEN];
  132.     char      szPath[MAXPATHLEN];
  133.     char      szLogSrc[MAXPATHLEN];
  134.     char      szSrcBase[15];
  135.     char      szSrc[MAXPATHLEN];
  136.     char      szErrFile[MAXPATHLEN];
  137.     LPSTR far *pFileList;
  138.     LPSTR far *pFileListBegin;
  139.     LPSTR     pFile;
  140.     LPSTR     pFileBegin;
  141.     BOOL      f;
  142.     BOOL      fDoCopy;
  143.     int       n = 0;
  144.     int       nDisk;
  145.     char      cDisk;
  146.     int       cntFiles = 0;
  147.     PINF      pinf;
  148.  
  149.     #define CALLBACK(msg,n,pFile) \
  150.         (fpfnCopy ? ((*fpfnCopy)((WORD)(msg),(int)(n),(LPSTR)(pFile))) : FC_IGNORE)
  151.  
  152.     if (!szSource || !*szSource || !szDir || !*szDir)
  153.         return FALSE;
  154.  
  155. #ifndef COMPRESS
  156.     AllocCopyBuf();
  157. #endif
  158.  
  159.     /*
  160.      *  fix up the drive in the destination
  161.      */
  162.  
  163.     if ( fCopy & FC_DEST_QUALIFIED )
  164.        lstrcpy(szPath,szDir);
  165.     else
  166.        ExpandFileName(szDir,szPath);
  167.  
  168.     fCopy &= ~FC_DEST_QUALIFIED;
  169.  
  170.     if (szSource[0] == '#' && fCopy == FC_FILE)
  171.     {
  172.         fCopy = FC_SECTION;
  173.         ++szSource;
  174.     }
  175.  
  176.     switch (fCopy)
  177.     {
  178.         case FC_LSTPTR:
  179.             pFileList = pFileListBegin = (LPSTR far *)szSource;
  180.             pFileBegin = *pFileList;
  181.  
  182.             while ( pFileList[n] ) {
  183.                if ( *pFileList[n] )
  184.                   ++cntFiles;
  185.                ++n;
  186.             }
  187.  
  188.             break;
  189.  
  190.         case FC_SECTION:
  191.         {
  192.         char buf[40];
  193.  
  194.         fartonear(buf, szSource);
  195.             szSource = infFindSection(NULL,buf);
  196.             if (szSource == NULL)
  197.                 goto exit;
  198.  
  199.         fCopy = FC_LIST;
  200.         }
  201.             // fall through to FC_LIST
  202.  
  203.         case FC_LIST:
  204.             pFileBegin = szSource;
  205.             cntFiles = infLineCount(szSource);
  206.             break;
  207.  
  208.         case FC_FILE:
  209.         case FC_QUALIFIED:
  210.         default:
  211.             pFileBegin = szSource;
  212.             cntFiles = 1;
  213.     }
  214.  
  215.     /*
  216.      * Does the destination directory exist? if not create it.
  217.      */
  218.     if (!DosValidDir(szPath)) {
  219.  
  220.         err = DosMkDir(szPath);
  221.  
  222.     // oh no! this is bad
  223.  
  224.         if (err != ERROR_OK) {
  225.             CALLBACK(COPY_ERROR,err,szPath);
  226.             goto exit;
  227.         }
  228.     }
  229.  
  230.     /*
  231.      *  walk all files in the list and call DosCopy ....
  232.      *
  233.      *  NOTES:
  234.      *      we must walk file list sorted by disk number.
  235.      *      we should use the disk that is currently inserted.
  236.      *      we should do a find first/find next on the files????
  237.      *      we need to check for errors.
  238.      *      we need to ask the user to insert disk in drive.
  239.      *
  240.      */
  241.     CALLBACK(COPY_START,0,NULL);
  242.  
  243.     for (nDisk = 1; cntFiles > 0; nDisk++) {
  244.  
  245.         cDisk      = CHDISK(nDisk);
  246.         pFileList  = pFileListBegin;
  247.         pFile      = pFileBegin;
  248.         n          = 0;
  249.  
  250.         while (pFile) {
  251.  
  252.             /*
  253.              *  should we copy this file?
  254.              *  copy the files in disk order.
  255.              */
  256.             fDoCopy = pFile[1] == ':' && cDisk == UP_CASE(pFile[0]) ||
  257.                       pFile[1] != ':' && nDisk == 1 && *pFile ||
  258.                       fCopy == FC_QUALIFIED;
  259.  
  260.             if (fDoCopy)
  261.                 cntFiles--;         // done with a file. decrement count.
  262.  
  263.             if (fDoCopy && CALLBACK(COPY_QUERYCOPY,n,pFile)) {
  264.  
  265.                 if (CALLBACK(COPY_STATUS, 0, pFile) == FC_ABORT) {
  266.             err = ERROR_NOFILES;
  267.                     goto exit;
  268.         }
  269.  
  270.         // now we convert logical dest into a physical (unless FC_QUALIFIED)
  271.  
  272.                 infParseField(pFile, 1, szLogSrc);     // logical source
  273.                 if ( fCopy != FC_QUALIFIED )
  274.                    ExpandFileName(szLogSrc, szSrc); // full physical source
  275.                 else
  276.                    lstrcpy(szSrc,szLogSrc);
  277.  
  278. tryagain:   
  279.                 // Call low level copy command
  280.  
  281.                 err = DosCopy(szSrc, szPath);
  282.       
  283.                 if (err != ERROR_OK) {
  284.  
  285.             lstrcpy(szSrcBase, FileName(szSrc)); // save base name
  286.  
  287.                     if (err == ERROR_FILENOTFOUND || err == ERROR_PATHNOTFOUND) {
  288.  
  289.                         // isolate the path
  290.  
  291.                         StripPathName(szSrc);
  292.  
  293.                // now try to get a new path in szSrc
  294.  
  295.                        switch (CALLBACK(COPY_INSERTDISK, szLogSrc[0], szSrc)) {
  296.                    case FC_RETRY:
  297.                    catpath(szSrc, szSrcBase);    // add the file back on
  298.                    goto tryagain;            // and try again...
  299.  
  300.                        case FC_ABORT:
  301.                            goto exit;
  302.  
  303.                    case FC_IGNORE:
  304.                         break;
  305.                        }
  306.  
  307.                     }
  308.  
  309.             // ERROR situation
  310.             //
  311.             // this may be a real error or something like
  312.             // a share violation on a network.
  313.  
  314.             ExpandFileName(szLogSrc, szSrc);    // full physical source
  315.  
  316.             // if it is a write error report the destination file
  317.             // otherwise report with the source file
  318.  
  319.             switch (err) {
  320.             case ERROR_WRITE:
  321.                 lstrcpy(szErrFile, szPath);
  322.             catpath(szErrFile, szSrcBase);
  323.                 break;
  324.  
  325.             default:
  326.                 lstrcpy(szErrFile, szSrc);
  327.             }
  328.  
  329.                     switch (CALLBACK(COPY_ERROR, err, szErrFile)) {
  330.  
  331.                     case FC_RETRY:
  332.                             goto tryagain;
  333.     
  334.                     case FC_ABORT:
  335.                             goto exit;
  336.  
  337.                     case FC_IGNORE:
  338.                             break;
  339.                     }
  340.                 }
  341.  
  342.                 if (CALLBACK(COPY_STATUS,100,pFile) == FC_ABORT) {
  343.                     err = !ERROR_OK;
  344.                     goto exit;
  345.                 }
  346.             }
  347.  
  348.             /*
  349.              * Move on to next file in the list
  350.              */
  351.             n++;
  352.             if (fCopy == FC_LSTPTR)
  353.                 pFile = *(++pFileList);
  354.              else if (fCopy == FC_LIST)
  355.                 pFile = infNextLine(pFile);
  356.             else
  357.                 pFile = NULL;
  358.         }
  359.     }
  360.  
  361.     err = ERROR_OK;
  362.  
  363. exit:
  364.     CALLBACK(COPY_END,err,NULL);
  365. #ifndef COMPRESS
  366.     FreeCopyBuf();
  367. #endif
  368.     return err;
  369.  
  370.     #undef CALLBACK
  371. }
  372.  
  373. #ifndef COMPRESS
  374.  
  375. /*  AllocCopyBuf()
  376.  *
  377.  *  allocate a buffer for DosCopy to use
  378.  *
  379.  */
  380. void NEAR PASCAL AllocCopyBuf()
  381. {
  382.     if (iBuf++ == 0)
  383.     {
  384.         nBufSize = MAXBUF;
  385.         for(;;)
  386.         {
  387.             lpBuf = FALLOC(nBufSize);
  388.             if (lpBuf || nBufSize == 1)
  389.                 break;
  390.             nBufSize /= 2;
  391.         }
  392.         if (lpBuf == NULL)
  393.             iBuf--;
  394.     }
  395. }
  396.  
  397. /*  FreeCopyBuf()
  398.  *
  399.  *  free copy buffer, if its use count is zero
  400.  *
  401.  */
  402. void NEAR PASCAL FreeCopyBuf()
  403. {
  404.     if (iBuf > 0 && --iBuf == 0 && lpBuf)
  405.     {
  406.         FFREE(lpBuf);
  407.     }
  408. }
  409. #endif
  410.  
  411. PSTR GetExtension(PSTR szFile)
  412. {
  413.     PSTR ptr;
  414.  
  415.     for (ptr = szFile; *ptr && *ptr != '.'; ptr++);
  416.  
  417.     if (*ptr != '.')
  418.         return NULL;
  419.     else
  420.         return ptr+1;
  421.  
  422. }
  423.  
  424. BOOL GetCompressedName(PSTR szComp, PSTR szSrc)
  425. {
  426.     PSTR ptr;
  427.  
  428.     lstrcpy(szComp, szSrc);
  429.  
  430.     ptr = GetExtension(szComp);
  431.  
  432.     if (ptr && !lstrcmpi(ptr, "sys")) {
  433.         szComp[lstrlen(szComp)-1] = '$';
  434.         return TRUE;
  435.     }
  436.  
  437.     return FALSE;
  438. }
  439.  
  440. /*  DosCopy(PSTR szSrc, PSTR szPath)
  441.  *
  442.  *  Copy the file specifed by szSrc to the drive and directory
  443.  *  specifed by szPath
  444.  *
  445.  *  ENTRY:
  446.  *      szSrc   - File name to copy from
  447.  *      szPath  - directory to copy to
  448.  *
  449.  *  RETURNS:
  450.  *      0 - no error, else dos error code
  451.  *
  452.  */
  453. int NEAR DosCopy(PSTR szSrc, PSTR szPath)
  454. {
  455.     FCB         fcb;
  456.     WORD        size;
  457.     int         fhSrc,fhDst;
  458.     char        szFile[MAXPATHLEN];
  459.     char        szComp[MAXPATHLEN];
  460.     int         f = ERROR_OK;
  461.     unsigned    date;
  462.     unsigned    time;
  463.     long    l;
  464.     BOOL    bCompressedName;
  465.     
  466.  
  467. #ifdef DEBUG
  468.     if (fDontCopy)
  469.         return ERROR_OK;
  470.  
  471.     if (infGetProfileString(NULL,"setup","copy",szFile) && szFile[0] == 'f')
  472.         return ERROR_OK;
  473. #endif
  474.  
  475.     AllocCopyBuf();
  476.  
  477.     if (!lpBuf)
  478.         return ERROR_NOMEMORY;
  479.  
  480. #ifdef CHECK_FLOPPY
  481.     if (!IsDiskInDrive(szSrc[0]))
  482.     {
  483.         f = ERROR_FILENOTFOUND;
  484.         goto errfree;
  485.     }
  486. #endif
  487.  
  488.  
  489.     // allows both sy$ and sys on the disks
  490.  
  491.     if (GetCompressedName(szComp, szSrc) &&
  492.         DosFindFirst(&fcb, szComp, ATTR_FILES)) {
  493.  
  494.         bCompressedName = TRUE;
  495.  
  496.     } else {
  497.  
  498.         bCompressedName = FALSE;
  499.  
  500.         if (!DosFindFirst(&fcb, szSrc, ATTR_FILES)) {
  501.         f = ERROR_FILENOTFOUND;
  502.         goto errfree;
  503.     }
  504.     }
  505.  
  506.     /*
  507.      * copy every file that matches the file pattern passed in.
  508.      */
  509.     do
  510.     {
  511.         /*
  512.          * create the source file name from the source path and the file
  513.          * name that DosFindFirst/Next found
  514.          */
  515.         lstrcpy(szFile,szSrc);
  516.         StripPathName(szFile);
  517.         catpath(szFile,fcb.szName);
  518.  
  519.         fhSrc = FOPEN(szFile);
  520.  
  521.         if (fhSrc == -1)
  522.         {
  523.             f = FERROR();
  524.             goto errfree;
  525.         }
  526.  
  527.         /* Save date of opened file */
  528.  
  529.         if (_dos_getftime(fhSrc,&date,&time))
  530.            goto errclose1;
  531.  
  532.         /*
  533.          * create the destination file name from the dest path and the file
  534.          * name that DosFindFirst/Next found
  535.          */
  536.         lstrcpy(szFile,szPath);
  537.  
  538.     // don't support wildcards for compressed files
  539.  
  540.         if (bCompressedName)
  541.         catpath(szFile,FileName(szSrc));
  542.     else
  543.             catpath(szFile,fcb.szName);    // used name from fcb
  544.  
  545.         fhDst = FCREATE(szFile);
  546.  
  547.         if (fhDst == -1)
  548.         {
  549.             f = FERROR();
  550.             goto errclose1;
  551.         }
  552.  
  553.         while (size = FREAD(fhSrc,lpBuf,nBufSize))
  554.         {
  555.             if (FWRITE(fhDst,lpBuf,size) != size)
  556.             {
  557.                 /* write error? */
  558.                 f = FERROR();
  559.                 if (f == ERROR_OK)
  560.                     f = ERROR_WRITE;
  561.                 goto errclose;
  562.             }
  563.         }
  564.  
  565.         /* Restore date of written file */
  566.         _dos_setftime(fhDst,date,time);
  567.  
  568. errclose:
  569.         FCLOSE(fhDst);
  570. errclose1:
  571.         FCLOSE(fhSrc);
  572.  
  573.     }   while (f == ERROR_OK && DosFindNext(&fcb));
  574.  
  575. errfree:
  576.  
  577.     FreeCopyBuf();
  578.  
  579.     return f;
  580. }
  581.  
  582.  
  583. /* BOOL fnMystrstr(char *szSrcStr, char *szSearchStr);
  584.  *
  585.  * Function will return BOOL value as to weather the Search string exists
  586.  * any where within the source string. The difference between this func
  587.  * the C run time func is that this one is simpler and is also not case
  588.  * sensitive.
  589.  *
  590.  * ENTRY: szSrcStr    - Char buffer to be searched.
  591.  *
  592.  *        szSearchStr - String that will be searched for.
  593.  *
  594.  * EXIT:  BOOL value as to weather or not string was found.
  595.  *
  596.  *
  597.  * WARNING: Source and search strings MUST be null terminated.
  598.  *          
  599.  *
  600.  */
  601. BOOL fnMystrstr(szSrcStr, szSearchStr)
  602. char       *szSrcStr;
  603. char       *szSearchStr;
  604. {
  605.    unsigned      len;             // Get length of search string.
  606.  
  607.    while (szSearchStr[0] == '.' && SLASH(szSearchStr[1]))
  608.       szSearchStr+=2;
  609.  
  610.    len = lstrlen(szSearchStr);
  611.  
  612.    while ( !ISEOL(*szSrcStr) ) {
  613.       if ( ! strnicmp(szSrcStr,szSearchStr,len))
  614.          return TRUE;
  615.       ++szSrcStr;
  616.    }
  617.    return FALSE;
  618.  
  619. }
  620.  
  621. /*  BOOL GetDiskPath(char cDisk, szPath)
  622.  *
  623.  *  This function will retrive the full path name for a logical disk
  624.  *  the code reads the [disks] section of SETUP.INF and looks for
  625.  *  n = path where n is the disk char.  NOTE the disk '0' defaults to
  626.  *  the root windows directory.
  627.  *
  628.  *  ENTRY:
  629.  *
  630.  *  cDisk        : what disk to find 0-9,A-Z
  631.  *  szPath       : buffer to hold disk path
  632.  *
  633.  */
  634. BOOL NEAR GetDiskPath(char cDisk, PSTR szPath)
  635. {
  636.     char    ach[2];
  637.     char    szBuf[MAXPATHLEN];
  638.  
  639.     if (cDisk == '0')
  640.     {
  641.         /*
  642.          * return the windows setup directory
  643.          */
  644.         lstrcpy(szPath,szSetupPath);
  645.         return TRUE;
  646.     }
  647.  
  648.     /*
  649.      * now look in the [disks] section for a full path name
  650.      */
  651.     ach[0] = cDisk;
  652.     ach[1] = 0;
  653.     if ( !infGetProfileString(NULL,szDisks,ach,szPath) )
  654.        return FALSE;
  655.     infParseField(szPath,1,szPath);
  656.     /*
  657.      *  is the path relative? is so prepend the szDiskPath
  658.      */
  659.     if (szPath[0] == '.' || szPath[0] == 0)
  660.     {
  661.         lstrcpy(szBuf,szDiskPath);
  662.         if (! fnMystrstr(szDiskPath,szPath) )
  663.            catpath(szBuf,szPath);
  664.         lstrcpy(szPath,szBuf);
  665.     }
  666.     return TRUE;
  667. }
  668.  
  669.  
  670. /*  BOOL FAR PASCAL ExpandFileName(PSTR szFile, PSTR szPath)
  671.  *
  672.  *  This function will retrive the full path name for a file
  673.  *  it will expand, logical disk letters to pyshical ones
  674.  *  will use current disk and directory if non specifed.
  675.  *
  676.  *  if the drive specifed is 0-9, it will expand the drive into a
  677.  *  full pathname using GetDiskPath()
  678.  *
  679.  *  IE  0:system ==>  c:windows\system
  680.  *      1:foo.txt     a:\foo.txt
  681.  *
  682.  *  ENTRY:
  683.  *
  684.  *  szFile       : File name to expandwhat disk to find
  685.  *  szPath       : buffer to hold full file name
  686.  *
  687.  */
  688. BOOL FAR PASCAL ExpandFileName(PSTR szFile, PSTR szPath)
  689. {
  690.     char    szBuf[MAXPATHLEN*2];
  691.  
  692.     if (szFile[1] == ':' && GetDiskPath(szFile[0],szBuf))
  693.     {
  694.         lstrcpy(szPath,szBuf);
  695.         if (szFile[2])
  696.             catpath(szPath,szFile + 2);
  697.     }
  698.     else
  699.     {
  700.         lstrcpy(szPath,szFile);
  701.     }
  702.     return TRUE;
  703. }
  704.  
  705. /*----------------------------------------------------------------------------*\
  706. |   wsCopy()                                                                   |
  707. |                                                                              |
  708. \*----------------------------------------------------------------------------*/
  709. BOOL PUBLIC wsCopy(PSTR szSection)
  710. {
  711.     PINF    pinf;
  712.     char    szSource[MAXSTR];
  713.     char    szDest[MAXSTR];
  714.     char    szLocalTmp[MAXSTR];
  715.     int     nFiles;
  716.     int        err = ERROR_OK;
  717.     char    buf[MAXSTR];
  718.  
  719.     // we use different sections for net and win386 setup.  net setup
  720.     // overrides win386.
  721.  
  722.     dprintf("wsCopy %s\n",szSection);
  723.  
  724.     pinf = infFindSection(NULL,szSection);
  725.     if (pinf == NULL)
  726.         return FALSE;
  727.  
  728.     ProPrintf(ID_STATUS1, wsLoadSz(IDS_WAITCOPY,NULL));
  729.  
  730.     for (nFiles=0; pinf; pinf = infNextLine(pinf))
  731.     {
  732.  
  733.         dprintf("inf line:%ls\n", (LPSTR)pinf);
  734.  
  735.         infParseField(pinf,1,szSource);
  736.  
  737.         if (szSource[0] == '#') {
  738.  
  739.         // count these, and copy below
  740.  
  741.         nFiles += infLineCount(infFindSection(NULL, szSource + 1));
  742.         dprintf("nFiles:%d\n", nFiles);
  743.  
  744.         } else
  745.             nFiles++;
  746.     }
  747.     dprintf("nFiles:%d\n", nFiles);
  748.  
  749.     ProSetBarRange(nFiles);
  750.  
  751.     for (pinf = infFindSection(NULL,szSection); pinf; pinf = infNextLine(pinf))
  752.     {
  753.         infParseField(pinf,1,szSource);
  754.         infParseField(pinf,2,szDest);
  755.         if ((err = FileCopy(szSource,szDest,(FPFNCOPY)wsCopyStatus,FC_FILE)) != ERROR_OK)
  756.            break;
  757.     }
  758.  
  759.     return err == ERROR_OK;
  760. }
  761.  
  762. /*----------------------------------------------------------------------------*\
  763. |   define the call back function used by the FileCopy() function.           |
  764. |                                                                              |
  765. \*----------------------------------------------------------------------------*/
  766.  
  767. WORD FAR PASCAL wsCopyStatus(int msg, int n, LPSTR szFile)
  768. {
  769.     char buf[80];
  770.  
  771.     switch (msg)
  772.     {
  773.     case COPY_INSERTDISK:
  774.             return wsInsertDisk(n,szFile);
  775.  
  776.     case COPY_ERROR:
  777.             return wsCopyError(n,szFile);
  778.  
  779.     case COPY_QUERYCOPY:
  780.  
  781.         // special case hack for .386 files built into win386.exe
  782.  
  783.         infParseField(szFile, 1, buf);
  784.  
  785.         if (*FileName(buf) == '*')
  786.             return FALSE;        // don't copy
  787.  
  788.         return TRUE;
  789.  
  790.     case COPY_END:
  791.     case COPY_START:
  792.         SetErrorMode(msg == COPY_START);    // don't crit error on us
  793.         break;
  794.  
  795.         case COPY_STATUS:
  796.         if (n == 0)
  797.         {
  798.             dprintf("%ls\n", (LPSTR)szFile);
  799.  
  800.         // if their is a title update it.  this allows shared titles
  801.  
  802.         if (infParseField(szFile,2,buf))
  803.                     ProPrintf(ID_STATUS2, wsLoadSz(IDS_COPYING,NULL), (LPSTR)buf);
  804.             }
  805.  
  806.         if (n == 100)
  807.         {
  808.         ProDeltaPos(1);
  809.             }
  810.             if (! wsYield() )
  811.                 return FC_ABORT;
  812.  
  813.         break;
  814.     }
  815.     return FC_IGNORE;
  816. }
  817.  
  818. /*----------------------------------------------------------------------------*\
  819. |                                                                              |
  820. | wsCopyError()                                                                |
  821. |                                                                              |
  822. |   Handles errors, as the result of copying files.                            |
  823. |                                                                              |
  824. |   this may include net contention errors, in witch case the user must           |
  825. |   retry the operation.                               |
  826. |                                                                              |
  827. \*----------------------------------------------------------------------------*/
  828. WORD PUBLIC wsCopyError(int n, LPSTR sz)
  829. {
  830.     char buf[200];
  831.     char file[MAXSTR];
  832.     int  res;
  833.  
  834.     lstrcpy(file, sz);        // in case our DS moves durring wsLoadSz()
  835.  
  836.     if (!wsLoadSz(IDS_ERROR + n, buf)) {
  837.  
  838.         // error string doesn't exist.  if it is a net error use
  839.     // net string, if not that use generic error string
  840.  
  841.         if (n > ERROR_SHARE)
  842.         wsLoadSz(IDS_ERROR + ERROR_SHARE, buf);
  843.     else
  844.             wsprintf(buf, wsLoadSz(IDS_ERROR,NULL), n);
  845.     }
  846.  
  847.     lstrcat(buf,"\n");
  848.  
  849.     // check for the out of disk space case
  850.  
  851.     if (n == ERROR_WRITE) {        // check for out of disk space
  852.  
  853.         dprintf("free space on disk %ld\n", DosDiskFreeSpace(0));
  854.  
  855.         if (DosDiskFreeSpace(0) < 50000)
  856.             lstrcat(buf, wsLoadSz(IDS_OUTOFDISK, NULL));
  857.     }
  858.  
  859.     lstrcat(buf, file);        // add the file name
  860.  
  861.     // pass these through globals
  862.  
  863.     pErrMsg = buf;
  864.     res = fDialog(DLG_COPYERROR, GetActiveWindow(), wsErrorDlg);
  865.  
  866.     return res;
  867. }
  868.  
  869.  
  870. /*----------------------------------------------------------------------------*\
  871. |                                                                              |
  872. | wsInsertDisk()                                                               |
  873. |                                                                              |
  874. |   Handles errors, as the result of copying files.                            |
  875. |                                                                              |
  876. \*----------------------------------------------------------------------------*/
  877. WORD PUBLIC wsInsertDisk(int n, LPSTR szSrcPath)
  878. {
  879.     cDisk  = (char)n;
  880.  
  881.     szEdit = szSrcPath;
  882.  
  883.     return (WORD)fDialog(DLG_INSERTDISK, GetActiveWindow(), wsDiskDlg);
  884. }
  885.  
  886. /*----------------------------------------------------------------------------*\
  887. |   wsDiskDlg( hDlg, uiMessage, wParam, lParam )                               |
  888. |                                                                              |
  889. |   Arguments:                                                                 |
  890. |       hDlg            window handle of about dialog window                   |
  891. |       uiMessage       message number                                         |
  892. |       wParam          message-dependent                                      |
  893. |       lParam          message-dependent                                      |
  894. |                                                                              |
  895. |   Returns:                                                                   |
  896. |       TRUE if message has been processed, else FALSE                         |
  897. |                                                                              |
  898. \*----------------------------------------------------------------------------*/
  899.  
  900. BOOL FAR PASCAL wsDiskDlg(HWND hDlg, unsigned uiMessage, WORD wParam, long lParam)
  901. {
  902.  
  903.     switch (uiMessage)
  904.     {
  905.     case WM_COMMAND:
  906.         switch (wParam)
  907.         {
  908.         case ID_OK:
  909.  
  910.             // szEdit points to the path that will be retried
  911.  
  912.             GetDlgItemText(hDlg, ID_EDIT, szEdit, MAXSTR);
  913.             lstrcpy(szDiskPath, szEdit);    // and make this the default
  914.  
  915.                     EndDialog(hDlg, FC_RETRY);
  916.             break;
  917.  
  918.         case ID_CANCEL:
  919.  
  920.             EndDialog(hDlg, FC_IGNORE);
  921.             break;
  922.         }
  923.         return TRUE;
  924.  
  925.         case WM_INITDIALOG:
  926.         {
  927.             /*
  928.              *  now look in the [disks] section for the disk name
  929.              *  the disk name is the second field.
  930.              */
  931.         char ach[2];
  932.         char buf[MAXSTR];
  933.         char buf2[MAXSTR];
  934.  
  935.             ach[0] = cDisk;
  936.             ach[1] = 0;
  937.  
  938.             infGetProfileString(NULL,wsLoadSz(IDS_DISKS,NULL),ach,buf);
  939.  
  940.             infParseField(buf,2,buf2);
  941.  
  942.             SetDlgItemText(hDlg,ID_TEXT,buf2);
  943.         SetDlgItemText(hDlg,ID_EDIT,szEdit);
  944.  
  945.         wsDlgInit(hDlg);
  946.  
  947.         MessageBeep(0);
  948.  
  949.             return TRUE;
  950.         }
  951.     }
  952.     return FALSE;
  953. }
  954.  
  955. /*----------------------------------------------------------------------------*\
  956. |   wsYield()                                                                  |
  957. |                                                                              |
  958. |   Description:                                                               |
  959. |       Handle any messages in our Que, return when the Que is empty           |
  960. |                                                                              |
  961. |   Returns:                                                                   |
  962. |       FALSE if a WM_QUIT message was encountered, TRUE otherwise             |
  963. |                                                                              |
  964. \*----------------------------------------------------------------------------*/
  965. BOOL PUBLIC wsYield()
  966. {
  967.     MSG     msg;
  968.     BOOL    retval = TRUE;
  969.  
  970.     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  971.  
  972.         if ( msg.message == WM_QUIT )
  973.            retval = FALSE;
  974.  
  975.         if (CheckSpecialKeys(&msg))
  976.         continue;
  977.  
  978.         TranslateMessage(&msg);
  979.         DispatchMessage(&msg);
  980.  
  981.     }
  982.     return retval;
  983. }
  984.  
  985. /***************************************************************************
  986.  * BOOL PUBLIC CheckSpecialKeys(PMSG pmsg)
  987.  * 
  988.  * returns:
  989.  *    TRUE    it was special and I delt with it
  990.  *    FALSE    it wasn't special so pass it on
  991.  *
  992.  **************************************************************************/
  993. BOOL PUBLIC CheckSpecialKeys(LPMSG lpmsg)
  994. {
  995.     static HWND hwndOldActive = NULL;
  996.  
  997.         if (lpmsg->message != WM_KEYDOWN)
  998.         return FALSE;
  999.  
  1000.         switch(lpmsg->wParam) {
  1001.  
  1002.     // exit keys
  1003.  
  1004.         case VK_F3:
  1005.         PostMessage(hwndWS,WM_COMMAND,ID_EXITSETUP,0L);
  1006.         break;
  1007.  
  1008.     default:
  1009.         return FALSE;
  1010.         }
  1011.     return TRUE;        // yes, this was a special key
  1012. }
  1013.  
  1014. #define CBSECTORSIZE    512
  1015. #define INT13_READ    2
  1016.  
  1017. /*--------------------------------------------------------------------------
  1018.                                         
  1019.   IsValidDiskette() -                             
  1020.                                         
  1021. --------------------------------------------------------------------------*/
  1022.  
  1023. BOOL NEAR IsValidDiskette(int iDrive)
  1024. {
  1025.   char        buf[CBSECTORSIZE];
  1026.  
  1027.   iDrive |= 0x0020;    // make lower case
  1028.  
  1029.   iDrive -= 'a';    // A = 0, B = 1, etc. for BIOS stuff
  1030.  
  1031.   return MyReadWriteSector(buf, INT13_READ, iDrive, 0, 0, 1);
  1032. }
  1033.  
  1034.  
  1035.  
  1036. #ifdef CHECK_FLOPPY
  1037.  
  1038. /*  BOOL IsDiskInDrive(char cDisk)
  1039.  *
  1040.  *  Is the specifed disk in the drive
  1041.  *
  1042.  *  ENTRY:
  1043.  *
  1044.  *  cDisk        : what disk required to be in the drive (logical)
  1045.  *
  1046.  *  return TRUE if the specifed disk is in the drive
  1047.  *         FALSE if the wrong disk is in the drive or disk error
  1048.  *
  1049.  */
  1050. BOOL NEAR IsDiskInDrive(int iDisk)
  1051. {
  1052.  
  1053.     if ((iDisk  >= 'A' && iDisk <= 'Z') || 
  1054.         (iDisk  >= 'a' && iDisk <= 'z')) {
  1055.  
  1056.         if (DosRemoveable(iDisk)) {
  1057.  
  1058.             if (!IsValidDiskette(iDisk))
  1059.                 return FALSE;
  1060.         }
  1061.  
  1062.  
  1063.         return TRUE;
  1064.     }
  1065.  
  1066.     return TRUE;    // for non drive letters assume a path
  1067.                 // and thus always in.
  1068. }
  1069.  
  1070. #endif 
  1071.  
  1072. void FAR PASCAL catpath(PSTR path, PSTR sz)
  1073. {
  1074.     //
  1075.     // Remove any drive letters from the directory to append
  1076.     //
  1077.     if ( sz[1] == ':' )
  1078.        sz+=2;
  1079.  
  1080.     //
  1081.     // Remove any current directories ".\" from directory to append
  1082.     //
  1083.     while (sz[0] == '.' && SLASH(sz[1]))
  1084.         sz+=2;
  1085.  
  1086.     //
  1087.     // Dont append a NULL string or a single "."
  1088.     //
  1089.     if (*sz && !(sz[0] == '.' && sz[1] == 0))
  1090.     {
  1091.        if ( (!SLASH(path[lstrlen(path)-1])) && ((path[lstrlen(path)-1]) != ':') )
  1092.           lstrcat(path,CHSEPSTR);
  1093.        lstrcat(path,sz);
  1094.     }
  1095. }
  1096.  
  1097.  
  1098. PSTR FAR PASCAL FileName(PSTR szPath)
  1099. {
  1100.     PSTR   sz;
  1101.  
  1102.     for (sz=szPath; *sz; sz++)
  1103.         ;
  1104.     for (; sz>=szPath && !SLASH(*sz) && *sz!=':'; sz--)
  1105.         ;
  1106.     return ++sz;
  1107. }
  1108.  
  1109. PSTR FAR PASCAL StripPathName(PSTR szPath)
  1110. {
  1111.     PSTR   sz;
  1112.  
  1113.     sz = FileName(szPath);
  1114.  
  1115.     if (sz > szPath+1 && SLASH(sz[-1]) && sz[-2] != ':')
  1116.         sz--;
  1117.  
  1118.     *sz = 0;
  1119.     return szPath;
  1120. }
  1121.