📄 vncservice.cpp
字号:
// Copyright (C) 2006 Teamviewer GmbH. All Rights Reserved.
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of TeamViewer.
//
// TeamViewer 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 TeamViewer is not available from the place
// whence you received this file, check http://www.teamviewer.com
// for information on obtaining it.
// vncService
// Implementation of service-oriented functionality of WinVNC
#include "stdhdrs.h"
// Header
#include "vncService.h"
#include "vncMenu.h"
#include "vncTimedMsgBox.h"
#include "localization.h" // Act : add localization on messages
#include "Global.h"
#include "vncproperties.h"
#include "teamviewerinfo.h"
// Error message logging
void LogErrorMsg(char *message);
BOOL serviceshutdown;
// OS-SPECIFIC ROUTINES
// Create an instance of the vncService class to cause the static fields to be
// initialised properly
vncService init;
DWORD g_platform_id;
BOOL g_impersonating_user = 0;
DWORD g_version_major;
DWORD g_version_minor;
HANDLE vncService::m_impersonationtoken = 0;
bool vncService::bBeganImpersonation = false;
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;
serviceshutdown=false;
//already done
//HANDLE vncService::m_impersonationtoken = 0;
//bool vncService::bBeganImpersonation = false;
}
// CurrentUser - fills a buffer with the name of the current user!
BOOL
GetCurrentUser(char *buffer, UINT size) // RealVNC 336 change
{ // 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);
DWORD dwErrorCode = GetLastError();
SetLastError(0);
// Check the required buffer size isn't zero
if (usersize == 0)
{
// No user is logged in - ensure we're not impersonating anyone
RevertToSelf();
// 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"), GetLastError());
return FALSE;
}
}
}
return TRUE;
};
// OS was not recognised!
return FALSE;
}
// RealVNC 336 change
BOOL
vncService::CurrentUser(char *buffer, UINT size)
{
BOOL result = GetCurrentUser(buffer, size);
if (result && (strcmp(buffer, "") == 0) && !vncService::RunningAsService())
{
strncpy(buffer, "Default", size);
}
return result;
}
BOOL vncService::BeginImpersonation()
{
char buffer[256];
GetCurrentUser(buffer, 255);
buffer[255] = '\0';
// if running as service and current thread is not impersonated try to impersonate it
//vnclog.Print(LL_INTINFO, VNCLOG("BeginImpersonation %s"), buffer);
if(vncService::RunningAsService() && strcmp(buffer, "SYSTEM") == 0)
{
BOOL ok = ImpersonateUser();
if(ok)
{
bBeganImpersonation = true;
GetCurrentUser(buffer, 255);
buffer[255] = '\0';
vnclog.Print(LL_INTINFO, VNCLOG("impersonating user %s"), buffer);
}
return ok;
}
else
return FALSE;
}
BOOL vncService::EndImpersonation()
{
char buffer[256];
GetCurrentUser(buffer, 255);
buffer[255] = '\0';
//vnclog.Print(LL_INTINFO, VNCLOG("EndImpersonation %s"), buffer);
// test if running as service and username not "SYSTEM"
if(vncService::RunningAsService() && strcmp(buffer, "SYSTEM") != 0)
{
RevertToSelf();
vnclog.Print(LL_INTINFO, VNCLOG("finishing impersonation"), buffer);
bBeganImpersonation = false;
return TRUE;
}
else
return FALSE;
}
BOOL vncService::isImpersonated()
{
return (bBeganImpersonation);
}
BOOL vncService::IsWSLocked()
{
if (!IsWinNT())
return false;
bool bLocked = false;
HDESK hDesk;
BOOL bRes;
DWORD dwLen;
char sName[200];
hDesk = OpenInputDesktop(0, FALSE, 0);
if (hDesk == NULL)
{
bLocked = true;
}
else
{
bRes = GetUserObjectInformation(hDesk, UOI_NAME, sName, sizeof(sName), &dwLen);
if (bRes)
sName[dwLen]='\0';
else
sName[0]='\0';
CloseDesktop(hDesk);
if (stricmp(sName,"Default") != 0)
bLocked = true; // WS is locked or screen saver active
else
bLocked = false ;
}
return bLocked;
}
// IsWin95 - returns a BOOL indicating whether the current OS is Win95
BOOL
vncService::IsWin95()
{
return (g_platform_id == VER_PLATFORM_WIN32_WINDOWS);
}
// IsWinNT - returns a bool indicating whether the current OS is WinNT
BOOL
vncService::IsWinNT()
{
return (g_platform_id == VER_PLATFORM_WIN32_NT);
}
// Version info
DWORD
vncService::VersionMajor()
{
return g_version_major;
}
DWORD
vncService::VersionMinor()
{
return g_version_minor;
}
// Internal routine to find the WinVNC menu class window and
// post a message to it!
BOOL
PostToWinVNC(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 involved
BOOL
vncService::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"), new_name, new_desktop, old_desktop);
// Switch the desktop
if(!SetThreadDesktop(new_desktop)) {
return FALSE;
}
// Switched successfully - destroy the old desktop
if (old_desktop != new_desktop)
if(!CloseDesktop(old_desktop))
vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK failed to close old desktop %x (Err=%d)"), 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.
BOOL
vncService::SelectDesktop(char *name, BOOL silent)
{
// Are we running on NT?
if (IsWinNT())
{
HDESK desktop;
if(!silent)
vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop "));
if (name != NULL)
{
if(!silent)
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 named"));
// 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
{
if(!silent)
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 NULL"));
// 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)
{
if(!silent)
vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 "));
return FALSE;
}
else vnclog.Print(LL_INTERR, VNCLOG("OpenInputdesktop2 OK"));
// Switch to the new desktop
if (!SelectHDESK(desktop))
{
// Failed to enter the new desktop, so free it!
if (!CloseDesktop(desktop))
{
if(!silent)
vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop failed to close desktop"));
}
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;
}
BOOL
vncService::SelectInputWinStation()
{
home_window_station = GetProcessWindowStation();
return EnumWindowStations(&WinStationEnumProc, NULL);
}
void
vncService::SelectHomeWinStation()
{
HWINSTA station=GetProcessWindowStation();
SetProcessWindowStation(home_window_station);
CloseWindowStation(station);
}
// NT only function to establish whether we're on the current input desktop
BOOL
vncService::InputDesktopSelected(BOOL silent)
{
// Are we running on NT?
// if (serviceshutdown==true) return TRUE;
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -