home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 September / PCWK996.iso / demo / wgelectr / emul51 / setup.c < prev    next >
C/C++ Source or Header  |  1994-08-26  |  18KB  |  529 lines

  1. /****************************************************************************
  2. Module name: Setup.C
  3. Programmer : Nils E Thorell  & Michael Quirk
  4. *****************************************************************************/
  5.  
  6. /* #include "..\nowindws.h"
  7. #undef NOATOM
  8. #undef NOCTLMGR
  9. #undef NOKERNEL
  10. #undef NOLFILEIO
  11. #undef NOLSTRING
  12. #undef NOMB
  13. #undef NOMEMMGR
  14. #undef NOMINMAX
  15. #undef NOMSG
  16. #undef NOOPENFILE
  17. #undef NORESOURCE
  18. #undef NOSHOWWINDOW
  19. #undef NOSYSMETRICS
  20. #undef NOUSER
  21. #undef NOWINMESSAGES
  22. #undef NOWINOFFSETS
  23. #undef NOWINSTYLES */
  24. #pragma warn -pro
  25.  
  26. #define PATHS    "Paths"
  27.  
  28. #include <windows.h>
  29. #include <dde.h>
  30.  
  31. #include <dir.h>
  32. #include <dos.h>
  33. #include <direct.h>
  34. #include <string.h>
  35. #include <io.h>         // Borland
  36. #include <ctype.h>
  37.  
  38. #include "Setup.H"
  39. #include "SetupInf.H"
  40. #include "setuppm.h"
  41. #include "Meter.H"
  42.  
  43. BOOL NEAR PASCAL CreateDstDirTree (HWND hDlgStatus);
  44. BOOL NEAR PASCAL CopyAllFiles (HWND hDlgStatus);
  45. // BOOL NEAR PASCAL CreatePMInfo (HANDLE hInstance);
  46. #define WasCancelled(hDlg) (!IsWindowEnabled(GetDlgItem(hDlg, IDCANCEL)))
  47.  
  48. char _szAppName[] = "Setup";
  49. HANDLE hInstance;
  50. char _szSrcDir[MAXDIR] = "x:\\"; // Where SETUP.EXE was run from.
  51. char _szDstDir[MAXDIR];
  52.  
  53. void MyDelay(int ms)
  54. {
  55.     DWORD stop_time = GetTickCount() +  ms;    // in milliseconds ..
  56.  
  57.     while(GetTickCount() < stop_time)
  58.     ;
  59. }
  60.  
  61. #pragma argsused
  62. int PASCAL WinMain (HANDLE hInst, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  63. {
  64.    int nResult,i;
  65.    HWND hDlgStatus;
  66.    FARPROC fpStatDlgProc, fpProc, fpLoadDlgProc;
  67.    HANDLE hLibMeter;
  68.    DWORD dwDiskSpaceNeeded, dwFreeDiskSpace;
  69.    // struct diskfree_t DiskFreeSpace; Microsoft only!
  70.    struct dfree DiskFreeSpace;
  71.    char szBuf[100];
  72.  
  73.    // Don't let another instance of this application execute.
  74.    if (hPrevInstance != NULL) return(0);
  75.    
  76.    // Prepare the DDE Client window class so that we can use it later.
  77.    if (!RegisterDDEClient(hInst)) return(0);
  78.  
  79.    // Initialize the default source path so that it uses the same drive
  80.    // letter that the SETUP.EXE application was executed from.
  81.    GetModuleFileName(hInst, _szSrcDir, sizeof(_szSrcDir)); *(_fstrrchr(_szSrcDir, '\\') + 1) = 0;
  82.  
  83.    hInstance = hInst;
  84.  
  85.    // Check that the METER.DLL is available at the beginning.
  86.  
  87.    wsprintf(szBuf, "%sMETER.DLL", (LPSTR) _szSrcDir);
  88.    hLibMeter = LoadLibrary(szBuf);
  89.    if (hLibMeter < 32) {
  90.       MsgBox(hInstance, NULL, IDS_NOMETERLIB, _szAppName, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
  91.       return 0;
  92.    }
  93.  
  94.    // Read the SETUP.INF file into memory.
  95.    wsprintf(szBuf, "%s%sSETUP.INF", (LPSTR) _szSrcDir, (LPSTR) ((*(_fstrrchr(_szSrcDir, '\\') + 1) == 0) ? "" : "\\"));
  96.  
  97.    nResult = (SIM_INITIALIZE_ERROR) SetupInfoSys(SIM_INITIALIZE, 0, szBuf);
  98.    if (nResult != SIM_INIT_NOERROR) {
  99.       MsgBox(hInstance, NULL, (nResult == SIM_INIT_NOMEM) ? IDS_NOMEMORY : IDS_NOSETUPINFOFILE, _szAppName, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL, (LPSTR) szBuf);
  100.       FreeLibrary(hLibMeter);
  101.       return(0);
  102.    }
  103.  
  104.    // Get the amount of memory (in K) that is needed for the installation.
  105.    dwDiskSpaceNeeded = SetupInfoSys(SIM_GETSPACENEEDED, 0, 0);
  106.  
  107.  
  108.     // Create the Status dialog box.
  109.    fpStatDlgProc = MakeProcInstance(StatusDlgProc, hInstance);
  110.    hDlgStatus = CreateDialog(hInstance, MAKEINTRESOURCE(DLG_STATUS), NULL, fpStatDlgProc);
  111.  
  112.    do {
  113.       // Welcome user to setup program and prompt for destination directory.
  114.       fpProc = MakeProcInstance(WelcomeDlgProc, hInstance);
  115.       nResult = DialogBox(hInstance, MAKEINTRESOURCE(DLG_WELCOME), NULL, fpProc);
  116.       FreeProcInstance(fpProc);
  117.       if (nResult != IDOK) {
  118.       if(nResult != IDCANCEL)
  119.          MsgBox(hInstance, NULL, IDS_CANTSTART, _szAppName, MB_OK);
  120.       break;
  121.       }
  122.       // check if there is sufficient disk space on the destination drive.
  123.       //_dos_getdiskfree(_szDstDir[0] - 'A' + 1, &DiskFreeSpace);
  124.       getdfree(_szDstDir[0] - 'A' + 1, &DiskFreeSpace);
  125.       //dwFreeDiskSpace = ((DWORD) DiskFreeSpace.avail_clusters *
  126.       //                         (DWORD) DiskFreeSpace.sectors_per_cluster *
  127.       //                         (DWORD) DiskFreeSpace.bytes_per_sector) / 1024UL;
  128.       dwFreeDiskSpace = ((DWORD) DiskFreeSpace.df_avail *
  129.              (DWORD) DiskFreeSpace.df_sclus *
  130.              (DWORD) DiskFreeSpace.df_bsec) / 1024UL;
  131.  
  132.       if (dwFreeDiskSpace < dwDiskSpaceNeeded) {
  133.      MsgBox(hInstance, NULL, IDS_NODISKSPACE, _szAppName, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL, _szDstDir[0], dwFreeDiskSpace, dwDiskSpaceNeeded);
  134.      continue;
  135.       }
  136.  
  137.       // Try to create the destination directory tree.
  138.       ShowWindow(hDlgStatus, SW_SHOW);
  139.       UpdateWindow(hDlgStatus);
  140.       nResult = CreateDstDirTree(hDlgStatus);
  141.       ShowWindow(hDlgStatus, SW_HIDE);
  142.  
  143.       if (nResult == FALSE) {
  144.      // If the directory tree cannot be created, force loop to repeat.
  145.      dwFreeDiskSpace = 0;
  146.       }
  147.  
  148.    } while (dwFreeDiskSpace < dwDiskSpaceNeeded);
  149.  
  150.    if (nResult == IDCANCEL) {
  151.       DestroyWindow(hDlgStatus);
  152.       FreeProcInstance(fpStatDlgProc);
  153.       FreeLibrary(hLibMeter);
  154.       return(0);
  155.    }
  156.  
  157.    // Make the destination directory the current directory.
  158.    chdir(_szDstDir);
  159.  
  160.    // Try to copy the files.
  161.    ShowWindow(hDlgStatus, SW_SHOW);
  162.    UpdateWindow(hDlgStatus);
  163.    nResult = CopyAllFiles(hDlgStatus);
  164.    ShowWindow(hDlgStatus, SW_HIDE);
  165.  
  166.    // Cleanup the things that we no longer need.
  167.    DestroyWindow(hDlgStatus);
  168.    FreeProcInstance(fpStatDlgProc);
  169.    FreeLibrary(hLibMeter);
  170.  
  171.    if (nResult == FALSE) {
  172.       // Installation not complete.
  173.       MsgBox(hInstance, NULL, IDS_SETUPNOGOOD, _szAppName, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
  174.       return 0;
  175.    }
  176.  
  177.    i = CreatePMInfo(hInstance) ? IDS_PMADDOK : IDS_PMADDNOGOOD;
  178.    MsgBox(hInstance,NULL,i,_szAppName,MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
  179.    return 0;
  180. }
  181.  
  182.  
  183. // ********** Functions for Creating the destination directory tree **********
  184. BOOL NEAR PASCAL CreateDstDirTree (HWND hDlgStatus) {
  185.    int nResult, nMaxDirs, nDirNum;
  186.    char szBuf[MAXDIR]; MSG Msg;
  187.    /* new variables for multi-level directory create */
  188.    char tmp[80], destin[80];
  189.    int ix, totallen,i;
  190.    struct ffblk TEST;        /* for findfirst() function */
  191.  
  192.  
  193.    SetDlgItemText(hDlgStatus, ID_STATLINE1, "Creating destination directory tree...");
  194.    nMaxDirs = (int) SetupInfoSys(SIM_GETNUMDIRS, 0, 0);
  195.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 0, 0);
  196.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSINJOB, nMaxDirs + 1, 0);
  197.    SetDlgItemText(hDlgStatus, ID_STATLINE2, _szDstDir);
  198.  
  199.    // Create the destination directory.
  200.    nResult = chdir(_szDstDir);
  201.    if (nResult != 0) {
  202.       for(i = 0; i < 80 ; i++)    tmp[i] = '\0';
  203.  
  204.       strcpy(destin,_szDstDir);
  205.       totallen = strlen(destin);
  206.       i = ix = 0;
  207.       do{
  208.         if(ix > 3 && destin[ix] == '\\'){
  209.             if((i = findfirst(tmp,&TEST,FA_DIREC)) != 0){
  210.                 if((nResult = mkdir(tmp)) !=0)
  211.                 break;
  212.             }
  213.             tmp[ix] = destin[ix];
  214.         } else
  215.             tmp[ix] = destin[ix];
  216.  
  217.             if(destin[ix] == '\0' || ix == totallen){
  218.              if((i = findfirst(tmp,&TEST,FA_DIREC)) != 0){
  219.                 if((nResult = mkdir(tmp)) !=0)
  220.                     break;
  221.              }
  222.            i = 1;
  223.         }
  224.         ix++;
  225.       }while(ix <= totallen && i == 0);
  226.     }
  227.       if (nResult != 0) {
  228.      MsgBox(hInstance, hDlgStatus, IDS_CANTMAKEDIR, _szAppName, MB_ICONINFORMATION | MB_OK, (LPSTR) _szDstDir);
  229.      return FALSE;
  230.     } else chdir(_szDstDir);
  231.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 1, 0);
  232.  
  233.    MyDelay(600);
  234.    // Create any subdirectories under the destination directory.
  235.    for (nDirNum = 0; nDirNum < nMaxDirs; nDirNum++) {
  236.       // Let some other applications execute.
  237.       while (PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE)) {
  238.      TranslateMessage(&Msg);
  239.      DispatchMessage(&Msg);
  240.       }
  241.  
  242.       if (WasCancelled(hDlgStatus)) {
  243.      nResult = IDCANCEL;
  244.      break;
  245.       }
  246.  
  247.       wsprintf(szBuf, "%s%s", (LPSTR) _szDstDir, (LPSTR) ((*(_fstrrchr(_szDstDir, '\\') + 1) == 0) ? "" : "\\"));
  248.       SetupInfoSys(SIM_GETDIR, nDirNum, _fstrchr(szBuf, 0));
  249.       SetDlgItemText(hDlgStatus, ID_STATLINE2, szBuf);
  250.       MyDelay(300);
  251.       nResult = chdir(szBuf);
  252.       if (nResult != 0) {
  253.      nResult = mkdir(szBuf);
  254.      if (nResult != 0) {
  255.         MsgBox(hInstance, hDlgStatus, IDS_CANTMAKEDIR, _szAppName, MB_ICONINFORMATION | MB_OK, (LPSTR) szBuf);
  256.         nResult = IDCANCEL;
  257.         break;
  258.      } else chdir(szBuf);
  259.       }
  260.       nResult = IDOK;
  261.       SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, nDirNum + 2, 0);
  262.    }
  263.    MyDelay(400);
  264.    return nResult != IDCANCEL;
  265. }
  266.  
  267.  
  268. // ******************* Functions for Copying Files ***************************
  269.  
  270. typedef enum {
  271.    CFE_NOERROR,
  272.    CFE_NOMEMORY,
  273.    CFE_CANTOPENSRC,
  274.    CFE_CANTOPENDST,
  275. } COPYFILE_ERROR;
  276.  
  277. #pragma argsused
  278.  
  279. COPYFILE_ERROR NEAR PASCAL CopyFile (LPSTR szSrcPath, LPSTR szDstPath) {
  280.    const WORD wBufferSize = 65535u;
  281.    int nSrcFile, nDstFile;
  282.    WORD wBytesRead, wDate, wTime;
  283.    struct ftime ft;                     // Borland
  284.    OFSTRUCT ofSrc, ofDst;
  285.    LPSTR lpBuffer;
  286.    GLOBALHANDLE hMem;
  287.    char ffname[16];
  288.    char UserDir[80];
  289.    char fileName[100];
  290.    char whosINI = 0, OverWrite = 1;
  291.    char *testptr;
  292.    static char *PathName[] = {"LoadFilePath","SourceFilePath","EmulatorPath"};
  293.  
  294.    if((testptr = strstr(szSrcPath,".INI"))){
  295.     if((testptr = strstr(szSrcPath,"EMUL300")))    whosINI = 1;
  296.     if((testptr = strstr(szSrcPath,"BDM300")))    whosINI = 2;
  297.     if((testptr = strstr(szSrcPath,"EMUL16")))    whosINI = 3;
  298.     if((testptr = strstr(szSrcPath,"BDM16")))    whosINI = 4;
  299.     if((testptr = strstr(szSrcPath,"DEMO300")))    whosINI = 5;
  300.     if((testptr = strstr(szSrcPath,"DEMO16")))    whosINI = 6;
  301.     if((testptr = strstr(szSrcPath,"EMUL196")))    whosINI = 7;
  302.     if((testptr = strstr(szSrcPath,"EMUL51")))    whosINI = 8;
  303.     if((testptr = strstr(szSrcPath,"DEMO51")))    whosINI = 9;
  304.  
  305.     if((nDstFile = OpenFile(szDstPath, &ofDst, OF_READ)) == -1)
  306.         OverWrite = 1;
  307.     else {
  308.         OverWrite = 0;
  309.         _lclose(nDstFile);
  310.     }
  311.   } else
  312.     whosINI = 0;
  313.  
  314.    if(OverWrite){
  315.        nSrcFile = OpenFile(szSrcPath, &ofSrc, OF_READ);
  316.       if (nSrcFile == -1) return(CFE_CANTOPENSRC);
  317.  
  318.        hMem = GlobalAlloc(GMEM_MOVEABLE, wBufferSize);
  319.        if (hMem == NULL) {
  320.           _lclose(nSrcFile);
  321.           return(CFE_NOMEMORY);
  322.        }
  323.  
  324.        nDstFile = OpenFile(szDstPath, &ofDst, OF_CREATE | OF_WRITE);
  325.        if (nDstFile == -1) {
  326.          _lclose(nSrcFile);
  327.           GlobalFree(hMem);
  328.           return(CFE_CANTOPENDST);
  329.        }
  330.  
  331.        lpBuffer = GlobalLock(hMem);
  332.        do {
  333.           wBytesRead = _lread( nSrcFile, lpBuffer, wBufferSize);
  334.                _lwrite(nDstFile, lpBuffer, wBytesRead);
  335.        } while (wBytesRead == wBufferSize);
  336.        GlobalUnlock(hMem);
  337.  
  338.    // Make the destination file have the same time stamp as the source file.
  339.    // _dos_getftime(nSrcFile, &wDate, &wTime);
  340.    // _dos_setftime(nDstFile, wDate, wTime);
  341.        getftime(nSrcFile,&ft);                        // Borland
  342.        setftime(nDstFile,&ft);                        // Borland
  343.        _lclose(nDstFile);
  344.  
  345.        GlobalFree(hMem);
  346.        _lclose(nSrcFile);
  347.        if(whosINI){
  348.         if(whosINI == 1)    strcpy(ffname,"EMUL300.INI");
  349.         if(whosINI == 2)    strcpy(ffname,"BDM300.INI");
  350.         if(whosINI == 3)    strcpy(ffname,"EMUL16.INI");
  351.         if(whosINI == 4)    strcpy(ffname,"BDM16.INI");
  352.         if(whosINI == 5)    strcpy(ffname,"DEMO300.INI");
  353.         if(whosINI == 6)    strcpy(ffname,"DEMO16.INI");
  354.         if(whosINI == 7)    strcpy(ffname,"EMUL196.INI");
  355.         if(whosINI == 8)    strcpy(ffname,"EMUL51.INI");
  356.         if(whosINI == 9)    strcpy(ffname,"DEMO51.INI");
  357.  
  358.         strcpy(UserDir,_szDstDir);
  359.         strcpy(fileName,_szDstDir);
  360.         if(UserDir[strlen(UserDir)] != '\\'){
  361.             strcat(UserDir,"\\");
  362.             strcat(fileName,"\\");
  363.         }
  364.         strcat(fileName,ffname);
  365.         if(whosINI == 7)
  366.             strcat(UserDir,",.OMF");
  367.         else if(whosINI < 7 )
  368.             strcat(UserDir,",.OBJ");
  369.         else
  370.             strcat(UserDir,",.*");
  371.  
  372.         WritePrivateProfileString(PATHS,(LPSTR)PathName[0],UserDir,fileName);
  373.         if(UserDir[strlen(UserDir)] == '*')
  374.             UserDir[strlen(UserDir)-2] = '\0';
  375.         else
  376.             UserDir[strlen(UserDir)-3] = '\0';
  377.         strcat(UserDir,"C");
  378.         WritePrivateProfileString(PATHS,(LPSTR)PathName[1],UserDir,fileName);
  379.         if(UserDir[strlen(UserDir)] == '*')
  380.             UserDir[strlen(UserDir)-2] = '\0';
  381.         else
  382.             UserDir[strlen(UserDir)-3] = '\0';
  383.         if(whosINI == 8 || whosINI == 9)
  384.             strcat(UserDir,"STR.SYM\0");
  385.         WritePrivateProfileString(PATHS,(LPSTR)PathName[2],UserDir,fileName);
  386.        }
  387.   }
  388.    return(CFE_NOERROR);
  389. }
  390.  
  391.  
  392.  
  393.  
  394. BOOL NEAR PASCAL CopyAllFiles (HWND hDlgStatus)
  395. {
  396.    int nMaxFiles, nFileNum, nResult; COPYFILE_ERROR CFE;
  397.    char szSrcPath[MAXPATH], szDstPath[MAXPATH], szFileName[MAXFILENAME];
  398.    char szFileDesc[MAXFILEDESC], szDir[MAXDIRDESC], szDiskDesc[MAXDISKDESC];
  399.    char szTargetDir[MAXPATH];
  400.    MSG Msg; FARPROC fpProc;
  401.  
  402.    HANDLE hDlgRes;
  403.  
  404.    // Get the handle of the "InsertDisk" dialog box from the EXEcutable file.
  405.    hDlgRes = FindResource(hInstance, MAKEINTRESOURCE(DLG_INSERTDISK), RT_DIALOG);
  406.  
  407.    // Get the memory handle of the "InsertDisk" dialog box in memory.
  408.    // The block is already in memory because the dialog box is marked as
  409.    // PRELOAD FIXED.
  410.    hDlgRes = LoadResource(hInstance, hDlgRes);
  411.  
  412.    // Force the memory block to be locked down.  This prohibits Windows
  413.    // from discarding the dialog box template from memory.
  414.    LockResource(hDlgRes);
  415.  
  416.    SetDlgItemText(hDlgStatus, ID_STATLINE1, "Copying files...");
  417.    nMaxFiles = (int) SetupInfoSys(SIM_GETNUMFILES, 0, 0);
  418.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 0, 0);
  419.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSINJOB, nMaxFiles, 0);
  420.  
  421.    fpProc = MakeProcInstance(InsertDiskDlgProc, hInstance);
  422.    for (nFileNum = 0; nFileNum < nMaxFiles; nFileNum++) {
  423.       SetupInfoSys(SIM_GETFILEDESC, nFileNum, szFileDesc);
  424.       SetupInfoSys(SIM_GETFILENAME, nFileNum, szFileName);
  425.       SetupInfoSys(SIM_GETFILEDIR,  nFileNum, szDir);
  426.  
  427.     // if the target directory is "\WINDOWS" and the file extention
  428.     // is ".INI" then the actual WINDOWS home directory.
  429.       /*
  430.       if(stricmp(szDir,"\\WINDOWS") == 0 && (strstr(szFileName,".INI") || strstr(szFileName,".ini"))) {
  431.       char szWindowsDir[MAXDIR];
  432.       SetupInfoSys(SIM_GETWINDIR,0, szWindowsDir);
  433.       wsprintf(szDstPath, "%s\\%s",(LPSTR)szWindowsDir,(LPSTR)szFileName);
  434.       } else */
  435.     wsprintf(szDstPath, "%s%s%s\\%s", (LPSTR) _szDstDir, (LPSTR) ((*(_fstrrchr(_szDstDir, '\\') + 1) == 0) ? "" : "\\"), (LPSTR) szDir, (LPSTR) szFileName);
  436.     wsprintf(szTargetDir, "%s%s%s\\", (LPSTR) _szDstDir, (LPSTR) ((*(_fstrrchr(_szDstDir, '\\') + 1) == 0) ? "" : "\\"), (LPSTR) szDir);
  437.  
  438.       SetupInfoSys(SIM_GETFILEDISK, nFileNum, szDiskDesc);
  439.       SetDlgItemText(hDlgStatus, ID_STATLINE2, szFileDesc);
  440.  
  441.       do {
  442.      // Let other applications execute.
  443.      while (PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE)) {
  444.         TranslateMessage(&Msg);
  445.         DispatchMessage(&Msg);
  446.      }
  447.  
  448.      if (WasCancelled(hDlgStatus)) {
  449.         nResult = IDCANCEL;
  450.         break;
  451.      }
  452.  
  453.      wsprintf(szSrcPath, "%s%s%s\\%s", (LPSTR) _szSrcDir, (LPSTR) ((*(_fstrrchr(_szSrcDir, '\\') + 1) == 0) ? "" : "\\"), szDir[0] == '\\'? (LPSTR)(szDir+1):(LPSTR)szDir, (LPSTR) szFileName);
  454.  
  455.      nResult = IDOK;
  456.      if (!SetupInfoSys(SIM_ISFILECOMPRESSED, nFileNum, 0)) {
  457.        SetDlgItemText(hDlgStatus, ID_STATLINE1, "Copying files...");
  458.  
  459.         switch(CFE = CopyFile(szSrcPath, szDstPath)) {
  460.            case CFE_NOERROR: nResult = IDOK; break;
  461.            case CFE_NOMEMORY: nResult = MsgBox(hInstance, hDlgStatus, IDS_NOMEMORYCOPY, _szAppName, MB_ICONINFORMATION | MB_RETRYCANCEL); break;
  462.            case CFE_CANTOPENSRC:
  463.           nResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_INSERTDISK), hDlgStatus, fpProc, (LONG) (LPSTR)/* szSrcPath */ szDiskDesc);
  464.  
  465.           // Normally, Windows would have discarded the dialog box
  466.           // template from memory after the dialog box had been
  467.           // created.  By forcing the memory block to be locked by the
  468.           // call to LockResource() above, the template will NOT be
  469.           // discarded.  If the template were discarded, the next time
  470.           // this dialog box needed to be created Windows would have
  471.           // to load the template from the EXEcutable file.  However,
  472.           // the SETUP.EXE file is probably not on the diskette that
  473.           // is currently in the drive.  This would cause the program
  474.           // to behave erratically.
  475.           break;
  476.  
  477.            case CFE_CANTOPENDST: nResult = MsgBox(hInstance, hDlgStatus, IDS_CANTOPENDST, _szAppName, MB_ICONINFORMATION | MB_RETRYCANCEL); break;
  478.         }
  479.      } else {
  480.         // Use decompression function to copy the file.
  481.  
  482.  
  483.        SetDlgItemText(hDlgStatus, ID_STATLINE1, "Expanding file during copy...");
  484.         switch(CFE = Xpandmain(szSrcPath,(LPSTR) szTargetDir)){
  485.             case CFE_NOERROR: nResult = IDOK; break;
  486.             case CFE_CANTOPENSRC:
  487.               nResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_INSERTDISK), hDlgStatus, fpProc, (LONG) (LPSTR)/* szSrcPath */ szDiskDesc);
  488.               break;
  489.             case CFE_CANTOPENDST:
  490.                 nResult = MsgBox(hInstance, hDlgStatus,IDS_CANTOPENDST, _szAppName, MB_ICONINFORMATION | MB_RETRYCANCEL);
  491.                 break;
  492.         }
  493.      }
  494.  
  495.      // Make sure that the user really wants to cancel Setup.
  496.      if (nResult == IDCANCEL) {
  497.         nResult = MsgBox(hInstance, hDlgStatus, IDS_QUERYABORT, _szAppName, MB_ICONQUESTION | MB_YESNO);
  498.         if (nResult == IDYES) {
  499.            nResult = IDCANCEL;
  500.            break;
  501.         }
  502.      }
  503.  
  504.       } while (nResult != IDCANCEL && CFE != CFE_NOERROR);
  505.  
  506.       if (nResult == IDCANCEL) break;
  507.  
  508.       SendDlgItemMessage(hDlgStatus,ID_METER,MM_SETPARTSCOMPLETE,nFileNum+1,0);
  509.    }
  510.  
  511.    // The dialog box template is no longer necessary to keep around so
  512.    // it may be unlocked and removed from memory.
  513.    UnlockResource(hDlgRes);
  514.    FreeResource(hDlgRes);
  515.  
  516.    FreeProcInstance(fpProc);
  517.    return nResult != IDCANCEL;
  518. }
  519.  
  520. // *********************** Miscellaneous Function ****************************
  521. int FAR cdecl MsgBox (HANDLE hInstance, HWND hWnd, WORD wID, LPSTR szCaption, WORD wType, ...)
  522. {
  523.    char szResString[200], szText[200];
  524.    void FAR *VarArgList = (WORD FAR *) &wType + 1;
  525.    LoadString(hInstance, wID, szResString, sizeof(szResString) - 1);
  526.    wvsprintf(szText, szResString, VarArgList);
  527.    return MessageBox(hWnd, szText, szCaption, wType);
  528. }
  529.