diff --git a/src/init.cpp b/src/init.cpp index d253c3b7a..38e2b6f9e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -656,11 +656,6 @@ bool AppInit2(int argc, char* argv[]) if (fServer) CreateThread(ThreadRPCServer, NULL); -#ifdef QT_GUI - if (GetStartOnSystemStartup()) - SetStartOnSystemStartup(true); // Remove startup links -#endif - #if !defined(QT_GUI) while (1) Sleep(5000); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 91f6a56c8..cf115c48f 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -232,6 +232,10 @@ int main(int argc, char *argv[]) try { + // Regenerate startup link, to fix links to old versions + if (GUIUtil::GetStartOnSystemStartup()) + GUIUtil::SetStartOnSystemStartup(true); + BitcoinGUI window; guiref = &window; if(AppInit2(argc, argv)) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 67cbc51bd..23e657677 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -19,6 +19,7 @@ #include #include +#include #ifdef WIN32 #ifdef _WIN32_WINNT @@ -268,5 +269,149 @@ bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt) return QObject::eventFilter(obj, evt); } +#ifdef WIN32 +boost::filesystem::path static StartupShortcutPath() +{ + return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk"; +} + +bool GetStartOnSystemStartup() +{ + // check for Bitcoin.lnk + return boost::filesystem::exists(StartupShortcutPath()); +} + +bool SetStartOnSystemStartup(bool fAutoStart) +{ + // If the shortcut exists already, remove it for updating + boost::filesystem::remove(StartupShortcutPath()); + + if (fAutoStart) + { + CoInitialize(NULL); + + // Get a pointer to the IShellLink interface. + IShellLink* psl = NULL; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, + CLSCTX_INPROC_SERVER, IID_IShellLink, + reinterpret_cast(&psl)); + + if (SUCCEEDED(hres)) + { + // Get the current executable path + TCHAR pszExePath[MAX_PATH]; + GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); + + TCHAR pszArgs[5] = TEXT("-min"); + + // Set the path to the shortcut target + psl->SetPath(pszExePath); + PathRemoveFileSpec(pszExePath); + psl->SetWorkingDirectory(pszExePath); + psl->SetShowCmd(SW_SHOWMINNOACTIVE); + psl->SetArguments(pszArgs); + + // Query IShellLink for the IPersistFile interface for + // saving the shortcut in persistent storage. + IPersistFile* ppf = NULL; + hres = psl->QueryInterface(IID_IPersistFile, + reinterpret_cast(&ppf)); + if (SUCCEEDED(hres)) + { + WCHAR pwsz[MAX_PATH]; + // Ensure that the string is ANSI. + MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH); + // Save the link by calling IPersistFile::Save. + hres = ppf->Save(pwsz, TRUE); + ppf->Release(); + psl->Release(); + CoUninitialize(); + return true; + } + psl->Release(); + } + CoUninitialize(); + return false; + } + return true; +} + +#elif defined(LINUX) + +// Follow the Desktop Application Autostart Spec: +// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html + +boost::filesystem::path static GetAutostartDir() +{ + namespace fs = boost::filesystem; + + char* pszConfigHome = getenv("XDG_CONFIG_HOME"); + if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; + char* pszHome = getenv("HOME"); + if (pszHome) return fs::path(pszHome) / ".config" / "autostart"; + return fs::path(); +} + +boost::filesystem::path static GetAutostartFilePath() +{ + return GetAutostartDir() / "bitcoin.desktop"; +} + +bool GetStartOnSystemStartup() +{ + boost::filesystem::ifstream optionFile(GetAutostartFilePath()); + if (!optionFile.good()) + return false; + // Scan through file for "Hidden=true": + std::string line; + while (!optionFile.eof()) + { + getline(optionFile, line); + if (line.find("Hidden") != std::string::npos && + line.find("true") != std::string::npos) + return false; + } + optionFile.close(); + + return true; +} + +bool SetStartOnSystemStartup(bool fAutoStart) +{ + if (!fAutoStart) + boost::filesystem::remove(GetAutostartFilePath()); + else + { + char pszExePath[MAX_PATH+1]; + memset(pszExePath, 0, sizeof(pszExePath)); + if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1) + return false; + + boost::filesystem::create_directories(GetAutostartDir()); + + boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); + if (!optionFile.good()) + return false; + // Write a bitcoin.desktop file to the autostart directory: + optionFile << "[Desktop Entry]\n"; + optionFile << "Type=Application\n"; + optionFile << "Name=Bitcoin\n"; + optionFile << "Exec=" << pszExePath << " -min\n"; + optionFile << "Terminal=false\n"; + optionFile << "Hidden=false\n"; + optionFile.close(); + } + return true; +} +#else + +// TODO: OSX startup stuff; see: +// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html + +bool GetStartOnSystemStartup() { return false; } +bool SetStartOnSystemStartup(bool fAutoStart) { return false; } + +#endif + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 8d1a01e07..f30d5db35 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -90,6 +90,9 @@ namespace GUIUtil int size_threshold; }; + bool GetStartOnSystemStartup(); + bool SetStartOnSystemStartup(bool fAutoStart); + } // namespace GUIUtil #endif // GUIUTIL_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 78448d3ee..181dec440 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -4,6 +4,7 @@ #include "init.h" #include "walletdb.h" +#include "guiutil.h" OptionsModel::OptionsModel(QObject *parent) : QAbstractListModel(parent) @@ -107,7 +108,7 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const switch(index.row()) { case StartAtStartup: - return QVariant(GetStartOnSystemStartup()); + return QVariant(GUIUtil::GetStartOnSystemStartup()); case MinimizeToTray: return QVariant(fMinimizeToTray); case MapPortUPnP: @@ -146,7 +147,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in switch(index.row()) { case StartAtStartup: - successful = SetStartOnSystemStartup(value.toBool()); + successful = GUIUtil::SetStartOnSystemStartup(value.toBool()); break; case MinimizeToTray: fMinimizeToTray = value.toBool(); diff --git a/src/util.cpp b/src/util.cpp index d2db7cec8..170ea0513 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -48,7 +48,6 @@ namespace boost { #define NOMINMAX #endif #include "shlobj.h" -#include "shlwapi.h" #endif using namespace std; @@ -1078,146 +1077,4 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); return fs::path(""); } - -boost::filesystem::path static StartupShortcutPath() -{ - return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk"; -} - -bool GetStartOnSystemStartup() -{ - // check for Bitcoin.lnk - return boost::filesystem::exists(StartupShortcutPath()); -} - -bool SetStartOnSystemStartup(bool fAutoStart) -{ - // If the shortcut exists already, remove it for updating - boost::filesystem::remove(StartupShortcutPath()); - - if (fAutoStart) - { - CoInitialize(NULL); - - // Get a pointer to the IShellLink interface. - IShellLink* psl = NULL; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, - CLSCTX_INPROC_SERVER, IID_IShellLink, - reinterpret_cast(&psl)); - - if (SUCCEEDED(hres)) - { - // Get the current executable path - TCHAR pszExePath[MAX_PATH]; - GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); - - TCHAR pszArgs[5] = TEXT("-min"); - - // Set the path to the shortcut target - psl->SetPath(pszExePath); - PathRemoveFileSpec(pszExePath); - psl->SetWorkingDirectory(pszExePath); - psl->SetShowCmd(SW_SHOWMINNOACTIVE); - psl->SetArguments(pszArgs); - - // Query IShellLink for the IPersistFile interface for - // saving the shortcut in persistent storage. - IPersistFile* ppf = NULL; - hres = psl->QueryInterface(IID_IPersistFile, - reinterpret_cast(&ppf)); - if (SUCCEEDED(hres)) - { - WCHAR pwsz[MAX_PATH]; - // Ensure that the string is ANSI. - MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH); - // Save the link by calling IPersistFile::Save. - hres = ppf->Save(pwsz, TRUE); - ppf->Release(); - psl->Release(); - CoUninitialize(); - return true; - } - psl->Release(); - } - CoUninitialize(); - return false; - } - return true; -} - -#elif defined(LINUX) - -// Follow the Desktop Application Autostart Spec: -// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html - -boost::filesystem::path static GetAutostartDir() -{ - namespace fs = boost::filesystem; - - char* pszConfigHome = getenv("XDG_CONFIG_HOME"); - if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; - char* pszHome = getenv("HOME"); - if (pszHome) return fs::path(pszHome) / ".config" / "autostart"; - return fs::path(); -} - -boost::filesystem::path static GetAutostartFilePath() -{ - return GetAutostartDir() / "bitcoin.desktop"; -} - -bool GetStartOnSystemStartup() -{ - boost::filesystem::ifstream optionFile(GetAutostartFilePath()); - if (!optionFile.good()) - return false; - // Scan through file for "Hidden=true": - string line; - while (!optionFile.eof()) - { - getline(optionFile, line); - if (line.find("Hidden") != string::npos && - line.find("true") != string::npos) - return false; - } - optionFile.close(); - - return true; -} - -bool SetStartOnSystemStartup(bool fAutoStart) -{ - if (!fAutoStart) - boost::filesystem::remove(GetAutostartFilePath()); - else - { - char pszExePath[MAX_PATH+1]; - memset(pszExePath, 0, sizeof(pszExePath)); - if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1) - return false; - - boost::filesystem::create_directories(GetAutostartDir()); - - boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc); - if (!optionFile.good()) - return false; - // Write a bitcoin.desktop file to the autostart directory: - optionFile << "[Desktop Entry]\n"; - optionFile << "Type=Application\n"; - optionFile << "Name=Bitcoin\n"; - optionFile << "Exec=" << pszExePath << " -min\n"; - optionFile << "Terminal=false\n"; - optionFile << "Hidden=false\n"; - optionFile.close(); - } - return true; -} -#else - -// TODO: OSX startup stuff; see: -// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html - -bool GetStartOnSystemStartup() { return false; } -bool SetStartOnSystemStartup(bool fAutoStart) { return false; } - #endif diff --git a/src/util.h b/src/util.h index 1363fbbbf..8e65fa786 100644 --- a/src/util.h +++ b/src/util.h @@ -162,8 +162,6 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map #ifdef WIN32 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif -bool GetStartOnSystemStartup(); -bool SetStartOnSystemStartup(bool fAutoStart); void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); @@ -182,8 +180,6 @@ void AddTimeData(const CNetAddr& ip, int64 nTime); - - inline std::string i64tostr(int64 n) { return strprintf("%"PRI64d, n);