diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in
index e3b2d67..279df01 100644
--- a/dlls/gdi32/Makefile.in
+++ b/dlls/gdi32/Makefile.in
@@ -22,6 +22,7 @@ C_SRCS = \
 	clipping.c \
 	dc.c \
 	dib.c \
+	dibdrv.c \
 	driver.c \
 	enhmetafile.c \
 	enhmfdrv/bitblt.c \
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index d16e70f..d59906b 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -586,6 +586,18 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
 
     if (handle)
     {
+        BITMAPOBJ *old = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
+        if (old) 
+        {
+            /* When switching from non-DIB to DIB or vice versa adjust
+             * DC function pointers. */
+            if (!old->dib && bitmap->dib)
+                DIBDRV_Install( dc, bitmap );
+            else if (old->dib && !bitmap->dib)
+                DIBDRV_Remove( dc, old );
+        }
+        GDI_ReleaseObj( old );
+
         dc->hBitmap = handle;
         dc->flags &= ~DC_DIRTY;
         SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight);
diff --git a/dlls/gdi32/dibdrv.c b/dlls/gdi32/dibdrv.c
new file mode 100644
index 0000000..e4a216e
--- /dev/null
+++ b/dlls/gdi32/dibdrv.c
@@ -0,0 +1,190 @@
+/*
+ * DIB driver
+ *
+ * Copyright 2007 Felix Nawothnig
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "gdi_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+static const DC_FUNCTIONS DIBDRV_Funcs =
+{
+    NULL,                            /* pAbortDoc */
+    NULL,                            /* pAbortPath */
+    NULL,                            /* pAlphaBlend */
+    NULL,                            /* pAngleArc */
+    NULL,                            /* pArc */
+    NULL,                            /* pArcTo */
+    NULL,                            /* pBeginPath */
+    NULL,                            /* pBitBlt */
+    NULL,                            /* pChoosePixelFormat */
+    NULL,                            /* pChord */
+    NULL,                            /* pCloseFigure */
+    NULL,                            /* pCreateBitmap */
+    NULL,                            /* pCreateDC */
+    NULL,                            /* pCreateDIBSection */
+    NULL,                            /* pDeleteBitmap */
+    NULL,                            /* pDeleteDC */
+    NULL,                            /* pDeleteObject */
+    NULL,                            /* pDescribePixelFormat */
+    NULL,                            /* pDeviceCapabilities */
+    NULL,                            /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
+    NULL,                            /* pEndPath */
+    NULL,                            /* pEnumDeviceFonts */
+    NULL,                            /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
+    NULL,                            /* pExtEscape */
+    NULL,                            /* pExtFloodFill */
+    NULL,                            /* pExtSelectClipRgn */
+    NULL,                            /* pExtTextOut */
+    NULL,                            /* pFillPath */
+    NULL,                            /* pFillRgn */
+    NULL,                            /* pFlattenPath */
+    NULL,                            /* pFrameRgn */
+    NULL,                            /* pGdiComment */
+    NULL,                            /* pGetBitmapBits */
+    NULL,                            /* pGetCharWidth */
+    NULL,                            /* pGetDCOrgEx */
+    NULL,                            /* pGetDIBColorTable */
+    NULL,                            /* pGetDIBits */
+    NULL,                            /* pGetDeviceCaps */
+    NULL,                            /* pGetDeviceGammaRamp */
+    NULL,                            /* pGetNearestColor */
+    NULL,                            /* pGetPixel */
+    NULL,                            /* pGetPixelFormat */
+    NULL,                            /* pGetSystemPaletteEntries */
+    NULL,                            /* pGetTextExtentExPoint */
+    NULL,                            /* pGetTextMetrics */
+    NULL,                            /* pIntersectClipRect */
+    NULL,                            /* pInvertRgn */
+    NULL,                            /* pLineTo */
+    NULL,                            /* pLockDIBSection */
+    NULL,                            /* pModifyWorldTransform */
+    NULL,                            /* pMoveTo */
+    NULL,                            /* pOffsetClipRgn */
+    NULL,                            /* pOffsetViewportOrg */
+    NULL,                            /* pOffsetWindowOrg */
+    NULL,                            /* pPaintRgn */
+    NULL,                            /* pPatBlt */
+    NULL,                            /* pPie */
+    NULL,                            /* pPolyBezier */
+    NULL,                            /* pPolyBezierTo */
+    NULL,                            /* pPolyDraw */
+    NULL,                            /* pPolyPolygon */
+    NULL,                            /* pPolyPolyline */
+    NULL,                            /* pPolygon */
+    NULL,                            /* pPolyline */
+    NULL,                            /* pPolylineTo */
+    NULL,                            /* pRealizeDefaultPalette */
+    NULL,                            /* pRealizePalette */
+    NULL,                            /* pRectangle */
+    NULL,                            /* pResetDC */
+    NULL,                            /* pRestoreDC */
+    NULL,                            /* pRoundRect */
+    NULL,                            /* pSaveDC */
+    NULL,                            /* pScaleViewportExt */
+    NULL,                            /* pScaleWindowExt */
+    NULL,                            /* pSelectBitmap */
+    NULL,                            /* pSelectBrush */
+    NULL,                            /* pSelectClipPath */
+    NULL,                            /* pSelectFont */
+    NULL,                            /* pSelectPalette */
+    NULL,                            /* pSelectPen */
+    NULL,                            /* pSetArcDirection */
+    NULL,                            /* pSetBitmapBits */
+    NULL,                            /* pSetBkColor */
+    NULL,                            /* pSetBkMode */
+    NULL,                            /* pSetDCBrushColor*/
+    NULL,                            /* pSetDCOrg */
+    NULL,                            /* pSetDCPenColor*/
+    NULL,                            /* pSetDIBColorTable */
+    NULL,                            /* pSetDIBits */
+    NULL,                            /* pSetDIBitsToDevice */
+    NULL,                            /* pSetDeviceClipping */
+    NULL,                            /* pSetDeviceGammaRamp */
+    NULL,                            /* pSetMapMode */
+    NULL,                            /* pSetMapperFlags */
+    NULL,                            /* pSetPixel */
+    NULL,                            /* pSetPixelFormat */
+    NULL,                            /* pSetPolyFillMode */
+    NULL,                            /* pSetROP2 */
+    NULL,                            /* pSetRelAbs */
+    NULL,                            /* pSetStretchBltMode */
+    NULL,                            /* pSetTextAlign */
+    NULL,                            /* pSetTextCharacterExtra */
+    NULL,                            /* pSetTextColor */
+    NULL,                            /* pSetTextJustification */
+    NULL,                            /* pSetViewportExt */
+    NULL,                            /* pSetViewportOrg */
+    NULL,                            /* pSetWindowExt */
+    NULL,                            /* pSetWindowOrg */
+    NULL,                            /* pSetWorldTransform */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
+    NULL,                            /* pStretchBlt */
+    NULL,                            /* pStretchDIBits */
+    NULL,                            /* pStrokeAndFillPath */
+    NULL,                            /* pStrokePath */
+    NULL,                            /* pSwapBuffers */
+    NULL,                            /* pUnlockDIBSection */
+    NULL,                            /* pUnrealizePalette */
+    NULL                             /* pWidenPath */
+};
+
+/***********************************************************************
+ * DIBDRV_Install
+ *
+ * Note: We do not use DRIVER_load_driver because we want to forward
+ *       unimplemented functions to the DC driver.
+ */
+void DIBDRV_Install(DC *dc, BITMAPOBJ *bmp)
+{
+    int i;
+
+    TRACE("(%p,%p)\n", dc, bmp);
+
+    bmp->orig_funcs = dc->funcs;
+    dc->funcs = &bmp->local_funcs;
+
+    memcpy(&bmp->local_funcs, bmp->orig_funcs, sizeof(DC_FUNCTIONS));
+    
+    /* Overload implemented functions */
+    for(i = 0; i < sizeof(DC_FUNCTIONS) / sizeof(void *); i++)
+        if(((void **)&DIBDRV_Funcs)[i])
+            ((void **)dc->funcs)[i] = ((void **)&DIBDRV_Funcs)[i];
+}
+
+/***********************************************************************
+ * DIBDRV_Remove
+ */
+void DIBDRV_Remove(DC *dc, BITMAPOBJ *bmp)
+{
+    TRACE("(%p,%p)\n", dc, bmp);
+
+    dc->funcs = bmp->orig_funcs;
+}
+
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 6d06e02..cb8f7f4 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -367,6 +367,8 @@ typedef struct tagBITMAPOBJ
     const DC_FUNCTIONS *funcs; /* DC function table */
     /* For device-independent bitmaps: */
     DIBSECTION         *dib;
+    const DC_FUNCTIONS *orig_funcs;
+    DC_FUNCTIONS        local_funcs;
     SEGPTR              segptr_bits;  /* segptr to DIB bits */
     RGBQUAD            *color_table;  /* DIB color table if <= 8bpp */
     UINT                nb_colors;    /* number of colors in table */
@@ -408,6 +410,10 @@ extern int DIB_GetDIBWidthBytes( int width, int depth );
 extern int DIB_GetDIBImageBytes( int width, int height, int depth );
 extern int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse );
 
+/* dibdrv.c */
+extern void DIBDRV_Install( DC *dc, BITMAPOBJ *bmp );
+extern void DIBDRV_Remove( DC *dc, BITMAPOBJ *bmp );
+
 /* driver.c */
 extern const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name );
 extern const DC_FUNCTIONS *DRIVER_get_driver( const DC_FUNCTIONS *funcs );
