Daemon.cpp
Upload User: sbftbdw
Upload Date: 2007-01-03
Package Size: 379k
Code Size: 7k
Category:

Remote Control

Development Platform:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // Daemon.cpp: implementation of the Daemon class.
  24. #include "stdhdrs.h"
  25. #include "vncviewer.h"
  26. #include "Daemon.h"
  27. #include "Exception.h"
  28. #include "ClientConnection.h"
  29. #include "AboutBox.h"
  30. //////////////////////////////////////////////////////////////////////
  31. // Construction/Destruction
  32. //////////////////////////////////////////////////////////////////////
  33. #define DAEMON_CLASS_NAME "VNCviewer Daemon"
  34. Daemon::Daemon(int port)
  35. {
  36. // Create a dummy window
  37. WNDCLASSEX wndclass;
  38. wndclass.cbSize = sizeof(wndclass);
  39. wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  40. wndclass.lpfnWndProc = Daemon::WndProc;
  41. wndclass.cbClsExtra = 0;
  42. wndclass.cbWndExtra = 0;
  43. wndclass.hInstance = pApp->m_instance;
  44. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  45. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  46. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  47. wndclass.lpszMenuName = (const char *) NULL;
  48. wndclass.lpszClassName = DAEMON_CLASS_NAME;
  49. wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  50. RegisterClassEx(&wndclass);
  51. m_hwnd = CreateWindow(DAEMON_CLASS_NAME,
  52. DAEMON_CLASS_NAME,
  53. WS_OVERLAPPEDWINDOW,
  54. CW_USEDEFAULT,
  55. CW_USEDEFAULT,
  56. 200, 200,
  57. NULL,
  58. NULL,
  59. pApp->m_instance,
  60. NULL);
  61. // record which client created this window
  62. SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);
  63. // Load a popup menu
  64. m_hmenu = LoadMenu(pApp->m_instance, MAKEINTRESOURCE(IDR_TRAYMENU));
  65. // Create a listening socket
  66.     struct sockaddr_in addr;
  67.     addr.sin_family = AF_INET;
  68.     addr.sin_port = htons(port);
  69.     addr.sin_addr.s_addr = INADDR_ANY;
  70.     m_sock = socket(AF_INET, SOCK_STREAM, 0);
  71. if (!m_sock) throw WarningException("Error creating Daemon socket");
  72.     
  73. try {
  74. int one = 1, res = 0;
  75. //res = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof(one));
  76. //if (res == SOCKET_ERROR) 
  77. //  throw WarningException("Error setting Daemon socket options");
  78. res = bind(m_sock, (struct sockaddr *)&addr, sizeof(addr));
  79. if (res == SOCKET_ERROR)
  80. throw WarningException("Error binding Daemon socket");
  81. res = listen(m_sock, 5);
  82. if (res == SOCKET_ERROR)
  83. throw WarningException("Error when Daemon listens");
  84. } catch (...) {
  85. closesocket(m_sock);
  86. m_sock = 0;
  87. throw;
  88. }
  89. // Send a message to specified window on an incoming connection
  90. WSAAsyncSelect (m_sock,  m_hwnd,  WM_SOCKEVENT, FD_ACCEPT);
  91. // Create the tray icon
  92. AddTrayIcon();
  93. // A timer checks that the tray icon is intact
  94. m_timer = SetTimer( m_hwnd, IDT_TRAYTIMER,  15000, NULL);
  95. }
  96. void Daemon::AddTrayIcon() {
  97. log.Print(4, _T("Adding tray iconn"));
  98. SendTrayMsg(NIM_ADD);
  99. }
  100. void Daemon::CheckTrayIcon() {
  101. log.Print(8, _T("Checking tray iconn"));
  102. if (!SendTrayMsg(NIM_MODIFY)) {
  103. log.Print(4, _T("Tray icon not there - reinstallingn"));
  104. AddTrayIcon();
  105. };
  106. }
  107. void Daemon::RemoveTrayIcon() {
  108. log.Print(4, _T("Deleting tray iconn"));
  109. SendTrayMsg(NIM_DELETE);
  110. }
  111. bool Daemon::SendTrayMsg(DWORD msg)
  112. {
  113. m_nid.hWnd = m_hwnd;
  114. m_nid.cbSize = sizeof(m_nid);
  115. m_nid.uID = IDR_TRAY; // never changes after construction
  116. m_nid.hIcon = LoadIcon(pApp->m_instance, MAKEINTRESOURCE(IDR_TRAY));
  117. m_nid.uFlags = NIF_ICON | NIF_MESSAGE;
  118. m_nid.uCallbackMessage = WM_TRAYNOTIFY;
  119. m_nid.szTip[0] = '';
  120. // Use resource string as tip if there is one
  121. if (LoadString(pApp->m_instance, IDR_TRAY, m_nid.szTip, sizeof(m_nid.szTip))) {
  122. m_nid.uFlags |= NIF_TIP;
  123. }
  124. return (bool) (Shell_NotifyIcon(msg, &m_nid) != 0);
  125. }
  126. // Process window messages
  127. LRESULT CALLBACK Daemon::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
  128. // This is a static method, so we don't know which instantiation we're 
  129. // dealing with. We have stored a pseudo-this in the window user data, 
  130. // though.
  131. Daemon *_this = (Daemon *) GetWindowLong(hwnd, GWL_USERDATA);
  132. switch (iMsg) {
  133. case WM_CREATE:
  134. {
  135. return 0;
  136. }
  137. case WM_SOCKEVENT:
  138. {
  139. assert(HIWORD(lParam) == 0);
  140. // A new socket created by accept might send messages to
  141. // this procedure. We can ignore them.
  142. if(wParam != _this->m_sock) {
  143. return 0;
  144. }
  145. switch(lParam) {
  146. case FD_ACCEPT:
  147. {
  148. SOCKET hNewSock;
  149. hNewSock = accept(_this->m_sock, NULL, NULL);
  150. WSAAsyncSelect(hNewSock, hwnd, 0, 0);
  151. unsigned long nbarg = 0;
  152. ioctlsocket(hNewSock, FIONBIO, &nbarg);
  153. pApp->NewConnection(hNewSock);
  154. break;
  155. }
  156. case FD_READ:
  157. {
  158. unsigned long numbytes;
  159. ioctlsocket(_this->m_sock, FIONREAD, &numbytes);
  160. recv(_this->m_sock, _this->netbuf, numbytes, 0);
  161. break;
  162. }
  163. case FD_CLOSE:
  164. log.Print(5, _T("Daemon connection closedn"));
  165. DestroyWindow(hwnd);
  166. break;
  167. }
  168. return 0;
  169. }
  170. case WM_COMMAND:
  171. switch (LOWORD(wParam)) {
  172. case ID_NEWCONN:
  173. pApp->NewConnection();
  174. break;
  175. case IDC_OPTIONBUTTON:
  176. pApp->m_options.DoDialog();
  177. break;
  178. case ID_CLOSEDAEMON:
  179. PostQuitMessage(0);
  180. break;
  181. case IDD_APP_ABOUT:
  182. ShowAboutBox();
  183. break;
  184. }
  185. return 0;
  186. case WM_TRAYNOTIFY:
  187. {
  188. HMENU hSubMenu = GetSubMenu(_this->m_hmenu, 0);
  189. if (lParam==WM_LBUTTONDBLCLK) {
  190. // double click: execute first menu item
  191. ::SendMessage(_this->m_nid.hWnd, WM_COMMAND, 
  192. GetMenuItemID(hSubMenu, 0), 0);
  193. } else if (lParam==WM_RBUTTONUP || lParam==WM_LBUTTONUP) {
  194. if (hSubMenu == NULL) { 
  195. log.Print(2, _T("No systray submenun"));
  196. return 0;
  197. }
  198. // Make first menu item the default (bold font)
  199. ::SetMenuDefaultItem(hSubMenu, 0, TRUE);
  200. // Display the menu at the current mouse location. There's a "bug"
  201. // (Microsoft calls it a feature) in Windows 95 that requires calling
  202. // SetForegroundWindow. To find out more, search for Q135788 in MSDN.
  203. //
  204. POINT mouse;
  205. GetCursorPos(&mouse);
  206. ::SetForegroundWindow(_this->m_nid.hWnd);
  207. ::TrackPopupMenu(hSubMenu, 0, mouse.x, mouse.y, 0,
  208. _this->m_nid.hWnd, NULL);
  209. return 0;
  210. }
  211. case WM_TIMER:
  212. _this->CheckTrayIcon();
  213. return 0;
  214. case WM_DESTROY:
  215. PostQuitMessage(0);
  216. return 0;
  217. }
  218. return DefWindowProc(hwnd, iMsg, wParam, lParam);
  219. }
  220. Daemon::~Daemon()
  221. {
  222. KillTimer(m_hwnd, m_timer);
  223. RemoveTrayIcon();
  224. DestroyMenu(m_hmenu);
  225. shutdown(m_sock, SD_BOTH);
  226. closesocket(m_sock);
  227. }