⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncservice.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//  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 + -