home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / libreg / src / VerReg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  28.5 KB  |  1,148 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* ====================================================================
  19.  * VerReg.c
  20.  * XP Version Registry functions (prototype)
  21.  * ====================================================================
  22.  */
  23.  
  24. /* --------------------------------------------------------------------
  25.  * Install 'Navigator' produces a tree of:
  26.  *
  27.  *        /Components/Netscape/Web/Navigator/
  28.  *                ...Path="c:\netscape\program\netscape.exe"
  29.  *                ...Version=4.0.0.0
  30.  *
  31.  * --------------------------------------------------------------------
  32.  */
  33. #include <fcntl.h>
  34. #include <errno.h>
  35.  
  36. #if defined(XP_WIN)
  37. #include <io.h>
  38. #endif
  39.  
  40. #ifndef STANDALONE_REGISTRY
  41. #include "xp_mcom.h"
  42. #include "xp_core.h"
  43. #ifndef NSPR20
  44. #include "prosdep.h"
  45. #else
  46. #ifdef XP_MAC
  47. #include <Folders.h>
  48. #include "prosdep.h"
  49. #else
  50. #include "md/prosdep.h"
  51. #endif
  52. #endif
  53. #include "prmon.h"
  54. #ifdef BROKEN
  55. #include "su_folderspec.h"
  56. #endif
  57. #else
  58. #ifdef XP_MAC
  59.   #include <types.h>
  60.   #include <stat.h>
  61. #else
  62.   #include <sys/types.h>
  63.   #include <sys/stat.h>
  64. #endif
  65. #include <stdio.h>
  66. #include <stdlib.h>
  67. #include <string.h>
  68. #include <assert.h>
  69. #endif
  70.  
  71. #include "reg.h"
  72. #include "NSReg.h"
  73. #include "VerReg.h"
  74.  
  75. /* -------- local defines ---------------
  76. */
  77. #define MAXREGVERLEN 32    /* Version=12345.12345.12345.12345 */
  78.  
  79. #define VERSTR    "Version"
  80. #define CHKSTR    "Check"
  81. #define PATHSTR    "Path"
  82. #define DIRSTR  "Directory"
  83. #define NAVHOME "Navigator Home"
  84.  
  85. #define VERSION_NAME            "Communicator"
  86. #define NAVIGATOR_NODE          "/Netscape"
  87. #define CURRENT_VER             "Current Navigator"
  88.  
  89. #define PATH_ROOT(p)   ( ((p) && *(p)==PATHDEL) ? ROOTKEY_VERSIONS : curver )
  90. #define UNIX_ROOT(p)   ( ((p) && *(p)==PATHDEL) ? ROOTKEY_VERSIONS : unixver )
  91.  
  92.  
  93. /* ---------------------------------------------------------------------
  94.  * Global variables
  95.  * ---------------------------------------------------------------------
  96.  */
  97. static int isInited = 0;
  98. static RKEY curver = 0;
  99.  
  100. static HREG vreg = 0;
  101.  
  102. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  103. /* Extra Unix variables to deal with two registries
  104.  *   "vreg" is always the writable registry.
  105.  *   If "vreg" is the local registry then "unixreg" will
  106.  *   be the global registry read-only (unless we couldn't
  107.  *   open it).
  108.  */
  109. static HREG unixreg = 0;
  110. static RKEY unixver = 0;
  111. XP_Bool bGlobalRegistry = FALSE;
  112. #endif
  113.  
  114. #ifndef STANDALONE_REGISTRY
  115. PRMonitor *vr_monitor = NULL;
  116. #endif
  117.  
  118.  
  119. /* ---------------------------------------------------------------------
  120.  * local functions
  121.  * ---------------------------------------------------------------------
  122.  */
  123. static REGERR vr_Init(void);
  124. static REGERR vr_BuildVersion(VERSION *pVer, char *buf);
  125. static Bool   vr_CompareDirs( char *dir1, char *dir2 );
  126. static REGERR vr_SetCurrentNav( char *product, char *programPath, char *versionStr);
  127. static REGERR vr_ParseVersion(char *verstr, VERSION *result);
  128.  
  129. #ifdef USE_CHECKSUM
  130. static REGERR vr_GetCheck(char *path, int32 *check);
  131. #endif
  132.  
  133. static REGERR vr_SetPathname(HREG reg, RKEY key, char *entry, char *dir);
  134. static REGERR vr_GetPathname(HREG reg, RKEY key, char *entry, char *buf, uint32 sizebuf);
  135.  
  136. static REGERR vr_FindKey(char *name, HREG *hreg, RKEY *key);
  137.  
  138. #ifdef XP_MAC
  139. static void vr_MacAliasFromPath(const char * fileName, void ** alias, int32 * length);
  140. static char * vr_PathFromMacAlias(const void * alias, uint32 aliasLength);
  141. #endif
  142.  
  143. /* --------------------------------------------------------------------- */
  144.  
  145. static REGERR vr_Init(void)
  146. {
  147.  
  148.     REGERR  err = REGERR_OK;
  149.     char    *regname = "";
  150.     char    curstr[MAXREGNAMELEN];
  151.     RKEY    navKey;
  152. #ifndef STANDALONE_REGISTRY
  153.     char    *curPath = NULL;
  154. #ifdef XP_UNIX
  155.     char    *regbuf = NULL;
  156. #endif
  157.  
  158.     PR_EnterMonitor(vr_monitor);
  159. #endif
  160.  
  161.     if (!isInited)
  162.     {
  163. #ifndef STANDALONE_REGISTRY
  164. #ifdef BROKEN
  165.         curPath = FE_GetDirectoryPath(eCommunicatorFolder);
  166. #else
  167.         /* can't use Version Registry interface until "BROKEN" works */
  168.         err = REGERR_FAIL;
  169.         goto done;
  170. #endif
  171. #ifdef XP_UNIX
  172.         if (curPath != NULL) {
  173.             regbuf = (char*)XP_ALLOC( 10 + XP_STRLEN(curPath) );
  174.             if (regbuf != NULL ) {
  175.                 XP_STRCPY( regbuf, curPath );
  176.                 XP_STRCAT( regbuf, "registry" );
  177.             }
  178.         }
  179.  
  180.         if ( curPath == NULL || regbuf == NULL ) {
  181.             err = REGERR_MEMORY;
  182.             goto done;
  183.         }
  184.  
  185.         if (bGlobalRegistry)
  186.             regname = regbuf;
  187. #endif
  188. #endif
  189.  
  190.         /* Open version registry */
  191.         err = NR_RegOpen( regname, &vreg );
  192.  
  193. #ifndef STANDALONE_REGISTRY
  194.         if (err == REGERR_NOFILE) {
  195.             /* create it if not found */
  196.             err = VR_CreateRegistry( VERSION_NAME, curPath, "" );
  197.         }
  198.         else if (err == REGERR_OK) {
  199.             /* otherwise find/set the current nav node */
  200.             err = vr_SetCurrentNav( VERSION_NAME, curPath, NULL );
  201.         }
  202.  
  203. #ifdef XP_UNIX
  204.         /* try to open shared Unix registry, but not an error if you can't */
  205.         unixreg = NULL;
  206.         if (!bGlobalRegistry && err == REGERR_OK ) {
  207.             unixver = 0;
  208.             if (NR_RegOpen( regbuf, &unixreg ) == REGERR_OK) {
  209.                 if (NR_RegGetKey( unixreg, ROOTKEY_VERSIONS, NAVIGATOR_NODE,
  210.                     &navKey) == REGERR_OK)
  211.                 {
  212.                     if (NR_RegGetEntryString( unixreg, navKey, CURRENT_VER,
  213.                         curstr, sizeof(curstr)) == REGERR_OK )
  214.                     {
  215.                         NR_RegGetKey( unixreg, navKey, curstr, &unixver );
  216.                     }
  217.                 }
  218.             }
  219.         }
  220. #endif
  221.  
  222.         if (err == REGERR_OK) {
  223.             /* successfully opened! */
  224.             isInited = 1;
  225.         }
  226.         goto done;
  227. #else
  228.         if (err != REGERR_OK)
  229.             goto done;
  230.  
  231.         /* Determine 'curver' key and ensure correct structure by adding */
  232.  
  233.         /* ...find top-level "Navigator" node (add if missing) */
  234.         err = NR_RegAddKey( vreg, ROOTKEY_VERSIONS, NAVIGATOR_NODE, &navKey );
  235.         if (err != REGERR_OK)
  236.             goto done;
  237.  
  238.         /* ...look for "Current Version" entry */
  239.         err = NR_RegGetEntryString( vreg, navKey, CURRENT_VER, curstr,
  240.                                     sizeof(curstr) );
  241.         if ( err == REGERR_NOFIND ) {
  242.             /* If not found create one with the built-in version */
  243.             err = NR_RegSetEntryString( vreg, navKey, CURRENT_VER, VERSION_NAME );
  244.             XP_STRCPY( curstr, VERSION_NAME );
  245.         }
  246.         if ( err != REGERR_OK )
  247.             goto done;
  248.  
  249.         /* ...look for "curstr" child key of the navigator node */
  250.         err = NR_RegAddKey( vreg, navKey, curstr, &curver );
  251.  
  252.         if (err == REGERR_OK) {
  253.             /* successfully opened! */
  254.             isInited = 1;
  255.         }
  256. #endif
  257.     }
  258.  
  259. done:
  260. #ifndef STANDALONE_REGISTRY
  261.     PR_ExitMonitor(vr_monitor);
  262.     XP_FREEIF(curPath);
  263. #ifdef XP_UNIX
  264.     XP_FREEIF(regbuf);
  265. #endif
  266. #endif
  267.     return err;
  268.  
  269. }    /* Init */
  270.  
  271.  
  272.  
  273. #ifdef XP_PC
  274. #define VR_FILE_SEP '\\'
  275. #endif
  276. #ifdef XP_MAC
  277. #define VR_FILE_SEP ':'
  278. #endif
  279. #ifdef XP_UNIX
  280. #define VR_FILE_SEP '/'
  281. #endif
  282. static Bool vr_CompareDirs( char *dir1, char *dir2 )
  283. {
  284.     int len1,len2;
  285.     len1 = XP_STRLEN( dir1 );
  286.     len2 = XP_STRLEN( dir2 );
  287.  
  288.     if ( dir1[len1-1] == VR_FILE_SEP )
  289.         len1--;
  290.     if ( dir2[len2-1] == VR_FILE_SEP )
  291.         len2--;
  292.  
  293.     if ( len1 != len2 )
  294.         return FALSE;
  295.  
  296. #ifdef XP_UNIX
  297.     return ( XP_STRNCMP(dir1, dir2, len1) == 0 );
  298. #else
  299.     return ( XP_STRNCASECMP(dir1, dir2, len1) == 0 );
  300. #endif
  301. }
  302.  
  303.  
  304. REGERR vr_ParseVersion(char *verstr, VERSION *result)
  305. {
  306.  
  307.     result->major = result->minor = result->release = result->build = 0;
  308.     result->major = atoi(verstr);
  309.     while (*verstr && *verstr != '.')
  310.         verstr++;
  311.     if (*verstr)
  312.     {
  313.         verstr++;
  314.         result->minor = atoi(verstr);
  315.         while (*verstr && *verstr != '.')
  316.             verstr++;
  317.         if (*verstr)
  318.         {
  319.             verstr++;
  320.             result->release = atoi(verstr);
  321.             while (*verstr && *verstr != '.')
  322.                 verstr++;
  323.             if (*verstr)
  324.             {
  325.                 verstr++;
  326.                 result->build = atoi(verstr);
  327.                 while (*verstr && *verstr != '.')
  328.                     verstr++;
  329.             }
  330.         }
  331.     }
  332.  
  333.     return REGERR_OK;
  334.  
  335. }    /* ParseVersion */
  336.  
  337.  
  338.  
  339. #ifdef USE_CHECKSUM
  340. #define BLKSIZ 16384
  341.  
  342. static REGERR vr_GetCheck(char *path, int32 *check)
  343. {
  344.  
  345.     int fh;
  346.     char *buf;
  347.     int actual;
  348.     char *p;
  349.     int i;
  350.     int chk;
  351.  
  352.     XP_ASSERT(path);
  353.     XP_ASSERT(check);
  354.     
  355.     *check = chk = 0;
  356.  
  357. #ifdef NEED_XP_FIXES
  358.     /* open file for read */
  359.     fh = open(path, O_RDONLY| O_BINARY);
  360.     if (fh < 0)
  361.     {
  362.         switch (errno)
  363.         { 
  364.         case ENOENT:    /* file not found */
  365.             return REGERR_NOFILE;
  366.  
  367.         case EACCES:    /* file in use */
  368.         case EMFILE:    /* too many files open */
  369.         default:
  370.             return REGERR_FAIL;
  371.         }
  372.     }
  373.  
  374.     buf = malloc(BLKSIZ);
  375.     if (!buf)
  376.     {
  377.         close(fh);
  378.         return REGERR_MEMORY;
  379.     }
  380.  
  381.     do
  382.     {
  383.         /* read a block */
  384.         actual = read(fh, buf, BLKSIZ);
  385.         /* add to checksum */
  386.         for (p=buf, i=0; i<actual; i++, p++)
  387.             chk += *p;
  388.  
  389.         /* if the block was partial, we're done, else loop */
  390.     } while (actual == BLKSIZ);
  391.  
  392.     /* close file */
  393.     close(fh);
  394.     free(buf);
  395. #endif
  396.  
  397.     /* return calculated checksum */
  398.     *check = chk;
  399.  
  400.     return REGERR_OK;
  401.  
  402. }    /* GetCheck */
  403.  
  404. #endif /* USE_CHECKSUM */
  405.  
  406.  
  407.  
  408. static REGERR vr_SetPathname(HREG reg, RKEY key, char *entry, char *dir)
  409. {
  410.     /* save in platform/OS charset, so use BYTES. */
  411.     REGERR err;
  412.     void * alias = dir;
  413.     int32  datalen = XP_STRLEN(dir)+1; /* include '\0' */
  414. #ifdef XP_MAC
  415.     alias = NULL;
  416.     vr_MacAliasFromPath(dir, &alias, &datalen);
  417. #endif
  418.     err = NR_RegSetEntry( reg, key, entry, REGTYPE_ENTRY_BYTES, alias, datalen);
  419. #ifdef XP_MAC
  420.     XP_FREEIF(alias);
  421. #endif
  422.     return err;
  423. }
  424.  
  425.  
  426.  
  427. static REGERR vr_GetPathname(HREG reg, RKEY key, char *entry, char *buf, uint32 sizebuf)
  428. {
  429.     /* stored as BYTES since it's platform OS charset */
  430. #ifndef XP_MAC
  431.     REGERR err;
  432.     err = NR_RegGetEntry( reg, key, entry, (void*)buf, &sizebuf );
  433.     return err;
  434. #else
  435.     REGERR err;
  436.     REGINFO info;
  437.  
  438.     info.size = sizeof(REGINFO);
  439.  
  440.     err = NR_RegGetEntryInfo( reg, key, entry,&info );
  441.     if (err != REGERR_OK)
  442.         return err;
  443.  
  444.     if (info.entryType == REGTYPE_ENTRY_STRING_UTF)    /* Assume that it is a file name */
  445.         err = NR_RegGetEntry( reg, key, entry, (void*)buf, &sizebuf );
  446.      else
  447.      {
  448. #define MAC_ALIAS_BUFFER_SIZE 4000
  449.         char stackBuf[MAC_ALIAS_BUFFER_SIZE];
  450.         uint32 stackBufSize = MAC_ALIAS_BUFFER_SIZE;
  451.         char * tempBuf;
  452.  
  453.         err = NR_RegGetEntry( reg, key, entry, (void*)stackBuf, &stackBufSize );
  454.         if (err != REGERR_OK)
  455.             return err;
  456.  
  457.         tempBuf = vr_PathFromMacAlias(stackBuf, stackBufSize);
  458.  
  459.         if (tempBuf == NULL)
  460.             err = REGERR_FAIL;
  461.         else
  462.             if (XP_STRLEN(tempBuf) > sizebuf)
  463.                 err = REGERR_BUFTOOSMALL;
  464.             else
  465.                 XP_STRCPY(buf, tempBuf);
  466.  
  467.         XP_FREEIF(tempBuf);
  468.     }
  469.     return err;
  470. #endif
  471. }
  472.  
  473.  
  474.  
  475. /* create default tree with 'installation' under Navigator */
  476. /* set Current to the installation string */
  477. static REGERR vr_SetCurrentNav( char *installation, char *programPath, char *versionStr)
  478. {
  479.     REGERR      err;
  480.     REGENUM     state;
  481.     RKEY        navKey;
  482.     int         bFound;
  483.     int         nCopy;
  484.     char        regname[MAXREGNAMELEN];
  485.     char        curstr[MAXREGNAMELEN];
  486.     char        dirbuf[MAXREGNAMELEN];
  487.  
  488.     err = NR_RegAddKey( vreg, ROOTKEY_VERSIONS, NAVIGATOR_NODE, &navKey );
  489.     if (err != REGERR_OK)
  490.         goto done;
  491.  
  492.     /* ...look for "Current Version" entry */
  493.     err = NR_RegGetEntryString( vreg, navKey, CURRENT_VER, curstr, sizeof(curstr));
  494.     if ( err == REGERR_NOFIND )
  495.     {
  496.         /* No current installation, we can simply add a new one  */
  497.         err = NR_RegAddKey( vreg, navKey, installation, &curver );
  498.  
  499.         /* ... add Path and Version properties */
  500.         if ( err == REGERR_OK ) {
  501.             err = vr_SetPathname( vreg, curver, NAVHOME, programPath );
  502.             if ( REGERR_OK == err && versionStr != NULL) {
  503.                 err = NR_RegSetEntryString( vreg, curver, VERSTR, versionStr );
  504.             }
  505.         }
  506.  
  507.         if ( REGERR_OK == err ) {
  508.             /* successfully added, make it the current version */
  509.             err = NR_RegSetEntryString(vreg, navKey, CURRENT_VER, installation);
  510.         }
  511.  
  512.         if (err != REGERR_OK)
  513.             goto done;
  514.     }
  515.     else if ( REGERR_OK == err )
  516.     {
  517.         /* found one: if we're lucky we got the right one */
  518.         bFound = FALSE;
  519.         err = NR_RegGetKey( vreg, navKey, curstr, &curver );
  520.         if ( REGERR_OK == err ) {
  521.             err = vr_GetPathname( vreg, curver, NAVHOME, dirbuf, sizeof(dirbuf) );
  522.             if ( REGERR_OK == err )
  523.                 bFound = vr_CompareDirs(dirbuf, programPath);
  524.             else if ( REGERR_NOFIND == err ) {
  525.                 /* assume this is the right one since it's 'Current' */
  526.                 err = vr_SetPathname( vreg, curver, NAVHOME, programPath );
  527.                 bFound = TRUE;
  528.             }
  529.         }
  530.  
  531.         /* Look for an existing installation if not found */
  532.         state = 0;
  533.         while (!bFound && err == REGERR_OK ) {
  534.             err = NR_RegEnumSubkeys( vreg, navKey, &state, curstr,
  535.                     sizeof(curstr), REGENUM_NORMAL );
  536.  
  537.             if (REGERR_OK == err ) {
  538.                 err = vr_GetPathname( vreg, state, NAVHOME, dirbuf, sizeof(dirbuf) );
  539.                 if (REGERR_OK == err ) {
  540.                     if (vr_CompareDirs( dirbuf, programPath )) {
  541.                         bFound = TRUE;
  542.                         curver = (RKEY)state;
  543.                     }
  544.                 }
  545.                 else if ( err == REGERR_NOFIND ) {
  546.                     /* wasn't a navigator node */
  547.                     err = REGERR_OK;
  548.                 }
  549.             }
  550.         }
  551.  
  552.         /* found the right one, make it current */
  553.         if (bFound) {
  554.             err = NR_RegSetEntryString( vreg, navKey, CURRENT_VER, curstr );
  555.             /* update version (curver already set) */
  556.             if ( REGERR_OK == err && versionStr != NULL ) {
  557.                 err = NR_RegSetEntryString( vreg, curver, VERSTR, versionStr );
  558.             }
  559.         }
  560.         /* otherwise if no current installation matches */
  561.         else if ( err == REGERR_NOMORE )
  562.         {
  563.             /* look for an empty slot to put new installation */
  564.             nCopy = 1;
  565.             XP_STRCPY( regname, installation );
  566.             do {
  567.                 err = NR_RegGetKey( vreg, navKey, regname, &curver );
  568.                 if (err == REGERR_OK) {
  569.                     nCopy++;
  570.                     sprintf( regname, "%s #%d", installation, nCopy );
  571.                 }
  572.             } while (err==REGERR_OK);
  573.  
  574.             if (err != REGERR_NOFIND)
  575.                 goto done;  /* real error, bail */
  576.  
  577.             /* found an unused name -- add it */
  578.             err = NR_RegAddKey( vreg, navKey, regname, &curver );
  579.             if ( err != REGERR_OK )
  580.                 goto done;
  581.  
  582.             /* add path and version properties */
  583.             err = vr_SetPathname( vreg, curver, NAVHOME, programPath );
  584.             if ( REGERR_OK == err && versionStr != NULL ) {
  585.                 err = NR_RegSetEntryString( vreg, curver, VERSTR, versionStr );
  586.             }
  587.  
  588.             if ( REGERR_OK == err ) {
  589.                 /* everything's OK, make it current */
  590.                 err = NR_RegSetEntryString(vreg,navKey,CURRENT_VER,regname);
  591.             }
  592.         }
  593.     }
  594. done:
  595.     return err;
  596. }
  597.  
  598.  
  599. #ifdef XP_MAC
  600.  
  601. #include <Aliases.h>
  602. #include <TextUtils.h>
  603. #include <Memory.h>
  604. #include "FullPath.h"
  605.  
  606. /* returns an alias as a malloc'd pointer.
  607.  * On failure, *alias is NULL
  608.  */
  609. static void vr_MacAliasFromPath(const char * fileName, void ** alias, int32 * length)
  610. {
  611.     OSErr err;
  612.     FSSpec fs;
  613.     AliasHandle macAlias;
  614.     *alias = NULL;
  615.     *length = 0;
  616.     c2pstr((char*)fileName);
  617.     err = FSMakeFSSpec(0, 0, (unsigned char *)fileName, &fs);
  618.     p2cstr((unsigned char *)fileName);
  619.     if ( err != noErr )
  620.         return;
  621.     err = NewAlias(NULL, &fs, &macAlias);
  622.     if ( (err != noErr) || ( macAlias == NULL ))
  623.         return;
  624.     *length = GetHandleSize( (Handle) macAlias );
  625.     *alias = XP_ALLOC( *length );
  626.     if ( *alias == NULL )
  627.     {
  628.         DisposeHandle((Handle)macAlias);
  629.         return;
  630.     }
  631.     HLock( (Handle) macAlias );
  632.     XP_MEMCPY(*alias, *macAlias , *length);
  633.     HUnlock( (Handle) macAlias );
  634.     DisposeHandle( (Handle) macAlias);
  635.     return;
  636. }
  637.  
  638. /* resolves an alias, and returns a full path to the Mac file
  639.  * If the alias changed, it would be nice to update our alias pointers
  640.  */
  641. static char * vr_PathFromMacAlias(const void * alias, uint32 aliasLength)
  642. {
  643.     OSErr err;
  644.     AliasHandle h = NULL;
  645.     Handle fullPath = NULL;
  646.     short fullPathLength;
  647.     char * cpath = NULL;
  648.     FSSpec fs;
  649.     Boolean ignore;    /* Change flag, it would be nice to change the alias on disk
  650.                         if the file location changed */
  651.  
  652.     /* Copy the alias to a handle and resolve it */
  653.     h = (AliasHandle) NewHandle(aliasLength);
  654.     if ( h == NULL)
  655.         goto fail;
  656.     HLock( (Handle) h);
  657.     XP_MEMCPY( *h, alias, aliasLength );
  658.     HUnlock( (Handle) h);
  659.  
  660.     err = ResolveAlias(NULL, h, &fs, &ignore);
  661.     if (err != noErr)
  662.         goto fail;
  663.  
  664.     /* if the file is inside the trash, assume that user has deleted
  665.          it and that we do not want to look at it */
  666.     {
  667.         short vRefNum;
  668.         long dirID;
  669.         err = FindFolder(fs.vRefNum, kTrashFolderType, false, &vRefNum, &dirID);
  670.         if (err == noErr)
  671.             if (dirID == fs.parID)    /* File is inside the trash */
  672.                 goto fail;
  673.     }
  674.     /* Get the full path and create a char * out of it */
  675.  
  676.     err = GetFullPath(fs.vRefNum, fs.parID,fs.name, &fullPathLength, &fullPath);
  677.     if ( (err != noErr) || (fullPath == NULL) )
  678.         goto fail;
  679.  
  680.     cpath = (char*) XP_ALLOC(fullPathLength + 1);
  681.     if ( cpath == NULL)
  682.         goto fail;
  683.     HLock( fullPath );
  684.     XP_MEMCPY(cpath, *fullPath, fullPathLength);
  685.     cpath[fullPathLength] = 0;
  686.     HUnlock( fullPath );
  687.     /* Drop through */
  688. fail:
  689.     if (h != NULL)
  690.         DisposeHandle( (Handle) h);
  691.     if (fullPath != NULL)
  692.         DisposeHandle( fullPath);
  693.     return cpath;
  694. }
  695.  
  696. #endif
  697.  
  698. /* assumes registries are open (only use after vr_Init() returns OK).
  699.  * For UNIX look first in the global, then in the local if not found
  700.  * -- returns both hreg and key of the named node (if found)
  701.  */
  702. static REGERR vr_FindKey(char *component_path, HREG *hreg, RKEY *key)
  703. {
  704.     REGERR err;
  705.     RKEY rootkey;
  706.  
  707. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  708.     if (unixreg != NULL) {
  709.         *hreg = unixreg;
  710.         rootkey = UNIX_ROOT(component_path);
  711.         err = NR_RegGetKey( *hreg, rootkey, component_path, key );
  712.     }
  713.     if (unixreg == NULL || err == REGERR_NOFIND )
  714. #endif
  715.     {
  716.         *hreg = vreg;
  717.         rootkey = PATH_ROOT(component_path);
  718.         err = NR_RegGetKey( *hreg, rootkey, component_path, key );
  719.     }
  720.  
  721.     return err;
  722. }
  723.  
  724.  
  725. /* ---------------------------------------------------------------------
  726.  * Interface
  727.  * ---------------------------------------------------------------------
  728.  */
  729.  
  730. VR_INTERFACE(REGERR) VR_PackRegistry(void)
  731. {
  732.     REGERR err;
  733.  
  734.     /* make sure vreg (src) is open */
  735.     err = vr_Init();
  736.     if (err != REGERR_OK)
  737.         return err;
  738.  
  739.     err = NR_RegPack( vreg );
  740.  
  741.     return err;
  742.  
  743. }   /* PackRegistry */
  744.  
  745.  
  746.  
  747. VR_INTERFACE(REGERR) VR_CreateRegistry( char *installation, char *programPath, char *versionStr )
  748. {
  749.     FILEHANDLE  fh;
  750.     REGERR      err;
  751.     XP_StatStruct st;
  752.     char *      regname = "";
  753. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  754.     char *      regbuf = NULL;
  755. #endif
  756.  
  757.     if ( installation == NULL || *installation == '\0' )
  758.         return REGERR_PARAM;
  759.  
  760. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  761.     if (bGlobalRegistry)
  762.     {
  763.         regbuf = (char*)XP_ALLOC( 10 + XP_STRLEN(programPath) );
  764.         if (regbuf == NULL)
  765.             return REGERR_MEMORY;
  766.  
  767.         XP_STRCPY( regbuf, programPath );
  768.         XP_STRCAT( regbuf, "registry" );
  769.         regname = regbuf;
  770.     }
  771. #endif
  772.  
  773. #ifdef STANDALONE_REGISTRY
  774.     /* standalone registry automatically creates it if not found */
  775.     fh = XP_FileOpen( regname, xpRegistry, XP_FILE_UPDATE_BIN );
  776. #else
  777.     if ( ( XP_Stat ( regname, &st, xpRegistry ) == 0) )
  778.         fh = XP_FileOpen( regname, xpRegistry, XP_FILE_UPDATE_BIN );
  779.     else
  780.         /* create a new empty registry */
  781.         fh = XP_FileOpen( regname, xpRegistry, XP_FILE_WRITE_BIN );
  782. #endif
  783.  
  784.     if (fh == NULL) {
  785.         err = REGERR_FAIL;
  786.         goto done;
  787.     }
  788.     XP_FileClose(fh);
  789.  
  790.     err = NR_RegOpen( regname, &vreg );
  791.     if (err != REGERR_OK)
  792.         goto done;
  793.  
  794.     /* create default tree with 'installation' under Navigator */
  795.     /* set Current to the installation string */
  796.  
  797.     err = vr_SetCurrentNav( installation, programPath, versionStr );
  798.  
  799.     if ( REGERR_OK == err )
  800.         isInited = 1;
  801.  
  802. done:
  803. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  804.     XP_FREEIF( regbuf );
  805. #endif
  806.     return err;
  807.  
  808. }    /* CreateRegistry */
  809.  
  810.  
  811. #ifdef XP_MAC
  812. #pragma export on
  813. #endif
  814.  
  815. VR_INTERFACE(REGERR) VR_Close(void)
  816. {
  817.     REGERR err = REGERR_OK;
  818.  
  819. #ifndef STANDALONE_REGISTRY
  820.     PR_EnterMonitor(vr_monitor);
  821. #endif
  822.  
  823.     if (isInited) {
  824. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  825.         if ( unixreg != NULL )
  826.             NR_RegClose( unixreg );
  827. #endif
  828.         err = NR_RegClose( vreg );
  829.         isInited = 0;
  830.     }
  831.  
  832. #ifndef STANDALONE_REGISTRY
  833.     PR_ExitMonitor(vr_monitor);
  834. #endif
  835.  
  836.     return err;
  837. }    /* Close */
  838.  
  839. VR_INTERFACE(REGERR) VR_GetVersion(char *component_path, VERSION *result)
  840. {
  841.     REGERR  err;
  842.     RKEY    rootkey;
  843.     RKEY    key;
  844.     HREG    hreg;
  845.     VERSION ver;
  846.     char    buf[MAXREGNAMELEN];
  847.  
  848.     err = vr_Init();
  849.     if (err != REGERR_OK)
  850.         return err;
  851.  
  852.     hreg = vreg;
  853.     
  854. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  855.     err = vr_FindKey( component_path, &hreg, &key );
  856. #else
  857.     rootkey = PATH_ROOT(component_path);
  858.     err = NR_RegGetKey( vreg, rootkey, component_path, &key );
  859. #endif
  860.     if (err != REGERR_OK)
  861.         return err;
  862.  
  863.     err = NR_RegGetEntryString( hreg, key, VERSTR, buf, sizeof(buf) );
  864.     if (err != REGERR_OK)
  865.         return err;
  866.  
  867.     vr_ParseVersion(buf, &ver);
  868.  
  869.     memcpy(result, &ver, sizeof(VERSION));
  870.  
  871.     return REGERR_OK;
  872.  
  873. }    /* GetVersion */
  874.  
  875. VR_INTERFACE(REGERR) VR_GetPath(char *component_path, uint32 sizebuf, char *buf)
  876. {
  877.     REGERR err;
  878.     RKEY rootkey;
  879.     RKEY key;
  880.     HREG hreg;
  881.  
  882.     err = vr_Init();
  883.     if (err != REGERR_OK)
  884.         return err;
  885.  
  886.     hreg = vreg;
  887.     
  888. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  889.     err = vr_FindKey( component_path, &hreg, &key );
  890. #else
  891.     rootkey = PATH_ROOT(component_path);
  892.     err = NR_RegGetKey( vreg, rootkey, component_path, &key );
  893. #endif
  894.     if (err != REGERR_OK)
  895.         return err;
  896.     
  897.     err = vr_GetPathname( hreg, key, PATHSTR, buf, sizebuf );
  898.  
  899.     return err;
  900.  
  901. }    /* GetPath */
  902.  
  903. #ifdef XP_MAC
  904. #pragma export reset
  905. #endif
  906.  
  907.  
  908. VR_INTERFACE(REGERR) VR_SetDefaultDirectory(char *component_path, char *directory)
  909. {
  910.     REGERR err;
  911.     RKEY rootkey;
  912.     RKEY key;
  913.  
  914.     err = vr_Init();
  915.     if (err != REGERR_OK)
  916.         return err;
  917.  
  918.     rootkey = PATH_ROOT(component_path);
  919.  
  920.     err = NR_RegGetKey( vreg, rootkey, component_path, &key );
  921.     if (err != REGERR_OK)
  922.         return err;
  923.     
  924. /*    err = NR_RegSetEntryString( vreg, key, DIRSTR, directory ); */
  925.     err = vr_SetPathname( vreg, key, DIRSTR, directory );
  926.  
  927.     return err;
  928. }
  929.  
  930.  
  931.  
  932. VR_INTERFACE(REGERR) VR_GetDefaultDirectory(char *component_path, uint32 sizebuf, char *buf)
  933. {
  934.     REGERR err;
  935.     RKEY rootkey;
  936.     RKEY key;
  937.     HREG hreg;
  938.  
  939.     err = vr_Init();
  940.     if (err != REGERR_OK)
  941.         return err;
  942.  
  943.     hreg = vreg;
  944.     
  945. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  946.     err = vr_FindKey( component_path, &hreg, &key );
  947. #else
  948.     rootkey = PATH_ROOT(component_path);
  949.     err = NR_RegGetKey( vreg, rootkey, component_path, &key );
  950. #endif
  951.     if (err != REGERR_OK)
  952.         return err;
  953.     
  954. /*    err = NR_RegGetEntryString( vreg, key, DIRSTR, buf, sizebuf ); */
  955.     err = vr_GetPathname( hreg, key, DIRSTR, buf, sizebuf );
  956.  
  957.     return err;
  958. }
  959.  
  960.  
  961.  
  962. VR_INTERFACE(REGERR) VR_Install(char *component_path, char *filepath, char *version, int bDirectory)
  963. {
  964.     REGERR err;
  965.     RKEY rootKey;
  966.     RKEY key;
  967.  
  968.     /* Initialize the registry in case this is first call */
  969.     err = vr_Init();
  970.     if (err != REGERR_OK)
  971.         return err;
  972.  
  973.     /* Use curver if path is relative */
  974.     rootKey = PATH_ROOT(component_path);
  975.  
  976.     /* Make sure path components (keys) exist by calling Add */
  977.     /* (special "" component must always exist, and Add fails) */
  978.     if ( component_path != NULL && *component_path == '\0' ) {
  979.         err = NR_RegGetKey( vreg, rootKey, component_path, &key );
  980.     }
  981.     else {
  982.         err = NR_RegAddKey( vreg, rootKey, component_path, &key );
  983.     }
  984.     if (err != REGERR_OK)
  985.         return err;
  986.  
  987.     if ( version != NULL && *version != '\0' ) {
  988.         /* Add "Version" entry with values like "4.0.0.0" */
  989.         err = NR_RegSetEntryString( vreg, key, VERSTR, version );
  990.         if (err != REGERR_OK)
  991.             goto abort;
  992.     }
  993.  
  994.     if ( filepath != NULL && *filepath != '\0' ) {
  995.         /* add "Path" entry */
  996.         err = vr_SetPathname( vreg, key, (bDirectory)?DIRSTR:PATHSTR, filepath );
  997.  
  998.         if (err != REGERR_OK)
  999.             goto abort;
  1000.     }
  1001.  
  1002.     return REGERR_OK;
  1003.  
  1004. abort:
  1005.     NR_RegDeleteKey( vreg, rootKey, component_path );
  1006.     return err;
  1007.  
  1008. }    /* Install */
  1009.  
  1010.  
  1011.  
  1012. VR_INTERFACE(REGERR) VR_Remove(char *component_path)
  1013. {
  1014.     REGERR err;
  1015.     RKEY rootkey;
  1016.  
  1017.     err = vr_Init();
  1018.     if (err != REGERR_OK)
  1019.         return err;
  1020.  
  1021.     rootkey = PATH_ROOT(component_path);
  1022.  
  1023.     return NR_RegDeleteKey( vreg, rootkey, component_path );
  1024.  
  1025. }    /* Remove */
  1026.  
  1027.  
  1028.  
  1029. VR_INTERFACE(REGERR) VR_Enum(REGENUM *state, char *buffer, uint32 buflen)
  1030. {
  1031.     REGERR err;
  1032.  
  1033.     err = vr_Init();
  1034.     if (err != REGERR_OK)
  1035.         return err;
  1036.  
  1037.     return NR_RegEnumSubkeys( vreg, ROOTKEY_VERSIONS, state, buffer, buflen, REGENUM_DESCEND);
  1038. }
  1039.  
  1040. #ifdef XP_MAC
  1041. #pragma export on
  1042. #endif
  1043.  
  1044. VR_INTERFACE(REGERR) VR_InRegistry(char *component_path)
  1045. {
  1046.     REGERR err;
  1047.     RKEY rootkey;
  1048.     RKEY key;
  1049.     HREG hreg;
  1050.  
  1051.     err = vr_Init();
  1052.     if (err != REGERR_OK)
  1053.         return err;
  1054.  
  1055. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  1056.     return vr_FindKey( component_path, &hreg, &key );
  1057. #else
  1058.     rootkey = PATH_ROOT(component_path);
  1059.     return NR_RegGetKey( vreg, rootkey, component_path, &key );
  1060. #endif
  1061. }    /* InRegistry */
  1062.  
  1063.  
  1064. VR_INTERFACE(REGERR) VR_ValidateComponent(char *component_path)
  1065. {
  1066.     REGERR err;
  1067.     RKEY rootkey;
  1068.     RKEY key;
  1069.     HREG hreg;
  1070.     char path[MAXREGPATHLEN];
  1071.     char *url = NULL;
  1072.     char *urlPath;
  1073.     XP_StatStruct s;
  1074.  
  1075.  
  1076. #ifdef USE_CHECKSUM
  1077.     char buf[MAXREGNAMELEN];
  1078.     long calculatedCheck;
  1079.     int storedCheck;
  1080. #endif
  1081.  
  1082.     err = vr_Init();
  1083.     if (err != REGERR_OK)
  1084.         return err;
  1085.  
  1086. #if !defined(STANDALONE_REGISTRY) && defined(XP_UNIX)
  1087.     err = vr_FindKey( component_path, &hreg, &key );
  1088. #else
  1089.     rootkey = PATH_ROOT(component_path);
  1090.     err = NR_RegGetKey( vreg, rootkey, component_path, &key );
  1091. #endif
  1092.     if ( err != REGERR_OK )
  1093.         return err;
  1094.  
  1095.     err = VR_GetPath( component_path, sizeof(path), path );
  1096.     if ( err != REGERR_OK ) {
  1097.         if ( err == REGERR_NOFIND ) {
  1098.             err = REGERR_NOPATH;
  1099.         }
  1100.         return err;
  1101.     }
  1102.  
  1103.     urlPath = path;
  1104. #ifndef STANDALONE_REGISTRY
  1105.     url = XP_PlatformFileToURL(path);
  1106.     if ( url == NULL )
  1107.         return REGERR_MEMORY;
  1108.     urlPath = url+7;
  1109. #endif
  1110.  
  1111.     if ( XP_Stat( urlPath, &s, xpURL ) != 0 ) {
  1112.         err = REGERR_NOFILE;
  1113.     }
  1114.     XP_FREEIF(url);
  1115.     if (err != REGERR_OK)
  1116.         return err;
  1117.  
  1118.  
  1119. #if defined(USE_CHECKSUM) && !defined(XP_UNIX)
  1120.     err = NR_RegGetEntryString( vreg, key, CHKSTR, buf, sizeof(buf) );
  1121.     if (err != REGERR_OK)
  1122.         return err;
  1123.  
  1124.     storedCheck = atoi(buf);
  1125.  
  1126.     err = vr_GetCheck(filepath, &calculatedCheck);
  1127.     if (err != REGERR_OK)
  1128.         return err;
  1129.  
  1130.     if (storedCheck != calculatedCheck)
  1131.     {
  1132.         /* printf("File %s checksum was %d, not %d as expected.\n", 
  1133.             filepath, calculatedCheck, storedCheck);
  1134.         */
  1135.         return REGERR_BADCHECK;
  1136.     }
  1137. #endif /* USE_CHECKSUM */
  1138.  
  1139.     return REGERR_OK;
  1140.  
  1141. }    /* CheckEntry */
  1142.  
  1143. #ifdef XP_MAC
  1144. #pragma export reset
  1145. #endif
  1146.  
  1147. /* EOF: VerReg.c */
  1148.