|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
Duinst.cpp
Abstract:
Contains the entry point for the Dynamic Update package and the install and uninstall main functions.
Notes:
Unicode only.
History:
03/02/2001 rparsons Created --*/
#include "precomp.h"
#include "systemrestore.h"
SETUP_INFO g_si;
/*++
Routine Description:
Application entry point
Arguments:
hInstance - App instance handle hPrevInstance - Always NULL lpCmdLine - Pointer to the command line nCmdShow - Window show flag
Return Value:
-1 on failure, 0 on success
--*/ int APIENTRY WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nCmdShow ) { int nReturn = -1; BOOL fReturn = FALSE;
Print(TRACE, L"[WinMain] Application is started\n");
//
// Ensure that two separate instances of the app
// are not running
//
if (IsAnotherInstanceRunning(L"WUINST")) { return -1; }
//
// Parse the command line and save app-related
// data away
//
if (!ParseCommandLine()) { Print(ERROR, L"[WinMain] Call to ParseCommandLine failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_PARSE_CMD_LINE, TRUE); goto eh; }
g_si.hInstance = hInstance;
//
// Determine the action to take
//
if (g_si.fInstall) {
//
// Start system restore point
//
if (!SystemRestorePointStart(TRUE)) { Print(ERROR, L"[WinMain] Call to SystemRestorePointStart failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_INIT_FAILED, TRUE); goto eh; }
if (!WUInitialize()) {
Print(ERROR, L"[WinMain] Call to WUInitialize failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_INIT_FAILED, TRUE); goto eh; }
fReturn = DoInstallation(); } else if (!g_si.fInstall) {
//
// Start system restore point
//
if (!SystemRestorePointStart(FALSE)) { Print(ERROR, L"[WinMain] Call to SystemRestorePointStart failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_SYSTEM_RESTORE_FAIL, TRUE); goto eh; }
if (!WUInitialize()) { Print(ERROR, L"[WinMain] Call to WUInitialize failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_INIT_FAILED, TRUE); goto eh; } fReturn = DoUninstallation(); } else { goto eh; }
nReturn = 0;
eh: //
// Perform cleanup
//
WUCleanup(); if (nReturn == 0) { if (!SystemRestorePointEnd()) { Print(ERROR, L"[WinMain] Call to SystemRestorePointEnd failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_SYSTEM_RESTORE_FAIL, TRUE); } } else { if (!SystemRestorePointCancel()) { Print(ERROR, L"[WinMain] Call to SystemRestorePointCancel failed\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_SYSTEM_RESTORE_FAIL, TRUE); } }
return nReturn; }
/*++
Routine Description:
Performs the grunt work of the installation
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/ BOOL DoInstallation() { int nReturn = 0; WCHAR wszError[1024] = L""; WCHAR wszTemp[MAX_PATH] = L""; WCHAR wszBegin[MAX_PATH] = L""; WCHAR wszDestFileName[MAX_PATH] = L""; WORD wNumStrings = 0; LPWSTR lpwMessageArray[2];
Print(TRACE, L"[DoInstallation] Installation is starting\n");
//
// Display the prompt for installation if we're
// not in quiet mode
//
if (!g_si.fQuiet) {
LoadString(g_si.hInstance, IDS_INSTALL_PROMPT, wszTemp, MAX_PATH);
wsprintf(wszBegin, wszTemp, g_si.lpwPrettyAppName);
if (MessageBox(NULL, wszBegin, g_si.lpwMessageBoxTitle, MB_YESNO | MB_ICONQUESTION)!=IDYES) { return TRUE; } }
//
// Log an event that the install is starting
//
LogEventDisplayError(EVENTLOG_INFORMATION_TYPE, ID_INSTALL_START, FALSE, FALSE);
//
// If we're not forcing an installation, check the
// version number
//
if (!g_si.fForceInstall) { nReturn = InstallCheckVersion(); }
if (0 == nReturn) {
//
// This indicates that a newer package is installed
// on the user's PC. Warn them if we're not in quiet
// mode
//
Print(TRACE, L"[DoInstallation] Newer package is installed\n");
if (!g_si.fQuiet) {
LoadString(g_si.hInstance, IDS_NEWER_VERSION, wszTemp, MAX_PATH);
wsprintf(wszError, wszTemp, g_si.lpwPrettyAppName, g_si.lpwPrettyAppName);
if (MessageBox(NULL, wszError, g_si.lpwMessageBoxTitle, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2)!=IDYES) { return TRUE; } } else {
//
// If we're in quiet mode, log an event to the event log
//
LogEventDisplayError(EVENTLOG_INFORMATION_TYPE, ID_NO_ACTION_TAKEN, FALSE, FALSE); return TRUE; } }
//
// Attempt to verify if our target directory exists
// If not, try to create it
//
if (GetFileAttributes(g_si.lpwInstallDirectory)== -1) {
if (!CreateDirectory(g_si.lpwInstallDirectory, NULL)) { wNumStrings = 0; lpwMessageArray[wNumStrings++] = (LPWSTR) g_si.lpwPrettyAppName; lpwMessageArray[wNumStrings++] = (LPWSTR) g_si.lpwInstallDirectory; LogWUEvent(EVENTLOG_ERROR_TYPE, ID_NO_APPPATCH_DIR, 2, (LPCWSTR*) lpwMessageArray); if (!g_si.fQuiet) {
DisplayErrMsg(GetDesktopWindow(), ID_NO_APPPATCH_DIR, (LPWSTR) lpwMessageArray); }
Print(ERROR, L"[DoInstallation] Failed to create installation directory\n");
return FALSE; } } //
// If we need to adjust permissions on our target directory, do it
//
if (g_si.fNeedToAdjustACL) { if (!AdjustDirectoryPerms(g_si.lpwInstallDirectory)) { wNumStrings = 0; lpwMessageArray[wNumStrings++] = (LPWSTR) g_si.lpwPrettyAppName; lpwMessageArray[wNumStrings++] = (LPWSTR) g_si.lpwInstallDirectory;
LogWUEvent(EVENTLOG_ERROR_TYPE, ID_ACL_APPPATCH_FAILED, 2, (LPCWSTR*) lpwMessageArray);
if (!g_si.fQuiet) { DisplayErrMsg(GetDesktopWindow(), ID_ACL_APPPATCH_FAILED, (LPWSTR) lpwMessageArray); }
Print(ERROR, L"[DoInstallation] Failed to apply ACL to installation directory\n");
return FALSE; } }
//
// Get section names from the INF
//
if (!InstallGetSectionsFromINF()) {
Print(ERROR, L"[DoInstallation] Failed to get section names from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_INF_SCAN_FAILED, TRUE, FALSE); return FALSE; }
//
// Install catalog files
//
if (!InstallCatalogFiles(g_si.hInf, g_si.lpwExtractPath)) {
Print(ERROR, L"[DoInstallation] Failed to install catalog file\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_CATALOG_INSTALL_FAILED, TRUE, FALSE); return FALSE;
}
//
// If we're allowing an uninstall, backup files listed in the INF
//
if (!g_si.fNoUninstall) {
if (!InstallBackupFiles()) {
Print(ERROR, L"[DoInstallation] Failed to backup files from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_FILE_BACKUP_FAILED, TRUE, FALSE); g_si.fCanUninstall = FALSE; } }
//
// If we're allowing an uninstall and the backup of files worked,
// backup registry keys listed in the INF
//
if (!g_si.fNoUninstall) {
if (g_si.fCanUninstall) {
if (!InstallBackupRegistryKeys()) {
Print(ERROR, L"[DoInstallation] Failed to backup registry keys from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_REG_BACKUP_FAILED, TRUE, FALSE); g_si.fCanUninstall = FALSE; } } }
//
// Remove any registry keys specified in the INF
//
CommonDeleteRegistryKeys();
//
// Remove files from the installation directory
//
CommonRemoveDirectoryAndFiles(g_si.lpwInstallDirectory, (PVOID) TRUE, FALSE, FALSE);
//
// Copy files specified in the INF
//
if (!InstallCopyFiles()) {
Print(ERROR, L"[DoInstallation] Failed to copy files from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_FILE_COPY_FAILED, TRUE, FALSE); return FALSE; }
//
// Merge any registry data specified in the INF
//
if (!InstallRegistryData()) {
Print(ERROR, L"[DoInstallation] Failed to install registry data from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_REG_MERGE_FAILED, TRUE, FALSE); return FALSE; }
//
// Perform any server registrations specified in the INF
//
if (!CommonRegisterServers(TRUE)) {
Print(ERROR, L"[DoInstallation] Failed to register servers from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_REGSVR32_FAILED, TRUE, FALSE); }
//
// Run any processes specified in the INF
//
InstallRunINFProcesses();
//
// If the backup operations worked, write out the uninstall key
// In addition, put our uninstall INF in the installation directory
//
if (g_si.fCanUninstall) { InstallWriteUninstallKey(); wsprintf(wszDestFileName, L"%s\\%s", g_si.lpwInstallDirectory, UNINST_INF_FILE_NAMEW);
ForceCopy(g_si.lpwUninstallINFPath, wszDestFileName); }
//
// Perform a reboot
//
if (!g_si.fQuiet && !g_si.fNoReboot) { LoadString(g_si.hInstance, IDS_REBOOT_NEEDED, wszTemp, MAX_PATH); nReturn = MessageBox(NULL, wszTemp, g_si.lpwMessageBoxTitle, MB_YESNO | MB_ICONQUESTION);
if (nReturn == IDYES) {
if (!ShutdownSystem(FALSE, TRUE)) {
// The shutdown failed - prompt the user for a manual one
LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_INS_REBOOT_FAILED, TRUE, FALSE); } else {
// The shutdown was successful - write a message to the event log
LogEventDisplayError(EVENTLOG_INFORMATION_TYPE, ID_INSTALL_SUCCESSFUL, FALSE, FALSE); } } else {
// Interactive mode - the user said no to the reboot - write it to the event log
// Don't display a message.
LogEventDisplayError(EVENTLOG_WARNING_TYPE, ID_INS_QREBOOT_NEEDED, FALSE, FALSE); } } else { // Quiet mode - A reboot is needed - write it to event log
LogEventDisplayError(EVENTLOG_WARNING_TYPE, ID_INS_QREBOOT_NEEDED, FALSE, FALSE); }
Print(TRACE, L"[DoInstallation] Installation is complete\n");
return TRUE; }
/*++
Routine Description:
Performs the grunt work of the uninstall
Arguments:
None
Return Value:
TRUE on success, FALSE otherwise
--*/ BOOL DoUninstallation() { WCHAR wszTemp[MAX_PATH] = L""; WCHAR wszBegin[MAX_PATH] = L""; WCHAR wszBackupDir[MAX_PATH] = L""; char szGuid[80] = ""; WCHAR wszGuid[80] = L""; BOOL fReturn = FALSE; int nReturn = 0;
Print(TRACE, L"[DoUninstallation] Uninstall is starting\n");
//
// Display the prompt for installation if we're
// not in quiet mode
//
if (!g_si.fQuiet) {
LoadString(g_si.hInstance, IDS_UNINSTALL_PROMPT, wszTemp, MAX_PATH);
wsprintf(wszBegin, wszTemp, g_si.lpwPrettyAppName);
if (MessageBox(NULL, wszBegin, g_si.lpwMessageBoxTitle, MB_YESNO | MB_ICONQUESTION)!=IDYES) { return TRUE; } }
//
// Log an event that the uninstall is starting
//
LogEventDisplayError(EVENTLOG_INFORMATION_TYPE, ID_UNINSTALL_START, FALSE, FALSE);
//
// Get section names from the INF
//
if (!UninstallGetSectionsFromINF()) {
Print(ERROR, L"[DoUninstallation] Failed to get section names from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_INF_SCAN_FAILED, TRUE, FALSE); return FALSE; }
//
// Remove the Uninstall key
// If we replaced it during install, it will be restored
// below. If not, no package was installed previously
//
fReturn = SetupGetLineTextA(NULL, g_si.hInf, "Strings", "GUID", szGuid, sizeof(szGuid), NULL);
if (!fReturn) { Print(ERROR, L"[DoUninstallation] Failed to get GUID from INF\n"); LogEventDisplayError(NULL, EVENTLOG_ERROR_TYPE, ID_GET_INF_FAIL, TRUE); return FALSE; }
pAnsiToUnicode(szGuid, wszGuid, 80);
UninstallDeleteSubKey(REG_UNINSTALL, wszGuid); UninstallDeleteSubKey(REG_ACTIVE_SETUP, wszGuid);
//
// Delete any registry keys in prep for restore
//
if (!CommonDeleteRegistryKeys()) {
Print(ERROR, L"[DoUninstallation] Failed to delete registry keys\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_REG_DELETE_FAILED, TRUE, FALSE); return FALSE; }
//
// Restore registry keys we replaced
//
if (!UninstallRestoreRegistryKeys()) {
Print(ERROR, L"[DoUninstallation] Failed to restore registry keys from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_REG_RESTORE_FAILED, TRUE, FALSE); return FALSE; }
//
// The routine below does some custom things
//
UninstallCustomWorker();
//
// Remove files under the installation directory
//
UninstallRemoveFiles();
//
// Restore any files we replaced
//
if (!UninstallRestoreFiles()) { Print(ERROR, L"[DoUninstallation] Failed to restore files from INF\n"); LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_FILE_RESTORE_FAILED, TRUE, FALSE); return FALSE; }
//
// Remove the '$Uninstall$ directory and delete the uninstall INF file
//
wsprintf(wszBackupDir, L"%s\\%s", g_si.lpwInstallDirectory, g_si.lpwUninstallDirectory);
Print(TRACE, L"[DoUninstallation] Path to Uninstall dir: %s\n", wszBackupDir);
CommonRemoveDirectoryAndFiles(wszBackupDir, (PVOID) FALSE, TRUE, FALSE);
SetupCloseInfFile(g_si.hInf);
DeleteFile(g_si.lpwUninstallINFPath); //
// Perform a reboot
//
if (!g_si.fQuiet) { LoadString(g_si.hInstance, IDS_REBOOT_NEEDED, wszTemp, MAX_PATH); // Prompt the user to reboot
nReturn = MessageBox(NULL, wszTemp, g_si.lpwMessageBoxTitle, MB_YESNO | MB_ICONQUESTION);
if (nReturn == IDYES) {
if (!ShutdownSystem(FALSE, TRUE)) {
// The shutdown failed - prompt the user for a manual one
LogEventDisplayError(EVENTLOG_ERROR_TYPE, ID_UNINS_REBOOT_FAILED, TRUE, FALSE); } else {
// The shutdown was successful - write a message to the event log
LogEventDisplayError(EVENTLOG_INFORMATION_TYPE, ID_UNINSTALL_SUCCESSFUL, FALSE, FALSE); } } else {
// Interactive mode - the user said no to the reboot - write it to the event log
// Don't display a message.
LogEventDisplayError(EVENTLOG_WARNING_TYPE, ID_UNINS_QREBOOT_NEEDED, FALSE, FALSE); } } else {
// Quiet mode - A reboot is needed - write it to event log
LogEventDisplayError(EVENTLOG_WARNING_TYPE, ID_UNINS_QREBOOT_NEEDED, FALSE, FALSE); }
return TRUE; }
|