FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
WinMessageWindow.cpp
1 /**********************************************************\
2 Original Author: Richard Bateman (taxilian)
3 
4 Created: Jan 5, 2011
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2010 Richard Bateman, Firebreath development team
13 \**********************************************************/
14 
15 #include "win_targetver.h"
16 #include "win_common.h"
17 #include <boost/lexical_cast.hpp>
18 #include <boost/bind.hpp>
19 #include <boost/thread/recursive_mutex.hpp>
20 #include "AsyncFunctionCall.h"
21 #include "logging.h"
22 #include "../precompiled_headers.h" // On windows, everything above this line in PCH
23 
24 #include <ShlGuid.h>
25 #include <string>
26 
27 #include "WinMessageWindow.h"
28 
29 // thanks http://blogs.msdn.com/b/oldnewthing/archive/2004/10/25/247180.aspx
30 EXTERN_C IMAGE_DOS_HEADER __ImageBase;
31 #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
32 
33 class WindowsClassRegistration
34 {
35  ATOM m_atom;
36  DWORD m_err;
37  const wchar_t* m_className;
38 
39 public:
40  WindowsClassRegistration(const wchar_t* classname)
41  : m_err(0)
42  , m_className(classname)
43  {
44  WNDCLASSEX wc;
45  wc.cbSize = sizeof(WNDCLASSEX);
46  wc.style = 0;
47  wc.lpfnWndProc = &FB::WinMessageWindow::_WinProc;
48  wc.cbClsExtra = 0;
49  wc.cbWndExtra = 0;
50  wc.hInstance = HINST_THISCOMPONENT;
51  wc.lpszMenuName = NULL;
52  wc.lpszClassName = m_className;
53  wc.hIcon = NULL;
54  wc.hCursor = NULL;
55  wc.hIconSm = NULL;
56  wc.hbrBackground = NULL;
57  m_atom = ::RegisterClassEx(&wc);
58 
59  if (!m_atom) {
60  m_err = ::GetLastError();
61  }
62  }
63 
64  ~WindowsClassRegistration()
65  {
66  if (0 == m_err) {
67  UnregisterClass(MAKEINTATOM(m_atom), HINST_THISCOMPONENT);
68  }
69  }
70 
71  ATOM atom() const
72  {
73  if (m_err) {
74  std::stringstream ss;
75  ss << "Could not register window class, error:" << m_err;
76  throw std::runtime_error(ss.str());
77  }
78  return m_atom;
79  }
80 };
81 
82 static boost::recursive_mutex _windowMapMutex;
83 static std::map<HWND, FB::WinMessageWindow*> _windowMap;
84 static WindowsClassRegistration _winclass(L"FBEventWindow");
85 
86 FB::WinMessageWindow::WinMessageWindow() {
87  DWORD err(0);
88 
89  static int count(0);
90  std::wstring winName = L"FireBreathEventWindow" + boost::lexical_cast<std::wstring>(count);
91  ++count;
92 
93  HWND messageWin = CreateWindowEx(
94  WS_OVERLAPPED,
95  MAKEINTATOM(_winclass.atom()),
96  winName.c_str(),
97  0,
98  0, 0, 0, 0,
99  HWND_MESSAGE, NULL, HINST_THISCOMPONENT, NULL);
100  if (!messageWin) {
101  err = ::GetLastError();
102  throw std::runtime_error("Could not create Message Window");
103  }
104  _windowMap[messageWin] = this;
105  m_hWnd = messageWin;
106  boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
107  winProc = boost::bind(&FB::WinMessageWindow::DefaultWinProc, this, _1, _2, _3, _4, _5);
108 }
109 
110 LRESULT CALLBACK FB::WinMessageWindow::_WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
111 {
112  LRESULT lres = S_OK;
113  FB::WinMessageWindow* self(NULL);
114  {
115  boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
116  if (_windowMap.find(hWnd) != _windowMap.end())
117  self = _windowMap[hWnd];
118  }
119  if (!self || !self->winProc(hWnd, uMsg, wParam, lParam, lres)) {
120  return DefWindowProc(hWnd, uMsg, wParam, lParam);
121  } else {
122  return lres;
123  }
124 }
125 
126 HWND FB::WinMessageWindow::getHWND()
127 {
128  return m_hWnd;
129 }
130 
131 FB::WinMessageWindow::~WinMessageWindow()
132 {
133  boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
134  _windowMap.erase(m_hWnd);
135  ::DestroyWindow(m_hWnd);
136 }
137 
138 bool FB::WinMessageWindow::DefaultWinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult )
139 {
140  if (uMsg == WM_ASYNCTHREADINVOKE) {
141  FBLOG_TRACE("PluginWindow", "Running async function call");
142  FB::AsyncFunctionCall *evt = static_cast<FB::AsyncFunctionCall*>((void*)lParam);
143  evt->func(evt->userData);
144  delete evt;
145  lResult = S_OK;
146  return true;
147  }
148  return false;
149 }
Creates a message window. Don't touch this if you don't understand what you are doing.