📄 videodriver.cpp
字号:
// 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 + -