Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@591 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/win/winvnc/VNCServerWin32.cxx b/win/winvnc/VNCServerWin32.cxx
new file mode 100644
index 0000000..3b0e1a0
--- /dev/null
+++ b/win/winvnc/VNCServerWin32.cxx
@@ -0,0 +1,333 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+// -=- WinVNC Version 4.0 Main Routine
+
+#include <winvnc/VNCServerWin32.h>
+#include <winvnc/resource.h>
+#include <winvnc/STrayIcon.h>
+#include <rfb_win32/ComputerName.h>
+#include <rfb_win32/CurrentUser.h>
+#include <rfb_win32/Service.h>
+#include <rfb/SSecurityFactoryStandard.h>
+#include <rfb/Hostname.h>
+#include <rfb/LogWriter.h>
+#include <rfb_win32/SFileTransferWin32.h>
+
+using namespace rfb;
+using namespace win32;
+using namespace winvnc;
+using namespace network;
+
+static LogWriter vlog("VNCServerWin32");
+
+
+const TCHAR* winvnc::VNCServerWin32::RegConfigPath = _T("Software\\TightVNC\\WinVNC4");
+
+// FIXME: Move into an .h file?
+extern const UINT VNCM_FT_DOWNLOAD;
+
+
+static IntParameter http_port("HTTPPortNumber",
+  "TCP/IP port on which the server will serve the Java applet VNC Viewer ", 5800);
+static IntParameter port_number("PortNumber",
+  "TCP/IP port on which the server will accept connections", 5900);
+static StringParameter hosts("Hosts",
+  "Filter describing which hosts are allowed access to this server", "+0.0.0.0/0.0.0.0");
+static BoolParameter localHost("LocalHost",
+  "Only accept connections from via the local loop-back network interface", false);
+static BoolParameter queryOnlyIfLoggedOn("QueryOnlyIfLoggedOn",
+  "Only prompt for a local user to accept incoming connections if there is a user logged on", false);
+
+
+VNCServerWin32::VNCServerWin32()
+  : command(NoCommand), commandSig(commandLock),
+    commandEvent(CreateEvent(0, TRUE, FALSE, 0)),
+    vncServer(CStr(ComputerName().buf), &desktop),
+    hostThread(0), runServer(false), isDesktopStarted(false),
+    httpServer(&vncServer), config(&sockMgr), trayIcon(0),
+    rfbSock(&sockMgr), httpSock(&sockMgr),
+    queryConnectDialog(0)
+{
+  // Initialise the desktop
+  desktop.setStatusLocation(&isDesktopStarted);
+
+  // Initialise the VNC server
+  vncServer.setQueryConnectionHandler(this);
+
+  // Register the desktop's event to be handled
+  sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
+
+  // Register the queued command event to be handled
+  sockMgr.addEvent(commandEvent, this);
+
+  vncServer.setFTManager((rfb::SFileTransferManager *)&m_FTManager);
+}
+
+VNCServerWin32::~VNCServerWin32() {
+  delete trayIcon;
+
+  // Stop the SDisplay from updating our state
+  desktop.setStatusLocation(0);
+
+  // Join the Accept/Reject dialog thread
+  if (queryConnectDialog)
+    delete queryConnectDialog->join();
+}
+
+
+void VNCServerWin32::processAddressChange(network::SocketListener* sock_) {
+  if (!trayIcon || (sock_ != rfbSock.sock))
+    return;
+
+  // Tool-tip prefix depends on server mode
+  const TCHAR* prefix = _T("VNC Server (User):");
+  if (isServiceProcess())
+    prefix = _T("VNC Server (Service):");
+
+  // Fetch the list of addresses
+  std::list<char*> addrs;
+  if (rfbSock.sock)
+    rfbSock.sock->getMyAddresses(&addrs);
+  else
+    addrs.push_front(strDup("Not accepting connections"));
+
+  // Allocate space for the new tip
+  std::list<char*>::iterator i, next_i;
+  int length = _tcslen(prefix)+1;
+  for (i=addrs.begin(); i!= addrs.end(); i++)
+    length += strlen(*i) + 1;
+
+  // Build the new tip
+  TCharArray toolTip(length);
+  _tcscpy(toolTip.buf, prefix);
+  for (i=addrs.begin(); i!= addrs.end(); i=next_i) {
+    next_i = i; next_i ++;
+    TCharArray addr = *i;    // Assumes ownership of string
+    _tcscat(toolTip.buf, addr.buf);
+    if (next_i != addrs.end())
+      _tcscat(toolTip.buf, _T(","));
+  }
+  
+  // Pass the new tip to the tray icon
+  vlog.info("Refreshing tray icon");
+  trayIcon->setToolTip(toolTip.buf);
+}
+
+void VNCServerWin32::regConfigChanged() {
+  // -=- Make sure we're listening on the right ports.
+  rfbSock.setServer(&vncServer);
+  rfbSock.setPort(port_number, localHost);
+  httpSock.setServer(&httpServer);
+  httpSock.setPort(http_port, localHost);
+
+  // -=- Update the Java viewer's web page port number.
+  httpServer.setRFBport(rfbSock.sock ? port_number : 0);
+
+  // -=- Update the TCP address filter for both ports, if open.
+  CharArray pattern(hosts.getData());
+  rfbSock.setFilter(pattern.buf);
+  httpSock.setFilter(pattern.buf);
+
+  // -=- Update the tray icon tooltip text with IP addresses
+  processAddressChange(rfbSock.sock);
+}
+
+
+int VNCServerWin32::run() {
+  { Lock l(runLock);
+    hostThread = Thread::self();
+    runServer = true;
+  }
+
+  // - Create the tray icon (if possible)
+  trayIcon = new STrayIconThread(*this, IDI_ICON, IDI_CONNECTED,
+                                 IDI_ICON_DISABLE, IDI_CONNECTED_DISABLE,
+                                 IDR_TRAY);
+
+  // - Register for notification of configuration changes
+  config.setCallback(this);
+  if (isServiceProcess())
+    config.setKey(HKEY_LOCAL_MACHINE, RegConfigPath);
+  else
+    config.setKey(HKEY_CURRENT_USER, RegConfigPath);
+
+  // - Set the address-changed handler for the RFB socket
+  rfbSock.setAddressChangeNotifier(this);
+
+  DWORD result = 0;
+  try {
+    vlog.debug("Entering message loop");
+
+    // - Run the server until we're told to quit
+    MSG msg;
+    int result = 0;
+    while (runServer) {
+      result = sockMgr.getMessage(&msg, NULL, 0, 0);
+      if (result < 0)
+        throw rdr::SystemException("getMessage", GetLastError());
+      if (!isServiceProcess() && (result == 0))
+        break;
+      if (msg.message == VNCM_FT_DOWNLOAD)
+        m_FTManager.processDownloadMsg(msg);
+      TranslateMessage(&msg);
+      DispatchMessage(&msg);
+    }
+
+    vlog.debug("Server exited cleanly");
+  } catch (rdr::SystemException &s) {
+    vlog.error(s.str());
+    result = s.err;
+  } catch (rdr::Exception &e) {
+    vlog.error(e.str());
+  }
+
+  { Lock l(runLock);
+    runServer = false;
+    hostThread = 0;
+  }
+
+  return result;
+}
+
+void VNCServerWin32::stop() {
+  Lock l(runLock);
+  runServer = false;
+  if (hostThread)
+    PostThreadMessage(hostThread->getThreadId(), WM_QUIT, 0, 0);
+}
+
+
+bool VNCServerWin32::disconnectClients(const char* reason) {
+  return queueCommand(DisconnectClients, reason, 0);
+}
+
+bool VNCServerWin32::addNewClient(const char* client) {
+  TcpSocket* sock = 0;
+  try {
+    CharArray hostname;
+    int port;
+    getHostAndPort(client, &hostname.buf, &port, 5500);
+    vlog.error("port=%d", port);
+    sock = new TcpSocket(hostname.buf, port);
+    if (queueCommand(AddClient, sock, 0))
+      return true;
+    delete sock;
+  } catch (...) {
+    delete sock;
+  }
+  return false;
+}
+
+bool VNCServerWin32::getClientsInfo(rfb::ListConnInfo* LCInfo) {
+  return queueCommand(GetClientsInfo, LCInfo, 0);
+}
+
+bool VNCServerWin32::setClientsStatus(rfb::ListConnInfo* LCInfo) {
+  return queueCommand(SetClientsStatus, LCInfo, 0);
+}
+
+VNCServerST::queryResult VNCServerWin32::queryConnection(network::Socket* sock,
+                                            const char* userName,
+                                            char** reason)
+{
+  if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn())
+    return VNCServerST::ACCEPT;
+  if (queryConnectDialog) {
+    *reason = rfb::strDup("Another connection is currently being queried.");
+    return VNCServerST::REJECT;
+  }
+  queryConnectDialog = new QueryConnectDialog(sock, userName, this);
+  queryConnectDialog->startDialog();
+  return VNCServerST::PENDING;
+}
+
+void VNCServerWin32::queryConnectionComplete() {
+  queueCommand(QueryConnectionComplete, 0, 0, false);
+}
+
+
+bool VNCServerWin32::queueCommand(Command cmd, const void* data, int len, bool wait) {
+  Lock l(commandLock);
+  while (command != NoCommand)
+    commandSig.wait();
+  command = cmd;
+  commandData = data;
+  commandDataLen = len;
+  SetEvent(commandEvent);
+  if (wait) {
+    while (command != NoCommand)
+      commandSig.wait();
+    commandSig.signal();
+  }
+  return true;
+}
+
+void VNCServerWin32::processEvent(HANDLE event_) {
+  ResetEvent(event_);
+
+  if (event_ == commandEvent.h) {
+    // If there is no command queued then return immediately
+    {
+      Lock l(commandLock);
+      if (command == NoCommand)
+        return;
+    }
+
+    // Perform the required command
+    switch (command) {
+
+    case DisconnectClients:
+      // Disconnect all currently active VNC Viewers
+      vncServer.closeClients((const char*)commandData);
+      break;
+
+    case AddClient:
+      // Make a reverse connection to a VNC Viewer
+      sockMgr.addSocket((network::Socket*)commandData, &vncServer);
+      break;
+  case GetClientsInfo:
+    vncServer.getConnInfo((ListConnInfo*)commandData); 
+    break;
+  case SetClientsStatus:
+    vncServer.setConnStatus((ListConnInfo*)commandData); 
+    break;
+
+    case QueryConnectionComplete:
+      // The Accept/Reject dialog has completed
+      // Get the result, then clean it up
+      vncServer.approveConnection(queryConnectDialog->getSock(),
+                                  queryConnectDialog->isAccepted(),
+                                  "Connection rejected by user");
+      delete queryConnectDialog->join();
+      queryConnectDialog = 0;
+      break;
+
+    default:
+      vlog.error("unknown command %d queued", command);
+    };
+
+    // Clear the command and signal completion
+    {
+      Lock l(commandLock);
+      command = NoCommand;
+      commandSig.signal();
+    }
+  }
+}
+