--- tightvnc-2.8.8-gpl.orig/tvnviewer/ViewerInstance.cpp    2018-06-04 16:52:30.625792300 -0700
+++ tightvnc-2.8.8-gpl/tvnviewer/ViewerInstance.cpp 2018-06-04 16:10:26.240405000 -0700
@@ -27,16 +27,11 @@
 #include "viewer-core/RemoteViewerCore.h"
 #include "viewer-core/FileTransferCapability.h"

-ViewerInstance::ViewerInstance(WindowsApplication *application,
-                               ConnectionData *condata,
+Instance::Instance(            ConnectionData *condata,
                                const ConnectionConfig *conConf)
 : m_conConf(*conConf),
   m_condata(*condata),
   m_socket(0),
-  m_viewerWnd(application,
-              &m_condata,
-              &m_conConf,
-              ViewerConfig::getInstance()->getLogger()),
   m_vncAuthHandler(&m_condata),
   m_viewerCore(ViewerConfig::getInstance()->getLogger())
 {
@@ -44,22 +39,40 @@

 ViewerInstance::ViewerInstance(WindowsApplication *application,
                                ConnectionData *condata,
+                               const ConnectionConfig *conConf)
+
+: Instance   (condata, conConf),
+  m_viewerWnd(application,
+              &m_condata,
+              &m_conConf,
+              ViewerConfig::getInstance()->getLogger())
+{}
+
+Instance::Instance(            ConnectionData *condata,
                                const ConnectionConfig *conConf,
                                SocketIPv4 *socket)
 : m_conConf(*conConf),
   m_condata(*condata),
   m_socket(socket),
+  m_vncAuthHandler(&m_condata),
+  m_viewerCore(ViewerConfig::getInstance()->getLogger())
+{
+}
+
+ViewerInstance::ViewerInstance(WindowsApplication *application,
+                               ConnectionData *condata,
+                               const ConnectionConfig *conConf,
+                               SocketIPv4 *socket)
+: Instance(condata,conConf),
   m_viewerWnd(application,
               &m_condata,
               &m_conConf,
-              ViewerConfig::getInstance()->getLogger()),
-  m_vncAuthHandler(&m_condata),
-  m_viewerCore(ViewerConfig::getInstance()->getLogger())
+              ViewerConfig::getInstance()->getLogger())
 {
 }

-ViewerInstance::~ViewerInstance()
+Instance::~Instance()
 {
   if (m_socket != 0) {
     m_socket->shutdown(SD_BOTH);
@@ -75,7 +88,7 @@
   }
 }

-void ViewerInstance::waitViewer()
+void Instance::waitViewer()
 {
   m_viewerCore.waitTermination();
 }
@@ -95,13 +108,10 @@
   m_viewerWnd.postMessage(ViewerWindow::WM_USER_STOP);
 }

-void ViewerInstance::start()
+
+void Instance::start()
 {
   Logger *logger = ViewerConfig::getInstance()->getLogger();
-  m_viewerWnd.setRemoteViewerCore(&m_viewerCore);
-
-
-  m_viewerWnd.setFileTransfer(&m_fileTransfer);

   m_vncAuthHandler.addAuthCapability(&m_viewerCore);

@@ -112,6 +122,15 @@
     m_viewerCore.enableDispatching(&m_idHolder);
   }

+}
+
+void ViewerInstance::start()
+{
+  m_viewerWnd.setFileTransfer(&m_fileTransfer);
+  m_viewerWnd.setRemoteViewerCore(&m_viewerCore);
+
+  Instance::start();
+
   if (m_socket) {
     m_viewerCore.start(m_socket,
                        &m_viewerWnd, m_conConf.getSharedFlag());
diff -rubN tightvnc-2.8.8-gpl.orig/tvnviewer/ViewerInstance.h tightvnc-2.8.8-gpl/tvnviewer/ViewerInstance.h
--- tightvnc-2.8.8-gpl.orig/tvnviewer/ViewerInstance.h  2018-06-04 16:52:30.631792600 -0700
+++ tightvnc-2.8.8-gpl/tvnviewer/ViewerInstance.h   2018-06-04 16:10:26.240405000 -0700
@@ -31,26 +31,19 @@
 #include "ViewerVncAuthHandler.h"
 #include "viewer-core/DispatchIdProvider.h"

-class ViewerInstance
+class Instance
 {
 public:
-  // creates the viewer instance by using host:port from condata
-  ViewerInstance(WindowsApplication *application,
-                 ConnectionData *condata,
+  Instance(ConnectionData *condata,
                  const ConnectionConfig *conConf);

-  // creates the viewer instance if we have the socket
-  ViewerInstance(WindowsApplication *application,
-                 ConnectionData *condata,
+  Instance(      ConnectionData *condata,
                  const ConnectionConfig *conConf,
                  SocketIPv4 *socket);

-  virtual ~ViewerInstance();
+  virtual ~Instance();

-  bool requiresReconnect() const;
-  bool isStopped() const;
-  void start();
-  void stop();
+  virtual void start();

   // wait while viewer is not terminated
   void waitViewer();
@@ -59,7 +52,6 @@
   ConnectionData m_condata;
   ConnectionConfig m_conConf;

-  ViewerWindow m_viewerWnd;
   RemoteViewerCore m_viewerCore;
   ViewerVncAuthHandler m_vncAuthHandler;
   FileTransferCapability m_fileTransfer;
@@ -67,4 +59,26 @@
   SocketIPv4 *m_socket;
 };

+class ViewerInstance :public Instance
+{
+public:
+  // creates the viewer instance by using host:port from condata
+  ViewerInstance(WindowsApplication *application,
+                 ConnectionData *condata,
+                 const ConnectionConfig *conConf);
+
+  // creates the viewer instance if we have the socket
+  ViewerInstance(WindowsApplication *application,
+                 ConnectionData *condata,
+                 const ConnectionConfig *conConf,
+                 SocketIPv4 *socket);
+
+
+  virtual void start();
+  bool requiresReconnect() const;
+  bool isStopped() const;
+  void stop();
+protected:
+    ViewerWindow m_viewerWnd;
+};
 #endif
diff -rubN tightvnc-2.8.8-gpl.orig/VnCP/VnCP.cpp tightvnc-2.8.8-gpl/VnCP/VnCP.cpp
--- tightvnc-2.8.8-gpl.orig/VnCP/VnCP.cpp   1969-12-31 16:00:00.000000000 -0800
+++ tightvnc-2.8.8-gpl/VnCP/VnCP.cpp    2018-06-04 16:38:57.074259000 -0700
@@ -0,0 +1,281 @@
+
+#include "client-config-lib/ViewerConfig.h"
+#include "client-config-lib/ViewerSettingsManager.h"
+
+#include        "log-writer/FileLogger.h"
+
+#include         "tvnviewer/NamingDefs.h"
+#include         "tvnviewer/ViewerInstance.h"
+
+#include       "viewer-core/FileTransferCapability.h"
+#include       "viewer-core/RemoteViewerCore.h"
+;
+HANDLE connctd, done;int rv(0);
+
+class CmdLnInstance : public ViewerInstance
+{
+    public:
+        CmdLnInstance (ConnectionData *condata,
+            const ConnectionConfig *conConf):ViewerInstance(NULL,condata
+                                                      ,conConf), efti(&m_viewerCore, m_fileTransfer.getCore()),
+            rien(&m_viewerCore, &m_fileTransfer)
+        {
+            m_fileTransfer.setInterface(&efti);
+        }
+
+        virtual void start()
+        {
+            Instance::start();
+
+            if (m_socket) {
+                m_viewerCore.start(m_socket,
+                    &rien, m_conConf.getSharedFlag());
+            }
+            else {
+                StringStorage strHost;
+                m_condata.getReducedHost(&strHost);
+                UINT16 portVal = m_condata.getPort();
+                m_viewerCore.start(strHost.getString(), portVal,
+                    &rien, m_conConf.getSharedFlag());
+            }
+        }
+protected:
+    class SimplestCoreEventsAdapter : public CoreEventsAdapter
+    {
+    public:
+        SimplestCoreEventsAdapter(RemoteViewerCore *  const viewerCore,FileTransferCapability *  const fileTransfer) :m_viewerCore(viewerCore),m_fileTransfer(fileTransfer ){}
+        void onConnected(RfbOutputGate *output)
+        {
+            /* TODO: commonize w/ viewer core ?*/
+
+            // Set output for client-to-server messages in file transfer.
+            m_fileTransfer->setOutput(output);
+
+            // Update list of supported operation for file transfer.
+            vector<UINT32> clientMsgCodes;
+            m_viewerCore->getEnabledClientMsgCapabilities(&clientMsgCodes);
+
+            vector<UINT32> serverMsgCodes;
+            m_viewerCore->getEnabledServerMsgCapabilities(&serverMsgCodes);
+
+            m_fileTransfer->getCore()->updateSupportedOperations(&clientMsgCodes, &serverMsgCodes);
+            if (!SetEvent(connctd))
+            {
+                printf("SetEvent failed (%d)\n", GetLastError());
+                return;
+            }
+        }
+        RemoteViewerCore *  const m_viewerCore;
+        FileTransferCapability *  const m_fileTransfer;
+
+    } rien;
+    class CmdLnFTI :
+        public FileTransferInterface
+    {
+    public:
+        CmdLnFTI(RemoteViewerCore *  const viewerCore, FileTransferCore *core) :m_viewerCore(viewerCore), FileTransferInterface(core) {}
+
+        virtual int onFtTargetFileExists(FileInfo *sourceFileInfo,
+            FileInfo *targetFileInfo,
+            const TCHAR *pathToTargetFile) {
+            return CopyFileEventListener::TFE_OVERWRITE
+                ;
+        }
+        // Progress is in interval [0.0, 1.0].
+        virtual void setProgress(double progress) {}
+
+        //
+        // This function inform user about error.
+        // This function must be is not blocking, otherwise it may happen deadlock.
+        //
+        virtual void onFtOpError(const TCHAR *message) {
+            if (!SetEvent(done))
+            {
+                printf("SetEvent failed (%d)\n", GetLastError());
+                return;
+            }
+
+            printf("%s\n", message); rv = 1;
+        }
+
+        //
+        // This function inform user additional information.
+        // This function must be is not blocking, otherwise it may happen deadlock.
+        //
+        virtual void onFtOpInfo(const TCHAR *message) {
+            printf("%s\n", message);
+        }
+        virtual void onFtOpStarted() {}
+        virtual void onFtOpFinished(int state, int result) {
+            if (!SetEvent(done))
+            {
+                printf("SetEvent failed (%d)\n", GetLastError());
+                return;
+            }
+
+        }
+
+        //
+        // filetransfer's operation is finished. Need update of control
+        //
+        virtual void setNothingState() {}
+
+        //
+        // Called if local file list is updated
+        //
+        virtual void onRefreshLocalFileList() {}
+
+        // Called if remote file list is updated
+        virtual void onRefreshRemoteFileList() {}
+
+        //
+        // Shows error message and throws exception
+        //
+        RemoteViewerCore *m_viewerCore;
+
+        virtual void raise(Exception &ex) {};
+
+    } efti;
+
+public:
+    void download(FileInfo *filesInfo, int n_files, char const *pathToTargetRoot, char const *pathToSourceRoot)
+    {
+        TCHAR pathTgt[MAX_PATH], pathSrc[MAX_PATH];
+        swprintf_s(pathTgt, L"%S", pathToTargetRoot);
+        swprintf_s(pathSrc, L"%S", pathToSourceRoot);
+
+        m_fileTransfer.getCore()->downloadOperation(filesInfo, n_files,
+            pathTgt, pathSrc);
+    }
+
+    void upload(FileInfo *filesInfo, int n_files, char const *pathToSourceRoot, char const *pathToTargetRoot)
+    {
+        TCHAR pathSrc[MAX_PATH], pathTgt[MAX_PATH];
+
+        swprintf_s(pathSrc, L"%S", pathToSourceRoot);
+        swprintf_s(pathTgt, L"%S", pathToTargetRoot);
+
+        m_fileTransfer.getCore()->uploadOperation(filesInfo, n_files, pathSrc,
+            pathTgt);
+    }
+};
+
+int
+main(int argc, char  *argv[])
+{
+    ViewerSettingsManager::initInstance(RegistryPaths::VIEWER_PATH);
+    SettingsManager *sm = ViewerSettingsManager::getInstance();
+
+    int n_files = argc - 6 /* Program name, host:port, pass, command (upload, ul, UL or download, dl or DL), local folder, remote folder */;
+
+    if (n_files < 1)
+    {
+        printf("\nSyntax:\n\n\tvncp [host:port] [password] [command (`upload', `ul' or `UL', or `download', `dl' or `DL')] [local folder] [remote folder] [file] <other files> \n");
+
+        exit(1);
+    }
+    
+    ViewerConfig config(RegistryPaths::VIEWER_PATH);
+    config.loadFromStorage(sm);
+
+    try {
+        config.initLog(LogNames::LOG_DIR_NAME, LogNames::VIEWER_LOG_FILE_STUB_NAME);
+    }
+    catch (...) {
+    }
+
+    RemoteViewerCore m_viewerCore(config.getLogger());
+
+    FileInfo *filesInfo = new FileInfo[n_files];
+    for(int i = 0; n_files != i;++i)
+    {
+        TCHAR path[MAX_PATH], name[MAX_PATH];
+        swprintf_s(path, L"%S", argv[5]);
+        swprintf_s(name, L"%S", argv[6 + i]);
+        File file(path, name);
+
+        filesInfo[i]=&file;
+    }
+    ConnectionData condata;
+    TCHAR lhost[MAX_PATH], lpass[MAX_PATH];
+    swprintf_s(lhost, L"%S", argv[1]);
+    swprintf_s(lpass, L"%S", argv[2]);
+
+    StringStorage const host ( lhost );
+    StringStorage const pass ( lpass );
+
+    condata.setHost         (&host);
+    condata.setPlainPassword(&pass);
+
+    /*);
+    */ConnectionConfig conConf;
+    connctd = CreateEvent(
+        NULL,               // default security attributes
+        TRUE,               // manual-reset event
+        FALSE,              // initial state is nonsignaled
+        TEXT("connctd")  // object name
+    );
+
+    done = CreateEvent(
+        NULL,               // default security attributes
+        TRUE,               // manual-reset event
+        FALSE,              // initial state is nonsignaled
+        TEXT("done")  // object name
+    );
+
+    CmdLnInstance *inst = new CmdLnInstance( &condata, &conConf);
+    inst->start();
+
+    DWORD dwWaitResult = WaitForSingleObject(
+        connctd, // event handle
+        INFINITE);    // indefinite wait
+    switch (dwWaitResult)
+    {
+        // Event object was signaled
+    case WAIT_OBJECT_0:
+        //
+        // TODO: Read from the shared buffer
+        //
+        printf("Thread %d reading from buffer\n",
+            GetCurrentThreadId());
+        break;
+
+        // An error occurred
+    default:
+        printf("Wait error (%d)\n", GetLastError());
+        return 0;
+    }
+
+
+    if(0==(stricmp("UL", argv[3]))||0==(stricmp("upload", argv[3])))
+        inst->upload  (filesInfo, n_files, argv[4]
+                                         , argv[5]);
+    else
+        inst->download(filesInfo, n_files, argv[4]
+                                         , argv[5]);
+
+     dwWaitResult = WaitForSingleObject(
+        done,         // event handle
+        INFINITE);    // indefinite wait
+
+    switch (dwWaitResult)
+    {
+        // Event object was signaled
+    case WAIT_OBJECT_0:
+        //
+        // TODO: Read from the shared buffer
+        //
+        printf("Thread %d reading from buffer\n",
+            GetCurrentThreadId());
+        break;
+
+        // An error occurred
+    default:
+        printf("Wait error (%d)\n", GetLastError());
+        return 0;
+    }
+
+
+
+    return rv;
+}
