Permalink
Browse files

Safely shutdown HBN during windows shutdown.

  • Loading branch information...
Tranz5 committed Sep 27, 2014
1 parent c8ba5b7 commit 88f579b9b9fe4be97f476875d036596558cc9055
Showing with 122 additions and 3 deletions.
  1. +4 −2 HoboNickels-qt.pro
  2. +11 −1 src/qt/bitcoin.cpp
  3. +5 −0 src/qt/bitcoingui.cpp
  4. +3 −0 src/qt/bitcoingui.h
  5. +70 −0 src/qt/winshutdownmonitor.cpp
  6. +29 −0 src/qt/winshutdownmonitor.h
View
@@ -237,7 +237,8 @@ HEADERS += src/qt/bitcoingui.h \
src/clientversion.h \
src/timer.h \
src/qt/blockbrowser.h \
src/qt/macnotificationhandler.h
src/qt/macnotificationhandler.h \
src/qt/winshutdownmonitor.h
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \
@@ -312,7 +313,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/scrypt_mine.cpp \
src/pbkdf2.cpp \
src/timer.cpp \
src/qt/blockbrowser.cpp
src/qt/blockbrowser.cpp \
src/qt/winshutdownmonitor.cpp
RESOURCES += \
src/qt/bitcoin.qrc
View
@@ -7,6 +7,7 @@
#include "optionsmodel.h"
#include "guiutil.h"
#include "guiconstants.h"
#include "winshutdownmonitor.h"
#include "init.h"
#include "ui_interface.h"
@@ -155,7 +156,7 @@ int main(int argc, char *argv[])
// Application identification (must be set before OptionsModel is initialized,
// as it is used to locate QSettings)
app.setOrganizationName("HoboNickels");
app.setOrganizationDomain("HoboNickels.su");
app.setOrganizationDomain("HoboNickels.info");
if(GetBoolArg("-testnet")) // Separate UI settings for testnet
app.setApplicationName("HoboNickels-Qt-testnet");
else
@@ -252,6 +253,11 @@ int main(int argc, char *argv[])
}
window.setCurrentWallet("~Default");
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
app.installNativeEventFilter(new WinShutdownMonitor());
#endif
// If -min option passed, start window minimized.
if(GetBoolArg("-min"))
{
@@ -265,6 +271,10 @@ int main(int argc, char *argv[])
// Place this here as guiref has to be defined if we don't want to lose URIs
ipcInit(argc, argv);
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("HoboNickels shutting down. Please wait..."), (HWND)window.getMainWinId());
#endif
app.exec();
window.hide();
View
@@ -1293,3 +1293,8 @@ void BitcoinGUI::updateStakingIcon()
}
}
}
WId BitcoinGUI::getMainWinId() const
{
return winId();
}
View
@@ -62,6 +62,9 @@ class BitcoinGUI : public QMainWindow
QAction *exportAction;
/// Get window identifier of QMainWindow (BitcoinGUI)
WId getMainWinId() const;
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
@@ -0,0 +1,70 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "winshutdownmonitor.h"
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
#include "init.h"
#include "util.h"
#include <windows.h>
#include <QDebug>
#include <openssl/rand.h>
// If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
Q_UNUSED(eventType);
MSG *pMsg = static_cast<MSG *>(pMessage);
// Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
// Warn only once as this is performance-critical
static bool warned = false;
if (!warned) {
printf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
warned = true;
}
}
switch(pMsg->message)
{
case WM_QUERYENDSESSION:
{
// Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block
// Windows session end until we have finished client shutdown.
StartShutdown();
*pnResult = FALSE;
return true;
}
case WM_ENDSESSION:
{
*pnResult = FALSE;
return true;
}
}
return false;
}
void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
if (shutdownBRCreate == NULL) {
qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
return;
}
if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str()))
qWarning() << "registerShutdownBlockReason: Successfully registered: " + strReason;
else
qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason;
}
#endif
@@ -0,0 +1,29 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef WINSHUTDOWNMONITOR_H
#define WINSHUTDOWNMONITOR_H
#ifdef WIN32
#include <QByteArray>
#include <QString>
#if QT_VERSION >= 0x050000
#include <windef.h> // for HWND
#include <QAbstractNativeEventFilter>
class WinShutdownMonitor : public QAbstractNativeEventFilter
{
public:
/** Implements QAbstractNativeEventFilter interface for processing Windows messages */
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult);
/** Register the reason for blocking shutdown on Windows to allow clean client exit */
static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId);
};
#endif
#endif
#endif // WINSHUTDOWNMONITOR_H

0 comments on commit 88f579b

Please sign in to comment.