home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / INSTVER / INSTVER.C_ / INSTVER.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  15.0 KB  |  531 lines

  1. /**************************************************************************
  2.  *
  3.  * InstVer.c - SDK version-checking installer for the 3.0 compatible windows
  4.  *           DLLs
  5.  *
  6.  **************************************************************************/
  7.  
  8. #include <dos.h>    /* for file i/o */
  9. #include <fcntl.h>    /* for file i/o */
  10. #include <share.h>    /* for file i/o */
  11. #include <io.h>     /* for file i/o */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #ifdef DLL
  18.     #undef NULL
  19.     #include <windows.h>
  20. #endif
  21.  
  22. #include "Instpriv.h"
  23. #include "Instver.h"
  24.  
  25. #ifndef DLL
  26. #define LIB
  27. #endif
  28. #include  <ver.h>
  29.  
  30.  
  31. /* forward declaration of functions used in this module */
  32. BOOL PASCAL InstallFiles (LPSTR lpszSrcDir,
  33.               LPSTR lpszWinDir);
  34.  
  35. BOOL PASCAL DoVerInstall (LPSTR pszSrcPath,
  36.               LPSTR pszSrcFile,
  37.               LPSTR pszDstPath);
  38.  
  39. BOOL PASCAL GetFilesFromDat (LPSTR lpszDat);
  40.  
  41. void PASCAL CleanUp (void);
  42.  
  43. /* header of list of files to be copied */
  44. char *pDatLibFiles = NULL;
  45. BOOL bDatFile;
  46.  
  47.  
  48. #ifdef DLL
  49.  
  50. /* ========================= START: Windows DLL code ====================== */
  51.  
  52. /**************************************************************************
  53.  *
  54.  * int FAR PASCAL LibMain (hInstance, wDataSeg, wcbHeapSize, lpstrCmdLine)
  55.  *
  56.  * Routine invoked by the dll entry code (LibEntry)
  57.  *
  58.  * ENTRY   : HANDLE hInst    - DLL instance handle
  59.  *         WORD   wDS      - DLL data segment
  60.  *         WORD   wcbHS    - number of bytes in DLL's heap
  61.  *         LPSTR  lpstrCmd - Command line string
  62.  *
  63.  * EXIT    : TRUE - success
  64.  * WARNING : None
  65.  *
  66.  **************************************************************************/
  67. int FAR PASCAL LibMain(HANDLE hInst, WORD wDS, WORD wcbHS ,LPSTR lpstrCmd)
  68. {
  69.      /* Make the DLL data seg. moveable */
  70.      if (wcbHS > 0)
  71.      UnlockData (0);
  72.  
  73.      /* success */
  74.      return 1;
  75. }
  76.  
  77. /**************************************************************************
  78.  *
  79.  * int FAR PASCAL WEP (int nParam)
  80.  *
  81.  * Handles clean-up when DLL is removed from the system. Since there is
  82.  * nothing to clean up, this function just returns success.
  83.  *
  84.  * ENTRY   : nExitType - Exit type code (system shutdown, DLL being
  85.  *             freed...etc)
  86.  * EXIT    : TRUE - success
  87.  * WARNING : None
  88.  *
  89.  **************************************************************************/
  90. int FAR PASCAL WEP (int nExitType)
  91. {
  92.     return TRUE;
  93. }
  94. /**************************************************************************
  95.  *
  96.  * BOOL InstallVersionFiles (LPSTR szSrcPath, LPSTR szWindowsPath)
  97.  *
  98.  * Top level (public) version-checking installer routine. Copies the DLLs
  99.  * from the specified source pathname to the Windows system directory. If a
  100.  * DAT file is specified, the files listed in it are copied over,
  101.  * otherwise, the default list of files are copied.
  102.  *
  103.  * ENTRY   : LPSTR lpszSrcPath       - path where the source files are located
  104.  *         LPSTR lpszWindowsPath - Windows directory or NULL
  105.  *         LPSTR lpszWindowsPath - .DAT filename or NULL
  106.  *
  107.  * EXIT    : TRUE   - success
  108.  *         ERR_??code - otherwise ( The complete list is in instver.h )
  109.  *
  110.  * WARNING : If lpszWindowsPath is NULL, the function determines the path
  111.  *         of the Windows installation.
  112.  *
  113.  **************************************************************************/
  114.  
  115. BOOL FAR PASCAL InstallVersionFiles (LPSTR lpszSrcPath,
  116.                      LPSTR lpszWindowsPath,
  117.                      LPSTR lpszDatFile)
  118. {
  119.     int wRet;
  120.     static char szWindowsPath [_MAX_PATH];
  121.  
  122.     /* make sure input pathname and .DAT filenames are real */
  123.     if ( !DosValidDir(lpszSrcPath))
  124.     return ERR_BADSRCDIR;
  125.  
  126.     /* If a .DAT file is specified, set a flag, otherwise, make sure it
  127.      * exists at the specified path
  128.      */
  129.     if (lpszDatFile){
  130.     if (FileExists (lpszDatFile) < 0)
  131.         return ERR_BADDATFILE;
  132.     bDatFile = TRUE;
  133.     }
  134.     else
  135.     bDatFile = FALSE;
  136.  
  137.     /* If user hasn't supplied a Windows pathname, get the pathname of the
  138.      * current Windows installation, otherwise verify the supplied
  139.      * pathname.
  140.      */
  141.     if (!lpszWindowsPath){
  142.     if (!GetWindowsDirectory ((LPSTR)szWindowsPath, _MAX_PATH))
  143.         return ERR_BADWINDIR;
  144.     lpszWindowsPath = szWindowsPath;
  145.     }
  146.     else{
  147.     if ( !DosValidDir (lpszWindowsPath))
  148.         return ERR_BADWINDIR;
  149.     }
  150.  
  151.     /* Parse names in the DAT file into temporary buffer  */
  152.     if (bDatFile){
  153.     if ((wRet = GetFilesFromDat (lpszDatFile)) < 0)
  154.         return wRet;
  155.     }
  156.  
  157.     /* Copy each of the files over, after version checking */
  158.     wRet = InstallFiles (lpszSrcPath, lpszWindowsPath);
  159.  
  160.     return (wRet < 0 ? wRet : TRUE);
  161. }
  162. /* ========================= END: Windows DLL code ======================== */
  163.  
  164. #else
  165.  
  166.  
  167.  
  168.  
  169. /* ========================= START: DOS .EXE code ========================= */
  170.  
  171. int PASCAL GrabArguments (char * argv[], LPSTR szSrcPath,
  172.                      LPSTR szWinPath, LPSTR szDatPath);
  173.  
  174. /**************************************************************************
  175.  *
  176.  * Entry point for the DOS .EXE version of the installer. The input arguments
  177.  * are the source files pathname, the Windows pathname, and an optional .DAT
  178.  * file containing names of the files to be installed.
  179.  *
  180.  * WARNING : Target Windows directory has to exist.
  181.  *
  182.  **************************************************************************/
  183. main (int argc, char *argv[])
  184. {
  185.     int wRet;
  186.     static char szSrcPath     [_MAX_PATH];
  187.     static char szDatPath     [_MAX_PATH];
  188.     static char szWindowsPath [_MAX_PATH];
  189.  
  190.     /* Verify that there are at least 2 arguments and parse the argument
  191.      * list to obtain source dir. and windows, and the .DAT (optional) pathnames
  192.      */
  193.     if ((argc < 3) || (!GrabArguments (argv, szSrcPath,
  194.                          szWindowsPath, szDatPath)))
  195.     return ERR_BADARGS;
  196.  
  197.     /* Validate the input pathnames */
  198.  
  199.     if ( !DosValidDir ((LPSTR)szSrcPath))
  200.     return ERR_BADSRCDIR;
  201.     if ( !DosValidDir ((LPSTR)szWindowsPath))
  202.     return ERR_BADWINDIR;
  203.     if (bDatFile)
  204.        if (FileExists (szDatPath) < 0)
  205.        return ERR_BADDATFILE;
  206.  
  207.     /* Parse names in the DAT file into temporary buffer  */
  208.     if (bDatFile){
  209.     if ((wRet = GetFilesFromDat (szDatPath)) < 0)
  210.         return wRet;
  211.     }
  212.  
  213.     /* Copy each of the files over, after version checking */
  214.     wRet = InstallFiles (szSrcPath, szWindowsPath);
  215.  
  216.     return (wRet < 0 ? wRet : TRUE);
  217. }
  218.  
  219. /**************************************************************************
  220.  *
  221.  * GrabArguments (char * argv[], LPSTR szSrcPath, LPSTR szWinPath, LPSTR lpszDat)
  222.  *
  223.  * Gets the pathnames from the program's argument list and copies them into
  224.  * buffers.
  225.  *
  226.  * ENTRY   : char * argv[]  - argument list
  227.  *
  228.  * EXIT    : LPSTR lpszSrcPath       - path where the source files are located
  229.  *         LPSTR lpszWindowsPath - Windows directory pathname
  230.  *         LPSTR lpszDatPath       - Optional .DAT file name
  231.  *
  232.  *       Returns TRUE if successful, FALSE otherwise
  233.  *       A flag is set if a .DAT file is specified.
  234.  *
  235.  * WARNING : First two args. are required. The .DAT file is optional
  236.  *
  237.  **************************************************************************/
  238. int PASCAL GrabArguments (char * argv[], LPSTR szSrcPath,
  239.                      LPSTR szWinPath, LPSTR szDatPath)
  240. {
  241.     register char * psz;
  242.  
  243.     if (psz = argv [1])
  244.     _fstrncpy (szSrcPath, (LPSTR)psz, _MAX_PATH - 1);
  245.     else
  246.     return FALSE;
  247.  
  248.     if (psz = argv [2])
  249.     _fstrncpy (szWinPath, (LPSTR)psz, _MAX_PATH - 1);
  250.     else
  251.     return FALSE;
  252.  
  253.     if (psz = argv [3]){
  254.     _fstrncpy (szDatPath, (LPSTR)psz, _MAX_PATH - 1);
  255.     bDatFile = TRUE;
  256.     }
  257.     else{
  258.     *szDatPath = '\0';
  259.     bDatFile = FALSE;
  260.     }
  261.     return TRUE;
  262. }
  263. #endif
  264. /* ========================= END: DOS .EXE code =========================== */
  265.  
  266.  
  267.  
  268.  
  269.  
  270. /* ========================= START: common code =========================== */
  271.  
  272. /**************************************************************************
  273.  *
  274.  * BOOL PASCAL InstallFiles (LPSTR szSrcDir, LPSTR lpszWinDir)
  275.  *
  276.  * Core installation routine. Copies files from either the default internal
  277.  * list, or the .DAT file buffer to the destination Windows system directory.
  278.  * Both the above are in the format:
  279.  *
  280.  *  file1\0file2\0file3\0....fileN\0\0
  281.  *
  282.  * ENTRY   : LPSTR lpszSrcDir - Source files directory
  283.  *         LPSTR lpszWinDir - Target Windows directory.
  284.  *
  285.  * EXIT    : TRUE   - success
  286.  *         ERR_??code - otherwise ( The complete list is in instver.h )
  287.  * WARNING : None
  288.  *
  289.  **************************************************************************/
  290.  
  291. BOOL PASCAL InstallFiles (LPSTR lpszSrcDir, LPSTR lpszWinDir)
  292. {
  293.     int wRet = 0;
  294.     static char *szFilePtr;
  295.  
  296.     /* point to appropriate filenames buffer */
  297.     if (bDatFile)
  298.        szFilePtr = pDatLibFiles;
  299.     else
  300.        szFilePtr = szDefLibFiles;   /* default */
  301.  
  302.     for (; *szFilePtr && (wRet >= 0); szFilePtr += _fstrlen(szFilePtr) + 1){
  303.  
  304.     if ((wRet = DoVerInstall (lpszSrcDir, szFilePtr, lpszWinDir)) < 0){
  305.         CleanUp ();
  306.         return wRet;
  307.     }
  308.     }
  309.  
  310.     /* free DAT file buffer, if it exists */
  311.     CleanUp ();
  312.  
  313.     return (wRet < 0 ? wRet : TRUE);
  314. }
  315.  
  316. /**************************************************************************
  317.  *
  318.  * BOOL PASCAL GetFilesFromDat (LPSTR lpszDat)
  319.  *
  320.  * Reads the .DAT file which contains a list of files to be copied and
  321.  * parses it into a buffer in the form:
  322.  *
  323.  *  file1\0file2\0file3\0....fileN\0\0
  324.  *
  325.  * ENTRY   :   LPSTR lpszDat  - Dat file pathname.
  326.  *
  327.  * EXIT    : TRUE   - success
  328.  *         ERR_??code - otherwise ( The complete list is in instver.h )
  329.  *
  330.  *         pDatLibFiles points to parsed filename buffer.
  331.  *
  332.  * WARNING : .DAT file has to consist of only filenames (no full pathnames)
  333.  *         with one filename per line. No comments are allowed. Leading
  334.  *         and trailing whitespace may be present.
  335.  *
  336.  *         The DAT file has to contain the filenames as they will appear in
  337.  *         the destination directory. i.e even if a file exists in source
  338.  *         directory as FOO.EX_,(a Windows compressed renamed file),the DAT
  339.  *         file should list it as FOO.EXT. The copying function will take
  340.  *         care of renaming FOO.EX_ appropriately after it is expanded.
  341.  *
  342.  **************************************************************************/
  343. BOOL PASCAL GetFilesFromDat (LPSTR lpszDat)
  344.  
  345. {
  346.     static char szDat [_MAX_PATH];
  347.     char * pSrcBuf;
  348.     char * pTmpSrc, *pTmpDst;
  349.     char * pBufEnd;
  350.     int wLen;
  351.     int fh;
  352.     int c;
  353.  
  354.     /* copy pathname to a NEAR buffer for FOPEN () */
  355.     _fstrcpy (szDat, lpszDat);
  356.  
  357.     fh = FOPEN (szDat);
  358.     if (fh == -1)
  359.     return ERR_CANTOPENDATFILE;
  360.  
  361.     /* Get the length of the file */
  362.     wLen = (WORD)FSEEK(fh,0L,SEEK_END);
  363.     FSEEK (fh, 0L, SEEK_SET);
  364.  
  365.     /* allocate for (temporary)source and (destination).DAT file buffers */
  366.     pSrcBuf = pTmpSrc = ALLOC (wLen);
  367.     if (!pSrcBuf)
  368.     return ERR_NOMEM;
  369.  
  370.     pDatLibFiles = pTmpDst = ALLOC (wLen);
  371.     if (!pDatLibFiles){
  372.     FREE (pSrcBuf);
  373.     return ERR_NOMEM;
  374.     }
  375.     pBufEnd = pSrcBuf + wLen;
  376.  
  377.     /* Read in entire file into temporary source buffer to avoid
  378.      * repeated file i/o operations.
  379.      */
  380.     if ((int)FREAD (fh, pSrcBuf, wLen) != wLen)
  381.     return ERR_READINGDATFILE;
  382.     FCLOSE (fh);
  383.  
  384.     /* Now parse source buffer into destination buffer into format:
  385.      *       file1\0file2\0file3\0....fileN\0\0
  386.      */
  387.     while (pTmpSrc < pBufEnd){
  388.     switch (c = *pTmpSrc++){
  389.         case ' ' :
  390.         case '\r':
  391.         case '\t':
  392.          break;      /* ignore whitespace */
  393.  
  394.         case '\n':
  395.         case EOF :
  396.          *pTmpDst++ = '\0';
  397.          break;      /* terminate current filename */
  398.  
  399.         default:
  400.          *pTmpDst++ = (char)c;
  401.     }
  402.     }
  403.  
  404.     /* add the additional final NULL to signal end of list */
  405.     *pTmpDst = '\0';
  406.  
  407.     /* discard temporary source buffer */
  408.     FREE (pSrcBuf);
  409. }
  410.  
  411.  
  412. /**************************************************************************
  413.  *
  414.  * BOOL PASCAL DoVerInstall (LPSTR lpszSrcPath, LPSTR lpszDstFile
  415.  *                 LPSTR lpszDstPath)
  416.  *
  417.  * Uses the VER library to determine the appropriate directory to copy the
  418.  * file to, and copies the file over. If the file sxists in the source
  419.  * directory is lz-compressed and in LZ-renamed format, the destination file
  420.  * is expanded and renamed correctly.
  421.  *
  422.  * ENTRY   : LPSTR lpszSrcPath - Source directory name.
  423.  *         LPSTR lpszDstFile - Destination filename.
  424.  *         LPSTR lpszDstPath - Target pathname.
  425.  *
  426.  * EXIT    : TRUE  - OK to copy over library file
  427.  *         FALSE - version mismatch. Don't copy file
  428.  *         Otherwise a ERR_ code to indicate an installation error has occured
  429.  *
  430.  **************************************************************************/
  431. BOOL PASCAL DoVerInstall (LPSTR lpszSrcPath,
  432.               LPSTR lpszDstFile,
  433.               LPSTR lpszDstPath)
  434. {
  435.     static char szCurDir [_MAX_PATH];
  436.     static char szDstDir [_MAX_PATH];
  437.     static char szTmpFile[_MAX_PATH];
  438.     WORD wRet;
  439.     int wCopy = TRUE;
  440.     DWORD dwRet;
  441.     WORD wCurDirLen = sizeof(szCurDir);
  442.     WORD wDstDirLen = sizeof(szDstDir);
  443.     WORD wTmpFileLen = sizeof(szTmpFile);
  444.  
  445.     wRet = VerFindFile (VFFF_ISSHAREDFILE,
  446.             lpszDstFile,
  447.             lpszDstPath,
  448.             lpszDstPath,
  449.             szCurDir,
  450.             &wCurDirLen,
  451.             szDstDir,
  452.             &wDstDirLen);
  453.  
  454.     /*
  455.      * The LZ-routine called by VerInstallFile looks for a renamed file
  456.      * (i.e with the "_" in it's extension if the actual file is not
  457.      * found in the source directory).
  458.      */
  459.     dwRet = VerInstallFile ( 0,
  460.                  lpszDstFile,
  461.                  lpszDstFile,
  462.                  lpszSrcPath,
  463.                  szDstDir,
  464.                  szCurDir,
  465.                  szTmpFile,
  466.                  &wTmpFileLen);
  467.  
  468.     /* Compare return value against all defined bit values and take
  469.      * appropriate action on each.
  470.      */
  471.     if (dwRet & (VIF_MISMATCH|VIF_SRCOLD|VIF_DIFFLANG|VIF_DIFFCODEPG|\
  472.               VIF_DIFFTYPE | VIF_CANNOTREADDST)){
  473.  
  474.  
  475.      wCopy = FALSE;          /* a mismatch , don't copy */
  476.     }
  477.     /* The remaining flags (if any) represent errors. Depending on broad
  478.      * classification of these, return a suitable INSTVER error code
  479.      */
  480.     else if (dwRet & (VIF_WRITEPROT | VIF_FILEINUSE | VIF_ACCESSVIOLATION|
  481.               VIF_SHARINGVIOLATION | VIF_CANNOTDELETE |\
  482.               VIF_CANNOTREADSRC))
  483.  
  484.      wCopy = ERR_CANNOTREADSRC;
  485.  
  486.     else if (dwRet & VIF_OUTOFSPACE)
  487.  
  488.      wCopy =  ERR_OUTOFSPACE;
  489.  
  490.     else if (dwRet & VIF_OUTOFMEMORY)
  491.  
  492.      wCopy =  ERR_NOMEM;
  493.  
  494.     else if (dwRet & (VIF_CANNOTCREATE | VIF_CANNOTRENAME | VIF_TEMPFILE))
  495.  
  496.      wCopy =  ERR_CREATINGFILE;
  497.  
  498.     if (wCopy <= 0) {
  499.  
  500.     /* delete the temp. file if one has been left behind */
  501.     if (dwRet & VIF_TEMPFILE) {
  502.          if (!SLASH(szDstDir[_fstrlen (szDstDir) - 1]))
  503.          _fstrcat (szDstDir, "\\");
  504.          _fstrcat (szDstDir, szTmpFile);
  505.          DosDelete ((LPSTR)szDstDir);
  506.     }
  507.     }
  508.  
  509.     return wCopy;
  510. }
  511. /**************************************************************************
  512.  *
  513.  * void PASCAL CleanUp (void)
  514.  *
  515.  * Frees allocated buffers
  516.  *
  517.  * ENTRY   : none
  518.  * EXIT    : none
  519.  * WARNING : none
  520.  *
  521.  **************************************************************************/
  522. void PASCAL CleanUp (void)
  523. {
  524.     if (pDatLibFiles){
  525.  
  526.     /* free the DAT file buffer */
  527.     FREE (pDatLibFiles);
  528.     pDatLibFiles = NULL;
  529.     }
  530. }
  531.