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

📄 videodriver.cpp

📁 Web VNC samples delphi
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//  Copyright (C) 2005-2006 Lev Kazarkin. All Rights Reserved.
//
//  TightVNC 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.
//
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/

#include "VideoDriver.h"
#include "vncDesktop.h"

char	vncVideoDriver::szDriverString[] = "Mirage Driver";
char	vncVideoDriver::szDriverStringAlt[] = "DemoForge Mirage Driver";
char	vncVideoDriver::szMiniportName[] = "dfmirage";

#define MINIPORT_REGISTRY_PATH	"SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services"

BOOL IsWinNT();
BOOL IsNtVer(ULONG mj, ULONG mn);
BOOL IsWinVerOrHigher(ULONG mj, ULONG mn);


vncVideoDriver::vncVideoDriver()
{
	bufdata.buffer = NULL;
	bufdata.Userbuffer = NULL;
	m_fIsActive = false;
	m_fDirectAccessInEffect = false;
	m_fHandleScreen2ScreenBlt = false;
	*m_devname= 0;
	m_drv_ver_mj = 0;
	m_drv_ver_mn = 0;
}

vncVideoDriver::~vncVideoDriver()
{
	UnMapSharedbuffers();
	Deactivate();
	_ASSERTE(!m_fIsActive);
	_ASSERTE(!m_fDirectAccessInEffect);
}

#define	BYTE0(x)	((x) & 0xFF)
#define	BYTE1(x)	(((x) >> 8) & 0xFF)
#define	BYTE2(x)	(((x) >> 16) & 0xFF)
#define	BYTE3(x)	(((x) >> 24) & 0xFF)

BOOL vncVideoDriver::CheckVersion()
{
	_ASSERTE(IsWinNT());

	HDC	l_gdc= ::CreateDC(m_devname, NULL, NULL, NULL);
	if (!l_gdc)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("vncVideoDriver::CheckVersion: can't create DC on \"%s\"\n"),
			m_devname);
		return FALSE;
	}

	Esc_dmf_Qvi_IN qvi_in;
	qvi_in.cbSize = sizeof(qvi_in);
	vnclog.Print(
		LL_INTINFO,
		"Supported driver version is: min = %u.%u.%u.%u, cur = %u.%u.%u.%u\n",
		BYTE3(DMF_PROTO_VER_MINCOMPAT), BYTE2(DMF_PROTO_VER_MINCOMPAT), BYTE1(DMF_PROTO_VER_MINCOMPAT), BYTE0(DMF_PROTO_VER_MINCOMPAT),
		BYTE3(DMF_PROTO_VER_CURRENT), BYTE2(DMF_PROTO_VER_CURRENT), BYTE1(DMF_PROTO_VER_CURRENT), BYTE0(DMF_PROTO_VER_CURRENT));
	qvi_in.app_actual_version = DMF_PROTO_VER_CURRENT;
	qvi_in.display_minreq_version = DMF_PROTO_VER_MINCOMPAT;
	qvi_in.connect_options = 0;

	Esc_dmf_Qvi_OUT qvi_out;
	qvi_out.cbSize = sizeof(qvi_out);

	int drvCr = ExtEscape(
		l_gdc,
		ESC_QVI,
		sizeof(qvi_in), (LPSTR) &qvi_in,
		sizeof(qvi_out), (LPSTR) &qvi_out);
	DeleteDC(l_gdc);

	if (drvCr == 0)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("vncVideoDriver::CheckVersion: ESC_QVI not supported by this version of Mirage\n"));
		return FALSE;
	}

	vnclog.Print(
		LL_INTINFO,
		"Driver version is: display = %u.%u.%u.%u (build %u),"
		" miniport = %u.%u.%u.%u (build %u),"
		" appMinReq = %u.%u.%u.%u\n",
		BYTE3(qvi_out.display_actual_version), BYTE2(qvi_out.display_actual_version), BYTE1(qvi_out.display_actual_version), BYTE0(qvi_out.display_actual_version),
		qvi_out.display_buildno, 
		BYTE3(qvi_out.miniport_actual_version), BYTE2(qvi_out.miniport_actual_version), BYTE1(qvi_out.miniport_actual_version), BYTE0(qvi_out.miniport_actual_version),
		qvi_out.miniport_buildno,
		BYTE3(qvi_out.app_minreq_version), BYTE2(qvi_out.app_minreq_version), BYTE1(qvi_out.app_minreq_version), BYTE0(qvi_out.app_minreq_version));

	if (drvCr < 0)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("vncVideoDriver::CheckVersion: ESC_QVI call returned 0x%x\n"),
			drvCr);
		return FALSE;
	}

	m_drv_ver_mj = BYTE3(qvi_out.display_actual_version);
	m_drv_ver_mn = BYTE2(qvi_out.display_actual_version);

	return TRUE;
}

BOOL vncVideoDriver::MapSharedbuffers(BOOL fForDirectScreenAccess)
{
	_ASSERTE(!m_fIsActive);
	_ASSERTE(!m_fDirectAccessInEffect);
	_ASSERTE(IsWinNT());

	HDC	l_gdc= ::CreateDC(m_devname, NULL, NULL, NULL);
	if (!l_gdc)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("vncVideoDriver::MapSharedbuffers: can't create DC on \"%s\"\n"),
			m_devname);
		return FALSE;
	}

	oldCounter = 0;
	int drvCr = ExtEscape(
		l_gdc,
		MAP1,
		0, NULL,
		sizeof(GETCHANGESBUF), (LPSTR) &bufdata);
	DeleteDC(l_gdc);

	if (drvCr <= 0)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("vncVideoDriver::MapSharedbuffers: MAP1 call returned 0x%x\n"),
			drvCr);
		return FALSE;
	}
	m_fIsActive = true;
	if (fForDirectScreenAccess)
	{
		if (!bufdata.Userbuffer)
		{
			vnclog.Print(
				LL_INTERR,
				VNCLOG("vncVideoDriver::MapSharedbuffers: mirror screen view is NULL\n"));
			return FALSE;
		}
		m_fDirectAccessInEffect = true;
	}
	else
	{
		if (bufdata.Userbuffer)
		{
			vnclog.Print(
				LL_INTINFO,
				VNCLOG("vncVideoDriver::MapSharedbuffers: mirror screen view is mapped but direct access mode is OFF\n"));
		}
	}

// Screen2Screen support added in Mirage ver 1.2
	m_fHandleScreen2ScreenBlt = (m_drv_ver_mj > 1) || (m_drv_ver_mj == 1 && m_drv_ver_mn >= 2);

	return TRUE;	
}

BOOL vncVideoDriver::TestMapped()
{
	_ASSERTE(IsWinNT());

	TCHAR *pDevName;
	if (IsWinVerOrHigher(5, 0))
	{
		DISPLAY_DEVICE dd;
		INT devNum = 0;
		if (!LookupVideoDeviceAlt(szDriverString, szDriverStringAlt, devNum, &dd))
			return FALSE;
		pDevName = (TCHAR *)dd.DeviceName;
	}
	else
	{
		pDevName = "DISPLAY";
	}

	HDC	l_ddc = ::CreateDC(pDevName, NULL, NULL, NULL);
	if (l_ddc)
	{
		BOOL b = ExtEscape(l_ddc, TESTMAPPED, 0, NULL, 0, NULL);	
		DeleteDC(l_ddc);
		return b;
	}
	return FALSE;
}

void vncVideoDriver::UnMapSharedbuffers()
{
	_ASSERTE(IsWinNT());

	int DrvCr = 0;
	if (m_devname[0])
	{
		_ASSERTE(m_fIsActive);
		_ASSERTE(bufdata.buffer);
		_ASSERTE(!m_fDirectAccessInEffect || bufdata.Userbuffer);

		HDC	l_gdc= ::CreateDC(m_devname, NULL, NULL, NULL);
		if (!l_gdc)
		{
			vnclog.Print(
				LL_INTERR,
				VNCLOG("vncVideoDriver::UnMapSharedbuffers: can't create DC on \"%s\"\n"),
				m_devname);
		}
		else
		{
			DrvCr = ExtEscape(
				l_gdc,
				UNMAP1,
				sizeof(GETCHANGESBUF), (LPSTR) &bufdata,
				0, NULL);
			DeleteDC(l_gdc);

			_ASSERTE(DrvCr > 0);
		}
	}
// 0 return value is unlikely for Mirage because its DC is independent
// from the reference device;
// this happens with Quasar if its mode was changed externally.
// nothing is particularly bad with it.

	if (DrvCr <= 0)
	{
		vnclog.Print(
			LL_INTINFO,
			VNCLOG("vncVideoDriver::UnMapSharedbuffers failed. unmapping manually\n"));
		if (bufdata.buffer)
		{
			BOOL br = UnmapViewOfFile(bufdata.buffer);
			vnclog.Print(
				LL_INTINFO,
				VNCLOG("vncVideoDriver::UnMapSharedbuffers: UnmapViewOfFile(bufdata.buffer) returned %d\n"),
				br);
		}
		if (bufdata.Userbuffer)
		{
			BOOL br = UnmapViewOfFile(bufdata.Userbuffer);
			vnclog.Print(
				LL_INTINFO,
				VNCLOG("vncVideoDriver::UnMapSharedbuffers: UnmapViewOfFile(bufdata.Userbuffer) returned %d\n"),
				br);
		}
	}
	m_fIsActive = false;
	m_fDirectAccessInEffect = false;
	m_fHandleScreen2ScreenBlt = false;
}

template <class TpFn>
HINSTANCE  LoadNImport(LPCTSTR szDllName, LPCTSTR szFName, TpFn &pfn)
{
	HINSTANCE hDll = LoadLibrary(szDllName);
	if (hDll)
	{
		pfn = (TpFn)GetProcAddress(hDll, szFName);
		if (pfn)
			return hDll;
		FreeLibrary(hDll);
	}
	vnclog.Print(
		LL_INTERR,
		VNCLOG("Can not import '%s' from '%s'.\n"),
		szFName, szDllName);
	return NULL;
}

//BOOL vncVideoDriver::LookupVideoDevice(LPCTSTR szDeviceString, INT &devNum, DISPLAY_DEVICE *pDd)
BOOL vncVideoDriver::LookupVideoDeviceAlt(
		LPCTSTR szDevStr,
		LPCTSTR szDevStrAlt,
		INT &devNum,
		DISPLAY_DEVICE *pDd)
{
	_ASSERTE(IsWinVerOrHigher(5, 0));

	pEnumDisplayDevices pd = NULL;
	HINSTANCE  hInstUser32 = LoadNImport("User32.DLL", "EnumDisplayDevicesA", pd);
	if (!hInstUser32) return FALSE;

	ZeroMemory(pDd, sizeof(DISPLAY_DEVICE));
	pDd->cb = sizeof(DISPLAY_DEVICE);
	BOOL result;
	while (result = (*pd)(NULL,devNum, pDd, 0))
	{
		if (strcmp((const char *)pDd->DeviceString, szDevStr) == 0 ||
			szDevStrAlt && strcmp((const char *)pDd->DeviceString, szDevStrAlt) == 0)
		{
			vnclog.Print(
				LL_INTINFO,
				VNCLOG("Found display device \"%s\": \"%s\"\n"),
				pDd->DeviceString,
				pDd->DeviceName);
			break;
		}
		devNum++;
	}

	FreeLibrary(hInstUser32);
	return result;
}

HKEY vncVideoDriver::CreateDeviceKey(LPCTSTR szMpName)
{
	HKEY hKeyProfileMirror = (HKEY)0;
	if (RegCreateKey(
			HKEY_LOCAL_MACHINE,
			(MINIPORT_REGISTRY_PATH),
			&hKeyProfileMirror) != ERROR_SUCCESS)
	{
		vnclog.Print(LL_INTERR, VNCLOG("Can't access registry.\n"));
		return FALSE;
	}
	HKEY hKeyProfileMp = (HKEY)0;
	LONG cr = RegCreateKey(
			hKeyProfileMirror,
			szMpName,
			&hKeyProfileMp);
	RegCloseKey(hKeyProfileMirror);
	if (cr != ERROR_SUCCESS)
	{
		vnclog.Print(
			LL_INTERR,
			VNCLOG("Can't access \"%s\" hardware profiles key.\n"),
			szMpName);
		return FALSE;
	}
	HKEY hKeyDevice = (HKEY)0;
	if (RegCreateKey(
			hKeyProfileMp,
			("DEVICE0"),
			&hKeyDevice) != ERROR_SUCCESS)
	{
		vnclog.Print(LL_INTERR, VNCLOG("Can't access DEVICE0 hardware profiles key.\n"));
	}
	RegCloseKey(hKeyProfileMp);
	return hKeyDevice;
}

BOOL vncVideoDriver::Activate(
		BOOL fForDirectAccess,
		const RECT *prcltarget)
{
	_ASSERTE(IsWinNT());

	if (IsWinVerOrHigher(5, 0))
	{
		return Activate_NT50(fForDirectAccess, prcltarget);
	}
	else
	{
// NOTE: prcltarget is just a SourceDisplayRect.
// there is only 1 possibility on NT4, so safely ignore it
		return Activate_NT46(fForDirectAccess);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -