📄 vncservice.cpp
字号:
// Copyright (C) 2002-2003 RealVNC Ltd. 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.//// 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.// vncService// Implementation of service-oriented functionality of WinVNC#include "stdhdrs.h"// Header#include "vncService.h"#include <lmcons.h>#include "omnithread.h"#include "WinVNC.h"#include "vncMenu.h"#include "vncTimedMsgBox.h"// Error message loggingvoid LogErrorMsg(char *message);// OS-SPECIFIC ROUTINES// Create an instance of the vncService class to cause the static fields to be// initialised properlyvncService init;DWORD g_platform_id;BOOL g_impersonating_user = 0;DWORD g_version_major;DWORD g_version_minor;vncService::vncService(){ OSVERSIONINFO osversioninfo; osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo); // Get the current OS version if (!GetVersionEx(&osversioninfo)) g_platform_id = 0; g_platform_id = osversioninfo.dwPlatformId; g_version_major = osversioninfo.dwMajorVersion; g_version_minor = osversioninfo.dwMinorVersion;}// CurrentUser - fills a buffer with the name of the current user!BOOLGetCurrentUser(char *buffer, UINT size){ // How to obtain the name of the current user depends upon the OS being used if ((g_platform_id == VER_PLATFORM_WIN32_NT) && vncService::RunningAsService()) { // Windows NT, service-mode // -=- FIRSTLY - verify that a user is logged on // Get the current Window station HWINSTA station = GetProcessWindowStation(); if (station == NULL) return FALSE; // Get the current user SID size DWORD usersize; GetUserObjectInformation(station, UOI_USER_SID, NULL, 0, &usersize); // Check the required buffer size isn't zero if (usersize == 0) { // No user is logged in - ensure we're not impersonating anyone RevertToSelf(); g_impersonating_user = FALSE; // Return "" as the name... if (strlen("") >= size) return FALSE; strcpy(buffer, ""); return TRUE; } // -=- SECONDLY - a user is logged on but if we're not impersonating // them then we can't continue! if (!g_impersonating_user) { // Return "" as the name... if (strlen("") >= size) return FALSE; strcpy(buffer, ""); return TRUE; } } // -=- When we reach here, we're either running under Win9x, or we're running // under NT as an application or as a service impersonating a user // Either way, we should find a suitable user name. switch (g_platform_id) { case VER_PLATFORM_WIN32_WINDOWS: case VER_PLATFORM_WIN32_NT: { // Just call GetCurrentUser DWORD length = size; if (GetUserName(buffer, &length) == 0) { UINT error = GetLastError(); if (error == ERROR_NOT_LOGGED_ON) { // No user logged on if (strlen("") >= size) return FALSE; strcpy(buffer, ""); return TRUE; } else { // Genuine error... vnclog.Print(LL_INTERR, VNCLOG("getusername error %d\n"), GetLastError()); return FALSE; } } } return TRUE; }; // OS was not recognised! return FALSE;}BOOLvncService::CurrentUser(char *buffer, UINT size){ BOOL result = GetCurrentUser(buffer, size); if (result && (strcmp(buffer, "") == 0) && !vncService::RunningAsService()) { strncpy(buffer, "Default", size); } return result;}// IsWin95 - returns a BOOL indicating whether the current OS is Win95BOOLvncService::IsWin95(){ return (g_platform_id == VER_PLATFORM_WIN32_WINDOWS);}// IsWinNT - returns a bool indicating whether the current OS is WinNTBOOLvncService::IsWinNT(){ return (g_platform_id == VER_PLATFORM_WIN32_NT);}// Version infoDWORDvncService::VersionMajor(){ return g_version_major;}DWORDvncService::VersionMinor(){ return g_version_minor;}// Internal routine to find the WinVNC menu class window and// post a message to it!BOOLPostToWinVNC(UINT message, WPARAM wParam, LPARAM lParam){ // Locate the hidden WinVNC menu window HWND hservwnd = FindWindow(MENU_CLASS_NAME, NULL); if (hservwnd == NULL) return FALSE; // Post the message to WinVNC PostMessage(hservwnd, message, wParam, lParam); return TRUE;}// Static routines only used on Windows NT to ensure we're in the right desktop// These routines are generally available to any thread at any time.// - SelectDesktop(HDESK)// Switches the current thread into a different desktop by deskto handle// This call takes care of all the evil memory management involvedBOOLvncService::SelectHDESK(HDESK new_desktop){ // Are we running on NT? if (IsWinNT()) { HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId()); DWORD dummy; char new_name[256]; if (!GetUserObjectInformation(new_desktop, UOI_NAME, &new_name, 256, &dummy)) { return FALSE; } vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK to %s (%x) from %x\n"), new_name, new_desktop, old_desktop); // Switch the desktop if(!SetThreadDesktop(new_desktop)) { vnclog.Print(LL_INTERR, VNCLOG("unable to SetThreadDesktop\n"), GetLastError()); return FALSE; } // Switched successfully - destroy the old desktop if (!CloseDesktop(old_desktop)) vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK failed to close old desktop %x (Err=%d)\n"), old_desktop, GetLastError()); return TRUE; } return TRUE;}// - SelectDesktop(char *)// Switches the current thread into a different desktop, by name// Calling with a valid desktop name will place the thread in that desktop.// Calling with a NULL name will place the thread in the current input desktop.BOOLvncService::SelectDesktop(char *name){ // Are we running on NT? if (IsWinNT()) { HDESK desktop; if (name != NULL) { // Attempt to open the named desktop desktop = OpenDesktop(name, 0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); } else { // No, so open the input desktop desktop = OpenInputDesktop(0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); } // Did we succeed? if (desktop == NULL) { vnclog.Print(LL_INTERR, VNCLOG("unable to open desktop:%d\n"), GetLastError()); return FALSE; } // Switch to the new desktop if (!SelectHDESK(desktop)) { // Failed to enter the new desktop, so free it! if (!CloseDesktop(desktop)) vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop failed to close desktop:%d\n"), GetLastError()); return FALSE; } // We successfully switched desktops! return TRUE; } return (name == NULL);}// Find the visible window station and switch to it// This would allow the service to be started non-interactive// Needs more supporting code & a redesign of the server core to// work, with better partitioning between server & UI components.static HWINSTA home_window_station = GetProcessWindowStation();BOOL CALLBACK WinStationEnumProc(LPTSTR name, LPARAM param) { HWINSTA station = OpenWindowStation(name, FALSE, GENERIC_ALL); HWINSTA oldstation = GetProcessWindowStation(); USEROBJECTFLAGS flags; if (!GetUserObjectInformation(station, UOI_FLAGS, &flags, sizeof(flags), NULL)) { return TRUE; } BOOL visible = flags.dwFlags & WSF_VISIBLE; if (visible) { if (SetProcessWindowStation(station)) { if (oldstation != home_window_station) { CloseWindowStation(oldstation); } } else { CloseWindowStation(station); } return FALSE; } return TRUE;}BOOLvncService::SelectInputWinStation(){ home_window_station = GetProcessWindowStation(); return EnumWindowStations(&WinStationEnumProc, NULL);}voidvncService::SelectHomeWinStation(){ HWINSTA station=GetProcessWindowStation(); SetProcessWindowStation(home_window_station); CloseWindowStation(station);}// NT only function to establish whether we're on the current input desktopBOOLvncService::InputDesktopSelected(){ // Are we running on NT? if (IsWinNT()) { // Get the input and thread desktops HDESK threaddesktop = GetThreadDesktop(GetCurrentThreadId()); HDESK inputdesktop = OpenInputDesktop(0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); // Get the desktop names: // *** I think this is horribly inefficient but I'm not sure. if (inputdesktop == NULL) return FALSE; DWORD dummy; char threadname[256]; char inputname[256]; if (!GetUserObjectInformation(threaddesktop, UOI_NAME, &threadname, 256, &dummy)) { if (!CloseDesktop(inputdesktop)) vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n")); return FALSE; } _ASSERT(dummy <= 256); if (!GetUserObjectInformation(inputdesktop, UOI_NAME, &inputname, 256, &dummy)) { if (!CloseDesktop(inputdesktop)) vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n")); return FALSE; } _ASSERT(dummy <= 256); if (!CloseDesktop(inputdesktop)) vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n")); if (strcmp(threadname, inputname) != 0) return FALSE; } return TRUE;}// Static routine used to fool Winlogon into thinking CtrlAltDel was pressedvoid *SimulateCtrlAltDelThreadFn(void *context){ HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId()); // Switch into the Winlogon desktop if (!vncService::SelectDesktop("Winlogon")) { vnclog.Print(LL_INTERR, VNCLOG("failed to select logon desktop\n")); return FALSE; } vnclog.Print(LL_ALL, VNCLOG("generating ctrl-alt-del\n")); // Fake a hotkey event to any windows we find there.... :( // Winlogon uses hotkeys to trap Ctrl-Alt-Del... PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); // Switch back to our original desktop if (old_desktop != NULL) vncService::SelectHDESK(old_desktop); return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -