|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
Duuninst.cpp
Abstract:
Contains the main uninstallation code used by the app.
Notes:
Unicode only.
History:
03/02/2001 rparsons Created --*/
#include "precomp.h"
extern SETUP_INFO g_si;
/*++
Routine Description:
Removes the specified registry key Assumes HKEY_LOCAL_MACHINE
Arguments: lpwKey - Path of the key to open lpwSubKey - Path of the subkey to delete Return Value:
None
--*/ void UninstallDeleteSubKey( IN LPCWSTR lpwKey, IN LPCWSTR lpwSubKey ) { CRegistry creg;
//
// Remove the key from the registry
//
creg.DeleteRegistryKey(HKEY_LOCAL_MACHINE, lpwKey, lpwSubKey, TRUE, TRUE); return; }
/*++
Routine Description:
Retrieves the section names from the uninstall INF file. This dictates what operations will be performed during uninstall
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/ BOOL UninstallGetSectionsFromINF() { 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_RESTORE_FILES)) { dwType = dwRestoreFiles; } else if (strstr(szSectionName, INF_DELETE_REGISTRY)) { dwType = dwDeleteRegistry; } else if (strstr(szSectionName, INF_RESTORE_REGISTRY)) { dwType = dwRestoreRegistry; } else if (strstr(szSectionName, INF_UNREGISTRATIONS)) { dwType = dwUnRegistrations; } else if (strstr(szSectionName, INF_EXCLUDE)) { dwType = dwExclusionsUninstall; } else { Print(ERROR, L"[UninstallGetSectionsFromINF] 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 dwRestoreFiles: g_si.RestoreFileQueue.Enqueue(wszDirective); break;
case dwDeleteRegistry: g_si.DeleteRegistryQueue.Enqueue(wszDirective); break;
case dwRestoreRegistry: g_si.RestoreRegistryQueue.Enqueue(wszDirective); break;
case dwUnRegistrations: g_si.RegistrationQueue.Enqueue(wszDirective); break;
case dwExclusionsUninstall: g_si.ExclusionQueue.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:
Restores registry keys that were saved during the install
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/ BOOL UninstallRestoreRegistryKeys() { BOOL fReturn = FALSE, fResult = FALSE; HKEY hKeyRoot = NULL; char szEntry[MAX_QUEUE_SIZE] = ""; WCHAR wszEntry[MAX_QUEUE_SIZE] = L""; char szKeyPath[MAX_PATH*3] = ""; WCHAR wszKeyPath[MAX_PATH*3] = L""; LPWSTR lpwSubKey = NULL, lpwFilePath = NULL, lpwKeyRoot = NULL; UINT uCount = 0; CRegistry creg; INFCONTEXT InfContext;
//
// The entry in the uninstall INF will have the following format:
// HKxx,SubKeyPath,PathToBackupFile
//
//
// Step through each entry in the queue
//
while (g_si.RestoreRegistryQueue.GetSize()) {
g_si.RestoreRegistryQueue.Dequeue(wszEntry, MAX_PATH - 1, FALSE);
pUnicodeToAnsi(wszEntry, szEntry, MAX_PATH);
//
// Loop through all the lines in the restore registry section(s),
// and perform the restore
//
fReturn = SetupFindFirstLineA(g_si.hInf, szEntry, NULL, &InfContext) && SetupGetLineTextA(&InfContext, NULL, NULL, NULL, szKeyPath, MAX_PATH*3, NULL);
while (fReturn) {
pAnsiToUnicode(szKeyPath, wszKeyPath, MAX_PATH*3);
//
// Split the key path into three separate parts
//
lpwKeyRoot = GetNextToken(wszKeyPath, L","); if (NULL == lpwKeyRoot) { break; }
Print(TRACE, L"[UninstallRestoreRegistryKeys] Key root: %s\n", lpwKeyRoot);
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; }
//
// Get the subkey path
//
lpwSubKey = GetNextToken(NULL, L",");
if (NULL == lpwSubKey) { break; }
Print(TRACE, L"[UninstallRestoreRegistryKeys] Subkey path: %s\n", lpwSubKey);
//
// Get the file name with full path
//
lpwFilePath = GetNextToken(NULL, L",");
if (NULL == lpwFilePath) { break; } Print(TRACE, L"[UninstallRestoreRegistryKeys] File path: %s\n", lpwFilePath);
//
// Restore the key
//
fResult = creg.RestoreKey(hKeyRoot, lpwSubKey, lpwFilePath, TRUE);
if (!fResult) { Print(ERROR, L"[UninstallRestoreRegistryKeys] Failed to restore key\n"); return FALSE; }
fReturn = SetupFindNextLine(&InfContext, &InfContext) && SetupGetLineTextA(&InfContext, NULL, NULL, NULL, szKeyPath, MAX_PATH*3, NULL); } }
return TRUE; }
/*++
Routine Description:
Removes files from the installation directory
Arguments: None Return Value:
None
--*/ BOOL UninstallRemoveFiles() { CEnumDir ced;
//
// Remove files from the installation directory,
// but leave subdirectories alone
//
ced.EnumerateDirectoryTree(g_si.lpwInstallDirectory, DeleteOneFile, FALSE, (PVOID) TRUE);
return TRUE; }
/*++
Routine Description:
Restores files that were backed up during the install
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/ BOOL UninstallRestoreFiles() { 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.RestoreFileQueue.GetSize()) {
g_si.RestoreFileQueue.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 restore 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\\%s", g_si.lpwExtractPath, g_si.lpwUninstallDirectory, wszFileName); //
// Ensure that this file is not under WFP
//
fResult = IsFileProtected(wszDestFileName); //
// Copy the file - be sensitive to WFP
//
if (fResult) { Print(TRACE, L"[UninstallRestoreFiles] Preparing to restore WFP file from %s to %s\n", wszSourceFileName, wszDestFileName);
fResult = CommonEnableProtectedRenames();
if (!fResult) { Print(ERROR, L"[UninstallRestoreFiles] Failed to enable protected renames\n"); return FALSE; }
Print(TRACE, L"[UninstallRestoreFiles] Preparing to install WFP file from %s to %s\n", wszSourceFileName, wszDestFileName); fResult = UninstallWFPFile(wszSourceFileName, wszFileName, wszDestFileName, g_si.fUpdateDllCache);
if (!fResult) { Print(ERROR, L"[UninstallRestoreFiles] Failed to install WFP file %s\n", wszFileName); return FALSE; } } else {
Print(TRACE, L"[UninstallRestoreFiles] Preparing to restore file from %s to %s\n", wszSourceFileName, wszDestFileName);
fResult = ForceMove(wszSourceFileName, wszDestFileName);
if (!fResult) { Print(ERROR, L"[UninstallRestoreFiles] Failed to restore file from %s to %s. GLE = %d\n", wszSourceFileName, wszDestFileName, GetLastError()); return FALSE; } }
fReturn = SetupFindNextLine(&InfContext, &InfContext) && SetupGetLineTextA(&InfContext, NULL, NULL, NULL, szFileName, MAX_PATH, NULL); } }
return TRUE; }
/*++
Routine Description:
Restores 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 UninstallWFPFile( 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""; CRegistry creg;
if (g_si.fUpdateDllCache) {
Print(TRACE, L"[UninstallWFPFile] Restoring %s to DllCache dir\n", lpwSourceFileName); //
// 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"[UninstallWFPFile] Failed to copy %s to %s\n", lpwSourceFileName, wszDllCachePath); goto cleanup; return FALSE; } }
//
// This is semi-custom, but because some of the
// WFPs will be in use, we'll delay replace them
// and let the Session Manager rename them
//
lpwTempFileName = CopyTempFile(lpwSourceFileName, g_si.lpwSystem32Directory); if (NULL == lpwTempFileName) { Print(ERROR, L"[UninstallWFPFile] Failed to get temp file\n"); goto cleanup; return FALSE; } if (!MoveFileEx(lpwTempFileName, lpwDestFileNamePath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT)) { Print(ERROR, L"[UninstallWFPFile] 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:
Custom worker routine for uninstall
Arguments:
None
Return Value:
None
--*/ void UninstallCustomWorker() { //
// This is where determine if we should remove
// any regsvr32s that we did during install.
// We also remove the $Sources$ directory,
// if necessary.
// Our method of detection is to see if our
// Guid is present under the Active Setup
// key. If not, it's safe to assume that
// no package is currently installed
//
BOOL fReturn = FALSE; CRegistry creg; char szActiveSetupKey[MAX_PATH] = ""; WCHAR wszActiveSetupKey[MAX_PATH] = L""; WCHAR wszSourcesDir[MAX_PATH] = L"";
fReturn = SetupGetLineTextA(NULL, g_si.hInf, "Strings", "ActiveSetupKey", szActiveSetupKey, sizeof(szActiveSetupKey), NULL);
if (!fReturn) { return; }
pAnsiToUnicode(szActiveSetupKey, wszActiveSetupKey, MAX_PATH);
fReturn = creg.IsRegistryKeyPresent(HKEY_LOCAL_MACHINE, wszActiveSetupKey);
if (!fReturn) { wsprintf(wszSourcesDir, L"%s\\$Sources$", g_si.lpwInstallDirectory); CommonRemoveDirectoryAndFiles(wszSourcesDir, (PVOID) FALSE, TRUE, FALSE); CommonRegisterServers(FALSE); } return; }
|