summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comphelper/source/misc/backupfilehelper.cxx11
-rw-r--r--configmgr/source/components.cxx43
-rw-r--r--desktop/source/app/app.cxx99
-rw-r--r--desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui37
-rw-r--r--include/comphelper/backupfilehelper.hxx14
5 files changed, 188 insertions, 16 deletions
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 778f0a0e7d27..7a353b8e90bb 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -15,6 +15,7 @@
namespace comphelper
{
sal_uInt16 BackupFileHelper::mnMaxAllowedBackups = 10;
+ bool BackupFileHelper::mbExitWasCalled = false;
BackupFileHelper::BackupFileHelper(
const OUString& rBaseURL,
@@ -28,6 +29,16 @@ namespace comphelper
{
}
+ void BackupFileHelper::setExitWasCalled()
+ {
+ mbExitWasCalled = true;
+ }
+
+ bool BackupFileHelper::getExitWasCalled()
+ {
+ return mbExitWasCalled;
+ }
+
bool BackupFileHelper::tryPush()
{
if (isDifferentOrNew())
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx
index f7c473c53899..a193da06b167 100644
--- a/configmgr/source/components.cxx
+++ b/configmgr/source/components.cxx
@@ -613,25 +613,48 @@ Components::Components(
Components::~Components()
{
- flushModifications();
+ SAL_WARN("configmgr", "################# Components::~Components() #####################");
+
+ // get flag if _exit was already called which is a sign to not to secure user config
+ const bool bExitWasCalled(comphelper::BackupFileHelper::getExitWasCalled());
+
+#ifndef WNT
+ // we can add a SAL_WARN here for other systems where the destructor gets called after
+ // an _exit() call - which should not happen. Still safe - the getExitWasCalled() is
+ // used, but a hint that _exit behaves different on a system
+ SAL_WARN_IF(bExitWasCalled, "configmgr", "Components::~Components() called after _exit() call");
+#endif
+
+ if (bExitWasCalled)
+ {
+ osl::MutexGuard g(*lock_);
+
+ if (writeThread_.is())
+ {
+ writeThread_->join();
+ }
+ }
+ else
+ {
+ flushModifications();
+ }
+
for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) {
(*i)->setAlive(false);
}
- // test backup of registrymodifications (currently off)
- static bool bFeatureSecureUserConfig(false);
+ // test backup of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
- if (bFeatureSecureUserConfig && ModificationTarget::File == modificationTarget_ && !modificationFileUrl_.isEmpty())
+ if (!bExitWasCalled &&
+ bFeatureSecureUserConfig &&
+ ModificationTarget::File == modificationTarget_ &&
+ !modificationFileUrl_.isEmpty())
{
static sal_uInt16 nNumCopies(5);
comphelper::BackupFileHelper aBackupFileHelper(modificationFileUrl_, nNumCopies);
- aBackupFileHelper.tryPush();
- static bool bTryPop(false);
- if (bTryPop)
- {
- aBackupFileHelper.tryPop();
- }
+ aBackupFileHelper.tryPush();
}
}
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index bb836d235b6d..4c52d79183cd 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -81,6 +81,7 @@
#include <comphelper/configuration.hxx>
#include <comphelper/fileurl.hxx>
#include <comphelper/processfactory.hxx>
+#include <comphelper/backupfilehelper.hxx>
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/moduleoptions.hxx>
@@ -567,6 +568,14 @@ void Desktop::Init()
{
SetBootstrapError( BE_OFFICECONFIG_BROKEN, e.Message );
}
+
+ static bool bTryHardOfficeconfigBroken(false);
+
+ if (bTryHardOfficeconfigBroken)
+ {
+ SAL_WARN("configmgr", "################# Desktop::Init() #####################");
+ SetBootstrapError(BE_OFFICECONFIG_BROKEN, OUString());
+ }
}
if ( true )
@@ -938,15 +947,93 @@ void Desktop::HandleBootstrapErrors(
}
else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
{
- OUString msg(
- GetMsgString(
+ // test restore of registrymodifications
+ static bool bFeatureSecureUserConfig(true);
+ static sal_uInt16 nNumCopies(5);
+ bool bFireOriginalError(true);
+
+ if (bFeatureSecureUserConfig)
+ {
+ // try to asccess user layer configuration file
+ OUString conf("${CONFIGURATION_LAYERS}");
+ rtl::Bootstrap::expandMacros(conf);
+ const OUString aTokenUser("user:");
+ sal_Int32 nStart(conf.indexOf(aTokenUser));
+ OUString aUser;
+
+ if (-1 != nStart)
+ {
+ nStart += aTokenUser.getLength();
+ sal_Int32 nEnd(conf.indexOf(' ', nStart));
+
+ if (-1 == nEnd)
+ {
+ nEnd = conf.getLength();
+ }
+
+ aUser = conf.copy(nStart, nEnd - nStart);
+ aUser.startsWith("!", &aUser);
+ }
+
+ if (!aUser.isEmpty())
+ {
+ comphelper::BackupFileHelper aBackupFileHelper(aUser, nNumCopies);
+
+ if (aBackupFileHelper.isPopPossible())
+ {
+ // for linux (and probably others?) we need to instantiate XDesktop2
+ // to be able to open a *.ui-file based dialog, so do this here locally.
+ // does no harm on win, so better always do this (in error case only anyways)
+ Reference< XComponentContext > xLocalContext = ::comphelper::getProcessComponentContext();
+ Reference< XDesktop2 > xDesktop = css::frame::Desktop::create(xLocalContext);
+
+ ScopedVclPtrInstance< MessageDialog > aQueryShouldRestore(
+ Application::GetDefDialogParent(),
+ "QueryTryToRestoreConfigurationDialog",
+ "desktop/ui/querytrytorestoreconfigurationdialog.ui");
+
+ if (aQueryShouldRestore.get())
+ {
+ if (!aErrorMessage.isEmpty())
+ {
+ OUString aPrimaryText(aQueryShouldRestore->get_primary_text());
+
+ aPrimaryText += "\n(\"" + aErrorMessage + "\")";
+ aQueryShouldRestore->set_primary_text(aPrimaryText);
+ }
+
+ if (RET_YES == aQueryShouldRestore->Execute())
+ {
+ aBackupFileHelper.tryPop();
+ bFireOriginalError = false;
+ }
+ }
+ }
+ }
+ }
+
+ // set flag at BackupFileHelper to be able to know if _exit was called and
+ // actions are executed after this
+ comphelper::BackupFileHelper::setExitWasCalled();
+
+ if (bFireOriginalError)
+ {
+ OUString msg(
+ GetMsgString(
STR_CONFIG_ERR_ACCESS_GENERAL,
("A general error occurred while accessing your central"
- " configuration.")));
- if (!aErrorMessage.isEmpty()) {
- msg += "\n(\"" + aErrorMessage + "\")";
+ " configuration.")));
+ if (!aErrorMessage.isEmpty()) {
+ msg += "\n(\"" + aErrorMessage + "\")";
+ }
+ FatalError(MakeStartupErrorMessage(msg));
+ }
+ else
+ {
+ // Already presented all information to the user.
+ // just do what FatalError does at it's end
+ _exit(EXITHELPER_FATAL_ERROR);
}
- FatalError(MakeStartupErrorMessage(msg));
}
else if ( aBootstrapError == BE_USERINSTALL_FAILED )
{
diff --git a/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
new file mode 100644
index 000000000000..4c332d1889d6
--- /dev/null
+++ b/desktop/uiconfig/ui/querytrytorestoreconfigurationdialog.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkMessageDialog" id="QueryTryToRestoreConfigurationDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes">LibreOffice Startup: General Configuration Error</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="buttons">yes-no</property>
+ <property name="text" translatable="yes">A general error occurred during startup while accessing the central configuration.</property>
+ <property name="secondary_text" translatable="yes">A Backup of your configuration was detected. Restoring the configuration might solve this problem, but is not guaranteed to work. A restart of the Program is needed.
+
+Do you want to restore the configuration?</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox5">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area5">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx
index 3061254615ae..f407d2b8815c 100644
--- a/include/comphelper/backupfilehelper.hxx
+++ b/include/comphelper/backupfilehelper.hxx
@@ -14,6 +14,7 @@
#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
namespace comphelper
{
@@ -51,6 +52,15 @@ namespace comphelper
osl::File maBaseFile;
bool mbBaseFileIsOpen;
+ // internal flag if _exit() was called already - a hint to evtl.
+ // not create copies of potentially not well-defined data. This
+ // may be used in destructors of static instances - which unfortunately
+ // get called on WNT but not on linux. Thus I thought about encapsulating
+ // in some '#ifdefs', but it's just more safe to always do it and
+ // allows to add a SAL_WARN when one of these destructors is called
+ // after _exit()
+ static bool mbExitWasCalled;
+
// internal upper limit (max) of allowed backups
static sal_uInt16 mnMaxAllowedBackups;
@@ -69,6 +79,10 @@ namespace comphelper
*/
BackupFileHelper(const OUString& rBaseURL, sal_uInt16 nNumBackups = 5);
+ // allow to set flag when app had to call _exit()
+ static void setExitWasCalled();
+ static bool getExitWasCalled();
+
/** tries to create a new backup, if there is none yet, or if the
* last differs from the base file. It will then put a new verion
* on the 'stack' of copies and evtl. delete the oldest backup.