📄 vncclient.cpp
字号:
//////////////////
// LOG it also in the event
//////////////////
if (!m_ms_logon){
typedef BOOL (*LogeventFn)(char *machine);
LogeventFn Logevent = 0;
char szCurrentDir[MAX_PATH];
if (GetModuleFileName(NULL, szCurrentDir, MAX_PATH))
{
char* p = strrchr(szCurrentDir, '\\');
*p = '\0';
strcat (szCurrentDir,"\\logging.dll");
}
HMODULE hModule = LoadLibrary(szCurrentDir);
if (hModule)
{
BOOL result=false;
Logevent = (LogeventFn) GetProcAddress( hModule, "LOGLOGON" );
Logevent((char *)m_client->GetClientName());
FreeLibrary(hModule);
}
}
if (!m_socket->SendExact((char *)&authmsg, sizeof(authmsg)))
return FALSE;
}
}
// Read the client's initialisation message
rfbClientInitMsg client_ini;
if (!m_socket->ReadExact((char *)&client_ini, sz_rfbClientInitMsg))
return FALSE;
// If the client wishes to have exclusive access then remove other clients
if (m_server->ConnectPriority()==3 && !m_shared )
{
// Existing
if (m_server->AuthClientCount() > 0)
{
vnclog.Print(LL_CLIENTS, VNCLOG("connections already exist - client rejected\n"));
return FALSE;
}
}
if (!client_ini.shared && !m_shared)
{
// Which client takes priority, existing or incoming?
if (m_server->ConnectPriority() < 1)
{
// Incoming
vnclog.Print(LL_INTINFO, VNCLOG("non-shared connection - disconnecting old clients\n"));
m_server->KillAuthClients();
} else if (m_server->ConnectPriority() > 1)
{
// Existing
if (m_server->AuthClientCount() > 0)
{
vnclog.Print(LL_CLIENTS, VNCLOG("connections already exist - client rejected\n"));
return FALSE;
}
}
}
// Tell the server that this client is ok
return m_server->Authenticated(m_client->GetClientId());
}
void
ClearKeyState(BYTE key)
{
// This routine is used by the VNC client handler to clear the
// CAPSLOCK, NUMLOCK and SCROLL-LOCK states.
BYTE keyState[256];
GetKeyboardState((LPBYTE)&keyState);
if(keyState[key] & 1)
{
// Simulate the key being pressed
keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY, 0);
// Simulate it being release
keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
// Modif sf@2002
// Get the local ip addresses as a human-readable string.
// If more than one, then with \n between them.
// If not available, then gets a message to that effect.
void GetIPString(char *buffer, int buflen)
{
char namebuf[256];
if (gethostname(namebuf, 256) != 0)
{
strncpy(buffer, "Host name unavailable", buflen);
return;
}
HOSTENT *ph = gethostbyname(namebuf);
if (!ph)
{
strncpy(buffer, "IP address unavailable", buflen);
return;
}
*buffer = '\0';
char digtxt[5];
for (int i = 0; ph->h_addr_list[i]; i++)
{
for (int j = 0; j < ph->h_length; j++)
{
sprintf(digtxt, "%d.", (unsigned char) ph->h_addr_list[i][j]);
strncat(buffer, digtxt, (buflen-1)-strlen(buffer));
}
buffer[strlen(buffer)-1] = '\0';
if (ph->h_addr_list[i+1] != 0)
strncat(buffer, ", ", (buflen-1)-strlen(buffer));
}
}
void
vncClientThread::run(void *arg)
{
// All this thread does is go into a socket-receive loop,
// waiting for stuff on the given socket
// IMPORTANT : ALWAYS call RemoveClient on the server before quitting
// this thread.
vnclog.Print(LL_CLIENTS, VNCLOG("client connected : %s (%hd)\n"),
m_client->GetClientName(),
m_client->GetClientId());
// Save the handle to the thread's original desktop
HDESK home_desktop = GetThreadDesktop(GetCurrentThreadId());
// To avoid people connecting and then halting the connection, set a timeout
if (!m_socket->SetTimeout(30000))
vnclog.Print(LL_INTERR, VNCLOG("failed to set socket timeout(%d)\n"), GetLastError());
// sf@2002 - DSM Plugin - Tell the client's socket where to find the DSMPlugin
if (m_server->GetDSMPluginPointer() != NULL)
{
m_socket->SetDSMPluginPointer(m_server->GetDSMPluginPointer());
vnclog.Print(LL_INTINFO, VNCLOG("DSMPlugin Pointer to socket OK\n"));
}
else
{
vnclog.Print(LL_INTINFO, VNCLOG("Invalid DSMPlugin Pointer\n"));
return;
}
// Initially blacklist the client so that excess connections from it get dropped
m_server->AddAuthHostsBlacklist(m_client->GetClientName());
// LOCK INITIAL SETUP
// All clients have the m_protocol_ready flag set to FALSE initially, to prevent
// updates and suchlike interfering with the initial protocol negotiations.
// sf@2002 - DSMPlugin
// Use Plugin only from this point (now BEFORE Protocole handshaking)
if (m_server->GetDSMPluginPointer()->IsEnabled())
{
m_server->GetDSMPluginPointer()->ResetPlugin(); //SEC reset if needed
m_socket->EnableUsePlugin(true);
m_client->m_encodemgr.EnableQueuing(false);
// TODO: Make a more secured challenge (with time stamp)
}
else
m_client->m_encodemgr.EnableQueuing(true);
// GET PROTOCOL VERSION
if (!InitVersion())
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
vnclog.Print(LL_INTINFO, VNCLOG("negotiated version\n"));
// AUTHENTICATE LINK
if (!InitAuthenticate())
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
// Authenticated OK - remove from blacklist and remove timeout
m_server->RemAuthHostsBlacklist(m_client->GetClientName());
m_socket->SetTimeout(m_server->AutoIdleDisconnectTimeout()*1000);
vnclog.Print(LL_INTINFO, VNCLOG("authenticated connection\n"));
// Set Client Connect time
m_client->SetConnectTime(timeGetTime());
// INIT PIXEL FORMAT
// Get the screen format
// m_client->m_fullscreen = m_client->m_encodemgr.GetSize();
// Modif sf@2002 - Scaling
{
omni_mutex_lock l(m_client->GetUpdateLock());
m_client->m_encodemgr.m_buffer->SetScale(m_server->GetDefaultScale()); // v1.1.2
}
m_client->m_ScaledScreen = m_client->m_encodemgr.m_buffer->GetViewerSize();
m_client->m_nScale = m_client->m_encodemgr.m_buffer->GetScale();
// Get the name of this desktop
// sf@2002 - v1.1.x - Complete the computer name with the IP address if necessary
bool fIP = false;
char desktopname[MAX_COMPUTERNAME_LENGTH + 1 + 256];
DWORD desktopnamelen = MAX_COMPUTERNAME_LENGTH + 1 + 256;
memset((char*)desktopname, 0, sizeof(desktopname));
if (GetComputerName(desktopname, &desktopnamelen))
{
// Make the name lowercase
for (int x=0; x<strlen(desktopname); x++)
{
desktopname[x] = tolower(desktopname[x]);
}
// Check for the presence of "." in the string (then it's presumably an IP adr)
if (strchr(desktopname, '.') != NULL) fIP = true;
}
else
{
strcpy(desktopname, "WinVNC");
}
// We add the IP address(es) to the computer name, if possible and necessary
if (!fIP)
{
char szIP[256];
GetIPString(szIP, sizeof(szIP));
if (strlen(szIP) > 3 && szIP[0] != 'I' && szIP[0] != 'H')
{
strcat(desktopname, " ( ");
strcat(desktopname, szIP);
strcat(desktopname, " )");
}
}
// Send the server format message to the client
rfbServerInitMsg server_ini;
server_ini.format = m_client->m_encodemgr.m_buffer->GetLocalFormat();
// Endian swaps
// Modif sf@2002 - Scaling
server_ini.framebufferWidth = Swap16IfLE(m_client->m_ScaledScreen.br.x - m_client->m_ScaledScreen.tl.x);
server_ini.framebufferHeight = Swap16IfLE(m_client->m_ScaledScreen.br.y - m_client->m_ScaledScreen.tl.y);
// server_ini.framebufferWidth = Swap16IfLE(m_client->m_fullscreen.br.x-m_client->m_fullscreen.tl.x);
// server_ini.framebufferHeight = Swap16IfLE(m_client->m_fullscreen.br.y-m_client->m_fullscreen.tl.y);
server_ini.format.redMax = Swap16IfLE(server_ini.format.redMax);
server_ini.format.greenMax = Swap16IfLE(server_ini.format.greenMax);
server_ini.format.blueMax = Swap16IfLE(server_ini.format.blueMax);
server_ini.nameLength = Swap32IfLE(strlen(desktopname));
if (!m_socket->SendExact((char *)&server_ini, sizeof(server_ini)))
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
if (!m_socket->SendExact(desktopname, strlen(desktopname)))
{
m_server->RemoveClient(m_client->GetClientId());
return;
}
vnclog.Print(LL_INTINFO, VNCLOG("sent pixel format to client\n"));
// UNLOCK INITIAL SETUP
// Initial negotiation is complete, so set the protocol ready flag
m_client->EnableProtocol();
// Add a fullscreen update to the client's update list
// sf@2002 - Scaling
// m_client->m_update_tracker.add_changed(m_client->m_fullscreen);
{ // RealVNC 336
omni_mutex_lock l(m_client->GetUpdateLock());
m_client->m_update_tracker.add_changed(m_client->m_ScaledScreen);
}
// Clear the CapsLock and NumLock keys
if (m_client->m_keyboardenabled)
{
ClearKeyState(VK_CAPITAL);
// *** JNW - removed because people complain it's wrong
//ClearKeyState(VK_NUMLOCK);
ClearKeyState(VK_SCROLL);
}
// MAIN LOOP
// Set the input thread to a high priority
set_priority(omni_thread::PRIORITY_HIGH);
BOOL connected = TRUE;
while (connected)
{
rfbClientToServerMsg msg;
// Ensure that we're running in the correct desktop
if (!vncService::InputDesktopSelected())
if (!vncService::SelectDesktop(NULL))
break;
// sf@2002 - v1.1.2
int nTO = 1; // Type offset
// If DSM Plugin, we must read all the transformed incoming rfb messages (type included)
if (m_socket->IsUsePluginEnabled() && m_server->GetDSMPluginPointer()->IsEnabled())
{
if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type)))
{
connected = FALSE;
break;
}
nTO = 0;
}
else
{
// Try to read a message ID
if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type)))
{
connected = FALSE;
break;
}
}
// What to do is determined by the message id
switch(msg.type)
{
case rfbSetPixelFormat:
// Read the rest of the message:
if (!m_socket->ReadExact(((char *) &msg)+nTO, sz_rfbSetPixelFormatMsg-nTO))
{
connected = FALSE;
break;
}
// Swap the relevant bits.
msg.spf.format.redMax = Swap16IfLE(msg.spf.format.redMax);
msg.spf.format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
msg.spf.format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
// sf@2005 - Additional param for Grey Scale transformation
m_client->m_encodemgr.EnableGreyPalette((msg.spf.format.pad1 == 1));
// Prevent updates while the pixel format is changed
m_client->DisableProtocol();
// Tell the buffer object of the change
if (!m_client->m_encodemgr.SetClientFormat(msg.spf.format))
{
vnclog.Print(LL_CONNERR, VNCLOG("remote pixel format invalid\n"));
connected = FALSE;
}
// Set the palette-changed flag, just in case...
m_client->m_palettechanged = TRUE;
// Re-enable updates
m_client->EnableProtocol();
break;
case rfbSetEncodings:
// Read the rest of the message:
if (!m_socket->ReadExact(((char *) &msg)+nTO, sz_rfbSetEncodingsMsg-nTO))
{
connected = FALSE;
break;
}
// RDV cache
m_client->m_encodemgr.EnableCache(FALSE);
// RDV XOR and client detection
m_client->m_encodemgr.AvailableXOR(FALSE);
m_client->m_encodemgr.AvailableZRLE(FALSE);
m_client->m_encodemgr.AvailableTight(FALSE);
// sf@2002 - Tight
m_client->m_encodemgr.SetQualityLevel(-1);
m_client->m_encodemgr.SetCompressLevel(6);
m_client->m_encodemgr.EnableLastRect(FALSE);
// Tight - CURSOR HANDLING
m_client->m_encodemgr.EnableXCursor(FALSE);
m_client->m_encodemgr.EnableRichCursor(FALSE);
m_server->EnableXRichCursor(FALSE);
m_client->m_cursor_update_pending = FALSE;
m_client->m_cursor_update_sent = FALSE;
// Prevent updates while the encoder is changed
m_client->DisableProtocol();
// Read in the preferred encodings
msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
{
int x;
BOOL encoding_set = FALSE;
// By default, don't use copyrect!
m_client->m_update_tracker.enable_copyrect(false);
for (x=0; x<msg.se.nEncodings; x++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -