summaryrefslogtreecommitdiff
path: root/RealtimeSync/notify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'RealtimeSync/notify.cpp')
-rw-r--r--RealtimeSync/notify.cpp274
1 files changed, 0 insertions, 274 deletions
diff --git a/RealtimeSync/notify.cpp b/RealtimeSync/notify.cpp
deleted file mode 100644
index 5969ee08..00000000
--- a/RealtimeSync/notify.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-//
-#include "notify.h"
-#include <set>
-#include "../shared/last_error.h"
-#include "../shared/Loki/ScopeGuard.h"
-#include <algorithm>
-#include <boost/bind.hpp>
-#include <dbt.h>
-
-using namespace zen;
-
-
-/*
-//convert bitmask into "real" drive-letter
-Zstring getDriveFromMask(ULONG unitmask)
-{
- for (int i = 0; i < 26; ++i)
- {
- if (unitmask & 0x1)
- return Zstring() + static_cast<DefaultChar>(DefaultChar('A') + i) + DefaultStr(":\\");
- unitmask >>= 1;
- }
- return Zstring();
-}
-*/
-
-namespace
-{
-bool messageProviderConstructed = false;
-}
-
-
-class MessageProvider //administrates a single dummy window to receive messages
-{
-public:
- static MessageProvider& instance() //throw (FileError)
- {
- static MessageProvider inst;
- messageProviderConstructed = true;
- return inst;
- }
-
- class Listener
- {
- public:
- virtual ~Listener() {}
- virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) = 0; //throw()!
- };
- void registerListener(Listener& l);
- void unregisterListener(Listener& l); //don't unregister objects with static lifetime
-
- HWND getWnd() const; //get handle in order to register additional notifications
-
-private:
- MessageProvider();
- ~MessageProvider();
- MessageProvider(const MessageProvider&);
- MessageProvider& operator=(const MessageProvider&);
-
- static const wchar_t WINDOW_NAME[];
-
- friend LRESULT CALLBACK topWndProc(HWND, UINT, WPARAM, LPARAM);
- void processMessage(UINT message, WPARAM wParam, LPARAM lParam);
-
- const HINSTANCE process;
- HWND windowHandle;
-
- std::set<Listener*> listener;
-};
-
-
-const wchar_t MessageProvider::WINDOW_NAME[] = L"E6AD5EB1-527B-4EEF-AC75-27883B233380"; //random name
-
-
-LRESULT CALLBACK topWndProc(
- HWND hwnd, //handle to window
- UINT uMsg, //message identifier
- WPARAM wParam, //first message parameter
- LPARAM lParam) //second message parameter
-{
- if (messageProviderConstructed) //attention: this callback is triggered in the middle of singleton construction! It is a bad idea to to call back at this time!
- try
- {
- MessageProvider::instance().processMessage(uMsg, wParam, lParam); //not supposed to throw
- }
- catch (...) {}
-
- return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-
-MessageProvider::MessageProvider() :
- process(::GetModuleHandle(NULL)), //get program's module handle
- windowHandle(NULL)
-{
- if (process == NULL)
- throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") +
- zen::getLastErrorFormatted() + wxT(" (GetModuleHandle)"));
-
- //register the main window class
- WNDCLASS wc = {};
- wc.lpfnWndProc = topWndProc;
- wc.hInstance = process;
- wc.lpszClassName = WINDOW_NAME;
-
- if (::RegisterClass(&wc) == 0)
- throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") +
- zen::getLastErrorFormatted() + wxT(" (RegisterClass)"));
-
- Loki::ScopeGuard guardClass = Loki::MakeGuard(::UnregisterClass, WINDOW_NAME, process);
-
- //create dummy-window
- windowHandle = ::CreateWindow(
- WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word!
- NULL, //LPCTSTR lpWindowName,
- 0, //DWORD dwStyle,
- 0, //int x,
- 0, //int y,
- 0, //int nWidth,
- 0, //int nHeight,
- 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)!
- NULL, //HMENU hMenu,
- process, //HINSTANCE hInstance,
- NULL); //LPVOID lpParam
- if (windowHandle == NULL)
- throw zen::FileError(wxString(wxT("Could not start monitoring window notifications:")) + wxT("\n\n") +
- zen::getLastErrorFormatted() + wxT(" (CreateWindow)"));
-
- guardClass.Dismiss();
-}
-
-
-MessageProvider::~MessageProvider()
-{
- //clean-up in reverse order
- ::DestroyWindow(windowHandle);
- ::UnregisterClass(WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word!
- process); //HINSTANCE hInstance
-}
-
-
-inline
-void MessageProvider::registerListener(Listener& l)
-{
- listener.insert(&l);
-}
-
-
-inline
-void MessageProvider::unregisterListener(Listener& l) //don't unregister objects with static lifetime
-{
- listener.erase(&l);
-}
-
-
-inline
-HWND MessageProvider::getWnd() const //get handle in order to register additional notifications
-{
- return windowHandle;
-}
-
-
-void MessageProvider::processMessage(UINT message, WPARAM wParam, LPARAM lParam)
-{
- std::for_each(listener.begin(), listener.end(), boost::bind(&Listener::onMessage, _1, message, wParam, lParam));
-}
-//####################################################################################################
-
-
-class NotifyRequestDeviceRemoval::Pimpl : private MessageProvider::Listener
-{
-public:
- Pimpl(NotifyRequestDeviceRemoval& parent, const std::vector<HANDLE>& openHandles) : //throw (FileError)
- parent_(parent)
- {
- MessageProvider::instance().registerListener(*this); //throw (FileError)
-
- //register handles to receive notifications
- DEV_BROADCAST_HANDLE filter = {};
- filter.dbch_size = sizeof(filter);
- filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
-
- try
- {
- for (std::vector<HANDLE>::const_iterator i = openHandles.begin(); i != openHandles.end(); ++i)
- {
- filter.dbch_handle = *i;
-
- HDEVNOTIFY hNotfication = ::RegisterDeviceNotification(
- MessageProvider::instance().getWnd(), //__in HANDLE hRecipient,
- &filter, //__in LPVOID NotificationFilter,
- DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags
- if (hNotfication == NULL)
- {
- const DWORD lastError = ::GetLastError();
- if (lastError != ERROR_CALL_NOT_IMPLEMENTED && //fail on SAMBA share: this shouldn't be a showstopper!
- lastError != ERROR_SERVICE_SPECIFIC_ERROR && //neither should be fail for "Pogoplug" mapped network drives
- lastError != ERROR_INVALID_DATA) //this seems to happen for a NetDrive-mapped FTP server
- throw zen::FileError(wxString(wxT("Could not register device removal notifications:")) + wxT("\n\n") + zen::getLastErrorFormatted(lastError));
- }
- else
- notifications.insert(hNotfication);
- }
- }
- catch (...)
- {
- std::for_each(notifications.begin(), notifications.end(), ::UnregisterDeviceNotification);
- MessageProvider::instance().unregisterListener(*this); //throw() in this case
- throw;
- }
- }
-
- ~Pimpl()
- {
- std::for_each(notifications.begin(), notifications.end(), ::UnregisterDeviceNotification);
- MessageProvider::instance().unregisterListener(*this);
- }
-
-private:
- virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) //throw()!
- {
- //DBT_DEVICEQUERYREMOVE example: http://msdn.microsoft.com/en-us/library/aa363427(v=VS.85).aspx
- if (message == WM_DEVICECHANGE)
- {
- if ( wParam == DBT_DEVICEQUERYREMOVE ||
- wParam == DBT_DEVICEQUERYREMOVEFAILED ||
- wParam == DBT_DEVICEREMOVECOMPLETE)
- {
- PDEV_BROADCAST_HDR header = reinterpret_cast<PDEV_BROADCAST_HDR>(lParam);
- if (header->dbch_devicetype == DBT_DEVTYP_HANDLE)
- {
- PDEV_BROADCAST_HANDLE body = reinterpret_cast<PDEV_BROADCAST_HANDLE>(lParam);
-
-#ifdef __MINGW32__
- const HDEVNOTIFY requestNotification = reinterpret_cast<HDEVNOTIFY>(body->dbch_hdevnotify);
-#else
- const HDEVNOTIFY requestNotification = body->dbch_hdevnotify;
-#endif
- if (notifications.find(requestNotification) != notifications.end()) //is it for one of our notifications we registered?
- switch (wParam)
- {
- case DBT_DEVICEQUERYREMOVE:
- parent_.onRequestRemoval(body->dbch_handle);
- break;
- case DBT_DEVICEQUERYREMOVEFAILED:
- parent_.onRemovalFinished(body->dbch_handle, false);
- break;
- case DBT_DEVICEREMOVECOMPLETE:
- parent_.onRemovalFinished(body->dbch_handle, true);
- break;
- }
- }
- }
- }
- }
-
- NotifyRequestDeviceRemoval& parent_;
- std::set<HDEVNOTIFY> notifications;
-};
-//####################################################################################################
-
-
-NotifyRequestDeviceRemoval::NotifyRequestDeviceRemoval(const std::vector<HANDLE>& openHandles)
-{
- pimpl.reset(new Pimpl(*this, openHandles));
-}
-
-
-NotifyRequestDeviceRemoval::~NotifyRequestDeviceRemoval() {} //make sure ~auto_ptr() works with complete type
bgstack15