Windows: Backup and restore configuration across installs
authorAsanka C. Herath <asanka@secure-endpoints.com>
Mon, 18 Oct 2010 08:52:34 +0000 (04:52 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Sat, 23 Oct 2010 20:35:22 +0000 (13:35 -0700)
The MSI installer for OpenAFS does not preserve configuration data
across installs.  This patch creates a backup of specific
configuration registry values when uninstalling OpenAFS and uses this
backup when subsequently installing OpenAFS.

Change-Id: Ie30f8f7f0eada3f0aeef2341b04aca55657ec864
Reviewed-on: http://gerrit.openafs.org/2977
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/install/wix/Binary/newconfig.ico [new file with mode: 0644]
src/WINNT/install/wix/Binary/restore.ico [new file with mode: 0644]
src/WINNT/install/wix/custom/NTMakefile
src/WINNT/install/wix/custom/afscustom.cpp
src/WINNT/install/wix/lang/en_US/ui.wxi
src/WINNT/install/wix/openafs.wxs
src/WINNT/install/wix/property.wxi
src/WINNT/install/wix/registry.wxi

diff --git a/src/WINNT/install/wix/Binary/newconfig.ico b/src/WINNT/install/wix/Binary/newconfig.ico
new file mode 100644 (file)
index 0000000..1da8cac
Binary files /dev/null and b/src/WINNT/install/wix/Binary/newconfig.ico differ
diff --git a/src/WINNT/install/wix/Binary/restore.ico b/src/WINNT/install/wix/Binary/restore.ico
new file mode 100644 (file)
index 0000000..3204c58
Binary files /dev/null and b/src/WINNT/install/wix/Binary/restore.ico differ
index ddd1c8b..01038bd 100644 (file)
@@ -18,7 +18,10 @@ DLLEXPORTS=\
        -EXPORT:AbortMsiImmediate \
        -EXPORT:UninstallNsisInstallation \
         -EXPORT:CreateAFSClientAdminGroup \
-        -EXPORT:RemoveAFSClientAdminGroup
+        -EXPORT:RemoveAFSClientAdminGroup \
+       -EXPORT:BackupAFSClientRegistryKeys \
+       -EXPORT:RestoreAFSClientRegistryKeys \
+       -EXPORT:DetectSavedConfiguration
 
 DLLLIBFILES=\
        msi.lib advapi32.lib netapi32.lib
index 08f1554..9e03670 100644 (file)
@@ -38,9 +38,14 @@ SOFTWARE.
 // Only works for Win2k and above
 
 #define _WIN32_WINNT 0x0500
+#define UNICODE
+#define _UNICODE
 
 #include "afscustom.h"
-#include "tchar.h"
+#include <varargs.h>
+#include <tchar.h>
+#include <strsafe.h>
+
 
 void ShowMsiError( MSIHANDLE hInstall, DWORD errcode, DWORD param ){
        MSIHANDLE hRecord;
@@ -79,7 +84,7 @@ MSIDLLEXPORT AbortMsiImmediate( MSIHANDLE hInstall ) {
 
        dwSize = 0;
 
-       rv = MsiFormatRecord(hInstall, hRecord, "", &dwSize);
+       rv = MsiFormatRecord(hInstall, hRecord, _T(""), &dwSize);
        if(rv != ERROR_MORE_DATA) goto _cleanup;
 
        sFormatted = new TCHAR[ ++dwSize ];
@@ -485,3 +490,384 @@ UINT removeAfsAdminGroup(void) {
     return status;
 }
 
+const TCHAR * reg_NP = _T("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider");
+const TCHAR * reg_NP_Backup = _T("SOFTWARE\\OpenAFS\\Client\\BackupSettings\\NetworkProvider");
+
+const TCHAR * reg_NP_Domains = _T("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider\\Domain");
+const TCHAR * reg_NP_Domains_Backup = _T("SOFTWARE\\OpenAFS\\Client\\BackupSettings\\NetworkProvider\\Domain");
+
+const TCHAR * reg_Param = _T("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
+const TCHAR * reg_Param_Backup = _T("SOFTWARE\\OpenAFS\\Client\\BackupSettings\\Parameters");
+
+const TCHAR * reg_Client = _T("SOFTWARE\\OpenAFS\\Client");
+const TCHAR * reg_Client_Backup = _T("SOFTWARE\\OpenAFS\\Client\\BackupSettings\\Client");
+
+const TCHAR * reg_Backup = _T("SOFTWARE\\OpenAFS\\Client\\BackupSettings");
+
+const TCHAR * reg_NP_values[] = {
+    _T("LogonOptions"),
+    _T("VerboseLogging"),
+    _T("LogonScript"),
+    _T("FailLoginsSilently"),
+    _T("LoginRetryInterval"),
+    _T("LoginSleepInterval"),
+    _T("Realm"),
+    _T("TheseCells"),
+    NULL
+};
+
+const TCHAR * reg_Everything[] = {
+    _T("*"),
+    NULL
+};
+
+const TCHAR * reg_Client_values[] = {
+    _T("CellServDBDir"),
+    _T("VerifyServiceSignature"),
+    _T("IoctlDebug"),
+    _T("MiniDumpType"),
+    _T("SMBAsyncStoreSize"),
+    _T("StoreAnsiFilenames"),
+    _T("StartAfscredsOnStartup"),
+    _T("AfscredsShortcutParams"),
+    NULL
+};
+
+struct registry_backup {
+    const TCHAR * key;
+    const TCHAR ** values;
+    const TCHAR * backup_key;
+} registry_backups[] = {
+
+    // Subkeys must be specified before parent keys.
+
+    { reg_NP_Domains, reg_Everything, reg_NP_Domains_Backup },
+    { reg_NP, reg_NP_values, reg_NP_Backup },
+    { reg_Param, reg_Everything, reg_Param_Backup },
+    { reg_Client, reg_Client_values, reg_Client_Backup },
+    { NULL, NULL, NULL }
+};
+
+void
+ShowMsiActionData(MSIHANDLE hInstall, const TCHAR * format, ...)
+{
+    va_list vl;
+    TCHAR buf[1024];
+    MSIHANDLE hRec;
+
+    va_start(vl, format);
+    StringCbVPrintf(buf, sizeof(buf), format, vl);
+    va_end(vl);
+
+    hRec = MsiCreateRecord(2);
+    MsiRecordSetString(hRec, 1, buf);
+    MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONDATA, hRec);
+    MsiCloseHandle(hRec);
+}
+
+void
+do_reg_copy_value(MSIHANDLE hInstall, HKEY hk_src, HKEY hk_dest, const TCHAR * value)
+{
+    BYTE static_buffer[4096];
+    BYTE * buffer = static_buffer;
+    DWORD cb = sizeof(static_buffer);
+    LONG rv;
+    DWORD type = 0;
+
+    rv = RegQueryValueEx(hk_src, value, 0, &type, buffer, &cb);
+    if (rv == ERROR_MORE_DATA) {
+        buffer = new BYTE[cb];
+        if (buffer == NULL) {
+            ShowMsiActionData(hInstall, _T("Out of memory"));
+            return;
+        }
+
+        rv = RegQueryValueEx(hk_src, value, 0, &type, buffer, &cb);
+    }
+
+    if (rv == ERROR_SUCCESS) {
+        rv = RegSetValueEx(hk_dest, value, 0, type, buffer, cb);
+        if (rv == ERROR_SUCCESS) {
+            ShowMsiActionData(hInstall, _T("Copied value [%s]"), value);
+        } else {
+            ShowMsiActionData(hInstall, _T("Can't write value [%s]. Return code =%d"), value, rv);
+        }
+    } else if (rv != ERROR_FILE_NOT_FOUND) {
+        ShowMsiActionData(hInstall, _T("Can't read registry value [%s].  Return code = %d"), value, rv);
+    }
+
+    if (buffer != static_buffer)
+        delete[] buffer;
+}
+
+//! Copy a registry key and optionally all its subkeys
+//
+// @return TRUE if the source was deleted
+BOOL
+do_reg_copy(MSIHANDLE hInstall,
+            HKEY hk_root_src, const TCHAR * src,
+            HKEY hk_root_dest, const TCHAR * dest,
+            const TCHAR ** values, BOOL delete_source)
+{
+    BOOL retval = FALSE;
+    HKEY hk_src = 0;
+    HKEY hk_dest = 0;
+
+    LONG rv;
+
+    rv = RegOpenKeyEx(hk_root_src, src, 0, KEY_READ, &hk_src);
+    if (rv != ERROR_SUCCESS) {
+        if (rv == ERROR_FILE_NOT_FOUND) {
+            ShowMsiActionData(hInstall, _T("Source key %s does not exist"), src);
+        } else {
+            ShowMsiActionData(hInstall, _T("Can't open source key while copying %s.  Return value=%d"), src, rv);
+        }
+        goto cleanup;
+    }
+
+    ShowMsiActionData(hInstall, _T("Copying registry key %s to %s"), src, dest);
+
+    // If dest == NULL, then we are just being asked to cleanup src
+    if (dest == NULL)
+        goto del_source;
+
+    rv = RegCreateKeyEx(hk_root_dest, dest, 0, NULL, REG_OPTION_NON_VOLATILE,
+                        KEY_WRITE, NULL, &hk_dest, NULL);
+    if (rv != ERROR_SUCCESS) {
+        ShowMsiActionData(hInstall, _T("Can't create target key.  Return value=%d"), rv);
+        goto cleanup;
+    }
+
+    if (values[0][0] == _T('*')) {
+        BOOL retry;
+
+        for (DWORD index = 0; ; index++) {
+            TCHAR name[16384];
+            DWORD cch = 16384;
+
+            rv = RegEnumValue(hk_src, index, name, &cch, NULL, NULL, NULL, NULL);
+            if (rv == ERROR_SUCCESS) {
+                do_reg_copy_value(hInstall, hk_src, hk_dest, name);
+            } else {
+                break;
+            }
+        }
+
+        do {
+            retry = FALSE;
+
+            for (DWORD index = 0; ; index++) {
+                TCHAR name[256];
+                DWORD cch = 256;
+
+                rv = RegEnumKeyEx(hk_src, index, name, &cch, NULL, NULL, NULL, NULL);
+                if (rv == ERROR_SUCCESS) {
+                    if (do_reg_copy(hInstall, hk_src, name, hk_dest, name,
+                                    reg_Everything, delete_source)) {
+                        index--;
+                        retry = TRUE;
+                    }
+                } else {
+                    break;
+                }
+            }
+
+        } while (retry);
+
+    } else {
+
+        for (const TCHAR ** pv = values; *pv; pv++) {
+            do_reg_copy_value(hInstall, hk_src, hk_dest, *pv);
+        }
+    }
+
+del_source:
+    if (delete_source) {
+        rv = RegDeleteKey(hk_root_src, src);
+        retval = (rv == ERROR_SUCCESS);
+        if (rv == ERROR_SUCCESS) {
+            ShowMsiActionData(hInstall, _T("Deleted source key"));
+        } else {
+            ShowMsiActionData(hInstall, _T("Unable to delete source key. Return code=%d"), rv);
+        }
+    }
+
+cleanup:
+    if (hk_dest != 0)
+        RegCloseKey(hk_dest);
+    if (hk_src != 0)
+        RegCloseKey(hk_src);
+
+    return retval;
+}
+
+
+MSIDLLEXPORT BackupAFSClientRegistryKeys( MSIHANDLE hInstall )
+{
+    registry_backup *b;
+    MSIHANDLE hRec;
+
+    hRec = MsiCreateRecord(4);
+    MsiRecordSetString(hRec, 1, _T("BackupAFSClientRegistryKeys"));
+    MsiRecordSetString(hRec, 2, _T("Backing up AFS client configuration registry keys"));
+    MsiRecordSetString(hRec, 3, _T("[1]"));
+    MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONSTART, hRec);
+    MsiCloseHandle(hRec);
+
+    for (b = registry_backups; b->key != NULL; b++) {
+        do_reg_copy(hInstall, HKEY_LOCAL_MACHINE, b->key, HKEY_LOCAL_MACHINE, b->backup_key,
+                    b->values, FALSE);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+MSIDLLEXPORT RestoreAFSClientRegistryKeys( MSIHANDLE hInstall )
+{
+    registry_backup *b;
+    MSIHANDLE hRec;
+
+    hRec = MsiCreateRecord(4);
+    MsiRecordSetString(hRec, 1, _T("RestoreAFSClientRegistryKeys"));
+    MsiRecordSetString(hRec, 2, _T("Restoring AFS client configuration registry keys"));
+    MsiRecordSetString(hRec, 3, _T("[1]"));
+    MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONSTART, hRec);
+    MsiCloseHandle(hRec);
+
+    for (b = registry_backups; b->key != NULL; b++) {
+        do_reg_copy(hInstall, HKEY_LOCAL_MACHINE, b->backup_key, HKEY_LOCAL_MACHINE, b->key,
+                    b->values, TRUE);
+    }
+    do_reg_copy(hInstall, HKEY_LOCAL_MACHINE, reg_Backup, NULL, NULL, NULL, TRUE);
+
+    return ERROR_SUCCESS;
+}
+
+LONG
+SetMsiPropertyFromRegValue(MSIHANDLE hInstall, HKEY hk,
+                           const TCHAR * property, const TCHAR * value_name)
+{
+    LONG rv;
+    BYTE static_buffer[4096];
+    BYTE *buffer = static_buffer;
+    DWORD cb = sizeof(static_buffer);
+    DWORD type = 0;
+
+    rv = RegQueryValueEx(hk, value_name, NULL, &type, buffer, &cb);
+    if (rv == ERROR_FILE_NOT_FOUND)
+        return rv;
+
+    if (rv == ERROR_MORE_DATA ||
+        ((type == REG_SZ || type == REG_EXPAND_SZ) && cb >= sizeof(static_buffer))) {
+
+        if (type == REG_SZ || type == REG_EXPAND_SZ)
+            cb += sizeof(TCHAR);
+
+        buffer = new BYTE[cb];
+        rv = RegQueryValueEx(hk, value_name, NULL, &type, buffer, &cb);
+    }
+
+    if (rv != ERROR_SUCCESS)
+        goto cleanup;
+
+    switch (type) {
+    case REG_DWORD:
+    {
+        DWORD d = *((DWORD *) buffer);
+        StringCbPrintf((TCHAR *) static_buffer, sizeof(static_buffer), _T("%d"), (int) d);
+        rv = MsiSetProperty(hInstall, property, (const TCHAR *) static_buffer);
+        break;
+    }
+
+    case REG_SZ:
+    case REG_EXPAND_SZ:
+    {
+        TCHAR * s = (TCHAR *) buffer;
+
+        if (s[cb / sizeof(TCHAR) - 1] != _T('\0'))
+            s[cb / sizeof(TCHAR)] = _T('\0');
+        rv = MsiSetProperty(hInstall, property, s);
+        break;
+    }
+
+    default:
+        rv = ERROR_FILE_NOT_FOUND;
+    }
+
+cleanup:
+    if (buffer != static_buffer)
+        delete[] buffer;
+
+    return rv;
+}
+
+LONG
+SetAfscredsOptionsFromRegValue(MSIHANDLE hInstall, HKEY hk)
+{
+    TCHAR buffer[16];
+    DWORD cb = sizeof(buffer);
+    LONG rv;
+    DWORD type;
+
+    rv = RegQueryValueEx(hk, _T("AfscredsShortcutParams"), NULL, &type, (LPBYTE) buffer, &cb);
+    if (rv != ERROR_SUCCESS || type != REG_SZ || cb == sizeof(buffer)) {
+        return ERROR_FILE_NOT_FOUND;
+    }
+
+    MsiSetProperty(hInstall, _T("CREDSAUTOINIT"), (_tcsstr(buffer, _T("-a")) != NULL)? _T("-a"): NULL);
+    MsiSetProperty(hInstall, _T("CREDSIPCHDET"), (_tcsstr(buffer, _T("-n")) != NULL)? _T("-n"): NULL);
+    MsiSetProperty(hInstall, _T("CREDSQUIET"), (_tcsstr(buffer, _T("-q")) != NULL)? _T("-q"): NULL);
+    MsiSetProperty(hInstall, _T("CREDSRENEWDRMAP"), (_tcsstr(buffer, _T("-m")) != NULL)? _T("-m"): NULL);
+    MsiSetProperty(hInstall, _T("CREDSSHOW"), (_tcsstr(buffer, _T("-s")) != NULL)? _T("-s"): NULL);
+
+    return rv;
+}
+
+/// Pull in known configuration values for use during this installation
+//
+MSIDLLEXPORT DetectSavedConfiguration( MSIHANDLE hInstall )
+{
+    {
+        MSIHANDLE hRec;
+
+        hRec = MsiCreateRecord(4);
+        MsiRecordSetString(hRec, 1, _T("DetectSavedConfiguration"));
+        MsiRecordSetString(hRec, 2, _T("Detecting saved configuration"));
+        MsiRecordSetString(hRec, 3, _T("[1]"));
+        MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONSTART, hRec);
+        MsiCloseHandle(hRec);
+    }
+
+    HKEY hk_client = 0, hk_param = 0, hk_np = 0;
+    LONG rv;
+    BOOL found = FALSE;
+
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_Param_Backup, 0, KEY_READ, &hk_param);
+    if (rv == ERROR_SUCCESS) {
+        SetMsiPropertyFromRegValue(hInstall, hk_param, _T("AFSCELLNAME"), _T("Cell"));
+        SetMsiPropertyFromRegValue(hInstall, hk_param, _T("FREELANCEMODE"), _T("FreelanceClient"));
+        SetMsiPropertyFromRegValue(hInstall, hk_param, _T("USEDNS"), _T("UseDNS"));
+        SetMsiPropertyFromRegValue(hInstall, hk_param, _T("SECURITYLEVEL"), _T("SecurityLevel"));
+        RegCloseKey(hk_param);
+        found = TRUE;
+    }
+
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_Client_Backup, 0, KEY_READ, &hk_client);
+    if (rv == ERROR_SUCCESS) {
+        SetMsiPropertyFromRegValue(hInstall, hk_client, _T("CREDSSTARTUP"), _T("StartAfscredsOnStartup"));
+        SetAfscredsOptionsFromRegValue(hInstall, hk_client);
+        RegCloseKey(hk_client);
+        found = TRUE;
+    }
+
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_NP_Backup, 0, KEY_READ, &hk_np);
+    if (rv == ERROR_SUCCESS) {
+        SetMsiPropertyFromRegValue(hInstall, hk_np, _T("LOGONOPTIONS"), _T("LogonOptions"));
+        RegCloseKey(hk_np);
+        found = TRUE;
+    }
+
+    MsiSetProperty(hInstall, _T("SAVED_CONFIG"), (found)?_T("1"):NULL);
+
+    return 0;
+}
index cc351b5..cd12f7b 100644 (file)
@@ -37,6 +37,8 @@
                <Property Id="Setup">Setup</Property>
                <Property Id="ShowUserRegistrationDlg">0</Property>
                <Property Id="Wizard">Setup Wizard</Property>
+                <Property Id="RestoreIcon">restore</Property>
+                <Property Id="NewSettingsIcon">newconfig</Property>
 
       <Dialog Id="AdminBrowseDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes">
         <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="17" Property="TARGETDIR" />
         <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
           <?ifndef BinsOnly ?>
           <Publish Event="NewDialog" Value="ConfigClientDlg">
-            <![CDATA[ &feaClient = 3 AND NOT ((&feaServer=3 OR (!feaServer=3 AND &feaServer<1)) AND (&feaClient=2 OR (&feaClient<>3 AND !feaClient<>3) OR &feaControlCenter=2 OR (&feaControlCenter<>3 AND !feaControlCenter<>3) ))]]>
+            <![CDATA[ &feaClient = 3 AND NOT ((&feaServer=3 OR (!feaServer=3 AND &feaServer<1)) AND (&feaClient=2 OR (&feaClient<>3 AND !feaClient<>3) OR &feaControlCenter=2 OR (&feaControlCenter<>3 AND !feaControlCenter<>3) )) AND NOT SAVED_CONFIG ]]>
+          </Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">
+            <![CDATA[ &feaClient = 3 AND NOT ((&feaServer=3 OR (!feaServer=3 AND &feaServer<1)) AND (&feaClient=2 OR (&feaClient<>3 AND !feaClient<>3) OR &feaControlCenter=2 OR (&feaControlCenter<>3 AND !feaControlCenter<>3) )) AND SAVED_CONFIG ]]>
           </Publish>
           <Publish Event="NewDialog" Value="VerifyReadyDlg">
             <![CDATA[ &feaClient <> 3 AND NOT ((&feaServer=3 OR (!feaServer=3 AND &feaServer<1)) AND (&feaClient=2 OR (&feaClient<>3 AND !feaClient<>3) OR &feaControlCenter=2 OR (&feaControlCenter<>3 AND !feaControlCenter<>3) ))]]>
           <Publish Event="AddLocal" Value="feaClient"><![CDATA[&feaClient=2 OR (&feaClient<>3 AND !feaClient<>3)]]></Publish>
           <Publish Event="AddLocal" Value="feaControlCenter"><![CDATA[&feaControlCenter=2 OR (&feaControlCenter<>3 AND !feaControlCenter<>3)]]></Publish>
           <Publish Event="NewDialog" Value="ConfigClientDlg">
-            <![CDATA[ &feaClient = 3 ]]>
+            <![CDATA[ &feaClient = 3 AND NOT SAVED_CONFIG ]]>
+          </Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">
+            <![CDATA[ &feaClient = 3 AND SAVED_CONFIG ]]>
           </Publish>
           <Publish Event="NewDialog" Value="VerifyReadyDlg">
             <![CDATA[ &feaClient <> 3 ]]>
           <Publish Property="InstallMode" Value="Typical">1</Publish>
           <Publish Event="SetInstallLevel" Value="100">1</Publish>
           <?ifndef BinsOnly?>
-         <Publish Event="NewDialog" Value="ConfigClientDlg">1</Publish>
+         <Publish Event="NewDialog" Value="ConfigClientDlg">NOT SAVED_CONFIG</Publish>
+         <Publish Event="NewDialog" Value="RestoreConfigDlg">SAVED_CONFIG</Publish>
           <?else?>
          <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
           <?endif?>
           <Publish Property="InstallMode" Value="Complete">1</Publish>
           <Publish Event="SetInstallLevel" Value="1000">1</Publish>
           <?ifndef BinsOnly ?>
-          <Publish Event="NewDialog" Value="ConfigClientDlg">1</Publish>
+          <Publish Event="NewDialog" Value="ConfigClientDlg">NOT SAVED_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">SAVED_CONFIG</Publish>
           <?else?>
           <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
           <?endif?>
       </Dialog>
 
       <?ifndef BinsOnly ?>
-      <Dialog Id="ConfigClientDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes">
+
+      <Dialog Id="RestoreConfigDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes">
+        <Control Id="RestoreLabel" Type="Text" X="105" Y="65" Width="100" Height="10" TabSkip="no">
+          <Text>[DlgTitleFont]&amp;Restore</Text>
+        </Control>
+        <Control Id="RestoreButton" Type="PushButton" X="50" Y="65" Width="38" Height="38" ToolTip="Restore saved settings" Default="yes" Icon="yes" FixedSize="yes" IconSize="32" Text="[RestoreIcon]">
+          <Publish Property="RESTORE_CONFIG" Value="1">1</Publish>
+         <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+        </Control>
+        <Control Id="NewSettingsLabel" Type="Text" X="105" Y="118" Width="100" Height="10" TabSkip="no">
+          <Text>[DlgTitleFont]&amp;New settings</Text>
+        </Control>
+        <Control Id="NewSettingsButton" Type="PushButton" X="50" Y="118" Width="38" Height="38" ToolTip="New settings" Icon="yes" FixedSize="yes" IconSize="32" Text="[NewSettingsIcon]">
+          <Publish Property="RESTORE_CONFIG">1</Publish>
+          <Publish Event="NewDialog" Value="ConfigClientDlg">1</Publish>
+        </Control>
         <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
           <Publish Event="NewDialog" Value="CustomizeDlg">InstallMode &lt;&gt; "Typical" AND InstallMode &lt;&gt; "Complete"</Publish>
           <Publish Event="NewDialog" Value="SetupTypeDlg">InstallMode = "Typical" OR InstallMode = "Complete"</Publish>
         </Control>
+        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" />
+        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
+          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
+        </Control>
+        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="374" Height="44" FixedSize="yes" TabSkip="no" Text="[BannerBitmap]" />
+        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
+          <Text>Configuration settings from a prior OpenAFS installation is available.</Text>
+        </Control>
+        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="374" Height="0" />
+        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="374" Height="0" />
+        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
+          <Text>[DlgTitleFont]Restore configuration?</Text>
+        </Control>
+        <Control Id="CustomText" Type="Text" X="105" Y="131" Width="230" Height="30">
+          <Text>Specify new settings.  Basic settings can be set via this installer.  All others will be reset to defaults.</Text>
+        </Control>
+        <Control Id="TypicalText" Type="Text" X="105" Y="78" Width="230" Height="20">
+          <Text>Restore and use the saved configuration settings.</Text>
+        </Control>
+      </Dialog>
+
+      <Dialog Id="ConfigClientDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes">
+        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
+          <Publish Event="NewDialog" Value="CustomizeDlg">InstallMode &lt;&gt; "Typical" AND InstallMode &lt;&gt; "Complete" AND NOT SAVED_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="SetupTypeDlg">( InstallMode = "Typical" OR InstallMode = "Complete" ) AND NOT SAVED_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">SAVED_CONFIG</Publish>
+        </Control>
         <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Text="[ButtonText_Next]">
           <Publish Event="NewDialog" Value="ConfigCredsDlg">1</Publish>
         </Control>
         <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
           <Text>[DlgTitleFont]Configure AFS Client</Text>
         </Control>
-        <Control Id="CellLabel" Type="Text" X="45" Y="73" Width="100" Height="15" TabSkip="no" Text="Default &amp;Cell" />
-        <Control Id="CellEdit" Type="Edit" X="150" Y="73" Width="115" Height="18" Property="AFSCELLNAME" Text="{120}" />
-        <Control Id="LogonOptionsLabel" Type="Text"                            X="45"  Y="100" Width="100" Height="15" Text="Integrated logon" />
-        <Control Id="LogonOptionSel" Type="RadioButtonGroup"   X="150" Y="100" Width="120" Height="20" Property="LOGONOPTIONS" />
-        <Control Id="SecurityLevelLabel" Type="Text"                   X="45"  Y="120" Width="100" Height="15" Text="AFS crypt security" />
-        <Control Id="SecurityLevelSel" Type="RadioButtonGroup" X="150" Y="120" Width="120" Height="20" Property="SECURITYLEVEL" />
-        <Control Id="FreelanceLabel" Type="Text"                               X="45"  Y="140" Width="100" Height="15" Text="Freelance mode" />
-        <Control Id="FreelanceSel" Type="RadioButtonGroup"             X="150" Y="140" Width="120" Height="20" Property="FREELANCEMODE" />
-        <Control Id="DNSLabel" Type="Text"                                             X="45"  Y="160" Width="100" Height="15" Text="Lookup cells in DNS" />
-        <Control Id="DNSSel" Type="RadioButtonGroup"                   X="150" Y="160" Width="120" Height="20" Property="USEDNS" />
+        <Control Id="CellLabel" Type="Text"                     X="45"  Y="73"  Width="100" Height="15" TabSkip="no" Text="Default &amp;Cell" />
+        <Control Id="CellEdit" Type="Edit"                      X="150" Y="73"  Width="115" Height="18" Property="AFSCELLNAME" Text="{120}" />
+        <Control Id="LogonOptionsLabel" Type="Text"             X="45"  Y="100" Width="100" Height="15" Text="Integrated logon" />
+        <Control Id="LogonOptionSel" Type="RadioButtonGroup"    X="150" Y="100" Width="120" Height="20" Property="LOGONOPTIONS" />
+        <Control Id="SecurityLevelLabel" Type="Text"           X="45"  Y="120" Width="100" Height="15" Text="AFS crypt security" />
+        <Control Id="SecurityLevelSel" Type="RadioButtonGroup"  X="150"        Y="120" Width="120" Height="20" Property="SECURITYLEVEL" />
+        <Control Id="FreelanceLabel" Type="Text"               X="45"  Y="140" Width="100" Height="15" Text="Freelance mode" />
+        <Control Id="FreelanceSel" Type="RadioButtonGroup"     X="150" Y="140" Width="120" Height="20" Property="FREELANCEMODE" />
+        <Control Id="DNSLabel" Type="Text"                     X="45"  Y="160" Width="100" Height="15" Text="Lookup cells in DNS" />
+        <Control Id="DNSSel" Type="RadioButtonGroup"           X="150" Y="160" Width="120" Height="20" Property="USEDNS" />
       </Dialog>
       <RadioButtonGroup Property="SECURITYLEVEL">
                <RadioButton X="5" Y="0" Width="55" Height="15" Text="Disable" Value="0"></RadioButton>
           <Publish Event="NewDialog" Value="AdminInstallPointDlg">InstallMode = "Server Image"</Publish>
           <?ifndef BinsOnly ?>
           <Publish Event="NewDialog" Value="CustomizeDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaClient &lt;&gt; 3</Publish>
-          <Publish Event="NewDialog" Value="ConfigCredsDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaClient = 3</Publish>
-          <Publish Event="NewDialog" Value="ConfigCredsDlg">InstallMode = "Typical" OR InstallMode = "Complete"</Publish>
+          <Publish Event="NewDialog" Value="ConfigCredsDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaClient = 3 AND NOT RESTORE_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="ConfigCredsDlg">(InstallMode = "Typical" OR InstallMode = "Complete") AND NOT RESTORE_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">(InstallMode = "Custom" OR InstallMode = "Change") AND &amp;feaClient = 3 AND RESTORE_CONFIG</Publish>
+          <Publish Event="NewDialog" Value="RestoreConfigDlg">(InstallMode = "Typical" OR InstallMode = "Complete") AND RESTORE_CONFIG</Publish>
           <?else?>
           <Publish Event="NewDialog" Value="CustomizeDlg">InstallMode = "Custom" OR InstallMode = "Change"</Publish>
           <Publish Event="NewDialog" Value="SetupTypeDlg">InstallMode = "Typical" OR InstallMode = "Complete"</Publish>
         <Show Dialog="MaintenanceWelcomeDlg" After="ResumeDlg">Installed AND NOT RESUME AND NOT Preselected</Show>
         <Show Dialog="ContinueDlg" After="MaintenanceWelcomeDlg">(NOT Installed) AND AFTERREBOOT</Show>
         <Show Dialog="ProgressDlg" After="ContinueDlg" />
+        <?ifndef BinsOnly?>
+        <Custom Action="DetectSavedConfiguration" Before="CostInitialize" />
+        <?endif?>
       </InstallUISequence>
     </UI>
     <Binary Id="Up" src="Binary\Up.ico" />
     <Binary Id="insticon" src="Binary\insticon.ico" />
     <Binary Id="removico" src="Binary\removico.ico" />
     <Binary Id="repairic" src="Binary\repairic.ico" />
+    <Binary Id="restore" src="Binary\restore.ico" />
+    <Binary Id="newconfig" src="Binary\newconfig.ico" />
     <Icon Id="ico_AcctManager" src="Icon\ico_AcctManager.ico" />
     <Icon Id="ico_afscreds" src="Icon\ico_afscreds.ico" />
     <Icon Id="ico_Help" src="Icon\ico_Help.ico" />
index 127af09..e955ea2 100644 (file)
                 DllEntry="AbortMsiImmediate"
                 Execute="immediate" />
                 <CustomAction
+                    Id="BackupAFSClientRegistryKeys"
+                    BinaryKey="BIN_afsCustom"
+                    DllEntry="BackupAFSClientRegistryKeys"
+                    Execute="deferred"
+                    Impersonate="no" />
+                <CustomAction
+                    Id="RestoreAFSClientRegistryKeys"
+                    BinaryKey="BIN_afsCustom"
+                    DllEntry="RestoreAFSClientRegistryKeys"
+                    Execute="deferred"
+                    Impersonate="no" />
+                <CustomAction
+                    Id="RollbackRestoreAFSClientRegistryKeys"
+                    BinaryKey="BIN_afsCustom"
+                    DllEntry="BackupAFSClientRegistryKeys"
+                    Execute="rollback"
+                    Impersonate="no" />
+                <CustomAction
+                    Id="DetectSavedConfiguration"
+                    BinaryKey="BIN_afsCustom"
+                    DllEntry="DetectSavedConfiguration"
+                    Execute="firstSequence" />
+                <CustomAction
                    Id="SetInstallLocation"
                    Property="ARPINSTALLLOCATION"
                    Value="[AFSDIR]" />
       <Custom Action="InstallIDNMRedistributable" After="WriteRegistryValues">!feaClient=2 And &amp;feaClient=3 And (VersionNT=501 Or VersionNT=502)</Custom>
                        <Custom Action="ConfigureClient" After="InstallServices">&amp;feaClient=3</Custom>
                        <Custom Action="ConfigureServer" After="ConfigureClient">&amp;feaServer=3</Custom>
+                        <Custom Action="RollbackRestoreAFSClientRegistryKeys" After="RemoveNetProvider">!feaClient=2 And &amp;feaClient=3 And RESTORE_CONFIG</Custom>
+                        <Custom Action="RestoreAFSClientRegistryKeys" After="RollbackRestoreAFSClientRegistryKeys">!feaClient=2 And &amp;feaClient=3 And RESTORE_CONFIG</Custom>
+                        <Custom Action="BackupAFSClientRegistryKeys" Before="DeleteServices">!feaClient=3 And &amp;feaClient=2</Custom>
                        <!-- <Custom Action="RemoveAFSAdminGroup" Before="">&amp;feaClient=2</Custom> -->
                        <Custom Action="RollbackAFSAdminGroup" Before="CreateAFSAdminGroup">&amp;feaClient=3</Custom>
                        <Custom Action="CreateAFSAdminGroup" Before="CreateFolders">&amp;feaClient=3</Custom>
                         <Custom Action="SetInstallLocation" Before="RegisterProduct" />
+                        <Custom Action="DetectSavedConfiguration" Before="CostInitialize" />
             <ScheduleReboot After="PublishProduct">&amp;feaClient=3 OR &amp;feaServer=3 OR &amp;feaClient=2 OR &amp;feaServer=2</ScheduleReboot>
         </InstallExecuteSequence>
 
index b8d7d9b..9446831 100644 (file)
     <!-- empty property
     <Property Id="STOREANSIFILENAMES"></Property>
     -->
+    <!-- empty property
+    <Property Id="SAVED_CONFIG" Secure="yes"></Property>
+    -->
+    <Property Id="RESTORE_CONFIG" Secure="yes">1</Property>
 <?endif?>
 
     <!-- Add/remove programs -->
index 210a974..cca7455 100644 (file)
@@ -1,4 +1,4 @@
-\feff<?xml version="1.0"?> 
+<?xml version="1.0"?>
 <Include>
     <!--
     This file will be included as a child of the root Directory tag.
@@ -93,6 +93,7 @@
         <Registry Root="HKLM" Key="SOFTWARE\OpenAFS\Client\Submounts" Action="createKey" Id="reg_Client53" />
         <Registry Root="HKLM" Key="SOFTWARE\OpenAFS\Client" Name="AfscredsShortcutParams" Type="string" Value="[CREDSAUTOINIT] [CREDSRENEWDRMAP] [CREDSIPCHDET] [CREDSQUIET] [CREDSSHOW]" Id="reg_Client54" />
         <Registry Root="HKLM" Key="SOFTWARE\OpenAFS\Client" Name="ShowTrayIcon" Type="integer" Value="1" Id="reg_Client18" />
+        <Registry Root="HKLM" Key="SOFTWARE\OpenAFS\Client" Name="StartAfscredsOnStartup" Type="string" Value="[CREDSSTARTUP]" Id="reg_Client55" />
         <Registry Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" Action="createKeyAndRemoveKeyOnUninstall" Id="reg_Client21" />
         <Registry Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" Name="AuthentProviderPath" Type="expandable" Value="[AFSDIR]Client\Program\afslogon.dll" Id="reg_Client22" />
         <Registry Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" Id="reg_Client23" />