void addClntThrdCD::run( void * ) { HAB thab = WinInitialize( 0 ); HMQ hmq = WinCreateMsgQueue( thab , 0 ); // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (tmpsock!=NULL) { // Connect out to the specified host on the VNCviewer listen port // To be really good, we should allow a display number here but // for now we'll just assume we're connecting to display zero tmpsock->Create(); if (tmpsock->Connect(m_host, m_port)) { // Add the new client to this server m_server->AddClient(tmpsock, TRUE, TRUE); } else { // Print up an error message WinMessageBox( HWND_DESKTOP , HWND_DESKTOP , (PSZ)"Failed to connect to listening VNC viewer", (PSZ)"Outgoing Connection", 10001 , MB_ICONEXCLAMATION | MB_OK ); delete tmpsock; } } WinDestroyMsgQueue( hmq ); WinTerminate( thab ); }
BOOL vncClientThread::InitVersion() { // Generate the server's protocol version rfbProtocolVersionMsg protocolMsg; sprintf((char *)protocolMsg, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion); // Send the protocol message if (!m_socket->SendExact((char *)&protocolMsg, sz_rfbProtocolVersionMsg)) return FALSE; // Now, get the client's protocol version rfbProtocolVersionMsg protocol_ver; protocol_ver[12] = 0; if (!m_socket->ReadExact((char *)&protocol_ver, sz_rfbProtocolVersionMsg)) return FALSE; // Check the protocol version int major, minor; sscanf((char *)&protocol_ver, rfbProtocolVersionFormat, &major, &minor); if (major != rfbProtocolMajorVersion) return FALSE; return TRUE; }
// Code to be executed by the thread void *vncHTTPConnectThread::run_undetached(void * arg) { vnclog.Print(LL_INTINFO, VNCLOG("started HTTP server thread\n")); // Go into a loop, listening for connections on the given socket while (!m_shutdown) { // Accept an incoming connection VSocket *new_socket = m_socket->Accept(); if (new_socket == NULL) break; vnclog.Print(LL_CLIENTS, VNCLOG("HTTP client connected\n")); // Successful accept - perform the transaction new_socket->SetTimeout(15000); DoHTTP(new_socket); // And close the client new_socket->Shutdown(); new_socket->Close(); delete new_socket; } vnclog.Print(LL_INTINFO, VNCLOG("quitting HTTP server thread\n")); return NULL; }
qint64 vsocketDispatcher( char * _buf, const qint64 _len, const SocketOpCodes _op_code, void * _user ) { VSocket * sock = static_cast<VSocket *>( _user ); switch( _op_code ) { case SocketRead: return( sock->ReadExact( _buf, _len ) ? _len : 0 ); case SocketWrite: return( sock->SendExact( _buf, _len ) ? _len : 0 ); case SocketGetPeerAddress: strncpy( _buf, sock->GetPeerName(), _len ); return( 0 ); } return( 0 ); }
VBool VSocket::Bind(const VCard port, const VBool localOnly, const VBool checkIfInUse) { struct sockaddr_in addr; // Check that the socket is open! if (sock < 0) return VFalse; // If a specific port is being set then check it's not already used! if (port != 0 && checkIfInUse) { VSocket dummy; if (dummy.Create()) { // If we're able to connect then the port number is in use... if (dummy.Connect("localhost", port)) return VFalse; } } // Set up the address to bind the socket to addr.sin_family = AF_INET; addr.sin_port = htons(port); if (localOnly) addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else addr.sin_addr.s_addr = htonl(INADDR_ANY); // And do the binding if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) return VFalse; return VTrue; }
vncSockConnect::~vncSockConnect() { m_socket.Shutdown(); // Join with our lovely thread if (m_thread != NULL) { // *** This is a hack to force the listen thread out of the accept call, // because Winsock accept semantics are broken ((vncSockConnectThread *)m_thread)->m_shutdown = TRUE; VSocket socket; socket.Create(); socket.Bind(0); socket.Connect("localhost", m_port); socket.Close(); void *returnval; m_thread->join(&returnval); m_thread = NULL; m_socket.Close(); } }
// Code to be executed by the thread void *vncSockConnectThread::run_undetached(void * arg) { vnclog.Print(LL_STATE, VNCLOG("started socket connection thread\n")); // Go into a loop, listening for connections on the given socket while (!m_shutdown) { // Accept an incoming connection VSocket *new_socket; if (!m_socket->TryAccept(&new_socket, 100)) break; if (new_socket != NULL) { vnclog.Print(LL_CLIENTS, VNCLOG("accepted connection from %s\n"), new_socket->GetPeerName()); // Successful accept - start the client unauthenticated m_server->AddClient(new_socket, FALSE, FALSE); } } vnclog.Print(LL_STATE, VNCLOG("quitting socket connection thread\n")); return NULL; }
BOOL CALLBACK vncConnDialog::vncConnDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. But we can get a pseudo-this from the parameter to // WM_INITDIALOG, which we therafter store with the window and retrieve // as follows: vncConnDialog *_this = helper::SafeGetWindowUserData<vncConnDialog>(hwnd); switch (uMsg) { case WM_PAINT: { //adzm 2009-06-20 if (GetUpdateRect(hwnd, NULL, TRUE)) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); { RECT rcIcon; rcIcon.top = 0; rcIcon.left = 0; rcIcon.bottom = 48; rcIcon.right = 48; RECT rcClient; if (GetClientRect(hwnd, &rcClient)) { int nDifference = (rcClient.bottom - rcIcon.bottom) / 2; if (nDifference > 0) { rcIcon.top += nDifference; rcIcon.bottom += nDifference; } } RECT rcLabel; HWND hwndLabel = GetDlgItem(hwnd, IDC_CONNECTION_NUMBER_STATIC); if (GetWindowRect(hwndLabel, &rcLabel)) { LPRECT lprcLabel = &rcLabel; ScreenToClient(hwnd, (LPPOINT)lprcLabel); ScreenToClient(hwnd, ((LPPOINT)lprcLabel)+1); int nAdjustment = (rcLabel.left - rcIcon.right) / 2; rcIcon.left += nAdjustment; rcIcon.right += nAdjustment; } RECT rcIntersect; if (IntersectRect(&rcIntersect, &rcIcon, &(ps.rcPaint))) { if (_this->m_hicon == NULL) { _this->m_hicon = (HICON)LoadImage(hInstResDLL, MAKEINTRESOURCE(IDI_WINVNC), IMAGE_ICON, 48, 48, 0); } if (_this->m_hicon) { HBRUSH hbr = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (WPARAM)hwnd); DrawIconEx(hdc, rcIcon.left, rcIcon.top, _this->m_hicon, 48, 48, 0, hbr, DI_NORMAL); } } } EndPaint(hwnd, &ps); } return 0; } // Dialog has just been created case WM_INITDIALOG: { // Save the lParam into our user data so that subsequent calls have // access to the parent C++ object helper::SafeSetWindowUserData(hwnd, lParam); vncConnDialog *_this = (vncConnDialog *) lParam; //adzm 2009-06-20 if (g_szRepeaterHost) { SetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, g_szRepeaterHost); //adzm 2009-06-20 if (SPECIAL_SC_PROMPT) { HWND hwndChild = GetDlgItem(hwnd, IDC_HOSTNAME_EDIT); if (hwndChild) { ShowWindow(hwndChild, SW_HIDE); } hwndChild = GetDlgItem(hwnd, IDC_HOSTNAME_STATIC); if (hwndChild) { ShowWindow(hwndChild, SW_HIDE); } HWND hwndEdit = GetDlgItem(hwnd, IDC_IDCODE); HWND hwndLabel = GetDlgItem(hwnd, IDC_CONNECTION_NUMBER_STATIC); RECT rcEdit; RECT rcLabel; GetWindowRect(hwndEdit, &rcEdit); GetWindowRect(hwndLabel, &rcLabel); LPRECT lprcEdit = &rcEdit; LPRECT lprcLabel = &rcLabel; ScreenToClient(hwnd, (LPPOINT)lprcEdit); ScreenToClient(hwnd, ((LPPOINT)lprcEdit)+1); ScreenToClient(hwnd, (LPPOINT)lprcLabel); ScreenToClient(hwnd, ((LPPOINT)lprcLabel)+1); RECT rcClient; GetClientRect(hwnd, &rcClient); long nTotalHeight = rcEdit.bottom - rcLabel.top; long nAdjustedTop = (rcClient.bottom - nTotalHeight) / 2; long nAdjustment = nAdjustedTop - rcLabel.top; MoveWindow(hwndLabel, rcLabel.left, rcLabel.top + nAdjustment, rcLabel.right - rcLabel.left, rcLabel.bottom - rcLabel.top, TRUE); MoveWindow(hwndEdit, rcEdit.left, rcEdit.top + nAdjustment, rcEdit.right - rcEdit.left, rcEdit.bottom - rcEdit.top, TRUE); HWND hwndCaption = GetDlgItem(hwnd, IDC_CAPTION_STATIC); HFONT hFont = (HFONT)SendMessage(hwndCaption, WM_GETFONT, 0, 0); if (hFont) { LOGFONT lf; if (GetObject(hFont, sizeof(LOGFONT), &lf)) { lf.lfWidth = 0; lf.lfHeight = (lf.lfHeight * 6) / 4; _this->m_hfont = CreateFontIndirect(&lf); if (_this->m_hfont) { SendMessage(hwndCaption, WM_SETFONT, (WPARAM)_this->m_hfont, (LPARAM)TRUE); } } } SetWindowText(hwndCaption, "Connect to Technical Support"); ShowWindow(hwndCaption, SW_SHOWNA); } SetFocus(GetDlgItem(hwnd, IDC_IDCODE)); } else { // Make the text entry box active SetFocus(GetDlgItem(hwnd, IDC_HOSTNAME_EDIT)); } SetForegroundWindow(hwnd); // Return success! return TRUE; } // Dialog has just received a command case WM_COMMAND: switch (LOWORD(wParam)) { // User clicked OK or pressed return case IDOK: { // sf@2002 - host:num & host::num analyse. // Compatible with both RealVNC and TightVNC methods char hostname[_MAX_PATH]; char actualhostname[_MAX_PATH]; char idcode[_MAX_PATH]; char *portp; int port; bool id; // Get the hostname of the VNCviewer GetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, hostname, _MAX_PATH); GetDlgItemText(hwnd, IDC_IDCODE, idcode, _MAX_PATH); if (strcmp(idcode,"")==0) id=false; else id=true; strcpy(actualhostname, hostname); //adzm 2010-02-15 - Multiple repeaters chosen by modulo of ID char finalidcode[_MAX_PATH]; //adzm 2010-08 - this was sending uninitialized data over the wire ZeroMemory(finalidcode, sizeof(finalidcode)); //adzm 2009-06-20 if (id) { size_t i = 0; for (i = 0; i < strlen(idcode); i++) { finalidcode[i] = toupper(idcode[i]); } finalidcode[i] = 0; if (0 != strncmp("ID:", idcode, 3)) { strcpy(finalidcode, "ID:"); for (i = 0; i < strlen(idcode); i++) { finalidcode[i+3] = toupper(idcode[i]); } finalidcode[i+3] = 0; } //adzm 2010-02-15 - At this point, finalidcode is of the form "ID:#####" int numericId = atoi(finalidcode + 3); int numberOfHosts = 1; for (i = 0; i < strlen(hostname); i++) { if (hostname[i] == ';') { numberOfHosts++; } } if (numberOfHosts <= 1) { // then hostname == actualhostname } else { int modulo = numericId % numberOfHosts; char* szToken = strtok(hostname, ";"); while (szToken) { if (modulo == 0) { strcpy(actualhostname, szToken); break; } modulo--; szToken = strtok(NULL, ";"); } } } // Calculate the Display and Port offset. port = INCOMING_PORT_OFFSET; portp = strchr(actualhostname, ':'); if (portp) { *portp++ = '\0'; if (*portp == ':') // Tight127 method { port = atoi(++portp); // Port number after "::" } else // RealVNC method { if (atoi(portp) < 100) // If < 100 after ":" -> display number port += atoi(portp); else port = atoi(portp); // If > 100 after ":" -> Port number } } // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (!tmpsock) { return TRUE; } // Connect out to the specified host on the VNCviewer listen port // To be really good, we should allow a display number here but // for now we'll just assume we're connecting to display zero tmpsock->Create(); if (tmpsock->Connect(actualhostname, port)) { if (id) { tmpsock->Send(finalidcode,250); tmpsock->SetTimeout(0); /* if (strncmp(hostname,"ID",2)!=0) { while (true) { char result[1]; tmpsock->Read(result,1); if (strcmp(result,"2")==0) break; tmpsock->Send("1",1); } }*/ // adzm 2009-07-05 - repeater IDs // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, finalidcode, actualhostname, port); } else { // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, NULL, actualhostname, port); } // And close the dialog EndDialog(hwnd, TRUE); } else { // Print up an error message MessageBoxSecure(NULL, sz_ID_FAILED_CONNECT_LISTING_VIEW, sz_ID_OUTGOING_CONNECTION, MB_OK | MB_ICONEXCLAMATION ); delete tmpsock; } return TRUE; } // Cancel the dialog case IDCANCEL: EndDialog(hwnd, FALSE); return TRUE; }; break; case WM_DESTROY: EndDialog(hwnd, FALSE); if (_this->m_hicon != NULL) { DestroyIcon(_this->m_hicon); _this->m_hicon = NULL; } if (_this->m_hfont != NULL) { DeleteObject(_this->m_hfont); _this->m_hfont = NULL; } return TRUE; } return 0; }
// Process window messages LRESULT CALLBACK vncMenu::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. We use Allen Hadden's ([email protected]) suggestion // from a newsgroup to get the pseudo-this. vncMenu *_this = (vncMenu *) GetWindowLong(hwnd, GWL_USERDATA); // Beep(100,10); // vnclog.Print(LL_INTINFO, VNCLOG("iMsg 0x%x \n"),iMsg); switch (iMsg) { // Every five seconds, a timer message causes the icon to update case WM_TIMER: // *** HACK for running servicified if (vncService::RunningAsService()) { // Attempt to add the icon if it's not already there _this->AddTrayIcon(); // Trigger a check of the current user PostMessage(hwnd, WM_USERCHANGED, 0, 0); } if (nport!=0) { PostMessage(hwnd, RETRY_MESSAGE, 0, 0); } // Update the icon _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; // DEAL WITH NOTIFICATIONS FROM THE SERVER: case WM_SRV_CLIENT_AUTHENTICATED: case WM_SRV_CLIENT_DISCONNECT: // Adjust the icon accordingly _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); if (_this->m_server->AuthClientCount() != 0) { if (_this->m_server->RemoveWallpaperEnabled()) KillWallpaper(); } else { if (_this->m_server->RemoveWallpaperEnabled()) RestoreWallpaper(); } return 0; // STANDARD MESSAGE HANDLING case WM_CREATE: return 0; case WM_COMMAND: // User has clicked an item on the tray menu switch (LOWORD(wParam)) { case ID_DEFAULT_PROPERTIES: /* // Show the default properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show default properties requested\n")); _this->m_properties.ShowAdmin(TRUE, FALSE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0);*/ break; case ID_PROPERTIES: // Show the properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show user properties requested\n")); _this->m_propertiesPoll.Show(TRUE, TRUE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_ABOUT: // Show the About box _this->m_about.Show(TRUE); break; case ID_CLOSE: // User selected Close from the tray menu _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); break; } return 0; case WM_TRAYNOTIFY: // User has clicked on the tray icon or the menu { // Get the submenu to use as a pop-up menu HMENU submenu = GetSubMenu(_this->m_hmenu, 0); // What event are we responding to, RMB click? if (lParam==WM_RBUTTONUP) { if (submenu == NULL) { vnclog.Print(LL_INTERR, VNCLOG("no submenu available\n")); return 0; } // Make the first menu item the default (bold font) SetMenuDefaultItem(submenu, 0, TRUE); // Get the current cursor position, to display the menu at POINT mouse; GetCursorPos(&mouse); // There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // SetForegroundWindow(_this->m_nid.hWnd); // Display the menu at the desired position TrackPopupMenu(submenu, 0, mouse.x, mouse.y, 0, _this->m_nid.hWnd, NULL); return 0; } // Or was there a LMB double click? if (lParam==WM_LBUTTONDBLCLK) { // double click: execute first menu item SendMessage(_this->m_nid.hWnd, WM_COMMAND, GetMenuItemID(submenu, 0), 0); } return 0; } case WM_CLOSE: // Only accept WM_CLOSE if the logged on user has AllowShutdown set if (!_this->m_properties.AllowShutdown()) { return 0; } // tnatsni Wallpaper fix RestoreWallpaper(); break; case WM_DESTROY: // The user wants WinVNC to quit cleanly... vnclog.Print(LL_INTINFO, VNCLOG("quitting from WM_DESTROY\n")); PostQuitMessage(0); return 0; case WM_QUERYENDSESSION: vnclog.Print(LL_INTERR, VNCLOG("WM_QUERYENDSESSION\n")); break; case WM_ENDSESSION: vnclog.Print(LL_INTERR, VNCLOG("WM_ENDSESSION\n")); break; case WM_USERCHANGED: // The current user may have changed. { char newuser[UNLEN+1]; if (vncService::CurrentUser((char *) &newuser, sizeof(newuser))) { vnclog.Print(LL_INTINFO, // VNCLOG("usernames : old=\"%s\", new=\"%s\"\n"), _this->m_username, newuser); // Check whether the user name has changed! if (strcmp(newuser, _this->m_username) != 0) { vnclog.Print(LL_INTINFO, VNCLOG("user name has changed\n")); // User has changed! strcpy(_this->m_username, newuser); // Redraw the tray icon and set it's state _this->DelTrayIcon(); _this->AddTrayIcon(); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); } } } return 0; default: if (iMsg == MENU_DEFAULT_PROPERTIES_SHOW) { // External request to show our Properties dialog PostMessage(hwnd, WM_COMMAND, MAKELONG(ID_DEFAULT_PROPERTIES, 0), 0); return 0; } if (iMsg == MENU_ABOUTBOX_SHOW) { // External request to show our About dialog PostMessage(hwnd, WM_COMMAND, MAKELONG(ID_ABOUT, 0), 0); return 0; } if (iMsg == MENU_SERVICEHELPER_MSG) { // External ServiceHelper message. // This message holds a process id which we can use to // impersonate a specific user. In doing so, we can load their // preferences correctly // vncService::ProcessUserHelperMessage(wParam, lParam); // Modif Jeremy C. vncService::ProcessUserHelperMessage((WPARAM)&_this->m_server->m_impersonationtoken, lParam); // - Trigger a check of the current user PostMessage(hwnd, WM_USERCHANGED, 0, 0); return 0; } if (iMsg == RETRY_MESSAGE) { connect_counter++; if (connect_counter%5==0) { // Attempt to create a new socket // Beep(1000,100); VSocket *tmpsock; tmpsock = new VSocket; if (tmpsock) { // Connect out to the specified host on the VNCviewer listen port tmpsock->Create(); if (tmpsock->Connect(szAdrName, nport)) { // Add the new client to this server if (strcmp(g_idcode,"")==NULL) g_id=false; else g_id=true; char sendID[_MAX_PATH]; strcpy(sendID,"ID:"); strcat(sendID,g_idcode); if (g_id) tmpsock->Send(sendID,250); _this->m_server->AddClient(tmpsock, TRUE, TRUE); nport=0; connected=1; _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); return 0; } else { delete tmpsock; connect_counter++; if (connect_counter>25) // Sleep(5000); PostMessage(hwnd, WM_CLOSE, 0, 0); } } } return 0; } if (iMsg == MENU_ADD_CLIENT_MSG) { // sf@2003 - Autoreconnect // Dirty trick to avoid to add a new MSG... no time if (lParam == 999) { _this->m_server->AutoReconnect(true); return 0; } /* // sf@2005 - FTNoUserImpersonation // Dirty trick to avoid to add a new MSG... no time if (lParam == 998) { _this->m_server->FTUserImpersonation(false); return 0; } */ // Add Client message. This message includes an IP address // of a listening client, to which we should connect. char *nameDup = 0; // sf@2003 - Values are already converted if (_this->m_server->AutoReconnect() && strlen(_this->m_server->AutoReconnectAdr()) > 0) { nport = _this->m_server->AutoReconnectPort(); strcpy(szAdrName, _this->m_server->AutoReconnectAdr()); } else { // Get the IP address stringified struct in_addr address; address.S_un.S_addr = lParam; char *name = inet_ntoa(address); if (name == 0) return 0; nameDup = strdup(name); if (nameDup == 0) return 0; strcpy(szAdrName, nameDup); // Free the duplicate name if (nameDup != 0) free(nameDup); // Get the port number nport = (unsigned short)wParam; if (nport == 0) nport = INCOMING_PORT_OFFSET; } // sf@2003 // Stores the client adr/ports the first time we try to connect // This way we can call this message again later to reconnect with the same values if (_this->m_server->AutoReconnect() && strlen(_this->m_server->AutoReconnectAdr()) == 0) { _this->m_server->AutoReconnectAdr(szAdrName); _this->m_server->AutoReconnectPort(nport); } // Attempt to create a new socket _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); VSocket *tmpsock; tmpsock = new VSocket; if (tmpsock) { // Connect out to the specified host on the VNCviewer listen port tmpsock->Create(); if (tmpsock->Connect(szAdrName, nport)) { // Add the new client to this server if (strcmp(g_idcode,"")==NULL) g_id=false; else g_id=true; char sendID[_MAX_PATH]; strcpy(sendID,"ID:"); strcat(sendID,g_idcode); if (g_id) tmpsock->Send(sendID,250); _this->m_server->AddClient(tmpsock, TRUE, TRUE); nport=0; connected=1; _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); return 0; } else { delete tmpsock; // Sleep(5000); // PostMessage(hwnd, WM_CLOSE, 0, 0); } } return 0; } // Process FileTransfer asynchronous Send Packet Message if (iMsg == FileTransferSendPacketMessage) { vncClient* pClient = (vncClient*) wParam; if (_this->m_server->IsClient(pClient)) pClient->SendFileChunk(); } } // Message not recognised return DefWindowProc(hwnd, iMsg, wParam, lParam); }
BOOL CALLBACK vncConnDialog::vncConnDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. But we can get a pseudo-this from the parameter to // WM_INITDIALOG, which we therafter store with the window and retrieve // as follows: vncConnDialog *_this = (vncConnDialog *) GetWindowLong(hwnd, GWL_USERDATA); switch (uMsg) { // Dialog has just been created case WM_INITDIALOG: { // Save the lParam into our user data so that subsequent calls have // access to the parent C++ object SetWindowLong(hwnd, GWL_USERDATA, lParam); vncConnDialog *_this = (vncConnDialog *) lParam; // Make the text entry box active SetFocus(GetDlgItem(hwnd, IDC_HOSTNAME_EDIT)); // Return success! return TRUE; } // Dialog has just received a command case WM_COMMAND: switch (LOWORD(wParam)) { // User clicked OK or pressed return case IDOK: { char viewer[256]; char hostname[256]; VCard display_or_port; // Get the viewer to connect to GetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, viewer, 256); // Process the supplied viewer address int result = sscanf(viewer, "%255[^:]:%u", hostname, &display_or_port); if (result == 1) { display_or_port = 0; result = 2; } if (result == 2) { // Correct a display number to a port number if required if (display_or_port < 100) { display_or_port += INCOMING_PORT_OFFSET; } // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (!tmpsock) return TRUE; // Connect out to the specified host on the VNCviewer listen port // To be really good, we should allow a display number here but // for now we'll just assume we're connecting to display zero tmpsock->Create(); if (tmpsock->Connect(hostname, display_or_port)) { // Add the new client to this server _this->m_server->AddClient(tmpsock, TRUE, TRUE); // And close the dialog EndDialog(hwnd, TRUE); } else { // Print up an error message MessageBox(NULL, "Failed to connect to listening VNC viewer", "Outgoing Connection", MB_OK | MB_ICONEXCLAMATION ); delete tmpsock; } } else { // We couldn't process the machine specification MessageBox(NULL, "Unable to process specified hostname and display/port", "Outgoing Connection", MB_OK | MB_ICONEXCLAMATION); } } return TRUE; // Cancel the dialog case IDCANCEL: EndDialog(hwnd, FALSE); return TRUE; }; break; case WM_DESTROY: EndDialog(hwnd, FALSE); return TRUE; } return 0; }
// 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); vnclog.Print(LL_CLIENTS, VNCLOG("trying port number %d\n"), m_port); // 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; } } } } else { // *** JNW - Trying to fix up a lock-up when the listening socket closes KillAuthClients(); KillUnauthClients(); WaitUntilAuthEmpty(); WaitUntilUnauthEmpty(); // Is there a listening socket? if (m_socketConn != NULL) { // Close the socket delete m_socketConn; m_socketConn = NULL; } } return TRUE; }
// Process window messages LRESULT CALLBACK vncMenu::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. We use Allen Hadden's ([email protected]) suggestion // from a newsgroup to get the pseudo-this. vncMenu *_this = helper::SafeGetWindowUserData<vncMenu>(hwnd); // Beep(100,10); // vnclog.Print(LL_INTINFO, VNCLOG("iMsg 0x%x \n"),iMsg); if (iMsg==WM_TASKBARCREATED) { if (_this->m_server->RunningFromExternalService()) { Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("WM_TASKBARCREATED \n")); // User has changed! strcpy(_this->m_username, newuser); vnclog.Print(LL_INTINFO, VNCLOG("############## Kill vncMenu thread\n")); // Order impersonation thread killing KillTimer(hwnd,1); PostQuitMessage(0); } } switch (iMsg) { // Every five seconds, a timer message causes the icon to update case WM_TIMER: // sf@2007 - Can't get the WTS_CONSOLE_CONNECT message work properly for now.. // So use a hack instead // jdp reread some ini settings _this->m_properties.ReloadDynamicSettings(); // G_1111==true --> reconnect if (G_1111==true) { if (_this->IsIconSet==true) { vnclog.Print(LL_INTERR, VNCLOG("Add client reconnect from timer\n")); G_1111=false; PostMessage(hwnd,MENU_ADD_CLIENT_MSG,1111,1111); } } vnclog.Print(LL_INTERR, VNCLOG("########### vncMenu::TIMER TrayIcon 5s hack\n")); if (_this->m_server->RunningFromExternalService()) { strcpy(newuser,""); if (vncService::CurrentUser((char *) &newuser, sizeof(newuser))) { // Check whether the user name has changed! if (_stricmp(newuser, _this->m_username) != 0 || _this->IconFaultCounter>2) { Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("user name has changed\n")); // User has changed! strcpy(_this->m_username, newuser); vnclog.Print(LL_INTINFO, VNCLOG("############## Kill vncMenu thread\n")); // Order impersonation thread killing PostQuitMessage(0); break; } } } // *** HACK for running servicified if (vncService::RunningAsService()) { vnclog.Print(LL_INTERR, VNCLOG("########### vncMenu::TIMER TrayIcon 5s hack call - Runningasservice\n")); // Attempt to add the icon if it's not already there _this->AddTrayIcon(); // Trigger a check of the current user PostMessage(hwnd, WM_USERCHANGED, 0, 0); } // Update the icon _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; // DEAL WITH NOTIFICATIONS FROM THE SERVER: case WM_SRV_CLIENT_AUTHENTICATED: case WM_SRV_CLIENT_DISCONNECT: // Adjust the icon accordingly _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); if (_this->m_server->AuthClientCount() != 0) { if (_this->m_server->RemoveWallpaperEnabled()) KillWallpaper(); if (_this->m_server->RemoveAeroEnabled()) // Moved, redundant if //PGM @ Advantig DisableAero(); // Moved, redundant if //PGM @ Advantig } else { if (_this->m_server->RemoveAeroEnabled()) // Moved, redundant if //PGM @ Advantig ResetAero(); // Moved, redundant if //PGM @ Advantig if (_this->m_server->RemoveWallpaperEnabled()) { // Added { //PGM @ Advantig Sleep(2000); // Added 2 second delay to help wallpaper restore //PGM @ Advantig RestoreWallpaper(); } //PGM @ Advantig } //PGM @ Advantig if (_this->m_server->AuthClientCount() != 0) { //PGM @ Advantig if (_this->m_server->RemoveAeroEnabled()) //PGM @ Advantig DisableAero(); //PGM @ Advantig } else { //PGM @ Advantig if (_this->m_server->RemoveAeroEnabled()) //PGM @ Advantig ResetAero(); //PGM @ Advantig } return 0; // STANDARD MESSAGE HANDLING case WM_CREATE: WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated"); return 0; case WM_COMMAND: // User has clicked an item on the tray menu switch (LOWORD(wParam)) { case ID_DEFAULT_PROPERTIES: // Show the default properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show default properties requested\n")); _this->m_properties.ShowAdmin(TRUE, FALSE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_PROPERTIES: // Show the properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show user properties requested\n")); _this->m_propertiesPoll.Show(TRUE, TRUE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_ADMIN_PROPERTIES: // Show the properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show user properties requested\n")); _this->m_properties.ShowAdmin(TRUE, TRUE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_OUTGOING_CONN: // Connect out to a listening VNC viewer { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { newconn->DoDialog(); // delete newconn; // NO ! Already done in vncConnDialog. } } break; case ID_KILLCLIENTS: // Disconnect all currently connected clients vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_KILLCLIENTS \n")); _this->m_server->KillAuthClients(); break; // sf@2002 case ID_LISTCLIENTS: _this->m_ListDlg.Display(); break; case ID_ABOUT: // Show the About box _this->m_about.Show(TRUE); break; case ID_VISITUSONLINE_HOMEPAGE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -openhomepage"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess); //if (error==1314) // { // Open_homepage(); // } } } } break; case ID_VISITUSONLINE_FORUM: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -openforum"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess); //if (error==1314) // { // Open_forum(); // } } } } break; case ID_CLOSE: // User selected Close from the tray menu fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_UNINSTALL_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -uninstallhelper"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD errorcode=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (errorcode==1314) { Set_uninstall_service_as_admin(); } } fShutdownOrdered=TRUE; vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; case ID_RUNASSERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -installhelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (error==1314) { Set_install_service_as_admin(); } } fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } break; case ID_CLOSE_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) { CloseHandle(hProcess); break; } char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -stopservicehelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (hProcess) CloseHandle(hProcess); if (error==1314) { Set_stop_service_as_admin(); } } } break; case ID_START_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) { CloseHandle(hProcess); break; } char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -startservicehelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (hPToken) CloseHandle(hPToken); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (hProcess) CloseHandle(hProcess); if (error==1314) { Set_start_service_as_admin(); } fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; } return 0; case WM_TRAYNOTIFY: // User has clicked on the tray icon or the menu { // Get the submenu to use as a pop-up menu HMENU submenu = GetSubMenu(_this->m_hmenu, 0); // What event are we responding to, RMB click? if (lParam==WM_RBUTTONUP) { if (submenu == NULL) { vnclog.Print(LL_INTERR, VNCLOG("no submenu available\n")); return 0; } // Make the first menu item the default (bold font) SetMenuDefaultItem(submenu, 0, TRUE); // Get the current cursor position, to display the menu at POINT mouse; GetCursorPos(&mouse); // There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // SetForegroundWindow(_this->m_nid.hWnd); // Display the menu at the desired position TrackPopupMenu(submenu, 0, mouse.x, mouse.y, 0, _this->m_nid.hWnd, NULL); PostMessage(hwnd, WM_NULL, 0, 0); return 0; } // Or was there a LMB double click? if (lParam==WM_LBUTTONDBLCLK) { // double click: execute first menu item SendMessage(_this->m_nid.hWnd, WM_COMMAND, GetMenuItemID(submenu, 0), 0); } return 0; } case WM_CLOSE: // Only accept WM_CLOSE if the logged on user has AllowShutdown set if (!_this->m_properties.AllowShutdown()) { return 0; } // tnatsni Wallpaper fix if (_this->m_server->RemoveWallpaperEnabled()) RestoreWallpaper(); if (_this->m_server->RemoveAeroEnabled()) ResetAero(); vnclog.Print(LL_INTERR, VNCLOG("vncMenu WM_CLOSE call - All cleanup done\n")); Sleep(2000); DestroyWindow(hwnd); break; case WM_DESTROY: // The user wants WinVNC to quit cleanly... vnclog.Print(LL_INTINFO, VNCLOG("quitting from WM_DESTROY\n")); PostQuitMessage(0); return 0; case WM_QUERYENDSESSION: { //shutdown or reboot if((lParam & ENDSESSION_LOGOFF) != ENDSESSION_LOGOFF) { fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTERR, VNCLOG("SHUTDOWN OS detected\n")); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); break; } DWORD SessionID; SessionID=GetCurrentSessionID(); vnclog.Print(LL_INTERR, VNCLOG("Session ID %i\n"),SessionID); if (SessionID!=0) { fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTERR, VNCLOG("WM_QUERYENDSESSION session!=0\n")); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; case WM_ENDSESSION: vnclog.Print(LL_INTERR, VNCLOG("WM_ENDSESSION\n")); break; case WM_USERCHANGED: // The current user may have changed. { strcpy(newuser,""); if (vncService::CurrentUser((char *) &newuser, sizeof(newuser))) { vnclog.Print(LL_INTINFO, VNCLOG("############### Usernames change: old=\"%s\", new=\"%s\"\n"), _this->m_username, newuser); // Check whether the user name has changed! if (_stricmp(newuser, _this->m_username) != 0) { vnclog.Print(LL_INTINFO, VNCLOG("user name has changed\n")); // User has changed! strcpy(_this->m_username, newuser); // Redraw the tray icon and set it's state _this->DelTrayIcon(); _this->AddTrayIcon(); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); // We should load in the prefs for the new user if (_this->m_properties.m_fUseRegistry) { _this->m_properties.Load(TRUE); _this->m_propertiesPoll.Load(TRUE); } else { _this->m_properties.LoadFromIniFile(); _this->m_propertiesPoll.LoadFromIniFile(); } } } } return 0; // [v1.0.2-jp1 fix] Don't show IME toolbar on right click menu. case WM_INITMENU: case WM_INITMENUPOPUP: SendMessage(ImmGetDefaultIMEWnd(hwnd), WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0); return 0; default: // Deal with any of our custom message types // wa@2005 -- added support for the AutoReconnectId // removed the previous code that used 999,999 if ( iMsg == MENU_AUTO_RECONNECT_MSG ) { char szId[MAX_PATH] = {0}; UINT ret = 0; if ( lParam != NULL ) { ret = GlobalGetAtomName( (ATOM)lParam, szId, sizeof( szId ) ); GlobalDeleteAtom( (ATOM)lParam ); } _this->m_server->AutoReconnect(true); if ( ret > 0 ) _this->m_server->AutoReconnectId(szId); return 0; } if ( iMsg == MENU_REPEATER_ID_MSG ) { char szId[MAX_PATH] = {0}; UINT ret = 0; if ( lParam != NULL ) { ret = GlobalGetAtomName( (ATOM)lParam, szId, sizeof( szId ) ); GlobalDeleteAtom( (ATOM)lParam ); } _this->m_server->IdReconnect(true); if ( ret > 0 ) _this->m_server->AutoReconnectId(szId); return 0; } if (iMsg == MENU_ADD_CLIENT_MSG) { /* // sf@2005 - FTNoUserImpersonation // Dirty trick to avoid to add a new MSG... no time if (lParam == 998) { _this->m_server->FTUserImpersonation(false); return 0; } */ // Add Client message. This message includes an IP address // of a listening client, to which we should connect. //adzm 2009-06-20 - Check for special add repeater client message if (wParam == 0xFFFFFFFF && lParam == 0xFFFFFFFF) { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { if (IDOK != newconn->DoDialog()) { if (SPECIAL_SC_PROMPT && _this->m_server->AuthClientCount() == 0 && _this->m_server->UnauthClientCount() == 0) { PostMessage(hwnd, WM_COMMAND, ID_CLOSE, 0); } } } return 0; } // If there is no IP address then show the connection dialog if (!lParam) { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { newconn->DoDialog(); // winvnc -connect fixed //CHECH memeory leak // delete newconn; } return 0; } unsigned short nport = 0; char *nameDup = 0; char szAdrName[64]; char szId[MAX_PATH] = {0}; // sf@2003 - Values are already converted if ((_this->m_server->AutoReconnect()|| _this->m_server->IdReconnect() )&& strlen(_this->m_server->AutoReconnectAdr()) > 0) { nport = _this->m_server->AutoReconnectPort(); strcpy(szAdrName, _this->m_server->AutoReconnectAdr()); } else { // Get the IP address stringified struct in_addr address; address.S_un.S_addr = lParam; char *name = inet_ntoa(address); if (name == 0) return 0; nameDup = _strdup(name); if (nameDup == 0) return 0; strcpy(szAdrName, nameDup); // Free the duplicate name if (nameDup != 0) free(nameDup); // Get the port number nport = (unsigned short)wParam; if (nport == 0) nport = INCOMING_PORT_OFFSET; } // wa@2005 -- added support for the AutoReconnectId // (but it's not required) bool bId = ( strlen(_this->m_server->AutoReconnectId() ) > 0); if ( bId ) strcpy( szId, _this->m_server->AutoReconnectId() ); // sf@2003 // Stores the client adr/ports the first time we try to connect // This way we can call this message again later to reconnect with the same values if ((_this->m_server->AutoReconnect() || _this->m_server->IdReconnect())&& strlen(_this->m_server->AutoReconnectAdr()) == 0) { _this->m_server->AutoReconnectAdr(szAdrName); _this->m_server->AutoReconnectPort(nport); } // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (tmpsock) { // Connect out to the specified host on the VNCviewer listen port tmpsock->Create(); if (tmpsock->Connect(szAdrName, nport)) { if ( bId ) { // wa@2005 -- added support for the AutoReconnectId // Set the ID for this client -- code taken from vncconndialog.cpp (ln:142) tmpsock->Send(szId,250); tmpsock->SetTimeout(0); // adzm 2009-07-05 - repeater IDs // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, szId, szAdrName, nport); } else { // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, NULL, szAdrName, nport); } } else { delete tmpsock; _this->m_server->AutoConnectRetry(); } } return 0; } // Process FileTransfer asynchronous Send Packet Message if (iMsg == FileTransferSendPacketMessage) { vncClient* pClient = (vncClient*) wParam; if (_this->m_server->IsClient(pClient)) pClient->SendFileChunk(); } // adzm 2009-07-05 - Tray icon balloon tips if (iMsg == MENU_TRAYICON_BALLOON_MSG) { omni_mutex_lock sync(_this->m_mutexTrayIcon); // adzm 2009-07-05 - Tray icon balloon tips if (_this->m_BalloonInfo) { free(_this->m_BalloonInfo); _this->m_BalloonInfo = NULL; } if (_this->m_BalloonTitle) { free(_this->m_BalloonTitle); _this->m_BalloonTitle = NULL; } char* szInfo = (char*)wParam; char* szTitle = (char*)lParam; if (szInfo && (strlen(szInfo) > 0) ) { _this->m_BalloonInfo = _strdup(szInfo); } if (szTitle && (strlen(szTitle) > 0) ) { _this->m_BalloonTitle = _strdup(szTitle); } if (szInfo) { free(szInfo); } if (szTitle) { free(szTitle); } if (_this->IsIconSet) { _this->SendTrayMsg(NIM_MODIFY, _this->m_nid.hIcon == _this->m_winvnc_icon ? FALSE : TRUE); } } } // Message not recognised return DefWindowProc(hwnd, iMsg, wParam, lParam); }
void vncClientThread::run(void *arg) { // All this thread does is go into a socket-recieve 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()); // 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. // 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")); // INIT PIXEL FORMAT // Get the screen format m_client->m_fullscreen = m_client->m_encodemgr.GetSize(); // Get the name of this desktop char desktopname[MAX_COMPUTERNAME_LENGTH+1]; DWORD desktopnamelen = MAX_COMPUTERNAME_LENGTH + 1; if (GetComputerName(desktopname, &desktopnamelen)) { // Make the name lowercase for (int x=0; x<strlen(desktopname); x++) { desktopname[x] = tolower(desktopname[x]); } } else { strcpy(desktopname, "WinVNC"); } // Send the server format message to the client rfbServerInitMsg server_ini; server_ini.format = m_client->m_encodemgr.m_buffer->GetLocalFormat(); // Endian swaps server_ini.framebufferWidth = Swap16IfLE(m_client->m_fullscreen.br.x); server_ini.framebufferHeight = Swap16IfLE(m_client->m_fullscreen.br.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 { omni_mutex_lock l(m_client->GetUpdateLock()); m_client->m_update_tracker.add_changed(m_client->m_fullscreen); } // 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; // 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)+1, sz_rfbSetPixelFormatMsg-1)) { 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); // 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)+1, sz_rfbSetEncodingsMsg-1)) { connected = FALSE; break; } // 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++) { CARD32 encoding; // Read an encoding in if (!m_socket->ReadExact((char *)&encoding, sizeof(encoding))) { connected = FALSE; break; } // Is this the CopyRect encoding (a special case)? if (Swap32IfLE(encoding) == rfbEncodingCopyRect) { m_client->m_update_tracker.enable_copyrect(true); continue; } // Have we already found a suitable encoding? if (!encoding_set) { // No, so try the buffer to see if this encoding will work... if (m_client->m_encodemgr.SetEncoding(Swap32IfLE(encoding))) encoding_set = TRUE; } } // If no encoding worked then default to RAW! if (!encoding_set) { vnclog.Print(LL_INTINFO, VNCLOG("defaulting to raw encoder\n")); if (!m_client->m_encodemgr.SetEncoding(Swap32IfLE(rfbEncodingRaw))) { vnclog.Print(LL_INTERR, VNCLOG("failed to select raw encoder!\n")); connected = FALSE; } } } // Re-enable updates m_client->EnableProtocol(); break; case rfbFramebufferUpdateRequest: // Read the rest of the message: if (!m_socket->ReadExact(((char *) &msg)+1, sz_rfbFramebufferUpdateRequestMsg-1)) { connected = FALSE; break; } { rfb::Rect update; // Get the specified rectangle as the region to send updates for. update.tl.x = Swap16IfLE(msg.fur.x); update.tl.y = Swap16IfLE(msg.fur.y); update.br.x = update.tl.x + Swap16IfLE(msg.fur.w); update.br.y = update.tl.y + Swap16IfLE(msg.fur.h); rfb::Region2D update_rgn = update; if (update_rgn.is_empty()) { vnclog.Print(LL_INTERR, VNCLOG("FATAL! client update region is empty!\n")); connected = FALSE; break; } { omni_mutex_lock l(m_client->GetUpdateLock()); // Add the requested area to the incremental update cliprect m_client->m_incr_rgn = m_client->m_incr_rgn.union_(update_rgn); // Is this request for a full update? if (!msg.fur.incremental) { // Yes, so add the region to the update tracker m_client->m_update_tracker.add_changed(update_rgn); // Tell the desktop grabber to fetch the region's latest state m_client->m_encodemgr.m_buffer->m_desktop->QueueRect(update); } // Kick the update thread (and create it if not there already) m_client->TriggerUpdateThread(); } } break; case rfbKeyEvent: // Read the rest of the message: if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbKeyEventMsg-1)) { if (m_client->m_keyboardenabled) { msg.ke.key = Swap32IfLE(msg.ke.key); // Get the keymapper to do the work vncKeymap::keyEvent(msg.ke.key, msg.ke.down); m_client->m_remoteevent = TRUE; } } break; case rfbPointerEvent: // Read the rest of the message: if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbPointerEventMsg-1)) { if (m_client->m_pointerenabled) { // Convert the coords to Big Endian msg.pe.x = Swap16IfLE(msg.pe.x); msg.pe.y = Swap16IfLE(msg.pe.y); // Work out the flags for this event DWORD flags = MOUSEEVENTF_ABSOLUTE; long data = 0; if (msg.pe.x != m_client->m_ptrevent.x || msg.pe.y != m_client->m_ptrevent.y) flags |= MOUSEEVENTF_MOVE; if ( (msg.pe.buttonMask & rfbButton1Mask) != (m_client->m_ptrevent.buttonMask & rfbButton1Mask) ) { if (GetSystemMetrics(SM_SWAPBUTTON)) flags |= (msg.pe.buttonMask & rfbButton1Mask) ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; else flags |= (msg.pe.buttonMask & rfbButton1Mask) ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; } if ( (msg.pe.buttonMask & rfbButton2Mask) != (m_client->m_ptrevent.buttonMask & rfbButton2Mask) ) { flags |= (msg.pe.buttonMask & rfbButton2Mask) ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; } if ( (msg.pe.buttonMask & rfbButton3Mask) != (m_client->m_ptrevent.buttonMask & rfbButton3Mask) ) { if (GetSystemMetrics(SM_SWAPBUTTON)) flags |= (msg.pe.buttonMask & rfbButton3Mask) ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; else flags |= (msg.pe.buttonMask & rfbButton3Mask) ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; } // Mouse wheel support if (msg.pe.buttonMask & rfbWheelUpMask) { flags |= MOUSEEVENTF_WHEEL; data = WHEEL_DELTA; } if (msg.pe.buttonMask & rfbWheelDownMask) { flags |= MOUSEEVENTF_WHEEL; data = -WHEEL_DELTA; } // Generate coordinate values unsigned long x = (msg.pe.x * 65535) / (m_client->m_fullscreen.br.x); unsigned long y = (msg.pe.y * 65535) / (m_client->m_fullscreen.br.y); // Do the pointer event ::mouse_event(flags, (DWORD) x, (DWORD) y, data, 0); // Save the old position m_client->m_ptrevent = msg.pe; // Flag that a remote event occurred m_client->m_remoteevent = TRUE; // Tell the desktop hook system to grab the screen... m_client->m_encodemgr.m_buffer->m_desktop->TriggerUpdate(); } } break; case rfbClientCutText: // Read the rest of the message: if (m_socket->ReadExact(((char *) &msg)+1, sz_rfbClientCutTextMsg-1)) { // Allocate storage for the text const UINT length = Swap32IfLE(msg.cct.length); char *text = new char [length+1]; if (text == NULL) break; text[length] = 0; // Read in the text if (!m_socket->ReadExact(text, length)) { delete [] text; break; } // Get the server to update the local clipboard m_server->UpdateLocalClipText(text); // Free the clip text we read delete [] text; } break; default: // Unknown message, so fail! connected = FALSE; } } // Move into the thread's original desktop vncService::SelectHDESK(home_desktop); // Quit this thread. This will automatically delete the thread and the // associated client. vnclog.Print(LL_CLIENTS, VNCLOG("client disconnected : %s (%hd)\n"), m_client->GetClientName(), m_client->GetClientId()); // Disable the protocol to ensure that the update thread // is not accessing the desktop and buffer objects m_client->DisableProtocol(); // Finally, it's safe to kill the update thread here if (m_client->m_updatethread) { m_client->m_updatethread->Kill(); m_client->m_updatethread->join(NULL); } // Remove the client from the server // This may result in the desktop and buffer being destroyed // It also guarantees that the client will not be passed further // updates m_server->RemoveClient(m_client->GetClientId()); }
BOOL vncClientThread::InitAuthenticate() { // Retrieve the local password char password[MAXPWLEN]; m_server->GetPassword(password); vncPasswd::ToText plain(password); // Verify the peer host name against the AuthHosts string vncServer::AcceptQueryReject verified; if (m_auth) { verified = vncServer::aqrAccept; } else { verified = m_server->VerifyHost(m_socket->GetPeerName()); } // If necessary, query the connection with a timed dialog if (verified == vncServer::aqrQuery) { vncAcceptDialog *acceptDlg = new vncAcceptDialog(m_server->QueryTimeout(), m_socket->GetPeerName()); if ((acceptDlg == 0) || (!(acceptDlg->DoDialog()))) verified = vncServer::aqrReject; } if (verified == vncServer::aqrReject) { CARD32 auth_val = Swap32IfLE(rfbConnFailed); char *errmsg = "Your connection has been rejected."; CARD32 errlen = Swap32IfLE(strlen(errmsg)); if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val))) return FALSE; if (!m_socket->SendExact((char *)&errlen, sizeof(errlen))) return FALSE; m_socket->SendExact(errmsg, strlen(errmsg)); return FALSE; } // By default we disallow passwordless workstations! if ((strlen(plain) == 0) && m_server->AuthRequired()) { vnclog.Print(LL_CONNERR, VNCLOG("no password specified for server - client rejected\n")); // Send an error message to the client CARD32 auth_val = Swap32IfLE(rfbConnFailed); char *errmsg = "This server does not have a valid password enabled. " "Until a password is set, incoming connections cannot be accepted."; CARD32 errlen = Swap32IfLE(strlen(errmsg)); if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val))) return FALSE; if (!m_socket->SendExact((char *)&errlen, sizeof(errlen))) return FALSE; m_socket->SendExact(errmsg, strlen(errmsg)); return FALSE; } // By default we filter out local loop connections, because they're pointless if (!m_server->LoopbackOk()) { char *localname = strdup(m_socket->GetSockName()); char *remotename = strdup(m_socket->GetPeerName()); // Check that the local & remote names are different! if ((localname != NULL) && (remotename != NULL)) { BOOL ok = strcmp(localname, remotename) != 0; if (localname != NULL) free(localname); if (remotename != NULL) free(remotename); if (!ok) { vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client rejected\n")); // Send an error message to the client CARD32 auth_val = Swap32IfLE(rfbConnFailed); char *errmsg = "Local loop-back connections are disabled."; CARD32 errlen = Swap32IfLE(strlen(errmsg)); if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val))) return FALSE; if (!m_socket->SendExact((char *)&errlen, sizeof(errlen))) return FALSE; m_socket->SendExact(errmsg, strlen(errmsg)); return FALSE; } } } // Authenticate the connection, if required if (m_auth || (strlen(plain) == 0)) { // Send no-auth-required message CARD32 auth_val = Swap32IfLE(rfbNoAuth); if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val))) return FALSE; } else { // Send auth-required message CARD32 auth_val = Swap32IfLE(rfbVncAuth); if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val))) return FALSE; BOOL auth_ok = TRUE; { // Now create a 16-byte challenge char challenge[16]; vncRandomBytes((BYTE *)&challenge); // Send the challenge to the client if (!m_socket->SendExact(challenge, sizeof(challenge))) return FALSE; // Read the response char response[16]; if (!m_socket->ReadExact(response, sizeof(response)))\ return FALSE; // Encrypt the challenge bytes vncEncryptBytes((BYTE *)&challenge, plain); // Compare them to the response for (int i=0; i<sizeof(challenge); i++) { if (challenge[i] != response[i]) { auth_ok = FALSE; break; } } } // Did the authentication work? CARD32 authmsg; if (!auth_ok) { vnclog.Print(LL_CONNERR, VNCLOG("authentication failed\n")); authmsg = Swap32IfLE(rfbVncAuthFailed); m_socket->SendExact((char *)&authmsg, sizeof(authmsg)); return FALSE; } else { // Tell the client we're ok authmsg = Swap32IfLE(rfbVncAuthOK); 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 (!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()); }
extern "C" DLLEXPORT /*export without name mangling*/ int WinVNCDll_ListenForClient(PSTR szRemoteClient, PSTR szIdCode) { // Compatible with both RealVNC and TightVNC methods char hostname[_MAX_PATH]; char actualhostname[_MAX_PATH]; char idcode[_MAX_PATH]; char *portp; int port; bool id; // Get the hostname of the VNCviewer strcpy(hostname, szRemoteClient); strcpy(idcode, szIdCode); //GetDlgItemText(hwnd, IDC_HOSTNAME_EDIT, hostname, _MAX_PATH); //GetDlgItemText(hwnd, IDC_IDCODE, idcode, _MAX_PATH); if (strcmp(idcode,"")==0) id=false; else id=true; strcpy(actualhostname, hostname); vnclog.Print(LL_STATE, VNCLOG("WinVNCDll_ListenForClient(%s %s)\n"),hostname,idcode); //adzm 2010-02-15 - Multiple repeaters chosen by modulo of ID char finalidcode[_MAX_PATH]; //adzm 2010-08 - this was sending uninitialized data over the wire ZeroMemory(finalidcode, sizeof(finalidcode)); //adzm 2009-06-20 if (id) { size_t i = 0; for (i = 0; i < strlen(idcode); i++) { finalidcode[i] = toupper(idcode[i]); } finalidcode[i] = 0; if (0 != strncmp("ID:", idcode, 3)) { strcpy(finalidcode, "ID:"); for (i = 0; i < strlen(idcode); i++) { finalidcode[i+3] = toupper(idcode[i]); } finalidcode[i+3] = 0; } //adzm 2010-02-15 - At this point, finalidcode is of the form "ID:#####" int numericId = atoi(finalidcode + 3); int numberOfHosts = 1; for (i = 0; i < strlen(hostname); i++) { if (hostname[i] == ';') { numberOfHosts++; } } if (numberOfHosts <= 1) { // then hostname == actualhostname } else { int modulo = numericId % numberOfHosts; char* szToken = strtok(hostname, ";"); while (szToken) { if (modulo == 0) { strcpy(actualhostname, szToken); break; } modulo--; szToken = strtok(NULL, ";"); } } } // Calculate the Display and Port offset. port = INCOMING_PORT_OFFSET; portp = strchr(actualhostname, ':'); if (portp) { *portp++ = '\0'; if (*portp == ':') // Tight127 method { port = atoi(++portp); // Port number after "::" } else // RealVNC method { if (atoi(portp) < 100) // If < 100 after ":" -> display number port += atoi(portp); else port = atoi(portp); // If > 100 after ":" -> Port number } } // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (!tmpsock) { vnclog.Print(LL_STATE, VNCLOG("Could not create socket\n")); return -1; } // Connect out to the specified host on the VNCviewer listen port // To be really good, we should allow a display number here but // for now we'll just assume we're connecting to display zero tmpsock->Create(); vnclog.Print(LL_STATE, VNCLOG("Connecting to: %s %d\n"),actualhostname,port); if (tmpsock->Connect(actualhostname, port)) { vnclog.Print(LL_STATE, VNCLOG("Adding client: %s %d\n"),actualhostname,port); if (id) { tmpsock->Send(finalidcode,250); tmpsock->SetTimeout(0); // adzm 2009-07-05 - repeater IDs // Add the new client to this server // adzm 2009-08-02 return m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, finalidcode, actualhostname, port); } else { // Add the new client to this server // adzm 2009-08-02 return m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, NULL, actualhostname, port); } } }
// 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); vnclog.Print(LL_CLIENTS, VNCLOG("trying port number %d\n"), m_port); // 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_port_http == m_port) { vnclog.Print(LL_INTERR, VNCLOG("cannot start both RFB and HTTP servers " "on the same port\n")); } 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; }