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

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