windows-nt/Source/XPSP1/NT/windows/appcompat/windowsupdate/installer/wuinst.cpp
2020-09-26 16:20:57 +08:00

1415 lines
40 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
Duinst.cpp
Abstract:
Contains the main installation code
used by the app.
Notes:
Unicode only.
History:
03/02/2001 rparsons Created
--*/
#include "precomp.h"
extern SETUP_INFO g_si;
/*++
Routine Description:
Determines if a newer version of our package
exists on the target
Arguments:
None
Return Value:
TRUE if the installation should take place
FALSE if the installation should not take place
-1 on failure
--*/
int
InstallCheckVersion()
{
BOOL fReturn = FALSE;
CRegistry creg;
DWORDLONG dwlPackageVersion = 0;
DWORDLONG dwlInstalledVersion = 0;
char szActiveSetupKey[MAX_PATH] = "";
char szBuffer[MAX_PATH*3] = "";
WCHAR wszActiveSetupKey[MAX_PATH] = L"";
WCHAR wszPackageVersion[MAX_PATH] = L"";
LPWSTR lpwInstalledVersion = NULL;
//
// Get the registry key path from the INF
//
fReturn = SetupGetLineTextA(NULL,
g_si.hInf,
"Strings",
"ActiveSetupKey",
szActiveSetupKey,
sizeof(szActiveSetupKey),
NULL);
if (!fReturn) {
return -1;
}
pAnsiToUnicode(szActiveSetupKey, wszActiveSetupKey, MAX_PATH);
//
// Determine if a package is already installed
//
fReturn = creg.IsRegistryKeyPresent(HKEY_LOCAL_MACHINE,
wszActiveSetupKey);
if (!fReturn) {
return TRUE;
}
//
// A package is installed - determine the version
//
lpwInstalledVersion = creg.GetString(HKEY_LOCAL_MACHINE,
wszActiveSetupKey,
L"Version",
TRUE);
if (NULL == lpwInstalledVersion) {
return -1;
}
//
// Convert the installed version string to a number
//
VersionStringToNumber(lpwInstalledVersion, &dwlInstalledVersion);
creg.Free(lpwInstalledVersion);
//
// Now scan the INF AddReg data to determine if a newer version
// is present with our package
//
if (0 != dwlInstalledVersion) {
INFCONTEXT InfContext;
BOOL fRetVal = FALSE;
fRetVal = SetupFindFirstLineA(g_si.hInf,
INF_VERSION_INFO,
NULL,
&InfContext);
while (fRetVal) {
if ((SetupGetStringFieldA(&InfContext,
1,
szBuffer, sizeof(szBuffer),
NULL) == FALSE) ||
(_stricmp(szBuffer, "HKLM") != 0 )) {
goto NextLine;
}
if ((SetupGetStringFieldA(&InfContext,
2,
szBuffer,
sizeof(szBuffer),
NULL) == FALSE) ||
(_stricmp(szBuffer, szActiveSetupKey) != 0 )) {
goto NextLine;
}
if ((SetupGetStringFieldA(&InfContext,
3,
szBuffer,
sizeof(szBuffer),
NULL) == TRUE) &&
(_stricmp(szBuffer, "Version") == 0 )) {
break;
}
NextLine:
fRetVal = SetupFindNextLine(&InfContext, &InfContext);
}
if (fRetVal) {
if (SetupGetStringFieldA(&InfContext,
5,
szBuffer,
sizeof(szBuffer),
NULL) == TRUE) {
pAnsiToUnicode(szBuffer, wszPackageVersion, MAX_PATH);
VersionStringToNumber(wszPackageVersion, &dwlPackageVersion);
g_si.dwlUpdateVersion = dwlPackageVersion;
}
}
//
// Compare the versions
//
if (dwlPackageVersion >= dwlInstalledVersion) {
return TRUE; // Package has newer than what's installed
}
}
return FALSE;
}
/*++
Routine Description:
Installs catalog files, if there are any to install
Arguments:
hInf - Handle to the INF containing catalog names
lpwSourcePath - The path where the file is currently located
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallCatalogFiles(
IN HINF hInf,
IN LPCWSTR lpwSourcePath
)
{
DWORD dwTargetCatVersion = 0;
DWORD dwSourceCatVersion = 0;
DWORD dwError = 0;
BOOL fReturn = FALSE;
char szCatFileName[MAX_PATH] = "";
WCHAR wszCatFileName[MAX_PATH] = L"";
WCHAR wszTargetCat[MAX_PATH] = L"";
char szSourceCat[MAX_PATH] = "";
WCHAR wszSourceCat[MAX_PATH] = L"";
char szTempCat[MAX_PATH] = "";
WCHAR wszTempCat[MAX_PATH] = L"";
INFCONTEXT InfContext;
WCHAR wszCatRoot[] = L"CatRoot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}";
//
// Loop through all the lines in the CatalogsToInstall section,
// verifying and installing each one
//
fReturn = SetupFindFirstLineA(hInf, INF_CAT_SECTION_NAME, NULL, &InfContext) &&
SetupGetLineTextA(&InfContext, NULL, NULL, NULL,
szCatFileName, MAX_PATH, NULL);
while (fReturn) {
pAnsiToUnicode(szCatFileName, wszCatFileName, MAX_PATH);
//
// Get paths to src and dest, compare versions,
// and do the copy if necessary
//
wsprintf(wszSourceCat, L"%s\\%s", g_si.lpwExtractPath, wszCatFileName);
wsprintf(wszTargetCat, L"%s\\%s\\%s", g_si.lpwSystem32Directory,
wszCatRoot, wszCatFileName);
wsprintf(wszTempCat, L"%s\\%s", g_si.lpwWindowsDirectory,
wszCatFileName);
dwTargetCatVersion = GetCatVersion(wszTargetCat);
dwSourceCatVersion = GetCatVersion(wszSourceCat);
if (dwTargetCatVersion > dwSourceCatVersion) {
// If the SP?.CAT on the target is greater than ours
// don't install ours
Print(TRACE, L"[InstallCatalogFiles] Not installing older catalog\n");
return TRUE;
}
pUnicodeToAnsi(wszSourceCat, szSourceCat, MAX_PATH);
pUnicodeToAnsi(wszTempCat, szTempCat, MAX_PATH);
//
// Put the CAT file in the Windows directory
//
dwError = SetupDecompressOrCopyFileA(szSourceCat,
szTempCat,
NULL);
if (NO_ERROR == dwError) {
//
// Perform the installation using the approriate function
//
dwError = pInstallCatalogFile(wszTempCat, wszCatFileName);
if (NO_ERROR != dwError) {
Print(ERROR,
L"[InstallCatalogFiles] Failed to install catalog %s\n",
wszTempCat);
return FALSE;
}
}
DeleteFile(wszTempCat); // clean up copied-over file
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext, NULL, NULL, NULL,
szCatFileName, MAX_PATH, NULL);
}
return TRUE;
}
/*++
Routine Description:
Creates the uninstall key in the registry
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallWriteUninstallKey()
{
BOOL fReturn = FALSE;
CRegistry creg;
char szUninstallKey[MAX_PATH] = "";
WCHAR wszUninstallKey[MAX_PATH] = L"";
WCHAR wszUninstallCommand[MAX_PATH] = L"";
HKEY hKey = NULL;
//
// Get the path for the uninstall key from the INF
//
fReturn = SetupGetLineTextA(NULL,
g_si.hInf,
"Strings",
"UninstallKey",
szUninstallKey,
sizeof(szUninstallKey),
NULL);
if (!fReturn) {
return FALSE;
}
pAnsiToUnicode(szUninstallKey, wszUninstallKey, MAX_PATH);
//
// Attempt to create the key or open if it already exists
//
hKey = creg.CreateKey(HKEY_LOCAL_MACHINE,
wszUninstallKey,
KEY_SET_VALUE);
if (NULL == hKey) {
Print(ERROR, L"[InstallWriteUninstallKey] Failed to create key\n");
return FALSE;
}
//
// Set the DisplayName
//
fReturn = creg.SetString(hKey,
NULL,
REG_DISPLAY_NAME,
g_si.lpwPrettyAppName,
FALSE);
if (!fReturn) {
Print(ERROR, L"[InstallWriteUninstallKey] Failed to set DisplayName\n");
return FALSE;
}
//
// Build the uninstall string
//
wsprintf(wszUninstallCommand, L"%s\\%s.exe %s", g_si.lpwInstallDirectory,
g_si.lpwEventLogSourceName, UNINSTALL_SWITCH);
//
// Set the Uninstall string
//
fReturn = creg.SetString(HKEY_LOCAL_MACHINE,
wszUninstallKey,
REG_UNINSTALL_STRING,
wszUninstallCommand,
TRUE);
if (!fReturn) {
Print(ERROR, L"[InstallWriteUninstallKey] Failed to set UninstallString\n");
return FALSE;
}
return TRUE;
}
/*++
Routine Description:
Run any EXEs specified in the INF file
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallRunINFProcesses()
{
char szFileName[MAX_PATH] = "";
WCHAR wszExpFileName[MAX_PATH] = L"";
WCHAR wszFileName[MAX_PATH] = L"";
BOOL fReturn = FALSE;
INFCONTEXT InfContext;
//
// Loop through all the lines in the ProcessesToRun section,
// spawning off each one
//
fReturn = SetupFindFirstLineA(g_si.hInf, INF_PROCESSES_TO_RUN, NULL,
&InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
while (fReturn) {
pAnsiToUnicode(szFileName, wszFileName, MAX_PATH);
//
// Spawn the EXE and ignore any errors returned
//
ExpandEnvironmentStrings(wszFileName,
wszExpFileName,
MAX_PATH);
LaunchProcessAndWait(wszExpFileName, NULL);
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
}
return TRUE;
}
/*++
Routine Description:
Sets up the specified directory for use
Arguments:
lpwDirectoryPath - Full path to the directory
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallPrepareDirectory(
IN LPWSTR lpwDirectoryPath,
IN DWORD dwAttributes
)
{
BOOL fReturn = FALSE;
LPWSTR lpwParentPath = NULL, lpwEnd = NULL;
//
// See if the directory exists
//
if (GetFileAttributes(lpwDirectoryPath) == -1) {
//
// Didn't exist - attempt to create the directory
//
if (!CreateDirectory(lpwDirectoryPath, NULL)) {
Print(ERROR, L"[InstallPrepareDirectory] Failed to create directory %s\n",
lpwDirectoryPath);
return FALSE;
}
}
//
// Build a path to the parent based on it's child
//
lpwParentPath = (LPWSTR) MALLOC((wcslen(lpwDirectoryPath)+1)*sizeof(WCHAR));
if (NULL == lpwParentPath) {
return FALSE;
}
wcscpy(lpwParentPath, lpwDirectoryPath);
lpwEnd = wcsrchr(lpwParentPath, '\\');
if (lpwEnd) {
*lpwEnd = 0;
}
//
// Adjust the permissions on the new directory
// to match the parent
//
fReturn = MirrorDirectoryPerms(lpwParentPath,
lpwDirectoryPath);
if (!fReturn) {
Print(ERROR,
L"[InstallPrepareDirectory] Failed to mirror permissions from %s to %s\n",
lpwParentPath, lpwDirectoryPath);
return FALSE;
}
SetFileAttributes(lpwDirectoryPath, dwAttributes);
return TRUE;
}
/*++
Routine Description:
Performs the backup of files that get
replaced during install
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallBackupFiles()
{
WCHAR wszBackupDir[MAX_PATH] = L"";
WCHAR wszSourceFileName[MAX_PATH] = L"";
WCHAR wszBackupFileName[MAX_PATH] = L"";
char szEntry[MAX_PATH] = "";
WCHAR wszEntry[MAX_PATH] = L"";
char szFileName[MAX_PATH] = "";
WCHAR wszFileName[MAX_PATH] = L"";
WCHAR wszRestoreSection[MAX_PATH] = L"";
WCHAR wszKey[10] = L"";
BOOL fReturn = FALSE, fResult = FALSE;
LPWSTR lpwDestDir = NULL;
UINT uCount = 0;
INFCONTEXT InfContext;
//
// Remove any previous backup directories
// Don't check the return as it's not critical
// that this happen successfully
//
wsprintf(wszBackupDir, L"%s\\Backup", g_si.lpwInstallDirectory);
CommonRemoveDirectoryAndFiles(wszBackupDir, (PVOID) FALSE, FALSE, FALSE);
wszBackupDir[0] = 0;
wsprintf(wszBackupDir,
L"%s\\%s",
g_si.lpwInstallDirectory,
g_si.lpwUninstallDirectory);
CommonRemoveDirectoryAndFiles(wszBackupDir, (PVOID) FALSE, FALSE, FALSE);
//
// Prepare the new backup directory
//
fReturn = InstallPrepareDirectory(wszBackupDir,
FILE_ATTRIBUTE_HIDDEN);
if (!fReturn) {
return FALSE;
}
//
// Step through each entry in the queue
//
while (g_si.BackupFileQueue.GetSize()) {
g_si.BackupFileQueue.Dequeue(wszEntry, MAX_PATH - 1, FALSE);
pUnicodeToAnsi(wszEntry, szEntry, MAX_PATH);
//
// Get the destination directory
//
GetNextToken(wszEntry, L".");
GetNextToken(NULL, L".");
lpwDestDir = GetNextToken(NULL, L".");
if (NULL == lpwDestDir) {
return FALSE;
}
//
// Loop through all the lines in the backup files section(s),
// and perform the backup
//
fReturn = SetupFindFirstLineA(g_si.hInf, szEntry, NULL,
&InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
while (fReturn) {
pAnsiToUnicode(szFileName, wszFileName, MAX_PATH);
//
// Build the path to the source file
//
wsprintf(wszSourceFileName,
L"%s\\%s\\%s",
g_si.lpwWindowsDirectory,
lpwDestDir,
wszFileName);
//
// Ensure that the source file exists
//
fResult = PathFileExists(wszSourceFileName);
if (fResult) {
//
// Ensure that this file is not under WFP
//
fResult = IsFileProtected(wszSourceFileName);
//
// Build a path to the backup file
//
wsprintf(wszBackupFileName,
L"%s\\%s",
wszBackupDir,
wszFileName);
//
// Backup the file - be sensitive to WFP
//
if (fResult) {
fResult = ForceCopy(wszSourceFileName, wszBackupFileName);
if (!fResult) {
Print(ERROR, L"[InstallBackupFiles] Failed to copy %s to %s\n",
wszSourceFileName, wszBackupFileName);
return FALSE;
}
} else {
fResult = ForceMove(wszSourceFileName, wszBackupFileName);
if (!fResult) {
Print(ERROR, L"[InstallBackupFiles] Failed to move %s to %s\n",
wszSourceFileName, wszBackupFileName);
return FALSE;
}
}
//
// Now save an entry to the INF
//
wsprintf(wszRestoreSection, L"Restore.Files.%s", lpwDestDir);
wsprintf(wszKey, L"%u", ++uCount);
SaveEntryToINF(wszRestoreSection,
wszKey,
wszFileName,
g_si.lpwUninstallINFPath);
}
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
}
}
return TRUE;
}
/*++
Routine Description:
Performs a backup of the specified registry
keys during install
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallBackupRegistryKeys()
{
BOOL fReturn = FALSE, fResult = FALSE;
HKEY hKeyRoot = NULL;
char szEntry[MAX_PATH] = "";
WCHAR wszEntry[MAX_PATH] = L"";
char szKeyPath[MAX_PATH*3] = "";
WCHAR wszKeyPath[MAX_PATH*3] = L"";
WCHAR wszBackupFile[MAX_PATH] = L"";
WCHAR wszKey[10] = L"";
WCHAR wszEntryToSave[MAX_PATH*2] = L"";
LPWSTR lpwKeyPart = NULL, lpwKeyRoot = NULL;
UINT uCount = 0;
CRegistry creg;
INFCONTEXT InfContext;
//
// Step through each entry in the queue
//
while (g_si.BackupRegistryQueue.GetSize()) {
g_si.BackupRegistryQueue.Dequeue(wszEntry, MAX_PATH - 1, FALSE);
pUnicodeToAnsi(wszEntry, szEntry, MAX_PATH);
//
// Loop through all the lines in the backup registry section(s),
// and perform the backup
//
fReturn = SetupFindFirstLineA(g_si.hInf, szEntry, NULL,
&InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szKeyPath, MAX_PATH, NULL);
while (fReturn) {
pAnsiToUnicode(szKeyPath, wszKeyPath, MAX_PATH*3);
//
// Split the key path into two separate parts
//
lpwKeyRoot = GetNextToken(wszKeyPath, L",");
if (NULL == lpwKeyRoot) {
break;
}
if (!_wcsicmp(lpwKeyRoot, L"HKLM")) {
hKeyRoot = HKEY_LOCAL_MACHINE;
} else if (!_wcsicmp(lpwKeyRoot, L"HKCR")) {
hKeyRoot = HKEY_CLASSES_ROOT;
} else if (!_wcsicmp(lpwKeyRoot, L"HKCU")) {
hKeyRoot = HKEY_CURRENT_USER;
} else if (!_wcsicmp(lpwKeyRoot, L"HKU")) {
hKeyRoot = HKEY_USERS;
} else {
break;
}
lpwKeyPart = GetNextToken(NULL, L",");
if (NULL == lpwKeyPart) {
break;
}
//
// Verify that the specified key exists
//
fResult = creg.IsRegistryKeyPresent(hKeyRoot, lpwKeyPart);
if (fResult) {
//
// Build a path to the file for the backup
// and backup the key
//
wsprintf(wszBackupFile,
L"%s\\%s\\Regbkp%u",
g_si.lpwInstallDirectory,
g_si.lpwUninstallDirectory,
++uCount);
fResult = creg.BackupRegistryKey(hKeyRoot, lpwKeyPart, wszBackupFile, TRUE);
if (!fResult) {
Print(ERROR,
L"[InstallBackupRegistryKeys] Failed to backup key %s to %s\n",
lpwKeyPart, wszBackupFile);
return FALSE;
}
//
// Now save an entry to the queue for the uninstall INF
// We need one for deletion and restoration
//
wsprintf(wszEntryToSave, L"%s,%s", lpwKeyRoot, lpwKeyPart);
wsprintf(wszKey, L"%u", ++uCount);
SaveEntryToINF(INF_DELETE_REGISTRYW,
wszKey,
wszEntryToSave,
g_si.lpwUninstallINFPath);
wsprintf(wszEntryToSave, L"%s,%s,%s", lpwKeyRoot, lpwKeyPart, wszBackupFile);
SaveEntryToINF(INF_RESTORE_REGISTRYW,
wszKey,
wszEntryToSave,
g_si.lpwUninstallINFPath);
}
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szKeyPath, MAX_PATH, NULL);
}
}
return TRUE;
}
/*++
Routine Description:
Performs the file copy operations
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallCopyFiles()
{
WCHAR wszBackupDir[MAX_PATH] = L"";
WCHAR wszDestFileName[MAX_PATH] = L"";
WCHAR wszSourceFileName[MAX_PATH] = L"";
char szEntry[MAX_PATH] = "";
WCHAR wszEntry[MAX_PATH] = L"";
char szFileName[MAX_PATH] = "";
WCHAR wszFileName[MAX_PATH] = L"";
BOOL fReturn = FALSE, fResult = FALSE;
LPWSTR lpwDestDir = NULL;
DWORDLONG dwlSourceVersion = 0, dwlDestVersion = 0;
INFCONTEXT InfContext;
//
// Step through each entry in the queue
//
while (g_si.CopyFileQueue.GetSize()) {
g_si.CopyFileQueue.Dequeue(wszEntry, MAX_PATH - 1, FALSE);
pUnicodeToAnsi(wszEntry, szEntry, MAX_PATH);
//
// Get the destination directory
//
GetNextToken(wszEntry, L".");
GetNextToken(NULL, L".");
lpwDestDir = GetNextToken(NULL, L".");
if (NULL == lpwDestDir) {
break;
}
//
// Loop through all the lines in the copy files section(s),
// and perform the copy
//
fReturn = SetupFindFirstLineA(g_si.hInf, szEntry, NULL,
&InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
while (fReturn) {
pAnsiToUnicode(szFileName, wszFileName, MAX_PATH);
//
// Build the path to the destination file
//
wsprintf(wszDestFileName,
L"%s\\%s\\%s",
g_si.lpwWindowsDirectory,
lpwDestDir,
wszFileName);
//
// Build the path to the source file
//
wsprintf(wszSourceFileName,
L"%s\\%s",
g_si.lpwExtractPath,
wszFileName);
//
// Get version information from the source and destination
//
if (!GetVersionInfoFromImage(wszSourceFileName, &dwlSourceVersion)) {
Print(TRACE, L"[InstallCopyFiles] Failed to get version info from %s\n",
wszSourceFileName);
dwlSourceVersion = 0;
}
if (!GetVersionInfoFromImage(wszDestFileName, &dwlDestVersion)) {
Print(TRACE, L"[InstallCopyFiles] Failed to get version info from %s\n",
wszDestFileName);
dwlDestVersion = 0;
}
//
// If neither file had version information, perform the copy.
// If the target version is less than the source version,
// perform the copy.
// Otherwise, move to the next file
//
if ((dwlSourceVersion == 0 && dwlDestVersion == 0) ||
(dwlDestVersion <= dwlSourceVersion)) {
//
// Ensure that this file is not under WFP
//
fResult = IsFileProtected(wszDestFileName);
//
// Copy the file - be sensitive to WFP
//
if (fResult) {
Print(TRACE,
L"[InstallCopyFiles] Preparing to install WFP file from %s to %s\n",
wszSourceFileName, wszDestFileName);
fResult = CommonEnableProtectedRenames();
if (!fResult) {
return FALSE;
}
fResult = InstallWFPFile(wszSourceFileName,
wszFileName,
wszDestFileName,
g_si.fUpdateDllCache);
if (!fResult) {
return FALSE;
}
} else {
Print(TRACE,
L"[InstallCopyFiles] Preparing to install file from %s to %s\n",
wszSourceFileName, wszDestFileName);
fResult = ForceCopy(wszSourceFileName, wszDestFileName);
if (!fResult) {
Print(ERROR,
L"[InstallCopyFiles] Failed to install file from %s to %s\n",
wszSourceFileName, wszDestFileName);
return FALSE;
}
}
} else {
break;
}
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szFileName, MAX_PATH, NULL);
}
}
return TRUE;
}
/*++
Routine Description:
Installs a file that is protected
by WFP
Arguments:
lpwSourceFileName - Path to the source file
lpwDestFileName - Name of the destination file
lpwDestFileNamePath - Name & path to the destination file
fUpdateDllCache - A flag to indicate if the file
should be placed in the DllCache directory
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallWFPFile(
IN LPCWSTR lpwSourceFileName,
IN LPCWSTR lpwDestFileName,
IN LPCWSTR lpwDestFileNamePath,
IN BOOL fUpdateDllCache
)
{
LPWSTR lpwCachePath = NULL;
LPWSTR lpwExpandedCachePath = NULL;
LPWSTR lpwTempFileName = NULL;
DWORD cbSize = 0;
WCHAR wszDllCachePath[MAX_PATH] = L"";
WCHAR wszExtraFilePath[MAX_PATH] = L"";
WCHAR wszExtraFileName[MAX_PATH] = L"";
WCHAR wszOldSourcesPath[MAX_PATH] = L"";
CRegistry creg;
BOOL fAddedToReg = FALSE, fReturn = FALSE;
if (fUpdateDllCache) {
//
// Try to get the dllcache directory path from
// the registry
//
lpwCachePath = creg.GetString(HKEY_LOCAL_MACHINE,
REG_WINFP_PATH,
L"SfcDllCacheDir",
TRUE);
if (lpwCachePath) {
if (cbSize = ExpandEnvironmentStrings(lpwCachePath,
lpwExpandedCachePath,
0)) {
lpwExpandedCachePath = (LPWSTR) MALLOC(cbSize*sizeof(WCHAR));
if (lpwExpandedCachePath) {
if (ExpandEnvironmentStrings(lpwCachePath,
lpwExpandedCachePath,
cbSize)) {
//
// Build a full path to \%windir%\system32\dllcache\filename.xxx
//
wsprintf(wszDllCachePath,
L"%s\\%s",
lpwExpandedCachePath,
lpwDestFileName);
}
}
}
}
//
// If we couldn't get it from that key, try another
//
if (NULL == lpwExpandedCachePath) {
lpwCachePath = creg.GetString(HKEY_LOCAL_MACHINE,
REG_WINLOGON_PATH,
L"SfcDllCacheDir",
TRUE);
if (lpwCachePath) {
if (cbSize = ExpandEnvironmentStrings(lpwCachePath,
lpwExpandedCachePath,
0)) {
lpwExpandedCachePath = (LPWSTR) MALLOC(cbSize*sizeof(WCHAR));
if (lpwExpandedCachePath) {
if (ExpandEnvironmentStrings(lpwCachePath,
lpwExpandedCachePath,
cbSize)) {
//
// Build a full path to \%windir%\system32\dllcache\filename.xxx
//
wsprintf(wszDllCachePath,
L"%s\\%s",
lpwExpandedCachePath,
lpwDestFileName);
}
}
}
}
}
//
// If neither key worked, build the path manually
//
if (NULL == lpwExpandedCachePath) {
wsprintf(wszDllCachePath,
L"%s\\DllCache\\%s",
g_si.lpwSystem32Directory,
lpwDestFileName);
}
//
// Replace the file in the DllCache directory
//
if (!CopyFile(lpwSourceFileName, wszDllCachePath, FALSE)) {
Print(ERROR,
L"[InstallWFPFile] Failed to copy %s to %s\n",
lpwSourceFileName, wszDllCachePath);
goto cleanup;
return FALSE;
}
}
//
// Put an additional copy in 'Sources' under the install dir
// The return is not critical for this operation
//
wsprintf(wszExtraFilePath, L"%s\\$Sources$", g_si.lpwInstallDirectory);
wsprintf(wszOldSourcesPath, L"%s\\Sources", g_si.lpwInstallDirectory);
CommonRemoveDirectoryAndFiles(wszExtraFilePath, (PVOID) FALSE, FALSE, FALSE);
InstallPrepareDirectory(wszExtraFilePath,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
wcscpy(wszExtraFileName, wszExtraFilePath);
wcscat(wszExtraFileName, L"\\");
wcscat(wszExtraFileName, lpwDestFileName);
if (!CopyFile(lpwSourceFileName, wszExtraFileName, FALSE)) {
Print(ERROR,
L"[InstallWFPFile] Failed to copy %s to %s\n",
lpwSourceFileName, wszExtraFileName);
}
if (!g_si.fSourceDirAdded) {
//
// Remove any old source path that may exist
//
creg.RemoveStringFromMultiSz(HKEY_LOCAL_MACHINE,
REG_INSTALL_SOURCES,
L"Installation Sources",
wszOldSourcesPath,
TRUE);
creg.RemoveStringFromMultiSz(HKEY_LOCAL_MACHINE,
REG_INSTALL_SOURCES,
L"Installation Sources",
wszExtraFilePath,
TRUE);
fReturn = creg.AddStringToMultiSz(HKEY_LOCAL_MACHINE,
REG_INSTALL_SOURCES,
L"Installation Sources",
wszExtraFilePath,
TRUE);
if (!fReturn) {
Print(ERROR,
L"[InstallWFPFile] Failed to add %s to registry\n",
wszExtraFilePath);
}
g_si.fSourceDirAdded = TRUE;
}
//
// The catalog file won't vouch for WFP files until
// the next reboot. Put the file down and let the
// Session Manager rename them
//
lpwTempFileName = CopyTempFile(lpwSourceFileName,
g_si.lpwSystem32Directory);
if (NULL == lpwTempFileName) {
Print(ERROR, L"[InstallWFPFile] Failed to get temp file\n");
goto cleanup;
return FALSE;
}
if (!MoveFileEx(lpwTempFileName,
lpwDestFileNamePath,
MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT)) {
Print(ERROR, L"[InstallWFPFile] Failed to delay replace from %s to %s\n",
lpwTempFileName, lpwDestFileNamePath);
goto cleanup;
return FALSE;
}
cleanup:
if (lpwTempFileName) {
FREE(lpwTempFileName);
}
if (lpwExpandedCachePath) {
FREE(lpwExpandedCachePath);
}
return TRUE;
}
/*++
Routine Description:
Retrieves the section names from the installation
INF file. This dictates what operations will be
performed during install
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallGetSectionsFromINF()
{
BOOL fReturn = FALSE;
DWORD dwType = 0;
char szSectionName[MAX_QUEUE_SIZE] = "";
char *pSectionName;
WCHAR wszDirective[MAX_PATH] = L"";
INFCONTEXT InfContext;
//
// Loop through all the lines in the Sections section(s),
//
fReturn = SetupFindFirstLineA(g_si.hInf, INF_MASTER_SECTIONS, NULL,
&InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szSectionName, MAX_QUEUE_SIZE, NULL);
while (fReturn) {
//
// Determine which section we're working with
//
if (strstr(szSectionName, INF_BACKUP_FILES)) {
dwType = dwBackupFiles;
} else if (strstr(szSectionName, INF_BACKUP_REGISTRY)) {
dwType = dwBackupRegistry;
} else if (strstr(szSectionName, INF_DELETE_REGISTRY)) {
dwType = dwDeleteRegistry;
} else if (strstr(szSectionName, INF_COPY_FILES)) {
dwType = dwCopyFiles;
} else if (strstr(szSectionName, INF_REGISTRATIONS)) {
dwType = dwRegistrations;
} else if (strstr(szSectionName, INF_EXCLUDE)) {
dwType = dwExclusionsInstall;
} else if (strstr(szSectionName, INF_ADD_REGISTRY)) {
dwType = dwAddRegistry;
} else {
Print(ERROR,
L"[InstallGetSectionsFromINF] Illegal section name passed %s\n",
szSectionName);
return FALSE; // illegal section name
}
pSectionName = strtok(szSectionName, ",");
do {
pAnsiToUnicode(pSectionName, wszDirective, MAX_PATH);
//
// Loop through each section name and add it to the
// appropriate queue
//
switch (dwType) {
case dwBackupFiles:
g_si.BackupFileQueue.Enqueue(wszDirective);
break;
case dwBackupRegistry:
g_si.BackupRegistryQueue.Enqueue(wszDirective);
break;
case dwDeleteRegistry:
g_si.DeleteRegistryQueue.Enqueue(wszDirective);
break;
case dwCopyFiles:
g_si.CopyFileQueue.Enqueue(wszDirective);
break;
case dwRegistrations:
g_si.RegistrationQueue.Enqueue(wszDirective);
break;
case dwExclusionsInstall:
g_si.ExclusionQueue.Enqueue(wszDirective);
break;
case dwAddRegistry:
g_si.AddRegistryQueue.Enqueue(wszDirective);
break;
default:
return FALSE; // illegal section name
}
pSectionName = strtok(NULL, ",");
} while (NULL != pSectionName);
fReturn = SetupFindNextLine(&InfContext, &InfContext) &&
SetupGetLineTextA(&InfContext,
NULL, NULL, NULL,
szSectionName, MAX_QUEUE_SIZE, NULL);
}
return TRUE;
}
/*++
Routine Description:
Merges the registry data from the INF
into the registry
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/
BOOL
InstallRegistryData()
{
BOOL fReturn = FALSE;
char szEntry[MAX_PATH] = "";
WCHAR wszEntry[MAX_PATH] = L"";
//
// Step through each entry in the queue
//
while (g_si.AddRegistryQueue.GetSize()) {
g_si.AddRegistryQueue.Dequeue(wszEntry, MAX_PATH - 1, FALSE);
pUnicodeToAnsi(wszEntry, szEntry, MAX_PATH);
//
// Merge all the registry data from the INF
//
fReturn = SetupInstallFromInfSectionA(NULL,
g_si.hInf,
szEntry,
SPINST_REGISTRY,
NULL,
NULL,
0,
NULL,
NULL,
NULL,
NULL);
if (!fReturn) {
Print(ERROR, L"[InstallRegistryData] Failed to merge registry data\n");
return FALSE;
}
}
return TRUE;
}