xref: /plan9-contrib/sys/src/cmd/gs/src/dwinst.cpp (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 1999-2002, Ghostgum Software Pty Ltd.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier // $Id: dwinst.cpp,v 1.6 2004/11/18 06:48:41 ghostgum Exp $
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier #define STRICT
207dd7cddfSDavid du Colombier #include <windows.h>
217dd7cddfSDavid du Colombier #include <objbase.h>
227dd7cddfSDavid du Colombier #include <shlobj.h>
237dd7cddfSDavid du Colombier #include <stdio.h>
247dd7cddfSDavid du Colombier #include <io.h>
257dd7cddfSDavid du Colombier #include <direct.h>
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier #include "dwinst.h"
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier #define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
307dd7cddfSDavid du Colombier #define UNINSTALLSTRINGKEY TEXT("UninstallString")
317dd7cddfSDavid du Colombier #define DISPLAYNAMEKEY TEXT("DisplayName")
327dd7cddfSDavid du Colombier #define UNINSTALL_FILE "uninstal.txt"
337dd7cddfSDavid du Colombier char szSection[] = "////////////////////////////////\n";
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier #ifdef _MSC_VER
367dd7cddfSDavid du Colombier #define mktemp(x) _mktemp(x)
377dd7cddfSDavid du Colombier #define chdir(x) _chdir(x)
387dd7cddfSDavid du Colombier #define mkdir(x) _mkdir(x)
397dd7cddfSDavid du Colombier #endif
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier //////////////////////////////////////////////////////////////////////
447dd7cddfSDavid du Colombier // Construction/Destruction
457dd7cddfSDavid du Colombier //////////////////////////////////////////////////////////////////////
467dd7cddfSDavid du Colombier 
CInstall()477dd7cddfSDavid du Colombier CInstall::CInstall()
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier 	CoInitialize(NULL);
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier 	m_szTargetDir[0] = '\0';
527dd7cddfSDavid du Colombier 	m_szTargetGroup[0] = '\0';
537dd7cddfSDavid du Colombier 	m_szPrograms[0] = '\0';
547dd7cddfSDavid du Colombier 	m_szMainDir[0] = '\0';
557dd7cddfSDavid du Colombier 	AddMessageFn = NULL;
567dd7cddfSDavid du Colombier 	SetAllUsers(FALSE);
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier 
~CInstall()597dd7cddfSDavid du Colombier CInstall::~CInstall()
607dd7cddfSDavid du Colombier {
617dd7cddfSDavid du Colombier 	CoUninitialize();
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier 
CleanUp(void)647dd7cddfSDavid du Colombier void CInstall::CleanUp(void)
657dd7cddfSDavid du Colombier {
667dd7cddfSDavid du Colombier 	// delete all temporary files
677dd7cddfSDavid du Colombier 	if (m_fLogNew)
687dd7cddfSDavid du Colombier 		fclose(m_fLogNew);
697dd7cddfSDavid du Colombier 	m_fLogNew = NULL;
707dd7cddfSDavid du Colombier 	if (m_fLogOld)
717dd7cddfSDavid du Colombier 		fclose(m_fLogOld);
727dd7cddfSDavid du Colombier 	m_fLogOld = NULL;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	if (strlen(m_szRegistryNew))
757dd7cddfSDavid du Colombier 		DeleteFile(m_szRegistryNew);
767dd7cddfSDavid du Colombier 	m_szRegistryNew[0] = '\0';
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier 	if (strlen(m_szRegistryOld))
797dd7cddfSDavid du Colombier 		DeleteFile(m_szRegistryOld);
807dd7cddfSDavid du Colombier 	m_szRegistryOld[0] = '\0';
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier 	if (strlen(m_szShellNew))
837dd7cddfSDavid du Colombier 		DeleteFile(m_szShellNew);
847dd7cddfSDavid du Colombier 	m_szShellNew[0] = '\0';
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier 	if (strlen(m_szShellOld))
877dd7cddfSDavid du Colombier 		DeleteFile(m_szShellOld);
887dd7cddfSDavid du Colombier 	m_szShellOld[0] = '\0';
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier 	if (strlen(m_szFileNew))
917dd7cddfSDavid du Colombier 		DeleteFile(m_szFileNew);
927dd7cddfSDavid du Colombier 	m_szFileNew[0] = '\0';
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier 
SetMessageFunction(void (* fn)(const char *))967dd7cddfSDavid du Colombier void CInstall::SetMessageFunction(void(*fn)(const char *))
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier 	AddMessageFn = fn;
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier 
AddMessage(const char * message)1017dd7cddfSDavid du Colombier void CInstall::AddMessage(const char *message)
1027dd7cddfSDavid du Colombier {
1037dd7cddfSDavid du Colombier 	if (AddMessageFn)
1047dd7cddfSDavid du Colombier 		(*AddMessageFn)(message);
1057dd7cddfSDavid du Colombier }
1067dd7cddfSDavid du Colombier 
SetTargetDir(const char * szTargetDir)1077dd7cddfSDavid du Colombier void CInstall::SetTargetDir(const char *szTargetDir)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier 	strcpy(m_szTargetDir, szTargetDir);
1107dd7cddfSDavid du Colombier 	// remove trailing backslash
1117dd7cddfSDavid du Colombier 	char *p;
1127dd7cddfSDavid du Colombier 	p = m_szTargetDir + strlen(m_szTargetDir) - 1;
1137dd7cddfSDavid du Colombier 	if (*p == '\\')
1147dd7cddfSDavid du Colombier 		*p = '\0';
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier 
SetTargetGroup(const char * szTargetGroup)1177dd7cddfSDavid du Colombier void CInstall::SetTargetGroup(const char *szTargetGroup)
1187dd7cddfSDavid du Colombier {
1197dd7cddfSDavid du Colombier 	strcpy(m_szTargetGroup, szTargetGroup);
1207dd7cddfSDavid du Colombier 	// remove trailing backslash
1217dd7cddfSDavid du Colombier 	char *p;
1227dd7cddfSDavid du Colombier 	p = m_szTargetGroup + strlen(m_szTargetGroup) - 1;
1237dd7cddfSDavid du Colombier 	if (*p == '\\')
1247dd7cddfSDavid du Colombier 		*p = '\0';
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
GetMainDir()1277dd7cddfSDavid du Colombier const char *CInstall::GetMainDir()
1287dd7cddfSDavid du Colombier {
1297dd7cddfSDavid du Colombier 	return m_szMainDir;
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier 
GetUninstallName()1327dd7cddfSDavid du Colombier const char *CInstall::GetUninstallName()
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier 	return m_szUninstallName;
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier 
Init(const char * szSourceDir,const char * szFileList)1377dd7cddfSDavid du Colombier BOOL CInstall::Init(const char *szSourceDir, const char *szFileList)
1387dd7cddfSDavid du Colombier {
1397dd7cddfSDavid du Colombier 	FILE *f;
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier 	strcpy(m_szSourceDir, szSourceDir);
1427dd7cddfSDavid du Colombier 	// remove trailing backslash
1437dd7cddfSDavid du Colombier 	char *p;
1447dd7cddfSDavid du Colombier 	p = m_szSourceDir + strlen(m_szSourceDir) - 1;
1457dd7cddfSDavid du Colombier 	if (*p == '\\')
1467dd7cddfSDavid du Colombier 		*p = '\0';
1477dd7cddfSDavid du Colombier 	strcpy(m_szFileList, szFileList);
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	m_szRegistryNew[0] = m_szRegistryOld[0] =
1507dd7cddfSDavid du Colombier 		m_szShellNew[0] = m_szShellOld[0] =
1517dd7cddfSDavid du Colombier 		m_szFileNew[0] = '\0';
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier 	// Open list of files
1547dd7cddfSDavid du Colombier 	SetCurrentDirectory(m_szSourceDir);
1557dd7cddfSDavid du Colombier 	f = fopen(m_szFileList, "r");
1567dd7cddfSDavid du Colombier 	if (f == (FILE *)NULL) {
1577dd7cddfSDavid du Colombier 		char buf[MAXSTR];
1587dd7cddfSDavid du Colombier 		wsprintf(buf, "Failed to open \042%s\042\n", m_szFileList);
1597dd7cddfSDavid du Colombier 		AddMessage(buf);
1607dd7cddfSDavid du Colombier 		return FALSE;
1617dd7cddfSDavid du Colombier 	}
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier 	// get application and directory name
1647dd7cddfSDavid du Colombier 	m_szUninstallName[0] = '\0';
1657dd7cddfSDavid du Colombier 	if (!fgets(m_szUninstallName, sizeof(m_szUninstallName), f)) {
1667dd7cddfSDavid du Colombier 		AddMessage("Invalid file list\n");
1677dd7cddfSDavid du Colombier 		fclose(f);
1687dd7cddfSDavid du Colombier 		return FALSE;
1697dd7cddfSDavid du Colombier 	}
1707dd7cddfSDavid du Colombier 	if (*m_szUninstallName )
1717dd7cddfSDavid du Colombier 		m_szUninstallName[strlen(m_szUninstallName)-1] = '\0';
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier 	m_szMainDir[0] = '\0';
1747dd7cddfSDavid du Colombier 	if (!fgets(m_szMainDir, sizeof(m_szMainDir), f)) {
1757dd7cddfSDavid du Colombier 		AddMessage("Invalid file list\n");
1767dd7cddfSDavid du Colombier 		fclose(f);
1777dd7cddfSDavid du Colombier 		return FALSE;
1787dd7cddfSDavid du Colombier 	}
1797dd7cddfSDavid du Colombier 	if (*m_szMainDir )
1807dd7cddfSDavid du Colombier 		m_szMainDir[strlen(m_szMainDir)-1] = '\0';
1817dd7cddfSDavid du Colombier 	fclose(f);
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier 	// Create log directory
1847dd7cddfSDavid du Colombier 	strcpy(m_szLogDir, m_szTargetDir);
1857dd7cddfSDavid du Colombier 	strcat(m_szLogDir, "\\");
1867dd7cddfSDavid du Colombier 	strcat(m_szLogDir, m_szMainDir);
1877dd7cddfSDavid du Colombier 	MakeDir(m_szLogDir);
1887dd7cddfSDavid du Colombier 
1897dd7cddfSDavid du Colombier 	return TRUE;
1907dd7cddfSDavid du Colombier }
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier //////////////////////////////////////////
1947dd7cddfSDavid du Colombier // File installation methods
1957dd7cddfSDavid du Colombier 
InstallFiles(BOOL bNoCopy,BOOL * pbQuit)1967dd7cddfSDavid du Colombier BOOL CInstall::InstallFiles(BOOL bNoCopy, BOOL *pbQuit)
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier 	char szLogNew[MAXSTR];
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier 	AddMessage(bNoCopy ? "Checking" : "Copying");
2017dd7cddfSDavid du Colombier 	AddMessage(" files listed in ");
2027dd7cddfSDavid du Colombier 	AddMessage(m_szFileList);
2037dd7cddfSDavid du Colombier 	AddMessage("\n");
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	// Open list of files
2067dd7cddfSDavid du Colombier 	SetCurrentDirectory(m_szSourceDir);
2077dd7cddfSDavid du Colombier 	FILE *f = fopen(m_szFileList, "r");
2087dd7cddfSDavid du Colombier 	if (f == (FILE *)NULL) {
2097dd7cddfSDavid du Colombier 		AddMessage("Failed to open \042");
2107dd7cddfSDavid du Colombier 		AddMessage(m_szFileList);
2117dd7cddfSDavid du Colombier 		AddMessage("\042\n");
2127dd7cddfSDavid du Colombier 		return FALSE;
2137dd7cddfSDavid du Colombier 	}
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier 	// skip application and directory name
2167dd7cddfSDavid du Colombier 	fgets(szLogNew, sizeof(szLogNew), f);
2177dd7cddfSDavid du Colombier 	fgets(szLogNew, sizeof(szLogNew), f);
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier 	// Create target log
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier 	m_fLogNew = MakeTemp(m_szFileNew);
2227dd7cddfSDavid du Colombier 	if (!m_fLogNew) {
2237dd7cddfSDavid du Colombier 		AddMessage("Failed to create FileNew temporary file\n");
2247dd7cddfSDavid du Colombier 		return FALSE;
2257dd7cddfSDavid du Colombier 	}
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier 	// Copy files
2287dd7cddfSDavid du Colombier 	char line[MAXSTR];
2297dd7cddfSDavid du Colombier 	while (fgets(line, sizeof(line), f) != (char *)NULL) {
2307dd7cddfSDavid du Colombier 		if (*pbQuit)
2317dd7cddfSDavid du Colombier 			return FALSE;
2327dd7cddfSDavid du Colombier 		if (*line)
2337dd7cddfSDavid du Colombier 			line[strlen(line)-1] = '\0';
2347dd7cddfSDavid du Colombier 		if (!InstallFile(line, bNoCopy)) {
2357dd7cddfSDavid du Colombier 			fclose(f);
2367dd7cddfSDavid du Colombier 			fclose(m_fLogNew);
2377dd7cddfSDavid du Colombier 			return FALSE;
2387dd7cddfSDavid du Colombier 		}
2397dd7cddfSDavid du Colombier 	}
2407dd7cddfSDavid du Colombier 	fclose(f);
2417dd7cddfSDavid du Colombier 	fclose(m_fLogNew);
2427dd7cddfSDavid du Colombier 	m_fLogNew = NULL;
2437dd7cddfSDavid du Colombier 	return TRUE;
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier 
AppendFileNew(const char * filename)247*593dc095SDavid du Colombier void CInstall::AppendFileNew(const char *filename)
248*593dc095SDavid du Colombier {
249*593dc095SDavid du Colombier     FILE *f;
250*593dc095SDavid du Colombier     /* mark backup file for uninstall */
251*593dc095SDavid du Colombier     if ((f = fopen(m_szFileNew, "a")) != (FILE *)NULL) {
252*593dc095SDavid du Colombier 	fputs(filename, f);
253*593dc095SDavid du Colombier 	fputs("\n", f);
254*593dc095SDavid du Colombier 	fclose(f);
255*593dc095SDavid du Colombier     }
256*593dc095SDavid du Colombier }
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier // recursive mkdir
2597dd7cddfSDavid du Colombier // requires a full path to be specified, so ignores root \
2607dd7cddfSDavid du Colombier // apart from root \, must not contain trailing \
2617dd7cddfSDavid du Colombier // Examples:
2627dd7cddfSDavid du Colombier //  c:\          (OK, but useless)
2637dd7cddfSDavid du Colombier //  c:\gstools   (OK)
2647dd7cddfSDavid du Colombier //  c:\gstools\  (incorrect)
2657dd7cddfSDavid du Colombier //  c:gstools    (incorrect)
2667dd7cddfSDavid du Colombier //  gstools      (incorrect)
2677dd7cddfSDavid du Colombier // The following UNC names should work,
2687dd7cddfSDavid du Colombier // but didn't under Win3.1 because gs_chdir wouldn't accept UNC names
2697dd7cddfSDavid du Colombier // Needs to be tested under Windows 95.
2707dd7cddfSDavid du Colombier //  \\server\sharename\gstools    (OK)
2717dd7cddfSDavid du Colombier //  \\server\sharename\           (OK, but useless)
2727dd7cddfSDavid du Colombier //
2737dd7cddfSDavid du Colombier 
MakeDir(const char * dirname)2747dd7cddfSDavid du Colombier BOOL CInstall::MakeDir(const char *dirname)
2757dd7cddfSDavid du Colombier {
2767dd7cddfSDavid du Colombier 	char newdir[MAXSTR];
2777dd7cddfSDavid du Colombier 	const char *p;
2787dd7cddfSDavid du Colombier     if (strlen(dirname) < 3)
2797dd7cddfSDavid du Colombier         return -1;
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier     if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') {
2827dd7cddfSDavid du Colombier         // drive mapped path
2837dd7cddfSDavid du Colombier         p = dirname+3;
2847dd7cddfSDavid du Colombier     }
2857dd7cddfSDavid du Colombier     else if (dirname[1]=='\\' && dirname[1]=='\\') {
2867dd7cddfSDavid du Colombier         // UNC path
2877dd7cddfSDavid du Colombier         p = strchr(dirname+2, '\\');    // skip servername
2887dd7cddfSDavid du Colombier         if (p == NULL)
2897dd7cddfSDavid du Colombier             return -1;
2907dd7cddfSDavid du Colombier         p++;
2917dd7cddfSDavid du Colombier         p = strchr(p, '\\');            // skip sharename
2927dd7cddfSDavid du Colombier         if (p == NULL)
2937dd7cddfSDavid du Colombier             return -1;
2947dd7cddfSDavid du Colombier     }
2957dd7cddfSDavid du Colombier     else {
2967dd7cddfSDavid du Colombier         // not full path so error
2977dd7cddfSDavid du Colombier         return -1;
2987dd7cddfSDavid du Colombier     }
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier     while (1) {
3017dd7cddfSDavid du Colombier         strncpy(newdir, dirname, (int)(p-dirname));
3027dd7cddfSDavid du Colombier         newdir[(int)(p-dirname)] = '\0';
3037dd7cddfSDavid du Colombier         if (chdir(newdir)) {
3047dd7cddfSDavid du Colombier             if (mkdir(newdir))
3057dd7cddfSDavid du Colombier                 return -1;
3067dd7cddfSDavid du Colombier         }
3077dd7cddfSDavid du Colombier         p++;
3087dd7cddfSDavid du Colombier         if (p >= dirname + strlen(dirname))
3097dd7cddfSDavid du Colombier             break;              // all done
3107dd7cddfSDavid du Colombier         p = strchr(p, '\\');
3117dd7cddfSDavid du Colombier         if (p == NULL)
3127dd7cddfSDavid du Colombier             p = dirname + strlen(dirname);
3137dd7cddfSDavid du Colombier     }
3147dd7cddfSDavid du Colombier 
3157dd7cddfSDavid du Colombier     return SetCurrentDirectory(dirname);
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier 
ResetReadonly(const char * filename)318*593dc095SDavid du Colombier void CInstall::ResetReadonly(const char *filename)
319*593dc095SDavid du Colombier {
320*593dc095SDavid du Colombier     DWORD dwAttr = GetFileAttributes(filename);
321*593dc095SDavid du Colombier     if (dwAttr & FILE_ATTRIBUTE_READONLY)
322*593dc095SDavid du Colombier         SetFileAttributes(filename, dwAttr & (~FILE_ATTRIBUTE_READONLY));
323*593dc095SDavid du Colombier }
324*593dc095SDavid du Colombier 
InstallFile(char * filename,BOOL bNoCopy)3257dd7cddfSDavid du Colombier BOOL CInstall::InstallFile(char *filename, BOOL bNoCopy)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier 	char existing_name[MAXSTR];
3287dd7cddfSDavid du Colombier 	char new_name[MAXSTR];
3297dd7cddfSDavid du Colombier 	char dir_name[MAXSTR];
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier 	strcpy(existing_name, m_szSourceDir);
3327dd7cddfSDavid du Colombier 	strcat(existing_name, "\\");
3337dd7cddfSDavid du Colombier 	strcat(existing_name, filename);
3347dd7cddfSDavid du Colombier 	strcpy(new_name, m_szTargetDir);
3357dd7cddfSDavid du Colombier 	strcat(new_name, "\\");
3367dd7cddfSDavid du Colombier 	strcat(new_name, filename);
3377dd7cddfSDavid du Colombier 	strcpy(dir_name, new_name);
3387dd7cddfSDavid du Colombier 	char *p = strrchr(dir_name, '\\');
3397dd7cddfSDavid du Colombier 	if (p) {
3407dd7cddfSDavid du Colombier 		*p = '\0';
3417dd7cddfSDavid du Colombier 		if (!MakeDir(dir_name)) {
3427dd7cddfSDavid du Colombier 			AddMessage("Failed to make directory ");
3437dd7cddfSDavid du Colombier 			AddMessage(dir_name);
3447dd7cddfSDavid du Colombier 			AddMessage("\n");
3457dd7cddfSDavid du Colombier 			return FALSE;
3467dd7cddfSDavid du Colombier 		}
3477dd7cddfSDavid du Colombier 	}
3487dd7cddfSDavid du Colombier 	AddMessage("   ");
3497dd7cddfSDavid du Colombier 	AddMessage(new_name);
3507dd7cddfSDavid du Colombier 	AddMessage("\n");
3517dd7cddfSDavid du Colombier 
3527dd7cddfSDavid du Colombier 	if (bNoCopy) {
3537dd7cddfSDavid du Colombier 		// Don't copy files.  Leave them where they are.
3547dd7cddfSDavid du Colombier 		// Check that all files exist
3557dd7cddfSDavid du Colombier 		FILE *f;
3567dd7cddfSDavid du Colombier 		if ((f = fopen(existing_name, "r")) == (FILE *)NULL) {
3577dd7cddfSDavid du Colombier 			AddMessage("Missing file ");
3587dd7cddfSDavid du Colombier 			AddMessage(existing_name);
3597dd7cddfSDavid du Colombier 			AddMessage("\n");
3607dd7cddfSDavid du Colombier 			return FALSE;
3617dd7cddfSDavid du Colombier 		}
3627dd7cddfSDavid du Colombier 		fclose(f);
3637dd7cddfSDavid du Colombier 	}
3647dd7cddfSDavid du Colombier 	else {
3657dd7cddfSDavid du Colombier 		if (!CopyFile(existing_name, new_name, FALSE)) {
3667dd7cddfSDavid du Colombier 			char message[MAXSTR+MAXSTR+100];
3677dd7cddfSDavid du Colombier 			wsprintf(message, "Failed to copy file %s to %s\n",
3687dd7cddfSDavid du Colombier 				existing_name, new_name);
3697dd7cddfSDavid du Colombier 			AddMessage(message);
3707dd7cddfSDavid du Colombier 			return FALSE;
3717dd7cddfSDavid du Colombier 		}
372*593dc095SDavid du Colombier 		ResetReadonly(new_name);
3737dd7cddfSDavid du Colombier 		fputs(new_name, m_fLogNew);
3747dd7cddfSDavid du Colombier 		fputs("\n", m_fLogNew);
3757dd7cddfSDavid du Colombier 	}
3767dd7cddfSDavid du Colombier 
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier 	return TRUE;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier //////////////////////////////////////////
3827dd7cddfSDavid du Colombier // Shell methods
3837dd7cddfSDavid du Colombier 
StartMenuBegin()3847dd7cddfSDavid du Colombier BOOL CInstall::StartMenuBegin()
3857dd7cddfSDavid du Colombier {
3867dd7cddfSDavid du Colombier 	m_fLogNew = MakeTemp(m_szShellNew);
3877dd7cddfSDavid du Colombier 	if (!m_fLogNew) {
3887dd7cddfSDavid du Colombier 		AddMessage("Failed to create ShellNew temporary file\n");
3897dd7cddfSDavid du Colombier 		return FALSE;
3907dd7cddfSDavid du Colombier 	}
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier 	m_fLogOld = MakeTemp(m_szShellOld);
3937dd7cddfSDavid du Colombier 	if (!m_fLogOld) {
3947dd7cddfSDavid du Colombier 		AddMessage("Failed to create ShellNew temporary file\n");
3957dd7cddfSDavid du Colombier 		return FALSE;
3967dd7cddfSDavid du Colombier 	}
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 	// make folder if needed
3997dd7cddfSDavid du Colombier 	char szLink[MAXSTR];
4007dd7cddfSDavid du Colombier 	strcpy(szLink, m_szPrograms);
4017dd7cddfSDavid du Colombier 	strcat(szLink, "\\");
4027dd7cddfSDavid du Colombier 	strcat(szLink, m_szTargetGroup);
4037dd7cddfSDavid du Colombier 	if (chdir(szLink) != 0) {
4047dd7cddfSDavid du Colombier 		if (mkdir(szLink) != 0) {
4057dd7cddfSDavid du Colombier 			char buf[MAXSTR+64];
4067dd7cddfSDavid du Colombier 			wsprintf(buf, "Couldn't make Programs folder \042%s'042", szLink);
4077dd7cddfSDavid du Colombier 			AddMessage(buf);
4087dd7cddfSDavid du Colombier 			StartMenuEnd();
4097dd7cddfSDavid du Colombier 			return FALSE;
4107dd7cddfSDavid du Colombier 		}
4117dd7cddfSDavid du Colombier 	}
4127dd7cddfSDavid du Colombier 	else {
4137dd7cddfSDavid du Colombier 		fprintf(m_fLogOld, "Group=%s\n\n", szLink);
4147dd7cddfSDavid du Colombier 	}
4157dd7cddfSDavid du Colombier 	fprintf(m_fLogNew, "Group=%s\n\n", szLink);
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier 	return TRUE;
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier 
StartMenuEnd()4207dd7cddfSDavid du Colombier BOOL CInstall::StartMenuEnd()
4217dd7cddfSDavid du Colombier {
4227dd7cddfSDavid du Colombier 	if (m_fLogOld)
4237dd7cddfSDavid du Colombier 		fclose(m_fLogOld);
4247dd7cddfSDavid du Colombier 	m_fLogOld = NULL;
4257dd7cddfSDavid du Colombier 	if (m_fLogNew)
4267dd7cddfSDavid du Colombier 		fclose(m_fLogNew);
4277dd7cddfSDavid du Colombier 	m_fLogNew = NULL;
4287dd7cddfSDavid du Colombier 	return TRUE;
4297dd7cddfSDavid du Colombier }
4307dd7cddfSDavid du Colombier 
StartMenuAdd(const char * szDescription,const char * szProgram,const char * szArguments)4317dd7cddfSDavid du Colombier BOOL CInstall::StartMenuAdd(const char *szDescription,
4327dd7cddfSDavid du Colombier 							const char *szProgram, const char *szArguments)
4337dd7cddfSDavid du Colombier {
4347dd7cddfSDavid du Colombier 	if (!CreateShellLink(szDescription, szProgram, szArguments)) {
4357dd7cddfSDavid du Colombier 		AddMessage("Couldn't make shell link for ");
4367dd7cddfSDavid du Colombier 		AddMessage(szDescription);
4377dd7cddfSDavid du Colombier 		AddMessage("\n");
4387dd7cddfSDavid du Colombier 		StartMenuEnd();
4397dd7cddfSDavid du Colombier 		return FALSE;
4407dd7cddfSDavid du Colombier 	}
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier 	return TRUE;
4437dd7cddfSDavid du Colombier }
4447dd7cddfSDavid du Colombier 
4457dd7cddfSDavid du Colombier 
CreateShellLink(LPCSTR description,LPCSTR program,LPCSTR arguments,LPCSTR icon,int nIconIndex)4467dd7cddfSDavid du Colombier BOOL CInstall::CreateShellLink(LPCSTR description, LPCSTR program,
4477dd7cddfSDavid du Colombier 							   LPCSTR arguments, LPCSTR icon, int nIconIndex)
4487dd7cddfSDavid du Colombier {
4497dd7cddfSDavid du Colombier 	HRESULT hres;
4507dd7cddfSDavid du Colombier 	IShellLink* psl;
4517dd7cddfSDavid du Colombier 	CHAR szLink[MAXSTR];
4527dd7cddfSDavid du Colombier 	strcpy(szLink, m_szPrograms);
4537dd7cddfSDavid du Colombier 	strcat(szLink, "\\");
4547dd7cddfSDavid du Colombier 	strcat(szLink, m_szTargetGroup);
4557dd7cddfSDavid du Colombier 	strcat(szLink, "\\");
4567dd7cddfSDavid du Colombier 	strcat(szLink, description);
4577dd7cddfSDavid du Colombier 	strcat(szLink, ".LNK");
4587dd7cddfSDavid du Colombier 	AddMessage("Adding shell link\n   ");
4597dd7cddfSDavid du Colombier 	AddMessage(szLink);
4607dd7cddfSDavid du Colombier 	AddMessage("\n");
4617dd7cddfSDavid du Colombier 
4627dd7cddfSDavid du Colombier 	// Ensure string is UNICODE.
4637dd7cddfSDavid du Colombier 	WCHAR wsz[MAX_PATH];
4647dd7cddfSDavid du Colombier 	MultiByteToWideChar(CP_ACP, 0, szLink, -1, wsz, MAX_PATH);
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier 	// Save old shell link
4677dd7cddfSDavid du Colombier 
4687dd7cddfSDavid du Colombier 	// Get a pointer to the IShellLink interface.
4697dd7cddfSDavid du Colombier 	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
4707dd7cddfSDavid du Colombier 		IID_IShellLink, (void **)&psl);
4717dd7cddfSDavid du Colombier 	if (SUCCEEDED(hres))    {
4727dd7cddfSDavid du Colombier 		IPersistFile* ppf;
4737dd7cddfSDavid du Colombier 		// Query IShellLink for the IPersistFile interface.
4747dd7cddfSDavid du Colombier 		hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
4757dd7cddfSDavid du Colombier 		if (SUCCEEDED(hres))       {
4767dd7cddfSDavid du Colombier 			// Load the shell link.
4777dd7cddfSDavid du Colombier 			hres = ppf->Load(wsz, STGM_READ);
4787dd7cddfSDavid du Colombier 			if (SUCCEEDED(hres)) {
4797dd7cddfSDavid du Colombier 				// Resolve the link.
4807dd7cddfSDavid du Colombier 				hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);
4817dd7cddfSDavid du Colombier 				if (SUCCEEDED(hres)) {
4827dd7cddfSDavid du Colombier 					// found it, so save details
4837dd7cddfSDavid du Colombier 					CHAR szTemp[MAXSTR];
4847dd7cddfSDavid du Colombier 					WIN32_FIND_DATA wfd;
4857dd7cddfSDavid du Colombier 					int i;
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier 
4887dd7cddfSDavid du Colombier 					fprintf(m_fLogOld, "Name=%s\n", szLink);
4897dd7cddfSDavid du Colombier 					hres = psl->GetPath(szTemp, MAXSTR, (WIN32_FIND_DATA *)&wfd,
4907dd7cddfSDavid du Colombier 						SLGP_SHORTPATH );
4917dd7cddfSDavid du Colombier 					if (SUCCEEDED(hres))
4927dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "Path=%s\n", szTemp);
4937dd7cddfSDavid du Colombier 					hres = psl->GetDescription(szTemp, MAXSTR);
4947dd7cddfSDavid du Colombier 					if (SUCCEEDED(hres))
4957dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "Description=%s\n", szTemp);
4967dd7cddfSDavid du Colombier 					hres = psl->GetArguments(szTemp, MAXSTR);
4977dd7cddfSDavid du Colombier 					if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
4987dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "Arguments=%s\n", szTemp);
4997dd7cddfSDavid du Colombier 					hres = psl->GetWorkingDirectory(szTemp, MAXSTR);
5007dd7cddfSDavid du Colombier 					if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
5017dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "Directory=%s\n", szTemp);
5027dd7cddfSDavid du Colombier 					hres = psl->GetIconLocation(szTemp, MAXSTR, &i);
5037dd7cddfSDavid du Colombier 					if (SUCCEEDED(hres) && (szTemp[0] != '\0')) {
5047dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "IconLocation=%s\n", szTemp);
5057dd7cddfSDavid du Colombier 						fprintf(m_fLogOld, "IconIndex=%d\n", i);
5067dd7cddfSDavid du Colombier 					}
5077dd7cddfSDavid du Colombier 					fprintf(m_fLogOld, "\n");
5087dd7cddfSDavid du Colombier 				}
5097dd7cddfSDavid du Colombier 			}
5107dd7cddfSDavid du Colombier 			// Release pointer to IPersistFile.
5117dd7cddfSDavid du Colombier 			ppf->Release();
5127dd7cddfSDavid du Colombier 		}
5137dd7cddfSDavid du Colombier 		// Release pointer to IShellLink.
5147dd7cddfSDavid du Colombier 		psl->Release();
5157dd7cddfSDavid du Colombier 	}
5167dd7cddfSDavid du Colombier 
5177dd7cddfSDavid du Colombier 
5187dd7cddfSDavid du Colombier 	// Save new shell link
5197dd7cddfSDavid du Colombier 
5207dd7cddfSDavid du Colombier 	// Get a pointer to the IShellLink interface.
5217dd7cddfSDavid du Colombier 	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
5227dd7cddfSDavid du Colombier 		IID_IShellLink, (void **)&psl);
5237dd7cddfSDavid du Colombier 	if (SUCCEEDED(hres))    {
5247dd7cddfSDavid du Colombier 		IPersistFile* ppf;
5257dd7cddfSDavid du Colombier 		// Query IShellLink for the IPersistFile interface for
5267dd7cddfSDavid du Colombier 		// saving the shell link in persistent storage.
5277dd7cddfSDavid du Colombier 		hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
5287dd7cddfSDavid du Colombier 		if (SUCCEEDED(hres)) {
5297dd7cddfSDavid du Colombier 			fprintf(m_fLogNew, "Name=%s\n", szLink);
5307dd7cddfSDavid du Colombier 
5317dd7cddfSDavid du Colombier 			// Set the path to the shell link target.
5327dd7cddfSDavid du Colombier 			hres = psl->SetPath(program);
5337dd7cddfSDavid du Colombier 			if (!SUCCEEDED(hres))
5347dd7cddfSDavid du Colombier 				AddMessage("SetPath failed!");
5357dd7cddfSDavid du Colombier 			fprintf(m_fLogNew, "Path=%s\n", program);
5367dd7cddfSDavid du Colombier 			// Set the description of the shell link.
5377dd7cddfSDavid du Colombier 			hres = psl->SetDescription(description);
5387dd7cddfSDavid du Colombier 			if (!SUCCEEDED(hres))
5397dd7cddfSDavid du Colombier 				AddMessage("SetDescription failed!");
5407dd7cddfSDavid du Colombier 			fprintf(m_fLogNew, "Description=%s\n", description);
5417dd7cddfSDavid du Colombier 			if (arguments != (LPCSTR)NULL) {
5427dd7cddfSDavid du Colombier 				// Set the arguments of the shell link target.
5437dd7cddfSDavid du Colombier 				hres = psl->SetArguments(arguments);
5447dd7cddfSDavid du Colombier 				if (!SUCCEEDED(hres))
5457dd7cddfSDavid du Colombier 					AddMessage("SetArguments failed!");
5467dd7cddfSDavid du Colombier 				fprintf(m_fLogNew, "Arguments=%s\n", arguments);
5477dd7cddfSDavid du Colombier 			}
5487dd7cddfSDavid du Colombier 			if (icon != (LPCSTR)NULL) {
5497dd7cddfSDavid du Colombier 				// Set the arguments of the shell link target.
5507dd7cddfSDavid du Colombier 				hres = psl->SetIconLocation(icon, nIconIndex);
5517dd7cddfSDavid du Colombier 				if (!SUCCEEDED(hres))
5527dd7cddfSDavid du Colombier 					AddMessage("SetIconLocation failed!");
5537dd7cddfSDavid du Colombier 				fprintf(m_fLogNew, "IconLocation=%s\n", icon);
5547dd7cddfSDavid du Colombier 				fprintf(m_fLogNew, "IconIndex=%d\n", nIconIndex);
5557dd7cddfSDavid du Colombier 			}
5567dd7cddfSDavid du Colombier 
5577dd7cddfSDavid du Colombier 			// Save the link via the IPersistFile::Save method.
5587dd7cddfSDavid du Colombier 			hres = ppf->Save(wsz, TRUE);
5597dd7cddfSDavid du Colombier 			// Release pointer to IPersistFile.
5607dd7cddfSDavid du Colombier 			ppf->Release();
5617dd7cddfSDavid du Colombier 		}
5627dd7cddfSDavid du Colombier 		// Release pointer to IShellLink.
5637dd7cddfSDavid du Colombier 		psl->Release();
5647dd7cddfSDavid du Colombier 		fprintf(m_fLogNew, "\n");
5657dd7cddfSDavid du Colombier 	}
5667dd7cddfSDavid du Colombier 
5677dd7cddfSDavid du Colombier 	return (hres == 0);
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier 
5707dd7cddfSDavid du Colombier 
5717dd7cddfSDavid du Colombier //////////////////////////////////////////
5727dd7cddfSDavid du Colombier // Registry methods
5737dd7cddfSDavid du Colombier 
5747dd7cddfSDavid du Colombier void
reg_quote(char * d,const char * s)5757dd7cddfSDavid du Colombier reg_quote(char *d, const char *s)
5767dd7cddfSDavid du Colombier {
5777dd7cddfSDavid du Colombier     while (*s) {
5787dd7cddfSDavid du Colombier 		if (*s == '\\')
5797dd7cddfSDavid du Colombier 			*d++ = '\\';
5807dd7cddfSDavid du Colombier 		*d++ = *s++;
5817dd7cddfSDavid du Colombier     }
5827dd7cddfSDavid du Colombier     *d = *s;
5837dd7cddfSDavid du Colombier }
5847dd7cddfSDavid du Colombier 
UpdateRegistryBegin()5857dd7cddfSDavid du Colombier BOOL CInstall::UpdateRegistryBegin()
5867dd7cddfSDavid du Colombier {
5877dd7cddfSDavid du Colombier 	const char regheader[]="REGEDIT4\n";
5887dd7cddfSDavid du Colombier 	m_fLogNew = MakeTemp(m_szRegistryNew);
5897dd7cddfSDavid du Colombier 	if (!m_fLogNew) {
5907dd7cddfSDavid du Colombier 		AddMessage("Failed to create RegistryNew temporary file\n");
5917dd7cddfSDavid du Colombier 		return FALSE;
5927dd7cddfSDavid du Colombier 	}
5937dd7cddfSDavid du Colombier 	fputs(regheader, m_fLogNew);
5947dd7cddfSDavid du Colombier 
5957dd7cddfSDavid du Colombier 	m_fLogOld = MakeTemp(m_szRegistryOld);
5967dd7cddfSDavid du Colombier 	if (!m_fLogOld) {
5977dd7cddfSDavid du Colombier 		AddMessage("Failed to create RegistryOld temporary file\n");
5987dd7cddfSDavid du Colombier 		UpdateRegistryEnd();
5997dd7cddfSDavid du Colombier 		return FALSE;
6007dd7cddfSDavid du Colombier 	}
6017dd7cddfSDavid du Colombier 	fputs(regheader, m_fLogOld);
6027dd7cddfSDavid du Colombier 
6037dd7cddfSDavid du Colombier 	return TRUE;
6047dd7cddfSDavid du Colombier }
6057dd7cddfSDavid du Colombier 
UpdateRegistryEnd()6067dd7cddfSDavid du Colombier BOOL CInstall::UpdateRegistryEnd()
6077dd7cddfSDavid du Colombier {
6087dd7cddfSDavid du Colombier 	if (m_fLogNew)
6097dd7cddfSDavid du Colombier 		fclose(m_fLogNew);
6107dd7cddfSDavid du Colombier 	m_fLogNew = NULL;
6117dd7cddfSDavid du Colombier 	if (m_fLogOld)
6127dd7cddfSDavid du Colombier 		fclose(m_fLogOld);
6137dd7cddfSDavid du Colombier 	m_fLogOld = NULL;
6147dd7cddfSDavid du Colombier 	return TRUE;
6157dd7cddfSDavid du Colombier }
6167dd7cddfSDavid du Colombier 
UpdateRegistryKey(const char * product,const char * version)6177dd7cddfSDavid du Colombier BOOL CInstall::UpdateRegistryKey(const char *product, const char *version)
6187dd7cddfSDavid du Colombier {
6197dd7cddfSDavid du Colombier 	const char hkey_name[] = "HKEY_LOCAL_MACHINE";
6207dd7cddfSDavid du Colombier 	const HKEY hkey_key = HKEY_LOCAL_MACHINE;
6217dd7cddfSDavid du Colombier 	const char key_format[] = "\n[%s\\%s]\n";
6227dd7cddfSDavid du Colombier 
6237dd7cddfSDavid du Colombier 	/* Create default registry entries */
6247dd7cddfSDavid du Colombier 	HKEY hkey;
6257dd7cddfSDavid du Colombier 	LONG lrc;
6267dd7cddfSDavid du Colombier 	char name[MAXSTR];
6277dd7cddfSDavid du Colombier 
6287dd7cddfSDavid du Colombier 	// Create/Open application key
6297dd7cddfSDavid du Colombier 	sprintf(name, "SOFTWARE\\%s", product);
6307dd7cddfSDavid du Colombier 	lrc = RegOpenKey(hkey_key, name, &hkey);
6317dd7cddfSDavid du Colombier 	if (lrc == ERROR_SUCCESS) {
6327dd7cddfSDavid du Colombier 		fprintf(m_fLogOld, key_format, hkey_name, name);
6337dd7cddfSDavid du Colombier 	}
6347dd7cddfSDavid du Colombier 	else {
6357dd7cddfSDavid du Colombier 		lrc = RegCreateKey(hkey_key, name, &hkey);
6367dd7cddfSDavid du Colombier 		if (lrc == ERROR_SUCCESS)
6377dd7cddfSDavid du Colombier 			fprintf(m_fLogNew, key_format, hkey_name, name);
6387dd7cddfSDavid du Colombier 	}
6397dd7cddfSDavid du Colombier 	if (lrc == ERROR_SUCCESS)
6407dd7cddfSDavid du Colombier 		RegCloseKey(hkey);
6417dd7cddfSDavid du Colombier 
6427dd7cddfSDavid du Colombier 	// Create/Open application version key
6437dd7cddfSDavid du Colombier 	sprintf(name, "SOFTWARE\\%s\\%s", product, version);
6447dd7cddfSDavid du Colombier 
6457dd7cddfSDavid du Colombier 	AddMessage("   ");
6467dd7cddfSDavid du Colombier 	AddMessage(hkey_name);
6477dd7cddfSDavid du Colombier 	AddMessage("\\");
6487dd7cddfSDavid du Colombier 	AddMessage(name);
6497dd7cddfSDavid du Colombier 	AddMessage("\n");
6507dd7cddfSDavid du Colombier 	lrc = RegOpenKey(hkey_key, name, &hkey);
6517dd7cddfSDavid du Colombier 	if (lrc == ERROR_SUCCESS)
6527dd7cddfSDavid du Colombier 		fprintf(m_fLogOld, key_format, hkey_name, name);
6537dd7cddfSDavid du Colombier 	else
6547dd7cddfSDavid du Colombier 		lrc = RegCreateKey(hkey_key, name, &hkey);
6557dd7cddfSDavid du Colombier 	if (lrc == ERROR_SUCCESS) {
6567dd7cddfSDavid du Colombier 		fprintf(m_fLogNew, key_format, hkey_name, name);
6577dd7cddfSDavid du Colombier 	}
6587dd7cddfSDavid du Colombier 	else {
6597dd7cddfSDavid du Colombier 		UpdateRegistryEnd();
6607dd7cddfSDavid du Colombier 	}
6617dd7cddfSDavid du Colombier 	return TRUE;
6627dd7cddfSDavid du Colombier }
6637dd7cddfSDavid du Colombier 
UpdateRegistryValue(const char * product,const char * version,const char * name,const char * value)6647dd7cddfSDavid du Colombier BOOL CInstall::UpdateRegistryValue(const char *product, const char *version,
6657dd7cddfSDavid du Colombier 								   const char *name, const char *value)
6667dd7cddfSDavid du Colombier {
6677dd7cddfSDavid du Colombier 	char appver[MAXSTR];
6687dd7cddfSDavid du Colombier 	BOOL flag = FALSE;
6697dd7cddfSDavid du Colombier 	HKEY hkey;
6707dd7cddfSDavid du Colombier 	// Open application/version key
6717dd7cddfSDavid du Colombier 	sprintf(appver, "SOFTWARE\\%s\\%s", product, version);
6727dd7cddfSDavid du Colombier 
6737dd7cddfSDavid du Colombier 	if (RegOpenKey(HKEY_LOCAL_MACHINE, appver, &hkey)
6747dd7cddfSDavid du Colombier 		== ERROR_SUCCESS) {
6757dd7cddfSDavid du Colombier 		flag = SetRegistryValue(hkey, name, value);
6767dd7cddfSDavid du Colombier 		RegCloseKey(hkey);
6777dd7cddfSDavid du Colombier 	}
6787dd7cddfSDavid du Colombier 
6797dd7cddfSDavid du Colombier 	return flag;
6807dd7cddfSDavid du Colombier }
6817dd7cddfSDavid du Colombier 
SetRegistryValue(HKEY hkey,const char * value_name,const char * value)6827dd7cddfSDavid du Colombier BOOL CInstall::SetRegistryValue(HKEY hkey, const char *value_name, const char *value)
6837dd7cddfSDavid du Colombier {
6847dd7cddfSDavid du Colombier 	char buf[MAXSTR];
6857dd7cddfSDavid du Colombier 	char qbuf[MAXSTR];
6867dd7cddfSDavid du Colombier 	DWORD cbData;
6877dd7cddfSDavid du Colombier 	DWORD keytype;
6887dd7cddfSDavid du Colombier 
6897dd7cddfSDavid du Colombier 	cbData = sizeof(buf);
6907dd7cddfSDavid du Colombier 	keytype =  REG_SZ;
6917dd7cddfSDavid du Colombier 	if (RegQueryValueEx(hkey, value_name, 0, &keytype,
6927dd7cddfSDavid du Colombier 		(LPBYTE)buf, &cbData) == ERROR_SUCCESS) {
6937dd7cddfSDavid du Colombier 		reg_quote(qbuf, buf);
6947dd7cddfSDavid du Colombier 		fprintf(m_fLogOld, "\042%s\042=\042%s\042\n", value_name, qbuf);
6957dd7cddfSDavid du Colombier 	}
6967dd7cddfSDavid du Colombier 	reg_quote(qbuf, value);
6977dd7cddfSDavid du Colombier 	fprintf(m_fLogNew, "\042%s\042=\042%s\042\n", value_name, qbuf);
6987dd7cddfSDavid du Colombier 	AddMessage("      ");
6997dd7cddfSDavid du Colombier 	AddMessage(value_name);
7007dd7cddfSDavid du Colombier 	AddMessage("=");
7017dd7cddfSDavid du Colombier 	AddMessage(value);
7027dd7cddfSDavid du Colombier 	AddMessage("\n");
7037dd7cddfSDavid du Colombier 	if (RegSetValueEx(hkey, value_name, 0, REG_SZ,
7047dd7cddfSDavid du Colombier 		(CONST BYTE *)value, strlen(value)+1) != ERROR_SUCCESS)
7057dd7cddfSDavid du Colombier 		return FALSE;
7067dd7cddfSDavid du Colombier 	return TRUE;
7077dd7cddfSDavid du Colombier }
7087dd7cddfSDavid du Colombier 
7097dd7cddfSDavid du Colombier ////////////////////////////////////
7107dd7cddfSDavid du Colombier // Uninstall
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier 
WriteUninstall(const char * szProg,BOOL bNoCopy)7137dd7cddfSDavid du Colombier BOOL CInstall::WriteUninstall(const char *szProg, BOOL bNoCopy)
7147dd7cddfSDavid du Colombier {
7157dd7cddfSDavid du Colombier 	LONG rc;
7167dd7cddfSDavid du Colombier 	HKEY hkey;
7177dd7cddfSDavid du Colombier 	HKEY hsubkey;
7187dd7cddfSDavid du Colombier 	char buffer[MAXSTR];
7197dd7cddfSDavid du Colombier 	char ungsprog[MAXSTR];
7207dd7cddfSDavid du Colombier 
7217dd7cddfSDavid du Colombier 	lstrcpy(ungsprog, m_szTargetDir);
7227dd7cddfSDavid du Colombier 	lstrcat(ungsprog, "\\");
7237dd7cddfSDavid du Colombier 	lstrcat(ungsprog, szProg);
7247dd7cddfSDavid du Colombier 
7257dd7cddfSDavid du Colombier 	lstrcpy(buffer, m_szSourceDir);
7267dd7cddfSDavid du Colombier 	lstrcat(buffer, "\\");
7277dd7cddfSDavid du Colombier 	lstrcat(buffer, szProg);
7287dd7cddfSDavid du Colombier 
7297dd7cddfSDavid du Colombier 	if (bNoCopy) {
7307dd7cddfSDavid du Colombier 		// Don't copy files.  Leave them where they are.
7317dd7cddfSDavid du Colombier 		// Check that all files exist
7327dd7cddfSDavid du Colombier 		FILE *f;
7337dd7cddfSDavid du Colombier 		if ((f = fopen(buffer, "r")) == (FILE *)NULL) {
7347dd7cddfSDavid du Colombier 			AddMessage("Missing file ");
7357dd7cddfSDavid du Colombier 			AddMessage(buffer);
7367dd7cddfSDavid du Colombier 			AddMessage("\n");
7377dd7cddfSDavid du Colombier 			return FALSE;
7387dd7cddfSDavid du Colombier 		}
7397dd7cddfSDavid du Colombier 		fclose(f);
7407dd7cddfSDavid du Colombier 	}
7417dd7cddfSDavid du Colombier 	else if (!CopyFile(buffer, ungsprog, FALSE)) {
7427dd7cddfSDavid du Colombier 		char message[MAXSTR+MAXSTR+100];
7437dd7cddfSDavid du Colombier 		wsprintf(message, "Failed to copy file %s to %s", buffer, ungsprog);
7447dd7cddfSDavid du Colombier 		AddMessage(message);
7457dd7cddfSDavid du Colombier 		return FALSE;
7467dd7cddfSDavid du Colombier 	}
747*593dc095SDavid du Colombier 	ResetReadonly(ungsprog);
7487dd7cddfSDavid du Colombier 
7497dd7cddfSDavid du Colombier 	/* write registry entries for uninstall */
7507dd7cddfSDavid du Colombier 	if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINSTALLKEY, 0,
7517dd7cddfSDavid du Colombier 		KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS) {
7527dd7cddfSDavid du Colombier 		/* failed to open key, so try to create it */
7537dd7cddfSDavid du Colombier         rc = RegCreateKey(HKEY_LOCAL_MACHINE, UNINSTALLKEY, &hkey);
7547dd7cddfSDavid du Colombier 	}
7557dd7cddfSDavid du Colombier 	if (rc == ERROR_SUCCESS) {
7567dd7cddfSDavid du Colombier 		// Uninstall key for program
7577dd7cddfSDavid du Colombier 		if (RegCreateKey(hkey, m_szUninstallName, &hsubkey) == ERROR_SUCCESS) {
7587dd7cddfSDavid du Colombier 			RegSetValueEx(hsubkey, DISPLAYNAMEKEY, 0, REG_SZ,
7597dd7cddfSDavid du Colombier 				(CONST BYTE *)m_szUninstallName, lstrlen(m_szUninstallName)+1);
7607dd7cddfSDavid du Colombier 			lstrcpy(buffer, ungsprog);
7617dd7cddfSDavid du Colombier 			lstrcat(buffer, " \042");
7627dd7cddfSDavid du Colombier 			lstrcat(buffer, m_szTargetDir);
7637dd7cddfSDavid du Colombier 			lstrcat(buffer, "\\");
7647dd7cddfSDavid du Colombier 			lstrcat(buffer, m_szMainDir);
7657dd7cddfSDavid du Colombier 			lstrcat(buffer, "\\");
7667dd7cddfSDavid du Colombier 			lstrcat(buffer, UNINSTALL_FILE);
7677dd7cddfSDavid du Colombier 			lstrcat(buffer, "\042");
7687dd7cddfSDavid du Colombier 			AddMessage("   ");
7697dd7cddfSDavid du Colombier 			AddMessage(m_szUninstallName);
7707dd7cddfSDavid du Colombier 			AddMessage("=");
7717dd7cddfSDavid du Colombier 			AddMessage(buffer);
7727dd7cddfSDavid du Colombier 			AddMessage("\n");
7737dd7cddfSDavid du Colombier 			RegSetValueEx(hsubkey, UNINSTALLSTRINGKEY, 0, REG_SZ,
7747dd7cddfSDavid du Colombier 				(CONST BYTE *)buffer, lstrlen(buffer)+1);
7757dd7cddfSDavid du Colombier 			RegCloseKey(hsubkey);
7767dd7cddfSDavid du Colombier 		}
7777dd7cddfSDavid du Colombier 
7787dd7cddfSDavid du Colombier 		RegCloseKey(hkey);
7797dd7cddfSDavid du Colombier 	}
7807dd7cddfSDavid du Colombier 	return TRUE;
7817dd7cddfSDavid du Colombier }
7827dd7cddfSDavid du Colombier 
7837dd7cddfSDavid du Colombier 
7847dd7cddfSDavid du Colombier void
CopyFileContents(FILE * df,FILE * sf)7857dd7cddfSDavid du Colombier CInstall::CopyFileContents(FILE *df, FILE *sf)
7867dd7cddfSDavid du Colombier {
7877dd7cddfSDavid du Colombier 	char buf[MAXSTR];
7887dd7cddfSDavid du Colombier 	int count;
7897dd7cddfSDavid du Colombier 	while ((count = fread(buf, 1, sizeof(buf), sf)) != 0)
7907dd7cddfSDavid du Colombier 		fwrite(buf, 1, count, df);
7917dd7cddfSDavid du Colombier }
7927dd7cddfSDavid du Colombier 
MakeTemp(char * fname)7937dd7cddfSDavid du Colombier FILE *CInstall::MakeTemp(char *fname)
7947dd7cddfSDavid du Colombier {
7957dd7cddfSDavid du Colombier 	char *temp;
7967dd7cddfSDavid du Colombier 	if ( (temp = getenv("TEMP")) == NULL )
7977dd7cddfSDavid du Colombier 		strcpy(fname, m_szTargetDir);
7987dd7cddfSDavid du Colombier 	else
7997dd7cddfSDavid du Colombier 		strcpy(fname, temp);
8007dd7cddfSDavid du Colombier 
8017dd7cddfSDavid du Colombier 	/* Prevent X's in path from being converted by mktemp. */
8027dd7cddfSDavid du Colombier 	for ( temp = fname; *temp; temp++ ) {
8037dd7cddfSDavid du Colombier 		*temp = (char)tolower(*temp);
8047dd7cddfSDavid du Colombier 		if (*temp == '/')
8057dd7cddfSDavid du Colombier 			*temp = '\\';
8067dd7cddfSDavid du Colombier 	}
8077dd7cddfSDavid du Colombier 	if ( strlen(fname) && (fname[strlen(fname)-1] != '\\') )
8087dd7cddfSDavid du Colombier 		strcat(fname, "\\");
8097dd7cddfSDavid du Colombier 
8107dd7cddfSDavid du Colombier 	strcat(fname, "gsXXXXXX");
8117dd7cddfSDavid du Colombier 	mktemp(fname);
8127dd7cddfSDavid du Colombier 	AddMessage("Creating temporary file ");
8137dd7cddfSDavid du Colombier 	AddMessage(fname);
8147dd7cddfSDavid du Colombier 	AddMessage("\n");
8157dd7cddfSDavid du Colombier 	return fopen(fname, "w");
8167dd7cddfSDavid du Colombier }
8177dd7cddfSDavid du Colombier 
MakeLog()8187dd7cddfSDavid du Colombier BOOL CInstall::MakeLog()
8197dd7cddfSDavid du Colombier {
8207dd7cddfSDavid du Colombier 	FILE *f, *lf;
8217dd7cddfSDavid du Colombier 	char szFileName[MAXSTR];
8227dd7cddfSDavid du Colombier 	char szLogDir[MAXSTR];
8237dd7cddfSDavid du Colombier 	strcpy(szLogDir, m_szTargetDir);
8247dd7cddfSDavid du Colombier 	strcat(szLogDir, "\\");
8257dd7cddfSDavid du Colombier 	strcat(szLogDir, m_szMainDir);
8267dd7cddfSDavid du Colombier 	strcat(szLogDir, "\\");
8277dd7cddfSDavid du Colombier 
8287dd7cddfSDavid du Colombier 	strcpy(szFileName, szLogDir);
8297dd7cddfSDavid du Colombier 	strcat(szFileName, UNINSTALL_FILE);
8307dd7cddfSDavid du Colombier 	lf = fopen(szFileName, "w");
8317dd7cddfSDavid du Colombier 	if (lf == (FILE *)NULL) {
8327dd7cddfSDavid du Colombier 		AddMessage("Can't create uninstall log");
8337dd7cddfSDavid du Colombier 		CleanUp();
8347dd7cddfSDavid du Colombier 		return FALSE;
8357dd7cddfSDavid du Colombier 	}
8367dd7cddfSDavid du Colombier 	fputs(szSection, lf);
8377dd7cddfSDavid du Colombier 	fputs("UninstallName\n", lf);
8387dd7cddfSDavid du Colombier 	fputs(m_szUninstallName, lf);
8397dd7cddfSDavid du Colombier 	fputs("\n\n", lf);
8407dd7cddfSDavid du Colombier 
8417dd7cddfSDavid du Colombier 	if (strlen(m_szRegistryNew) &&
8427dd7cddfSDavid du Colombier 		(f = fopen(m_szRegistryNew, "r")) != (FILE *)NULL) {
8437dd7cddfSDavid du Colombier 		fputs(szSection, lf);
8447dd7cddfSDavid du Colombier 		fputs("RegistryNew\n", lf);
8457dd7cddfSDavid du Colombier 		CopyFileContents(lf, f);
8467dd7cddfSDavid du Colombier 		fputs("\n", lf);
8477dd7cddfSDavid du Colombier 		fclose(f);
8487dd7cddfSDavid du Colombier 		DeleteFile(m_szRegistryNew);
8497dd7cddfSDavid du Colombier 		m_szRegistryNew[0] = '\0';
8507dd7cddfSDavid du Colombier 	}
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier 	if (strlen(m_szRegistryOld) &&
8537dd7cddfSDavid du Colombier 		(f = fopen(m_szRegistryOld, "r")) != (FILE *)NULL) {
8547dd7cddfSDavid du Colombier 		fputs(szSection, lf);
8557dd7cddfSDavid du Colombier 		fputs("RegistryOld\n", lf);
8567dd7cddfSDavid du Colombier 		CopyFileContents(lf, f);
8577dd7cddfSDavid du Colombier 		fputs("\n", lf);
8587dd7cddfSDavid du Colombier 		fclose(f);
8597dd7cddfSDavid du Colombier 		DeleteFile(m_szRegistryOld);
8607dd7cddfSDavid du Colombier 		m_szRegistryOld[0] = '\0';
8617dd7cddfSDavid du Colombier 	}
8627dd7cddfSDavid du Colombier 
8637dd7cddfSDavid du Colombier 	if (strlen(m_szShellNew) &&
8647dd7cddfSDavid du Colombier 		(f = fopen(m_szShellNew, "r")) != (FILE *)NULL) {
8657dd7cddfSDavid du Colombier 		fputs(szSection, lf);
8667dd7cddfSDavid du Colombier 		fputs("ShellNew\n", lf);
8677dd7cddfSDavid du Colombier 		CopyFileContents(lf, f);
8687dd7cddfSDavid du Colombier 		fputs("\n", lf);
8697dd7cddfSDavid du Colombier 		fclose(f);
8707dd7cddfSDavid du Colombier 		DeleteFile(m_szShellNew);
8717dd7cddfSDavid du Colombier 		m_szShellNew[0] = '\0';
8727dd7cddfSDavid du Colombier 	}
8737dd7cddfSDavid du Colombier 
8747dd7cddfSDavid du Colombier 	if (strlen(m_szShellOld) &&
8757dd7cddfSDavid du Colombier 		(f = fopen(m_szShellOld, "r")) != (FILE *)NULL) {
8767dd7cddfSDavid du Colombier 		fputs(szSection, lf);
8777dd7cddfSDavid du Colombier 		fputs("ShellOld\n", lf);
8787dd7cddfSDavid du Colombier 		CopyFileContents(lf, f);
8797dd7cddfSDavid du Colombier 		fputs("\n", lf);
8807dd7cddfSDavid du Colombier 		fclose(f);
8817dd7cddfSDavid du Colombier 		DeleteFile(m_szShellOld);
8827dd7cddfSDavid du Colombier 		m_szShellOld[0] = '\0';
8837dd7cddfSDavid du Colombier 	}
8847dd7cddfSDavid du Colombier 
8857dd7cddfSDavid du Colombier 	if (strlen(m_szFileNew) &&
8867dd7cddfSDavid du Colombier 		(f = fopen(m_szFileNew, "r")) != (FILE *)NULL) {
8877dd7cddfSDavid du Colombier 		fputs(szSection, lf);
8887dd7cddfSDavid du Colombier 		fputs("FileNew\n", lf);
8897dd7cddfSDavid du Colombier 		CopyFileContents(lf, f);
8907dd7cddfSDavid du Colombier 		fputs("\n", lf);
8917dd7cddfSDavid du Colombier 		fclose(f);
8927dd7cddfSDavid du Colombier 		DeleteFile(m_szFileNew);
8937dd7cddfSDavid du Colombier 		m_szFileNew[0] = '\0';
8947dd7cddfSDavid du Colombier 	}
8957dd7cddfSDavid du Colombier 
8967dd7cddfSDavid du Colombier 	fputs(szSection, lf);
8977dd7cddfSDavid du Colombier 	fclose(lf);
8987dd7cddfSDavid du Colombier 
8997dd7cddfSDavid du Colombier 	return TRUE;
9007dd7cddfSDavid du Colombier }
9017dd7cddfSDavid du Colombier 
GetPrograms(BOOL bUseCommon,char * buf,int buflen)9027dd7cddfSDavid du Colombier BOOL CInstall::GetPrograms(BOOL bUseCommon, char *buf, int buflen)
9037dd7cddfSDavid du Colombier {
9047dd7cddfSDavid du Colombier 	// Get the directory for the Program menu. This is
9057dd7cddfSDavid du Colombier 	// stored in the Registry under HKEY_CURRENT_USER\Software\
9067dd7cddfSDavid du Colombier 	// Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Programs.
9077dd7cddfSDavid du Colombier 	LONG rc;
9087dd7cddfSDavid du Colombier 	HKEY hCU;
9097dd7cddfSDavid du Colombier 	DWORD dwType;
9107dd7cddfSDavid du Colombier 	ULONG ulSize = buflen;
9117dd7cddfSDavid du Colombier 	HKEY hrkey = HKEY_CURRENT_USER;
9127dd7cddfSDavid du Colombier 	if (bUseCommon)
9137dd7cddfSDavid du Colombier 		hrkey = HKEY_LOCAL_MACHINE;
9147dd7cddfSDavid du Colombier 	if (RegOpenKeyEx(hrkey,
9157dd7cddfSDavid du Colombier 		"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
9167dd7cddfSDavid du Colombier 		0,KEY_QUERY_VALUE,
9177dd7cddfSDavid du Colombier 		&hCU) == ERROR_SUCCESS)    {
9187dd7cddfSDavid du Colombier 		rc = RegQueryValueEx( hCU,
9197dd7cddfSDavid du Colombier 			bUseCommon ? "Common Programs" : "Programs",
9207dd7cddfSDavid du Colombier 			NULL,
9217dd7cddfSDavid du Colombier 			&dwType,
9227dd7cddfSDavid du Colombier 			(unsigned char *)buf,
9237dd7cddfSDavid du Colombier 			&ulSize);
9247dd7cddfSDavid du Colombier 		RegCloseKey(hCU);
9257dd7cddfSDavid du Colombier 		return TRUE;
9267dd7cddfSDavid du Colombier 	}
9277dd7cddfSDavid du Colombier 	return FALSE;
9287dd7cddfSDavid du Colombier 
9297dd7cddfSDavid du Colombier #ifdef NOTUSED
9307dd7cddfSDavid du Colombier 	// This is an alternate version, but it needs
9317dd7cddfSDavid du Colombier 	// Internet Explorer 4.0 with Web Integrated Desktop.
9327dd7cddfSDavid du Colombier 	// It does not work with the standard
9337dd7cddfSDavid du Colombier 	// Windows 95, Windows NT 4.0, Internet Explorer 3.0,
9347dd7cddfSDavid du Colombier 	// and Internet Explorer 4.0 without Web Integrated Desktop.
9357dd7cddfSDavid du Colombier 
9367dd7cddfSDavid du Colombier 	HRESULT rc;
9377dd7cddfSDavid du Colombier 	m_szPrograms[0] = '\0';
9387dd7cddfSDavid du Colombier 	int nFolder = CSIDL_PROGRAMS;
9397dd7cddfSDavid du Colombier 	if (bUseCommon)
9407dd7cddfSDavid du Colombier 		nFolder = CSIDL_COMMON_PROGRAMS;
9417dd7cddfSDavid du Colombier 
9427dd7cddfSDavid du Colombier 	rc = SHGetSpecialFolderPath(HWND_DESKTOP, m_szPrograms,
9437dd7cddfSDavid du Colombier 		nFolder, FALSE);
9447dd7cddfSDavid du Colombier 	return (rc == NOERROR);
9457dd7cddfSDavid du Colombier #endif
9467dd7cddfSDavid du Colombier 
9477dd7cddfSDavid du Colombier }
9487dd7cddfSDavid du Colombier 
SetAllUsers(BOOL bUseCommon)9497dd7cddfSDavid du Colombier BOOL CInstall::SetAllUsers(BOOL bUseCommon)
9507dd7cddfSDavid du Colombier {
9517dd7cddfSDavid du Colombier 	m_bUseCommon = bUseCommon;
9527dd7cddfSDavid du Colombier 	return GetPrograms(bUseCommon, m_szPrograms, sizeof(m_szPrograms));
9537dd7cddfSDavid du Colombier }
9547dd7cddfSDavid du Colombier 
9557dd7cddfSDavid du Colombier 
9567dd7cddfSDavid du Colombier //////////////////////////////////////////////////////////////////////
957