669 lines
15 KiB
C++
669 lines
15 KiB
C++
|
// 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)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Esc_dmf_Qvi_IN qvi_in;
|
||
|
qvi_in.cbSize = sizeof(qvi_in);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (drvCr < 0)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
oldCounter = 0;
|
||
|
int drvCr = ExtEscape(
|
||
|
l_gdc,
|
||
|
MAP1,
|
||
|
0, NULL,
|
||
|
sizeof(GETCHANGESBUF), (LPSTR) &bufdata);
|
||
|
DeleteDC(l_gdc);
|
||
|
|
||
|
if (drvCr <= 0)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
m_fIsActive = true;
|
||
|
if (fForDirectScreenAccess)
|
||
|
{
|
||
|
if (!bufdata.Userbuffer)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
m_fDirectAccessInEffect = true;
|
||
|
}
|
||
|
|
||
|
// 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)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
if (bufdata.buffer)
|
||
|
{
|
||
|
BOOL br = UnmapViewOfFile(bufdata.buffer);
|
||
|
}
|
||
|
if (bufdata.Userbuffer)
|
||
|
{
|
||
|
BOOL br = UnmapViewOfFile(bufdata.Userbuffer);
|
||
|
}
|
||
|
}
|
||
|
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);
|
||
|
}
|
||
|
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)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
HKEY hKeyProfileMp = (HKEY)0;
|
||
|
LONG cr = RegCreateKey(
|
||
|
hKeyProfileMirror,
|
||
|
szMpName,
|
||
|
&hKeyProfileMp);
|
||
|
RegCloseKey(hKeyProfileMirror);
|
||
|
if (cr != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
HKEY hKeyDevice = (HKEY)0;
|
||
|
if (RegCreateKey(
|
||
|
hKeyProfileMp,
|
||
|
("DEVICE0"),
|
||
|
&hKeyDevice) != ERROR_SUCCESS)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vncVideoDriver::Deactivate()
|
||
|
{
|
||
|
_ASSERTE(IsWinNT());
|
||
|
|
||
|
if (IsWinVerOrHigher(5, 0))
|
||
|
{
|
||
|
Deactivate_NT50();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Deactivate_NT46();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL vncVideoDriver::Activate_NT50(
|
||
|
BOOL fForDirectAccess,
|
||
|
const RECT *prcltarget)
|
||
|
{
|
||
|
HDESK hdeskInput;
|
||
|
HDESK hdeskCurrent;
|
||
|
|
||
|
DISPLAY_DEVICE dd;
|
||
|
INT devNum = 0;
|
||
|
if (!LookupVideoDeviceAlt(szDriverString, szDriverStringAlt, devNum, &dd))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DEVMODE devmode;
|
||
|
FillMemory(&devmode, sizeof(DEVMODE), 0);
|
||
|
devmode.dmSize = sizeof(DEVMODE);
|
||
|
devmode.dmDriverExtra = 0;
|
||
|
BOOL change = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
|
||
|
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||
|
if (prcltarget)
|
||
|
{
|
||
|
// we always have to set position or
|
||
|
// a stale position info in registry would come into effect.
|
||
|
devmode.dmFields |= DM_POSITION;
|
||
|
devmode.dmPosition.x = prcltarget->left;
|
||
|
devmode.dmPosition.y = prcltarget->top;
|
||
|
|
||
|
devmode.dmPelsWidth = prcltarget->right - prcltarget->left;
|
||
|
devmode.dmPelsHeight = prcltarget->bottom - prcltarget->top;
|
||
|
}
|
||
|
|
||
|
devmode.dmDeviceName[0] = '\0';
|
||
|
|
||
|
HKEY hKeyDevice = CreateDeviceKey(szMiniportName);
|
||
|
if (hKeyDevice == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
// TightVNC does not use these features
|
||
|
RegDeleteValue(hKeyDevice, ("Screen.ForcedBpp"));
|
||
|
RegDeleteValue(hKeyDevice, ("Pointer.Enabled"));
|
||
|
|
||
|
DWORD dwVal = fForDirectAccess ? 3 : 0;
|
||
|
// NOTE that old driver ignores it and mapping is always ON with it
|
||
|
if (RegSetValueEx(
|
||
|
hKeyDevice,
|
||
|
("Cap.DfbBackingMode"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(unsigned char *)&dwVal,
|
||
|
4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwVal = 1;
|
||
|
if (RegSetValueEx(
|
||
|
hKeyDevice,
|
||
|
("Order.BltCopyBits.Enabled"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(unsigned char *)&dwVal,
|
||
|
4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwVal = 1;
|
||
|
if (RegSetValueEx(
|
||
|
hKeyDevice,
|
||
|
("Attach.ToDesktop"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(unsigned char *)&dwVal,
|
||
|
4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pChangeDisplaySettingsEx pCDS = NULL;
|
||
|
HINSTANCE hInstUser32 = LoadNImport("User32.DLL", "ChangeDisplaySettingsExA", pCDS);
|
||
|
if (!hInstUser32) return FALSE;
|
||
|
|
||
|
// Save the current desktop
|
||
|
hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
|
||
|
if (hdeskCurrent != NULL)
|
||
|
{
|
||
|
hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
|
||
|
if (hdeskInput != NULL)
|
||
|
SetThreadDesktop(hdeskInput);
|
||
|
}
|
||
|
// 24 bpp screen mode is MUNGED to 32 bpp.
|
||
|
// the underlying buffer format must be 32 bpp.
|
||
|
// see vncDesktop::ThunkBitmapInfo()
|
||
|
if (devmode.dmBitsPerPel==24) devmode.dmBitsPerPel = 32;
|
||
|
LONG cr = (*pCDS)(
|
||
|
(TCHAR *)dd.DeviceName,
|
||
|
&devmode,
|
||
|
NULL,
|
||
|
CDS_UPDATEREGISTRY,NULL);
|
||
|
|
||
|
strcpy(m_devname, (const char *)dd.DeviceName);
|
||
|
|
||
|
// Reset desktop
|
||
|
SetThreadDesktop(hdeskCurrent);
|
||
|
// Close the input desktop
|
||
|
CloseDesktop(hdeskInput);
|
||
|
RegCloseKey(hKeyDevice);
|
||
|
FreeLibrary(hInstUser32);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL vncVideoDriver::Activate_NT46(BOOL fForDirectAccess)
|
||
|
{
|
||
|
HKEY hKeyDevice = CreateDeviceKey(szMiniportName);
|
||
|
if (hKeyDevice == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
// TightVNC does not use these features
|
||
|
RegDeleteValue(hKeyDevice, ("Screen.ForcedBpp"));
|
||
|
RegDeleteValue(hKeyDevice, ("Pointer.Enabled"));
|
||
|
|
||
|
DWORD dwVal = fForDirectAccess ? 3 : 0;
|
||
|
// NOTE that old driver ignores it and mapping is always ON with it
|
||
|
if (RegSetValueEx(
|
||
|
hKeyDevice,
|
||
|
("Cap.DfbBackingMode"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(unsigned char *)&dwVal,
|
||
|
4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwVal = 1;
|
||
|
if (RegSetValueEx(
|
||
|
hKeyDevice,
|
||
|
("Order.BltCopyBits.Enabled"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(unsigned char *)&dwVal,
|
||
|
4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// NOTE: we cannot truly load the driver
|
||
|
// but ChangeDisplaySettings makes PDEV to reload
|
||
|
// and thus new settings come into effect
|
||
|
|
||
|
// TODO
|
||
|
|
||
|
strcpy(m_devname, "DISPLAY");
|
||
|
|
||
|
RegCloseKey(hKeyDevice);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void vncVideoDriver::Deactivate_NT50()
|
||
|
{
|
||
|
HDESK hdeskInput;
|
||
|
HDESK hdeskCurrent;
|
||
|
|
||
|
// it is important to us to be able to deactivate
|
||
|
// even what we have never activated. thats why we look it up, all over
|
||
|
// if (!m_devname[0])
|
||
|
// return;
|
||
|
// ... and forget the name
|
||
|
*m_devname = 0;
|
||
|
|
||
|
DISPLAY_DEVICE dd;
|
||
|
INT devNum = 0;
|
||
|
if (!LookupVideoDeviceAlt(szDriverString, szDriverStringAlt, devNum, &dd))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DEVMODE devmode;
|
||
|
FillMemory(&devmode, sizeof(DEVMODE), 0);
|
||
|
devmode.dmSize = sizeof(DEVMODE);
|
||
|
devmode.dmDriverExtra = 0;
|
||
|
BOOL change = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
|
||
|
devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||
|
devmode.dmDeviceName[0] = '\0';
|
||
|
|
||
|
HKEY hKeyDevice = CreateDeviceKey(szMiniportName);
|
||
|
if (hKeyDevice == NULL)
|
||
|
return;
|
||
|
|
||
|
DWORD one = 0;
|
||
|
if (RegSetValueEx(hKeyDevice,("Attach.ToDesktop"), 0, REG_DWORD, (unsigned char *)&one,4) != ERROR_SUCCESS)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
// reverting to default behavior
|
||
|
RegDeleteValue(hKeyDevice, ("Cap.DfbBackingMode"));
|
||
|
RegDeleteValue(hKeyDevice, ("Order.BltCopyBits.Enabled"));
|
||
|
|
||
|
pChangeDisplaySettingsEx pCDS = NULL;
|
||
|
HINSTANCE hInstUser32 = LoadNImport("User32.DLL", "ChangeDisplaySettingsExA", pCDS);
|
||
|
if (!hInstUser32) return;
|
||
|
|
||
|
// Save the current desktop
|
||
|
hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
|
||
|
if (hdeskCurrent != NULL)
|
||
|
{
|
||
|
hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
|
||
|
if (hdeskInput != NULL)
|
||
|
SetThreadDesktop(hdeskInput);
|
||
|
}
|
||
|
// 24 bpp screen mode is MUNGED to 32 bpp. see vncDesktop::ThunkBitmapInfo()
|
||
|
if (devmode.dmBitsPerPel==24) devmode.dmBitsPerPel = 32;
|
||
|
|
||
|
// Add 'Default.*' settings to the registry under above hKeyProfile\mirror\device
|
||
|
(*pCDS)((TCHAR *)dd.DeviceName, &devmode, NULL, CDS_UPDATEREGISTRY, NULL);
|
||
|
|
||
|
// Reset desktop
|
||
|
SetThreadDesktop(hdeskCurrent);
|
||
|
// Close the input desktop
|
||
|
CloseDesktop(hdeskInput);
|
||
|
RegCloseKey(hKeyDevice);
|
||
|
FreeLibrary(hInstUser32);
|
||
|
}
|
||
|
|
||
|
void vncVideoDriver::Deactivate_NT46()
|
||
|
{
|
||
|
// ... and forget the name
|
||
|
*m_devname = 0;
|
||
|
|
||
|
HKEY hKeyDevice = CreateDeviceKey(szMiniportName);
|
||
|
if (hKeyDevice == NULL)
|
||
|
return;
|
||
|
|
||
|
// reverting to default behavior
|
||
|
RegDeleteValue(hKeyDevice, ("Cap.DfbBackingMode"));
|
||
|
|
||
|
// RegDeleteValue(hKeyDevice, ("Order.BltCopyBits.Enabled"));
|
||
|
// TODO: remove "Order.BltCopyBits.Enabled"
|
||
|
// now we don't touch this important option
|
||
|
// because we dont apply the changed values
|
||
|
|
||
|
RegCloseKey(hKeyDevice);
|
||
|
}
|
||
|
|
||
|
void vncVideoDriver::HandleDriverChanges(
|
||
|
vncDesktop *pDesk,
|
||
|
vncRegion &rgn,
|
||
|
int xoffset,
|
||
|
int yoffset,
|
||
|
BOOL &bPointerShapeChange)
|
||
|
{
|
||
|
ULONG snapshot_counter = bufdata.buffer->counter;
|
||
|
if (oldCounter == snapshot_counter)
|
||
|
return;
|
||
|
|
||
|
if (oldCounter < snapshot_counter)
|
||
|
{
|
||
|
HandleDriverChangesSeries(
|
||
|
pDesk,
|
||
|
rgn,
|
||
|
xoffset, yoffset,
|
||
|
bufdata.buffer->pointrect + oldCounter,
|
||
|
bufdata.buffer->pointrect + snapshot_counter,
|
||
|
bPointerShapeChange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HandleDriverChangesSeries(
|
||
|
pDesk,
|
||
|
rgn,
|
||
|
xoffset, yoffset,
|
||
|
bufdata.buffer->pointrect + oldCounter,
|
||
|
bufdata.buffer->pointrect + MAXCHANGES_BUF,
|
||
|
bPointerShapeChange);
|
||
|
|
||
|
HandleDriverChangesSeries(
|
||
|
pDesk,
|
||
|
rgn,
|
||
|
xoffset, yoffset,
|
||
|
bufdata.buffer->pointrect,
|
||
|
bufdata.buffer->pointrect + snapshot_counter,
|
||
|
bPointerShapeChange);
|
||
|
}
|
||
|
|
||
|
oldCounter = snapshot_counter;
|
||
|
}
|
||
|
|
||
|
void vncVideoDriver::HandleDriverChangesSeries(
|
||
|
vncDesktop *pDesk,
|
||
|
vncRegion &rgn,
|
||
|
int xoffset,
|
||
|
int yoffset,
|
||
|
const CHANGES_RECORD *i,
|
||
|
const CHANGES_RECORD *last,
|
||
|
BOOL &bPointerShapeChange)
|
||
|
{
|
||
|
for (; i < last; i++)
|
||
|
{
|
||
|
// TODO bPointerShapeChange
|
||
|
|
||
|
if (m_fHandleScreen2ScreenBlt && i->type == dmf_dfo_SCREEN_SCREEN)
|
||
|
{
|
||
|
// DPF(("CopyRect: (%d, %d, %d, %d)\n",
|
||
|
// i->rect.left,
|
||
|
// i->rect.top,
|
||
|
// i->rect.right,
|
||
|
// i->rect.bottom));
|
||
|
|
||
|
RECT Rc;
|
||
|
Rc.left = i->rect.left + xoffset;
|
||
|
Rc.top = i->rect.top + yoffset;
|
||
|
Rc.right = i->rect.right + xoffset;
|
||
|
Rc.bottom = i->rect.bottom + yoffset;
|
||
|
|
||
|
POINT Pt;
|
||
|
Pt.x = i->point.x + xoffset;
|
||
|
Pt.y = i->point.y + yoffset;
|
||
|
pDesk->CopyRect(Rc, Pt);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (i->type >= dmf_dfo_SCREEN_SCREEN && i->type <= dmf_dfo_TEXTOUT)
|
||
|
{
|
||
|
// DPF(("XRect: (%d, %d, %d, %d)\n",
|
||
|
// i->rect.left,
|
||
|
// i->rect.top,
|
||
|
// i->rect.right,
|
||
|
// i->rect.bottom));
|
||
|
rgn.AddRect(i->rect, xoffset, yoffset);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID DebugPrint(PCHAR DebugMessage,
|
||
|
...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
va_start(ap, DebugMessage);
|
||
|
TCHAR pb[256];
|
||
|
vsprintf(pb, DebugMessage, ap);
|
||
|
va_end(ap);
|
||
|
OutputDebugString(pb);
|
||
|
}
|