/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Daniel Veditz * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* ==================================================================== * VerReg.c * XP Version Registry functions (prototype) * ==================================================================== */ /* -------------------------------------------------------------------- * Install 'Navigator' produces a tree of: * * /Components/Netscape/Web/Navigator/ * ...Path="c:\netscape\program\netscape.exe" * ...Version=4.0.0.0 * * -------------------------------------------------------------------- */ #include #include #if defined(XP_WIN) #include #endif #if defined(XP_OS2) #include #include #endif #include #include #ifdef STANDALONE_REGISTRY #include #include #endif /*STANDALONE_REGISTRY*/ #include "reg.h" #include "NSReg.h" #include "VerReg.h" /* -------- local defines --------------- */ #define MAXREGVERLEN 32 /* Version=12345.12345.12345.12345 */ #define VERSTR "Version" #define CHKSTR "Check" #define PATHSTR "Path" #define DIRSTR "Directory" #define NAVHOME "InstallDir" #define REFCSTR "RefCount" #define SHAREDSTR "Shared" #define PACKAGENAMESTR "PackageName" #define SHAREDFILESSTR "/Shared Files" #define VERSION_NAME "Mozilla" #define NAVIGATOR_NODE "/mozilla.org" #define CURRENT_VER "CurrentVersion" #define PATH_ROOT(p) ( ((p) && *(p)==PATHDEL) ? ROOTKEY_VERSIONS : curver ) #define UNIX_ROOT(p) ( ((p) && *(p)==PATHDEL) ? ROOTKEY_VERSIONS : unixver ) /* --------------------------------------------------------------------- * Global variables * --------------------------------------------------------------------- */ static int isInited = 0; static RKEY curver = 0; static char gCurstr[MAXREGNAMELEN]; static HREG vreg = 0; static char *app_dir = NULL; char *verRegName = NULL; #if defined(XP_UNIX) && !defined(XP_MACOSX) /* Extra Unix variables to deal with two registries * "vreg" is always the writable registry. * If "vreg" is the local registry then "unixreg" will * be the global registry read-only (unless we couldn't * open it). */ #if !defined(STANDALONE_REGISTRY) static HREG unixreg = 0; static RKEY unixver = 0; #endif XP_Bool bGlobalRegistry = FALSE; #endif #ifndef STANDALONE_REGISTRY PRLock *vr_lock = NULL; #endif /* --------------------------------------------------------------------- * local functions * --------------------------------------------------------------------- */ static REGERR vr_Init(void); static XP_Bool vr_CompareDirs( char *dir1, char *dir2 ); static REGERR vr_SetCurrentNav( char *product, char *programPath, char *versionStr); static REGERR vr_ParseVersion(char *verstr, VERSION *result); #ifdef USE_CHECKSUM static REGERR vr_GetCheck(char *path, int32 *check); #endif static REGERR vr_SetPathname(HREG reg, RKEY key, char *entry, char *dir); static REGERR vr_GetPathname(HREG reg, RKEY key, char *entry, char *buf, uint32 sizebuf); static REGERR vr_FindKey(char *name, HREG *hreg, RKEY *key); static REGERR vr_GetUninstallItemPath(char *regPackageName, char *regbuf, uint32 regbuflen); static REGERR vr_convertPackageName(char *regPackageName, char *convertedPackageName, uint32 convertedDataLength); static REGERR vr_unmanglePackageName(char *mangledPackageName, char *regPackageName, uint32 regPackageLength); /* --------------------------------------------------------------------- */ static REGERR vr_Init(void) { REGERR err = REGERR_OK; char *regname = vr_findVerRegName(); #if defined(XP_UNIX) && !defined(XP_MACOSX) || defined(STANDALONE_REGISTRY) char curstr[MAXREGNAMELEN]; RKEY navKey; #endif #if defined(XP_UNIX) && !defined(XP_MACOSX) char *regbuf = NULL; #endif #ifndef STANDALONE_REGISTRY if (vr_lock == NULL) return REGERR_FAIL; #endif PR_Lock(vr_lock); if (!isInited) { #if defined(XP_UNIX) && !defined(XP_MACOSX) /* need browser directory to find the correct registry */ if (app_dir != NULL) { regbuf = (char*)XP_ALLOC( 10 + XP_STRLEN(app_dir) ); if (regbuf != NULL ) { XP_STRCPY( regbuf, app_dir ); XP_STRCAT( regbuf, "/registry" ); } else { err = REGERR_MEMORY; } } if ( err != REGERR_OK ) goto done; if (bGlobalRegistry) regname = regbuf; #endif /* Open version registry */ err = NR_RegOpen( regname, &vreg ); #ifndef STANDALONE_REGISTRY if (err == REGERR_OK) { /* find/set the current nav node */ err = vr_SetCurrentNav( VERSION_NAME, app_dir, NULL ); if ( REGERR_OK != err ) { /* couldn't find or set current nav -- big problems! */ NR_RegClose( vreg ); goto done; } } #if defined(XP_UNIX) && !defined(XP_MACOSX) /* try to open shared Unix registry, but not an error if you can't */ unixreg = NULL; if (!bGlobalRegistry && err == REGERR_OK ) { unixver = 0; if (NR_RegOpen( regbuf, &unixreg ) == REGERR_OK) { if (NR_RegGetKey( unixreg, ROOTKEY_VERSIONS, NAVIGATOR_NODE, &navKey) == REGERR_OK) { if (NR_RegGetEntryString( unixreg, navKey, CURRENT_VER, curstr, sizeof(curstr)) == REGERR_OK ) { NR_RegGetKey( unixreg, navKey, curstr, &unixver ); } } } } #endif if (err == REGERR_OK) { /* successfully opened! */ isInited = 1; } goto done; #else if (err != REGERR_OK) goto done; /* Determine 'curver' key and ensure correct structure by adding */ /* ...find top-level "Navigator" node (add if missing) */ err = NR_RegAddKey( vreg, ROOTKEY_VERSIONS, NAVIGATOR_NODE, &navKey ); if (err != REGERR_OK) goto done; /* ...look for "Current Version" entry */ err = NR_RegGetEntryString( vreg, navKey, CURRENT_VER, curstr, sizeof(curstr) ); if ( err == REGERR_NOFIND ) { /* If not found create one with the built-in version */ err = NR_RegSetEntryString( vreg, navKey, CURRENT_VER, VERSION_NAME ); XP_STRCPY( curstr, VERSION_NAME ); } if ( err != REGERR_OK ) goto done; /* ...look for "curstr" child key of the navigator node */ err = NR_RegAddKey( vreg, navKey, curstr, &curver ); if (err == REGERR_OK) { /* successfully opened! */ isInited = 1; } #endif } done: PR_Unlock(vr_lock); #if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(STANDALONE_REGISTRY) XP_FREEIF(regbuf); #endif return err; } /* Init */ #if defined(XP_WIN) || defined(XP_OS2) #define VR_FILE_SEP '\\' #elif defined(XP_UNIX) || defined(XP_BEOS) #define VR_FILE_SEP '/' #endif static XP_Bool vr_CompareDirs( char *dir1, char *dir2 ) { int len1,len2; XP_ASSERT( dir1 && dir2 ); if (!dir1 || !dir2) return FALSE; len1 = XP_STRLEN( dir1 ); len2 = XP_STRLEN( dir2 ); if ( dir1[len1-1] == VR_FILE_SEP ) len1--; if ( dir2[len2-1] == VR_FILE_SEP ) len2--; if ( len1 != len2 ) return FALSE; #if defined(XP_UNIX) && !defined(XP_MACOSX) return ( XP_STRNCMP(dir1, dir2, len1) == 0 ); #else return ( XP_STRNCASECMP(dir1, dir2, len1) == 0 ); #endif } REGERR vr_ParseVersion(char *verstr, VERSION *result) { result->major = result->minor = result->release = result->build = 0; result->major = atoi(verstr); while (*verstr && *verstr != '.') verstr++; if (*verstr) { verstr++; result->minor = atoi(verstr); while (*verstr && *verstr != '.') verstr++; if (*verstr) { verstr++; result->release = atoi(verstr); while (*verstr && *verstr != '.') verstr++; if (*verstr) { verstr++; result->build = atoi(verstr); while (*verstr && *verstr != '.') verstr++; } } } return REGERR_OK; } /* ParseVersion */ #ifdef USE_CHECKSUM #define BLKSIZ 16384 static REGERR vr_GetCheck(char *path, int32 *check) { int fh; char *buf; int actual; char *p; int i; int chk; XP_ASSERT(path); XP_ASSERT(check); *check = chk = 0; #ifdef NEED_XP_FIXES /* open file for read */ fh = open(path, O_RDONLY| O_BINARY); if (fh < 0) { switch (errno) { case ENOENT: /* file not found */ return REGERR_NOFILE; case EACCES: /* file in use */ #ifdef EMFILE case EMFILE: /* too many files open */ #endif default: return REGERR_FAIL; } } buf = malloc(BLKSIZ); if (!buf) { close(fh); return REGERR_MEMORY; } do { /* read a block */ actual = read(fh, buf, BLKSIZ); /* add to checksum */ for (p=buf, i=0; i