//*************************************************************************** //* Copyright (c) Microsoft Corporation 1995-1996. All rights reserved. * //*************************************************************************** //* * //* ADVPACK.C - Advanced INF Installer. * //* * //*************************************************************************** //*************************************************************************** //* INCLUDE FILES * //*************************************************************************** #include #include #include #include #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, 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; iSource ) + 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 .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’s Version, GUID’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= _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); } }