選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

vncviewer.cxx 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. // -=- VNC Viewer for Win32
  19. #include <string.h>
  20. #ifdef WIN32
  21. #define strcasecmp _stricmp
  22. #endif
  23. #include <list>
  24. #include <vncviewer/resource.h>
  25. #include <vncviewer/CViewManager.h>
  26. #include <vncviewer/CView.h>
  27. #include <vncviewer/OptionsDialog.h>
  28. #include <rfb/Logger_stdio.h>
  29. #include <rfb/Logger_file.h>
  30. #include <rfb/LogWriter.h>
  31. #include <rfb/Exception.h>
  32. #include <rfb_win32/RegConfig.h>
  33. #include <rfb_win32/TrayIcon.h>
  34. #include <rfb_win32/Win32Util.h>
  35. #include <rfb_win32/AboutDialog.h>
  36. #include <network/TcpSocket.h>
  37. #ifdef _DIALOG_CAPTURE
  38. #include <extra/LoadBMP.h>
  39. #endif
  40. using namespace rfb;
  41. using namespace rfb::win32;
  42. using namespace rdr;
  43. using namespace network;
  44. static LogWriter vlog("main");
  45. TStr rfb::win32::AppName("VNC Viewer");
  46. #ifdef _DIALOG_CAPTURE
  47. BoolParameter captureDialogs("CaptureDialogs", "", false);
  48. #endif
  49. //
  50. // -=- Listener
  51. // Class to handle listening on a particular port for incoming connections
  52. // from servers, and spawning of clients
  53. //
  54. static BoolParameter acceptIncoming("Listen", "Accept incoming connections from VNC servers.", false);
  55. //
  56. // -=- AboutDialog global values
  57. //
  58. const WORD rfb::win32::AboutDialog::DialogId = IDD_ABOUT;
  59. const WORD rfb::win32::AboutDialog::Copyright = IDC_COPYRIGHT;
  60. const WORD rfb::win32::AboutDialog::Version = IDC_VERSION;
  61. const WORD rfb::win32::AboutDialog::BuildTime = IDC_BUILDTIME;
  62. const WORD rfb::win32::AboutDialog::Description = IDC_DESCRIPTION;
  63. //
  64. // -=- VNCviewer Tray Icon
  65. //
  66. class CViewTrayIcon : public TrayIcon {
  67. public:
  68. CViewTrayIcon(CViewManager& mgr) : manager(mgr) {
  69. setIcon(IDI_ICON);
  70. setToolTip(_T("VNC Viewer"));
  71. }
  72. virtual LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
  73. switch(msg) {
  74. case WM_USER:
  75. switch (lParam) {
  76. case WM_LBUTTONDBLCLK:
  77. SendMessage(getHandle(), WM_COMMAND, ID_NEW_CONNECTION, 0);
  78. break;
  79. case WM_RBUTTONUP:
  80. HMENU menu = LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(IDR_TRAY));
  81. HMENU trayMenu = GetSubMenu(menu, 0);
  82. // First item is New Connection, the default
  83. SetMenuDefaultItem(trayMenu, ID_NEW_CONNECTION, FALSE);
  84. // SetForegroundWindow is required, otherwise Windows ignores the
  85. // TrackPopupMenu because the window isn't the foreground one, on
  86. // some older Windows versions...
  87. SetForegroundWindow(getHandle());
  88. // Display the menu
  89. POINT pos;
  90. GetCursorPos(&pos);
  91. TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, getHandle(), 0);
  92. break;
  93. }
  94. return 0;
  95. case WM_COMMAND:
  96. switch (LOWORD(wParam)) {
  97. case ID_NEW_CONNECTION:
  98. manager.addClient(0);
  99. break;
  100. case ID_OPTIONS:
  101. OptionsDialog::global.showDialog(0);
  102. break;
  103. case ID_ABOUT:
  104. AboutDialog::instance.showDialog();
  105. break;
  106. case ID_CLOSE:
  107. SendMessage(getHandle(), WM_CLOSE, 0, 0);
  108. break;
  109. }
  110. return 0;
  111. case WM_CLOSE:
  112. PostQuitMessage(0);
  113. return 0;
  114. }
  115. return TrayIcon::processMessage(msg, wParam, lParam);
  116. }
  117. protected:
  118. CViewManager& manager;
  119. };
  120. //
  121. // -=- processParams
  122. // Read in the command-line parameters and interpret them.
  123. //
  124. void
  125. programInfo() {
  126. win32::FileVersionInfo inf;
  127. _tprintf(_T("%s - %s, Version %s\n"),
  128. inf.getVerString(_T("ProductName")),
  129. inf.getVerString(_T("FileDescription")),
  130. inf.getVerString(_T("FileVersion")));
  131. printf("%s\n", buildTime);
  132. _tprintf(_T("%s\n\n"), inf.getVerString(_T("LegalCopyright")));
  133. }
  134. void
  135. programUsage() {
  136. printf("usage: vncviewer <options> <hostname>[:<display>]\n");
  137. printf("Command-line options:\n");
  138. printf(" -help - Provide usage information.\n");
  139. printf(" -config <file> - Load connection settings from VNCViewer 3.3 settings file\n");
  140. printf(" -console - Run with a console window visible.\n");
  141. printf(" <setting>=<value> - Set the named configuration parameter.\n");
  142. printf(" (Parameter values specified on the command-line override those specified by other configuration methods.)\n");
  143. printf("\nLog names:\n");
  144. LogWriter::listLogWriters();
  145. printf("\nLog destinations:\n");
  146. Logger::listLoggers();
  147. printf("\nParameters:\n");
  148. Configuration::listParams();
  149. }
  150. bool print_usage = false;
  151. bool close_console = true;
  152. std::list<char*> hosts;
  153. std::list<char*> configFiles;
  154. void
  155. processParams(int argc, char* argv[]) {
  156. for (int i=1; i<argc; i++) {
  157. try {
  158. if (strcasecmp(argv[i], "-console") == 0) {
  159. close_console = false;
  160. } else if (((strcasecmp(argv[i], "-config") == 0) ||
  161. (strcasecmp(argv[i], "/config") == 0)) && (i < argc-1)) {
  162. configFiles.push_back(strDup(argv[i+1]));
  163. i++;
  164. } else if ((strcasecmp(argv[i], "-help") == 0) ||
  165. (strcasecmp(argv[i], "--help") == 0) ||
  166. (strcasecmp(argv[i], "-h") == 0) ||
  167. (strcasecmp(argv[i], "/?") == 0)) {
  168. print_usage = true;
  169. close_console = false;
  170. break;
  171. } else {
  172. // Try to process <option>=<value>, or -<bool>
  173. if (Configuration::setParam(argv[i], true))
  174. continue;
  175. // Try to process -<option> <value>
  176. if ((argv[i][0] == '-') && (i+1 < argc)) {
  177. if (Configuration::setParam(&argv[i][1], argv[i+1], true)) {
  178. i++;
  179. continue;
  180. }
  181. }
  182. // If it's -<option> then it's not recognised - error
  183. // If it's <host> then add it to the list to connect to.
  184. if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
  185. const char* fmt = "The option %s was not recognized. Use -help to see VNC Viewer usage";
  186. CharArray tmp(strlen(argv[i])+strlen(fmt)+1);
  187. sprintf(tmp.buf, fmt, argv[i]);
  188. MsgBox(0, TStr(tmp.buf), MB_ICONSTOP | MB_OK);
  189. exit(1);
  190. } else {
  191. hosts.push_back(strDup(argv[i]));
  192. }
  193. }
  194. } catch (rdr::Exception& e) {
  195. vlog.error(e.str());
  196. }
  197. }
  198. }
  199. //
  200. // -=- main
  201. //
  202. int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, char* cmdLine, int cmdShow) {
  203. try {
  204. // - Initialise the available loggers
  205. initStdIOLoggers();
  206. initFileLogger("C:\\temp\\vncviewer4.log");
  207. // - By default, just log errors to stderr
  208. logParams.setDefault("*:stderr:0");
  209. // - Process the command-line
  210. int argc = __argc;
  211. char** argv = __argv;
  212. processParams(argc, argv);
  213. // - By default the console will be closed
  214. if (close_console) {
  215. if (!FreeConsole())
  216. vlog.info("unable to close console:%u", GetLastError());
  217. } else {
  218. AllocConsole();
  219. freopen("CONIN$","rb",stdin);
  220. freopen("CONOUT$","wb",stdout);
  221. freopen("CONOUT$","wb",stderr);
  222. setbuf(stderr, 0);
  223. }
  224. #ifdef _DIALOG_CAPTURE
  225. if (captureDialogs) {
  226. CView::userConfigKey.openKey(HKEY_CURRENT_USER, _T("Software\\TightVNC\\VNCViewer4"));
  227. OptionsDialog::global.showDialog(0, true);
  228. return 0;
  229. }
  230. #endif
  231. // - If no clients are specified, bring up a connection dialog
  232. if (configFiles.empty() && hosts.empty() && !acceptIncoming && !print_usage)
  233. hosts.push_back(0);
  234. programInfo();
  235. // - Connect to the clients
  236. if (!configFiles.empty() || !hosts.empty() || acceptIncoming) {
  237. // - Configure the registry configuration reader
  238. win32::RegistryReader reg_reader;
  239. reg_reader.setKey(HKEY_CURRENT_USER, _T("Software\\TightVNC\\VNCViewer4"));
  240. // - Tell the rest of VNC Viewer where to write config data to
  241. CView::userConfigKey.openKey(HKEY_CURRENT_USER, _T("Software\\TightVNC\\VNCViewer4"));
  242. // - Start the Socket subsystem for TCP
  243. TcpSocket::initTcpSockets();
  244. // Create the client connection manager
  245. CViewManager view_manager;
  246. if (acceptIncoming) {
  247. int port = 5500;
  248. // Listening viewer
  249. if (hosts.size() > 1) {
  250. programUsage();
  251. exit(2);
  252. }
  253. if (!hosts.empty()) {
  254. port = atoi(hosts.front());
  255. }
  256. vlog.debug("opening listener");
  257. CViewTrayIcon tray(view_manager);
  258. view_manager.addDefaultTCPListener(port);
  259. // Run the view manager
  260. // Also processes the tray icon if necessary
  261. MSG msg;
  262. while (GetMessage(&msg, NULL, 0, 0) > 0) {
  263. TranslateMessage(&msg);
  264. DispatchMessage(&msg);
  265. }
  266. vlog.debug("quitting viewer");
  267. } else {
  268. // Read each config file in turn
  269. while (!configFiles.empty()) {
  270. char* filename = configFiles.front();
  271. view_manager.addClient(filename, true);
  272. strFree(filename);
  273. configFiles.pop_front();
  274. }
  275. // Connect to each client in turn
  276. while (!hosts.empty()) {
  277. char* hostinfo = hosts.front();
  278. view_manager.addClient(hostinfo);
  279. strFree(hostinfo);
  280. hosts.pop_front();
  281. }
  282. // Run the view manager
  283. MSG msg;
  284. while (GetMessage(&msg, NULL, 0, 0) > 0) {
  285. TranslateMessage(&msg);
  286. DispatchMessage(&msg);
  287. }
  288. vlog.debug("quitting viewer");
  289. }
  290. }
  291. // - If necessary, print the program's usage info
  292. if (print_usage)
  293. programUsage();
  294. if (!close_console) {
  295. printf("Press Enter/Return key to continue\n");
  296. char c = getchar();
  297. }
  298. } catch (rdr::Exception& e) {
  299. MsgBox(0, TStr(e.str()), MB_ICONSTOP | MB_OK);
  300. }
  301. return 0;
  302. }