注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BCB-DG's Blog

...

 
 
 

日志

 
 

Use DemoForge Mirage Driver  

2011-12-15 19:11:18|  分类: VNC |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

//  Copyright (C) 2005-2006 Lev Kazarkin. All Rights Reserved.
//
// This program 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; version 2 of the License.

// 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.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#pragma once

#define ESC_QVI  1026

#define MAP1  1030
#define UNMAP1  1031
#define TESTMAPPED 1051

#define MAXCHANGES_BUF 20000

typedef enum
{
 dmf_dfo_IGNORE  = 0,
 dmf_dfo_FROM_SCREEN = 1,
 dmf_dfo_FROM_DIB = 2,
 dmf_dfo_TO_SCREEN = 3,

 dmf_dfo_SCREEN_SCREEN = 11,
 dmf_dfo_BLIT  = 12,
 dmf_dfo_SOLIDFILL = 13,
 dmf_dfo_BLEND  = 14,
 dmf_dfo_TRANS  = 15,
 dmf_dfo_PLG   = 17,
 dmf_dfo_TEXTOUT  = 18,

 dmf_dfo_Ptr_Engage = 48, // point is used with this record
 dmf_dfo_Ptr_Avert = 49,

 // 1.0.9.0
 // mode-assert notifications to manifest PDEV limbo status
 dmf_dfn_assert_on = 64, // DrvAssert(TRUE): PDEV reenabled
 dmf_dfn_assert_off = 65, // DrvAssert(FALSE): PDEV disabled

} dmf_UpdEvent;


#define CDS_UPDATEREGISTRY  0x00000001
#define CDS_TEST            0x00000002
#define CDS_FULLSCREEN      0x00000004
#define CDS_GLOBAL          0x00000008
#define CDS_SET_PRIMARY     0x00000010
#define CDS_RESET           0x40000000
#define CDS_SETRECT         0x20000000
#define CDS_NORESET         0x10000000

typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD);
typedef LONG (WINAPI* pChangeDisplaySettingsEx)(LPCTSTR, LPDEVMODE, HWND, DWORD, LPVOID);

//*********************************************************************

typedef struct _CHANGES_RECORD
{
 ULONG type;  //screen_to_screen, blit, newcache,oldcache
 RECT rect;
 RECT origrect;
 POINT point;
 ULONG color; //number used in cache array
 ULONG refcolor; //slot used to pase btimap data
}CHANGES_RECORD;
typedef CHANGES_RECORD *PCHANGES_RECORD;
typedef struct _CHANGES_BUF
{
 ULONG counter;
 CHANGES_RECORD pointrect[MAXCHANGES_BUF];
}CHANGES_BUF;
typedef CHANGES_BUF *PCHANGES_BUF;

typedef struct _GETCHANGESBUF
{
 PCHANGES_BUF buffer;
 PVOID Userbuffer;
}GETCHANGESBUF;
typedef GETCHANGESBUF *PGETCHANGESBUF;

#define DMF_VERSION_DEFINE(_ver_0,_ver_1,_ver_2,_ver_3) ((_ver_0<<24) | (_ver_1<<16) | (_ver_2<<8) | _ver_3)

#define DMF_PROTO_VER_CURRENT DMF_VERSION_DEFINE(1,2,0,0)
#define DMF_PROTO_VER_MINCOMPAT DMF_VERSION_DEFINE(0,9,0,1)

struct Esc_dmf_Qvi_IN
{
 ULONG cbSize;

 ULONG app_actual_version;
 ULONG display_minreq_version;

 ULONG connect_options;  // reserved. must be 0.
};

enum
{
 esc_qvi_prod_name_max = 16,
};

#define ESC_QVI_PROD_MIRAGE "MIRAGE"

struct Esc_dmf_Qvi_OUT
{
 ULONG cbSize;

 ULONG display_actual_version;
 ULONG miniport_actual_version;
 ULONG app_minreq_version;
 ULONG display_buildno;
 ULONG miniport_buildno;

 char prod_name[esc_qvi_prod_name_max];
};

void InitVersion();
BOOL IsWinNT();
BOOL IsWinVerOrHigher(ULONG mj, ULONG mn);
DWORD VersionMajor();
DWORD VersionMinor();

class vncVideoDriver
{
public:
 vncVideoDriver();
 ~vncVideoDriver();

 // Methods
public:
 // Make the desktop thread & window proc friends
 BOOL Activate(BOOL fForDirectAccess, const RECT *prcltarget);
 void Deactivate();
 BOOL Activate_NT50(BOOL fForDirectAccess, const RECT *prcltarget);
 void Deactivate_NT50();
 BOOL Activate_NT46(BOOL fForDirectAccess);
 void Deactivate_NT46();
 BOOL CheckVersion();
 BOOL MapSharedbuffers(BOOL fForDirectScreenAccess);
 void UnMapSharedbuffers();
 BOOL TestMapped();
 void HandleDriverChanges(int xoffset,int yoffset);
 void HandleDriverChangesSeries(int xoffset,int yoffset,const CHANGES_RECORD *first,const CHANGES_RECORD *last);
 void ResetCounter() { oldCounter = bufdata.buffer->counter; }

 BYTE *GetScreenView(void) { return (BYTE*)bufdata.Userbuffer; }

 BOOL IsActive(void) { return m_fIsActive; }
 BOOL IsDirectAccessInEffect(void) { return m_fDirectAccessInEffect; }
 BOOL IsHandlingScreen2ScreenBlt(void) { return m_fHandleScreen2ScreenBlt; }

protected:

 static BOOL LookupVideoDeviceAlt(
  LPCTSTR szDevStr,
  LPCTSTR szDevStrAlt,
  INT &devNum,
  DISPLAY_DEVICE *pDd);
 static HKEY CreateDeviceKey(LPCTSTR szMpName);

 char m_devname[32];
 ULONG m_drv_ver_mj;
 ULONG m_drv_ver_mn;

 GETCHANGESBUF bufdata;
 ULONG oldCounter;
 HDC m_gdc;

 bool m_fIsActive;
 bool m_fDirectAccessInEffect;
 bool m_fHandleScreen2ScreenBlt;

 static char vncVideoDriver::szDriverString[];
 static char vncVideoDriver::szDriverStringAlt[];
 static char vncVideoDriver::szMiniportName[];
};

 

#include "stdafx.h"
#include "VideoDriver.h"
#include "..\Common.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"

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)
 {
  DebugMsg("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);
 DebugMsg("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)
 {
  DebugMsg("vncVideoDriver::CheckVersion: ESC_QVI not supported by this version of Mirage\n");
  return FALSE;
 }

 DebugMsg("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)
 {
  DebugMsg("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)
 {
  DebugMsg("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)
 {
  DebugMsg("vncVideoDriver::MapSharedbuffers: MAP1 call returned 0x%x\n", drvCr);
  return FALSE;
 }
 m_fIsActive = true;
 if (fForDirectScreenAccess)
 {
  if (!bufdata.Userbuffer)
  {
   DebugMsg("vncVideoDriver::MapSharedbuffers: mirror screen view is NULL\n");
   return FALSE;
  }
  m_fDirectAccessInEffect = true;
 }
 else
 {
  if (bufdata.Userbuffer)
  {
   DebugMsg("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)
  {
   DebugMsg("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)
 {
  DebugMsg("vncVideoDriver::UnMapSharedbuffers failed. unmapping manually\n");
  if (bufdata.buffer)
  {
   BOOL br = UnmapViewOfFile(bufdata.buffer);
   DebugMsg("vncVideoDriver::UnMapSharedbuffers: UnmapViewOfFile(bufdata.buffer) returned %d\n",br);
  }
  if (bufdata.Userbuffer)
  {
   BOOL br = UnmapViewOfFile(bufdata.Userbuffer);
   DebugMsg("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);
 }
 DebugMsg("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)
  {
   DebugMsg("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)
 {
  DebugMsg("Can't access registry.\n");
  return FALSE;
 }
 HKEY hKeyProfileMp = (HKEY)0;
 LONG cr = RegCreateKey(
  hKeyProfileMirror,
  szMpName,
  &hKeyProfileMp);
 RegCloseKey(hKeyProfileMirror);
 if (cr != ERROR_SUCCESS)
 {
  DebugMsg("Can't access \"%s\" hardware profiles key.\n",szMpName);
  return FALSE;
 }
 HKEY hKeyDevice = (HKEY)0;
 if (RegCreateKey(
  hKeyProfileMp,
  ("DEVICE0"),
  &hKeyDevice) != ERROR_SUCCESS)
 {
  DebugMsg("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);
 }
}

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))
 {
  DebugMsg("No '%s' or '%s' found.\n", szDriverString, szDriverStringAlt);
  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';

 DebugMsg("DevNum:%d\nName:%s\nString:%s\n\n", devNum, &dd.DeviceName[0], &dd.DeviceString[0]);
 DebugMsg("Screen Top-Left Position: (%i, %i)\n", devmode.dmPosition.x, devmode.dmPosition.y);
 DebugMsg("Screen Dimensions: (%i, %i)\n", devmode.dmPelsWidth, devmode.dmPelsHeight);
 DebugMsg("Screen Color depth: %i\n", devmode.dmBitsPerPel);

 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)
 {
  DebugMsg("Can't set \"Cap.DfbBackingMode\" to %d\n", dwVal);
  return FALSE;
 }

 dwVal = 1;
 if (RegSetValueEx(
  hKeyDevice,
  ("Order.BltCopyBits.Enabled"),
  0,
  REG_DWORD,
  (unsigned char *)&dwVal,
  4) != ERROR_SUCCESS)
 {
  DebugMsg("Can't set Order.BltCopyBits.Enabled to %d\n", dwVal);
  return FALSE;
 }

 dwVal = 1;
 if (RegSetValueEx(
  hKeyDevice,
  ("Attach.ToDesktop"),
  0,
  REG_DWORD,
  (unsigned char *)&dwVal,
  4) != ERROR_SUCCESS)
 {
  DebugMsg("Can't set Attach.ToDesktop to %d\n", dwVal);
  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);
 if (cr != DISP_CHANGE_SUCCESSFUL)
 {
  DebugMsg("ChangeDisplaySettingsEx failed on device \"%s\" with status: 0x%x\n",dd.DeviceName,cr);
 }

 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)
 {
  DebugMsg("Can't set \"Cap.DfbBackingMode\" to %d\n", dwVal);
  return FALSE;
 }

 dwVal = 1;
 if (RegSetValueEx(
  hKeyDevice,
  ("Order.BltCopyBits.Enabled"),
  0,
  REG_DWORD,
  (unsigned char *)&dwVal,
  4) != ERROR_SUCCESS)
 {
  DebugMsg("Can't set Order.BltCopyBits.Enabled to %d\n", dwVal);
  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))
 {
  DebugMsg("No '%s' or '%s' found.\n", szDriverString, szDriverStringAlt);
  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)
 {
  DebugMsg("Can't set Attach.ToDesktop to 0x1\n");
 }

 // 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(int xoffset,int yoffset)
{
 ULONG snapshot_counter = bufdata.buffer->counter;
 if (oldCounter == snapshot_counter)
  return;

 if (oldCounter < snapshot_counter)
 {
  HandleDriverChangesSeries(xoffset, yoffset,bufdata.buffer->pointrect + oldCounter,bufdata.buffer->pointrect + snapshot_counter);
 }
 else
 {
  HandleDriverChangesSeries(xoffset,yoffset,bufdata.buffer->pointrect + oldCounter,bufdata.buffer->pointrect + MAXCHANGES_BUF);

  HandleDriverChangesSeries(xoffset,yoffset,bufdata.buffer->pointrect,bufdata.buffer->pointrect + snapshot_counter);
 }

 oldCounter = snapshot_counter;
}

void vncVideoDriver::HandleDriverChangesSeries(int xoffset,int yoffset,const CHANGES_RECORD *i,const CHANGES_RECORD *last)
{
 for (; i < last; i++)
 {
  if (i->type >= dmf_dfo_SCREEN_SCREEN && i->type <= dmf_dfo_TEXTOUT)
  {
   DebugMsg("Rect (%d,%d,%d,%d)\n",i->rect.left,i->rect.top,i->rect.right,i->rect.bottom);
  }
 }
}

// Ported from Tight VNC
BOOL CRDSDlg::InitVideoDriver()
{
 // Mirror video drivers supported under Win2K, WinXP, WinVista
 // and Windows NT 4.0 SP3 (we assume SP6).
 if (!IsWinNT())
  return FALSE;

 // FIXME: Windows NT 4.0 support is broken and thus we disable it here.
 if (!IsWinVerOrHigher(5, 0))
  return FALSE;

 BOOL bSolicitDASD = FALSE;

 _ASSERTE(!m_videodriver);
 m_videodriver = new vncVideoDriver;
 if (!m_videodriver)
 {
  DebugMsg("failed to create vncVideoDriver object\n");
  return FALSE;
 }

 if (IsWinVerOrHigher(5, 0))
 {
// restart the driver if left running.
// NOTE that on NT4 it must be running beforehand
  if (m_videodriver->TestMapped())
  {
   DebugMsg("found abandoned Mirage driver running. restarting.\n");
   m_videodriver->Deactivate();
  }
  _ASSERTE(!m_videodriver->TestMapped());
 }

 {
  CRect vdesk_rect(m_cxStart,m_cyStart,m_cxWidth,m_cyHeight);
  BOOL b = m_videodriver->Activate(bSolicitDASD,&vdesk_rect);
 }

 if (!m_videodriver->CheckVersion())
 {
  DebugMsg("******** PLEASE INSTALL NEWER VERSION OF MIRAGE DRIVER! ********\n");
// IMPORTANT: fail on NT46
  if (IsNtVer(4, 0))
   return FALSE;
 }

 if (m_videodriver->MapSharedbuffers(bSolicitDASD))
 {
  DebugMsg("video driver interface activated\n");
 }
 else
 {
  delete m_videodriver;
  m_videodriver = NULL;
  DebugMsg("failed to activate video driver interface\n");
  return FALSE;
 }
 _ASSERTE(bSolicitDASD == m_videodriver->IsDirectAccessInEffect());
 return TRUE;
}

// Ported from Tight VNC
void CRDSDlg::ShutdownVideoDriver()
{
 if (m_videodriver == NULL)
  return;
 delete m_videodriver;
 m_videodriver = NULL;
 DebugMsg("video driver interface deactivated\n");
}

  评论这张
 
阅读(2521)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017