2827 lines
103 KiB
C
2827 lines
103 KiB
C
//***************************************************************************
|
||
//* Copyright (c) Microsoft Corporation 1995-1996. All rights reserved. *
|
||
//***************************************************************************
|
||
//* *
|
||
//* ADVPACK.C - Advanced INF Installer. *
|
||
//* *
|
||
//***************************************************************************
|
||
|
||
|
||
//***************************************************************************
|
||
//* INCLUDE FILES *
|
||
//***************************************************************************
|
||
#include <io.h>
|
||
#include <windows.h>
|
||
#include <winerror.h>
|
||
#include <ole2.h>
|
||
#include "resource.h"
|
||
#include "cpldebug.h"
|
||
#include "ntapi.h"
|
||
#include "advpub.h"
|
||
#include "w95pub32.h"
|
||
#include "advpack.h"
|
||
#include "regstr.h"
|
||
#include "globals.h"
|
||
#include "cfgmgr32.h"
|
||
#include "sfp.h"
|
||
|
||
//***************************************************************************
|
||
//* global defines *
|
||
//***************************************************************************
|
||
|
||
#define YES "1"
|
||
#define NO "0"
|
||
|
||
#define FILELIST_SIZE 10*BUF_1K
|
||
|
||
//***************************************************************************
|
||
//* globals *
|
||
//***************************************************************************
|
||
|
||
INFOPT RegInfOpt[] = { ADVINF_ADDREG, ADVINF_DELREG, ADVINF_BKREG }; // code below depending on this orders
|
||
|
||
static PSTR gst_pszFiles;
|
||
static PSTR gst_pszEndLastFile = NULL;
|
||
static HRESULT gst_hNeedReboot;
|
||
static PSTR gst_pszSmartReboot = NULL;
|
||
|
||
const char c_szActiveSetupKey[] = "software\\microsoft\\Active Setup\\Installed Components";
|
||
|
||
// globals for reg backup key and file names
|
||
const char c_szRegUninstPath[] = "BackupRegPathName";
|
||
const char c_szRegUninstSize[] = "BackupRegSize";
|
||
|
||
const char c_szHiveKey_FMT[] = "AINF%04d";
|
||
|
||
// NoBackupPlatform string table
|
||
LPCSTR c_pszPlatform[] = { "win9x", "NT3.5", "NT4", "NT5", "NT5.1" };
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// PerUser section defines
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
const CHAR REGVAL_OLDDISPN[]= "OldDisplayName";
|
||
const CHAR REGVAL_OLDVER[]= "OldVersion";
|
||
const CHAR REGVAL_OLDSTUB[]= "OldStubPath";
|
||
const CHAR REGVAL_OLDLANG[]= "OldLocale";
|
||
const CHAR REGVAL_OLDREALSTUBPATH[]= "OldRealStubPath";
|
||
|
||
const CHAR REGVAL_REALSTUBPATH[]= "RealStubPath";
|
||
|
||
const CHAR ADV_UNINSTSTUBWRAPPER[]= "rundll32.exe advpack.dll,UserUnInstStubWrapper %s";
|
||
const CHAR ADV_INSTSTUBWRAPPER[]= "rundll32.exe advpack.dll,UserInstStubWrapper %s";
|
||
|
||
const CHAR c_szRegDontAskValue[] = "DontAsk";
|
||
/* Check the "Don't Ask" value. If it's present, its value
|
||
* is interpreted as follows:
|
||
*
|
||
* 0 --> ask the user
|
||
* 1 --> do not run the stub
|
||
* 2 --> always run the stub
|
||
*/
|
||
|
||
HRESULT ProcessOneRegSec( HWND hw, PCSTR pszTitle, PCSTR pszInf, PCSTR pszSec, HKEY hKey, HKEY hCUKey, DWORD dwFlags, BOOL *lpbOneRegSave );
|
||
UINT WINAPI MyFileQueueCallback( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 );
|
||
UINT WINAPI MyFileQueueCallback2( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 );
|
||
void CleanRegLogFile( PCSTR pcszLogFileSecName );
|
||
BOOL VerifyBackupInfo( HKEY hKey, HKEY hCUKey );
|
||
void DeleteOldBackupData( HKEY hKey );
|
||
//int DeleteSubKey(HKEY root, char *keyname);
|
||
BOOL NeedBackupData(LPCSTR pszInf, LPCSTR pszSec);
|
||
BOOL GetUniBackupName( HKEY hKey, LPSTR pszBackupBase, DWORD dwInSize, LPCSTR pszBackupPath, LPCSTR pszModule );
|
||
|
||
|
||
//***************************************************************************
|
||
extern PFSetupDefaultQueueCallback pfSetupDefaultQueueCallback;
|
||
extern PFSetupInstallFromInfSection pfSetupInstallFromInfSection;
|
||
extern PFSetupInitDefaultQueueCallbackEx pfSetupInitDefaultQueueCallbackEx;
|
||
extern PFSetupTermDefaultQueueCallback pfSetupTermDefaultQueueCallback;
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: LaunchINFSectionEx *
|
||
//* *
|
||
//* SYNOPSIS: Detect which shell mode you are in and flip it over to *
|
||
//* the other mode *
|
||
//* *
|
||
//* REQUIRES: *
|
||
//* *
|
||
//* RETURNS: *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI LaunchINFSectionEx( HWND hwnd, HINSTANCE hInstance, PSTR pszParms, INT nShow )
|
||
{
|
||
LPSTR pszFlags;
|
||
PCABINFO pcabInfo = NULL;
|
||
HRESULT hRet = S_OK;
|
||
|
||
AdvWriteToLog("LaunchINFSectionEx: Param= %1\r\n", pszParms);
|
||
pcabInfo = (PCABINFO)LocalAlloc( LPTR, sizeof(CABINFO) );
|
||
if ( !pcabInfo )
|
||
{
|
||
ErrorMsg( hwnd, IDS_ERR_NO_MEMORY );
|
||
goto done;
|
||
}
|
||
|
||
// Parse the arguments, SETUP engine is not called. So we only need to check on \".
|
||
pcabInfo->pszInf = GetStringField( &pszParms, ",", '\"', TRUE );
|
||
pcabInfo->pszSection = GetStringField( &pszParms, ",", '\"', TRUE );
|
||
pcabInfo->pszCab = GetStringField( &pszParms, ",", '\"', TRUE );
|
||
pszFlags = GetStringField( &pszParms, ",", '\"', TRUE );
|
||
gst_pszSmartReboot = GetStringField( &pszParms, ",", '\"', TRUE );
|
||
|
||
if ( pszFlags != NULL )
|
||
pcabInfo->dwFlags = My_atol(pszFlags);
|
||
|
||
if ( pcabInfo->pszCab != NULL && *pcabInfo->pszCab )
|
||
{
|
||
if ( IsFullPath( pcabInfo->pszCab ) )
|
||
{
|
||
lstrcpy( pcabInfo->szSrcPath, pcabInfo->pszCab );
|
||
GetParentDir( pcabInfo->szSrcPath );
|
||
}
|
||
else
|
||
{
|
||
ErrorMsg1Param( hwnd, IDS_ERR_CABPATH, pcabInfo->pszCab );
|
||
goto done;
|
||
}
|
||
}
|
||
|
||
// if we need to switch the mode. call ExecuteCab()
|
||
hRet = ExecuteCab( hwnd, pcabInfo, NULL );
|
||
|
||
done:
|
||
if ( pcabInfo )
|
||
LocalFree( pcabInfo );
|
||
AdvWriteToLog("LaunchINFSectionEx: End hr=0x%1!x!\r\n",hRet);
|
||
return hRet;
|
||
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: ExecuteCab *
|
||
//* *
|
||
//* SYNOPSIS: Get INF from the cab and install it based on the flag. *
|
||
//* *
|
||
//* REQUIRES: hWnd: Handle to parent window. *
|
||
//* *
|
||
//* RETURNS: HRESULT: See advpub.h *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI ExecuteCab( HWND hWnd, PCABINFO pcabInfo, PVOID pvReserved )
|
||
{
|
||
HRESULT hRet = S_OK, hRet1 = S_OK;
|
||
DWORD dwFlags;
|
||
char szFullPathInf[MAX_PATH];
|
||
HKEY hKey = NULL;
|
||
char szSec[MAX_PATH] = { 0 };
|
||
DWORD dwSecSize = sizeof(szSec);
|
||
BOOL bExtracF = FALSE;
|
||
BOOL bExtractCatalog = FALSE;
|
||
BOOL fSavedContext = FALSE;
|
||
BOOL fTmpInf = FALSE;
|
||
char szModule[MAX_PATH];
|
||
char szCatalogName[MAX_PATH];
|
||
|
||
AdvWriteToLog("ExecuteCab:");
|
||
if (!SaveGlobalContext())
|
||
{
|
||
hRet1 = E_OUTOFMEMORY;
|
||
goto done;
|
||
}
|
||
|
||
fSavedContext = TRUE;
|
||
|
||
// Validate parameters:
|
||
// if INF filename info is missing, invalid.
|
||
if ( !pcabInfo || !(pcabInfo->pszInf) || !*(pcabInfo->pszInf) )
|
||
return E_INVALIDARG;
|
||
|
||
AdvWriteToLog("Inf = %1\r\n", pcabInfo->pszInf);
|
||
|
||
ctx.hWnd = hWnd;
|
||
|
||
// the flag ALINF_ROLLBACKDOALL includes meaning ALINF_ROLLBACK
|
||
// TO avoid check both flag everywhere, we set both on if DOALL
|
||
if ( pcabInfo->dwFlags & ALINF_ROLLBKDOALL )
|
||
{
|
||
pcabInfo->dwFlags |= ALINF_ROLLBACK;
|
||
}
|
||
|
||
// if INF is 8.3 format and the Cab file is given, extract INF out of the cab. Oterwise use it as it is.
|
||
if ( pcabInfo->pszCab && *pcabInfo->pszCab )
|
||
{
|
||
if ( !IsFullPath( pcabInfo->pszInf ) )
|
||
{
|
||
if ( SUCCEEDED(hRet = ExtractFiles( pcabInfo->pszCab, pcabInfo->szSrcPath, 0, pcabInfo->pszInf, 0, 0) ) )
|
||
bExtracF = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( pcabInfo->dwFlags & ALINF_ROLLBACK )
|
||
{
|
||
pcabInfo->dwFlags |= ALINF_ROLLBKDOALL;
|
||
}
|
||
}
|
||
|
||
if ( !GetFullInfNameAndSrcDir( pcabInfo->pszInf, szFullPathInf, pcabInfo->szSrcPath ) )
|
||
{
|
||
hRet1 = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
|
||
// if rollback case, we want to make the tmp INF file to use in case the rollback will delete the real file.
|
||
if ( (pcabInfo->dwFlags & ALINF_ROLLBACK) && !bExtracF )
|
||
{
|
||
PSTR pszFile;
|
||
char szPath[MAX_PATH];
|
||
char ch;
|
||
|
||
pszFile = ANSIStrRChr( szFullPathInf, '\\' );
|
||
if ( pszFile )
|
||
{
|
||
ch = *pszFile;
|
||
*pszFile = '\0';
|
||
if ( GetTempFileName( szFullPathInf, "INF", 0, szPath ) )
|
||
{
|
||
DeleteFile( szPath );
|
||
*pszFile = ch;
|
||
if ( CopyFile( szFullPathInf, szPath, FALSE ) )
|
||
{
|
||
AdvWriteToLog("InfFile Rename: %1 becomes %2\r\n", szFullPathInf, szPath);
|
||
fTmpInf = TRUE;
|
||
lstrcpy( szFullPathInf, szPath );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if ( pcabInfo->pszSection )
|
||
lstrcpy( szSec, pcabInfo->pszSection );
|
||
GetInfInstallSectionName( szFullPathInf, szSec, dwSecSize );
|
||
|
||
// GetComponent Name
|
||
if ( FAILED(GetTranslatedString( szFullPathInf, szSec, ADVINF_MODNAME,
|
||
szModule, sizeof(szModule), NULL)) && szModule[0])
|
||
{
|
||
*szModule = '\0'; // Or should we exit if we don't find a module name????
|
||
}
|
||
|
||
// extract the catalog, if specified
|
||
if (pcabInfo->pszCab && *pcabInfo->pszCab)
|
||
{
|
||
*szCatalogName = '\0';
|
||
|
||
GetTranslatedString(szFullPathInf, szSec, ADVINF_CATALOG_NAME, szCatalogName, sizeof(szCatalogName), NULL);
|
||
if (*szCatalogName)
|
||
{
|
||
if (SUCCEEDED(ExtractFiles(pcabInfo->pszCab, pcabInfo->szSrcPath, 0, szCatalogName, 0, 0)))
|
||
bExtractCatalog = TRUE;
|
||
}
|
||
}
|
||
|
||
// start Pre-rollback
|
||
//
|
||
dwFlags = COREINSTALL_PROMPT;
|
||
dwFlags |= (pcabInfo->dwFlags & ALINF_NGCONV ) ? 0 : COREINSTALL_GRPCONV;
|
||
if ( pcabInfo->dwFlags & ALINF_QUIET )
|
||
ctx.wQuietMode = QUIETMODE_ALL;
|
||
|
||
if ( pcabInfo->dwFlags & ALINF_CHECKBKDATA || pcabInfo->dwFlags & ALINF_ROLLBACK )
|
||
{
|
||
char szUninstall[MAX_PATH];
|
||
CHAR szBuf[MAX_PATH];
|
||
HKEY hCUKey = NULL;
|
||
|
||
if ( pcabInfo->dwFlags & ALINF_ROLLBACK )
|
||
{
|
||
szUninstall[0] = 0;
|
||
if ( SUCCEEDED(GetTranslatedString( szFullPathInf, szSec, ADVINF_PREROLBK,
|
||
szUninstall, sizeof(szUninstall), NULL)) && szUninstall[0])
|
||
{
|
||
hRet = CoreInstall( szFullPathInf, szUninstall, pcabInfo->szSrcPath, 0, dwFlags, NULL );
|
||
if ( FAILED( hRet ) )
|
||
{
|
||
hRet1 = hRet;
|
||
goto done;
|
||
}
|
||
}
|
||
}
|
||
// if just want to checking backup data, process here and return
|
||
//
|
||
hRet1 = E_UNEXPECTED; //if HKLM does not have the \Advance INF setup\Module, it is unexpected.s
|
||
|
||
if (*szModule)
|
||
{
|
||
// backup/restore the reg info referred by AddReg, DelReg, BackupReg lines inside the INF install section
|
||
//
|
||
lstrcpy( szBuf, REGKEY_SAVERESTORE );
|
||
AddPath( szBuf, szModule );
|
||
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szBuf, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
RegOpenKeyEx( HKEY_CURRENT_USER, szBuf, 0, KEY_READ, &hCUKey);
|
||
if ( VerifyBackupInfo( hKey, hCUKey ) )
|
||
hRet1 = S_OK;
|
||
else
|
||
hRet1 = E_FAIL;
|
||
}
|
||
|
||
if ( hKey )
|
||
RegCloseKey( hKey );
|
||
if ( hCUKey )
|
||
RegCloseKey( hCUKey );
|
||
}
|
||
if ( FAILED(hRet1) || (pcabInfo->dwFlags == ALINF_CHECKBKDATA) )
|
||
{
|
||
goto done;
|
||
}
|
||
}
|
||
|
||
dwFlags |= (pcabInfo->dwFlags & ALINF_DELAYREGISTEROCX) ? COREINSTALL_DELAYREGISTEROCX : 0;
|
||
dwFlags |= (pcabInfo->dwFlags & ALINF_BKINSTALL) ? COREINSTALL_BKINSTALL : 0;
|
||
dwFlags |= (pcabInfo->dwFlags & ALINF_ROLLBACK) ? COREINSTALL_ROLLBACK : 0;
|
||
dwFlags |= (pcabInfo->dwFlags & ALINF_ROLLBKDOALL) ? COREINSTALL_ROLLBKDOALL : 0;
|
||
dwFlags |= COREINSTALL_SMARTREBOOT;
|
||
|
||
hRet1 = CoreInstall( szFullPathInf, szSec, pcabInfo->szSrcPath, 0, dwFlags, gst_pszSmartReboot );
|
||
|
||
// save the cab file info
|
||
if ( SUCCEEDED( hRet1 ) && pcabInfo->pszCab && *pcabInfo->pszCab && (pcabInfo->dwFlags & ALINF_BKINSTALL) )
|
||
{
|
||
if ( hRet == ERROR_SUCCESS_REBOOT_REQUIRED )
|
||
hRet1 = hRet;
|
||
|
||
if (*szModule)
|
||
{
|
||
// reuse the buf so name is not acurate!!
|
||
lstrcpy( szSec, REGKEY_SAVERESTORE );
|
||
AddPath( szSec, szModule );
|
||
|
||
if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, szSec, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,
|
||
NULL, &hKey, &dwFlags ) == ERROR_SUCCESS )
|
||
{
|
||
RegSetValueEx( hKey, REGVAL_BKINSTCAB, 0, REG_SZ, pcabInfo->pszCab, lstrlen(pcabInfo->pszCab)+1 );
|
||
RegCloseKey( hKey );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
done:
|
||
|
||
if ( bExtracF || fTmpInf )
|
||
{
|
||
// need to delete the INF file
|
||
DeleteFile( szFullPathInf );
|
||
}
|
||
|
||
if (bExtractCatalog)
|
||
{
|
||
char szFullCatalogName[MAX_PATH];
|
||
|
||
lstrcpy(szFullCatalogName, pcabInfo->szSrcPath);
|
||
AddPath(szFullCatalogName, szCatalogName);
|
||
DeleteFile(szFullCatalogName);
|
||
}
|
||
|
||
if (fSavedContext)
|
||
{
|
||
RestoreGlobalContext();
|
||
}
|
||
if (pcabInfo->pszInf)
|
||
AdvWriteToLog("ExecuteCab: End hr=0x%1!x! Inf=%2\r\n", hRet1,pcabInfo->pszInf);
|
||
else
|
||
AdvWriteToLog("ExecuteCab: End hr=0x%1!x!\r\n", hRet1);
|
||
|
||
return hRet1;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT SaveRestoreInfo( PCSTR pszInf, PCSTR pszSection, PCSTR pszSrcDir, PCSTR pszCatalogs, DWORD dwFlags )
|
||
{
|
||
char szBuf[MAX_PATH];
|
||
char szModule[MAX_PATH];
|
||
char szBackupPath[MAX_PATH];
|
||
char szBackupBase[MAX_PATH];
|
||
UINT uErrid = 0;
|
||
DWORD dwTmp;
|
||
PSTR pszFileList = NULL;
|
||
BOOL bDeleteKey = FALSE;
|
||
HKEY hKey = NULL, hSubKey = NULL, hCUSubKey = NULL;
|
||
HRESULT hRet = S_OK;
|
||
BOOL bAtleastOneReg = FALSE;
|
||
DWORD adwAttr[8];
|
||
|
||
// check if we need to backup the data
|
||
if ( !NeedBackupData(pszInf, pszSection) )
|
||
goto done;
|
||
|
||
AdvWriteToLog("SaveRestoreInfo: ");
|
||
// GetComponent Name
|
||
if ( FAILED(GetTranslatedString( pszInf, pszSection, ADVINF_MODNAME,
|
||
szModule, sizeof(szModule), NULL)))
|
||
{
|
||
// error out if no component name
|
||
goto done;
|
||
}
|
||
|
||
AdvWriteToLog("CompName=%1 pszInf=%2 Sec=%3\r\n", szModule, pszInf, pszSection);
|
||
// backup/restore the reg info referred by AddReg, DelReg, BackupReg lines inside the INF install section
|
||
//
|
||
lstrcpy( szBuf, REGKEY_SAVERESTORE );
|
||
if ( dwFlags & COREINSTALL_BKINSTALL )
|
||
{
|
||
CleanRegLogFile( REG_SAVE_LOG_KEY );
|
||
CleanRegLogFile( REG_RESTORE_LOG_KEY );
|
||
}
|
||
|
||
AddPath( szBuf, szModule );
|
||
if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, szBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
||
NULL, &hKey, &dwTmp ) != ERROR_SUCCESS )
|
||
{
|
||
// If client does not have the access to this key, we may not want to fault out the rest setup process.
|
||
// For some reason with Read only access set, this call return error code 2 instead of 5 access denied
|
||
// so we just skip save rollback if this can not be opened/created
|
||
goto done;
|
||
}
|
||
|
||
// create HKCU branch
|
||
AddPath( szBuf, REGSUBK_REGBK );
|
||
if ( RegCreateKeyEx( HKEY_CURRENT_USER, szBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
|
||
NULL, &hCUSubKey, NULL ) != ERROR_SUCCESS )
|
||
{
|
||
hRet = HRESULT_FROM_WIN32(GetLastError());
|
||
goto done;
|
||
}
|
||
|
||
// get the bacup info folder
|
||
dwTmp = sizeof( szBackupPath );
|
||
szBackupPath[0] = 0;
|
||
RegQueryValueEx( hKey, REGVAL_BKDIR, NULL, NULL, szBackupPath, &dwTmp );
|
||
if ( szBackupPath[0] == 0 )
|
||
{
|
||
DWORD dwSize;
|
||
|
||
// use user specified: either the same as cab location #S or default location #D
|
||
if ( FAILED( GetTranslatedString( pszInf, pszSection, ADVINF_BACKUPPATH, szBackupPath,
|
||
sizeof(szBackupPath), &dwSize) ) || !IsFullPath( szBackupPath ) )
|
||
{
|
||
// use default dir
|
||
GetProgramFilesDir( szBackupPath, sizeof( szBackupPath ) );
|
||
AddPath( szBackupPath, DEF_BACKUPPATH );
|
||
CreateFullPath(szBackupPath, TRUE);
|
||
//CreateDirectory( szBackupPath, NULL );
|
||
//if ( dwFlags & COREINSTALL_BKINSTALL )
|
||
//SetFileAttributes( szBackupPath, FILE_ATTRIBUTE_HIDDEN );
|
||
AddPath( szBackupPath, szModule );
|
||
}
|
||
}
|
||
|
||
// set the flags and Process the AddReg/DelReg lines
|
||
dwTmp = (dwFlags & COREINSTALL_ROLLBACK) ? IE4_RESTORE : 0;
|
||
dwTmp |= (dwFlags & COREINSTALL_ROLLBKDOALL) ? IE4_FRDOALL : 0;
|
||
dwTmp |= IE4_NOPROGRESS;
|
||
|
||
// process files first ...
|
||
GetUniBackupName( hKey, szBackupBase, sizeof(szBackupBase), szBackupPath, szModule );
|
||
hRet = ProcessAllFiles( ctx.hWnd, pszSection, pszSrcDir, szBackupPath, szBackupBase, pszCatalogs, szModule, dwTmp );
|
||
|
||
// process regs second ...
|
||
|
||
// create/open the subkey where the registry backup info stored
|
||
if ( FAILED(hRet) )
|
||
goto done;
|
||
|
||
// On win95 and save/rollback client and hive not loaded, proce
|
||
if ( (ctx.wOSVer == _OSVER_WIN95) && !ctx.bHiveLoaded )
|
||
{
|
||
GetUniHiveKeyName( hKey, ctx.szRegHiveKey, sizeof(ctx.szRegHiveKey), szBackupPath );
|
||
lstrcpy( szBuf, szBackupPath );
|
||
// make sure the path folders are not hiden and not LFN
|
||
// flag TRUE: Set the path folders to NORMAL, save the old once in adwAttr
|
||
// BUGBUG: assume no deep than 8 levels here
|
||
//
|
||
SetPathForRegHiveUse( szBuf, adwAttr, 8, TRUE );
|
||
GetShortPathName( szBuf, szBuf, sizeof(szBuf) );
|
||
AddPath( szBuf, ctx.szRegHiveKey );
|
||
|
||
// 4 possibilities exist:
|
||
// Case 1: Reg uinstall file exists but IE4RegBackup doesn't exist
|
||
// - user is upgrading over IE4, load the file as a hive
|
||
|
||
// Case 2: Reg uinstall file doesn't exist and IE4RegBackup doesn't exist
|
||
// - clean install, create a hive under HKEY_LOCAL_MACHINE
|
||
|
||
// Case 3: Reg uninstall file doesn't exist but IE4RegBackup exists
|
||
// - user is upgrading over an older IE4 build which saved
|
||
// the reg backup info into the registry itself, call RegSaveKey
|
||
// to export the backup key to a file, then delete the backup key
|
||
// and load the file as a hive
|
||
|
||
// Case 4: Reg uninstall file exists and IE4RegBackup exists
|
||
// - THIS CASE SHOULDN'T HAPPEN AT ALL! If somehow happens,
|
||
// we will default to Case 1.
|
||
|
||
// to be safe, unload any previously loaded hive and delete the key
|
||
RegUnLoadKey(HKEY_LOCAL_MACHINE, ctx.szRegHiveKey);
|
||
RegDeleteKeyRecursively(HKEY_LOCAL_MACHINE, (char *) ctx.szRegHiveKey);
|
||
|
||
// Case 1 (or Case 4)
|
||
if (RegLoadKey(HKEY_LOCAL_MACHINE, ctx.szRegHiveKey, szBuf) == ERROR_SUCCESS)
|
||
{
|
||
ctx.bHiveLoaded = TRUE;
|
||
}
|
||
else
|
||
{
|
||
// To create a hive do the following steps:
|
||
// Step 1: Create a subkey under HKEY_LOCAL_MACHINE
|
||
// Step 2: Call RegSaveKey on the subkey to save it to a file
|
||
// Step 3: Delete the subkey
|
||
// Step 4: Load the file as a hive
|
||
|
||
// Step 1
|
||
if ( RegCreateKeyEx( hKey, REGSUBK_REGBK, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
||
NULL, &hSubKey, NULL ) == ERROR_SUCCESS )
|
||
{
|
||
LONG lErr;
|
||
|
||
// to be safe, delete any old reg unisntall file
|
||
SetFileAttributes(szBuf, FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFile(szBuf);
|
||
|
||
lErr = RegSaveKey( hSubKey, szBuf, NULL);
|
||
RegCloseKey(hSubKey);
|
||
hSubKey = NULL;
|
||
|
||
if (lErr == ERROR_SUCCESS)
|
||
{
|
||
// Step 3
|
||
RegDeleteKeyRecursively(hKey, REGSUBK_REGBK);
|
||
|
||
// Step 4
|
||
if (RegLoadKey(HKEY_LOCAL_MACHINE, ctx.szRegHiveKey, szBuf) == ERROR_SUCCESS)
|
||
{
|
||
ctx.bHiveLoaded = TRUE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hRet = HRESULT_FROM_WIN32(GetLastError());
|
||
goto done;
|
||
}
|
||
}
|
||
}
|
||
|
||
// create/open the backup reg key
|
||
if (RegCreateKeyEx( ctx.bHiveLoaded ? HKEY_LOCAL_MACHINE : hKey,
|
||
ctx.bHiveLoaded ? ctx.szRegHiveKey : REGSUBK_REGBK,
|
||
0, NULL, REG_OPTION_NON_VOLATILE,
|
||
KEY_READ|KEY_WRITE, NULL, &hSubKey, NULL ) != ERROR_SUCCESS)
|
||
{
|
||
hRet = HRESULT_FROM_WIN32(GetLastError());
|
||
goto done;
|
||
}
|
||
|
||
// set the flags and Process the AddReg/DelReg lines
|
||
dwTmp = (dwFlags & COREINSTALL_ROLLBACK) ? IE4_RESTORE : 0;
|
||
dwTmp |= (dwFlags & COREINSTALL_ROLLBKDOALL) ? IE4_FRDOALL : 0;
|
||
|
||
if ( dwFlags & COREINSTALL_ROLLBACK )
|
||
{
|
||
HRESULT hret1;
|
||
|
||
// RegRestoreAllEx will restore all the backed-up reg entries in one shot
|
||
hRet = RegRestoreAllEx( hSubKey );
|
||
hret1 = RegRestoreAllEx( hCUSubKey );
|
||
if ( FAILED(hret1) )
|
||
hRet = hret1;
|
||
}
|
||
else
|
||
{
|
||
// Save all reg sections
|
||
hRet = ProcessAllRegSec( ctx.hWnd, NULL, pszInf, pszSection, hSubKey, hCUSubKey, dwTmp, &bAtleastOneReg );
|
||
}
|
||
|
||
// after all the reg work, unload the hive to reg backup file and record where those
|
||
// reg backup data are in registry.
|
||
if ( (ctx.wOSVer == _OSVER_WIN95) && ctx.bHiveLoaded )
|
||
{
|
||
// flush the key and unload the hive
|
||
ctx.bHiveLoaded = FALSE;
|
||
|
||
RegFlushKey(hSubKey);
|
||
RegCloseKey(hSubKey);
|
||
hSubKey = NULL;
|
||
|
||
RegUnLoadKey(HKEY_LOCAL_MACHINE, ctx.szRegHiveKey);
|
||
// Flag: FALSE; reset the path folders to its orignal attributes
|
||
SetPathForRegHiveUse( szBackupPath, adwAttr, 8, FALSE );
|
||
|
||
if ( dwFlags & COREINSTALL_BKINSTALL )
|
||
{
|
||
// write the file<key>, path and size of the reg uninstall file to the registry
|
||
RegSetValueEx( hKey, c_szRegUninstPath, 0, REG_SZ, (LPBYTE)szBuf, lstrlen(szBuf) + 1 );
|
||
// the size can be used to validate the file during RegRestore; currently NOT USED
|
||
dwTmp = MyFileSize( szBuf );
|
||
RegSetValueEx( hKey, c_szRegUninstSize, 0, REG_DWORD, (LPBYTE)&dwTmp, sizeof(dwTmp) );
|
||
}
|
||
else if ( SUCCEEDED( hRet ) )
|
||
{
|
||
// delete reg data backup file
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
RegDeleteValue(hKey, c_szRegUninstPath);
|
||
RegDeleteValue(hKey, c_szRegUninstSize);
|
||
}
|
||
}
|
||
|
||
// store & cleanup the backup information
|
||
if ( SUCCEEDED( hRet ) )
|
||
{
|
||
PSTR ptmp;
|
||
PCSTR pszCatalogName;
|
||
|
||
lstrcpy( szBuf, szBackupPath );
|
||
AddPath( szBuf, szBackupBase );
|
||
ptmp = szBuf + lstrlen(szBuf);
|
||
lstrcpy( ptmp, ".DAT" );
|
||
|
||
if ( dwFlags & COREINSTALL_BKINSTALL )
|
||
{
|
||
dwTmp = MyFileSize( szBuf );
|
||
RegSetValueEx( hKey, REGVAL_BKFILE, 0, REG_SZ, szBuf, lstrlen(szBuf)+1 );
|
||
RegSetValueEx( hKey, REGVAL_BKSIZE, 0, REG_DWORD, (LPBYTE)&dwTmp, sizeof(DWORD) );
|
||
RegSetValueEx( hKey, REGVAL_BKDIR, 0, REG_SZ, szBackupPath, lstrlen(szBackupPath)+1 );
|
||
RegSetValueEx( hKey, REGVAL_BKINSTINF, 0, REG_SZ, pszInf, lstrlen(pszInf)+1 );
|
||
RegSetValueEx( hKey, REGVAL_BKINSTSEC, 0, REG_SZ, pszSection, lstrlen(pszSection)+1 );
|
||
RegSetValueEx( hKey, REGVAL_BKREGDATA, 0, REG_SZ, bAtleastOneReg ? "y" : "n", 2 );
|
||
if ( SUCCEEDED(GetTranslatedString( pszInf, pszSection, ADVINF_MODVER,
|
||
szBuf, sizeof(szBuf), NULL)) && szBuf[0])
|
||
{
|
||
RegSetValueEx( hKey, REGVAL_BKMODVER, 0, REG_SZ, szBuf, lstrlen(szBuf)+1 );
|
||
}
|
||
for (pszCatalogName = pszCatalogs; *pszCatalogName; pszCatalogName += lstrlen(pszCatalogName) + 1)
|
||
{
|
||
HKEY hkCatalogKey;
|
||
CHAR szFullCatalogName[MAX_PATH];
|
||
|
||
if (RegCreateKeyEx(hKey, REGSUBK_CATALOGS, 0, NULL, REG_OPTION_NON_VOLATILE,
|
||
KEY_SET_VALUE, NULL, &hkCatalogKey, NULL) == ERROR_SUCCESS)
|
||
{
|
||
DWORD dwVal = 1;
|
||
|
||
RegSetValueEx(hkCatalogKey, pszCatalogName, 0, REG_DWORD, (CONST BYTE *) &dwVal, sizeof(dwVal));
|
||
RegCloseKey(hkCatalogKey);
|
||
}
|
||
|
||
lstrcpy(szFullCatalogName, szBackupPath);
|
||
AddPath(szFullCatalogName, pszCatalogName);
|
||
if (FileExists(szFullCatalogName))
|
||
SetFileAttributes(szFullCatalogName, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
|
||
}
|
||
}
|
||
else if ( dwFlags & COREINSTALL_ROLLBACK )
|
||
{
|
||
// delete the catalogs
|
||
for (pszCatalogName = pszCatalogs; *pszCatalogName; pszCatalogName += lstrlen(pszCatalogName) + 1)
|
||
{
|
||
HKEY hkCatalogKey;
|
||
CHAR szFullCatalogName[MAX_PATH];
|
||
|
||
if (RegOpenKeyEx(hKey, REGSUBK_CATALOGS, 0, KEY_WRITE, &hkCatalogKey) == ERROR_SUCCESS)
|
||
{
|
||
RegDeleteValue(hkCatalogKey, pszCatalogName);
|
||
RegCloseKey(hkCatalogKey);
|
||
}
|
||
|
||
lstrcpy(szFullCatalogName, szBackupPath);
|
||
AddPath(szFullCatalogName, pszCatalogName);
|
||
if (FileExists(szFullCatalogName))
|
||
{
|
||
SetFileAttributes(szFullCatalogName, FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFile(szFullCatalogName);
|
||
}
|
||
}
|
||
|
||
// delete backup .dat .ini files
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
lstrcpy( ptmp, ".INI" );
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
MyRemoveDirectory( szBackupPath );
|
||
|
||
// since we have rollback all the files and delete the backup .dat .ini files, we
|
||
// should re-set the backup file size to ZERO to allow reg restore continue for whatever
|
||
// following users.
|
||
dwTmp = 0;
|
||
RegSetValueEx( hKey, REGVAL_BKSIZE, 0, REG_DWORD, (LPBYTE)&dwTmp, sizeof(DWORD) );
|
||
RegSetValueEx( hKey, REGVAL_BKREGDATA, 0, REG_SZ, "n", 2 );
|
||
RegDeleteValue( hKey, REGVAL_BKMODVER );
|
||
}
|
||
}
|
||
|
||
done:
|
||
|
||
if ( hSubKey )
|
||
{
|
||
RegCloseKey( hSubKey );
|
||
}
|
||
|
||
if ( hKey )
|
||
{
|
||
RegCloseKey( hKey );
|
||
}
|
||
|
||
if ( hCUSubKey )
|
||
{
|
||
BOOL bEmpty = TRUE;
|
||
DWORD dwKeys, dwValues;
|
||
|
||
if ( (RegQueryInfoKey(hCUSubKey, NULL, NULL, NULL, &dwKeys, NULL, NULL,
|
||
&dwValues, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) &&
|
||
(dwKeys || dwValues) )
|
||
{
|
||
// not empty key
|
||
bEmpty = FALSE;
|
||
}
|
||
|
||
RegCloseKey( hCUSubKey );
|
||
|
||
if ( bEmpty )
|
||
{
|
||
// delete the empty key
|
||
if ( RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_SAVERESTORE, 0, KEY_READ|KEY_WRITE, &hCUSubKey) == ERROR_SUCCESS)
|
||
{
|
||
RegDeleteKeyRecursively( hCUSubKey, szModule );
|
||
RegCloseKey( hCUSubKey );
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
if ( gst_pszFiles )
|
||
{
|
||
LocalFree( gst_pszFiles );
|
||
gst_pszFiles = NULL;
|
||
gst_pszEndLastFile = NULL;
|
||
}
|
||
|
||
AdvWriteToLog("SaveRestoreInfo: End hr=0x%1!x! %2\r\n", hRet, szModule);
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT ProcessAllRegSec( HWND hw, PCSTR pszTitle, PCSTR pszInf, PCSTR pszSection, HKEY hKey, HKEY hCUKey, DWORD dwFlags, BOOL *lpbOneReg )
|
||
{
|
||
int i, arraysize;
|
||
PSTR pszOneSec;
|
||
PSTR pszStr;
|
||
HRESULT hRet = S_OK;
|
||
char szBuf[MAX_PATH];
|
||
|
||
AdvWriteToLog("ProcessAllRegSec: \r\n");
|
||
arraysize = ARRAYSIZE( RegInfOpt );
|
||
for ( i=0; i<arraysize; i++ )
|
||
{
|
||
szBuf[0] = 0;
|
||
pszStr = szBuf;
|
||
|
||
GetTranslatedString( pszInf, pszSection, RegInfOpt[i].pszInfKey,
|
||
szBuf, sizeof(szBuf), NULL);
|
||
|
||
// Parse the arguments, SETUP engine is not called to process this line. So we check on \".
|
||
pszOneSec = GetStringField( &pszStr, ",", '\"', TRUE );
|
||
while ( (hRet == S_OK) && pszOneSec && *pszOneSec )
|
||
{
|
||
if ( i == 0 ) // AddReg section only
|
||
dwFlags |= IE4_NOENUMKEY;
|
||
else
|
||
dwFlags &= ~IE4_NOENUMKEY;
|
||
|
||
if (*pszOneSec != '!')
|
||
hRet = ProcessOneRegSec( hw, pszTitle, pszInf, pszOneSec, hKey, hCUKey, dwFlags, lpbOneReg );
|
||
|
||
pszOneSec = GetStringField( &pszStr, ",", '\"', TRUE );
|
||
}
|
||
|
||
}
|
||
AdvWriteToLog("ProcessAllRegSec: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT ProcessOneRegSec( HWND hw, PCSTR pszTitle, PCSTR pszInf, PCSTR pszSec, HKEY hLMKey, HKEY hCUKey, DWORD dwFlags, BOOL *lpbOneReg )
|
||
{
|
||
int j;
|
||
PSTR pszInfLine = NULL;
|
||
HRESULT hResult = S_OK;
|
||
PSTR pszRootKey, pszSubKey, pszValueName, pszTmp1, pszTmp2;
|
||
HKEY hKey;
|
||
|
||
AdvWriteToLog("ProcessOneRegSec: Section=%1\r\n", pszSec);
|
||
for ( j=0; (hResult==S_OK); j++ )
|
||
{
|
||
if ( FAILED(hResult = GetTranslatedLine( pszInf, pszSec, j, &pszInfLine, NULL )) ||
|
||
!pszInfLine )
|
||
{
|
||
// if the failure due to no more items, set to normal return
|
||
if ( hResult == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) )
|
||
hResult = S_OK;
|
||
|
||
break;
|
||
}
|
||
|
||
// at least, there is one reg data to be saved
|
||
if ( lpbOneReg && !*lpbOneReg )
|
||
*lpbOneReg = TRUE;
|
||
|
||
// Parse out the fields Registry op-line.
|
||
ParseCustomLine( pszInfLine, &pszRootKey, &pszSubKey, &pszValueName, &pszTmp1, &pszTmp2, FALSE, TRUE );
|
||
|
||
if ( !lstrcmpi( pszRootKey, "HKCU") || !lstrcmpi( pszRootKey, "HKEY_CURRENT_USER" ) )
|
||
hKey = hCUKey;
|
||
else
|
||
hKey = hLMKey;
|
||
|
||
// Check the specified registry branch and grab the contents.
|
||
hResult = RegSaveRestore( hw, pszTitle, hKey, pszRootKey, pszSubKey, pszValueName, dwFlags );
|
||
|
||
LocalFree( pszInfLine );
|
||
pszInfLine = NULL;
|
||
}
|
||
|
||
AdvWriteToLog("ProcessOneRegSec: End hr=0x%1!x! %2\r\n", hResult, pszSec);
|
||
return hResult;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT ProcessAllFiles( HWND hw, PCSTR pszSection, PCSTR pszSrcDir, PCSTR pszBackupPath,
|
||
PCSTR pszBaseName, PCSTR pszCatalogs, PCSTR pszModule, DWORD dwFlags )
|
||
{
|
||
HRESULT hRet = S_OK;
|
||
PCSTR pszCatalogName;
|
||
|
||
AdvWriteToLog("ProcessAllFiles: Sec=%1, SrcDir=%2, BackupPath=%3\r\n", pszSection, pszSrcDir, pszBackupPath);
|
||
// if CORESINSTALL_ROLLBKDOALL is on, no need to build the filelist. FileRestore will
|
||
// rollback everything based on its .INI backup data index file. Otherwise, build
|
||
// file list gst_pszFiles inside
|
||
gst_pszFiles = NULL;
|
||
if ( !(dwFlags & IE4_FRDOALL) )
|
||
{
|
||
// backup/restore the files referred by CopyFiles, DelFiles, RenFiles
|
||
//
|
||
gst_pszFiles = (PSTR)LocalAlloc( LPTR, FILELIST_SIZE ); // allocat 10k
|
||
gst_pszEndLastFile = gst_pszFiles; // already will have 2 zeros
|
||
if ( !gst_pszFiles )
|
||
{
|
||
ErrorMsg( hw, IDS_ERR_NO_MEMORY );
|
||
hRet = E_OUTOFMEMORY;
|
||
return hRet;
|
||
}
|
||
|
||
hRet = ProcessFileSections( pszSection, pszSrcDir, MyFileQueueCallback );
|
||
}
|
||
|
||
// if a catalog is specified, backup/restore it
|
||
for (pszCatalogName = pszCatalogs; SUCCEEDED(hRet) && *pszCatalogName; pszCatalogName += lstrlen(pszCatalogName) + 1)
|
||
{
|
||
DWORD dwRet;
|
||
CHAR szPrevCatalog[MAX_PATH];
|
||
|
||
AdvWriteToLog("ProcessAllFiles: Processing catalog=%1\r\n", pszCatalogName);
|
||
|
||
lstrcpy(szPrevCatalog, pszBackupPath);
|
||
AddPath(szPrevCatalog, pszCatalogName);
|
||
|
||
if ((dwFlags & IE4_RESTORE) || (dwFlags & IE4_FRDOALL))
|
||
{
|
||
// first delete the current catalog and then install the previous one
|
||
dwRet = g_pfSfpDeleteCatalog(pszCatalogName);
|
||
AdvWriteToLog("\tProcessAllFiles: SfpDeleteCatalog returned=%1!lu!\r\n", dwRet);
|
||
if (dwRet != ERROR_SUCCESS)
|
||
hRet = E_FAIL;
|
||
|
||
if (SUCCEEDED(hRet) && FileExists(szPrevCatalog))
|
||
{
|
||
dwRet = g_pfSfpInstallCatalog(szPrevCatalog, NULL);
|
||
AdvWriteToLog("\tProcessAllFiles: SfpInstallCatalog returned=%1!lu!\r\n", dwRet);
|
||
if (dwRet != ERROR_SUCCESS)
|
||
hRet = E_FAIL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
BOOL bBackupCatalog = FALSE;
|
||
CHAR szBuf[MAX_PATH];
|
||
|
||
if (pszModule != NULL)
|
||
{
|
||
HKEY hkCatalogKey;
|
||
|
||
lstrcpy(szBuf, REGKEY_SAVERESTORE);
|
||
AddPath(szBuf, pszModule);
|
||
AddPath(szBuf, REGSUBK_CATALOGS);
|
||
|
||
// back-up the catalog if it hasn't been already backed up
|
||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hkCatalogKey) == ERROR_SUCCESS)
|
||
{
|
||
if (RegQueryValueEx(hkCatalogKey, pszCatalogName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||
bBackupCatalog = TRUE;
|
||
|
||
RegCloseKey(hkCatalogKey);
|
||
}
|
||
else
|
||
bBackupCatalog = TRUE;
|
||
}
|
||
else
|
||
{
|
||
// back-up the catalog if the file back-up .dat doesn't exist
|
||
lstrcpy(szBuf, pszBackupPath);
|
||
AddPath(szBuf, pszBaseName);
|
||
lstrcat(szBuf, ".dat");
|
||
|
||
if (!FileExists(szBuf))
|
||
bBackupCatalog = TRUE;
|
||
}
|
||
|
||
if (bBackupCatalog)
|
||
{
|
||
dwRet = g_pfSfpDuplicateCatalog(pszCatalogName, pszBackupPath);
|
||
AdvWriteToLog("\tProcessAllFiles: SfpDuplicateCatalog returned=%1!lu!\r\n", dwRet);
|
||
if (dwRet != ERROR_SUCCESS && dwRet != ERROR_FILE_NOT_FOUND)
|
||
hRet = E_FAIL;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( SUCCEEDED(hRet) )
|
||
{
|
||
hRet = FileSaveRestore( hw, gst_pszFiles, (PSTR)pszBackupPath, (PSTR)pszBaseName, dwFlags );
|
||
}
|
||
|
||
AdvWriteToLog("ProcessAllFiles: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT ProcessFileSections( PCSTR pszSection, PCSTR pszSrcDir, MYFILEQUEUECALLBACK pMyFileQueueCallback )
|
||
{
|
||
PVOID pContext = NULL;
|
||
HRESULT hResult = S_OK;
|
||
|
||
AdvWriteToLog("ProcessFileSections: Sec=%1\r\n", pszSection);
|
||
// Build File list include all the files in CopyFiles/DelFiles/renFiles
|
||
//
|
||
|
||
// Setup Context data structure initialized for us for default UI provided by Setup API.
|
||
pContext = pfSetupInitDefaultQueueCallbackEx( NULL,
|
||
INVALID_HANDLE_VALUE,
|
||
0, 0, NULL );
|
||
|
||
if ( pContext == INVALID_HANDLE_VALUE )
|
||
{
|
||
hResult = HRESULT_FROM_SETUPAPI(GetLastError());
|
||
goto done;
|
||
}
|
||
|
||
if ( !pfSetupInstallFromInfSection( NULL, ctx.hInf, pszSection, SPINST_FILES, NULL,
|
||
pszSrcDir, SP_COPY_NEWER,
|
||
pMyFileQueueCallback,
|
||
pContext, NULL, NULL ) )
|
||
{
|
||
hResult = HRESULT_FROM_SETUPAPI(GetLastError());
|
||
pfSetupTermDefaultQueueCallback( pContext );
|
||
goto done;
|
||
}
|
||
|
||
// Free Context Data structure
|
||
pfSetupTermDefaultQueueCallback( pContext );
|
||
|
||
done:
|
||
AdvWriteToLog("ProcessFileSections: End hr=0x%1!x!\r\n",hResult);
|
||
return hResult;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
UINT WINAPI MyFileQueueCallback( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 )
|
||
{
|
||
UINT retVal = FILEOP_SKIP;
|
||
|
||
switch(Notification)
|
||
{
|
||
case SPFILENOTIFY_STARTDELETE:
|
||
case SPFILENOTIFY_STARTRENAME:
|
||
case SPFILENOTIFY_STARTCOPY:
|
||
{
|
||
FILEPATHS *pFilePath;
|
||
int len;
|
||
PCSTR pTmp;
|
||
|
||
pFilePath = (FILEPATHS *)parm1;
|
||
|
||
if ( !gst_pszFiles )
|
||
{
|
||
retVal = FILEOP_ABORT;
|
||
SetLastError( ERROR_OUTOFMEMORY );
|
||
break;
|
||
}
|
||
|
||
if ( Notification == SPFILENOTIFY_STARTRENAME )
|
||
{
|
||
len = lstrlen( pFilePath->Source ) + 1;
|
||
pTmp = pFilePath->Source;
|
||
}
|
||
else
|
||
{
|
||
len = lstrlen( pFilePath->Target ) + 1;
|
||
pTmp = pFilePath->Target;
|
||
}
|
||
|
||
if ( (FILELIST_SIZE - (gst_pszEndLastFile - gst_pszFiles )) <= (len + 8) )
|
||
{
|
||
retVal = FILEOP_ABORT;
|
||
SetLastError( ERROR_OUTOFMEMORY );
|
||
break;
|
||
}
|
||
|
||
lstrcpy( gst_pszEndLastFile, pTmp );
|
||
gst_pszEndLastFile += len;
|
||
*gst_pszEndLastFile = 0; // the second '\0' to end the list
|
||
}
|
||
break;
|
||
|
||
case SPFILENOTIFY_NEEDMEDIA:
|
||
return ( MyFileQueueCallback2( Context, Notification, parm1, parm2 ) );
|
||
|
||
default:
|
||
return ( pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) );
|
||
}
|
||
|
||
return( retVal );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
BOOL GetFullInfNameAndSrcDir( PCSTR pszInfFilename, PSTR pszFilename, PSTR pszSrcDir )
|
||
{
|
||
BOOL bRet = FALSE;
|
||
UINT uiErrid = 0;
|
||
PCSTR pszErrParm1 = NULL;
|
||
char szBuf[MAX_PATH];
|
||
|
||
if ( !pszInfFilename || !pszFilename || !(*pszInfFilename) )
|
||
goto done;
|
||
|
||
if ( !IsFullPath( pszInfFilename ) && pszSrcDir && *pszSrcDir )
|
||
{
|
||
lstrcpy( szBuf, pszSrcDir );
|
||
AddPath( szBuf, pszInfFilename );
|
||
}
|
||
else
|
||
lstrcpy( szBuf, pszInfFilename );
|
||
|
||
if ( GetFileAttributes( szBuf ) == 0xFFFFFFFF )
|
||
{
|
||
if ( IsFullPath( szBuf ) )
|
||
{
|
||
uiErrid = IDS_ERR_CANT_FIND_FILE;
|
||
pszErrParm1 = pszInfFilename;
|
||
goto done;
|
||
}
|
||
|
||
// If the file doesn't exist in the current directory, check the
|
||
// Windows\inf directory
|
||
|
||
if ( !GetWindowsDirectory( szBuf, sizeof(szBuf) ) )
|
||
{
|
||
uiErrid = IDS_ERR_GET_WIN_DIR;
|
||
goto done;
|
||
}
|
||
|
||
AddPath( szBuf, "inf" );
|
||
AddPath( szBuf, pszInfFilename );
|
||
|
||
if ( GetFileAttributes( szBuf) == 0xFFFFFFFF )
|
||
{
|
||
uiErrid = IDS_ERR_CANT_FIND_FILE;
|
||
pszErrParm1 = pszInfFilename;
|
||
goto done;
|
||
}
|
||
}
|
||
|
||
// Generate the source directory from the inf path.
|
||
lstrcpy( pszFilename, szBuf );
|
||
|
||
GetParentDir( szBuf );
|
||
lstrcpy( pszSrcDir, szBuf );
|
||
|
||
bRet = TRUE;
|
||
|
||
done:
|
||
|
||
if ( uiErrid )
|
||
ErrorMsg1Param( ctx.hWnd, uiErrid, pszErrParm1 );
|
||
|
||
return bRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
void CleanRegLogFile( PCSTR pcszLogFileSecName )
|
||
{
|
||
char szLogFileName[MAX_PATH];
|
||
char szBuf[MAX_PATH];
|
||
HKEY hkSubKey;
|
||
|
||
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SAVERESTORE, 0, KEY_READ, &hkSubKey) == ERROR_SUCCESS)
|
||
{
|
||
DWORD dwDataLen = sizeof(szLogFileName);
|
||
|
||
if (RegQueryValueEx(hkSubKey, pcszLogFileSecName, NULL, NULL, szLogFileName, &dwDataLen) != ERROR_SUCCESS)
|
||
*szLogFileName = '\0';
|
||
|
||
RegCloseKey(hkSubKey);
|
||
}
|
||
|
||
if (*szLogFileName)
|
||
{
|
||
if (szLogFileName[1] != ':') // crude way of determining if fully qualified path is specified or not
|
||
{
|
||
GetWindowsDirectory(szBuf, sizeof(szBuf)); // default to windows dir
|
||
AddPath(szBuf, szLogFileName);
|
||
}
|
||
else
|
||
lstrcpy(szBuf, szLogFileName);
|
||
|
||
DeleteFile( szBuf );
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
BOOL VerifyBackupRegData( HKEY hKey )
|
||
{
|
||
HKEY hSubKey;
|
||
char szBackData[MAX_PATH];
|
||
DWORD dwSize = 0, dwBkSize;
|
||
BOOL bRet = FALSE;
|
||
|
||
if ( ctx.wOSVer == _OSVER_WIN95 )
|
||
{
|
||
dwSize = sizeof( szBackData );
|
||
if ( RegQueryValueEx( hKey, c_szRegUninstPath, NULL, NULL, szBackData, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
dwSize = sizeof( DWORD );
|
||
if ( RegQueryValueEx( hKey, c_szRegUninstSize, NULL, NULL, (LPBYTE)&dwBkSize, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
if ( MyFileSize(szBackData) == dwBkSize )
|
||
{
|
||
bRet = TRUE;
|
||
return bRet;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// if you are here, the file backup info is OK. We check on reg backup info
|
||
if ( RegOpenKeyEx( hKey, REGSUBK_REGBK, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
|
||
{
|
||
HKEY hsubsubKey;
|
||
|
||
if ( RegOpenKeyEx( hSubKey, "0", 0, KEY_READ, &hsubsubKey) == ERROR_SUCCESS)
|
||
{
|
||
if ( (RegQueryInfoKey( hsubsubKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwSize,
|
||
NULL, NULL, NULL, NULL ) == ERROR_SUCCESS) && dwSize )
|
||
{
|
||
bRet = TRUE;
|
||
}
|
||
RegCloseKey( hsubsubKey );
|
||
}
|
||
RegCloseKey(hSubKey);
|
||
}
|
||
|
||
return bRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
BOOL VerifyBackupInfo( HKEY hKey, HKEY hCUKey )
|
||
{
|
||
char szBackData[MAX_PATH];
|
||
DWORD dwSize, dwBkSize = 0;
|
||
BOOL bRet = FALSE;
|
||
HKEY hSubKey = NULL;
|
||
|
||
if ( hKey )
|
||
{
|
||
// verify the backup file first
|
||
dwSize = sizeof( szBackData );
|
||
if ( RegQueryValueEx( hKey, REGVAL_BKFILE, NULL, NULL, szBackData, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
dwSize = sizeof( DWORD );
|
||
if ( RegQueryValueEx( hKey, REGVAL_BKSIZE, NULL, NULL, (LPBYTE)&dwBkSize, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
if ( MyFileSize(szBackData) == dwBkSize )
|
||
{
|
||
// if you are here, the file backup info is OK. We check on reg backup info
|
||
dwSize = sizeof( szBackData );
|
||
if ( (RegQueryValueEx( hKey, REGVAL_BKREGDATA, NULL, NULL, (LPBYTE)szBackData, &dwSize ) == ERROR_SUCCESS ) &&
|
||
( szBackData[0] == 'n' ) )
|
||
{
|
||
// no registry data backed up, so no need to verify further
|
||
bRet = TRUE;
|
||
}
|
||
else
|
||
{
|
||
if ( VerifyBackupRegData( hKey ) || (hCUKey && VerifyBackupRegData( hCUKey )) )
|
||
{
|
||
bRet = TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return bRet;
|
||
}
|
||
|
||
|
||
typedef HRESULT (*CHECKTOKENMEMBERSHIP)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
|
||
|
||
BOOL CheckToken(BOOL *pfIsAdmin)
|
||
{
|
||
BOOL bNewNT5check = FALSE;
|
||
HINSTANCE hAdvapi32 = NULL;
|
||
CHECKTOKENMEMBERSHIP pf;
|
||
PSID AdministratorsGroup;
|
||
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
||
hAdvapi32 = LoadLibrary("advapi32.dll");
|
||
if (hAdvapi32)
|
||
{
|
||
pf = (CHECKTOKENMEMBERSHIP)GetProcAddress(hAdvapi32, "CheckTokenMembership");
|
||
if (pf)
|
||
{
|
||
bNewNT5check = TRUE;
|
||
*pfIsAdmin = FALSE;
|
||
if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
|
||
{
|
||
pf(NULL, AdministratorsGroup, pfIsAdmin);
|
||
FreeSid(AdministratorsGroup);
|
||
}
|
||
}
|
||
FreeLibrary(hAdvapi32);
|
||
}
|
||
return bNewNT5check;
|
||
}
|
||
//***************************************************************************
|
||
//* Functions: IsNTAdmin() *
|
||
//* *
|
||
//* Returns TRUE if our process has admin priviliges. *
|
||
//* FALSE otherwise. *
|
||
//***************************************************************************
|
||
BOOL WINAPI IsNTAdmin( DWORD dwReserved, DWORD *lpdwReserved )
|
||
{
|
||
static int fIsAdmin = 2;
|
||
HANDLE hAccessToken;
|
||
PTOKEN_GROUPS ptgGroups;
|
||
DWORD dwReqSize;
|
||
UINT i;
|
||
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
PSID AdministratorsGroup;
|
||
BOOL bRet;
|
||
|
||
//
|
||
// If we have cached a value, return the cached value. Note I never
|
||
// set the cached value to false as I want to retry each time in
|
||
// case a previous failure was just a temp. problem (ie net access down)
|
||
//
|
||
|
||
bRet = FALSE;
|
||
ptgGroups = NULL;
|
||
|
||
if( fIsAdmin != 2 )
|
||
return (BOOL)fIsAdmin;
|
||
|
||
if (!CheckToken(&bRet))
|
||
{
|
||
if(!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hAccessToken ) )
|
||
return FALSE;
|
||
|
||
// See how big of a buffer we need for the token information
|
||
if(!GetTokenInformation( hAccessToken, TokenGroups, NULL, 0, &dwReqSize))
|
||
{
|
||
// GetTokenInfo should the buffer size we need - Alloc a buffer
|
||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||
ptgGroups = (PTOKEN_GROUPS) LocalAlloc(LMEM_FIXED, dwReqSize);
|
||
|
||
}
|
||
|
||
// ptgGroups could be NULL for a coupla reasons here:
|
||
// 1. The alloc above failed
|
||
// 2. GetTokenInformation actually managed to succeed the first time (possible?)
|
||
// 3. GetTokenInfo failed for a reason other than insufficient buffer
|
||
// Any of these seem justification for bailing.
|
||
|
||
// So, make sure it isn't null, then get the token info
|
||
if(ptgGroups && GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwReqSize, &dwReqSize))
|
||
{
|
||
if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) )
|
||
{
|
||
|
||
// Search thru all the groups this process belongs to looking for the
|
||
// Admistrators Group.
|
||
|
||
for( i=0; i < ptgGroups->GroupCount; i++ )
|
||
{
|
||
if( EqualSid(ptgGroups->Groups[i].Sid, AdministratorsGroup) )
|
||
{
|
||
// Yea! This guy looks like an admin
|
||
fIsAdmin = TRUE;
|
||
bRet = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
FreeSid(AdministratorsGroup);
|
||
}
|
||
}
|
||
if(ptgGroups)
|
||
LocalFree(ptgGroups);
|
||
|
||
// BUGBUG: Close handle here? doc's aren't clear whether this is needed.
|
||
CloseHandle(hAccessToken);
|
||
}
|
||
else if (bRet)
|
||
fIsAdmin = TRUE;
|
||
|
||
return bRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// MyFileCheckCallback()
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
UINT WINAPI MyFileCheckCallback( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 )
|
||
{
|
||
UINT retVal = FILEOP_SKIP;
|
||
|
||
switch(Notification)
|
||
{
|
||
case SPFILENOTIFY_STARTDELETE:
|
||
case SPFILENOTIFY_STARTRENAME:
|
||
case SPFILENOTIFY_STARTCOPY:
|
||
{
|
||
FILEPATHS *pFilePath;
|
||
PCSTR pTmp;
|
||
HANDLE hFile;
|
||
|
||
pFilePath = (FILEPATHS *)parm1;
|
||
|
||
if ( Notification == SPFILENOTIFY_STARTRENAME )
|
||
{
|
||
pTmp = pFilePath->Source;
|
||
}
|
||
else
|
||
{
|
||
pTmp = pFilePath->Target;
|
||
}
|
||
|
||
if ( FileExists(pTmp) ) // original file exists
|
||
{
|
||
// check if the File is in use
|
||
if ((hFile = CreateFile(pTmp, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
|
||
{
|
||
// File is in use which will trig the reboot if we actually install this section.
|
||
gst_hNeedReboot = S_OK;
|
||
|
||
// no need to continue if at least one file is in use, reboot is needed.
|
||
retVal = FILEOP_ABORT;
|
||
}
|
||
else
|
||
{
|
||
// file not in use
|
||
CloseHandle(hFile);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case SPFILENOTIFY_NEEDMEDIA:
|
||
return ( MyFileQueueCallback2( Context, Notification, parm1, parm2 ) );
|
||
|
||
default:
|
||
return ( pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) );
|
||
}
|
||
|
||
return( retVal );
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: RebootCheckOnInstall *
|
||
//* *
|
||
//* SYNOPSIS: Check reboot condition if given INF install section is *
|
||
//* installed. *
|
||
//* *
|
||
//* REQUIRES: hWnd: Handle to parent window. *
|
||
//* PCSTR The INF filename *
|
||
//* PCSTR INF Section name *
|
||
//* *
|
||
//* RETURNS: HRESULT: *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI RebootCheckOnInstall( HWND hWnd, PCSTR pszINF, PCSTR pszSection, DWORD dwFlags )
|
||
{
|
||
HRESULT hRet = S_FALSE;
|
||
char szSrcDir[MAX_PATH];
|
||
char szRealSec[100];
|
||
|
||
// Validate parameters:
|
||
// if INF filename info is missing, invalid.
|
||
if ( !pszINF || !*pszINF )
|
||
return hRet;
|
||
|
||
ctx.wQuietMode = QUIETMODE_ALL;
|
||
ctx.hWnd = hWnd;
|
||
|
||
if ( !IsFullPath( pszINF ) )
|
||
{
|
||
hRet = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
else
|
||
{
|
||
lstrcpy( szSrcDir, pszINF );
|
||
GetParentDir( szSrcDir );
|
||
}
|
||
|
||
hRet = CommonInstallInit( pszINF, pszSection, szRealSec, sizeof(szRealSec), NULL, FALSE, COREINSTALL_REBOOTCHECKONINSTALL );
|
||
if ( FAILED( hRet ) )
|
||
{
|
||
goto done;
|
||
}
|
||
|
||
hRet = SetLDIDs( pszINF, szRealSec, 0, NULL );
|
||
if ( FAILED( hRet ) )
|
||
{
|
||
goto done;
|
||
}
|
||
|
||
gst_hNeedReboot = S_FALSE;
|
||
hRet = ProcessFileSections( szRealSec, szSrcDir, MyFileCheckCallback );
|
||
if ( SUCCEEDED(hRet) || (gst_hNeedReboot == S_OK) )
|
||
{
|
||
hRet = gst_hNeedReboot;
|
||
}
|
||
|
||
done:
|
||
|
||
CommonInstallCleanup();
|
||
return hRet;
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: RegSaveRestoreOnINF *
|
||
//* *
|
||
//* SYNOPSIS: Save or restore the given INF section to given reg key *
|
||
//* *
|
||
//* REQUIRES: hWnd: Handle to parent window. *
|
||
//* PCSTR The Title if messagebox displayed *
|
||
//* PCSTR The INF filename *
|
||
//* PCSTR INF Section name *
|
||
//* HKEY The backup reg key handle *
|
||
//* DWORD Flags *
|
||
//* *
|
||
//* RETURNS: HRESULT: *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI RegSaveRestoreOnINF( HWND hWnd, PCSTR pcszTitle, PCSTR pszInf,
|
||
PCSTR pszSection, HKEY hLMBackKey, HKEY hCUBackKey, DWORD dwFlags )
|
||
{
|
||
HRESULT hRet = S_OK;
|
||
CHAR szRealInstallSection[100];
|
||
PSTR pszOldTitle;
|
||
HWND hwndOld;
|
||
BOOL bDoCommonInit = FALSE;
|
||
|
||
AdvWriteToLog("RegSaveRestoreOnINF: Inf=%1\r\n", pszInf);
|
||
hwndOld = ctx.hWnd;
|
||
pszOldTitle = ctx.lpszTitle;
|
||
|
||
if (hWnd != INVALID_HANDLE_VALUE)
|
||
ctx.hWnd = hWnd;
|
||
|
||
if ( dwFlags & ARSR_NOMESSAGES )
|
||
ctx.wQuietMode |= QUIETMODE_ALL;
|
||
|
||
if ( pcszTitle != NULL )
|
||
ctx.lpszTitle = (PSTR)pcszTitle;
|
||
|
||
if ( (dwFlags & ARSR_RESTORE) && !(dwFlags & ARSR_REMOVREGBKDATA) && !pszInf && !pszSection )
|
||
{
|
||
HRESULT hret1 = S_OK;
|
||
// restore all case
|
||
if ( hLMBackKey )
|
||
hRet = RegRestoreAllEx( hLMBackKey );
|
||
|
||
if ( ( hLMBackKey != hCUBackKey) && hCUBackKey )
|
||
hret1 = RegRestoreAllEx( hCUBackKey );
|
||
|
||
if ( FAILED(hret1) )
|
||
hRet = hret1;
|
||
|
||
goto done;
|
||
}
|
||
|
||
// params validation checks
|
||
if ( !IsFullPath(pszInf) || (!hLMBackKey && !hCUBackKey) || (dwFlags & ARSR_REGSECTION) && !pszSection
|
||
|| !(dwFlags & ARSR_RESTORE) && (dwFlags & ARSR_REMOVREGBKDATA) )
|
||
{
|
||
hRet = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
|
||
if ( !hCUBackKey )
|
||
hCUBackKey = hLMBackKey;
|
||
else if ( !hLMBackKey )
|
||
hLMBackKey = hCUBackKey;
|
||
|
||
bDoCommonInit = TRUE;
|
||
hRet = CommonInstallInit( pszInf, (dwFlags & ARSR_REGSECTION) ? NULL : pszSection, szRealInstallSection,
|
||
sizeof(szRealInstallSection), NULL, FALSE, 0 );
|
||
if ( FAILED( hRet ) )
|
||
{
|
||
goto done;
|
||
}
|
||
|
||
if ( dwFlags & ARSR_REGSECTION )
|
||
{
|
||
// process One Reg Section to do Save / restore based on given flags
|
||
hRet = ProcessOneRegSec( hWnd, pcszTitle, pszInf, pszSection, hLMBackKey, hCUBackKey, dwFlags, NULL );
|
||
}
|
||
else
|
||
{
|
||
// process All Reg sections
|
||
hRet = ProcessAllRegSec( hWnd, pcszTitle, pszInf, szRealInstallSection, hLMBackKey, hCUBackKey, dwFlags, NULL );
|
||
}
|
||
|
||
done:
|
||
if ( bDoCommonInit )
|
||
CommonInstallCleanup();
|
||
ctx.hWnd = hwndOld;
|
||
ctx.lpszTitle = pszOldTitle;
|
||
AdvWriteToLog("RegSaveRestoreOnINF: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: FileSaveRestoreOnINF *
|
||
//* *
|
||
//* SYNOPSIS: Save or restore Files defined by GenInstall INF section *
|
||
//* *
|
||
//* REQUIRES: hWnd: Handle to parent window. *
|
||
//* PCSTR The Title if messagebox displayed *
|
||
//* PCSTR The INF filename *
|
||
//* PCSTR INF Section name *
|
||
//* PCSTR backup directory path *
|
||
//* PCSTR backup file basename *
|
||
//* DWORD Flags *
|
||
//* *
|
||
//* RETURNS: HRESULT: *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI FileSaveRestoreOnINF( HWND hWnd, PCSTR pszTitle, PCSTR pszInf,
|
||
PCSTR pszSection, PCSTR pszBackupDir,
|
||
PCSTR pszBaseBkFile, DWORD dwFlags )
|
||
{
|
||
HRESULT hRet = S_OK;
|
||
char szRealInstallSection[100] = {0};
|
||
char szSrcDir[MAX_PATH] = {0};
|
||
PSTR pszOldTitle;
|
||
HWND hOldwnd;
|
||
BOOL bDoCommonInit = FALSE;
|
||
CHAR szCatalogName[MAX_PATH];
|
||
|
||
AdvWriteToLog("FileSaveRestoreOnINF: Inf=%1\r\n", (pszInf != NULL) ? pszInf : "NULL");
|
||
if ( dwFlags & AFSR_NOMESSAGES )
|
||
ctx.wQuietMode = QUIETMODE_ALL;
|
||
|
||
hOldwnd = ctx.hWnd;
|
||
if ( hWnd != INVALID_HANDLE_VALUE )
|
||
ctx.hWnd = hWnd;
|
||
|
||
pszOldTitle = ctx.lpszTitle;
|
||
if ( pszTitle != NULL )
|
||
ctx.lpszTitle = (PSTR)pszTitle;
|
||
|
||
// params validation checks
|
||
if ( !pszBackupDir || !*pszBackupDir || !pszBaseBkFile || !*pszBaseBkFile )
|
||
{
|
||
hRet = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
|
||
|
||
if ( (dwFlags & AFSR_RESTORE) && !pszInf && !pszSection )
|
||
{
|
||
dwFlags |= IE4_FRDOALL;
|
||
}
|
||
|
||
if ( !(dwFlags & IE4_FRDOALL) )
|
||
{
|
||
if ( !IsFullPath(pszInf) )
|
||
{
|
||
hRet = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
else
|
||
{
|
||
bDoCommonInit = TRUE;
|
||
hRet = CommonInstallInit( pszInf, pszSection, szRealInstallSection,
|
||
sizeof(szRealInstallSection), NULL, FALSE, 0 );
|
||
if ( FAILED( hRet ) )
|
||
{
|
||
goto done;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pszInf != NULL)
|
||
{
|
||
lstrcpy( szSrcDir, pszInf );
|
||
GetParentDir( szSrcDir );
|
||
}
|
||
|
||
// get the catalog name, if specified
|
||
ZeroMemory(szCatalogName, sizeof(szCatalogName));
|
||
|
||
if (pszInf == NULL)
|
||
{
|
||
CHAR szFullCatalogName[MAX_PATH];
|
||
|
||
// NOTE: assume that the catalog name is <BaseBkFile>.cat.
|
||
// can't use the REGKEY_SAVERESTORE key to read the catalog name
|
||
// because this API doesn't go thru SaveRestoreInfo which updates
|
||
// the REGKEY_SAVERESTORE key.
|
||
|
||
// check if the catalog file exists in the BackupDir
|
||
lstrcpy(szFullCatalogName, pszBackupDir);
|
||
AddPath(szFullCatalogName, pszBaseBkFile);
|
||
lstrcat(szFullCatalogName, ".cat");
|
||
if (FileExists(szFullCatalogName))
|
||
wsprintf(szCatalogName, "%s.cat", pszBaseBkFile);
|
||
}
|
||
else
|
||
GetTranslatedString(pszInf, szRealInstallSection, ADVINF_CATALOG_NAME, szCatalogName, sizeof(szCatalogName), NULL);
|
||
|
||
if (*szCatalogName)
|
||
{
|
||
// load sfc.dll and the relevant proc's
|
||
if (!LoadSfcDLL())
|
||
{
|
||
// couldn't load -- so empty out CatalogName
|
||
*szCatalogName = '\0';
|
||
}
|
||
}
|
||
|
||
// Process all the INF file sections
|
||
hRet = ProcessAllFiles( hWnd, szRealInstallSection, szSrcDir, pszBackupDir, pszBaseBkFile, szCatalogName, NULL, dwFlags );
|
||
|
||
done:
|
||
UnloadSfcDLL();
|
||
if ( bDoCommonInit )
|
||
CommonInstallCleanup();
|
||
ctx.lpszTitle = pszOldTitle;
|
||
ctx.hWnd = hOldwnd;
|
||
AdvWriteToLog("FileSaveRestoreOnINF: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
|
||
}
|
||
#if 0
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// MyGetSpecialFolder( int )
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
HRESULT MyGetSpecialFolder( HWND hwnd, int nFd, PSTR szPath )
|
||
{
|
||
LPITEMIDLIST pidl;
|
||
HRESULT hRet;
|
||
|
||
*szPath = 0;
|
||
|
||
hRet = SHGetSpecialFolderLocation( hwnd, nFd, &pidl );
|
||
if ( hRet == NOERROR )
|
||
{
|
||
if ( !SHGetPathFromIDList( pidl, szPath ) )
|
||
{
|
||
hRet = E_INVALIDARG;
|
||
}
|
||
}
|
||
return hRet;
|
||
}
|
||
#endif
|
||
|
||
void MySetSpecialFolder( HKEY hkey, PCSTR pcszValueN, PSTR pszPath )
|
||
{
|
||
DWORD dwTmp;
|
||
|
||
if ( (ctx.wOSVer >= _OSVER_WINNT40) && AddEnvInPath( pszPath, pszPath ) )
|
||
dwTmp = REG_EXPAND_SZ;
|
||
else
|
||
dwTmp = REG_SZ;
|
||
|
||
RegSetValueExA( hkey, pcszValueN, 0, dwTmp, pszPath, lstrlen(pszPath)+1 );
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// SetSysPathsInReg()
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
void SetSysPathsInReg()
|
||
{
|
||
HKEY hkey;
|
||
char szPath[MAX_PATH];
|
||
char szAS[100];
|
||
DWORD dwTmp;
|
||
int i = 0;
|
||
PSTR pszValName, pszKeyName;
|
||
|
||
// Add StartUp, StartMenu, Programs and accessories sys pathes to registries for further ref
|
||
// only if it is not set before.
|
||
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS )
|
||
{
|
||
// Program Files path
|
||
dwTmp = sizeof( szPath );
|
||
if ( RegQueryValueEx( hkey, REGVAL_PROGRAMFILESPATH, 0, NULL, (LPBYTE)szPath, &dwTmp ) != ERROR_SUCCESS )
|
||
{
|
||
if ( GetProgramFilesDir( szPath, sizeof(szPath) ) )
|
||
{
|
||
MySetSpecialFolder( hkey, REGVAL_PROGRAMFILESPATH, szPath );
|
||
}
|
||
}
|
||
|
||
// use wordpad.inf to look into the strings
|
||
GetWindowsDirectory( szPath, sizeof(szPath) );
|
||
AddPath( szPath, "inf\\wordpad.inf" );
|
||
|
||
// accessories Names
|
||
for ( i=0; i<2; i++ )
|
||
{
|
||
if ( i == 0 )
|
||
{
|
||
// start menu name
|
||
pszValName = REGVAL_SM_ACCESSORIES;
|
||
pszKeyName = "APPS_DESC";
|
||
}
|
||
else
|
||
{
|
||
pszValName = REGVAL_PF_ACCESSORIES;
|
||
if ( ctx.wOSVer >= _OSVER_WINNT40 )
|
||
pszKeyName = "APPS_DESC";
|
||
else
|
||
pszKeyName = "Accessories";
|
||
}
|
||
|
||
dwTmp = sizeof( szAS );
|
||
if ( RegQueryValueEx( hkey, pszValName, 0, NULL, (LPBYTE)szAS, &dwTmp ) != ERROR_SUCCESS )
|
||
{
|
||
// need to open the new INF so save the current context
|
||
if (SaveGlobalContext())
|
||
{
|
||
if ( FAILED(GetTranslatedString(szPath, "Strings", pszKeyName, szAS, sizeof(szAS), NULL)))
|
||
{
|
||
lstrcpy(szAS, "Accessories");
|
||
}
|
||
RegSetValueExA( hkey, pszValName, 0, REG_SZ, szAS, lstrlen(szAS)+1 );
|
||
RestoreGlobalContext();
|
||
}
|
||
}
|
||
}
|
||
|
||
RegCloseKey(hkey);
|
||
}
|
||
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// ProcessPerUserSec
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT ProcessPerUserSec( PCSTR pcszInf, PCSTR pcszSec )
|
||
{
|
||
char szSec[MAX_PATH];
|
||
DWORD dwTmp;
|
||
HRESULT hRet = S_OK;
|
||
PERUSERSECTION PU_Sec = {0};
|
||
|
||
|
||
if (SUCCEEDED(GetTranslatedString(pcszInf, pcszSec, ADVINF_PERUSER, szSec, sizeof(szSec), NULL)))
|
||
{
|
||
AdvWriteToLog("ProcessPerUserSec: \r\n");
|
||
AdvWriteToLog("Inf=%1, InstallSec=%2, PerUserInstall=%3\r\n", pcszInf, pcszSec, szSec);
|
||
// get GUID to create subkey
|
||
if ( SUCCEEDED( GetTranslatedString( pcszInf, szSec, ADVINF_PU_GUID, PU_Sec.szGUID, sizeof(PU_Sec.szGUID), &dwTmp) ) )
|
||
{
|
||
PU_Sec.dwIsInstalled = GetTranslatedInt(pcszInf, szSec, ADVINF_PU_ISINST, 999);
|
||
PU_Sec.bRollback = (BOOL)GetTranslatedInt(pcszInf, szSec, ADVINF_PU_ROLLBK, 0);
|
||
GetTranslatedString( pcszInf, szSec, ADVINF_PU_DSP, PU_Sec.szDispName, sizeof(PU_Sec.szDispName), &dwTmp);
|
||
GetTranslatedString( pcszInf, szSec, ADVINF_PU_VER, PU_Sec.szVersion, sizeof(PU_Sec.szVersion), &dwTmp);
|
||
GetTranslatedString( pcszInf, szSec, ADVINF_PU_STUB, PU_Sec.szStub, sizeof(PU_Sec.szStub), &dwTmp);
|
||
GetTranslatedString( pcszInf, szSec, ADVINF_PU_LANG, PU_Sec.szLocale, sizeof(PU_Sec.szLocale), &dwTmp);
|
||
GetTranslatedString( pcszInf, szSec, ADVINF_PU_CID, PU_Sec.szCompID, sizeof(PU_Sec.szCompID), &dwTmp);
|
||
|
||
// since we are close to beta1, we may hack here to avoid the external comp changes
|
||
//if (IsThisRollbkUninst(PU_Sec.szGUID))
|
||
// PU_Sec.bRollback = TRUE;
|
||
|
||
hRet = SetPerUserSecValues(&PU_Sec);
|
||
}
|
||
else
|
||
{
|
||
AdvWriteToLog("Failure: No GUID specified\r\n");
|
||
//hRet = E_FAIL; //unknown GUID, advpack will do nothing for this comp!
|
||
}
|
||
AdvWriteToLog("ProcessPerUserSec: End hr=0x%1!x!\r\n", hRet);
|
||
}
|
||
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// SetPerUserSecValues help functions
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
BOOL CopyRegValue( HKEY hFromkey, HKEY hTokey, LPCSTR pszFromVal, LPCSTR pszToVal)
|
||
{
|
||
DWORD dwSize,dwType;
|
||
char szBuf[BUF_1K];
|
||
BOOL bRet = FALSE;
|
||
|
||
//backup the older reg values
|
||
//AdvWriteToLog("CopyRegValue:");
|
||
dwSize = sizeof(szBuf);
|
||
if (RegQueryValueEx(hFromkey, pszFromVal, NULL, &dwType, (LPBYTE)szBuf, &dwSize)==ERROR_SUCCESS)
|
||
{
|
||
if (RegSetValueEx(hTokey, pszToVal, 0, dwType, szBuf, lstrlen(szBuf)+1)==ERROR_SUCCESS)
|
||
{
|
||
//AdvWriteToLog("From %1 to %2: %3", pszFromVal, pszToVal, szBuf);
|
||
bRet = TRUE;
|
||
}
|
||
}
|
||
//AdvWriteToLog("\r\n");
|
||
return bRet;
|
||
}
|
||
|
||
void SetSecRegValues( HKEY hSubKey, PPERUSERSECTION pPU, BOOL bUseStubWrapper )
|
||
{
|
||
char szBuf[BUF_1K];
|
||
|
||
if (pPU->szStub[0])
|
||
{
|
||
if (ctx.wOSVer >= _OSVER_WINNT40)
|
||
{
|
||
AddEnvInPath( pPU->szStub, szBuf );
|
||
if (bUseStubWrapper)
|
||
RegSetValueEx( hSubKey, REGVAL_REALSTUBPATH, 0, REG_EXPAND_SZ, szBuf, lstrlen(szBuf)+1 );
|
||
else
|
||
RegSetValueEx( hSubKey, ADVINF_PU_STUB, 0, REG_EXPAND_SZ, szBuf, lstrlen(szBuf)+1 );
|
||
}
|
||
else
|
||
{
|
||
if (bUseStubWrapper)
|
||
RegSetValueEx( hSubKey, REGVAL_REALSTUBPATH, 0, REG_SZ, pPU->szStub, lstrlen(pPU->szStub)+1 );
|
||
else
|
||
RegSetValueEx( hSubKey, ADVINF_PU_STUB, 0, REG_SZ, pPU->szStub, lstrlen(pPU->szStub)+1 );
|
||
}
|
||
}
|
||
|
||
if (pPU->szVersion[0])
|
||
{
|
||
RegSetValueEx( hSubKey, ADVINF_PU_VER, 0, REG_SZ, pPU->szVersion, lstrlen(pPU->szVersion)+1 );
|
||
// if we update the base version value, delete the previous QFE version
|
||
RegDeleteValue( hSubKey, "QFEVersion" );
|
||
}
|
||
|
||
if (pPU->szLocale[0])
|
||
RegSetValueEx( hSubKey, ADVINF_PU_LANG, 0, REG_SZ, pPU->szLocale, lstrlen(pPU->szLocale)+1 );
|
||
|
||
if (pPU->szCompID[0])
|
||
RegSetValueEx( hSubKey, ADVINF_PU_CID, 0, REG_SZ, pPU->szCompID, lstrlen(pPU->szCompID)+1 );
|
||
|
||
if (pPU->szDispName[0])
|
||
RegSetValueEx( hSubKey, "", 0, REG_SZ, pPU->szDispName, lstrlen(pPU->szDispName)+1 );
|
||
|
||
RegSetValueEx( hSubKey, ADVINF_PU_ISINST, 0, REG_DWORD, (LPBYTE)&(pPU->dwIsInstalled), sizeof(DWORD) );
|
||
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// SetPerUserSecValues
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT WINAPI SetPerUserSecValues( PPERUSERSECTION pPU )
|
||
{
|
||
HKEY hkey = NULL;
|
||
HKEY hSubKey = NULL;
|
||
HKEY hCUKey;
|
||
HRESULT hRet = S_OK;
|
||
DWORD dwTmp, dwSize;
|
||
char szBuf[BUF_1K];
|
||
BOOL bStubWrapper = FALSE;
|
||
|
||
AdvWriteToLog("SetPerUserSecValues:\r\n");
|
||
|
||
if ( (pPU == NULL) || (pPU->szGUID[0]==0) )
|
||
{
|
||
AdvWriteToLog("SetPerUserSecValues: End Warning: No Data\r\n");
|
||
return hRet;
|
||
}
|
||
|
||
AdvWriteToLog("Input params: %1,%2,%3,%4,%5,%6\r\n",
|
||
pPU->szGUID, pPU->szDispName, pPU->szLocale, pPU->szStub, pPU->szVersion,
|
||
pPU->dwIsInstalled ? "1" : "0");
|
||
|
||
if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, c_szActiveSetupKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,
|
||
NULL, &hkey, &dwTmp ) != ERROR_SUCCESS )
|
||
{
|
||
hRet = E_FAIL;
|
||
AdvWriteToLog("Failure: Cannot open %1 key\r\n", c_szActiveSetupKey);
|
||
goto done;
|
||
}
|
||
|
||
if ( RegCreateKeyEx( hkey, pPU->szGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
|
||
NULL, &hSubKey, &dwTmp ) != ERROR_SUCCESS )
|
||
{
|
||
hRet = E_FAIL;
|
||
AdvWriteToLog("Failure: Cannot create %1 key\r\n", pPU->szGUID);
|
||
goto done;
|
||
}
|
||
|
||
if (pPU->dwIsInstalled == 1)
|
||
{
|
||
// This is the install case. Need to do the following tasks:
|
||
//
|
||
// 1) If the given GUID key exists, has IsInstalled set to 1. Then check
|
||
// if the existing major version is smaller than the one to be installed. If so,
|
||
// backup the existing Version, Locale, StubPath values to OldVersion, OldLocale,
|
||
// OldStubPath first. Set the StubPath to advpack Install Stub Wrapper function.
|
||
// Set the Version, Locale, InstallStubPath based on the current INF PerUserInstall section values.
|
||
// 2) If there is no exist GUID key or the existing GUID key has IsInstalled set to 0,
|
||
// just set the current values and set IsInstalled to 1. ( as it is today)
|
||
// 3) Delete {GUID}.Restore key if exists.
|
||
//
|
||
dwSize = sizeof(DWORD);
|
||
if ((pPU->bRollback) &&
|
||
(RegQueryValueEx(hSubKey, ADVINF_PU_ISINST, NULL, NULL, (LPBYTE)&dwTmp, &dwSize)==ERROR_SUCCESS) &&
|
||
(dwTmp == 1) )
|
||
{
|
||
WORD wRegVer[4], wInfVer[4];
|
||
|
||
// case (1)
|
||
dwSize = sizeof(szBuf);
|
||
if (RegQueryValueEx(hSubKey, ADVINF_PU_VER, NULL, NULL, (LPBYTE)szBuf, &dwSize)==ERROR_SUCCESS)
|
||
{
|
||
ConvertVersionString(szBuf, wRegVer, ',');
|
||
if (pPU->szVersion[0])
|
||
{
|
||
ConvertVersionString(pPU->szVersion, wInfVer, ',');
|
||
// we only rollback to previous major version now so we only compare major ver.
|
||
if ( wRegVer[0] < wInfVer[0] )
|
||
{
|
||
CopyRegValue(hSubKey, hSubKey, "", REGVAL_OLDDISPN);
|
||
CopyRegValue(hSubKey, hSubKey, ADVINF_PU_VER, REGVAL_OLDVER);
|
||
CopyRegValue(hSubKey, hSubKey, ADVINF_PU_LANG, REGVAL_OLDLANG);
|
||
if (CopyRegValue(hSubKey, hSubKey, ADVINF_PU_STUB, REGVAL_OLDSTUB))
|
||
{
|
||
CopyRegValue(hSubKey, hSubKey, REGVAL_REALSTUBPATH, REGVAL_OLDREALSTUBPATH);
|
||
|
||
wsprintf(szBuf, ADV_INSTSTUBWRAPPER, pPU->szGUID);
|
||
RegSetValueEx( hSubKey, ADVINF_PU_STUB, 0, REG_SZ, szBuf, lstrlen(szBuf)+1 );
|
||
bStubWrapper = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// the case user have already backup the previous state, we only update
|
||
// the real stub path since its StubPath will point to Wrapper function
|
||
dwSize = sizeof(szBuf);
|
||
if (RegQueryValueEx(hSubKey, REGVAL_REALSTUBPATH, NULL, NULL, (LPBYTE)szBuf, &dwSize)==ERROR_SUCCESS)
|
||
bStubWrapper = TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// case (2)
|
||
SetSecRegValues(hSubKey, pPU, bStubWrapper);
|
||
|
||
// case (3)
|
||
lstrcpy(szBuf, pPU->szGUID);
|
||
lstrcat(szBuf, ".Restore");
|
||
RegDeleteKey(hkey, szBuf);
|
||
}
|
||
else if (pPU->dwIsInstalled == 0)
|
||
{
|
||
// This is the uninstall case, need to do the following tasks
|
||
//
|
||
// 1) If the {GUID} key OldVersion, OldStubpath, OldLocale exist, set them back to Version, Locale StubPath value and set IsInstall to 1 to reflect the current install state;
|
||
// 2) Then, Create the '{GUID}.Restore' key with the values of the version ( adjusted max( GUID<49>s Version, GUID<49>s MaxRestoreVersion)+1 ), locale, stubpath calling
|
||
// advpack.dll UserStubWraper with the {GUID}.Restore as param and the RestoreStubPath with the INF StubPath value. Set IsInstalled to 1.
|
||
// 3) If none of the above is applied, just set the current GUID key IsInstall to 0 like it is now.
|
||
//
|
||
if (CopyRegValue(hSubKey, hSubKey, REGVAL_OLDVER, ADVINF_PU_VER))
|
||
{
|
||
HKEY hResKey;
|
||
|
||
// case (1)
|
||
// restore the old version data
|
||
CopyRegValue(hSubKey, hSubKey, REGVAL_OLDDISPN, "");
|
||
CopyRegValue(hSubKey, hSubKey, REGVAL_OLDLANG, ADVINF_PU_LANG);
|
||
if(CopyRegValue(hSubKey, hSubKey, REGVAL_OLDSTUB, ADVINF_PU_STUB))
|
||
{
|
||
CopyRegValue(hSubKey, hSubKey, REGVAL_OLDREALSTUBPATH, REGVAL_REALSTUBPATH);
|
||
|
||
// case (2)
|
||
lstrcpy(szBuf, pPU->szGUID);
|
||
lstrcat(szBuf, ".Restore" );
|
||
if (RegCreateKeyEx(hkey, szBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
|
||
NULL, &hResKey, &dwTmp ) == ERROR_SUCCESS )
|
||
{
|
||
wsprintf(szBuf, ADV_UNINSTSTUBWRAPPER, pPU->szGUID);
|
||
RegSetValueEx(hResKey, ADVINF_PU_STUB, 0, REG_SZ, szBuf, lstrlen(szBuf)+1);
|
||
bStubWrapper = TRUE;
|
||
|
||
// also copy DontAskFlag
|
||
CopyRegValue(hSubKey, hResKey, c_szRegDontAskValue, c_szRegDontAskValue);
|
||
|
||
SetSecRegValues(hResKey, pPU, bStubWrapper);
|
||
RegCloseKey(hResKey);
|
||
}
|
||
}
|
||
|
||
// cleanup the backup data
|
||
RegDeleteValue(hSubKey, REGVAL_OLDDISPN);
|
||
RegDeleteValue(hSubKey, REGVAL_OLDLANG);
|
||
RegDeleteValue(hSubKey, REGVAL_OLDVER);
|
||
RegDeleteValue(hSubKey, REGVAL_OLDSTUB);
|
||
RegDeleteValue(hSubKey, REGVAL_OLDREALSTUBPATH);
|
||
}
|
||
else
|
||
{
|
||
// case (3)
|
||
SetSecRegValues(hSubKey, pPU, bStubWrapper);
|
||
}
|
||
}
|
||
|
||
done:
|
||
if ( hSubKey )
|
||
RegCloseKey( hSubKey );
|
||
|
||
if ( hkey )
|
||
RegCloseKey( hkey );
|
||
|
||
AdvWriteToLog("SetPerUserSecValues: End hr=0x%1!x!\r\n", hRet);
|
||
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// PerUser Install stub wrapper
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT WINAPI UserInstStubWrapper(HWND hwnd, HINSTANCE hInst, LPSTR pszParams, INT nShow)
|
||
{
|
||
HKEY hkList, hkcuGUIDRes, hkGUID;
|
||
char szBuf[MAX_PATH];
|
||
DWORD cbData,dwType;
|
||
HRESULT hRet = S_OK;
|
||
|
||
/* Component is an uninstall stub. */
|
||
if ((pszParams == NULL) || (*pszParams == 0))
|
||
{
|
||
hRet = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
||
return hRet;
|
||
}
|
||
|
||
AdvWriteToLog("UserInstStubWrapper:\r\n");
|
||
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveSetupKey, 0,
|
||
KEY_READ, &hkList) == ERROR_SUCCESS)
|
||
{
|
||
if ( RegOpenKeyEx(hkList, pszParams, 0, KEY_READ, &hkGUID) == ERROR_SUCCESS)
|
||
{
|
||
// run the real stub first
|
||
cbData = sizeof(szBuf);
|
||
if ((RegQueryValueEx(hkGUID, REGVAL_REALSTUBPATH, NULL, &dwType,
|
||
(LPBYTE)szBuf, &cbData) == ERROR_SUCCESS) && szBuf[0])
|
||
{
|
||
char szBuf2[MAX_PATH*2];
|
||
|
||
if (dwType == REG_EXPAND_SZ)
|
||
ExpandEnvironmentStrings(szBuf, szBuf2, sizeof(szBuf2));
|
||
else
|
||
lstrcpy(szBuf2,szBuf);
|
||
|
||
if ( LaunchAndWait( szBuf2, NULL, NULL, INFINITE, RUNCMDS_QUIET ) == E_FAIL )
|
||
{
|
||
char szMessage[BIG_STRING];
|
||
|
||
hRet = HRESULT_FROM_WIN32(GetLastError());
|
||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||
szMessage, sizeof(szMessage), NULL );
|
||
ErrorMsg2Param( ctx.hWnd, IDS_ERR_CREATE_PROCESS, szBuf2, szMessage );
|
||
RegCloseKey(hkGUID);
|
||
RegCloseKey(hkList);
|
||
return hRet;
|
||
}
|
||
}
|
||
|
||
// create {GUID}.Restore to enable the uninstall later
|
||
lstrcpy(szBuf, c_szActiveSetupKey);
|
||
AddPath(szBuf, pszParams);
|
||
lstrcat(szBuf,".Restore");
|
||
if (RegCreateKeyEx( HKEY_CURRENT_USER, szBuf, 0, NULL, REG_OPTION_NON_VOLATILE,
|
||
KEY_READ|KEY_WRITE, NULL, &hkcuGUIDRes, &cbData) == ERROR_SUCCESS)
|
||
{
|
||
CopyRegValue(hkGUID, hkcuGUIDRes, ADVINF_PU_VER, ADVINF_PU_VER);
|
||
CopyRegValue(hkGUID, hkcuGUIDRes, ADVINF_PU_LANG, ADVINF_PU_LANG);
|
||
|
||
RegCloseKey(hkcuGUIDRes);
|
||
}
|
||
RegCloseKey(hkGUID);
|
||
}
|
||
RegCloseKey(hkList);
|
||
}
|
||
AdvWriteToLog("UserInstStubWrapper: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------
|
||
//
|
||
// PerUser uninstall stub wrapper
|
||
//
|
||
//-----------------------------------------------------------------------------------------
|
||
|
||
HRESULT WINAPI UserUnInstStubWrapper(HWND hwnd, HINSTANCE hInst, LPSTR pszParams, INT nShow)
|
||
{
|
||
HKEY hkList, hkGUIDRes, hkGUID, hkcuGUID;
|
||
char szBuf[MAX_PATH];
|
||
DWORD cbData, dwType;
|
||
HRESULT hRet = S_OK;
|
||
|
||
|
||
/* Component is an uninstall stub. */
|
||
if ((pszParams == NULL) || (*pszParams == 0))
|
||
{
|
||
hRet = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
||
return hRet;
|
||
}
|
||
AdvWriteToLog("UserUnInstStubWrapper:\r\n");
|
||
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveSetupKey, 0,
|
||
KEY_READ|KEY_WRITE, &hkList) == ERROR_SUCCESS)
|
||
{
|
||
// restore the Installed IE version from HKLM
|
||
if ( RegOpenKeyEx( hkList, pszParams, 0, KEY_READ, &hkGUID) == ERROR_SUCCESS)
|
||
{
|
||
lstrcpy(szBuf, c_szActiveSetupKey);
|
||
AddPath(szBuf, pszParams);
|
||
if ( RegOpenKeyEx( HKEY_CURRENT_USER, szBuf, 0,
|
||
KEY_READ|KEY_WRITE, &hkcuGUID) == ERROR_SUCCESS)
|
||
{
|
||
CopyRegValue(hkGUID, hkcuGUID, ADVINF_PU_VER, ADVINF_PU_VER);
|
||
CopyRegValue(hkGUID, hkcuGUID, ADVINF_PU_LANG, ADVINF_PU_LANG);
|
||
RegCloseKey(hkcuGUID);
|
||
}
|
||
RegCloseKey(hkGUID);
|
||
}
|
||
|
||
// run the stub if needed
|
||
lstrcpy(szBuf, pszParams);
|
||
lstrcat(szBuf,".Restore");
|
||
|
||
if (RegOpenKeyEx( hkList, szBuf, 0, KEY_READ, &hkGUIDRes) == ERROR_SUCCESS)
|
||
{
|
||
cbData = sizeof(szBuf);
|
||
if ((RegQueryValueEx(hkGUIDRes, REGVAL_REALSTUBPATH, NULL, &dwType,
|
||
(LPBYTE)szBuf, &cbData) == ERROR_SUCCESS) && szBuf[0])
|
||
{
|
||
char szBuf2[MAX_PATH*2];
|
||
|
||
if (dwType == REG_EXPAND_SZ)
|
||
ExpandEnvironmentStrings(szBuf, szBuf2, sizeof(szBuf2));
|
||
else
|
||
lstrcpy(szBuf2,szBuf);
|
||
|
||
if ( LaunchAndWait( szBuf2, NULL, NULL, INFINITE, RUNCMDS_QUIET ) == E_FAIL )
|
||
{
|
||
char szMessage[BIG_STRING];
|
||
|
||
hRet = HRESULT_FROM_WIN32(GetLastError());
|
||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||
szMessage, sizeof(szMessage), NULL );
|
||
ErrorMsg2Param( ctx.hWnd, IDS_ERR_CREATE_PROCESS, szBuf2, szMessage );
|
||
}
|
||
}
|
||
RegCloseKey(hkGUIDRes);
|
||
}
|
||
RegCloseKey(hkList);
|
||
}
|
||
AdvWriteToLog("UserUnInstStubWrapper: End hr=0x%1!x!\r\n", hRet);
|
||
return hRet;
|
||
}
|
||
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: TranslateInfStringEx *
|
||
//* *
|
||
//* SYNOPSIS: Translates a string in an Advanced inf file -- replaces *
|
||
//* LDIDs with the directory. This new API requires called to *
|
||
//* init the INF first for efficiency. *
|
||
//* *
|
||
//* REQUIRES: *
|
||
//* *
|
||
//* RETURNS: *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI TranslateInfStringEx( HINF hInf, PCSTR pszInfFilename,
|
||
PCSTR pszTranslateSection, PCSTR pszTranslateKey,
|
||
PSTR pszBuffer, DWORD dwBufferSize,
|
||
PDWORD pdwRequiredSize, PVOID pvReserved )
|
||
{
|
||
HRESULT hReturnCode = S_OK;
|
||
|
||
// Validate parameters
|
||
if ( (hInf != ctx.hInf) || pszInfFilename == NULL || pszTranslateSection == NULL
|
||
|| pszTranslateKey == NULL || pdwRequiredSize == NULL )
|
||
{
|
||
hReturnCode = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
|
||
hReturnCode = GetTranslatedString( pszInfFilename, pszTranslateSection, pszTranslateKey,
|
||
pszBuffer, dwBufferSize, pdwRequiredSize );
|
||
|
||
done:
|
||
return hReturnCode;
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: OpenINFEngine *
|
||
//* *
|
||
//* SYNOPSIS: Initialize the INF Engine and open INF file for use. *
|
||
//* *
|
||
//* REQUIRES: *
|
||
//* *
|
||
//* RETURNS: HINF hInf the opened INF file handle *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI OpenINFEngine( PCSTR pszInfFilename, PCSTR pszInstallSection,
|
||
DWORD dwFlags, HINF *phInf, PVOID pvReserved )
|
||
{
|
||
HRESULT hReturnCode = S_OK;
|
||
CHAR szRealInstallSection[256];
|
||
BOOL fSaveContext = FALSE;
|
||
|
||
// Validate parameters
|
||
if ( (pszInfFilename == NULL) || !phInf)
|
||
{
|
||
hReturnCode = E_INVALIDARG;
|
||
goto done;
|
||
}
|
||
|
||
*phInf = NULL;
|
||
|
||
if (!SaveGlobalContext())
|
||
{
|
||
hReturnCode = E_OUTOFMEMORY;
|
||
goto done;
|
||
}
|
||
fSaveContext = TRUE;
|
||
|
||
ctx.wQuietMode = QUIETMODE_ALL;
|
||
|
||
|
||
hReturnCode = CommonInstallInit( pszInfFilename, pszInstallSection,
|
||
szRealInstallSection, sizeof(szRealInstallSection), NULL, FALSE, 0 );
|
||
if ( FAILED( hReturnCode ) ) {
|
||
goto done;
|
||
}
|
||
|
||
if ( ctx.dwSetupEngine != ENGINE_SETUPAPI )
|
||
{
|
||
hReturnCode = E_UNEXPECTED;
|
||
goto done;
|
||
}
|
||
|
||
hReturnCode = SetLDIDs( (LPSTR)pszInfFilename, szRealInstallSection, 0, NULL );
|
||
if ( FAILED( hReturnCode ) ) {
|
||
goto done;
|
||
}
|
||
|
||
*phInf = ctx.hInf;
|
||
|
||
done:
|
||
if ( FAILED(hReturnCode) )
|
||
{
|
||
CommonInstallCleanup();
|
||
if ( fSaveContext )
|
||
{
|
||
RestoreGlobalContext();
|
||
}
|
||
}
|
||
|
||
return hReturnCode;
|
||
}
|
||
|
||
//***************************************************************************
|
||
//* *
|
||
//* NAME: CloseINFEngine *
|
||
//* *
|
||
//* SYNOPSIS: Close the INF Engine and the current INF file. *
|
||
//* *
|
||
//* REQUIRES: *
|
||
//* *
|
||
//* RETURNS: HINF hInf the opened INF file handle *
|
||
//* *
|
||
//***************************************************************************
|
||
HRESULT WINAPI CloseINFEngine( HINF hInf )
|
||
{
|
||
if ( hInf == ctx.hInf )
|
||
{
|
||
CommonInstallCleanup();
|
||
RestoreGlobalContext();
|
||
}
|
||
else
|
||
return E_INVALIDARG;
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
#define BACKUPBASE "%s.%03d"
|
||
|
||
BOOL GetUniBackupName( HKEY hKey, LPSTR pszBackupBase, DWORD dwInSize, LPCSTR pszBackupPath, LPCSTR pszModule )
|
||
{
|
||
char szBuf[MAX_PATH];
|
||
DWORD dwSize;
|
||
BOOL bFound = FALSE;
|
||
|
||
|
||
// 1st check to see if the backup filename already in registry, if so, we use it.
|
||
dwSize = sizeof( szBuf );
|
||
if ( RegQueryValueEx(hKey, REGVAL_BKFILE, NULL, NULL, szBuf, &dwSize) == ERROR_SUCCESS )
|
||
{
|
||
LPSTR pszTmp;
|
||
|
||
pszTmp = ANSIStrRChr( szBuf, '\\' );
|
||
if ( pszTmp )
|
||
{
|
||
lstrcpy( pszBackupBase, CharNext(pszTmp) );
|
||
pszTmp = ANSIStrRChr( pszBackupBase, '.' );
|
||
if ( pszTmp && (lstrcmpi(pszTmp, ".dat")==0) )
|
||
{
|
||
*pszTmp = 0;
|
||
}
|
||
bFound = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( !bFound )
|
||
{
|
||
int i;
|
||
char szFilePath[MAX_PATH];
|
||
|
||
// 2nd, check to see if the default Module name has been used as the basename
|
||
lstrcpy( szFilePath, pszBackupPath );
|
||
AddPath( szFilePath, pszModule );
|
||
lstrcat( szFilePath, ".dat" );
|
||
if ( !FileExists(szFilePath) )
|
||
{
|
||
bFound = TRUE;
|
||
lstrcpy( pszBackupBase, pszModule );
|
||
}
|
||
else
|
||
{
|
||
for ( i = 1; i<999; i++ )
|
||
{
|
||
wsprintf( szBuf, BACKUPBASE, pszModule, i );
|
||
lstrcpy( szFilePath, pszBackupPath);
|
||
AddPath( szFilePath, szBuf );
|
||
lstrcat( szFilePath, ".dat" );
|
||
if ( !FileExists(szFilePath) )
|
||
{
|
||
bFound = TRUE;
|
||
lstrcpy( pszBackupBase, szBuf );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return bFound;
|
||
}
|
||
|
||
|
||
BOOL GetUniHiveKeyName( HKEY hKey, LPSTR pszRegHiveKey, DWORD dwInSize, LPCSTR pszBackupPath )
|
||
{
|
||
char szBuf[MAX_PATH];
|
||
DWORD dwSize;
|
||
BOOL bFound = FALSE;
|
||
|
||
// For each component, we always try to get the HIVE key from the reg backup filename
|
||
// 4 possibilities exist:
|
||
// Case 1: Reg uinstall file exists but IE4RegBackup doesn't exist
|
||
// - user is upgrading over IE4, load the file as a hive
|
||
|
||
// Case 2: Reg uinstall file doesn't exist and IE4RegBackup doesn't exist
|
||
// - clean install, create a hive under HKEY_LOCAL_MACHINE
|
||
|
||
// Case 3: Reg uninstall file doesn't exist but IE4RegBackup exists
|
||
// - user is upgrading over an older IE4 build which saved
|
||
// the reg backup info into the registry itself, call RegSaveKey
|
||
// to export the backup key to a file, then delete the backup key
|
||
// and load the file as a hive
|
||
|
||
// Case 4: Reg uninstall file exists and IE4RegBackup exists
|
||
// - THIS CASE SHOULDN'T HAPPEN AT ALL! If somehow happens,
|
||
// we will default to Case 1.
|
||
|
||
// For case 1 & 4: we should get the hive key name out of the existing reg value data
|
||
// For case 2 & 3: we should generate the unique hive key name with "AINF%d" format
|
||
dwSize = sizeof( szBuf );
|
||
if ( RegQueryValueEx(hKey, c_szRegUninstPath, NULL, NULL, szBuf, &dwSize) == ERROR_SUCCESS )
|
||
{
|
||
LPSTR pszTmp;
|
||
|
||
pszTmp = ANSIStrRChr( szBuf, '\\' );
|
||
if ( pszTmp )
|
||
{
|
||
lstrcpy( pszRegHiveKey, CharNext(pszTmp) );
|
||
bFound = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( !bFound )
|
||
{
|
||
int i;
|
||
HKEY hKey;
|
||
char szRegFilePath[MAX_PATH];
|
||
|
||
for ( i = 0; i<9999; i++ )
|
||
{
|
||
wsprintf( szBuf, c_szHiveKey_FMT, i );
|
||
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, szBuf, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
RegCloseKey( hKey );
|
||
}
|
||
else
|
||
{
|
||
lstrcpy( szRegFilePath, pszBackupPath);
|
||
AddPath( szRegFilePath, szBuf );
|
||
if ( GetFileAttributes( szRegFilePath ) == (DWORD)-1 )
|
||
{
|
||
bFound = TRUE;
|
||
lstrcpy( pszRegHiveKey, szBuf );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return bFound;
|
||
}
|
||
|
||
|
||
void SetPathForRegHiveUse( LPSTR pszPath, DWORD * adwAttr, int iLevels, BOOL bSave )
|
||
{
|
||
int i;
|
||
char szBuf[MAX_PATH];
|
||
|
||
lstrcpy( szBuf, pszPath );
|
||
// create the folder if it does not exist without hiden
|
||
if ( bSave )
|
||
CreateFullPath( szBuf, FALSE );
|
||
for ( i =0; i<iLevels ; i++ )
|
||
{
|
||
if ( bSave )
|
||
{
|
||
adwAttr[i] = GetFileAttributes( szBuf );
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
}
|
||
else
|
||
{
|
||
SetFileAttributes( szBuf, adwAttr[i] );
|
||
}
|
||
if ( !GetParentDir( szBuf ) )
|
||
break;
|
||
}
|
||
}
|
||
|
||
BOOL NeedBackupData(LPCSTR pszInf, LPCSTR pszSec)
|
||
{
|
||
char szBuf[MAX_PATH];
|
||
BOOL bRet = TRUE;
|
||
|
||
if ( (ctx.wOSVer >= _OSVER_WINNT50) &&
|
||
GetEnvironmentVariable( "Upgrade", szBuf, sizeof(szBuf) ) )
|
||
{
|
||
if ( GetModuleFileName( NULL, szBuf, sizeof(szBuf) ) )
|
||
{
|
||
LPSTR pszFile;
|
||
|
||
// if setup.exe is last filenane
|
||
pszFile = ANSIStrRChr( szBuf,'\\' );
|
||
if ( pszFile++ && (lstrcmpi(pszFile,"setup.exe")==0) )
|
||
bRet = FALSE;
|
||
}
|
||
}
|
||
|
||
if (bRet)
|
||
{
|
||
// check if INF specify not backup on this platform
|
||
if (SUCCEEDED(GetTranslatedString(pszInf, pszSec, ADVINF_NOBACKPLATF, szBuf, sizeof(szBuf), NULL)) && szBuf[0])
|
||
{
|
||
char szInfPlatform[10];
|
||
int i = 0;
|
||
|
||
while (GetFieldString(szBuf, i++, szInfPlatform, sizeof(szInfPlatform)))
|
||
{
|
||
if (!lstrcmpi(c_pszPlatform[ctx.wOSVer], szInfPlatform))
|
||
{
|
||
bRet = FALSE;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return bRet;
|
||
}
|
||
|
||
void DeleteOldBackupData( HKEY hKey )
|
||
{
|
||
CHAR szBuf[MAX_PATH];
|
||
DWORD dwSize;
|
||
|
||
// delete the backup files
|
||
dwSize = sizeof(szBuf);
|
||
if ( RegQueryValueEx( hKey, REGVAL_BKFILE, NULL, NULL, szBuf, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
LPSTR pszExt;
|
||
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
|
||
pszExt = ANSIStrRChr( szBuf, '.' );
|
||
if ( pszExt )
|
||
{
|
||
lstrcpy( pszExt, ".INI" );
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
}
|
||
|
||
// delete the catalogs
|
||
dwSize = sizeof(szBuf);
|
||
if (RegQueryValueEx(hKey, REGVAL_BKDIR, NULL, NULL, szBuf, &dwSize) == ERROR_SUCCESS)
|
||
{
|
||
HKEY hkCatalogKey;
|
||
|
||
if (RegOpenKeyEx(hKey, REGSUBK_CATALOGS, 0, KEY_READ, &hkCatalogKey) == ERROR_SUCCESS)
|
||
{
|
||
CHAR szCatalogName[MAX_PATH];
|
||
DWORD dwIndex;
|
||
|
||
dwIndex = 0;
|
||
dwSize = sizeof(szCatalogName);
|
||
while (RegEnumValue(hkCatalogKey, dwIndex, szCatalogName, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||
{
|
||
CHAR szFullCatalogName[MAX_PATH];
|
||
|
||
lstrcpy(szFullCatalogName, szBuf);
|
||
AddPath(szFullCatalogName, szCatalogName);
|
||
|
||
SetFileAttributes(szFullCatalogName, FILE_ATTRIBUTE_NORMAL);
|
||
DeleteFile(szFullCatalogName);
|
||
|
||
dwIndex++;
|
||
dwSize = sizeof(szCatalogName);
|
||
}
|
||
|
||
RegCloseKey(hkCatalogKey);
|
||
}
|
||
}
|
||
}
|
||
|
||
// delete reg data backup file if there
|
||
dwSize = sizeof(szBuf);
|
||
if ( RegQueryValueEx( hKey, c_szRegUninstPath, NULL, NULL, szBuf, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
|
||
DeleteFile( szBuf );
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
BOOL RemoveBackupBaseOnVer( LPCSTR pszInf, LPCSTR pszSection )
|
||
{
|
||
BOOL fRet = TRUE;
|
||
char szBuf[MAX_PATH], szModule[MAX_PATH];
|
||
HKEY hKey, hRootKey;
|
||
DWORD dwSize;
|
||
WORD wInfVer, wRegVer;
|
||
|
||
if (FAILED(GetTranslatedString( pszInf, pszSection, ADVINF_MODNAME, szModule, sizeof(szModule), NULL)))
|
||
{
|
||
// no ops if there is no ComponentName
|
||
goto done;
|
||
}
|
||
|
||
// Check if the Component MajorVer matches up the backup data version stamp, if not, delete the old backup data.
|
||
//
|
||
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGKEY_SAVERESTORE, 0, KEY_WRITE|KEY_READ, &hRootKey) == ERROR_SUCCESS)
|
||
{
|
||
if ( RegOpenKeyEx( hRootKey, szModule, 0, KEY_WRITE|KEY_READ, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
dwSize = sizeof(szBuf);
|
||
if ( RegQueryValueEx( hKey, REGVAL_BKMODVER, NULL, NULL, szBuf, &dwSize ) == ERROR_SUCCESS )
|
||
{
|
||
WORD wVer[4];
|
||
|
||
ConvertVersionString( szBuf, wVer, '.' );
|
||
wRegVer = wVer[0]; // taking Major version only
|
||
}
|
||
else
|
||
wRegVer = 0; // indication no version stamp
|
||
|
||
if (SUCCEEDED(GetTranslatedString(pszInf, pszSection, ADVINF_MODVER, szBuf, sizeof(szBuf), NULL)))
|
||
{
|
||
WORD wVer[4];
|
||
|
||
ConvertVersionString( szBuf, wVer, '.' );
|
||
wInfVer = wVer[0]; // taking Major version only
|
||
}
|
||
else
|
||
wInfVer = 0; // indication no version stamp
|
||
|
||
if ( wInfVer > wRegVer )
|
||
{
|
||
// delete HKLM branch
|
||
DeleteOldBackupData( hKey );
|
||
RegCloseKey( hKey );
|
||
RegDeleteKeyRecursively( hRootKey, szModule );
|
||
|
||
// delete HKCU branch
|
||
if ( RegOpenKeyEx( HKEY_CURRENT_USER, REGKEY_SAVERESTORE, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
RegDeleteKeyRecursively( hKey, szModule );
|
||
RegCloseKey( hKey );
|
||
}
|
||
hKey = NULL;
|
||
}
|
||
if ( hKey )
|
||
{
|
||
RegCloseKey( hKey );
|
||
}
|
||
}
|
||
RegCloseKey( hRootKey );
|
||
}
|
||
|
||
done:
|
||
return fRet;
|
||
}
|
||
|
||
|
||
VOID AdvStartLogging()
|
||
{
|
||
CHAR szBuf[MAX_PATH], szLogFileName[MAX_PATH];
|
||
HKEY hKey;
|
||
|
||
// Need to 0 the buffer, becauce if the registry branch below does not exist
|
||
// Advpack would use what ever (garbage) was in the buffer to create a log file
|
||
*szLogFileName = '\0';
|
||
// check if logging is enabled
|
||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SAVERESTORE, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
DWORD dwDataLen = sizeof(szLogFileName);
|
||
|
||
if (RegQueryValueEx(hKey, "AdvpackLogFile", NULL, NULL, szLogFileName, &dwDataLen) != ERROR_SUCCESS)
|
||
*szLogFileName = '\0';
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
if (*szLogFileName)
|
||
{
|
||
if (szLogFileName[1] != ':') // crude way of determining if fully qualified path is specified or not
|
||
{
|
||
GetWindowsDirectory(szBuf, sizeof(szBuf)); // default to windows dir
|
||
AddPath(szBuf, szLogFileName);
|
||
}
|
||
else
|
||
lstrcpy(szBuf, szLogFileName);
|
||
|
||
if ((g_hAdvLogFile == INVALID_HANDLE_VALUE) &&
|
||
(g_hAdvLogFile = CreateFile(szBuf, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
|
||
SetFilePointer(g_hAdvLogFile, 0, NULL, FILE_END); // append logging info to the file
|
||
}
|
||
}
|
||
|
||
|
||
VOID AdvWriteToLog(PCSTR pcszFormatString, ...)
|
||
{
|
||
va_list vaArgs;
|
||
LPSTR pszFullErrMsg = NULL;
|
||
DWORD dwBytesWritten;
|
||
|
||
if (g_hAdvLogFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
va_start(vaArgs, pcszFormatString);
|
||
|
||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING,
|
||
(LPCVOID) pcszFormatString, 0, 0, (LPSTR) &pszFullErrMsg, 0, &vaArgs);
|
||
|
||
if (pszFullErrMsg != NULL)
|
||
{
|
||
WriteFile(g_hAdvLogFile, pszFullErrMsg, lstrlen(pszFullErrMsg), &dwBytesWritten, NULL);
|
||
LocalFree(pszFullErrMsg);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
VOID AdvStopLogging()
|
||
{
|
||
if (g_hAdvLogFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
CloseHandle(g_hAdvLogFile);
|
||
g_hAdvLogFile = INVALID_HANDLE_VALUE;
|
||
}
|
||
}
|
||
|
||
VOID AdvLogDateAndTime()
|
||
{
|
||
if (g_hAdvLogFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
SYSTEMTIME SystemTime;
|
||
|
||
GetLocalTime(&SystemTime);
|
||
|
||
AdvWriteToLog("Date: %1!02d!/%2!02d!/%3!04d! (mm/dd/yyyy)\tTime: %4!02d!:%5!02d!:%6!02d! (hh:mm:ss)\r\n",
|
||
SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear,
|
||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
|
||
}
|
||
}
|