Blame SOURCES/tigervnc-encapsulate-pixelbuffer-internal-details.patch

12537a
From 53f913a76196c7357d4858bfbf2c33caa9181bae Mon Sep 17 00:00:00 2001
12537a
From: Pierre Ossman <ossman@cendio.se>
12537a
Date: Tue, 10 Sep 2019 15:18:30 +0200
12537a
Subject: [PATCH] Encapsulate PixelBuffer internal details
12537a
12537a
Don't allow subclasses to just override dimensions or buffer details
12537a
directly and instead force them to go via methods. This allows us
12537a
to do sanity checks on the new values and catch bugs and attacks.
12537a
---
12537a
 common/rfb/Cursor.cxx                 |   3 +-
12537a
 common/rfb/EncodeManager.cxx          |   5 +-
12537a
 common/rfb/PixelBuffer.cxx            | 103 ++++++++++++++++----------
12537a
 common/rfb/PixelBuffer.h              |  17 +++--
12537a
 unix/x0vncserver/XPixelBuffer.cxx     |   9 +--
12537a
 unix/xserver/hw/vnc/XserverDesktop.cc |  24 +++---
12537a
 unix/xserver/hw/vnc/XserverDesktop.h  |   2 +-
12537a
 vncviewer/PlatformPixelBuffer.cxx     |   9 +--
12537a
 win/rfb_win32/DIBSectionBuffer.cxx    |  41 ++++------
12537a
 9 files changed, 111 insertions(+), 102 deletions(-)
12537a
12537a
diff --git a/common/rfb/Cursor.cxx b/common/rfb/Cursor.cxx
12537a
index 99df82d..7f3fc9a 100644
12537a
--- a/common/rfb/Cursor.cxx
12537a
+++ b/common/rfb/Cursor.cxx
12537a
@@ -271,8 +271,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer,
12537a
   assert(cursor);
12537a
 
12537a
   format = framebuffer->getPF();
12537a
-  width_ = framebuffer->width();
12537a
-  height_ = framebuffer->height();
12537a
+  setSize(framebuffer->width(), framebuffer->height());
12537a
 
12537a
   rawOffset = pos.subtract(cursor->hotspot());
12537a
   clippedRect = Rect(0, 0, cursor->width(), cursor->height())
12537a
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx
12537a
index 0cd5206..1653cea 100644
12537a
--- a/common/rfb/EncodeManager.cxx
12537a
+++ b/common/rfb/EncodeManager.cxx
12537a
@@ -891,11 +891,8 @@ void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf,
12537a
                                               int stride_)
12537a
 {
12537a
   format = pf;
12537a
-  width_ = width;
12537a
-  height_ = height;
12537a
   // Forced cast. We never write anything though, so it should be safe.
12537a
-  data = (rdr::U8*)data_;
12537a
-  stride = stride_;
12537a
+  setBuffer(width, height, (rdr::U8*)data_, stride_);
12537a
 }
12537a
 
12537a
 // Preprocessor generated, optimised methods
12537a
diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx
12537a
index 007b6c8..ad58324 100644
12537a
--- a/common/rfb/PixelBuffer.cxx
12537a
+++ b/common/rfb/PixelBuffer.cxx
12537a
@@ -35,8 +35,14 @@ static LogWriter vlog("PixelBuffer");
12537a
 // -=- Generic pixel buffer class
12537a
 
12537a
 PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h)
12537a
-  : format(pf), width_(w), height_(h) {}
12537a
-PixelBuffer::PixelBuffer() : width_(0), height_(0) {}
12537a
+  : format(pf), width_(0), height_(0)
12537a
+{
12537a
+  setSize(w, h);
12537a
+}
12537a
+
12537a
+PixelBuffer::PixelBuffer() : width_(0), height_(0)
12537a
+{
12537a
+}
12537a
 
12537a
 PixelBuffer::~PixelBuffer() {}
12537a
 
12537a
@@ -53,7 +59,7 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          r.width(), r.height(),
12537a
-                         r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   data = getBuffer(r, &inStride);
12537a
 
12537a
@@ -89,7 +95,7 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          r.width(), r.height(),
12537a
-                         r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   if (stride == 0)
12537a
     stride = r.width();
12537a
@@ -100,6 +106,12 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,
12537a
                       stride, srcStride);
12537a
 }
12537a
 
12537a
+void PixelBuffer::setSize(int width, int height)
12537a
+{
12537a
+  width_ = width;
12537a
+  height_ = height;
12537a
+}
12537a
+
12537a
 // -=- Modifiable generic pixel buffer class
12537a
 
12537a
 ModifiablePixelBuffer::ModifiablePixelBuffer(const PixelFormat& pf,
12537a
@@ -124,7 +136,7 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix)
12537a
 
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
-                         r.width(), r.height(), r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.width(), r.height(), r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   w = r.width();
12537a
   h = r.height();
12537a
@@ -175,7 +187,7 @@ void ModifiablePixelBuffer::imageRect(const Rect& r,
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          r.width(), r.height(),
12537a
-                         r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   bytesPerPixel = getPF().bpp/8;
12537a
 
12537a
@@ -213,13 +225,13 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect,
12537a
   if (!drect.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          drect.width(), drect.height(),
12537a
-                         drect.tl.x, drect.tl.y, width_, height_);
12537a
+                         drect.tl.x, drect.tl.y, width(), height());
12537a
 
12537a
   srect = drect.translate(move_by_delta.negate());
12537a
   if (!srect.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          srect.width(), srect.height(),
12537a
-                         srect.tl.x, srect.tl.y, width_, height_);
12537a
+                         srect.tl.x, srect.tl.y, width(), height());
12537a
 
12537a
   srcData = getBuffer(srect, &srcStride);
12537a
   dstData = getBufferRW(drect, &dstStride);
12537a
@@ -272,7 +284,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest,
12537a
   if (!dest.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          dest.width(), dest.height(),
12537a
-                         dest.tl.x, dest.tl.y, width_, height_);
12537a
+                         dest.tl.x, dest.tl.y, width(), height());
12537a
 
12537a
   if (stride == 0)
12537a
     stride = dest.width();
12537a
@@ -301,7 +313,7 @@ rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_)
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          r.width(), r.height(),
12537a
-                         r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   *stride_ = stride;
12537a
   return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8];
12537a
@@ -316,55 +328,69 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons
12537a
   if (!r.enclosed_by(getRect()))
12537a
     throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d",
12537a
                          r.width(), r.height(),
12537a
-                         r.tl.x, r.tl.y, width_, height_);
12537a
+                         r.tl.x, r.tl.y, width(), height());
12537a
 
12537a
   *stride_ = stride;
12537a
   return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8];
12537a
 }
12537a
 
12537a
+void FullFramePixelBuffer::setBuffer(int width, int height,
12537a
+                                     rdr::U8* data_, int stride_)
12537a
+{
12537a
+  ModifiablePixelBuffer::setSize(width, height);
12537a
+  stride = stride_;
12537a
+  data = data_;
12537a
+}
12537a
+
12537a
+void FullFramePixelBuffer::setSize(int w, int h)
12537a
+{
12537a
+  // setBuffer() should be used
12537a
+  throw rfb::Exception("Invalid call to FullFramePixelBuffer::setSize()");
12537a
+}
12537a
+
12537a
 // -=- Managed pixel buffer class
12537a
 // Automatically allocates enough space for the specified format & area
12537a
 
12537a
 ManagedPixelBuffer::ManagedPixelBuffer()
12537a
-  : datasize(0)
12537a
+  : data_(NULL), datasize(0)
12537a
 {
12537a
-  checkDataSize();
12537a
 };
12537a
 
12537a
 ManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h)
12537a
-  : FullFramePixelBuffer(pf, w, h, NULL, w), datasize(0)
12537a
+  : FullFramePixelBuffer(pf, 0, 0, NULL, 0), data_(NULL), datasize(0)
12537a
 {
12537a
-  checkDataSize();
12537a
-};
12537a
+  setSize(w, h);
12537a
+}
12537a
 
12537a
-ManagedPixelBuffer::~ManagedPixelBuffer() {
12537a
-  if (data) delete [] data;
12537a
-};
12537a
+ManagedPixelBuffer::~ManagedPixelBuffer()
12537a
+{
12537a
+  if (data_)
12537a
+    delete [] data_;
12537a
+}
12537a
 
12537a
+void ManagedPixelBuffer::setPF(const PixelFormat &pf)
12537a
+{
12537a
+  format = pf;
12537a
+  setSize(width(), height());
12537a
+}
12537a
 
12537a
-void
12537a
-ManagedPixelBuffer::setPF(const PixelFormat &pf) {
12537a
-  format = pf; checkDataSize();
12537a
-};
12537a
-void
12537a
-ManagedPixelBuffer::setSize(int w, int h) {
12537a
-  width_ = w; height_ = h; stride = w; checkDataSize();
12537a
-};
12537a
+void ManagedPixelBuffer::setSize(int w, int h)
12537a
+{
12537a
+  unsigned long new_datasize = w * h * (format.bpp/8);
12537a
 
12537a
+  new_datasize = w * h * (format.bpp/8);
12537a
 
12537a
-inline void
12537a
-ManagedPixelBuffer::checkDataSize() {
12537a
-  unsigned long new_datasize = width_ * height_ * (format.bpp/8);
12537a
   if (datasize < new_datasize) {
12537a
-    if (data) {
12537a
-      delete [] data;
12537a
-      datasize = 0; data = 0;
12537a
+    if (data_) {
12537a
+      delete [] data_;
12537a
+      data_ = NULL;
12537a
+      datasize = 0;
12537a
     }
12537a
     if (new_datasize) {
12537a
-      data = new U8[new_datasize];
12537a
-      if (!data)
12537a
-        throw Exception("rfb::ManagedPixelBuffer unable to allocate buffer");
12537a
+      data_ = new U8[new_datasize];
12537a
       datasize = new_datasize;
12537a
     }
12537a
   }
12537a
-};
12537a
+
12537a
+  setBuffer(w, h, data_, w);
12537a
+}
12537a
diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h
12537a
index 75caa63..518c692 100644
12537a
--- a/common/rfb/PixelBuffer.h
12537a
+++ b/common/rfb/PixelBuffer.h
12537a
@@ -89,7 +89,12 @@ namespace rfb {
12537a
 
12537a
   protected:
12537a
     PixelBuffer();
12537a
+    virtual void setSize(int width, int height);
12537a
+
12537a
+  protected:
12537a
     PixelFormat format;
12537a
+
12537a
+  private:
12537a
     int width_, height_;
12537a
   };
12537a
 
12537a
@@ -153,7 +158,12 @@ namespace rfb {
12537a
 
12537a
   protected:
12537a
     FullFramePixelBuffer();
12537a
+    virtual void setBuffer(int width, int height, rdr::U8* data, int stride);
12537a
 
12537a
+  private:
12537a
+    virtual void setSize(int w, int h);
12537a
+
12537a
+  private:
12537a
     rdr::U8* data;
12537a
     int stride;
12537a
   };
12537a
@@ -171,12 +181,9 @@ namespace rfb {
12537a
     virtual void setPF(const PixelFormat &pf);
12537a
     virtual void setSize(int w, int h);
12537a
 
12537a
-    // Return the total number of bytes of pixel data in the buffer
12537a
-    int dataLen() const { return width_ * height_ * (format.bpp/8); }
12537a
-
12537a
-  protected:
12537a
+  private:
12537a
+    rdr::U8* data_; // Mirrors FullFramePixelBuffer::data
12537a
     unsigned long datasize;
12537a
-    void checkDataSize();
12537a
   };
12537a
 
12537a
 };
12537a
diff --git a/unix/x0vncserver/XPixelBuffer.cxx b/unix/x0vncserver/XPixelBuffer.cxx
12537a
index f464182..6f0effe 100644
12537a
--- a/unix/x0vncserver/XPixelBuffer.cxx
12537a
+++ b/unix/x0vncserver/XPixelBuffer.cxx
12537a
@@ -50,13 +50,8 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory,
12537a
                        ffs(m_image->xim->blue_mask) - 1);
12537a
 
12537a
   // Set up the remaining data of the parent class.
12537a
-  width_ = rect.width();
12537a
-  height_ = rect.height();
12537a
-  data = (rdr::U8 *)m_image->xim->data;
12537a
-
12537a
-  // Calculate the distance in pixels between two subsequent scan
12537a
-  // lines of the framebuffer. This may differ from image width.
12537a
-  stride = m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel;
12537a
+  setBuffer(rect.width(), rect.height(), (rdr::U8 *)m_image->xim->data,
12537a
+            m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel);
12537a
 
12537a
   // Get initial screen image from the X display.
12537a
   m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop);
12537a
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
12537a
index 4836782..7daa69b 100644
12537a
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
12537a
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
12537a
@@ -101,7 +101,7 @@ XserverDesktop::XserverDesktop(int screenIndex_,
12537a
   : screenIndex(screenIndex_),
12537a
     server(0), httpServer(0),
12537a
     listeners(listeners_), httpListeners(httpListeners_),
12537a
-    directFbptr(true),
12537a
+    shadowFramebuffer(NULL),
12537a
     queryConnectId(0)
12537a
 {
12537a
   format = pf;
12537a
@@ -138,8 +138,8 @@ XserverDesktop::~XserverDesktop()
12537a
     delete httpListeners.back();
12537a
     httpListeners.pop_back();
12537a
   }
12537a
-  if (!directFbptr)
12537a
-    delete [] data;
12537a
+  if (shadowFramebuffer)
12537a
+    delete [] shadowFramebuffer;
12537a
   delete httpServer;
12537a
   delete server;
12537a
 }
12537a
@@ -158,22 +158,18 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_)
12537a
 {
12537a
   ScreenSet layout;
12537a
 
12537a
-  width_ = w;
12537a
-  height_ = h;
12537a
-
12537a
-  if (!directFbptr) {
12537a
-    delete [] data;
12537a
-    directFbptr = true;
12537a
+  if (shadowFramebuffer) {
12537a
+    delete [] shadowFramebuffer;
12537a
+    shadowFramebuffer = NULL;
12537a
   }
12537a
 
12537a
   if (!fbptr) {
12537a
-    fbptr = new rdr::U8[w * h * (format.bpp/8)];
12537a
+    shadowFramebuffer = new rdr::U8[w * h * (format.bpp/8)];
12537a
+    fbptr = shadowFramebuffer;
12537a
     stride_ = w;
12537a
-    directFbptr = false;
12537a
   }
12537a
 
12537a
-  data = (rdr::U8*)fbptr;
12537a
-  stride = stride_;
12537a
+  setBuffer(w, h, (rdr::U8*)fbptr, stride_);
12537a
 
12537a
   layout = computeScreenLayout();
12537a
 
12537a
@@ -749,7 +745,7 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,
12537a
 
12537a
 void XserverDesktop::grabRegion(const rfb::Region& region)
12537a
 {
12537a
-  if (directFbptr)
12537a
+  if (shadowFramebuffer == NULL)
12537a
     return;
12537a
 
12537a
   std::vector<rfb::Rect> rects;
12537a
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
12537a
index c766c26..22114a0 100644
12537a
--- a/unix/xserver/hw/vnc/XserverDesktop.h
12537a
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
12537a
@@ -121,7 +121,7 @@ private:
12537a
   rfb::HTTPServer* httpServer;
12537a
   std::list<network::TcpListener*> listeners;
12537a
   std::list<network::TcpListener*> httpListeners;
12537a
-  bool directFbptr;
12537a
+  rdr::U8* shadowFramebuffer;
12537a
 
12537a
   uint32_t queryConnectId;
12537a
   network::Socket* queryConnectSocket;
12537a
diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx
12537a
index 22e4f72..2b934c5 100644
12537a
--- a/vncviewer/PlatformPixelBuffer.cxx
12537a
+++ b/vncviewer/PlatformPixelBuffer.cxx
12537a
@@ -36,7 +36,7 @@ static rfb::LogWriter vlog("PlatformPixelBuffer");
12537a
 PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
12537a
   FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
12537a
                                        255, 255, 255, 16, 8, 0),
12537a
-                       width, height, 0, stride),
12537a
+                       0, 0, NULL, 0),
12537a
   Surface(width, height)
12537a
 #if !defined(WIN32) && !defined(__APPLE__)
12537a
   , shminfo(NULL), xim(NULL)
12537a
@@ -65,11 +65,10 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
12537a
     vlog.debug("Using standard XImage");
12537a
   }
12537a
 
12537a
-  data = (rdr::U8*)xim->data;
12537a
-  stride = xim->bytes_per_line / (getPF().bpp/8);
12537a
+  setBuffer(width, height, (rdr::U8*)xim->data,
12537a
+            xim->bytes_per_line / (getPF().bpp/8));
12537a
 #else
12537a
-  FullFramePixelBuffer::data = (rdr::U8*)Surface::data;
12537a
-  stride = width;
12537a
+  setBuffer(width, height, (rdr::U8*)Surface::data, width);
12537a
 #endif
12537a
 }
12537a
 
12537a
diff --git a/win/rfb_win32/DIBSectionBuffer.cxx b/win/rfb_win32/DIBSectionBuffer.cxx
12537a
index e2b0d64..e00cf23 100644
12537a
--- a/win/rfb_win32/DIBSectionBuffer.cxx
12537a
+++ b/win/rfb_win32/DIBSectionBuffer.cxx
12537a
@@ -52,39 +52,28 @@ void DIBSectionBuffer::setPF(const PixelFormat& pf) {
12537a
   if (!pf.trueColour)
12537a
     throw rfb::Exception("palette format not supported");
12537a
   format = pf;
12537a
-  recreateBuffer();
12537a
+  setSize(width(), height());
12537a
 }
12537a
 
12537a
-void DIBSectionBuffer::setSize(int w, int h) {
12537a
-  if (width_ == w && height_ == h) {
12537a
-    vlog.debug("size unchanged by setSize()");
12537a
-    return;
12537a
-  }
12537a
-  width_ = w;
12537a
-  height_ = h;
12537a
-  recreateBuffer();
12537a
-}
12537a
-
12537a
-
12537a
 inline void initMaxAndShift(DWORD mask, int* max, int* shift) {
12537a
   for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1;
12537a
   (*max) = (rdr::U16)mask;
12537a
 }
12537a
 
12537a
-void DIBSectionBuffer::recreateBuffer() {
12537a
+void DIBSectionBuffer::setSize(int w, int h) {
12537a
   HBITMAP new_bitmap = 0;
12537a
   rdr::U8* new_data = 0;
12537a
 
12537a
-  if (width_ && height_ && (format.depth != 0)) {
12537a
+  if (w && h && (format.depth != 0)) {
12537a
     BitmapInfo bi;
12537a
     memset(&bi, 0, sizeof(bi));
12537a
     UINT iUsage = DIB_RGB_COLORS;
12537a
     bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
12537a
     bi.bmiHeader.biBitCount = format.bpp;
12537a
-    bi.bmiHeader.biSizeImage = (format.bpp / 8) * width_ * height_;
12537a
+    bi.bmiHeader.biSizeImage = (format.bpp / 8) * w * h;
12537a
     bi.bmiHeader.biPlanes = 1;
12537a
-    bi.bmiHeader.biWidth = width_;
12537a
-    bi.bmiHeader.biHeight = -height_;
12537a
+    bi.bmiHeader.biWidth = w;
12537a
+    bi.bmiHeader.biHeight = -h;
12537a
     bi.bmiHeader.biCompression = (format.bpp > 8) ? BI_BITFIELDS : BI_RGB;
12537a
     bi.mask.red = format.pixelFromRGB((rdr::U16)~0, 0, 0);
12537a
     bi.mask.green = format.pixelFromRGB(0, (rdr::U16)~0, 0);
12537a
@@ -115,12 +104,12 @@ void DIBSectionBuffer::recreateBuffer() {
12537a
     if (device) {
12537a
       BitmapDC src_dev(device, bitmap);
12537a
       BitmapDC dest_dev(device, new_bitmap);
12537a
-      BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
12537a
+      BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);
12537a
     } else {
12537a
       WindowDC wndDC(window);
12537a
       BitmapDC src_dev(wndDC, bitmap);
12537a
       BitmapDC dest_dev(wndDC, new_bitmap);
12537a
-      BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
12537a
+      BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);
12537a
     }
12537a
   }
12537a
   
12537a
@@ -128,17 +117,17 @@ void DIBSectionBuffer::recreateBuffer() {
12537a
     // Delete the old bitmap
12537a
     DeleteObject(bitmap);
12537a
     bitmap = 0;
12537a
-    data = 0;
12537a
+    setBuffer(0, 0, NULL, 0);
12537a
   }
12537a
 
12537a
   if (new_bitmap) {
12537a
     int bpp, depth;
12537a
     int redMax, greenMax, blueMax;
12537a
     int redShift, greenShift, blueShift;
12537a
+    int new_stride;
12537a
 
12537a
     // Set up the new bitmap
12537a
     bitmap = new_bitmap;
12537a
-    data = new_data;
12537a
 
12537a
     // Determine the *actual* DIBSection format
12537a
     DIBSECTION ds;
12537a
@@ -147,14 +136,16 @@ void DIBSectionBuffer::recreateBuffer() {
12537a
 
12537a
     // Correct the "stride" of the DIB
12537a
     // *** This code DWORD aligns each row - is that right???
12537a
-    stride = width_;
12537a
-    int bytesPerRow = stride * format.bpp/8;
12537a
+    new_stride = w;
12537a
+    int bytesPerRow = new_stride * format.bpp/8;
12537a
     if (bytesPerRow % 4) {
12537a
       bytesPerRow += 4 - (bytesPerRow % 4);
12537a
-      stride = (bytesPerRow * 8) / format.bpp;
12537a
-      vlog.info("adjusting DIB stride: %d to %d", width_, stride);
12537a
+      new_stride = (bytesPerRow * 8) / format.bpp;
12537a
+      vlog.info("adjusting DIB stride: %d to %d", w, new_stride);
12537a
     }
12537a
 
12537a
+    setBuffer(w, h, new_data, new_stride);
12537a
+
12537a
     // Calculate the PixelFormat for the DIB
12537a
     bpp = depth = ds.dsBm.bmBitsPixel;
12537a