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

BCB-DG's Blog

...

 
 
 

日志

 
 

VNC Desktop 1  

2009-09-18 09:26:06|  分类: VNC |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

#include <assert.h>
#include "stdhdrs.h"
#include <omnithread.h>
#include "WinVNC.h"
#include "VNCHooks\VNCHooks.h"
#include "vncServer.h"
#include "vncKeymap.h"
#include "rfbRegion.h"
#include "rfbRect.h"
#include "vncDesktop.h"
#include "vncService.h"
#include "vncOSVersion.h"
#include "mmSystem.h"
#include "TextChat.h"
#include "vncdesktopthread.h"

const UINT RFB_SCREEN_UPDATE = RegisterWindowMessage("WinVNC.Update.DrawRect");
const UINT RFB_COPYRECT_UPDATE = RegisterWindowMessage("WinVNC.Update.CopyRect");
const UINT RFB_MOUSE_UPDATE = RegisterWindowMessage("WinVNC.Update.Mouse");
const char szDesktopSink[] = "WinVNC desktop sink";

extern int counterwatch;//global var for driverwatch
bool g_Desktop_running;
extern bool g_DesktopThread_running;
extern bool g_update_triggered;
DWORD WINAPI BlackWindow(LPVOID lpParam);

void vncDesktop::FastDetectChanges(rfb::Region2D &rgn, rfb::Rect &rect, int nZone, bool fTurbo)
{
 RGBPixelList::iterator iPixelColor;
 RGBPixelList *pThePixelGrid;
 bool fInitGrid = false;
 bool fIncCycle = false;
 // For more accuracy, we could use 24 or even 16
 const int PIXEL_BLOCK_SIZE  = 32; // Pixels Grid definition
 const int GRID_OFFSET = 4;  // Pixels Grid shifting during cycle (in pixels)
        // The number of grid per zone is PIXEL_BLOCK_SIZE/GRID_OFFSET (must be int !)
 int x, y;
 int xo, yo;
 WindowsList::iterator iWindow;
 // In turbo mode, we clear the list of windows at each iteration -> Lot of updates because
 // the same windows can be detected several times during a complete cycle
 // (To avoid this pb, we must update all the grids at the same coordinate when a pixel of one grid has changed -> later)
 // Otherwise we only clear it each time the Grid cycle loops -> Less updates, less framerate, less CPU, less bandwidth
 if (fTurbo)
  m_lWList.clear();
 else if (m_nGridCycle == 0)
  m_lWList.clear();

 // Create all the Grids (for all the 5 zones (4 quarter screens + 1 full screen)
 // Actually, the quarter screens are not utilized in v1.1.0 but it does not
 // generate any overhead neither additionnal memory consumption (see below)
 if (m_lGridsList.empty())
 {
  for (int i = 0; i < (5 * PIXEL_BLOCK_SIZE / GRID_OFFSET); i++)
  {
   RGBPixelList *pList = new RGBPixelList;
   if (pList != NULL)
   {
    m_lGridsList.push_back(pList);
   }
  }
 }
 // We test one zone at a time
 GridsList::iterator iGrid;
 int nIndex = 0;
 int nGridPos = (nZone * PIXEL_BLOCK_SIZE / GRID_OFFSET) + m_nGridCycle;
 iGrid = m_lGridsList.begin();
 while (nIndex != nGridPos)
 {
  iGrid++;
  nIndex++;
 }
 iPixelColor = ((RGBPixelList*)(*iGrid))->begin();
 pThePixelGrid = (RGBPixelList*) *iGrid;
 if (nZone == 0 || nZone == 4) fIncCycle = true;
 if (pThePixelGrid->empty()) fInitGrid = true;
 int nOffset = GRID_OFFSET * m_nGridCycle;
 // We walk our way through the Grids
 for (y = rect.tl.y; y < rect.br.y; y += PIXEL_BLOCK_SIZE)
 {
  yo = y + nOffset;
  for (x = rect.tl.x; x < rect.br.x; x += PIXEL_BLOCK_SIZE)
  {
   xo = x + nOffset;
   // If init list
   if (fInitGrid)
   {
      COLORREF PixelColor = GetPixel(m_hrootdc, xo, yo);
      pThePixelGrid->push_back(PixelColor);
      continue;
   }
   // Read the pixel's color on the screen
    COLORREF PixelColor = GetPixel(m_hrootdc, xo, yo);
   // If the pixel has changed
   if (*iPixelColor != PixelColor)
   {
    // Save the new Pixel in the list
    *iPixelColor = PixelColor;
    // Then find the corresponding Window
    POINT point;
    RECT rect;
    point.x = xo;
    point.y = yo;
    // Find the smallest, non-hidden, non-disabled Window containing this pixel
    // REM: We don't use ChildWindowFromPoint because we don't want of hidden windows
    HWND hDeskWnd = GetDesktopWindow();
    HWND hwnd = WindowFromPoint(point);
    bool fAlready = false;
    // Look if we've already detected this window
    for (iWindow = m_lWList.begin(); iWindow != m_lWList.end(); iWindow++)
    {
     if (*iWindow == hwnd)
     {
      fAlready = true;
      break;
     }
    }    
    // Add the corresponding rect to the cache region
    if (!fAlready && (hwnd != hDeskWnd) && GetWindowRect(hwnd, &rect))
    {
     //Buffer coordinates
     rect.left-=m_ScreenOffsetx;
     rect.right-=m_ScreenOffsetx;
     rect.top-=m_ScreenOffsety;
     rect.bottom-=m_ScreenOffsety;
     rfb::Rect wrect = rfb::Rect(rect).intersect(m_Cliprect);
     if (!wrect.is_empty())
     {
      rgn = rgn.union_(wrect);
      m_lWList.push_back(hwnd);
     }
    }
   }
   iPixelColor++; // Next PixelColor in the list
  }
 }
 if (fIncCycle) m_nGridCycle = (m_nGridCycle + 1) % (PIXEL_BLOCK_SIZE / GRID_OFFSET);
}

// Implementation
vncDesktop::vncDesktop()
{
 m_thread = NULL;

 m_hwnd = NULL;
 m_timerid = 0;
 m_hnextviewer = NULL;
 m_hcursor = NULL;
 m_hOldcursor = NULL; // sf@2002

 m_displaychanged = FALSE;
 m_update_triggered = FALSE;
 g_update_triggered = FALSE;

 m_hrootdc = NULL;
 m_hmemdc = NULL;
 m_membitmap = NULL;
 m_initialClipBoardSeen = FALSE;
 m_foreground_window = NULL;

 // Vars for Will Dean's DIBsection patch
 m_DIBbits = NULL;
 m_formatmunged = FALSE;
 m_clipboard_active = FALSE;
 m_pollingcycle = 0;

 // Modif sf@2002 - v1.1.0
 m_lWList.clear();
    m_lGridsList.clear();
 m_nGridCycle = 0;

 // Modif sf@2002 - v1.1.0
 m_lLastMouseUpdateTime = 0L;
 m_lLastSlowClientTestTime = timeGetTime();

 // Modif rdv@2002 - v1.1.x - videodriver
 m_videodriver=NULL;
 m_ScreenOffsetx=0;
 m_ScreenOffsety=0;
 m_hookdriver=false;

 OldPowerOffTimeout=0;
 hModule=NULL;
 char szCurrentDir[MAX_PATH];
  if (GetModuleFileName(NULL, szCurrentDir, MAX_PATH))
  {
    char* p = strrchr(szCurrentDir, '\\');
    if (p == NULL) return;
    *p = '\0';
    strcat (szCurrentDir,"\\vnchooks.dll");
  }
 UnSetHooks=NULL;
 SetMouseFilterHook=NULL;
 SetKeyboardFilterHook=NULL;
 SetHooks=NULL;
 hModule = LoadLibrary(szCurrentDir);
 if (hModule)
  {
    UnSetHooks = (UnSetHooksFn) GetProcAddress( hModule, "UnSetHooks" );
    SetMouseFilterHook  = (SetMouseFilterHookFn) GetProcAddress( hModule, "SetMouseFilterHook" );
    SetKeyboardFilterHook  = (SetKeyboardFilterHookFn) GetProcAddress( hModule, "SetKeyboardFilterHook" );
    SetHooks  = (SetHooksFn) GetProcAddress( hModule, "SetHooks" );
  }
 On_Off_hookdll=false;
 g_Desktop_running=true;
 hUser32=LoadLibrary("USER32");
 pbi = (pBlockInput)GetProcAddress( hUser32, "BlockInput");
 Temp_Resolution=false;
 m_OrigpollingSet=false;
 m_Origpolling=false;
 DriverWantedSet=false;
 current_monitor=3;
}

vncDesktop::~vncDesktop()
{
 // If we created a thread then here we delete it The thread itself does most of the cleanup
 if(m_thread != NULL)
 {
  // Post a close message to quit our message handler thread
  PostMessage(Window(), WM_QUIT, 0, 0);
  vncDesktopThread *thread=(vncDesktopThread*)m_thread;
  while (g_DesktopThread_running!=false)
  {
   PostMessage(Window(), WM_QUIT, 0, 0);
   Sleep(200);
  }
  // Join with the desktop handler thread
  void *returnval;
  m_thread->join(&returnval);
  m_thread = NULL;
 }
 SetDisableInput(false);
 // Let's call Shutdown just in case something went wrong...
 Shutdown();

 // Modif sf@2002
 m_lWList.clear();
 GridsList::iterator iGrid;
 for (iGrid = m_lGridsList.begin(); iGrid != m_lGridsList.end(); iGrid++)
 {
  if (*iGrid)
  {
   // Since we've replaced this:
   // "typedef std::list<RGBPixelList*> GridsList;"
   // with this:
   // "typedef std::list<void*> GridsList;"
   // we must be carefull to avoid memory leaks...
   ((RGBPixelList*)(*iGrid))->clear();
   delete ((RGBPixelList*)(*iGrid));
  }
 }
 m_lGridsList.clear();
 if (hModule)FreeLibrary(hModule);
 if (hUser32) FreeLibrary(hUser32);
 g_Desktop_running=false;
}

// Tell the desktop hooks to grab & update a particular rectangle
void vncDesktop::QueueRect(const rfb::Rect &rect)
{
 ULONG vwParam = MAKELONG(rect.tl.x, rect.tl.y);
 ULONG vlParam = MAKELONG(rect.br.x, rect.br.y);
 PostMessage(Window(), RFB_SCREEN_UPDATE, vwParam, vlParam);
}
 
// Kick the desktop hooks to perform an update
void vncDesktop::TriggerUpdate()
{
 // Note that we should really lock the update lock here,
 // but there are periodic timer updates anyway, so we don't actually need to.  Something to think about.
 if (!m_update_triggered) {
  m_update_triggered = TRUE;
  g_update_triggered = TRUE;
  if (m_timerid != NULL)
  KillTimer(NULL, m_timerid);
  m_timerid = NULL;
  PostMessage(Window(), WM_TIMER, 0, 0);
 }
}

// Routine to startup and install all the hooks and stuff
BOOL vncDesktop::Startup()
{
 // Initialise the Desktop object
 if (!InitDesktop()) return FALSE;
 if (!Temp_Resolution)
  {
   if (DriverWantedSet==true)
   {
   m_server->Driver(DriverWanted);
   m_server->Hook(HookWanted);
   DriverWantedSet=false;
   }
   if (m_server->Driver())
    {
     if(OSVersion()==1 )
      {
       InitVideoDriver();
      }
    }
   if (m_Origpolling) m_server->PollFullScreen(m_Origpolling);
   m_OrigpollingSet=false;
  }
 else
  {
   m_Origpolling=m_server->PollFullScreen();
   m_OrigpollingSet=true;
   m_server->PollFullScreen(TRUE);
  }
 
 VideoBuffer();
 if (!InitBitmap()) return FALSE;
 if (!ThunkBitmapInfo()) return FALSE;
 EnableOptimisedBlits();
 if (!SetPixFormat()) return FALSE;
 if (!SetPixShifts()) return FALSE;
 if (!SetPalette()) return FALSE;
 if (!InitWindow()) return FALSE;
 if (VideoBuffer())
 {
  pchanges_buf=NULL;
  GETCHANGESBUF *pcommbuffer=m_videodriver->CreateCommunicationBuffer(m_bminfo.bmi.bmiHeader.biSizeImage);
  // we need to check again, communication service can be down In that case driver can not be used
  if (VideoBuffer())
  {
   if (m_membitmap != NULL)
    {
     DeleteObject(m_membitmap);
     m_membitmap = NULL;
    }
   m_DIBbits=pcommbuffer->UserbufferBegin;
   pchanges_buf=pcommbuffer->buffer;
   InvalidateRect(NULL,NULL,TRUE);
  }
 }
 // Start a timer to handle Polling Mode.  The timer will cause
 // an "idle" event once every 1/10 second, which is necessary if Polling
 // Mode is being used, to cause TriggerUpdate to be called. 
 m_timerid = SetTimer(m_hwnd, 1, 100, NULL);
 // Initialise the buffer object
 m_buffer.SetDesktop(this);
 GetQuarterSize();
 // Everything is ok, so return TRUE
 return TRUE;
}

// Routine to shutdown all the hooks and stuff
BOOL vncDesktop::Shutdown()
{
 // If we created a timer then kill it
 if (m_timerid != NULL) KillTimer(NULL, m_timerid);
 // If we created a window then kill it and the hooks
 if(m_hwnd != NULL)
 { 
  // Remove the system hooks
  if (UnSetHooks) UnSetHooks(GetCurrentThreadId());
  // The window is being closed - remove it from the viewer list
  ChangeClipboardChain(m_hwnd, m_hnextviewer);
  // Close the hook window
  DestroyWindow(m_hwnd);
  m_hwnd = NULL;
  m_hnextviewer = NULL;
 }
 if (m_hrootdc != NULL)
 {
    DeleteDC(m_hrootdc);
    m_hrootdc = NULL;
 }
 if (m_hmemdc != NULL)
 {
  DeleteDC(m_hmemdc);
  m_hmemdc = NULL;
 }
 if (m_membitmap != NULL)
 {
  DeleteObject(m_membitmap);
  m_membitmap = NULL;
 }
 // Modif rdv@2002 - v1.1.x - videodriver
 ShutdownVideoDriver();
 return TRUE;
}

// Routine to ensure we're on the correct NT desktop
BOOL vncDesktop::InitDesktop()
{
 if (vncService::InputDesktopSelected()) return TRUE;
 // Ask for the current input desktop
 return vncService::SelectDesktop(NULL);
}

// Routine used to close the screen saver, if it's active...
BOOL CALLBACK KillScreenSaverFunc(HWND hwnd, LPARAM lParam)
{
 char buffer[256];
 if ((GetClassName(hwnd, buffer, 256) != 0) && (strcmp(buffer, "WindowsScreenSaverClass") == 0))
  PostMessage(hwnd, WM_CLOSE, 0, 0);
 return TRUE;
}

void vncDesktop::KillScreenSaver()
{
 OSVERSIONINFO osversioninfo;
 osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
 if (!GetVersionEx(&osversioninfo)) return;
 switch (osversioninfo.dwPlatformId)
 {
 case VER_PLATFORM_WIN32_WINDOWS:
  {
   // Fidn the ScreenSaverClass window
   HWND hsswnd = FindWindow ("WindowsScreenSaverClass", NULL);
   if (hsswnd != NULL) PostMessage(hsswnd, WM_CLOSE, 0, 0);
   break;
  }
 case VER_PLATFORM_WIN32_NT:
  {
   // Find the screensaver desktop
   HDESK hDesk = OpenDesktop("Screen-saver", 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
   if (hDesk != NULL)
   {
    // Close all windows on the screen saver desktop
    EnumDesktopWindows(hDesk, (WNDENUMPROC) &KillScreenSaverFunc, 0);
    CloseDesktop(hDesk);
    // Reset the screen saver so it can run again
    SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_SENDWININICHANGE);
   }
   break;
  }
 }
}

// Modif sf@2002 - Single Window
BOOL CALLBACK EnumWindowsHnd(HWND hwnd, LPARAM arg)
{
 int  nRet;
 char buffer[128];
 char szNameAppli[16];

 strcpy(szNameAppli, (LPSTR)(((vncDesktop*)arg)->GetServerPointer()->GetWindowName()));
 szNameAppli[15]=0;
 nRet = GetWindowText(hwnd, buffer, sizeof(buffer));
 if (nRet > 0)
 {
  if ( !strnicmp(buffer, szNameAppli, lstrlen(szNameAppli)))
  {
       ((vncDesktop*)arg)->m_Single_hWnd = hwnd;
       return FALSE;
  }
  else
   return TRUE;
 }
 return TRUE;
}

BOOL vncDesktop::InitBitmap()

 // Get the device context for the whole screen and find it's size
 DriverType=NONE;
 if (OSVersion()==1) //XP W2k
  { 
    if (VideoBuffer())
      {
        pEnumDisplayDevices pd;
        LPSTR driverName = "Winvnc video hook driver";
        BOOL DriverFound;
        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;
        HMODULE hUser32=LoadLibrary("USER32");
        pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA");
          if (pd)
            {
              LPSTR deviceName=NULL;
              DISPLAY_DEVICE dd;
              ZeroMemory(&dd, sizeof(dd));
              dd.cb = sizeof(dd);
              devmode.dmDeviceName[0] = '\0';
              INT devNum = 0;
              BOOL result;
              DriverFound=false;
              while (result = (*pd)(NULL,devNum, &dd,0))
                {
                  if (strcmp((const char *)&dd.DeviceString[0], driverName) == 0)
                    {
                      DriverFound=true;
                      break;
                    }
                  devNum++;
                }
              if (DriverFound)
                {
                  deviceName = (LPSTR)&dd.DeviceName[0];
                  m_hrootdc = CreateDC("DISPLAY",deviceName,NULL,NULL);
                  BOOL change = EnumDisplaySettings(deviceName,ENUM_CURRENT_SETTINGS,&devmode);
                  m_ScreenOffsetx=devmode.dmPosition.x;
                  m_ScreenOffsety=devmode.dmPosition.y;
                  if (m_hrootdc) DriverType=MIRROR;
                  Checkmonitors();
                  asked_display=m_buffer.GetDisplay();
                  current_monitor=1;
                  if (asked_display==2 && nr_monitors>1) current_monitor=2;
                  if (asked_display==3 && nr_monitors>1) current_monitor=3;
                }
            }
        if (hUser32) FreeLibrary(hUser32);
      }//VIDEOBUFFER
    }//OS
 // RDV SINGLE WINDOW
 if (m_server->SingleWindow() && m_Single_hWnd==NULL)
 {  
  EnumWindows((WNDENUMPROC)EnumWindowsHnd, (LPARAM) this);
 }

 if (m_hrootdc == NULL) {
  //Multi-Monitor changes
  Checkmonitors();
  asked_display=m_buffer.GetDisplay();
  current_monitor=1;
  if (asked_display==2 && nr_monitors>1) current_monitor=2;
  if (asked_display==3 && nr_monitors>1) current_monitor=3;
  if (current_monitor==3) current_monitor=1;

  if (current_monitor==1)
  {
   m_hrootdc = CreateDC(("DISPLAY"),mymonitor[0].device,NULL,NULL);
   m_ScreenOffsetx=mymonitor[0].offsetx;
   m_ScreenOffsety=mymonitor[0].offsety;
  }
  if (current_monitor==2)
  {
   m_hrootdc =CreateDC(("DISPLAY"),mymonitor[1].device,NULL,NULL);
   m_ScreenOffsetx=mymonitor[1].offsetx;
   m_ScreenOffsety=mymonitor[1].offsety;
  }
  if (current_monitor==3)
  {
   m_hrootdc = GetDC(NULL);
   m_ScreenOffsetx=mymonitor[2].offsetx;
   m_ScreenOffsety=mymonitor[2].offsety;;
  }
  if (m_hrootdc == NULL) return FALSE;
 }
 m_bmrect = rfb::Rect(0, 0,GetDeviceCaps(m_hrootdc, HORZRES),GetDeviceCaps(m_hrootdc, VERTRES));
 // Create a compatible memory DC
 m_hmemdc = CreateCompatibleDC(m_hrootdc);
 if (m_hmemdc == NULL) return FALSE;
 // Check that the device capabilities are ok
 if ((GetDeviceCaps(m_hrootdc, RASTERCAPS) & RC_BITBLT) == 0)
 {
  MessageBox(NULL, "vncDesktop : root device doesn't support BitBlt\n", "WinVNC cannot be used with this graphic device driver", szAppName, MB_ICONSTOP | MB_OK);
  return FALSE;
 }
 if ((GetDeviceCaps(m_hmemdc, RASTERCAPS) & RC_DI_BITMAP) == 0)
 {
  MessageBox(NULL, "vncDesktop : memory device doesn't support GetDIBits\n","WinVNC cannot be used with this graphics device driver", szAppName, MB_ICONSTOP | MB_OK);
  return FALSE;
 }

 // Create the bitmap to be compatible with the ROOT DC!!!
 m_membitmap = CreateCompatibleBitmap(m_hrootdc, m_bmrect.br.x, m_bmrect.br.y);
 if (m_membitmap == NULL) return FALSE;
 // Get the bitmap's format and colour details
 int result;
 memset(&m_bminfo, 0, sizeof(m_bminfo));
 m_bminfo.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 m_bminfo.bmi.bmiHeader.biBitCount = 0;
 result = ::GetDIBits(m_hmemdc, m_membitmap, 0, 1, NULL, &m_bminfo.bmi, DIB_RGB_COLORS);
 if (result == 0) return FALSE;
 result = ::GetDIBits(m_hmemdc, m_membitmap,  0, 1, NULL, &m_bminfo.bmi, DIB_RGB_COLORS);
 if (result == 0) return FALSE;
 // Henceforth we want to use a top-down scanning representation
 m_bminfo.bmi.bmiHeader.biHeight = - abs(m_bminfo.bmi.bmiHeader.biHeight);
 // Is the bitmap palette-based or truecolour?
 m_bminfo.truecolour = (GetDeviceCaps(m_hmemdc, RASTERCAPS) & RC_PALETTE) == 0;
 InvalidateRect(NULL,NULL,TRUE);
 return TRUE;
}

BOOL vncDesktop::ThunkBitmapInfo()
{
 // If we leave the pixel format intact, the blist can be optimised (Will Dean's patch)
 m_formatmunged = FALSE;
 // HACK ***.  Optimised blits don't work with palette-based displays, yet
 if (!m_bminfo.truecolour) m_formatmunged = TRUE;
 // Attempt to force the actual format into one we can handle
 // We can handle 8-bit-palette and 16/32-bit-truecolour modes
 switch (m_bminfo.bmi.bmiHeader.biBitCount)
 {
 case 1:
 case 4:
  // Correct the BITMAPINFO header to the format we actually want
  m_bminfo.bmi.bmiHeader.biClrUsed = 0;
  m_bminfo.bmi.bmiHeader.biPlanes = 1;
  m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;
  m_bminfo.bmi.bmiHeader.biBitCount = 8;
  m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/ 8);
  m_bminfo.bmi.bmiHeader.biClrImportant = 0;
  m_bminfo.truecolour = FALSE;
  // Display format is non-VNC compatible - use the slow blit method
  m_formatmunged = TRUE;
  break; 
 case 24:
  // Update the bitmapinfo header
  m_bminfo.bmi.bmiHeader.biBitCount = 32;
  m_bminfo.bmi.bmiHeader.biPlanes = 1;
  m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;
  m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/ 8);
  // Display format is non-VNC compatible - use the slow blit method
  m_formatmunged = TRUE;
  break;
 }
 return TRUE;
}

BOOL vncDesktop::SetPixFormat()
{
  // If we are using a memory bitmap then check how many planes it uses
  // The VNC code can only handle formats with a single plane (CHUNKY pixels)
  if (!m_DIBbits)
  {
   if (GetDeviceCaps(m_hmemdc, PLANES) != 1)
   {
    MessageBox(NULL, "vncDesktop : current display is PLANAR, not CHUNKY!\n" "WinVNC cannot be used with this graphics device driver", szAppName, MB_ICONSTOP | MB_OK );
    return FALSE;
   }
  } 
 // Examine the bitmapinfo structure to obtain the current pixel format
 m_scrinfo.format.trueColour = m_bminfo.truecolour;
 m_scrinfo.format.bigEndian = 0;
 // Set up the native buffer width, height and format
 m_scrinfo.framebufferWidth    = (CARD16) (m_bmrect.br.x - m_bmrect.tl.x); // Swap endian before actually sending
 m_scrinfo.framebufferHeight   = (CARD16) (m_bmrect.br.y - m_bmrect.tl.y); // Swap endian before actually sending
 m_scrinfo.format.bitsPerPixel = (CARD8) m_bminfo.bmi.bmiHeader.biBitCount;
 m_scrinfo.format.depth        = (CARD8) m_bminfo.bmi.bmiHeader.biBitCount;
 // Calculate the number of bytes per row
 m_bytesPerRow = m_scrinfo.framebufferWidth * m_scrinfo.format.bitsPerPixel / 8;
 return TRUE;
}

BOOL vncDesktop::SetPixShifts()
{
 // Sort out the colour shifts, etc.
 DWORD redMask=0, blueMask=0, greenMask = 0;
 switch (m_bminfo.bmi.bmiHeader.biBitCount)
 {
    case 16:
      // Standard 16-bit display
      if (m_bminfo.bmi.bmiHeader.biCompression == BI_RGB)
      {
        // each word single pixel 5-5-5
        redMask = 0x7c00; greenMask = 0x03e0; blueMask = 0x001f;
      }
      else
      {
        if (m_bminfo.bmi.bmiHeader.biCompression == BI_BITFIELDS)
        {
          redMask =   *(DWORD *) &m_bminfo.bmi.bmiColors[0];
          greenMask = *(DWORD *) &m_bminfo.bmi.bmiColors[1];
          blueMask =  *(DWORD *) &m_bminfo.bmi.bmiColors[2];
        }
      }
      break;

    case 32:
      // Standard 24/32 bit displays
      if (m_bminfo.bmi.bmiHeader.biCompression == BI_RGB)
      {
        redMask = 0xff0000; greenMask = 0xff00; blueMask = 0x00ff;
      }
      else
      {
        if (m_bminfo.bmi.bmiHeader.biCompression == BI_BITFIELDS)
        {
          redMask =   *(DWORD *) &m_bminfo.bmi.bmiColors[0];
          greenMask = *(DWORD *) &m_bminfo.bmi.bmiColors[1];
          blueMask =  *(DWORD *) &m_bminfo.bmi.bmiColors[2];
        }
      }
      break;

    default:
      // Other pixel formats are only valid if they're palette-based
      if (m_bminfo.truecolour) return FALSE;
      return TRUE;
 }
 // Convert the data we just retrieved
 MaskToMaxAndShift(redMask, m_scrinfo.format.redMax, m_scrinfo.format.redShift);
 MaskToMaxAndShift(greenMask, m_scrinfo.format.greenMax, m_scrinfo.format.greenShift);
 MaskToMaxAndShift(blueMask, m_scrinfo.format.blueMax, m_scrinfo.format.blueShift);
 return TRUE;
}

BOOL vncDesktop::SetPalette()
{
 // Lock the current display palette into the memory DC we're holding
 // *** CHECK THIS FOR LEAKS!
 if (!m_bminfo.truecolour)
 {
  if (!m_DIBbits)
  {
   // - Handle the palette for a non DIB-Section   
   LOGPALETTE *palette;
   UINT size = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);   
   palette = (LOGPALETTE *) new char[size];
   if (palette == NULL) return FALSE;
   // Initialise the structure
   palette->palVersion = 0x300;
   palette->palNumEntries = 256;   
   // Get the system colours
   if (GetSystemPaletteEntries(m_hrootdc, 0, 256, palette->palPalEntry) == 0)
   {
    delete [] palette;
    return FALSE;
   }   
   // Create a palette from those
   HPALETTE pal = CreatePalette(palette);
   if (pal == NULL)
   {
    delete [] palette;
    return FALSE;
   }   
   // Select the palette into our memory DC
   HPALETTE oldpalette = SelectPalette(m_hmemdc, pal, FALSE);
   if (oldpalette == NULL)
   {
    delete [] palette;
    DeleteObject(pal);
    return FALSE;
   }   
   // Worked, so realise the palette
   RealizePalette(m_hmemdc); //GDI_ERROR
   // It worked!
   delete []palette;
   DeleteObject(oldpalette);   
   return TRUE;
  }
  else
  {
   // - Handle a DIB-Section's palette   
   // - Fetch the system palette for the framebuffer
   PALETTEENTRY syspalette[256];
   UINT entries = ::GetSystemPaletteEntries(m_hrootdc, 0, 256, syspalette);
   // - Store it and convert it to RGBQUAD format
   RGBQUAD dibpalette[256];
   unsigned int i;
   for (i=0;i<entries;i++)
      {
    dibpalette[i].rgbRed = syspalette[i].peRed;
    dibpalette[i].rgbGreen = syspalette[i].peGreen;
    dibpalette[i].rgbBlue = syspalette[i].peBlue;
    dibpalette[i].rgbReserved = 0;
   }   
   // - Set the rest of the palette to something nasty but usable
   for (i=entries;i<256;i++) {
    dibpalette[i].rgbRed = i % 2 ? 255 : 0;
    dibpalette[i].rgbGreen = i/2 % 2 ? 255 : 0;
    dibpalette[i].rgbBlue = i/4 % 2 ? 255 : 0;
    dibpalette[i].rgbReserved = 0;
   }   
   // - Update the DIB section to use the same palette
   HDC bitmapDC=::CreateCompatibleDC(m_hrootdc);
   if (!bitmapDC) return FALSE;
   HBITMAP old_bitmap = (HBITMAP)::SelectObject(bitmapDC, m_membitmap);
   if (!old_bitmap) return FALSE;
   UINT entries_set = ::SetDIBColorTable(bitmapDC, 0, 256, dibpalette);
   if (entries_set == 0) return FALSE;
   if (!::SelectObject(bitmapDC, old_bitmap)) return FALSE;
  }
  }
 // Not a palette based local screen - forget it!
 return TRUE;
}

DWORD WINAPI Driverwatch(LPVOID lpParam)
{
 //Mouse shape changed
 if(OSVersion()==1)
 {
  HANDLE event;
  HWND hwnd=(HWND)lpParam;
  event=NULL;
  while (event==NULL)
  {
   event = OpenEvent (SYNCHRONIZE, FALSE, "VncEvent") ;
   Sleep(900);
   if (!IsWindow(hwnd))
   {
    if (event) CloseHandle(event);
    return 0;
   }
  }
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  for (;;)
  {
      if (WaitForSingleObject(event, 2000) == WAIT_OBJECT_0)
   {
    PostMessage(hwnd, WM_USER, 0, 0);
   }
      if (!IsWindow(hwnd) || !g_Desktop_running)
      {
        if (event) CloseHandle(event);
        break;
      }
  }
 }
 return 0;
}

DWORD WINAPI Driverwatch2(LPVOID lpParam)
{
 //new screen update
 if(OSVersion()==1)
 {
  HANDLE event;
  HWND hwnd=(HWND)lpParam;
  event=NULL;
  while (event==NULL)
  {
   event = OpenEvent (SYNCHRONIZE, FALSE, "VncEvent2") ;
   Sleep(900);
   if (!IsWindow(hwnd))
   {
    if (event) CloseHandle(event);
    return 0;
   }
  }
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  counterwatch=0;
  for (;;)
  {
      if (WaitForSingleObject(event, 50) == WAIT_OBJECT_0)
   {
    PostMessage(hwnd, WM_TIMER, 0, 0);
    Sleep(100);
   }
      else
   {
    counterwatch++;
    if (counterwatch==100)
     {
      PostMessage(hwnd, WM_USER+2, 0, 0);
      counterwatch=0;
    }
   }
      if (!IsWindow(hwnd) || !g_Desktop_running)
   {
    if (event) CloseHandle(event);
    break;
   }
  }
 }
 return 0;
}

LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
ATOM m_wndClass = 0;
BOOL vncDesktop::InitWindow()
{
 if (m_wndClass == 0)
  {
  // Create the window class
  WNDCLASSEX wndclass;
  wndclass.cbSize   = sizeof(wndclass);
  wndclass.style   = 0;
  wndclass.lpfnWndProc = &DesktopWndProc;
  wndclass.cbClsExtra  = 0;
  wndclass.cbWndExtra  = 0;
  wndclass.hInstance  = hAppInstance;
  wndclass.hIcon   = NULL;
  wndclass.hCursor  = NULL;
  wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  wndclass.lpszMenuName = (const char *) NULL;
  wndclass.lpszClassName = szDesktopSink;
  wndclass.hIconSm  = NULL;
  m_wndClass = RegisterClassEx(&wndclass);
  if (!m_wndClass) return FALSE;
 }
 // And create a window
 m_hwnd = CreateWindow(szDesktopSink, "WinVNC", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, NULL, NULL, hAppInstance, NULL);
 if (m_hwnd == NULL) return FALSE;
 // Set the "this" pointer for the window
 SetWindowLong(m_hwnd, GWL_USERDATA, (long)this);
 // Enable clipboard hooking
 m_hnextviewer = SetClipboardViewer(m_hwnd);
 StopDriverWatches=false;
  DrvWatch mywatch;
  mywatch.stop=&StopDriverWatches;
  mywatch.hwnd=m_hwnd;
 if (VideoBuffer())
 {
  DWORD myword;
  HANDLE T1=CreateThread(NULL,0,Driverwatch,m_hwnd,0,&myword);
  CloseHandle(T1);
 }
 return TRUE;
}

void vncDesktop::EnableOptimisedBlits()
{
 // Create a new DIB section
 HBITMAP tempbitmap = CreateDIBSection(m_hmemdc, &m_bminfo.bmi, DIB_RGB_COLORS, &m_DIBbits, NULL, 0);
 if (tempbitmap == NULL)
  {
  m_DIBbits = NULL;
  return;
 }
 // Delete the old memory bitmap
 if (m_membitmap != NULL)
  {
  DeleteObject(m_membitmap);
  m_membitmap = NULL;
 }
 // Replace old membitmap with DIB section
 m_membitmap = tempbitmap;
}

BOOL vncDesktop::Init(vncServer *server)
{
 // Save the server pointer
 m_server = server;
 if (OSVersion()==1)
    m_fCaptureAlphaBlending = m_server->CaptureAlphaBlending();
 else
    m_fCaptureAlphaBlending = false;
 // Load in the arrow cursor
 m_hdefcursor = LoadCursor(NULL, IDC_ARROW);
 m_hcursor = m_hdefcursor;
 m_hOldcursor = m_hdefcursor; //sf@2002
 // Spawn a thread to handle that window's message queue
 vncDesktopThread *thread = new vncDesktopThread;
 if (thread == NULL) return FALSE;
 m_thread = thread;
 //SINGEL WINDOW
 SWinit();
 return thread->Init(this, m_server);
}

int vncDesktop::ScreenBuffSize()
{
 return m_scrinfo.format.bitsPerPixel/8 * m_scrinfo.framebufferWidth * m_scrinfo.framebufferHeight;
}

void vncDesktop::FillDisplayInfo(rfbServerInitMsg *scrinfo)
{
 memcpy(scrinfo, &m_scrinfo, sz_rfbServerInitMsg);
}

#define CAPTUREBLT 0x40000000
// Function to capture an area of the screen immediately prior to sending an update.
void vncDesktop::CaptureScreen(const rfb::Rect &rect, BYTE *scrBuff, UINT scrBuffSize)
{
 assert(rect.enclosed_by(m_bmrect));
 // Select the memory bitmap into the memory DC
 HBITMAP oldbitmap;
 if ((oldbitmap = (HBITMAP) SelectObject(m_hmemdc, m_membitmap)) == NULL) return;
 // Capture screen into bitmap
 BOOL blitok = BitBlt(m_hmemdc, rect.tl.x, rect.tl.y, (rect.br.x-rect.tl.x), (rect.br.y-rect.tl.y), m_hrootdc, rect.tl.x, rect.tl.y, m_fCaptureAlphaBlending ? (CAPTUREBLT | SRCCOPY) : SRCCOPY);
 // Select the old bitmap back into the memory DC
 SelectObject(m_hmemdc, oldbitmap);
  // Copy the new data to the screen buffer (CopyToBuffer optimises this if possible)
 if (blitok) CopyToBuffer(rect, scrBuff, scrBuffSize);
}

  评论这张
 
阅读(1418)| 评论(0)

历史上的今天

评论

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

页脚

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