2010-03-08 14:49:45 +00:00
|
|
|
// Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
|
|
|
|
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
|
|
|
//
|
|
|
|
// This file is part of the VNC system.
|
|
|
|
//
|
|
|
|
// The VNC system 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 program 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 program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
|
// USA.
|
|
|
|
//
|
|
|
|
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
|
|
|
|
//
|
|
|
|
// If the source code for the VNC system is not available from the place
|
|
|
|
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
|
|
|
|
// the authors on vnc@uk.research.att.com for information on obtaining it.
|
|
|
|
|
|
|
|
|
|
|
|
// vncServer.cpp
|
|
|
|
|
|
|
|
// vncServer class implementation
|
|
|
|
|
|
|
|
// Includes
|
|
|
|
#include "stdhdrs.h"
|
|
|
|
#include <omnithread.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <lmcons.h>
|
|
|
|
|
|
|
|
// Custom
|
|
|
|
#include "vncServer.h"
|
|
|
|
#include "vncSockConnect.h"
|
|
|
|
#include "vncCorbaConnect.h"
|
|
|
|
#include "vncClient.h"
|
|
|
|
#include "vncService.h"
|
|
|
|
|
|
|
|
// Constructor/destructor
|
|
|
|
vncServer::vncServer()
|
|
|
|
{
|
|
|
|
ResetPasswordsValidityInfo();
|
|
|
|
|
|
|
|
// Initialise some important stuffs...
|
|
|
|
m_socketConn = NULL;
|
|
|
|
m_corbaConn = NULL;
|
|
|
|
//m_httpConn = NULL;
|
|
|
|
m_desktop = NULL;
|
2010-03-24 00:00:05 +00:00
|
|
|
m_name = NULL;
|
|
|
|
SetName("");
|
2010-03-08 14:49:45 +00:00
|
|
|
m_port = DISPLAY_TO_PORT(0);
|
|
|
|
m_port_http = DISPLAY_TO_HPORT(0);
|
|
|
|
m_autoportselect = TRUE;
|
|
|
|
m_passwd_required = FALSE;
|
|
|
|
m_beepConnect = FALSE;
|
|
|
|
m_beepDisconnect = FALSE;
|
|
|
|
m_auth_hosts = 0;
|
|
|
|
m_blacklist = 0;
|
2010-03-24 00:00:05 +00:00
|
|
|
//{
|
|
|
|
// vncPasswd::FromClear clearPWD;
|
|
|
|
memcpy(m_password, "", MAXPWLEN);
|
2010-03-08 14:49:45 +00:00
|
|
|
m_password_set = FALSE;
|
2010-03-24 00:00:05 +00:00
|
|
|
memcpy(m_password_viewonly, "", MAXPWLEN);
|
2010-03-08 14:49:45 +00:00
|
|
|
m_password_viewonly_set = FALSE;
|
2010-03-24 00:00:05 +00:00
|
|
|
//}
|
2010-03-08 14:49:45 +00:00
|
|
|
m_querysetting = 2;
|
|
|
|
m_querytimeout = 10;
|
|
|
|
m_queryaccept = FALSE;
|
|
|
|
m_queryallownopass = FALSE;
|
|
|
|
|
|
|
|
// Autolock settings
|
|
|
|
m_lock_on_exit = 0;
|
|
|
|
|
|
|
|
// Set the polling mode options
|
|
|
|
m_poll_fullscreen = TRUE;
|
|
|
|
m_poll_foreground = TRUE;
|
|
|
|
m_poll_undercursor = TRUE;
|
|
|
|
|
|
|
|
m_poll_oneventonly = FALSE;
|
|
|
|
m_poll_consoleonly = FALSE;
|
|
|
|
|
|
|
|
m_dont_set_hooks = FALSE;
|
|
|
|
m_dont_use_driver = FALSE;
|
|
|
|
m_driver_direct_access_en = TRUE;
|
|
|
|
|
|
|
|
// General options
|
|
|
|
m_loopbackOnly = TRUE;
|
|
|
|
m_disableTrayIcon = TRUE;
|
|
|
|
m_loopback_allowed = TRUE;
|
|
|
|
m_httpd_enabled = FALSE;
|
|
|
|
m_httpd_params_enabled = FALSE;
|
|
|
|
m_lock_on_exit = 0;
|
|
|
|
m_connect_pri = 0;
|
|
|
|
|
|
|
|
// Set the input options
|
|
|
|
m_enable_remote_inputs = TRUE;
|
|
|
|
m_disable_local_inputs = FALSE;
|
|
|
|
|
|
|
|
// Clear the client mapping table
|
|
|
|
for (int x=0; x<MAX_CLIENTS; x++)
|
|
|
|
m_clientmap[x] = NULL;
|
|
|
|
m_nextid = 0;
|
|
|
|
|
|
|
|
// Signal set when a client quits
|
|
|
|
m_clientquitsig = new omni_condition(&m_clientsLock);
|
|
|
|
m_clients_disabled = FALSE;
|
|
|
|
m_local_input_priority = FALSE;
|
|
|
|
|
|
|
|
m_full_screen = TRUE;
|
|
|
|
m_WindowShared= FALSE;
|
|
|
|
m_hwndShared = NULL;
|
|
|
|
m_screen_area = FALSE;
|
|
|
|
m_primary_display_only_shared = FALSE;
|
|
|
|
m_disable_time = 3;
|
|
|
|
SetSharedRect(GetScreenRect());
|
|
|
|
SetPollingCycle(300);
|
|
|
|
PollingCycleChanged(false);
|
|
|
|
m_cursor_pos.x = 0;
|
|
|
|
m_cursor_pos.y = 0;
|
|
|
|
|
|
|
|
// initialize
|
|
|
|
m_enable_file_transfers = FALSE;
|
|
|
|
m_remove_wallpaper = FALSE;
|
|
|
|
m_blank_screen = FALSE;
|
|
|
|
|
|
|
|
#ifdef HORIZONLIVE
|
|
|
|
m_full_screen = FALSE;
|
|
|
|
m_WindowShared= TRUE;
|
|
|
|
m_local_input_priority = TRUE;
|
|
|
|
m_remote_mouse = 1;
|
|
|
|
m_remote_keyboard = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_wallpaper_wait = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vncServer::~vncServer()
|
|
|
|
{
|
|
|
|
// If there is a socket_conn object then delete it
|
|
|
|
if (m_socketConn != NULL)
|
|
|
|
{
|
|
|
|
delete m_socketConn;
|
|
|
|
m_socketConn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_corbaConn != NULL)
|
|
|
|
{
|
|
|
|
delete m_corbaConn;
|
|
|
|
m_corbaConn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*if (m_httpConn != NULL)
|
|
|
|
{
|
|
|
|
delete m_httpConn;
|
|
|
|
m_httpConn = NULL;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
// Remove any active clients!
|
|
|
|
KillAuthClients();
|
|
|
|
KillUnauthClients();
|
|
|
|
|
|
|
|
// Wait for all the clients to die
|
|
|
|
WaitUntilAuthEmpty();
|
|
|
|
WaitUntilUnauthEmpty();
|
|
|
|
|
|
|
|
// Don't free the desktop until no KillClient is likely to free it
|
|
|
|
{ omni_mutex_lock l(m_desktopLock);
|
|
|
|
|
|
|
|
if (m_desktop != NULL)
|
|
|
|
{
|
|
|
|
delete m_desktop;
|
|
|
|
m_desktop = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't free the authhosts string until no more connections are possible
|
|
|
|
if (m_auth_hosts != 0)
|
|
|
|
{
|
|
|
|
free(m_auth_hosts);
|
|
|
|
m_auth_hosts = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_name != NULL)
|
|
|
|
{
|
|
|
|
free(m_name);
|
|
|
|
m_name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_clientquitsig != NULL)
|
|
|
|
{
|
|
|
|
delete m_clientquitsig;
|
|
|
|
m_clientquitsig = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Client handling functions
|
|
|
|
void
|
|
|
|
vncServer::DisableClients(BOOL state)
|
|
|
|
{
|
|
|
|
m_clients_disabled = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::ClientsDisabled()
|
|
|
|
{
|
|
|
|
return m_clients_disabled;
|
|
|
|
}
|
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
vncClientId vncServer::AddClient( AGENT_CTX * lpAgentContext )
|
2010-03-08 14:49:45 +00:00
|
|
|
{
|
2010-03-24 00:00:05 +00:00
|
|
|
vncClient *client = NULL;
|
|
|
|
VSocket * socket = NULL;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
socket = new VSocket( &lpAgentContext->info, lpAgentContext->hCloseEvent );
|
|
|
|
|
2010-03-08 14:49:45 +00:00
|
|
|
// Try to allocate a client id...
|
|
|
|
vncClientId clientid = m_nextid;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
clientid = (clientid+1) % MAX_CLIENTS;
|
|
|
|
if (clientid == m_nextid)
|
|
|
|
{
|
|
|
|
delete socket;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (m_clientmap[clientid] != NULL);
|
|
|
|
|
|
|
|
// Create a new client and add it to the relevant client list
|
|
|
|
client = new vncClient();
|
|
|
|
if (client == NULL) {
|
|
|
|
delete socket;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the client's settings
|
2010-03-24 00:00:05 +00:00
|
|
|
client->EnableKeyboard(TRUE && m_enable_remote_inputs);
|
|
|
|
client->EnablePointer(TRUE && m_enable_remote_inputs);
|
2010-03-08 14:49:45 +00:00
|
|
|
|
|
|
|
// Start the client
|
2010-03-24 00:00:05 +00:00
|
|
|
if (!client->Init(this, socket, TRUE, TRUE, clientid, lpAgentContext ))
|
2010-03-08 14:49:45 +00:00
|
|
|
{
|
|
|
|
// The client will delete the socket for us...
|
|
|
|
delete client;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_clientmap[clientid] = client;
|
|
|
|
|
|
|
|
// Add the client to unauth the client list
|
|
|
|
m_unauthClients.push_back(clientid);
|
|
|
|
|
|
|
|
// Notify anyone interested about this event
|
|
|
|
//DoNotify(WM_SRV_CLIENT_CONNECT, 0, 0);
|
|
|
|
|
|
|
|
return clientid;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::Authenticated(vncClientId clientid)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
BOOL authok = TRUE;
|
|
|
|
|
|
|
|
omni_mutex_lock l1(m_desktopLock);
|
|
|
|
omni_mutex_lock l2(m_clientsLock);
|
|
|
|
|
|
|
|
// Search the unauthenticated client list
|
|
|
|
for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Is this the right client?
|
|
|
|
if ((*i) == clientid)
|
|
|
|
{
|
|
|
|
vncClient *client = GetClient(clientid);
|
|
|
|
|
|
|
|
// Yes, so remove the client and add it to the auth list
|
|
|
|
m_unauthClients.erase(i);
|
|
|
|
|
|
|
|
// Create the screen handler if necessary
|
|
|
|
if (m_desktop == NULL)
|
|
|
|
{
|
|
|
|
if (RemoveWallpaperEnabled()) {
|
|
|
|
m_wallpaper_wait = TRUE;
|
|
|
|
//DoNotify(WM_SRV_CLIENT_HIDEWALLPAPER, 0, 0);
|
|
|
|
}
|
|
|
|
m_desktop = new vncDesktop();
|
|
|
|
if (m_desktop == NULL)
|
|
|
|
{
|
|
|
|
client->Kill();
|
|
|
|
authok = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!m_desktop->Init(this))
|
|
|
|
{
|
|
|
|
|
|
|
|
client->Kill();
|
|
|
|
authok = FALSE;
|
|
|
|
|
|
|
|
delete m_desktop;
|
|
|
|
m_desktop = NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a buffer object for this client
|
|
|
|
vncBuffer *buffer = new vncBuffer(m_desktop);
|
|
|
|
if (buffer == NULL)
|
|
|
|
{
|
|
|
|
client->Kill();
|
|
|
|
authok = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tell the client about this new buffer
|
|
|
|
client->SetBuffer(buffer);
|
|
|
|
|
|
|
|
// Add the client to the auth list
|
|
|
|
m_authClients.push_back(clientid);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify anyone interested of this event
|
|
|
|
//DoNotify(WM_SRV_CLIENT_AUTHENTICATED, 0, 0);
|
|
|
|
|
|
|
|
// If so configured, beep to indicate the new connection is
|
|
|
|
// present.
|
|
|
|
if (authok && GetBeepConnect())
|
|
|
|
{
|
|
|
|
MessageBeep(MB_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return authok;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::KillClient(vncClientId clientid)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
BOOL done = FALSE;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Find the client in one of the two lists
|
|
|
|
for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Is this the right client?
|
|
|
|
if ((*i) == clientid)
|
|
|
|
{
|
|
|
|
// Ask the client to die
|
|
|
|
vncClient *client = GetClient(clientid);
|
|
|
|
client->Kill();
|
|
|
|
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Is this the right client?
|
|
|
|
if ((*i) == clientid)
|
|
|
|
{
|
|
|
|
// Yes, so kill it
|
|
|
|
vncClient *client = GetClient(clientid);
|
|
|
|
client->Kill();
|
|
|
|
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::KillAuthClients()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Tell all the authorised clients to die!
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Kill the client
|
|
|
|
GetClient(*i)->Kill();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::KillUnauthClients()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Tell all the authorised clients to die!
|
|
|
|
for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Kill the client
|
|
|
|
GetClient(*i)->Kill();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
vncServer::AuthClientCount()
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
return m_authClients.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
vncServer::UnauthClientCount()
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
return m_unauthClients.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::WaitUntilAuthEmpty()
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Wait for all the clients to exit
|
|
|
|
while (!m_authClients.empty())
|
|
|
|
{
|
|
|
|
// Wait for a client to quit
|
|
|
|
m_clientquitsig->wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::WaitUntilUnauthEmpty()
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Wait for all the clients to exit
|
|
|
|
while (!m_unauthClients.empty())
|
|
|
|
{
|
|
|
|
// Wait for a client to quit
|
|
|
|
m_clientquitsig->wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::RemoteEventReceived()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
BOOL result = FALSE;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Iterate over the authorised clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
result = result || GetClient(*i)->RemoteEventReceived();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Client info retrieval/setup
|
|
|
|
vncClient*
|
|
|
|
vncServer::GetClient(vncClientId clientid)
|
|
|
|
{
|
|
|
|
if ((clientid >= 0) && (clientid < MAX_CLIENTS))
|
|
|
|
return m_clientmap[clientid];
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vncClientList
|
|
|
|
vncServer::ClientList()
|
|
|
|
{
|
|
|
|
vncClientList clients;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
clients = m_authClients;
|
|
|
|
|
|
|
|
return clients;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::BlockRemoteInput(BOOL block)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
vncClientList::iterator i;
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
GetClient(*i)->BlockInput(block);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char*
|
|
|
|
vncServer::GetClientName(vncClientId clientid)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
vncClient *client = GetClient(clientid);
|
|
|
|
if (client != NULL)
|
|
|
|
return client->GetClientName();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveClient should ONLY EVER be used by the client to remove itself.
|
|
|
|
void
|
|
|
|
vncServer::RemoveClient(vncClientId clientid)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
BOOL done = FALSE;
|
|
|
|
|
|
|
|
omni_mutex_lock l1(m_desktopLock);
|
|
|
|
{ omni_mutex_lock l2(m_clientsLock);
|
|
|
|
|
|
|
|
// Find the client in one of the two lists
|
|
|
|
for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Is this the right client?
|
|
|
|
if ((*i) == clientid)
|
|
|
|
{
|
|
|
|
// Yes, so remove the client and kill it
|
|
|
|
m_unauthClients.erase(i);
|
|
|
|
m_clientmap[clientid] = NULL;
|
|
|
|
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Is this the right client?
|
|
|
|
if ((*i) == clientid)
|
|
|
|
{
|
|
|
|
// Yes, so remove the client and kill it
|
|
|
|
m_authClients.erase(i);
|
|
|
|
m_clientmap[clientid] = NULL;
|
|
|
|
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Signal that a client has quit
|
|
|
|
m_clientquitsig->signal();
|
|
|
|
|
|
|
|
} // Unlock the clientLock
|
|
|
|
|
|
|
|
// If so configured, beep to indicate the old connection is
|
|
|
|
// gone.
|
|
|
|
if (GetBeepDisconnect())
|
|
|
|
{
|
|
|
|
MessageBeep(MB_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Are there any authorised clients connected?
|
|
|
|
if (m_authClients.empty() && (m_desktop != NULL))
|
|
|
|
{
|
|
|
|
// Are there locksettings set?
|
|
|
|
if (LockSettings() == 1)
|
|
|
|
{
|
|
|
|
// Yes - lock the machine on disconnect!
|
|
|
|
vncService::LockWorkstation();
|
|
|
|
} else if (LockSettings() > 1)
|
|
|
|
{
|
|
|
|
char username[UNLEN+1];
|
|
|
|
|
|
|
|
vncService::CurrentUser((char *)&username, sizeof(username));
|
|
|
|
if (strcmp(username, "") != 0)
|
|
|
|
{
|
|
|
|
// Yes - force a user logoff on disconnect!
|
|
|
|
ExitWindowsEx(EWX_LOGOFF, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the screen server
|
|
|
|
delete m_desktop;
|
|
|
|
m_desktop = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify anyone interested of the change
|
|
|
|
//DoNotify(WM_SRV_CLIENT_DISCONNECT, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTIFICATION HANDLING!
|
|
|
|
|
|
|
|
// Connect/disconnect notification
|
|
|
|
BOOL
|
|
|
|
vncServer::AddNotify(HWND hwnd)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Add the window handle to the list
|
|
|
|
m_notifyList.push_front(hwnd);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::RemNotify(HWND hwnd)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Remove the window handle from the list
|
|
|
|
vncNotifyList::iterator i;
|
|
|
|
for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++)
|
|
|
|
{
|
|
|
|
if ((*i) == hwnd)
|
|
|
|
{
|
|
|
|
// Found the handle, so remove it
|
|
|
|
m_notifyList.erase(i);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a notification message
|
|
|
|
void
|
|
|
|
vncServer::DoNotify(UINT message, WPARAM wparam, LPARAM lparam)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Send the given message to all the notification windows
|
|
|
|
vncNotifyList::iterator i;
|
|
|
|
for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++)
|
|
|
|
{
|
|
|
|
PostMessage((*i), message, wparam, lparam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Client->Desktop update signalling
|
|
|
|
void
|
|
|
|
vncServer::RequestUpdate()
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_desktopLock);
|
|
|
|
if (m_desktop != NULL)
|
|
|
|
{
|
|
|
|
m_desktop->RequestUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update handling
|
|
|
|
void
|
|
|
|
vncServer::TriggerUpdate()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->TriggerUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateRect(RECT &rect)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->UpdateRect(rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateRegion(vncRegion ®ion)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->UpdateRegion(region);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::CopyRect(RECT &dest, POINT &source)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->CopyRect(dest, source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateMouse()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this mouse update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->UpdateMouse();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateClipText(LPSTR text)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->UpdateClipText(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdatePalette()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post this update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->UpdatePalette();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateLocalClipText(LPSTR text)
|
|
|
|
{
|
|
|
|
omni_mutex_lock l(m_desktopLock);
|
|
|
|
|
|
|
|
if (m_desktop != NULL)
|
|
|
|
m_desktop->SetClipText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Changing hook settings
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::DontSetHooks(BOOL enable)
|
|
|
|
{
|
|
|
|
m_dont_set_hooks = enable;
|
|
|
|
if (m_desktop != NULL)
|
|
|
|
m_desktop->TryActivateHooks();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Changing use driver settings
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::DontUseDriver(BOOL enable)
|
|
|
|
{
|
|
|
|
m_dont_use_driver = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::DriverDirectAccess(BOOL enable)
|
|
|
|
{
|
|
|
|
m_driver_direct_access_en = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name and port number handling
|
|
|
|
void
|
|
|
|
vncServer::SetName(const char * name)
|
|
|
|
{
|
|
|
|
// Set the name of the desktop
|
|
|
|
if (m_name != NULL)
|
|
|
|
{
|
|
|
|
free(m_name);
|
|
|
|
m_name = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_name = strdup(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetPorts(const UINT port_rfb, const UINT port_http)
|
|
|
|
{
|
|
|
|
if (m_port != port_rfb || m_port_http != port_http) {
|
|
|
|
// Set port numbers to use
|
|
|
|
m_port = port_rfb;
|
|
|
|
m_port_http = port_http;
|
|
|
|
|
|
|
|
// If there is already a listening socket then close and re-open it...
|
|
|
|
BOOL socketon = SockConnected();
|
|
|
|
SockConnect(FALSE);
|
|
|
|
if (socketon)
|
|
|
|
SockConnect(TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetPassword(BOOL activate, const char *passwd)
|
|
|
|
{
|
|
|
|
ResetPasswordsValidityInfo();
|
|
|
|
m_password_set = activate;
|
|
|
|
memcpy(m_password, passwd, MAXPWLEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::GetPassword(char *passwd)
|
|
|
|
{
|
|
|
|
memcpy(passwd, m_password, MAXPWLEN);
|
|
|
|
return m_password_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetPasswordViewOnly(BOOL activate, const char *passwd)
|
|
|
|
{
|
|
|
|
ResetPasswordsValidityInfo();
|
|
|
|
m_password_viewonly_set = activate;
|
|
|
|
memcpy(m_password_viewonly, passwd, MAXPWLEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::GetPasswordViewOnly(char *passwd)
|
|
|
|
{
|
|
|
|
memcpy(passwd, m_password_viewonly, MAXPWLEN);
|
|
|
|
return m_password_viewonly_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::ValidPasswordsSet()
|
|
|
|
{
|
|
|
|
if (!m_valid_passwords_set_cached) {
|
|
|
|
m_valid_passwords_set = ValidPasswordsSet_nocache();
|
|
|
|
m_valid_passwords_set_cached = TRUE;
|
|
|
|
}
|
|
|
|
return m_valid_passwords_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::ValidPasswordsSet_nocache()
|
|
|
|
{
|
|
|
|
char passwd1[MAXPWLEN];
|
|
|
|
char passwd2[MAXPWLEN];
|
|
|
|
BOOL set1 = GetPassword(passwd1);
|
|
|
|
BOOL set2 = GetPasswordViewOnly(passwd2);
|
|
|
|
if (!set1 && !set2)
|
|
|
|
return FALSE; // no passwords set, connections impossible
|
|
|
|
|
|
|
|
if (!AuthRequired())
|
|
|
|
return TRUE; // passwords may be empty, but we allow that
|
|
|
|
|
|
|
|
vncPasswd::ToText plain1(passwd1);
|
|
|
|
vncPasswd::ToText plain2(passwd2);
|
|
|
|
BOOL empty1 = !set1 || (strlen(plain1) == 0);
|
|
|
|
BOOL empty2 = !set2 || (strlen(plain2) == 0);
|
|
|
|
if (empty1 && empty2)
|
|
|
|
return FALSE; // both passwords empty or unset, not allowed
|
|
|
|
|
|
|
|
return TRUE; // at least one non-empty password
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::ValidPasswordsEmpty()
|
|
|
|
{
|
|
|
|
if (!m_valid_passwords_empty_cached) {
|
|
|
|
m_valid_passwords_empty = ValidPasswordsEmpty_nocache();
|
|
|
|
m_valid_passwords_empty_cached = TRUE;
|
|
|
|
}
|
|
|
|
return m_valid_passwords_empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::ValidPasswordsEmpty_nocache()
|
|
|
|
{
|
|
|
|
if (AuthRequired())
|
|
|
|
return FALSE; // empty passwords disallowed, always fail
|
|
|
|
|
|
|
|
char passwd1[MAXPWLEN];
|
|
|
|
char passwd2[MAXPWLEN];
|
|
|
|
BOOL set1 = GetPassword(passwd1);
|
|
|
|
BOOL set2 = GetPasswordViewOnly(passwd2);
|
|
|
|
if (!set1 && !set2)
|
|
|
|
return FALSE; // no passwords set, connections impossible
|
|
|
|
|
|
|
|
vncPasswd::ToText plain1(passwd1);
|
|
|
|
vncPasswd::ToText plain2(passwd2);
|
|
|
|
BOOL empty1 = !set1 || (strlen(plain1) == 0);
|
|
|
|
BOOL empty2 = !set2 || (strlen(plain2) == 0);
|
|
|
|
if (empty1 && empty2)
|
|
|
|
return TRUE; // there are no passwords that are non-empty
|
|
|
|
|
|
|
|
return FALSE; // at least one non-empty password
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remote input handling
|
|
|
|
void
|
|
|
|
vncServer::EnableRemoteInputs(BOOL enable)
|
|
|
|
{
|
|
|
|
m_enable_remote_inputs = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL vncServer::RemoteInputsEnabled()
|
|
|
|
{
|
|
|
|
return m_enable_remote_inputs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Local input handling
|
|
|
|
void
|
|
|
|
vncServer::DisableLocalInputs(BOOL disable)
|
|
|
|
{
|
|
|
|
if ( m_disable_local_inputs != disable )
|
|
|
|
{
|
|
|
|
m_disable_local_inputs = disable;
|
|
|
|
if ( AuthClientCount() != 0 )
|
|
|
|
m_desktop->SetLocalInputDisableHook(disable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL vncServer::LocalInputsDisabled()
|
|
|
|
{
|
|
|
|
return m_disable_local_inputs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vncServer::LocalInputPriority(BOOL disable)
|
|
|
|
{
|
|
|
|
if( m_local_input_priority != disable )
|
|
|
|
{
|
|
|
|
m_local_input_priority = disable;
|
|
|
|
m_remote_mouse = 0;
|
|
|
|
m_remote_keyboard = 0;
|
|
|
|
if ( AuthClientCount() != 0 )
|
|
|
|
m_desktop->SetLocalInputPriorityHook(disable);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Socket connection handling
|
|
|
|
BOOL
|
|
|
|
vncServer::SockConnect(BOOL On)
|
|
|
|
{
|
|
|
|
// Are we being asked to switch socket connects on or off?
|
|
|
|
if (On)
|
|
|
|
{
|
|
|
|
// Is there a listening socket?
|
|
|
|
if (m_socketConn == NULL)
|
|
|
|
{
|
|
|
|
m_socketConn = new vncSockConnect();
|
|
|
|
if (m_socketConn == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
// Are we to use automatic port selection?
|
|
|
|
if (m_autoportselect)
|
|
|
|
{
|
|
|
|
BOOL ok = FALSE;
|
|
|
|
|
|
|
|
// Yes, so cycle through the ports, looking for a free one!
|
|
|
|
for (int i = 0; i < 99; i++)
|
|
|
|
{
|
|
|
|
m_port = DISPLAY_TO_PORT(i);
|
|
|
|
m_port_http = DISPLAY_TO_HPORT(i);
|
|
|
|
|
|
|
|
// Attempt to connect to the port
|
|
|
|
VSocket tempsock;
|
|
|
|
if (tempsock.Create())
|
|
|
|
{
|
|
|
|
if (!tempsock.Connect("localhost", m_port))
|
|
|
|
{
|
|
|
|
// Couldn't connect, so this port is probably usable!
|
|
|
|
if (m_socketConn->Init(this, m_port))
|
|
|
|
{
|
|
|
|
ok = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
delete m_socketConn;
|
|
|
|
m_socketConn = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
// No autoportselect
|
|
|
|
if (!m_socketConn->Init(this, m_port))
|
|
|
|
{
|
|
|
|
delete m_socketConn;
|
|
|
|
m_socketConn = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now let's start the HTTP connection stuff
|
|
|
|
/*if (m_httpConn == NULL && m_httpd_enabled && m_port_http != m_port) {
|
|
|
|
m_httpConn = new vncHTTPConnect;
|
|
|
|
if (m_httpConn != NULL) {
|
|
|
|
// Start up the HTTP server
|
|
|
|
if (!m_httpConn->Init(this, m_port_http,
|
|
|
|
m_httpd_params_enabled)) {
|
|
|
|
delete m_httpConn;
|
|
|
|
m_httpConn = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// *** JNW - Trying to fix up a lock-up when the listening socket closes
|
|
|
|
#ifndef HORIZONLIVE
|
|
|
|
KillAuthClients();
|
|
|
|
KillUnauthClients();
|
|
|
|
WaitUntilAuthEmpty();
|
|
|
|
WaitUntilUnauthEmpty();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Is there a listening socket?
|
|
|
|
if (m_socketConn != NULL)
|
|
|
|
{
|
|
|
|
// Close the socket
|
|
|
|
delete m_socketConn;
|
|
|
|
m_socketConn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is there an HTTP socket active?
|
|
|
|
/*if (m_httpConn != NULL)
|
|
|
|
{
|
|
|
|
// Close the socket
|
|
|
|
delete m_httpConn;
|
|
|
|
m_httpConn = NULL;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::SockConnected()
|
|
|
|
{
|
|
|
|
return m_socketConn != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::SetHttpdEnabled(BOOL enable_httpd, BOOL enable_params)
|
|
|
|
{
|
|
|
|
if (enable_httpd != m_httpd_enabled) {
|
|
|
|
m_httpd_enabled = enable_httpd;
|
|
|
|
m_httpd_params_enabled = enable_params;
|
|
|
|
BOOL socketConn = SockConnected();
|
|
|
|
SockConnect(FALSE);
|
|
|
|
SockConnect(socketConn);
|
|
|
|
} else {
|
|
|
|
if (enable_params != m_httpd_params_enabled) {
|
|
|
|
m_httpd_params_enabled = enable_params;
|
|
|
|
if (SockConnected()) {
|
|
|
|
SockConnect(FALSE);
|
|
|
|
SockConnect(TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::SetLoopbackOnly(BOOL loopbackOnly)
|
|
|
|
{
|
|
|
|
if (loopbackOnly != m_loopbackOnly)
|
|
|
|
{
|
|
|
|
m_loopbackOnly = loopbackOnly;
|
|
|
|
BOOL socketConn = SockConnected();
|
|
|
|
SockConnect(FALSE);
|
|
|
|
SockConnect(socketConn);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::LoopbackOnly()
|
|
|
|
{
|
|
|
|
return m_loopbackOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::SetDisableTrayIcon(BOOL disableTrayIcon)
|
|
|
|
{
|
|
|
|
if (disableTrayIcon != m_disableTrayIcon)
|
|
|
|
{
|
|
|
|
m_disableTrayIcon = disableTrayIcon;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::GetDisableTrayIcon()
|
|
|
|
{
|
|
|
|
return m_disableTrayIcon;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CORBA connection handling
|
|
|
|
BOOL
|
|
|
|
vncServer::CORBAConnect(BOOL On)
|
|
|
|
{
|
|
|
|
// Are we being asked to switch CORBA connects on or off?
|
|
|
|
if (On)
|
|
|
|
{
|
|
|
|
// Is there a CORBA object?
|
|
|
|
if (m_corbaConn == NULL)
|
|
|
|
{
|
|
|
|
m_corbaConn = new vncCorbaConnect();
|
|
|
|
}
|
|
|
|
if (m_corbaConn == NULL)
|
|
|
|
return FALSE;
|
|
|
|
if (!m_corbaConn->Init(this))
|
|
|
|
{
|
|
|
|
delete m_corbaConn;
|
|
|
|
m_corbaConn = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Is there a listening socket?
|
|
|
|
if (m_corbaConn != NULL)
|
|
|
|
{
|
|
|
|
// Close the socket
|
|
|
|
delete m_corbaConn;
|
|
|
|
m_corbaConn = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::CORBAConnected()
|
|
|
|
{
|
|
|
|
return m_corbaConn != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::GetScreenInfo(int &width, int &height, int &depth)
|
|
|
|
{
|
|
|
|
rfbServerInitMsg scrinfo;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_desktopLock);
|
|
|
|
|
|
|
|
// Is a desktop object currently active?
|
|
|
|
if (m_desktop == NULL)
|
|
|
|
{
|
|
|
|
vncDesktop desktop;
|
|
|
|
|
|
|
|
// No, so create a dummy desktop and interrogate it
|
|
|
|
if (!desktop.Init(this))
|
|
|
|
{
|
|
|
|
scrinfo.framebufferWidth = 0;
|
|
|
|
scrinfo.framebufferHeight = 0;
|
|
|
|
scrinfo.format.bitsPerPixel = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
desktop.FillDisplayInfo(&scrinfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_desktop->FillDisplayInfo(&scrinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the info from the scrinfo structure
|
|
|
|
width = m_shared_rect.right - m_shared_rect.left;
|
|
|
|
height = m_shared_rect.bottom - m_shared_rect.top;
|
|
|
|
depth = scrinfo.format.bitsPerPixel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetAuthHosts(const char*hostlist) {
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
if (m_auth_hosts != 0)
|
|
|
|
free(m_auth_hosts);
|
|
|
|
|
|
|
|
if (hostlist == 0) {
|
|
|
|
m_auth_hosts = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_auth_hosts = strdup(hostlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
|
|
vncServer::AuthHosts() {
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
if (m_auth_hosts == 0)
|
|
|
|
return strdup("");
|
|
|
|
else
|
|
|
|
return strdup(m_auth_hosts);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BOOL
|
|
|
|
MatchStringToTemplate(const char *addr, size_t addrlen,
|
|
|
|
const char *filtstr, size_t filtlen) {
|
|
|
|
if (filtlen == 0)
|
|
|
|
return 1;
|
|
|
|
if (addrlen < filtlen)
|
|
|
|
return 0;
|
|
|
|
for (size_t x = 0; x < filtlen; x++) {
|
|
|
|
if (addr[x] != filtstr[x])
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ((addrlen > filtlen) && (addr[filtlen] != '.'))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vncServer::AcceptQueryReject
|
|
|
|
vncServer::VerifyHost(const char *hostname) {
|
|
|
|
if (ClientsDisabled())
|
|
|
|
return vncServer::aqrReject;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// -=- Is the specified host blacklisted?
|
|
|
|
vncServer::BlacklistEntry *current = m_blacklist;
|
|
|
|
vncServer::BlacklistEntry *previous = 0;
|
|
|
|
SYSTEMTIME systime;
|
|
|
|
FILETIME ftime;
|
|
|
|
LARGE_INTEGER now;
|
|
|
|
|
|
|
|
// Get the current time as a 64-bit value
|
|
|
|
GetSystemTime(&systime);
|
|
|
|
SystemTimeToFileTime(&systime, &ftime);
|
|
|
|
now.LowPart=ftime.dwLowDateTime;now.HighPart=ftime.dwHighDateTime;
|
|
|
|
now.QuadPart /= 10000000; // Convert it into seconds
|
|
|
|
|
|
|
|
while (current) {
|
|
|
|
|
|
|
|
// Has the blacklist entry timed out?
|
|
|
|
if ((now.QuadPart - current->_lastRefTime.QuadPart) > 0) {
|
|
|
|
|
|
|
|
// Yes. Is it a "blocked" entry?
|
|
|
|
if (current->_blocked) {
|
|
|
|
// Yes, so unblock it & re-set the reference time
|
|
|
|
current->_blocked = FALSE;
|
|
|
|
current->_lastRefTime.QuadPart = now.QuadPart + 10;
|
|
|
|
} else {
|
|
|
|
// No, so remove it
|
|
|
|
if (previous)
|
|
|
|
previous->_next = current->_next;
|
|
|
|
else
|
|
|
|
m_blacklist = current->_next;
|
|
|
|
vncServer::BlacklistEntry *next = current->_next;
|
|
|
|
free(current->_machineName);
|
|
|
|
delete current;
|
|
|
|
current = next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is this the entry we're interested in?
|
|
|
|
if ((strcmp(current->_machineName, hostname) == 0) &&
|
|
|
|
(current->_blocked)) {
|
|
|
|
// Machine is blocked, so just reject it
|
|
|
|
return vncServer::aqrReject;
|
|
|
|
}
|
|
|
|
|
|
|
|
previous = current;
|
|
|
|
current = current->_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Has a hostname been specified?
|
|
|
|
if (hostname == 0) {
|
|
|
|
return vncServer::aqrReject;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the state machine into the correct mode & process the filter
|
|
|
|
enum vh_Mode {vh_ExpectDelimiter, vh_ExpectIncludeExclude, vh_ExpectPattern};
|
|
|
|
vh_Mode machineMode = vh_ExpectIncludeExclude;
|
|
|
|
|
|
|
|
vncServer::AcceptQueryReject verifiedHost = vncServer::aqrAccept;
|
|
|
|
|
|
|
|
vncServer::AcceptQueryReject patternType = vncServer::aqrReject;
|
|
|
|
UINT authHostsPos = 0;
|
|
|
|
UINT patternStart = 0;
|
|
|
|
size_t hostNameLen = strlen(hostname);
|
|
|
|
|
|
|
|
// Run through the auth hosts string until we hit the end
|
|
|
|
if (m_auth_hosts) {
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
// Which mode are we in?
|
|
|
|
switch (machineMode) {
|
|
|
|
|
|
|
|
// ExpectIncludeExclude - we should see a + or -.
|
|
|
|
case vh_ExpectIncludeExclude:
|
|
|
|
if (m_auth_hosts[authHostsPos] == '+') {
|
|
|
|
patternType = vncServer::aqrAccept;
|
|
|
|
patternStart = authHostsPos+1;
|
|
|
|
machineMode = vh_ExpectPattern;
|
|
|
|
} else if (m_auth_hosts[authHostsPos] == '-') {
|
|
|
|
patternType = vncServer::aqrReject;
|
|
|
|
patternStart = authHostsPos+1;
|
|
|
|
machineMode = vh_ExpectPattern;
|
|
|
|
} else if (m_auth_hosts[authHostsPos] == '?') {
|
|
|
|
patternType = vncServer::aqrQuery;
|
|
|
|
patternStart = authHostsPos+1;
|
|
|
|
machineMode = vh_ExpectPattern;
|
|
|
|
} else if (m_auth_hosts[authHostsPos] != '\0') {
|
|
|
|
machineMode = vh_ExpectDelimiter;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ExpectPattern - we expect to see a valid pattern
|
|
|
|
case vh_ExpectPattern:
|
|
|
|
// ExpectDelimiter - we're scanning for the next ':', skipping a pattern
|
|
|
|
case vh_ExpectDelimiter:
|
|
|
|
if ((m_auth_hosts[authHostsPos] == ':') ||
|
|
|
|
(m_auth_hosts[authHostsPos] == '\0')) {
|
|
|
|
if (machineMode == vh_ExpectPattern) {
|
|
|
|
if (patternStart == 0) {
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Process the match
|
|
|
|
if (MatchStringToTemplate(hostname, hostNameLen,
|
|
|
|
&(m_auth_hosts[patternStart]), authHostsPos-patternStart)) {
|
|
|
|
// The hostname matched - apply the include/exclude rule
|
|
|
|
verifiedHost = patternType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We now expect another + or -
|
|
|
|
machineMode = vh_ExpectIncludeExclude;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Have we hit the end of the pattern string?
|
|
|
|
if (m_auth_hosts[authHostsPos] == '\0')
|
|
|
|
break;
|
|
|
|
authHostsPos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return AdjustVerification(verifiedHost);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vncServer::AcceptQueryReject
|
|
|
|
vncServer::AdjustVerification(vncServer::AcceptQueryReject host)
|
|
|
|
{
|
|
|
|
vncServer::AcceptQueryReject verifiedHost = host;
|
|
|
|
|
|
|
|
// Based on the server's QuerySetting, adjust the verification result
|
|
|
|
switch (host) {
|
|
|
|
case vncServer::aqrAccept:
|
|
|
|
if (QuerySetting() >= 3)
|
|
|
|
verifiedHost = vncServer::aqrQuery;
|
|
|
|
break;
|
|
|
|
case vncServer::aqrQuery:
|
|
|
|
if (QuerySetting() <= 1)
|
|
|
|
verifiedHost = vncServer::aqrAccept;
|
|
|
|
else if (QuerySetting() == 4)
|
|
|
|
verifiedHost = vncServer::aqrReject;
|
|
|
|
break;
|
|
|
|
case vncServer::aqrReject:
|
|
|
|
if (QuerySetting() == 0)
|
|
|
|
verifiedHost = vncServer::aqrQuery;
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
return verifiedHost;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::AddAuthHostsBlacklist(const char *machine) {
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// -=- Is the specified host blacklisted?
|
|
|
|
vncServer::BlacklistEntry *current = m_blacklist;
|
|
|
|
|
|
|
|
// Get the current time as a 64-bit value
|
|
|
|
SYSTEMTIME systime;
|
|
|
|
FILETIME ftime;
|
|
|
|
LARGE_INTEGER now;
|
|
|
|
GetSystemTime(&systime);
|
|
|
|
SystemTimeToFileTime(&systime, &ftime);
|
|
|
|
now.LowPart=ftime.dwLowDateTime;now.HighPart=ftime.dwHighDateTime;
|
|
|
|
now.QuadPart /= 10000000; // Convert it into seconds
|
|
|
|
|
|
|
|
while (current) {
|
|
|
|
|
|
|
|
// Is this the entry we're interested in?
|
|
|
|
if (strcmp(current->_machineName, machine) == 0) {
|
|
|
|
|
|
|
|
// If the host is already blocked then ignore
|
|
|
|
if (current->_blocked)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set the RefTime & failureCount
|
|
|
|
current->_lastRefTime.QuadPart = now.QuadPart + 10;
|
|
|
|
current->_failureCount++;
|
|
|
|
|
|
|
|
if (current->_failureCount > 5)
|
|
|
|
current->_blocked = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
current = current->_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Didn't find the entry
|
|
|
|
current = new vncServer::BlacklistEntry;
|
|
|
|
current->_blocked = FALSE;
|
|
|
|
current->_failureCount = 0;
|
|
|
|
current->_lastRefTime.QuadPart = now.QuadPart + 10;
|
|
|
|
current->_machineName = strdup(machine);
|
|
|
|
current->_next = m_blacklist;
|
|
|
|
m_blacklist = current;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::RemAuthHostsBlacklist(const char *machine) {
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// -=- Is the specified host blacklisted?
|
|
|
|
vncServer::BlacklistEntry *current = m_blacklist;
|
|
|
|
vncServer::BlacklistEntry *previous = 0;
|
|
|
|
|
|
|
|
while (current) {
|
|
|
|
|
|
|
|
// Is this the entry we're interested in?
|
|
|
|
if (strcmp(current->_machineName, machine) == 0) {
|
|
|
|
if (previous)
|
|
|
|
previous->_next = current->_next;
|
|
|
|
else
|
|
|
|
m_blacklist = current->_next;
|
|
|
|
vncServer::BlacklistEntry *next = current->_next;
|
|
|
|
free (current->_machineName);
|
|
|
|
delete current;
|
|
|
|
current = next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
previous = current;
|
|
|
|
current = current->_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetWindowShared(HWND hWnd)
|
|
|
|
{
|
|
|
|
m_hwndShared=hWnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vncServer::SetMatchSizeFields(int left,int top,int right,int bottom)
|
|
|
|
{
|
|
|
|
RECT trect = GetScreenRect();
|
|
|
|
|
|
|
|
/* if ( right - left < 32 )
|
|
|
|
right = left + 32;
|
|
|
|
|
|
|
|
if ( bottom - top < 32)
|
|
|
|
bottom = top + 32 ;*/
|
|
|
|
|
|
|
|
if( right > trect.right )
|
|
|
|
right = trect.right;
|
|
|
|
if( bottom > trect.bottom )
|
|
|
|
bottom = trect.bottom;
|
|
|
|
if( left < trect.left)
|
|
|
|
left = trect.left;
|
|
|
|
if( top < trect.top)
|
|
|
|
top = trect.top;
|
|
|
|
|
|
|
|
|
|
|
|
m_screenarea_rect.left=left;
|
|
|
|
m_screenarea_rect.top=top;
|
|
|
|
m_screenarea_rect.bottom=bottom;
|
|
|
|
m_screenarea_rect.right=right;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetKeyboardCounter(int count)
|
|
|
|
{
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
if (LocalInputPriority() && vncService::IsWin95())
|
|
|
|
{
|
|
|
|
m_remote_keyboard += count;
|
|
|
|
if (count == 0)
|
|
|
|
m_remote_keyboard = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetMouseCounter(int count, POINT &cursor_pos, BOOL mousemove)
|
|
|
|
{
|
|
|
|
if( (mousemove) && ( abs (m_cursor_pos.x - cursor_pos.x)==0
|
|
|
|
&& abs (m_cursor_pos.y - cursor_pos.y)==0 ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
if (LocalInputPriority() && vncService::IsWin95())
|
|
|
|
{
|
|
|
|
m_remote_mouse += count;
|
|
|
|
if (count == 0)
|
|
|
|
m_remote_mouse = 0;
|
|
|
|
|
|
|
|
m_cursor_pos.x = cursor_pos.x;
|
|
|
|
m_cursor_pos.y = cursor_pos.y;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetNewFBSize(BOOL sendnewfb)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Post new framebuffer size update to all the connected clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
// Post the update
|
|
|
|
GetClient(*i)->SetNewFBSize( sendnewfb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::FullRgnRequested()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Iterate over the authorised clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
if (GetClient(*i)->FullRgnRequested())
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::IncrRgnRequested()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Iterate over the authorised clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
if (GetClient(*i)->IncrRgnRequested())
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::UpdateLocalFormat()
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
omni_mutex_lock l(m_clientsLock);
|
|
|
|
|
|
|
|
// Iterate over the authorised clients
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
GetClient(*i)->UpdateLocalFormat();
|
|
|
|
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vncServer::SetPollingCycle(UINT msec)
|
|
|
|
{
|
|
|
|
if (m_polling_cycle != msec && msec > 10) {
|
|
|
|
m_polling_cycle = msec;
|
|
|
|
PollingCycleChanged(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::checkPointer(vncClient *pClient)
|
|
|
|
{
|
|
|
|
vncClientList::iterator i;
|
|
|
|
for (i = m_authClients.begin(); i != m_authClients.end(); i++)
|
|
|
|
{
|
|
|
|
if (GetClient(*i) == pClient) return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
vncServer::DriverActive() {
|
|
|
|
return (m_desktop != NULL) ? m_desktop->DriverActive() : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef HMONITOR (WINAPI* pMonitorFromPoint)(POINT,DWORD);
|
|
|
|
typedef BOOL (WINAPI* pGetMonitorInfo)(HMONITOR,LPMONITORINFO);
|
|
|
|
|
|
|
|
BOOL vncServer::SetShareMonitorFromPoint(POINT pt)
|
|
|
|
{
|
|
|
|
HINSTANCE hInstUser32 = LoadLibrary("User32.DLL");
|
|
|
|
if (!hInstUser32) return FALSE;
|
|
|
|
pMonitorFromPoint pMFP = (pMonitorFromPoint)GetProcAddress(hInstUser32, "MonitorFromPoint");
|
|
|
|
pGetMonitorInfo pGMI = (pGetMonitorInfo)GetProcAddress(hInstUser32, "GetMonitorInfoA");
|
|
|
|
if (!pMFP || !pGMI)
|
|
|
|
{
|
|
|
|
FreeLibrary(hInstUser32);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HMONITOR hm = pMFP(pt, MONITOR_DEFAULTTONEAREST);
|
|
|
|
if (!hm)
|
|
|
|
{
|
|
|
|
FreeLibrary(hInstUser32);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
MONITORINFO moninfo;
|
|
|
|
moninfo.cbSize = sizeof(moninfo);
|
|
|
|
if (!pGMI(hm, &moninfo))
|
|
|
|
{
|
|
|
|
FreeLibrary(hInstUser32);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FullScreen(FALSE);
|
|
|
|
WindowShared(FALSE);
|
|
|
|
ScreenAreaShared(TRUE);
|
|
|
|
PrimaryDisplayOnlyShared(FALSE);
|
|
|
|
|
|
|
|
SetMatchSizeFields(
|
|
|
|
moninfo.rcMonitor.left,
|
|
|
|
moninfo.rcMonitor.top,
|
|
|
|
moninfo.rcMonitor.right,
|
|
|
|
moninfo.rcMonitor.bottom);
|
|
|
|
|
|
|
|
FreeLibrary(hInstUser32);
|
|
|
|
return TRUE;
|
|
|
|
}
|