blob: 4aa5dcb665d4fa1354b4ef84ff024c6a6f960421 [file] [log] [blame]
Constantin Kaplinsky729598c2006-05-25 05:12:25 +00001/* Copyright (C) 2002-2005 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
19// -=- VNC Server 4.0 for Windows (WinVNC4)
20
21#include <string.h>
22#ifdef WIN32
23#define strcasecmp _stricmp
24#endif
25
26#include <winvnc/VNCServerWin32.h>
27#include <winvnc/VNCServerService.h>
28#include <winvnc/AddNewClientDialog.h>
29
30#include <rfb/Logger_stdio.h>
31#include <rfb/Logger_file.h>
32#include <rfb/LogWriter.h>
33#include <rfb_win32/AboutDialog.h>
34#include <rfb_win32/MsgBox.h>
35#include <network/TcpSocket.h>
36
37using namespace winvnc;
38using namespace rfb;
39using namespace win32;
40
41static LogWriter vlog("main");
42
43TStr rfb::win32::AppName("VNC Server");
44
45
Samuel Mannehed60c41932014-02-07 14:53:24 +000046extern bool runAsService;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000047static bool runServer = true;
48static bool close_console = false;
49
50
51//
52// -=- processParams
53// Read in the command-line parameters and interpret them.
54//
55
56static void programInfo() {
57 win32::FileVersionInfo inf;
58 _tprintf(_T("%s - %s, Version %s\n"),
59 inf.getVerString(_T("ProductName")),
60 inf.getVerString(_T("FileDescription")),
61 inf.getVerString(_T("FileVersion")));
62 printf("%s\n", buildTime);
63 _tprintf(_T("%s\n\n"), inf.getVerString(_T("LegalCopyright")));
64}
65
66static void programUsage() {
67 printf("Command-line options:\n");
68 printf(" -connect [<host[::port]>] - Connect an existing WinVNC server to a listening viewer.\n");
69 printf(" -disconnect - Disconnect all clients from an existing WinVNC server.\n");
70 printf(" -register <options...> - Register WinVNC server as a system service.\n");
71 printf(" -unregister - Remove WinVNC server from the list of system services.\n");
72 printf(" -start - Start the WinVNC server system service.\n");
73 printf(" -stop - Stop the WinVNC server system service.\n");
74 printf(" -status - Query the WinVNC service status.\n");
75 printf(" -help - Provide usage information.\n");
76 printf(" -noconsole - Run without a console (i.e. no stderr/stdout)\n");
77 printf(" <setting>=<value> - Set the named configuration parameter.\n");
78 printf(" (Parameter values specified on the command-line override those specified by other configuration methods.)\n");
79 printf("\nLog names:\n");
80 LogWriter::listLogWriters();
81 printf("\nLog destinations:\n");
82 Logger::listLoggers();
83 printf("\nAvailable configuration parameters:\n");
Adam Tkacc58b3d12010-04-23 13:55:10 +000084 Configuration::listParams(ConfServer);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000085}
86
87static void MsgBoxOrLog(const char* msg, bool isError=false) {
88 if (close_console) {
89 MsgBox(0, TStr(msg), (isError ? MB_ICONERROR : MB_ICONINFORMATION) | MB_OK);
90 } else {
91 if (isError) {
92 try {
93 vlog.error(msg);
94 return;
95 } catch (...) {
96 }
97 }
98 fprintf(stderr, "%s\n", msg);
99 }
100}
101
Adam Tkac8fb6ac02010-06-25 11:24:27 +0000102static void processParams(int argc, char** argv) {
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000103 for (int i=1; i<argc; i++) {
104 try {
105
106 if (strcasecmp(argv[i], "-connect") == 0) {
107 runServer = false;
108 CharArray host;
109 if (i+1 < argc) {
110 host.buf = strDup(argv[i+1]);
111 i++;
112 } else {
113 AddNewClientDialog ancd;
114 if (ancd.showDialog())
115 host.buf = strDup(ancd.getHostName());
116 }
117 if (host.buf) {
118 HWND hwnd = FindWindow(0, _T("winvnc::IPC_Interface"));
119 if (!hwnd)
120 throw rdr::Exception("Unable to locate existing VNC Server.");
121 COPYDATASTRUCT copyData;
122 copyData.dwData = 1; // *** AddNewClient
123 copyData.cbData = strlen(host.buf);
124 copyData.lpData = (void*)host.buf;
125 printf("Sending connect request to VNC Server...\n");
126 if (!SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData))
127 MsgBoxOrLog("Connection failed.", true);
128 }
129 } else if (strcasecmp(argv[i], "-disconnect") == 0) {
130 runServer = false;
131 HWND hwnd = FindWindow(0, _T("winvnc::IPC_Interface"));
132 if (!hwnd)
133 throw rdr::Exception("Unable to locate existing VNC Server.");
134 COPYDATASTRUCT copyData;
135 copyData.dwData = 2; // *** DisconnectClients
136 copyData.lpData = 0;
137 copyData.cbData = 0;
138 printf("Sending disconnect request to VNC Server...\n");
139 if (!SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData))
140 MsgBoxOrLog("Failed to disconnect clients.", true);
141 } else if (strcasecmp(argv[i], "-start") == 0) {
142 printf("Attempting to start service...\n");
143 runServer = false;
144 if (rfb::win32::startService(VNCServerService::Name))
145 MsgBoxOrLog("Started service successfully");
146 } else if (strcasecmp(argv[i], "-stop") == 0) {
147 printf("Attempting to stop service...\n");
148 runServer = false;
149 if (rfb::win32::stopService(VNCServerService::Name))
150 MsgBoxOrLog("Stopped service successfully");
151 } else if (strcasecmp(argv[i], "-status") == 0) {
152 printf("Querying service status...\n");
153 runServer = false;
154 DWORD state = rfb::win32::getServiceState(VNCServerService::Name);
155 CharArray stateStr(rfb::win32::serviceStateName(state));
156 const char* stateMsg = "The %s Service is in the %s state.";
157 CharArray result(strlen(stateStr.buf) + _tcslen(VNCServerService::Name) + strlen(stateMsg) + 1);
158 sprintf(result.buf, stateMsg, (const char*)CStr(VNCServerService::Name), stateStr.buf);
159 MsgBoxOrLog(result.buf);
160 } else if (strcasecmp(argv[i], "-service") == 0) {
161 printf("Run in service mode\n");
Samuel Mannehed60c41932014-02-07 14:53:24 +0000162 runServer = false;
163 runAsService = true;
164
165 } else if (strcasecmp(argv[i], "-service_run") == 0) {
166 printf("Run in service mode\n");
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000167 runAsService = true;
168
169 } else if (strcasecmp(argv[i], "-register") == 0) {
170 printf("Attempting to register service...\n");
171 runServer = false;
172 int j = i;
173 i = argc;
174 if (rfb::win32::registerService(VNCServerService::Name,
175 _T("VNC Server Version 4"),
176 argc-(j+1), &argv[j+1]))
177 MsgBoxOrLog("Registered service successfully");
178 } else if (strcasecmp(argv[i], "-unregister") == 0) {
179 printf("Attempting to unregister service...\n");
180 runServer = false;
181 if (rfb::win32::unregisterService(VNCServerService::Name))
182 MsgBoxOrLog("Unregistered service successfully");
183
184 } else if (strcasecmp(argv[i], "-noconsole") == 0) {
185 close_console = true;
186 vlog.info("closing console");
187 if (!FreeConsole())
188 vlog.info("unable to close console:%u", GetLastError());
189
190 } else if ((strcasecmp(argv[i], "-help") == 0) ||
191 (strcasecmp(argv[i], "--help") == 0) ||
192 (strcasecmp(argv[i], "-h") == 0) ||
193 (strcasecmp(argv[i], "/?") == 0)) {
194 runServer = false;
195 programUsage();
196 break;
197
198 } else {
199 // Try to process <option>=<value>, or -<bool>
200 if (Configuration::setParam(argv[i], true))
201 continue;
202 // Try to process -<option> <value>
203 if ((argv[i][0] == '-') && (i+1 < argc)) {
204 if (Configuration::setParam(&argv[i][1], argv[i+1], true)) {
205 i++;
206 continue;
207 }
208 }
209 // Nope. Show them usage and don't run the server
210 runServer = false;
211 programUsage();
212 break;
213 }
214
215 } catch (rdr::Exception& e) {
216 MsgBoxOrLog(e.str(), true);
217 }
218 }
219}
220
221
222//
223// -=- main
224//
225
Adam Tkac01345fc2010-06-25 11:29:22 +0000226int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, char* cmdLine, int cmdShow) {
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000227 int result = 0;
228
229 try {
230 // - Initialise the available loggers
231 //freopen("\\\\drupe\\tjr\\WinVNC4.log","ab",stderr);
Adam Tkacd41d4be2011-01-26 19:09:03 +0000232#ifdef _DEBUG
233 AllocConsole();
234 freopen("CONIN$", "rb", stdin);
235 freopen("CONOUT$", "wb", stdout);
236 freopen("CONOUT$", "wb", stderr);
237 setbuf(stderr, 0);
238 initStdIOLoggers();
239 initFileLogger("C:\\temp\\WinVNC4.log");
240 logParams.setParam("*:stderr:100");
241#else
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000242 initFileLogger("C:\\temp\\WinVNC4.log");
Adam Tkacd41d4be2011-01-26 19:09:03 +0000243 logParams.setParam("*:stderr:0");
244#endif
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000245 rfb::win32::initEventLogLogger(VNCServerService::Name);
246
Adam Tkac0c4dcd22010-11-11 11:29:55 +0000247 Configuration::enableServerParams();
248
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000249 // - By default, just log errors to stderr
Adam Tkacd41d4be2011-01-26 19:09:03 +0000250
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000251
252 // - Print program details and process the command line
253 programInfo();
Adam Tkac01345fc2010-06-25 11:29:22 +0000254
255 int argc = __argc;
256 char **argv = __argv;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000257 processParams(argc, argv);
258
259 // - Run the server if required
260 if (runServer) {
261 // Start the network subsystem and run the server
262 VNCServerWin32 server;
Samuel Mannehed60c41932014-02-07 14:53:24 +0000263 result = server.run();
264 } else if (runAsService) {
265 VNCServerService service;
266 service.start();
267 result = service.getStatus().dwWin32ExitCode;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000268 }
269
270 vlog.debug("WinVNC service destroyed");
271 } catch (rdr::Exception& e) {
272 MsgBoxOrLog(e.str(), true);
273 }
274
275 vlog.debug("WinVNC process quitting");
276 return result;
277}