Initial revision


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/winvnc/AddNewClientDialog.h b/winvnc/AddNewClientDialog.h
new file mode 100644
index 0000000..d8e0af3
--- /dev/null
+++ b/winvnc/AddNewClientDialog.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+// -=- AddnewClientDialog.h
+
+#ifndef __WINVNC_ADD_NEW_CLIENT_DIALOG_H__
+#define __WINVNC_ADD_NEW_CLIENT_DIALOG_H__
+
+#include <winvnc/resource.h>
+#include <rfb_win32/Dialog.h>
+//#include <rfb_win32/TCharArray.h>
+
+namespace winvnc {
+
+  class AddNewClientDialog : public rfb::win32::Dialog {
+  public:
+    AddNewClientDialog() : Dialog(GetModuleHandle(0)) {}
+    // - Show the dialog and return true if OK was clicked,
+    //   false in case of error or Cancel
+    virtual bool showDialog() {
+      return Dialog::showDialog(MAKEINTRESOURCE(IDD_ADD_NEW_CLIENT));
+    }
+    const char* getHostName() const {return hostName.buf;}
+  protected:
+
+    // Dialog methods (protected)
+    virtual void initDialog() {
+      if (hostName.buf)
+        setItemString(IDC_HOST, rfb::TStr(hostName.buf));
+    }
+    virtual bool onOk() {
+      hostName.replaceBuf(rfb::strDup(rfb::CStr(getItemString(IDC_HOST))));
+      return true;
+    }
+
+    rfb::CharArray hostName;
+  };
+
+};
+
+#endif
diff --git a/winvnc/JavaViewer.cxx b/winvnc/JavaViewer.cxx
new file mode 100644
index 0000000..fecbcee
--- /dev/null
+++ b/winvnc/JavaViewer.cxx
@@ -0,0 +1,95 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winvnc/JavaViewer.h>
+#include <winvnc/resource.h>
+#include <rdr/MemInStream.h>
+#include <rfb/LogWriter.h>
+#include <rfb/VNCserverST.h>
+#include <rfb_win32/TCharArray.h>
+
+#define strcasecmp _stricmp
+
+using namespace winvnc;
+using namespace rfb;
+
+
+static rfb::LogWriter vlog("JavaViewerServer");
+
+JavaViewerServer::JavaViewerServer(rfb::VNCServerST* svr) : server(svr) {
+}
+
+JavaViewerServer::~JavaViewerServer() {
+}
+
+rdr::InStream* JavaViewerServer::getFile(const char* name, const char** contentType) {
+  if (strcmp(name, "/") == 0)
+    name = "/index.vnc";
+
+  HRSRC resource = FindResource(0, TStr(name), _T("HTTPFILE"));
+  if (!resource) return 0;
+  HGLOBAL handle = LoadResource(0, resource);
+  if (!handle) return 0;
+  void* buf = LockResource(handle);
+  int len = SizeofResource(0, resource);
+
+  rdr::InStream* is = new rdr::MemInStream(buf, len);
+  if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
+    is = new rdr::SubstitutingInStream(is, this, 20);
+    *contentType = "text/html";
+  }
+  return is;
+}
+
+char* JavaViewerServer::substitute(const char* varName)
+{
+  if (strcmp(varName, "$$") == 0) {
+    return rfb::strDup("$");
+  }
+  if (strcmp(varName, "$PORT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", rfbPort);
+    return str;
+  }
+  if (strcmp(varName, "$WIDTH") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", server->getDesktopSize().x);
+    return str;
+  }
+  if (strcmp(varName, "$HEIGHT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", server->getDesktopSize().y);
+    return str;
+  }
+  if (strcmp(varName, "$APPLETWIDTH") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", server->getDesktopSize().x);
+    return str;
+  }
+  if (strcmp(varName, "$APPLETHEIGHT") == 0) {
+    char* str = new char[10];
+    sprintf(str, "%d", server->getDesktopSize().y + 32);
+    return str;
+  }
+  if (strcmp(varName, "$DESKTOP") == 0) {
+    return rfb::strDup(server->getName());
+  }
+  return 0;
+}
diff --git a/winvnc/JavaViewer.h b/winvnc/JavaViewer.h
new file mode 100644
index 0000000..20af786
--- /dev/null
+++ b/winvnc/JavaViewer.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+// -=- JavaViewer.h
+
+// Custom HTTPServer-derived class which serves the Java VNC Viewer
+// to clients, using resource files compiled in to the WinVNC executable.
+
+#ifndef WINVNC_JAVA_VIEWER
+#define WINVNC_JAVA_VIEWER
+
+#include <rfb/HTTPServer.h>
+#include <rfb/VNCServerST.h>
+#include <rdr/SubstitutingInStream.h>
+
+namespace winvnc {
+
+  class JavaViewerServer : public rfb::HTTPServer, public rdr::Substitutor {
+  public:
+    JavaViewerServer(rfb::VNCServerST* desktop);
+    virtual ~JavaViewerServer();
+
+    virtual rdr::InStream* getFile(const char* name, const char** contentType);
+
+    // rdr::Substitutor callback
+    virtual char* substitute(const char* varName);
+
+    void setRFBport(int port) {
+      rfbPort = port;
+    }
+  protected:
+    int rfbPort;
+    rfb::VNCServerST* server;
+  };
+
+};
+
+#endif
+
diff --git a/winvnc/QueryConnectDialog.cxx b/winvnc/QueryConnectDialog.cxx
new file mode 100644
index 0000000..52d7249
--- /dev/null
+++ b/winvnc/QueryConnectDialog.cxx
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002-2003 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.
+ */
+
+#include <winvnc/QueryConnectDialog.h>
+#include <winvnc/VNCServerWin32.h>
+#include <winvnc/resource.h>
+#include <rfb_win32/Win32Util.h>
+#include <rfb_win32/TCharArray.h>
+#include <rfb_win32/Service.h>
+#include <rfb/LogWriter.h>
+
+using namespace rfb;
+using namespace win32;
+using namespace winvnc;
+
+static LogWriter vlog("QueryConnectDialog");
+
+static IntParameter timeout("QueryConnectTimeout",
+                            "Number of seconds to show the Accept Connection dialog before "
+                            "rejecting the connection",
+                            10);
+
+
+// - Visible methods
+
+QueryConnectDialog::QueryConnectDialog(network::Socket* sock_,
+                                       const char* userName_,
+                                       VNCServerWin32* s)
+: Thread("QueryConnectDialog"), Dialog(GetModuleHandle(0)),
+  sock(sock_), approve(false), server(s) {
+  peerIp.buf = sock->getPeerAddress();
+  userName.buf = strDup(userName_);
+}
+
+void QueryConnectDialog::startDialog() {
+  start();
+}
+
+
+// - Thread overrides
+
+void QueryConnectDialog::run() {
+  countdown = timeout;
+  try {
+    if (desktopChangeRequired() && !changeDesktop())
+      throw rdr::Exception("changeDesktop failed");
+    approve = Dialog::showDialog(MAKEINTRESOURCE(IDD_QUERY_CONNECT));
+    server->queryConnectionComplete();
+  } catch (...) {
+    server->queryConnectionComplete();
+    throw;
+  }
+}
+
+
+// - Dialog overrides
+
+void QueryConnectDialog::initDialog() {
+  if (!SetTimer(handle, 1, 1000, 0))
+    throw rdr::SystemException("SetTimer", GetLastError());
+  setItemString(IDC_QUERY_HOST, TStr(peerIp.buf));
+  if (!userName.buf)
+    userName.buf = strDup("(anonymous)");
+  setItemString(IDC_QUERY_USER, TStr(userName.buf));
+  setCountdownLabel();
+}
+
+void QueryConnectDialog::setCountdownLabel() {
+  TCHAR buf[16];
+  _stprintf(buf, _T("%d"), countdown);
+  setItemString(IDC_QUERY_COUNTDOWN, buf);
+}
+
+BOOL QueryConnectDialog::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+  if (msg == WM_TIMER) {
+    if (--countdown == 0 || desktopChangeRequired()) {
+      DestroyWindow(hwnd);
+    } else {
+      setCountdownLabel();
+    }
+    return TRUE;
+  } else {
+    return Dialog::dialogProc(hwnd, msg, wParam, lParam);
+  }
+}
diff --git a/winvnc/QueryConnectDialog.h b/winvnc/QueryConnectDialog.h
new file mode 100644
index 0000000..30dd270
--- /dev/null
+++ b/winvnc/QueryConnectDialog.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2002-2003 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.
+ */
+
+// -=- QueryConnectDialog.h
+
+#ifndef __WINVNC_QUERY_CONNECT_DIALOG_H__
+#define __WINVNC_QUERY_CONNECT_DIALOG_H__
+
+#include <rfb/Threading.h>
+#include <rfb_win32/Dialog.h>
+#include <rfb/util.h>
+
+namespace network { class Socket; }
+
+namespace winvnc {
+
+  class VNCServerWin32;
+
+  class QueryConnectDialog : public rfb::Thread, rfb::win32::Dialog {
+  public:
+    QueryConnectDialog(network::Socket* sock, const char* userName, VNCServerWin32* s);
+    virtual void startDialog();
+    virtual void run();
+    network::Socket* getSock() {return sock;}
+    bool isAccepted() const {return approve;}
+  protected:
+
+    // Dialog methods (protected)
+    virtual void initDialog();
+    virtual BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+    // Custom internal methods
+    void setCountdownLabel();
+
+    int countdown;
+    network::Socket* sock;
+    rfb::CharArray peerIp;
+    rfb::CharArray userName;
+    bool approve;
+    VNCServerWin32* server;
+  };
+
+};
+
+#endif
diff --git a/winvnc/STrayIcon.cxx b/winvnc/STrayIcon.cxx
new file mode 100644
index 0000000..7cfea3c
--- /dev/null
+++ b/winvnc/STrayIcon.cxx
@@ -0,0 +1,234 @@
+/* Copyright (C) 2002-2004 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 Tray Icon implementation
+
+#include <winvnc/STrayIcon.h>
+#include <winvnc/resource.h>
+
+#include <rfb/LogWriter.h>
+#include <rfb/Configuration.h>
+#include <rfb_win32/LaunchProcess.h>
+#include <rfb_win32/TrayIcon.h>
+#include <rfb_win32/AboutDialog.h>
+#include <rfb_win32/Win32Util.h>
+#include <rfb_win32/Service.h>
+#include <rfb_win32/CurrentUser.h>
+
+using namespace rfb;
+using namespace win32;
+using namespace winvnc;
+
+static LogWriter vlog("STrayIcon");
+
+BoolParameter STrayIconThread::disableOptions("DisableOptions", "Disable the Options entry in the VNC Server tray menu.", false);
+
+
+//
+// -=- AboutDialog global values
+//
+
+const WORD rfb::win32::AboutDialog::DialogId = IDD_ABOUT;
+const WORD rfb::win32::AboutDialog::Copyright = IDC_COPYRIGHT;
+const WORD rfb::win32::AboutDialog::Version = IDC_VERSION;
+const WORD rfb::win32::AboutDialog::BuildTime = IDC_BUILDTIME;
+const WORD rfb::win32::AboutDialog::Description = IDC_DESCRIPTION;
+
+
+//
+// -=- Internal tray icon class
+//
+
+const UINT WM_SET_TOOLTIP = WM_USER + 1;
+
+
+class winvnc::STrayIcon : public TrayIcon {
+public:
+  STrayIcon(STrayIconThread& t) : thread(t),
+    vncConfig(_T("vncconfig.exe"), isServiceProcess() ? _T("-noconsole -service") : _T("-noconsole")),
+    vncConnect(_T("winvnc4.exe"), _T("-connect")) {
+
+    // ***
+    SetWindowText(getHandle(), _T("winvnc::IPC_Interface"));
+    // ***
+
+    SetTimer(getHandle(), 1, 3000, 0);
+    PostMessage(getHandle(), WM_TIMER, 1, 0);
+    PostMessage(getHandle(), WM_SET_TOOLTIP, 0, 0);
+  }
+
+  virtual LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
+    switch(msg) {
+
+    case WM_USER:
+      {
+        bool userKnown = CurrentUserToken().isValid();
+        bool allowOptions = !STrayIconThread::disableOptions && userKnown;
+
+        switch (lParam) {
+        case WM_LBUTTONDBLCLK:
+          SendMessage(getHandle(), WM_COMMAND, allowOptions ? ID_OPTIONS : ID_ABOUT, 0);
+          break;
+        case WM_RBUTTONUP:
+          HMENU menu = LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(thread.menu));
+          HMENU trayMenu = GetSubMenu(menu, 0);
+
+
+          // Default item is Options, if available, or About if not
+          SetMenuDefaultItem(trayMenu, allowOptions ? ID_OPTIONS : ID_ABOUT, FALSE);
+          
+          // Enable/disable options as required
+          EnableMenuItem(trayMenu, ID_OPTIONS, (!allowOptions ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
+          EnableMenuItem(trayMenu, ID_CONNECT, (!userKnown ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
+          EnableMenuItem(trayMenu, ID_CLOSE, (isServiceProcess() ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
+
+          // SetForegroundWindow is required, otherwise Windows ignores the
+          // TrackPopupMenu because the window isn't the foreground one, on
+          // some older Windows versions...
+          SetForegroundWindow(getHandle());
+
+          // Display the menu
+          POINT pos;
+          GetCursorPos(&pos);
+          TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, getHandle(), 0);
+          break;
+			  } 
+			  return 0;
+      }
+    
+      // Handle tray icon menu commands
+    case WM_COMMAND:
+      switch (LOWORD(wParam)) {
+      case ID_OPTIONS:
+        {
+          CurrentUserToken token;
+          if (token.isValid())
+            vncConfig.start(isServiceProcess() ? (HANDLE)token : 0);
+          else
+            vlog.error("Options: unknown current user");
+        }
+        break;
+      case ID_CONNECT:
+        {
+          CurrentUserToken token;
+          if (token.isValid())
+            vncConnect.start(isServiceProcess() ? (HANDLE)token : 0);
+          else
+            vlog.error("Options: unknown current user");
+        }
+        break;
+      case ID_DISCONNECT:
+        thread.server.disconnectClients("tray menu disconnect");
+        break;
+      case ID_CLOSE:
+        if (!isServiceProcess())
+          thread.server.stop();
+        break;
+      case ID_ABOUT:
+        AboutDialog::instance.showDialog();
+        break;
+      }
+      return 0;
+
+      // Handle commands send by other processes
+    case WM_COPYDATA:
+      {
+        COPYDATASTRUCT* command = (COPYDATASTRUCT*)lParam;
+        switch (command->dwData) {
+        case 1:
+          {
+            CharArray viewer = new char[command->cbData + 1];
+            memcpy(viewer.buf, command->lpData, command->cbData);
+            viewer.buf[command->cbData] = 0;
+            thread.server.addNewClient(viewer.buf);
+          }
+          break;
+        case 2:
+          thread.server.disconnectClients("IPC disconnect");
+          break;
+        };
+      };
+      break;
+
+    case WM_CLOSE:
+      PostQuitMessage(0);
+      break;
+
+    case WM_TIMER:
+      if (rfb::win32::desktopChangeRequired()) {
+        SendMessage(getHandle(), WM_CLOSE, 0, 0);
+        return 0;
+      }
+      setIcon(thread.server.isServerInUse() ? thread.activeIcon : thread.inactiveIcon);
+      return 0;
+
+    case WM_SET_TOOLTIP:
+      {
+        rfb::Lock l(thread.lock);
+        if (thread.toolTip.buf)
+          setToolTip(thread.toolTip.buf);
+      }
+      return 0;
+
+    }
+
+    return TrayIcon::processMessage(msg, wParam, lParam);
+  }
+
+protected:
+  LaunchProcess vncConfig;
+  LaunchProcess vncConnect;
+  STrayIconThread& thread;
+};
+
+
+STrayIconThread::STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon_, UINT activeIcon_, UINT menu_)
+: server(sm), inactiveIcon(inactiveIcon_), activeIcon(activeIcon_), menu(menu_),
+  windowHandle(0), runTrayIcon(true) {
+  start();
+}
+
+
+void STrayIconThread::run() {
+  while (runTrayIcon) {
+    if (rfb::win32::desktopChangeRequired() && 
+      !rfb::win32::changeDesktop())
+      Sleep(2000);
+
+    STrayIcon icon(*this);
+    windowHandle = icon.getHandle();
+
+    MSG msg;
+    while (runTrayIcon && ::GetMessage(&msg, 0, 0, 0) > 0) {
+      TranslateMessage(&msg);
+      DispatchMessage(&msg);
+    }
+
+    windowHandle = 0;
+  }
+}
+
+void STrayIconThread::setToolTip(const TCHAR* text) {
+  if (!windowHandle) return;
+  Lock l(lock);
+  delete [] toolTip.buf;
+  toolTip.buf = tstrDup(text);
+  PostMessage(windowHandle, WM_SET_TOOLTIP, 0, 0);
+}
+
+
diff --git a/winvnc/STrayIcon.h b/winvnc/STrayIcon.h
new file mode 100644
index 0000000..cfd5ec0
--- /dev/null
+++ b/winvnc/STrayIcon.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+#ifndef WINVNC_TRAYICON_H
+#define WINVNC_TRAYICON_H
+
+#include <winvnc/VNCServerWin32.h>
+#include <rfb_win32/TCharArray.h>
+#include <rfb/Configuration.h>
+#include <rfb/Threading.h>
+
+namespace winvnc {
+
+  class STrayIconThread : rfb::Thread {
+  public:
+    STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon,
+      UINT activeIcon, UINT menu);
+    virtual ~STrayIconThread() {
+      runTrayIcon = false;
+      PostThreadMessage(getThreadId(), WM_QUIT, 0, 0);
+    }
+
+    virtual void run();
+
+    void setToolTip(const TCHAR* text);
+
+    static rfb::BoolParameter disableOptions;
+
+    friend class STrayIcon;
+  protected:
+    rfb::Mutex lock;
+    HWND windowHandle;
+    rfb::TCharArray toolTip;
+    VNCServerWin32& server;
+    UINT inactiveIcon;
+    UINT activeIcon;
+    UINT menu;
+    bool runTrayIcon;
+  };
+
+};
+
+#endif
\ No newline at end of file
diff --git a/winvnc/VNCServerService.cxx b/winvnc/VNCServerService.cxx
new file mode 100644
index 0000000..c967a5a
--- /dev/null
+++ b/winvnc/VNCServerService.cxx
@@ -0,0 +1,52 @@
+/* Copyright (C) 2002-2003 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 Service-Mode implementation
+
+#include <winvnc/VNCServerService.h>
+#include <rfb_win32/OSVersion.h>
+
+using namespace winvnc;
+using namespace rfb;
+using namespace win32;
+
+const TCHAR* winvnc::VNCServerService::Name = _T("WinVNC4");
+
+
+VNCServerService::VNCServerService(VNCServerWin32& s)
+  : Service(Name), server(s) {
+  // - Set the service-mode logging defaults
+  //   These will be overridden by the Log option in the
+  //   registry, if present.
+  if (osVersion.isPlatformNT)
+    logParams.setParam("*:EventLog:0,Connections:EventLog:100");
+  else
+    logParams.setParam("*:file:0,Connections:file:100");
+}
+
+
+DWORD VNCServerService::serviceMain(int argc, TCHAR* argv[]) {
+  setStatus(SERVICE_RUNNING);
+  int result = server.run();
+  setStatus(SERVICE_STOP_PENDING);
+  return result;
+}
+
+void VNCServerService::stop() {
+  server.stop();
+}
diff --git a/winvnc/VNCServerService.h b/winvnc/VNCServerService.h
new file mode 100644
index 0000000..378ad0c
--- /dev/null
+++ b/winvnc/VNCServerService.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2003 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.
+ */
+
+#ifndef __WINVNC_SERVICEMODE_H__
+#define __WINVNC_SERVICEMODE_H__
+
+#include <winvnc/VNCServerWin32.h>
+#include <rfb_win32/Service.h>
+
+namespace winvnc {
+
+  class VNCServerService : public rfb::win32::Service {
+  public:
+    VNCServerService(VNCServerWin32& s);
+
+    DWORD serviceMain(int argc, TCHAR* argv[]);
+    void stop();
+
+    void osShuttingDown() {}
+    void readParams() {}
+
+    static const TCHAR* Name;
+  protected:
+    VNCServerWin32& server;
+  };
+
+};
+
+#endif
diff --git a/winvnc/VNCServerWin32.cxx b/winvnc/VNCServerWin32.cxx
new file mode 100644
index 0000000..a870cb1
--- /dev/null
+++ b/winvnc/VNCServerWin32.cxx
@@ -0,0 +1,341 @@
+/* Copyright (C) 2002-2004 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/Win32Util.h>
+#include <rfb_win32/Service.h>
+#include <rfb/SSecurityFactoryStandard.h>
+#include <rfb/Hostname.h>
+#include <rfb/LogWriter.h>
+
+using namespace rfb;
+using namespace win32;
+using namespace winvnc;
+using namespace network;
+
+static LogWriter vlog("VNCServerWin32");
+
+
+const TCHAR* winvnc::VNCServerWin32::RegConfigPath = _T("Software\\RealVNC\\WinVNC4");
+
+const UINT VNCM_REG_CHANGED = WM_USER;
+const UINT VNCM_COMMAND = WM_USER + 1;
+
+
+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", "+");
+static VncAuthPasswdConfigParameter vncAuthPasswd;
+static BoolParameter localHost("LocalHost",
+  "Only accept connections from via the local loop-back network interface", false);
+
+
+// -=- ManagedListener
+//     Wrapper class which simplifies the management of a listening socket
+//     on a specified port, attached to a SocketManager and SocketServer.
+//     Ensures that socket and filter are deleted and updated appropriately.
+
+class ManagedListener {
+public:
+  ManagedListener(win32::SocketManager* mgr, SocketServer* svr)
+    : sock(0), filter(0), port(0), manager(mgr),
+      server(svr), localOnly(0) {}
+  ~ManagedListener() {setPort(0);}
+  void setPort(int port, bool localOnly=false);
+  void setFilter(const char* filter);
+  TcpListener* sock;
+protected:
+  TcpFilter* filter;
+  win32::SocketManager* manager;
+  SocketServer* server;
+  int port;
+  bool localOnly;
+};
+
+// - If the port number/localHost setting has changed then tell the
+//   SocketManager to shutdown and delete it.  Also remove &
+//   delete the filter.  Then try to open a socket on the new port.
+void ManagedListener::setPort(int newPort, bool newLocalOnly) {
+  if ((port == newPort) && (localOnly == newLocalOnly) && sock) return;
+  if (sock) {
+    vlog.info("Closed TcpListener on port %d", port);
+    sock->setFilter(0);
+    delete filter;
+    manager->remListener(sock);
+    sock = 0;
+    filter = 0;
+  }
+  port = newPort;
+  localOnly = newLocalOnly;
+  if (port != 0) {
+    try {
+      sock = new TcpListener(port, localOnly);
+      vlog.info("Created TcpListener on port %d%s", port,
+                localOnly ? "(localhost)" : "(any)");
+    } catch (rdr::Exception& e) {
+      vlog.error("TcpListener on port %d failed (%s)", port, e.str());
+    }
+  }
+  if (sock)
+    manager->addListener(sock, server);
+}
+
+void ManagedListener::setFilter(const char* newFilter) {
+  if (!sock) return;
+  vlog.info("Updating TcpListener filter");
+  sock->setFilter(0);
+  delete filter;
+  filter = new TcpFilter(newFilter);
+  sock->setFilter(filter);
+}
+
+
+VNCServerWin32::VNCServerWin32()
+  : vncServer(CStr(ComputerName().buf), &desktop),
+    httpServer(0), runServer(false),
+    isDesktopStarted(false),
+    command(NoCommand), commandSig(commandLock),
+    queryConnectDialog(0) {
+  // Create the Java-viewer HTTP server
+  httpServer = new JavaViewerServer(&vncServer);
+
+  // 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);
+}
+
+VNCServerWin32::~VNCServerWin32() {
+  // Stop the SDisplay from updating our state
+  desktop.setStatusLocation(0);
+
+  // Destroy the HTTP server
+  delete httpServer;
+}
+
+
+int VNCServerWin32::run() {
+  { Lock l(runLock);
+    hostThread = Thread::self();
+    runServer = true;
+  }
+
+  // - Register for notification of configuration changes
+  if (isServiceProcess())
+    config.setKey(HKEY_LOCAL_MACHINE, RegConfigPath);
+  else
+    config.setKey(HKEY_CURRENT_USER, RegConfigPath);
+  config.setNotifyThread(Thread::self(), VNCM_REG_CHANGED);
+
+  // - Create the tray icon if possible
+  STrayIconThread trayIcon(*this, IDI_ICON, IDI_CONNECTED, IDR_TRAY);
+
+  DWORD result = 0;
+  try {
+    // - Create some managed listening sockets
+    ManagedListener rfb(&sockMgr, &vncServer);
+    ManagedListener http(&sockMgr, httpServer);
+
+    // - Continue to operate until WM_QUIT is processed
+    MSG msg;
+    do {
+      // -=- Make sure we're listening on the right ports.
+      rfb.setPort(port_number, localHost);
+      http.setPort(http_port, localHost);
+
+      // -=- Update the Java viewer's web page port number.
+      httpServer->setRFBport(rfb.sock ? port_number : 0);
+
+      // -=- Update the TCP address filter for both ports, if open.
+      CharArray pattern;
+      pattern.buf = hosts.getData();
+      if (!localHost) {
+        rfb.setFilter(pattern.buf);
+        http.setFilter(pattern.buf);
+      }
+
+      // - If there is a listening port then add the address to the
+      //   tray icon's tool-tip text.
+      {
+        const TCHAR* prefix = isServiceProcess() ?
+          _T("VNC Server (Service):") : _T("VNC Server (User):");
+
+        std::list<char*> addrs;
+        if (rfb.sock)
+          rfb.sock->getMyAddresses(&addrs);
+        else
+          addrs.push_front(strDup("Not accepting connections"));
+
+        std::list<char*>::iterator i, next_i;
+        int length = _tcslen(prefix)+1;
+        for (i=addrs.begin(); i!= addrs.end(); i++)
+          length += strlen(*i) + 1;
+
+        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(","));
+        }
+        trayIcon.setToolTip(toolTip.buf);
+      }
+
+      vlog.debug("Entering message loop");
+
+      // - Run the server until the registry changes, or we're told to quit
+      while (sockMgr.getMessage(&msg, NULL, 0, 0)) {
+        if (msg.hwnd == 0) {
+          if (msg.message == VNCM_REG_CHANGED)
+            break;
+          if (msg.message == VNCM_COMMAND)
+            doCommand();
+        }
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+      }
+
+    } while ((msg.message != WM_QUIT) || runServer);
+
+    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;
+  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;
+}
+
+
+VNCServerST::queryResult VNCServerWin32::queryConnection(network::Socket* sock,
+                                            const char* userName,
+                                            char** reason)
+{
+  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() {
+  Thread* qcd = queryConnectDialog;
+  queueCommand(QueryConnectionComplete, 0, 0);
+  delete qcd->join();
+}
+
+
+bool VNCServerWin32::queueCommand(Command cmd, const void* data, int len) {
+  Lock l(commandLock);
+  while (command != NoCommand) commandSig.wait();
+  command = cmd;
+  commandData = data;
+  commandDataLen = len;
+  if (PostThreadMessage(hostThread->getThreadId(), VNCM_COMMAND, 0, 0))
+    while (command != NoCommand) commandSig.wait();
+  else
+    return false;
+  return true;
+}
+
+void VNCServerWin32::doCommand() {
+  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
+    vncServer.addClient((network::Socket*)commandData, true);
+    sockMgr.addSocket((network::Socket*)commandData, &vncServer);
+    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");
+    queryConnectDialog = 0;
+    break;
+
+  default:
+    vlog.error("unknown command %d queued", command);
+  };
+
+  // Clear the command and signal completion
+  command = NoCommand;
+  commandSig.signal();
+}
diff --git a/winvnc/VNCServerWin32.h b/winvnc/VNCServerWin32.h
new file mode 100644
index 0000000..c824d54
--- /dev/null
+++ b/winvnc/VNCServerWin32.h
@@ -0,0 +1,99 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+#ifndef __VNCSERVER_WIN32_H__
+#define __VNCSERVER_WIN32_H__
+
+#include <winsock2.h>
+#include <network/TcpSocket.h>
+#include <rfb/VNCServerST.h>
+#include <rfb_win32/RegConfig.h>
+#include <rfb_win32/SDisplay.h>
+#include <rfb_win32/SocketManager.h>
+#include <rfb_win32/TCharArray.h>
+#include <winvnc/QueryConnectDialog.h>
+#include <winvnc/JavaViewer.h>
+
+namespace winvnc {
+
+  class VNCServerWin32 : rfb::VNCServerST::QueryConnectionHandler {
+  public:
+    VNCServerWin32();
+    virtual ~VNCServerWin32();
+
+    // Run the server in the current thread
+    int run();
+
+    // Cause the run() call to return
+    // THREAD-SAFE
+    void stop();
+
+    // Determine whether a viewer is active
+    // THREAD-SAFE
+    bool isServerInUse() const {return isDesktopStarted;}
+
+    // Connect out to the specified VNC Viewer
+    // THREAD-SAFE
+    bool addNewClient(const char* client);
+
+    // Disconnect all connected clients
+    // THREAD-SAFE
+    bool disconnectClients(const char* reason=0);
+
+    // Call used to notify VNCServerST of user accept/reject query completion
+    // CALLED FROM AcceptConnectDialog THREAD
+    void queryConnectionComplete();
+
+    // Overridden VNCServerST::QueryConnectionHandler callback,
+    // used to prompt user to accept or reject a connection.
+    // CALLBACK IN VNCServerST "HOST" THREAD
+    virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
+                                                          const char* userName,
+                                                          char** reason);
+
+    // Where to read the configuration settings from
+    static const TCHAR* RegConfigPath;
+
+  protected:
+
+    // Perform a particular internal function in the server thread
+    typedef enum {NoCommand, DisconnectClients, AddClient, QueryConnectionComplete} Command;
+    bool queueCommand(Command cmd, const void* data, int len);
+    void doCommand();
+    Command command;
+    const void* commandData;
+    int commandDataLen;
+    rfb::Mutex commandLock;
+    rfb::Condition commandSig;
+
+    // VNCServerWin32 Server-internal state
+    rfb::win32::SDisplay desktop;
+    rfb::VNCServerST vncServer;
+    rfb::Mutex runLock;
+    rfb::Thread* hostThread;
+    bool runServer;
+    bool isDesktopStarted;
+    JavaViewerServer* httpServer;
+    rfb::win32::RegistryReader config;
+    rfb::win32::SocketManager sockMgr;
+    QueryConnectDialog* queryConnectDialog;
+  };
+
+};
+
+#endif
diff --git a/winvnc/buildTime.cxx b/winvnc/buildTime.cxx
new file mode 100644
index 0000000..bab2e13
--- /dev/null
+++ b/winvnc/buildTime.cxx
@@ -0,0 +1 @@
+const char* buildTime = "Built on " __DATE__ " at " __TIME__;
\ No newline at end of file
diff --git a/winvnc/connected.ico b/winvnc/connected.ico
new file mode 100644
index 0000000..d996bcd
--- /dev/null
+++ b/winvnc/connected.ico
Binary files differ
diff --git a/winvnc/java/index.vnc b/winvnc/java/index.vnc
new file mode 100644
index 0000000..aecb613
--- /dev/null
+++ b/winvnc/java/index.vnc
@@ -0,0 +1,13 @@
+<HTML>
+<HEAD>
+<TITLE>
+VNC viewer for Java
+</TITLE>
+</HEAD>
+<BODY>
+<APPLET CODE=vncviewer/VNCViewer.class ARCHIVE=vncviewer.jar
+        WIDTH=400 HEIGHT=250>
+<PARAM name="port" value="$PORT">
+</APPLET>
+</BODY>
+</HTML>
diff --git a/winvnc/java/logo150x150.gif b/winvnc/java/logo150x150.gif
new file mode 100644
index 0000000..f1699ba
--- /dev/null
+++ b/winvnc/java/logo150x150.gif
Binary files differ
diff --git a/winvnc/java/vncviewer.jar b/winvnc/java/vncviewer.jar
new file mode 100644
index 0000000..3c92b5b
--- /dev/null
+++ b/winvnc/java/vncviewer.jar
Binary files differ
diff --git a/winvnc/msvcwarning.h b/winvnc/msvcwarning.h
new file mode 100644
index 0000000..53a0678
--- /dev/null
+++ b/winvnc/msvcwarning.h
@@ -0,0 +1,19 @@
+/* Copyright (C) 2002-2003 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.
+ */
+#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false'
+#pragma warning( disable : 4786 ) // debug identifier truncated
diff --git a/winvnc/resource.h b/winvnc/resource.h
new file mode 100644
index 0000000..81c89e2
--- /dev/null
+++ b/winvnc/resource.h
@@ -0,0 +1,37 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by winvnc.rc
+//
+#define IDR_MANIFEST                    1
+#define IDI_ICON                        101
+#define IDR_TRAY                        102
+#define IDD_DIALOG1                     103
+#define IDD_ABOUT                       104
+#define IDI_CONNECTED                   105
+#define IDR_VNCVIEWER_JAR               106
+#define IDD_QUERY_CONNECT               107
+#define IDD_ADD_NEW_CLIENT              108
+#define IDC_DESCRIPTION                 1000
+#define IDC_BUILDTIME                   1001
+#define IDC_VERSION                     1002
+#define IDC_COPYRIGHT                   1003
+#define IDC_QUERY_COUNTDOWN             1008
+#define IDC_QUERY_USER                  1009
+#define IDC_QUERY_HOST                  1010
+#define IDC_HOST                        1011
+#define ID_OPTIONS                      40001
+#define ID_CLOSE                        40002
+#define ID_ABOUT                        40003
+#define ID_DISCONNECT                   40004
+#define ID_CONNECT                      40005
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        109
+#define _APS_NEXT_COMMAND_VALUE         40006
+#define _APS_NEXT_CONTROL_VALUE         1012
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/winvnc/winvnc.cxx b/winvnc/winvnc.cxx
new file mode 100644
index 0000000..5ba6ebc
--- /dev/null
+++ b/winvnc/winvnc.cxx
@@ -0,0 +1,249 @@
+/* Copyright (C) 2002-2004 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.
+ */
+
+// -=- VNC Server 4.0 for Windows (WinVNC4)
+
+#include <string.h>
+#ifdef WIN32
+#define strcasecmp _stricmp
+#endif
+
+#include <winvnc/VNCServerWin32.h>
+#include <winvnc/VNCServerService.h>
+#include <winvnc/AddNewClientDialog.h>
+
+#include <rfb/Logger_stdio.h>
+#include <rfb/Logger_file.h>
+#include <rfb/LogWriter.h>
+#include <rfb_win32/AboutDialog.h>
+#include <rfb_win32/Win32Util.h>
+#include <network/TcpSocket.h>
+
+using namespace winvnc;
+using namespace rfb;
+using namespace win32;
+
+static LogWriter vlog("main");
+
+TStr rfb::win32::AppName("VNC Server");
+
+
+static bool runAsService = false;
+static bool runServer = true;
+static bool close_console = false;
+
+
+//
+// -=- processParams
+//     Read in the command-line parameters and interpret them.
+//
+
+void
+programInfo() {
+  win32::FileVersionInfo inf;
+  _tprintf(_T("%s - %s, Version %s\n"),
+    inf.getVerString(_T("ProductName")),
+    inf.getVerString(_T("FileDescription")),
+    inf.getVerString(_T("FileVersion")));
+  printf("%s\n", buildTime);
+  _tprintf(_T("%s\n\n"), inf.getVerString(_T("LegalCopyright")));
+}
+
+void
+programUsage() {
+  printf("Command-line options:\n");
+  printf("  -connect [<host[::port]>]            - Connect an existing WinVNC server to a listening viewer.\n");
+  printf("  -disconnect                          - Disconnect all clients from an existing WinVNC server.\n");
+  printf("  -register <options...>               - Register WinVNC server as a system service.\n");
+  printf("  -unregister                          - Remove WinVNC server from the list of system services.\n");
+  printf("  -start                               - Start the WinVNC server system service.\n");
+  printf("  -stop                                - Stop the WinVNC server system service.\n");
+  printf("  -status                              - Query the WinVNC service status.\n");
+  printf("  -help                                - Provide usage information.\n");
+  printf("  -noconsole                           - Run without a console (i.e. no stderr/stdout)\n");
+  printf("  <setting>=<value>                    - Set the named configuration parameter.\n");
+  printf("    (Parameter values specified on the command-line override those specified by other configuration methods.)\n");
+  printf("\nLog names:\n");
+  LogWriter::listLogWriters();
+  printf("\nLog destinations:\n");
+  Logger::listLoggers();
+  printf("\nAvailable configuration parameters:\n");
+  Configuration::listParams();
+}
+
+void
+processParams(int argc, const char* argv[]) {
+  for (int i=1; i<argc; i++) {
+    try {
+
+      if (strcasecmp(argv[i], "-connect") == 0) {
+        runServer = false;
+        CharArray host;
+        if (i+1 < argc) {
+          host.buf = strDup(argv[i+1]);
+        } else {
+          AddNewClientDialog ancd;
+          if (ancd.showDialog())
+            host.buf = strDup(ancd.getHostName());
+        }
+        if (host.buf) {
+          HWND hwnd = FindWindow(0, _T("winvnc::IPC_Interface"));
+          COPYDATASTRUCT copyData;
+          copyData.dwData = 1; // *** AddNewClient
+          copyData.cbData = strlen(host.buf);
+          copyData.lpData = (void*)host.buf;
+          i++;
+          SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData);
+          printf("Sent connect request to VNC Server...\n");
+        }
+      } else if (strcasecmp(argv[i], "-disconnect") == 0) {
+        HWND hwnd = FindWindow(0, _T("winvnc::IPC_Interface"));
+        COPYDATASTRUCT copyData;
+        copyData.dwData = 2; // *** DisconnectClients
+        copyData.lpData = 0;
+        copyData.cbData = 0;
+        SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData);
+        printf("Sent disconnect request to VNC Server...\n");
+        runServer = false;
+      } else if (strcasecmp(argv[i], "-start") == 0) {
+        printf("Attempting to start service...\n");
+        runServer = false;
+        if (rfb::win32::startService(VNCServerService::Name))
+          printf("Started service successfully\n");
+      } else if (strcasecmp(argv[i], "-stop") == 0) {
+        printf("Attempting to stop service...\n");
+        runServer = false;
+        if (rfb::win32::stopService(VNCServerService::Name))
+          printf("Stopped service successfully\n");
+      } else if (strcasecmp(argv[i], "-status") == 0) {
+        printf("Querying service status...\n");
+        runServer = false;
+        rfb::win32::printServiceStatus(VNCServerService::Name);
+
+      } else if (strcasecmp(argv[i], "-service") == 0) {
+        printf("Run in service mode\n");
+        runAsService = true;
+
+      } else if (strcasecmp(argv[i], "-register") == 0) {
+        printf("Attempting to register service...\n");
+        runServer = false;
+        int j = i;
+        i = argc;
+        if (rfb::win32::registerService(VNCServerService::Name,
+                                        _T("VNC Server Version 4"),
+                                        argc-(j+1), &argv[j+1]))
+          printf("Registered service successfully\n");
+      } else if (strcasecmp(argv[i], "-unregister") == 0) {
+        printf("Attempting to unregister service...\n");
+        runServer = false;
+        if (rfb::win32::unregisterService(VNCServerService::Name))
+          printf("Unregistered service successfully\n");
+
+      } else if (strcasecmp(argv[i], "-noconsole") == 0) {
+        close_console = true;
+
+      } else if ((strcasecmp(argv[i], "-help") == 0) ||
+        (strcasecmp(argv[i], "--help") == 0) ||
+        (strcasecmp(argv[i], "-h") == 0) ||
+        (strcasecmp(argv[i], "/?") == 0)) {
+        runServer = false;
+        programUsage();
+        break;
+
+      } else {
+        // Try to process <option>=<value>, or -<bool>
+        if (Configuration::setParam(argv[i], true))
+          continue;
+        // Try to process -<option> <value>
+        if ((argv[i][0] == '-') && (i+1 < argc)) {
+          if (Configuration::setParam(&argv[i][1], argv[i+1], true)) {
+            i++;
+            continue;
+          }
+        }
+        // Nope.  Show them usage and don't run the server
+        runServer = false;
+        programUsage();
+        break;
+      }
+
+    } catch (rdr::Exception& e) {
+      vlog.error(e.str());
+    }
+  }
+}
+
+
+//
+// -=- main
+//
+
+int main(int argc, const char* argv[]) {
+  int result = 0;
+
+  try {
+    // - Initialise the available loggers
+    //freopen("\\\\drupe\\tjr\\WinVNC4.log","ab",stderr);
+    //setbuf(stderr, 0);
+    initStdIOLoggers();
+    initFileLogger("C:\\temp\\WinVNC4.log");
+    rfb::win32::initEventLogLogger(VNCServerService::Name);
+
+    // - By default, just log errors to stderr
+    logParams.setParam("*:stderr:0");
+
+    // - Print program details and process the command line
+    programInfo();
+    processParams(argc, argv);
+
+    // - Run the server if required
+    if (runServer) {
+      if (close_console) {
+        vlog.info("closing console");
+        if (!FreeConsole())
+          vlog.info("unable to close console:%u", GetLastError());
+      }
+
+      network::TcpSocket::initTcpSockets();
+      VNCServerWin32 server;
+
+      if (runAsService) {
+        printf("Starting Service-Mode VNC Server.\n");
+        VNCServerService service(server);
+        service.start();
+        result = service.getStatus().dwWin32ExitCode;
+      } else {
+        printf("Starting User-Mode VNC Server.\n");
+        result = server.run();
+      }
+    }
+
+    vlog.debug("WinVNC service destroyed");
+  } catch (rdr::Exception& e) {
+    try {
+      vlog.error("Fatal Error: %s", e.str());
+    } catch (...) {
+      fprintf(stderr, "WinVNC: Fatal Error: %s\n", e.str());
+    }
+    if (!runAsService)
+      MsgBox(0, TStr(e.str()), MB_ICONERROR | MB_OK);
+  }
+
+  vlog.debug("WinVNC process quitting");
+  return result;
+}
diff --git a/winvnc/winvnc.dsp b/winvnc/winvnc.dsp
new file mode 100644
index 0000000..aa9580a
--- /dev/null
+++ b/winvnc/winvnc.dsp
@@ -0,0 +1,228 @@
+# Microsoft Developer Studio Project File - Name="winvnc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=winvnc - Win32 Debug Unicode
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "winvnc.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "winvnc.mak" CFG="winvnc - Win32 Debug Unicode"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "winvnc - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "winvnc - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "winvnc - Win32 Debug Unicode" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "winvnc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /FI"msvcwarning.h" /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 advapi32.lib user32.lib gdi32.lib ws2_32.lib version.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:console /machine:I386 /out:"../Release/winvnc4.exe"
+# SUBTRACT LINK32 /profile
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PreLink_Desc=Updating buildTime
+PreLink_Cmds=cl /c /nologo /FoRelease\ /FdRelease\ /MT buildTime.cxx
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "winvnc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 advapi32.lib user32.lib gdi32.lib ws2_32.lib version.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../Debug/winvnc4.exe" /fixed:no
+# SUBTRACT LINK32 /profile
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PreLink_Desc=Updating buildTime
+PreLink_Cmds=cl /c /nologo /FoDebug\ /FdDebug\ /MTd buildTime.cxx
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "winvnc - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "winvnc___Win32_Debug_Unicode"
+# PROP BASE Intermediate_Dir "winvnc___Win32_Debug_Unicode"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /FI"msvcwarning.h" /D "_CONSOLE" /D "_DEBUG" /D "WIN32" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib ws2_32.lib version.lib comctl32.lib shell32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../Debug/winvnc4.exe" /fixed:no
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 advapi32.lib user32.lib gdi32.lib ws2_32.lib version.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"..\Debug_Unicode/winvnc4.exe" /fixed:no
+# SUBTRACT LINK32 /pdb:none
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PreLink_Desc=Updating buildTime
+PreLink_Cmds=cl /c /nologo /FoDebug\ /FdDebug\ /MTd buildTime.cxx
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "winvnc - Win32 Release"
+# Name "winvnc - Win32 Debug"
+# Name "winvnc - Win32 Debug Unicode"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\buildTime.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\JavaViewer.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\QueryConnectDialog.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\STrayIcon.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\VNCServerService.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\VNCServerWin32.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\winvnc.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=.\winvnc.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\AddNewClientDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\JavaViewer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QueryConnectDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\STrayIcon.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\VNCServerService.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\VNCServerWin32.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\connected.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\java\logo150x150.gif
+# End Source File
+# Begin Source File
+
+SOURCE=.\winvnc.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\java\index.vnc
+# End Source File
+# Begin Source File
+
+SOURCE=.\java\vncviewer.jar
+# End Source File
+# Begin Source File
+
+SOURCE=.\vncviewer.jar
+# End Source File
+# Begin Source File
+
+SOURCE=.\winvnc4.exe.manifest
+# End Source File
+# End Target
+# End Project
diff --git a/winvnc/winvnc.ico b/winvnc/winvnc.ico
new file mode 100644
index 0000000..55b16bd
--- /dev/null
+++ b/winvnc/winvnc.ico
Binary files differ
diff --git a/winvnc/winvnc.rc b/winvnc/winvnc.rc
new file mode 100644
index 0000000..22d0ba9
--- /dev/null
+++ b/winvnc/winvnc.rc
@@ -0,0 +1,254 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 4,0,0,26
+ PRODUCTVERSION 4,0,0,26
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "080904b0"
+        BEGIN
+            VALUE "Comments", "\0"
+            VALUE "CompanyName", "RealVNC Ltd.\0"
+            VALUE "FileDescription", "VNC Server for Win32\0"
+            VALUE "FileVersion", "4.0\0"
+            VALUE "InternalName", "WinVNC 4.0\0"
+            VALUE "LegalCopyright", "Copyright © RealVNC Ltd. 2002-2004\0"
+            VALUE "LegalTrademarks", "RealVNC\0"
+            VALUE "OriginalFilename", "winvnc4.exe\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "VNC Server 4.0\0"
+            VALUE "ProductVersion", "4.0\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x809, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON                ICON    DISCARDABLE     "winvnc.ico"
+IDI_CONNECTED           ICON    DISCARDABLE     "connected.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_TRAY MENU DISCARDABLE 
+BEGIN
+    POPUP "Tray Menu"
+    BEGIN
+        MENUITEM "&Options...",                 ID_OPTIONS
+        MENUITEM SEPARATOR
+        MENUITEM "Add &New Client",             ID_CONNECT
+        MENUITEM "&Disconnect Clients",         ID_DISCONNECT
+        MENUITEM SEPARATOR
+        MENUITEM "&Close VNC Server",           ID_CLOSE
+        MENUITEM "&About...",                   ID_ABOUT
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUT DIALOG DISCARDABLE  0, 0, 249, 92
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | 
+    WS_SYSMENU
+CAPTION "About VNC Server for Windows"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,195,70,47,15
+    ICON            IDI_ICON,IDC_STATIC,7,7,20,20
+    LTEXT           ">appname<",IDC_DESCRIPTION,40,7,125,18
+    LTEXT           ">version<",IDC_VERSION,165,7,77,18
+    LTEXT           ">buildtime<",IDC_BUILDTIME,40,25,202,15
+    LTEXT           ">copyright<",IDC_COPYRIGHT,40,40,202,15
+    LTEXT           "See http://www.realvnc.com for more information on VNC.",
+                    IDC_STATIC,40,55,202,15
+END
+
+IDD_QUERY_CONNECT DIALOG DISCARDABLE  0, 0, 164, 93
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | 
+    WS_SYSMENU
+CAPTION "VNC Server : Accept Connection?"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "&Reject",IDCANCEL,105,72,52,14
+    PUSHBUTTON      "&Accept",IDOK,7,72,53,14
+    RTEXT           "User:",IDC_STATIC,7,10,28,15,SS_CENTERIMAGE
+    RTEXT           "Host:",IDC_STATIC,7,30,28,15,SS_CENTERIMAGE
+    CTEXT           "Seconds until automatic reject:",IDC_STATIC,7,50,113,15,
+                    SS_CENTERIMAGE
+    LTEXT           "-",IDC_QUERY_COUNTDOWN,125,50,32,15,SS_CENTERIMAGE
+    LTEXT           "-",IDC_QUERY_USER,40,10,117,15,SS_CENTERIMAGE
+    LTEXT           "-",IDC_QUERY_HOST,40,30,117,15,SS_CENTERIMAGE
+END
+
+IDD_ADD_NEW_CLIENT DIALOG DISCARDABLE  0, 0, 183, 53
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | 
+    WS_CAPTION | WS_SYSMENU
+CAPTION "VNC Server : Add New Client"
+FONT 8, "MS Sans Serif"
+BEGIN
+    EDITTEXT        IDC_HOST,70,10,105,15,ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "OK",IDOK,70,32,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,125,32,50,14
+    ICON            IDI_ICON,IDC_STATIC,7,10,21,20,SS_REALSIZEIMAGE
+    CONTROL         "Viewer:",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | 
+                    SS_CENTERIMAGE | WS_GROUP,35,10,30,15
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// HTTPFILE
+//
+
+/VNCVIEWER.JAR          HTTPFILE DISCARDABLE    "java\\vncviewer.jar"
+/LOGO150X150.GIF        HTTPFILE DISCARDABLE    "java\\logo150x150.gif"
+/INDEX.VNC              HTTPFILE DISCARDABLE    "java\\index.vnc"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 24
+//
+
+IDR_MANIFEST            24      DISCARDABLE     "winvnc4.exe.manifest"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_QUERY_CONNECT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 157
+        VERTGUIDE, 35
+        VERTGUIDE, 40
+        VERTGUIDE, 60
+        VERTGUIDE, 120
+        VERTGUIDE, 125
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 86
+        HORZGUIDE, 10
+        HORZGUIDE, 25
+        HORZGUIDE, 30
+        HORZGUIDE, 45
+        HORZGUIDE, 50
+        HORZGUIDE, 65
+    END
+
+    IDD_ADD_NEW_CLIENT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 176
+        VERTGUIDE, 35
+        VERTGUIDE, 65
+        VERTGUIDE, 70
+        VERTGUIDE, 120
+        VERTGUIDE, 125
+        VERTGUIDE, 175
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 46
+        HORZGUIDE, 10
+        HORZGUIDE, 25
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/winvnc/winvnc4.exe.manifest b/winvnc/winvnc4.exe.manifest
new file mode 100644
index 0000000..d5a2b87
--- /dev/null
+++ b/winvnc/winvnc4.exe.manifest
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+   version="4.0.0.26"
+   processorArchitecture="X86"
+   name="RealVNC.winvnc4.exe"
+   type="win32"
+/>
+<description>.NET control deployment tool</description>
+<dependency>
+   <dependentAssembly>
+     <assemblyIdentity
+       type="win32"
+       name="Microsoft.Windows.Common-Controls"
+       version="6.0.0.0"
+       processorArchitecture="X86"
+       publicKeyToken="6595b64144ccf1df"
+       language="*"
+     />
+   </dependentAssembly>
+</dependency>
+</assembly>